From 2da429cd0a4bebac84b8b91537867a08156aca7a Mon Sep 17 00:00:00 2001 From: Roland Franssen Date: Thu, 6 Apr 2017 18:31:06 +0200 Subject: [PATCH 0001/1099] [Console] Make SymfonyQuestionHelper::ask optional by default --- UPGRADE-3.3.md | 2 ++ UPGRADE-4.0.md | 2 ++ .../Bundle/WebServerBundle/Command/ServerStartCommand.php | 2 +- src/Symfony/Component/Console/CHANGELOG.md | 1 + .../Component/Console/Helper/SymfonyQuestionHelper.php | 4 ++++ 5 files changed, 10 insertions(+), 1 deletion(-) diff --git a/UPGRADE-3.3.md b/UPGRADE-3.3.md index f068e4f4322f5..423350373068c 100644 --- a/UPGRADE-3.3.md +++ b/UPGRADE-3.3.md @@ -72,6 +72,8 @@ Console have been deprecated in favor of the `console.error` event and the `ConsoleErrorEvent` class. The deprecated event and class will be removed in 4.0. + * The `SymfonyQuestionHelper::ask` default validation has been deprecated and will be removed in 4.0. Apply validation using `Question::setValidator` instead. + Debug ----- diff --git a/UPGRADE-4.0.md b/UPGRADE-4.0.md index 401f3ae736005..ed4c2f674fdad 100644 --- a/UPGRADE-4.0.md +++ b/UPGRADE-4.0.md @@ -61,6 +61,8 @@ Console * The `console.exception` event and the related `ConsoleExceptionEvent` class have been removed in favor of the `console.error` event and the `ConsoleErrorEvent` class. + * The `SymfonyQuestionHelper::ask` default validation has been removed in favor of `Question::setValidator`. + Debug ----- diff --git a/src/Symfony/Bundle/WebServerBundle/Command/ServerStartCommand.php b/src/Symfony/Bundle/WebServerBundle/Command/ServerStartCommand.php index c0888e944e136..0648ae34704b3 100644 --- a/src/Symfony/Bundle/WebServerBundle/Command/ServerStartCommand.php +++ b/src/Symfony/Bundle/WebServerBundle/Command/ServerStartCommand.php @@ -88,7 +88,7 @@ protected function execute(InputInterface $input, OutputInterface $output) 'You can either install it or use the "server:run" command instead.', )); - if ($io->ask('Do you want to execute server:run immediately? [yN] ', false)) { + if ($io->confirm('Do you want to execute server:run immediately?', false)) { return $this->getApplication()->find('server:run')->run($input, $output); } diff --git a/src/Symfony/Component/Console/CHANGELOG.md b/src/Symfony/Component/Console/CHANGELOG.md index f8539491d264b..901fdcf60259b 100644 --- a/src/Symfony/Component/Console/CHANGELOG.md +++ b/src/Symfony/Component/Console/CHANGELOG.md @@ -12,6 +12,7 @@ CHANGELOG * deprecated console.exception event in favor of console.error * added ability to handle `CommandNotFoundException` through the `console.error` event +* deprecated default validation in `SymfonyQuestionHelper::ask` 3.2.0 ------ diff --git a/src/Symfony/Component/Console/Helper/SymfonyQuestionHelper.php b/src/Symfony/Component/Console/Helper/SymfonyQuestionHelper.php index 25e094a04f45c..cf071d594d44a 100644 --- a/src/Symfony/Component/Console/Helper/SymfonyQuestionHelper.php +++ b/src/Symfony/Component/Console/Helper/SymfonyQuestionHelper.php @@ -29,6 +29,8 @@ class SymfonyQuestionHelper extends QuestionHelper { /** * {@inheritdoc} + * + * To be removed in 4.0 */ public function ask(InputInterface $input, OutputInterface $output, Question $question) { @@ -39,6 +41,8 @@ public function ask(InputInterface $input, OutputInterface $output, Question $qu } else { // make required if (!is_array($value) && !is_bool($value) && 0 === strlen($value)) { + @trigger_error('The default question validator is deprecated since Symfony 3.3 and will not be used anymore in version 4.0. Set a custom question validator if needed.', E_USER_DEPRECATED); + throw new LogicException('A value is required.'); } } From 761de99552b74408739d0f8e71a6e06e96c23941 Mon Sep 17 00:00:00 2001 From: Jakub Sacha Date: Mon, 3 Apr 2017 07:31:13 +0200 Subject: [PATCH 0002/1099] Fix passing options with defaultCommand --- src/Symfony/Component/Console/Application.php | 7 +++- .../Console/Tests/ApplicationTest.php | 24 ++++++++++--- .../Console/Tests/Fixtures/FooOptCommand.php | 36 +++++++++++++++++++ .../Tests/Fixtures/application_run2.txt | 2 +- 4 files changed, 63 insertions(+), 6 deletions(-) create mode 100644 src/Symfony/Component/Console/Tests/Fixtures/FooOptCommand.php diff --git a/src/Symfony/Component/Console/Application.php b/src/Symfony/Component/Console/Application.php index bc5e9ee66c09b..864979a40a8eb 100644 --- a/src/Symfony/Component/Console/Application.php +++ b/src/Symfony/Component/Console/Application.php @@ -179,7 +179,12 @@ public function doRun(InputInterface $input, OutputInterface $output) if (!$name) { $name = $this->defaultCommand; - $input = new ArrayInput(array('command' => $this->defaultCommand)); + $this->definition->setArguments(array_merge( + $this->definition->getArguments(), + array( + 'command' => new InputArgument('command', InputArgument::OPTIONAL, $this->definition->getArgument('command')->getDescription(), $name), + ) + )); } // the command name MUST be the first element of the input diff --git a/src/Symfony/Component/Console/Tests/ApplicationTest.php b/src/Symfony/Component/Console/Tests/ApplicationTest.php index df6d1976e7193..c3ae7c928d1ae 100644 --- a/src/Symfony/Component/Console/Tests/ApplicationTest.php +++ b/src/Symfony/Component/Console/Tests/ApplicationTest.php @@ -39,6 +39,7 @@ public static function setUpBeforeClass() { self::$fixturesPath = realpath(__DIR__.'/Fixtures/'); require_once self::$fixturesPath.'/FooCommand.php'; + require_once self::$fixturesPath.'/FooOptCommand.php'; require_once self::$fixturesPath.'/Foo1Command.php'; require_once self::$fixturesPath.'/Foo2Command.php'; require_once self::$fixturesPath.'/Foo3Command.php'; @@ -1123,16 +1124,31 @@ public function testSetRunCustomDefaultCommand() $application->setDefaultCommand($command->getName()); $tester = new ApplicationTester($application); - $tester->run(array()); - $this->assertEquals('interact called'.PHP_EOL.'called'.PHP_EOL, $tester->getDisplay(), 'Application runs the default set command if different from \'list\' command'); + $tester->run(array(), array('interactive' => false)); + $this->assertEquals('called'.PHP_EOL, $tester->getDisplay(), 'Application runs the default set command if different from \'list\' command'); $application = new CustomDefaultCommandApplication(); $application->setAutoExit(false); $tester = new ApplicationTester($application); - $tester->run(array()); + $tester->run(array(), array('interactive' => false)); - $this->assertEquals('interact called'.PHP_EOL.'called'.PHP_EOL, $tester->getDisplay(), 'Application runs the default set command if different from \'list\' command'); + $this->assertEquals('called'.PHP_EOL, $tester->getDisplay(), 'Application runs the default set command if different from \'list\' command'); + } + + public function testSetRunCustomDefaultCommandWithOption() + { + $command = new \FooOptCommand(); + + $application = new Application(); + $application->setAutoExit(false); + $application->add($command); + $application->setDefaultCommand($command->getName()); + + $tester = new ApplicationTester($application); + $tester->run(array('--fooopt' => 'opt'), array('interactive' => false)); + + $this->assertEquals('called'.PHP_EOL.'opt'.PHP_EOL, $tester->getDisplay(), 'Application runs the default set command if different from \'list\' command'); } /** diff --git a/src/Symfony/Component/Console/Tests/Fixtures/FooOptCommand.php b/src/Symfony/Component/Console/Tests/Fixtures/FooOptCommand.php new file mode 100644 index 0000000000000..9043aa483c20f --- /dev/null +++ b/src/Symfony/Component/Console/Tests/Fixtures/FooOptCommand.php @@ -0,0 +1,36 @@ +setName('foo:bar') + ->setDescription('The foo:bar command') + ->setAliases(array('afoobar')) + ->addOption('fooopt', 'fo', InputOption::VALUE_OPTIONAL, 'fooopt description') + ; + } + + protected function interact(InputInterface $input, OutputInterface $output) + { + $output->writeln('interact called'); + } + + protected function execute(InputInterface $input, OutputInterface $output) + { + $this->input = $input; + $this->output = $output; + + $output->writeln('called'); + $output->writeln($this->input->getOption('fooopt')); + } +} diff --git a/src/Symfony/Component/Console/Tests/Fixtures/application_run2.txt b/src/Symfony/Component/Console/Tests/Fixtures/application_run2.txt index 9a42503c6b05e..06ad09ad1e8d1 100644 --- a/src/Symfony/Component/Console/Tests/Fixtures/application_run2.txt +++ b/src/Symfony/Component/Console/Tests/Fixtures/application_run2.txt @@ -2,7 +2,7 @@ Usage: help [options] [--] [] Arguments: - command The command to execute + command The command to execute [default: "list"] command_name The command name [default: "help"] Options: From 612fb59b32074a36fe336e95ae4938f26ae9e824 Mon Sep 17 00:00:00 2001 From: Gavin Staniforth Date: Thu, 30 Mar 2017 22:53:13 +0100 Subject: [PATCH 0003/1099] [HttpKernel] minor: add ability to construct with headers on http exceptions --- .../Exception/AccessDeniedHttpException.php | 5 +++-- .../Exception/BadRequestHttpException.php | 5 +++-- .../HttpKernel/Exception/ConflictHttpException.php | 5 +++-- .../HttpKernel/Exception/GoneHttpException.php | 5 +++-- .../Exception/LengthRequiredHttpException.php | 5 +++-- .../Exception/MethodNotAllowedHttpException.php | 5 +++-- .../Exception/NotAcceptableHttpException.php | 5 +++-- .../HttpKernel/Exception/NotFoundHttpException.php | 5 +++-- .../Exception/PreconditionFailedHttpException.php | 5 +++-- .../Exception/PreconditionRequiredHttpException.php | 5 +++-- .../Exception/ServiceUnavailableHttpException.php | 6 +++--- .../Exception/TooManyRequestsHttpException.php | 6 +++--- .../Exception/UnauthorizedHttpException.php | 5 +++-- .../Exception/UnprocessableEntityHttpException.php | 5 +++-- .../Exception/UnsupportedMediaTypeHttpException.php | 5 +++-- .../Exception/MethodNotAllowedHttpExceptionTest.php | 13 +++++++++++++ .../ServiceUnavailableHttpExceptionTest.php | 13 +++++++++++++ .../Exception/TooManyRequestsHttpExceptionTest.php | 13 +++++++++++++ .../Exception/UnauthorizedHttpExceptionTest.php | 13 +++++++++++++ 19 files changed, 97 insertions(+), 32 deletions(-) diff --git a/src/Symfony/Component/HttpKernel/Exception/AccessDeniedHttpException.php b/src/Symfony/Component/HttpKernel/Exception/AccessDeniedHttpException.php index 79d8639a5f7d3..772379bf8905a 100644 --- a/src/Symfony/Component/HttpKernel/Exception/AccessDeniedHttpException.php +++ b/src/Symfony/Component/HttpKernel/Exception/AccessDeniedHttpException.php @@ -25,9 +25,10 @@ class AccessDeniedHttpException extends HttpException * @param string $message The internal exception message * @param \Exception $previous The previous exception * @param int $code The internal exception code + * @param array $headers */ - public function __construct($message = null, \Exception $previous = null, $code = 0) + public function __construct($message = null, \Exception $previous = null, $code = 0, array $headers = array()) { - parent::__construct(403, $message, $previous, array(), $code); + parent::__construct(403, $message, $previous, $headers, $code); } } diff --git a/src/Symfony/Component/HttpKernel/Exception/BadRequestHttpException.php b/src/Symfony/Component/HttpKernel/Exception/BadRequestHttpException.php index 5f68172a8d44e..cc78e4a267ad1 100644 --- a/src/Symfony/Component/HttpKernel/Exception/BadRequestHttpException.php +++ b/src/Symfony/Component/HttpKernel/Exception/BadRequestHttpException.php @@ -24,9 +24,10 @@ class BadRequestHttpException extends HttpException * @param string $message The internal exception message * @param \Exception $previous The previous exception * @param int $code The internal exception code + * @param array $headers */ - public function __construct($message = null, \Exception $previous = null, $code = 0) + public function __construct($message = null, \Exception $previous = null, $code = 0, array $headers = array()) { - parent::__construct(400, $message, $previous, array(), $code); + parent::__construct(400, $message, $previous, $headers, $code); } } diff --git a/src/Symfony/Component/HttpKernel/Exception/ConflictHttpException.php b/src/Symfony/Component/HttpKernel/Exception/ConflictHttpException.php index 34d738ed12030..83f78c6614167 100644 --- a/src/Symfony/Component/HttpKernel/Exception/ConflictHttpException.php +++ b/src/Symfony/Component/HttpKernel/Exception/ConflictHttpException.php @@ -24,9 +24,10 @@ class ConflictHttpException extends HttpException * @param string $message The internal exception message * @param \Exception $previous The previous exception * @param int $code The internal exception code + * @param array $headers */ - public function __construct($message = null, \Exception $previous = null, $code = 0) + public function __construct($message = null, \Exception $previous = null, $code = 0, array $headers = array()) { - parent::__construct(409, $message, $previous, array(), $code); + parent::__construct(409, $message, $previous, $headers, $code); } } diff --git a/src/Symfony/Component/HttpKernel/Exception/GoneHttpException.php b/src/Symfony/Component/HttpKernel/Exception/GoneHttpException.php index 16ea223fae558..30c5831b14429 100644 --- a/src/Symfony/Component/HttpKernel/Exception/GoneHttpException.php +++ b/src/Symfony/Component/HttpKernel/Exception/GoneHttpException.php @@ -24,9 +24,10 @@ class GoneHttpException extends HttpException * @param string $message The internal exception message * @param \Exception $previous The previous exception * @param int $code The internal exception code + * @param array $headers */ - public function __construct($message = null, \Exception $previous = null, $code = 0) + public function __construct($message = null, \Exception $previous = null, $code = 0, array $headers = array()) { - parent::__construct(410, $message, $previous, array(), $code); + parent::__construct(410, $message, $previous, $headers, $code); } } diff --git a/src/Symfony/Component/HttpKernel/Exception/LengthRequiredHttpException.php b/src/Symfony/Component/HttpKernel/Exception/LengthRequiredHttpException.php index 0c4b9431f4b9f..2b29d1ab2c42c 100644 --- a/src/Symfony/Component/HttpKernel/Exception/LengthRequiredHttpException.php +++ b/src/Symfony/Component/HttpKernel/Exception/LengthRequiredHttpException.php @@ -24,9 +24,10 @@ class LengthRequiredHttpException extends HttpException * @param string $message The internal exception message * @param \Exception $previous The previous exception * @param int $code The internal exception code + * @param array $headers */ - public function __construct($message = null, \Exception $previous = null, $code = 0) + public function __construct($message = null, \Exception $previous = null, $code = 0, array $headers = array()) { - parent::__construct(411, $message, $previous, array(), $code); + parent::__construct(411, $message, $previous, $headers, $code); } } diff --git a/src/Symfony/Component/HttpKernel/Exception/MethodNotAllowedHttpException.php b/src/Symfony/Component/HttpKernel/Exception/MethodNotAllowedHttpException.php index 78dd26bf0fd8f..0b0883bb68c2f 100644 --- a/src/Symfony/Component/HttpKernel/Exception/MethodNotAllowedHttpException.php +++ b/src/Symfony/Component/HttpKernel/Exception/MethodNotAllowedHttpException.php @@ -25,10 +25,11 @@ class MethodNotAllowedHttpException extends HttpException * @param string $message The internal exception message * @param \Exception $previous The previous exception * @param int $code The internal exception code + * @param array $headers */ - public function __construct(array $allow, $message = null, \Exception $previous = null, $code = 0) + public function __construct(array $allow, $message = null, \Exception $previous = null, $code = 0, array $headers = array()) { - $headers = array('Allow' => strtoupper(implode(', ', $allow))); + $headers['Allow'] = strtoupper(implode(', ', $allow)); parent::__construct(405, $message, $previous, $headers, $code); } diff --git a/src/Symfony/Component/HttpKernel/Exception/NotAcceptableHttpException.php b/src/Symfony/Component/HttpKernel/Exception/NotAcceptableHttpException.php index cc6be4ba45a7d..369f480a38f1d 100644 --- a/src/Symfony/Component/HttpKernel/Exception/NotAcceptableHttpException.php +++ b/src/Symfony/Component/HttpKernel/Exception/NotAcceptableHttpException.php @@ -24,9 +24,10 @@ class NotAcceptableHttpException extends HttpException * @param string $message The internal exception message * @param \Exception $previous The previous exception * @param int $code The internal exception code + * @param array $headers */ - public function __construct($message = null, \Exception $previous = null, $code = 0) + public function __construct($message = null, \Exception $previous = null, $code = 0, array $headers = array()) { - parent::__construct(406, $message, $previous, array(), $code); + parent::__construct(406, $message, $previous, $headers, $code); } } diff --git a/src/Symfony/Component/HttpKernel/Exception/NotFoundHttpException.php b/src/Symfony/Component/HttpKernel/Exception/NotFoundHttpException.php index 4639e379b90fc..4a1a4af830ff2 100644 --- a/src/Symfony/Component/HttpKernel/Exception/NotFoundHttpException.php +++ b/src/Symfony/Component/HttpKernel/Exception/NotFoundHttpException.php @@ -24,9 +24,10 @@ class NotFoundHttpException extends HttpException * @param string $message The internal exception message * @param \Exception $previous The previous exception * @param int $code The internal exception code + * @param array $headers */ - public function __construct($message = null, \Exception $previous = null, $code = 0) + public function __construct($message = null, \Exception $previous = null, $code = 0, array $headers = array()) { - parent::__construct(404, $message, $previous, array(), $code); + parent::__construct(404, $message, $previous, $headers, $code); } } diff --git a/src/Symfony/Component/HttpKernel/Exception/PreconditionFailedHttpException.php b/src/Symfony/Component/HttpKernel/Exception/PreconditionFailedHttpException.php index 9df0e7b49aa9b..28a36edb92699 100644 --- a/src/Symfony/Component/HttpKernel/Exception/PreconditionFailedHttpException.php +++ b/src/Symfony/Component/HttpKernel/Exception/PreconditionFailedHttpException.php @@ -24,9 +24,10 @@ class PreconditionFailedHttpException extends HttpException * @param string $message The internal exception message * @param \Exception $previous The previous exception * @param int $code The internal exception code + * @param array $headers */ - public function __construct($message = null, \Exception $previous = null, $code = 0) + public function __construct($message = null, \Exception $previous = null, $code = 0, array $headers = array()) { - parent::__construct(412, $message, $previous, array(), $code); + parent::__construct(412, $message, $previous, $headers, $code); } } diff --git a/src/Symfony/Component/HttpKernel/Exception/PreconditionRequiredHttpException.php b/src/Symfony/Component/HttpKernel/Exception/PreconditionRequiredHttpException.php index 08ebca2241e00..fc96b2b397fe3 100644 --- a/src/Symfony/Component/HttpKernel/Exception/PreconditionRequiredHttpException.php +++ b/src/Symfony/Component/HttpKernel/Exception/PreconditionRequiredHttpException.php @@ -26,9 +26,10 @@ class PreconditionRequiredHttpException extends HttpException * @param string $message The internal exception message * @param \Exception $previous The previous exception * @param int $code The internal exception code + * @param array $headers */ - public function __construct($message = null, \Exception $previous = null, $code = 0) + public function __construct($message = null, \Exception $previous = null, $code = 0, array $headers = array()) { - parent::__construct(428, $message, $previous, array(), $code); + parent::__construct(428, $message, $previous, $headers, $code); } } diff --git a/src/Symfony/Component/HttpKernel/Exception/ServiceUnavailableHttpException.php b/src/Symfony/Component/HttpKernel/Exception/ServiceUnavailableHttpException.php index 32b9e2d261218..77dafe5698bd7 100644 --- a/src/Symfony/Component/HttpKernel/Exception/ServiceUnavailableHttpException.php +++ b/src/Symfony/Component/HttpKernel/Exception/ServiceUnavailableHttpException.php @@ -25,12 +25,12 @@ class ServiceUnavailableHttpException extends HttpException * @param string $message The internal exception message * @param \Exception $previous The previous exception * @param int $code The internal exception code + * @param array $headers */ - public function __construct($retryAfter = null, $message = null, \Exception $previous = null, $code = 0) + public function __construct($retryAfter = null, $message = null, \Exception $previous = null, $code = 0, array $headers = array()) { - $headers = array(); if ($retryAfter) { - $headers = array('Retry-After' => $retryAfter); + $headers['Retry-After'] = $retryAfter; } parent::__construct(503, $message, $previous, $headers, $code); diff --git a/src/Symfony/Component/HttpKernel/Exception/TooManyRequestsHttpException.php b/src/Symfony/Component/HttpKernel/Exception/TooManyRequestsHttpException.php index ab86e0920bc69..8250e5c2afd7d 100644 --- a/src/Symfony/Component/HttpKernel/Exception/TooManyRequestsHttpException.php +++ b/src/Symfony/Component/HttpKernel/Exception/TooManyRequestsHttpException.php @@ -27,12 +27,12 @@ class TooManyRequestsHttpException extends HttpException * @param string $message The internal exception message * @param \Exception $previous The previous exception * @param int $code The internal exception code + * @param array $headers */ - public function __construct($retryAfter = null, $message = null, \Exception $previous = null, $code = 0) + public function __construct($retryAfter = null, $message = null, \Exception $previous = null, $code = 0, array $headers = array()) { - $headers = array(); if ($retryAfter) { - $headers = array('Retry-After' => $retryAfter); + $headers['Retry-After'] = $retryAfter; } parent::__construct(429, $message, $previous, $headers, $code); diff --git a/src/Symfony/Component/HttpKernel/Exception/UnauthorizedHttpException.php b/src/Symfony/Component/HttpKernel/Exception/UnauthorizedHttpException.php index 0dfe42db97280..e5f616251508e 100644 --- a/src/Symfony/Component/HttpKernel/Exception/UnauthorizedHttpException.php +++ b/src/Symfony/Component/HttpKernel/Exception/UnauthorizedHttpException.php @@ -25,10 +25,11 @@ class UnauthorizedHttpException extends HttpException * @param string $message The internal exception message * @param \Exception $previous The previous exception * @param int $code The internal exception code + * @param array $headers */ - public function __construct($challenge, $message = null, \Exception $previous = null, $code = 0) + public function __construct($challenge, $message = null, \Exception $previous = null, $code = 0, array $headers = array()) { - $headers = array('WWW-Authenticate' => $challenge); + $headers['WWW-Authenticate'] = $challenge; parent::__construct(401, $message, $previous, $headers, $code); } diff --git a/src/Symfony/Component/HttpKernel/Exception/UnprocessableEntityHttpException.php b/src/Symfony/Component/HttpKernel/Exception/UnprocessableEntityHttpException.php index eb13f563f6cbb..ef25bdd7640ea 100644 --- a/src/Symfony/Component/HttpKernel/Exception/UnprocessableEntityHttpException.php +++ b/src/Symfony/Component/HttpKernel/Exception/UnprocessableEntityHttpException.php @@ -24,9 +24,10 @@ class UnprocessableEntityHttpException extends HttpException * @param string $message The internal exception message * @param \Exception $previous The previous exception * @param int $code The internal exception code + * @param array $headers */ - public function __construct($message = null, \Exception $previous = null, $code = 0) + public function __construct($message = null, \Exception $previous = null, $code = 0, array $headers = array()) { - parent::__construct(422, $message, $previous, array(), $code); + parent::__construct(422, $message, $previous, $headers, $code); } } diff --git a/src/Symfony/Component/HttpKernel/Exception/UnsupportedMediaTypeHttpException.php b/src/Symfony/Component/HttpKernel/Exception/UnsupportedMediaTypeHttpException.php index a9d8fa086f13c..a8f2de8c541be 100644 --- a/src/Symfony/Component/HttpKernel/Exception/UnsupportedMediaTypeHttpException.php +++ b/src/Symfony/Component/HttpKernel/Exception/UnsupportedMediaTypeHttpException.php @@ -24,9 +24,10 @@ class UnsupportedMediaTypeHttpException extends HttpException * @param string $message The internal exception message * @param \Exception $previous The previous exception * @param int $code The internal exception code + * @param array $headers */ - public function __construct($message = null, \Exception $previous = null, $code = 0) + public function __construct($message = null, \Exception $previous = null, $code = 0, array $headers = array()) { - parent::__construct(415, $message, $previous, array(), $code); + parent::__construct(415, $message, $previous, $headers, $code); } } diff --git a/src/Symfony/Component/HttpKernel/Tests/Exception/MethodNotAllowedHttpExceptionTest.php b/src/Symfony/Component/HttpKernel/Tests/Exception/MethodNotAllowedHttpExceptionTest.php index b5def13ce38d7..ea82014952518 100644 --- a/src/Symfony/Component/HttpKernel/Tests/Exception/MethodNotAllowedHttpExceptionTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/Exception/MethodNotAllowedHttpExceptionTest.php @@ -12,6 +12,19 @@ public function testHeadersDefault() $this->assertSame(array('Allow' => 'GET, PUT'), $exception->getHeaders()); } + public function testWithHeaderConstruct() + { + $headers = array( + 'Cache-Control' => 'public, s-maxage=1200', + ); + + $exception = new MethodNotAllowedHttpException(array('get'), null, null, null, $headers); + + $headers['Allow'] = 'GET'; + + $this->assertSame($headers, $exception->getHeaders()); + } + /** * @dataProvider headerDataProvider */ diff --git a/src/Symfony/Component/HttpKernel/Tests/Exception/ServiceUnavailableHttpExceptionTest.php b/src/Symfony/Component/HttpKernel/Tests/Exception/ServiceUnavailableHttpExceptionTest.php index e41a23d4e7719..83cbdc2bccc5b 100644 --- a/src/Symfony/Component/HttpKernel/Tests/Exception/ServiceUnavailableHttpExceptionTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/Exception/ServiceUnavailableHttpExceptionTest.php @@ -12,6 +12,19 @@ public function testHeadersDefaultRetryAfter() $this->assertSame(array('Retry-After' => 10), $exception->getHeaders()); } + public function testWithHeaderConstruct() + { + $headers = array( + 'Cache-Control' => 'public, s-maxage=1337', + ); + + $exception = new ServiceUnavailableHttpException(1337, null, null, null, $headers); + + $headers['Retry-After'] = 1337; + + $this->assertSame($headers, $exception->getHeaders()); + } + /** * @dataProvider headerDataProvider */ diff --git a/src/Symfony/Component/HttpKernel/Tests/Exception/TooManyRequestsHttpExceptionTest.php b/src/Symfony/Component/HttpKernel/Tests/Exception/TooManyRequestsHttpExceptionTest.php index 2079bb3380d20..6ec7f3d0796d2 100644 --- a/src/Symfony/Component/HttpKernel/Tests/Exception/TooManyRequestsHttpExceptionTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/Exception/TooManyRequestsHttpExceptionTest.php @@ -12,6 +12,19 @@ public function testHeadersDefaultRertyAfter() $this->assertSame(array('Retry-After' => 10), $exception->getHeaders()); } + public function testWithHeaderConstruct() + { + $headers = array( + 'Cache-Control' => 'public, s-maxage=69', + ); + + $exception = new TooManyRequestsHttpException(69, null, null, null, $headers); + + $headers['Retry-After'] = 69; + + $this->assertSame($headers, $exception->getHeaders()); + } + /** * @dataProvider headerDataProvider */ diff --git a/src/Symfony/Component/HttpKernel/Tests/Exception/UnauthorizedHttpExceptionTest.php b/src/Symfony/Component/HttpKernel/Tests/Exception/UnauthorizedHttpExceptionTest.php index 37a0028dc8257..1e93d25b1a9b8 100644 --- a/src/Symfony/Component/HttpKernel/Tests/Exception/UnauthorizedHttpExceptionTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/Exception/UnauthorizedHttpExceptionTest.php @@ -12,6 +12,19 @@ public function testHeadersDefault() $this->assertSame(array('WWW-Authenticate' => 'Challenge'), $exception->getHeaders()); } + public function testWithHeaderConstruct() + { + $headers = array( + 'Cache-Control' => 'public, s-maxage=1200', + ); + + $exception = new UnauthorizedHttpException('Challenge', null, null, null, $headers); + + $headers['WWW-Authenticate'] = 'Challenge'; + + $this->assertSame($headers, $exception->getHeaders()); + } + /** * @dataProvider headerDataProvider */ From 7b59412301f6c2f98d0f1b0d694c5369ee998f41 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Wed, 17 May 2017 18:21:40 +0200 Subject: [PATCH 0004/1099] updated version to 3.4 --- composer.json | 2 +- src/Symfony/Bridge/Doctrine/composer.json | 2 +- src/Symfony/Bridge/Monolog/composer.json | 2 +- src/Symfony/Bridge/PhpUnit/composer.json | 2 +- src/Symfony/Bridge/ProxyManager/composer.json | 2 +- src/Symfony/Bridge/Twig/composer.json | 2 +- src/Symfony/Bundle/DebugBundle/composer.json | 2 +- src/Symfony/Bundle/FrameworkBundle/composer.json | 2 +- src/Symfony/Bundle/SecurityBundle/composer.json | 2 +- src/Symfony/Bundle/TwigBundle/composer.json | 2 +- src/Symfony/Bundle/WebProfilerBundle/composer.json | 2 +- src/Symfony/Bundle/WebServerBundle/composer.json | 2 +- src/Symfony/Component/Asset/composer.json | 2 +- src/Symfony/Component/BrowserKit/composer.json | 2 +- src/Symfony/Component/Cache/composer.json | 2 +- src/Symfony/Component/ClassLoader/composer.json | 2 +- src/Symfony/Component/Config/composer.json | 2 +- src/Symfony/Component/Console/composer.json | 2 +- src/Symfony/Component/CssSelector/composer.json | 2 +- src/Symfony/Component/Debug/composer.json | 2 +- .../Component/DependencyInjection/composer.json | 2 +- src/Symfony/Component/DomCrawler/composer.json | 2 +- src/Symfony/Component/Dotenv/composer.json | 2 +- src/Symfony/Component/EventDispatcher/composer.json | 2 +- src/Symfony/Component/ExpressionLanguage/composer.json | 2 +- src/Symfony/Component/Filesystem/composer.json | 2 +- src/Symfony/Component/Finder/composer.json | 2 +- src/Symfony/Component/Form/composer.json | 2 +- src/Symfony/Component/HttpFoundation/composer.json | 2 +- src/Symfony/Component/HttpKernel/Kernel.php | 10 +++++----- src/Symfony/Component/HttpKernel/composer.json | 2 +- src/Symfony/Component/Inflector/composer.json | 2 +- src/Symfony/Component/Intl/composer.json | 2 +- src/Symfony/Component/Ldap/composer.json | 2 +- src/Symfony/Component/OptionsResolver/composer.json | 2 +- src/Symfony/Component/Process/composer.json | 2 +- src/Symfony/Component/PropertyAccess/composer.json | 2 +- src/Symfony/Component/PropertyInfo/composer.json | 2 +- src/Symfony/Component/Routing/composer.json | 2 +- src/Symfony/Component/Security/Core/composer.json | 2 +- src/Symfony/Component/Security/Csrf/composer.json | 2 +- src/Symfony/Component/Security/Guard/composer.json | 2 +- src/Symfony/Component/Security/Http/composer.json | 2 +- src/Symfony/Component/Security/composer.json | 2 +- src/Symfony/Component/Serializer/composer.json | 2 +- src/Symfony/Component/Stopwatch/composer.json | 2 +- src/Symfony/Component/Templating/composer.json | 2 +- src/Symfony/Component/Translation/composer.json | 2 +- src/Symfony/Component/Validator/composer.json | 2 +- src/Symfony/Component/VarDumper/composer.json | 2 +- src/Symfony/Component/WebLink/composer.json | 2 +- src/Symfony/Component/Workflow/composer.json | 2 +- src/Symfony/Component/Yaml/composer.json | 2 +- 53 files changed, 57 insertions(+), 57 deletions(-) diff --git a/composer.json b/composer.json index 13ad97446582a..7b3f706469103 100644 --- a/composer.json +++ b/composer.json @@ -133,7 +133,7 @@ "minimum-stability": "dev", "extra": { "branch-alias": { - "dev-master": "3.3-dev" + "dev-master": "3.4-dev" } } } diff --git a/src/Symfony/Bridge/Doctrine/composer.json b/src/Symfony/Bridge/Doctrine/composer.json index 67854035ce6b8..bfa3a495d8e58 100644 --- a/src/Symfony/Bridge/Doctrine/composer.json +++ b/src/Symfony/Bridge/Doctrine/composer.json @@ -57,7 +57,7 @@ "minimum-stability": "dev", "extra": { "branch-alias": { - "dev-master": "3.3-dev" + "dev-master": "3.4-dev" } } } diff --git a/src/Symfony/Bridge/Monolog/composer.json b/src/Symfony/Bridge/Monolog/composer.json index d60949aab872c..ee82d5624927f 100644 --- a/src/Symfony/Bridge/Monolog/composer.json +++ b/src/Symfony/Bridge/Monolog/composer.json @@ -42,7 +42,7 @@ "minimum-stability": "dev", "extra": { "branch-alias": { - "dev-master": "3.3-dev" + "dev-master": "3.4-dev" } } } diff --git a/src/Symfony/Bridge/PhpUnit/composer.json b/src/Symfony/Bridge/PhpUnit/composer.json index 847bb691d3ad8..47f6d7b5e8719 100644 --- a/src/Symfony/Bridge/PhpUnit/composer.json +++ b/src/Symfony/Bridge/PhpUnit/composer.json @@ -40,7 +40,7 @@ "minimum-stability": "dev", "extra": { "branch-alias": { - "dev-master": "3.3-dev" + "dev-master": "3.4-dev" } } } diff --git a/src/Symfony/Bridge/ProxyManager/composer.json b/src/Symfony/Bridge/ProxyManager/composer.json index 42751d000e59d..df96cae73c43d 100644 --- a/src/Symfony/Bridge/ProxyManager/composer.json +++ b/src/Symfony/Bridge/ProxyManager/composer.json @@ -32,7 +32,7 @@ "minimum-stability": "dev", "extra": { "branch-alias": { - "dev-master": "3.3-dev" + "dev-master": "3.4-dev" } } } diff --git a/src/Symfony/Bridge/Twig/composer.json b/src/Symfony/Bridge/Twig/composer.json index 38949fad20792..9b431c04362e2 100644 --- a/src/Symfony/Bridge/Twig/composer.json +++ b/src/Symfony/Bridge/Twig/composer.json @@ -62,7 +62,7 @@ "minimum-stability": "dev", "extra": { "branch-alias": { - "dev-master": "3.3-dev" + "dev-master": "3.4-dev" } } } diff --git a/src/Symfony/Bundle/DebugBundle/composer.json b/src/Symfony/Bundle/DebugBundle/composer.json index 7bf23af8d6ada..f6a6e217a5ea6 100644 --- a/src/Symfony/Bundle/DebugBundle/composer.json +++ b/src/Symfony/Bundle/DebugBundle/composer.json @@ -39,7 +39,7 @@ "minimum-stability": "dev", "extra": { "branch-alias": { - "dev-master": "3.3-dev" + "dev-master": "3.4-dev" } } } diff --git a/src/Symfony/Bundle/FrameworkBundle/composer.json b/src/Symfony/Bundle/FrameworkBundle/composer.json index 75725c32b90b1..63ad8d3246731 100644 --- a/src/Symfony/Bundle/FrameworkBundle/composer.json +++ b/src/Symfony/Bundle/FrameworkBundle/composer.json @@ -92,7 +92,7 @@ "minimum-stability": "dev", "extra": { "branch-alias": { - "dev-master": "3.3-dev" + "dev-master": "3.4-dev" } } } diff --git a/src/Symfony/Bundle/SecurityBundle/composer.json b/src/Symfony/Bundle/SecurityBundle/composer.json index df6049b059964..84274f8167e99 100644 --- a/src/Symfony/Bundle/SecurityBundle/composer.json +++ b/src/Symfony/Bundle/SecurityBundle/composer.json @@ -58,7 +58,7 @@ "minimum-stability": "dev", "extra": { "branch-alias": { - "dev-master": "3.3-dev" + "dev-master": "3.4-dev" } } } diff --git a/src/Symfony/Bundle/TwigBundle/composer.json b/src/Symfony/Bundle/TwigBundle/composer.json index 454349b0f0890..98d93bb4d79b0 100644 --- a/src/Symfony/Bundle/TwigBundle/composer.json +++ b/src/Symfony/Bundle/TwigBundle/composer.json @@ -49,7 +49,7 @@ "minimum-stability": "dev", "extra": { "branch-alias": { - "dev-master": "3.3-dev" + "dev-master": "3.4-dev" } } } diff --git a/src/Symfony/Bundle/WebProfilerBundle/composer.json b/src/Symfony/Bundle/WebProfilerBundle/composer.json index 276f8f68cc4ee..151d5d2eee5ae 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/composer.json +++ b/src/Symfony/Bundle/WebProfilerBundle/composer.json @@ -44,7 +44,7 @@ "minimum-stability": "dev", "extra": { "branch-alias": { - "dev-master": "3.3-dev" + "dev-master": "3.4-dev" } } } diff --git a/src/Symfony/Bundle/WebServerBundle/composer.json b/src/Symfony/Bundle/WebServerBundle/composer.json index c87dab356e2d4..95e4968da69f5 100644 --- a/src/Symfony/Bundle/WebServerBundle/composer.json +++ b/src/Symfony/Bundle/WebServerBundle/composer.json @@ -33,7 +33,7 @@ "minimum-stability": "dev", "extra": { "branch-alias": { - "dev-master": "3.3-dev" + "dev-master": "3.4-dev" } } } diff --git a/src/Symfony/Component/Asset/composer.json b/src/Symfony/Component/Asset/composer.json index 8ed8d9d725212..01e0031216229 100644 --- a/src/Symfony/Component/Asset/composer.json +++ b/src/Symfony/Component/Asset/composer.json @@ -34,7 +34,7 @@ "minimum-stability": "dev", "extra": { "branch-alias": { - "dev-master": "3.3-dev" + "dev-master": "3.4-dev" } } } diff --git a/src/Symfony/Component/BrowserKit/composer.json b/src/Symfony/Component/BrowserKit/composer.json index a18d66e81ea73..e6e07f1a3bff6 100644 --- a/src/Symfony/Component/BrowserKit/composer.json +++ b/src/Symfony/Component/BrowserKit/composer.json @@ -35,7 +35,7 @@ "minimum-stability": "dev", "extra": { "branch-alias": { - "dev-master": "3.3-dev" + "dev-master": "3.4-dev" } } } diff --git a/src/Symfony/Component/Cache/composer.json b/src/Symfony/Component/Cache/composer.json index 5c0df4b2a598a..677d5b0f32f93 100644 --- a/src/Symfony/Component/Cache/composer.json +++ b/src/Symfony/Component/Cache/composer.json @@ -46,7 +46,7 @@ "minimum-stability": "dev", "extra": { "branch-alias": { - "dev-master": "3.3-dev" + "dev-master": "3.4-dev" } } } diff --git a/src/Symfony/Component/ClassLoader/composer.json b/src/Symfony/Component/ClassLoader/composer.json index a1dfc3fa0e096..ebed7026fcade 100644 --- a/src/Symfony/Component/ClassLoader/composer.json +++ b/src/Symfony/Component/ClassLoader/composer.json @@ -34,7 +34,7 @@ }, "extra": { "branch-alias": { - "dev-master": "3.3-dev" + "dev-master": "3.4-dev" } } } diff --git a/src/Symfony/Component/Config/composer.json b/src/Symfony/Component/Config/composer.json index 88090d463da63..407bc1eadbd00 100644 --- a/src/Symfony/Component/Config/composer.json +++ b/src/Symfony/Component/Config/composer.json @@ -38,7 +38,7 @@ "minimum-stability": "dev", "extra": { "branch-alias": { - "dev-master": "3.3-dev" + "dev-master": "3.4-dev" } } } diff --git a/src/Symfony/Component/Console/composer.json b/src/Symfony/Component/Console/composer.json index 362d55d1af8e9..9849b7b54ac4e 100644 --- a/src/Symfony/Component/Console/composer.json +++ b/src/Symfony/Component/Console/composer.json @@ -46,7 +46,7 @@ "minimum-stability": "dev", "extra": { "branch-alias": { - "dev-master": "3.3-dev" + "dev-master": "3.4-dev" } } } diff --git a/src/Symfony/Component/CssSelector/composer.json b/src/Symfony/Component/CssSelector/composer.json index e94cfbded0d33..a4abde9bc8d9f 100644 --- a/src/Symfony/Component/CssSelector/composer.json +++ b/src/Symfony/Component/CssSelector/composer.json @@ -31,7 +31,7 @@ "minimum-stability": "dev", "extra": { "branch-alias": { - "dev-master": "3.3-dev" + "dev-master": "3.4-dev" } } } diff --git a/src/Symfony/Component/Debug/composer.json b/src/Symfony/Component/Debug/composer.json index 6531eefd999ee..a9e58086d67d9 100644 --- a/src/Symfony/Component/Debug/composer.json +++ b/src/Symfony/Component/Debug/composer.json @@ -34,7 +34,7 @@ "minimum-stability": "dev", "extra": { "branch-alias": { - "dev-master": "3.3-dev" + "dev-master": "3.4-dev" } } } diff --git a/src/Symfony/Component/DependencyInjection/composer.json b/src/Symfony/Component/DependencyInjection/composer.json index 7b0932881b464..7269eeb65c7ca 100644 --- a/src/Symfony/Component/DependencyInjection/composer.json +++ b/src/Symfony/Component/DependencyInjection/composer.json @@ -48,7 +48,7 @@ "minimum-stability": "dev", "extra": { "branch-alias": { - "dev-master": "3.3-dev" + "dev-master": "3.4-dev" } } } diff --git a/src/Symfony/Component/DomCrawler/composer.json b/src/Symfony/Component/DomCrawler/composer.json index 84df31fdeae2f..bad9b5a7633e7 100644 --- a/src/Symfony/Component/DomCrawler/composer.json +++ b/src/Symfony/Component/DomCrawler/composer.json @@ -34,7 +34,7 @@ "minimum-stability": "dev", "extra": { "branch-alias": { - "dev-master": "3.3-dev" + "dev-master": "3.4-dev" } } } diff --git a/src/Symfony/Component/Dotenv/composer.json b/src/Symfony/Component/Dotenv/composer.json index 020342bdd4a96..99998756b7ecb 100644 --- a/src/Symfony/Component/Dotenv/composer.json +++ b/src/Symfony/Component/Dotenv/composer.json @@ -30,7 +30,7 @@ "minimum-stability": "dev", "extra": { "branch-alias": { - "dev-master": "3.3-dev" + "dev-master": "3.4-dev" } } } diff --git a/src/Symfony/Component/EventDispatcher/composer.json b/src/Symfony/Component/EventDispatcher/composer.json index faa0429e2d1a0..3c56010c0dbd5 100644 --- a/src/Symfony/Component/EventDispatcher/composer.json +++ b/src/Symfony/Component/EventDispatcher/composer.json @@ -41,7 +41,7 @@ "minimum-stability": "dev", "extra": { "branch-alias": { - "dev-master": "3.3-dev" + "dev-master": "3.4-dev" } } } diff --git a/src/Symfony/Component/ExpressionLanguage/composer.json b/src/Symfony/Component/ExpressionLanguage/composer.json index d9d95f00cf4e4..e0298e4c749c3 100644 --- a/src/Symfony/Component/ExpressionLanguage/composer.json +++ b/src/Symfony/Component/ExpressionLanguage/composer.json @@ -28,7 +28,7 @@ "minimum-stability": "dev", "extra": { "branch-alias": { - "dev-master": "3.3-dev" + "dev-master": "3.4-dev" } } } diff --git a/src/Symfony/Component/Filesystem/composer.json b/src/Symfony/Component/Filesystem/composer.json index 715a34f7d86bc..be3633d272001 100644 --- a/src/Symfony/Component/Filesystem/composer.json +++ b/src/Symfony/Component/Filesystem/composer.json @@ -27,7 +27,7 @@ "minimum-stability": "dev", "extra": { "branch-alias": { - "dev-master": "3.3-dev" + "dev-master": "3.4-dev" } } } diff --git a/src/Symfony/Component/Finder/composer.json b/src/Symfony/Component/Finder/composer.json index b57dd8bcda24e..fddd37d086fd7 100644 --- a/src/Symfony/Component/Finder/composer.json +++ b/src/Symfony/Component/Finder/composer.json @@ -27,7 +27,7 @@ "minimum-stability": "dev", "extra": { "branch-alias": { - "dev-master": "3.3-dev" + "dev-master": "3.4-dev" } } } diff --git a/src/Symfony/Component/Form/composer.json b/src/Symfony/Component/Form/composer.json index 5a1d6ef9cba51..4bd2b395ddbfe 100644 --- a/src/Symfony/Component/Form/composer.json +++ b/src/Symfony/Component/Form/composer.json @@ -57,7 +57,7 @@ "minimum-stability": "dev", "extra": { "branch-alias": { - "dev-master": "3.3-dev" + "dev-master": "3.4-dev" } } } diff --git a/src/Symfony/Component/HttpFoundation/composer.json b/src/Symfony/Component/HttpFoundation/composer.json index dfa25f79ec405..adf85e0fe5245 100644 --- a/src/Symfony/Component/HttpFoundation/composer.json +++ b/src/Symfony/Component/HttpFoundation/composer.json @@ -31,7 +31,7 @@ "minimum-stability": "dev", "extra": { "branch-alias": { - "dev-master": "3.3-dev" + "dev-master": "3.4-dev" } } } diff --git a/src/Symfony/Component/HttpKernel/Kernel.php b/src/Symfony/Component/HttpKernel/Kernel.php index 8d4953886e3a0..a5e104de11131 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -61,15 +61,15 @@ abstract class Kernel implements KernelInterface, TerminableInterface private $projectDir; - const VERSION = '3.3.0-DEV'; - const VERSION_ID = 30300; + const VERSION = '3.4.0-DEV'; + const VERSION_ID = 30400; const MAJOR_VERSION = 3; - const MINOR_VERSION = 3; + const MINOR_VERSION = 4; const RELEASE_VERSION = 0; const EXTRA_VERSION = 'DEV'; - const END_OF_MAINTENANCE = '01/2018'; - const END_OF_LIFE = '07/2018'; + const END_OF_MAINTENANCE = '11/2020'; + const END_OF_LIFE = '11/2021'; /** * Constructor. diff --git a/src/Symfony/Component/HttpKernel/composer.json b/src/Symfony/Component/HttpKernel/composer.json index a680eb05e856d..c17a00950c638 100644 --- a/src/Symfony/Component/HttpKernel/composer.json +++ b/src/Symfony/Component/HttpKernel/composer.json @@ -63,7 +63,7 @@ "minimum-stability": "dev", "extra": { "branch-alias": { - "dev-master": "3.3-dev" + "dev-master": "3.4-dev" } } } diff --git a/src/Symfony/Component/Inflector/composer.json b/src/Symfony/Component/Inflector/composer.json index 79f4ed788f62b..9f4e562bc695a 100644 --- a/src/Symfony/Component/Inflector/composer.json +++ b/src/Symfony/Component/Inflector/composer.json @@ -34,7 +34,7 @@ "minimum-stability": "dev", "extra": { "branch-alias": { - "dev-master": "3.3-dev" + "dev-master": "3.4-dev" } } } diff --git a/src/Symfony/Component/Intl/composer.json b/src/Symfony/Component/Intl/composer.json index dea362ed22040..87c34b5f54ee5 100644 --- a/src/Symfony/Component/Intl/composer.json +++ b/src/Symfony/Component/Intl/composer.json @@ -43,7 +43,7 @@ "minimum-stability": "dev", "extra": { "branch-alias": { - "dev-master": "3.3-dev" + "dev-master": "3.4-dev" } } } diff --git a/src/Symfony/Component/Ldap/composer.json b/src/Symfony/Component/Ldap/composer.json index a2f580f4319fc..dbb5fbdd35af7 100644 --- a/src/Symfony/Component/Ldap/composer.json +++ b/src/Symfony/Component/Ldap/composer.json @@ -30,7 +30,7 @@ "minimum-stability": "dev", "extra": { "branch-alias": { - "dev-master": "3.3-dev" + "dev-master": "3.4-dev" } } } diff --git a/src/Symfony/Component/OptionsResolver/composer.json b/src/Symfony/Component/OptionsResolver/composer.json index a751730af3819..7bb68ece4c27b 100644 --- a/src/Symfony/Component/OptionsResolver/composer.json +++ b/src/Symfony/Component/OptionsResolver/composer.json @@ -27,7 +27,7 @@ "minimum-stability": "dev", "extra": { "branch-alias": { - "dev-master": "3.3-dev" + "dev-master": "3.4-dev" } } } diff --git a/src/Symfony/Component/Process/composer.json b/src/Symfony/Component/Process/composer.json index f899c52b2b818..700cf6b68ec07 100644 --- a/src/Symfony/Component/Process/composer.json +++ b/src/Symfony/Component/Process/composer.json @@ -27,7 +27,7 @@ "minimum-stability": "dev", "extra": { "branch-alias": { - "dev-master": "3.3-dev" + "dev-master": "3.4-dev" } } } diff --git a/src/Symfony/Component/PropertyAccess/composer.json b/src/Symfony/Component/PropertyAccess/composer.json index 508dd78cc70f4..2d0347cbcea84 100644 --- a/src/Symfony/Component/PropertyAccess/composer.json +++ b/src/Symfony/Component/PropertyAccess/composer.json @@ -35,7 +35,7 @@ "minimum-stability": "dev", "extra": { "branch-alias": { - "dev-master": "3.3-dev" + "dev-master": "3.4-dev" } } } diff --git a/src/Symfony/Component/PropertyInfo/composer.json b/src/Symfony/Component/PropertyInfo/composer.json index 8a7b33dbfddb0..9f1956a3cd6b1 100644 --- a/src/Symfony/Component/PropertyInfo/composer.json +++ b/src/Symfony/Component/PropertyInfo/composer.json @@ -53,7 +53,7 @@ "minimum-stability": "dev", "extra": { "branch-alias": { - "dev-master": "3.3-dev" + "dev-master": "3.4-dev" } } } diff --git a/src/Symfony/Component/Routing/composer.json b/src/Symfony/Component/Routing/composer.json index 38069dc4e9ab0..e92517755581e 100644 --- a/src/Symfony/Component/Routing/composer.json +++ b/src/Symfony/Component/Routing/composer.json @@ -50,7 +50,7 @@ "minimum-stability": "dev", "extra": { "branch-alias": { - "dev-master": "3.3-dev" + "dev-master": "3.4-dev" } } } diff --git a/src/Symfony/Component/Security/Core/composer.json b/src/Symfony/Component/Security/Core/composer.json index 3e045fb227545..8db108b3642f7 100644 --- a/src/Symfony/Component/Security/Core/composer.json +++ b/src/Symfony/Component/Security/Core/composer.json @@ -43,7 +43,7 @@ "minimum-stability": "dev", "extra": { "branch-alias": { - "dev-master": "3.3-dev" + "dev-master": "3.4-dev" } } } diff --git a/src/Symfony/Component/Security/Csrf/composer.json b/src/Symfony/Component/Security/Csrf/composer.json index 913cc458b2e2a..d360eefba2b8f 100644 --- a/src/Symfony/Component/Security/Csrf/composer.json +++ b/src/Symfony/Component/Security/Csrf/composer.json @@ -36,7 +36,7 @@ "minimum-stability": "dev", "extra": { "branch-alias": { - "dev-master": "3.3-dev" + "dev-master": "3.4-dev" } } } diff --git a/src/Symfony/Component/Security/Guard/composer.json b/src/Symfony/Component/Security/Guard/composer.json index 4bf473a89fa93..9789ef59f8055 100644 --- a/src/Symfony/Component/Security/Guard/composer.json +++ b/src/Symfony/Component/Security/Guard/composer.json @@ -32,7 +32,7 @@ "minimum-stability": "dev", "extra": { "branch-alias": { - "dev-master": "3.3-dev" + "dev-master": "3.4-dev" } } } diff --git a/src/Symfony/Component/Security/Http/composer.json b/src/Symfony/Component/Security/Http/composer.json index b1458eaa93c7a..61643f4642167 100644 --- a/src/Symfony/Component/Security/Http/composer.json +++ b/src/Symfony/Component/Security/Http/composer.json @@ -43,7 +43,7 @@ "minimum-stability": "dev", "extra": { "branch-alias": { - "dev-master": "3.3-dev" + "dev-master": "3.4-dev" } } } diff --git a/src/Symfony/Component/Security/composer.json b/src/Symfony/Component/Security/composer.json index e6835fe883e2e..202ee891ea3c8 100644 --- a/src/Symfony/Component/Security/composer.json +++ b/src/Symfony/Component/Security/composer.json @@ -56,7 +56,7 @@ "minimum-stability": "dev", "extra": { "branch-alias": { - "dev-master": "3.3-dev" + "dev-master": "3.4-dev" } } } diff --git a/src/Symfony/Component/Serializer/composer.json b/src/Symfony/Component/Serializer/composer.json index 37dd110bc3f25..6ca2534f24109 100644 --- a/src/Symfony/Component/Serializer/composer.json +++ b/src/Symfony/Component/Serializer/composer.json @@ -55,7 +55,7 @@ "minimum-stability": "dev", "extra": { "branch-alias": { - "dev-master": "3.3-dev" + "dev-master": "3.4-dev" } } } diff --git a/src/Symfony/Component/Stopwatch/composer.json b/src/Symfony/Component/Stopwatch/composer.json index 0b40c8d102d0d..85dba6105e5a4 100644 --- a/src/Symfony/Component/Stopwatch/composer.json +++ b/src/Symfony/Component/Stopwatch/composer.json @@ -27,7 +27,7 @@ "minimum-stability": "dev", "extra": { "branch-alias": { - "dev-master": "3.3-dev" + "dev-master": "3.4-dev" } } } diff --git a/src/Symfony/Component/Templating/composer.json b/src/Symfony/Component/Templating/composer.json index 7b1d0fb03bf5e..6890f7816bec3 100644 --- a/src/Symfony/Component/Templating/composer.json +++ b/src/Symfony/Component/Templating/composer.json @@ -33,7 +33,7 @@ "minimum-stability": "dev", "extra": { "branch-alias": { - "dev-master": "3.3-dev" + "dev-master": "3.4-dev" } } } diff --git a/src/Symfony/Component/Translation/composer.json b/src/Symfony/Component/Translation/composer.json index e107e2538a15d..c6036de40efb9 100644 --- a/src/Symfony/Component/Translation/composer.json +++ b/src/Symfony/Component/Translation/composer.json @@ -43,7 +43,7 @@ "minimum-stability": "dev", "extra": { "branch-alias": { - "dev-master": "3.3-dev" + "dev-master": "3.4-dev" } } } diff --git a/src/Symfony/Component/Validator/composer.json b/src/Symfony/Component/Validator/composer.json index 7c7214b54878a..76fa66ef68108 100644 --- a/src/Symfony/Component/Validator/composer.json +++ b/src/Symfony/Component/Validator/composer.json @@ -58,7 +58,7 @@ "minimum-stability": "dev", "extra": { "branch-alias": { - "dev-master": "3.3-dev" + "dev-master": "3.4-dev" } } } diff --git a/src/Symfony/Component/VarDumper/composer.json b/src/Symfony/Component/VarDumper/composer.json index 464462663eca2..441772151b990 100644 --- a/src/Symfony/Component/VarDumper/composer.json +++ b/src/Symfony/Component/VarDumper/composer.json @@ -40,7 +40,7 @@ "minimum-stability": "dev", "extra": { "branch-alias": { - "dev-master": "3.3-dev" + "dev-master": "3.4-dev" } } } diff --git a/src/Symfony/Component/WebLink/composer.json b/src/Symfony/Component/WebLink/composer.json index 336feaf006031..b5bb071ae095c 100644 --- a/src/Symfony/Component/WebLink/composer.json +++ b/src/Symfony/Component/WebLink/composer.json @@ -37,7 +37,7 @@ "minimum-stability": "dev", "extra": { "branch-alias": { - "dev-master": "3.3-dev" + "dev-master": "3.4-dev" } } } diff --git a/src/Symfony/Component/Workflow/composer.json b/src/Symfony/Component/Workflow/composer.json index cba7243523f7c..0bbfdf660e901 100644 --- a/src/Symfony/Component/Workflow/composer.json +++ b/src/Symfony/Component/Workflow/composer.json @@ -36,7 +36,7 @@ "minimum-stability": "dev", "extra": { "branch-alias": { - "dev-master": "3.3-dev" + "dev-master": "3.4-dev" } } } diff --git a/src/Symfony/Component/Yaml/composer.json b/src/Symfony/Component/Yaml/composer.json index 698b5ced17364..d1272b3ce6139 100644 --- a/src/Symfony/Component/Yaml/composer.json +++ b/src/Symfony/Component/Yaml/composer.json @@ -33,7 +33,7 @@ "minimum-stability": "dev", "extra": { "branch-alias": { - "dev-master": "3.3-dev" + "dev-master": "3.4-dev" } } } From d8594de9c64d3f84fd4c27053a9f7b06d3cb47e0 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Wed, 17 May 2017 18:33:00 +0200 Subject: [PATCH 0005/1099] updated version to 4.0 --- composer.json | 2 +- src/Symfony/Bridge/Doctrine/composer.json | 2 +- src/Symfony/Bridge/Monolog/composer.json | 2 +- src/Symfony/Bridge/PhpUnit/composer.json | 2 +- src/Symfony/Bridge/ProxyManager/composer.json | 2 +- src/Symfony/Bridge/Twig/composer.json | 2 +- src/Symfony/Bundle/DebugBundle/composer.json | 2 +- src/Symfony/Bundle/FrameworkBundle/composer.json | 2 +- src/Symfony/Bundle/SecurityBundle/composer.json | 2 +- src/Symfony/Bundle/TwigBundle/composer.json | 2 +- src/Symfony/Bundle/WebProfilerBundle/composer.json | 2 +- src/Symfony/Bundle/WebServerBundle/composer.json | 2 +- src/Symfony/Component/Asset/composer.json | 2 +- src/Symfony/Component/BrowserKit/composer.json | 2 +- src/Symfony/Component/Cache/composer.json | 2 +- src/Symfony/Component/ClassLoader/composer.json | 2 +- src/Symfony/Component/Config/composer.json | 2 +- src/Symfony/Component/Console/composer.json | 2 +- src/Symfony/Component/CssSelector/composer.json | 2 +- src/Symfony/Component/Debug/composer.json | 2 +- .../Component/DependencyInjection/composer.json | 2 +- src/Symfony/Component/DomCrawler/composer.json | 2 +- src/Symfony/Component/Dotenv/composer.json | 2 +- src/Symfony/Component/EventDispatcher/composer.json | 2 +- .../Component/ExpressionLanguage/composer.json | 2 +- src/Symfony/Component/Filesystem/composer.json | 2 +- src/Symfony/Component/Finder/composer.json | 2 +- src/Symfony/Component/Form/composer.json | 2 +- src/Symfony/Component/HttpFoundation/composer.json | 2 +- src/Symfony/Component/HttpKernel/Kernel.php | 12 ++++++------ src/Symfony/Component/HttpKernel/composer.json | 2 +- src/Symfony/Component/Inflector/composer.json | 2 +- src/Symfony/Component/Intl/composer.json | 2 +- src/Symfony/Component/Ldap/composer.json | 2 +- src/Symfony/Component/OptionsResolver/composer.json | 2 +- src/Symfony/Component/Process/composer.json | 2 +- src/Symfony/Component/PropertyAccess/composer.json | 2 +- src/Symfony/Component/PropertyInfo/composer.json | 2 +- src/Symfony/Component/Routing/composer.json | 2 +- src/Symfony/Component/Security/Core/composer.json | 2 +- src/Symfony/Component/Security/Csrf/composer.json | 2 +- src/Symfony/Component/Security/Guard/composer.json | 2 +- src/Symfony/Component/Security/Http/composer.json | 2 +- src/Symfony/Component/Security/composer.json | 2 +- src/Symfony/Component/Serializer/composer.json | 2 +- src/Symfony/Component/Stopwatch/composer.json | 2 +- src/Symfony/Component/Templating/composer.json | 2 +- src/Symfony/Component/Translation/composer.json | 2 +- src/Symfony/Component/Validator/composer.json | 2 +- src/Symfony/Component/VarDumper/composer.json | 2 +- src/Symfony/Component/WebLink/composer.json | 2 +- src/Symfony/Component/Workflow/composer.json | 2 +- src/Symfony/Component/Yaml/composer.json | 2 +- 53 files changed, 58 insertions(+), 58 deletions(-) diff --git a/composer.json b/composer.json index 7b3f706469103..d6649b4be41ae 100644 --- a/composer.json +++ b/composer.json @@ -133,7 +133,7 @@ "minimum-stability": "dev", "extra": { "branch-alias": { - "dev-master": "3.4-dev" + "dev-master": "4.0-dev" } } } diff --git a/src/Symfony/Bridge/Doctrine/composer.json b/src/Symfony/Bridge/Doctrine/composer.json index bfa3a495d8e58..c216c1a0965fd 100644 --- a/src/Symfony/Bridge/Doctrine/composer.json +++ b/src/Symfony/Bridge/Doctrine/composer.json @@ -57,7 +57,7 @@ "minimum-stability": "dev", "extra": { "branch-alias": { - "dev-master": "3.4-dev" + "dev-master": "4.0-dev" } } } diff --git a/src/Symfony/Bridge/Monolog/composer.json b/src/Symfony/Bridge/Monolog/composer.json index ee82d5624927f..1aaeb12c51640 100644 --- a/src/Symfony/Bridge/Monolog/composer.json +++ b/src/Symfony/Bridge/Monolog/composer.json @@ -42,7 +42,7 @@ "minimum-stability": "dev", "extra": { "branch-alias": { - "dev-master": "3.4-dev" + "dev-master": "4.0-dev" } } } diff --git a/src/Symfony/Bridge/PhpUnit/composer.json b/src/Symfony/Bridge/PhpUnit/composer.json index 47f6d7b5e8719..cdaafa0610976 100644 --- a/src/Symfony/Bridge/PhpUnit/composer.json +++ b/src/Symfony/Bridge/PhpUnit/composer.json @@ -40,7 +40,7 @@ "minimum-stability": "dev", "extra": { "branch-alias": { - "dev-master": "3.4-dev" + "dev-master": "4.0-dev" } } } diff --git a/src/Symfony/Bridge/ProxyManager/composer.json b/src/Symfony/Bridge/ProxyManager/composer.json index df96cae73c43d..b9a06a7199026 100644 --- a/src/Symfony/Bridge/ProxyManager/composer.json +++ b/src/Symfony/Bridge/ProxyManager/composer.json @@ -32,7 +32,7 @@ "minimum-stability": "dev", "extra": { "branch-alias": { - "dev-master": "3.4-dev" + "dev-master": "4.0-dev" } } } diff --git a/src/Symfony/Bridge/Twig/composer.json b/src/Symfony/Bridge/Twig/composer.json index 9b431c04362e2..29991fc615fb8 100644 --- a/src/Symfony/Bridge/Twig/composer.json +++ b/src/Symfony/Bridge/Twig/composer.json @@ -62,7 +62,7 @@ "minimum-stability": "dev", "extra": { "branch-alias": { - "dev-master": "3.4-dev" + "dev-master": "4.0-dev" } } } diff --git a/src/Symfony/Bundle/DebugBundle/composer.json b/src/Symfony/Bundle/DebugBundle/composer.json index f6a6e217a5ea6..68c45be59d882 100644 --- a/src/Symfony/Bundle/DebugBundle/composer.json +++ b/src/Symfony/Bundle/DebugBundle/composer.json @@ -39,7 +39,7 @@ "minimum-stability": "dev", "extra": { "branch-alias": { - "dev-master": "3.4-dev" + "dev-master": "4.0-dev" } } } diff --git a/src/Symfony/Bundle/FrameworkBundle/composer.json b/src/Symfony/Bundle/FrameworkBundle/composer.json index 63ad8d3246731..b5235f61fb553 100644 --- a/src/Symfony/Bundle/FrameworkBundle/composer.json +++ b/src/Symfony/Bundle/FrameworkBundle/composer.json @@ -92,7 +92,7 @@ "minimum-stability": "dev", "extra": { "branch-alias": { - "dev-master": "3.4-dev" + "dev-master": "4.0-dev" } } } diff --git a/src/Symfony/Bundle/SecurityBundle/composer.json b/src/Symfony/Bundle/SecurityBundle/composer.json index 84274f8167e99..836dd57ae1463 100644 --- a/src/Symfony/Bundle/SecurityBundle/composer.json +++ b/src/Symfony/Bundle/SecurityBundle/composer.json @@ -58,7 +58,7 @@ "minimum-stability": "dev", "extra": { "branch-alias": { - "dev-master": "3.4-dev" + "dev-master": "4.0-dev" } } } diff --git a/src/Symfony/Bundle/TwigBundle/composer.json b/src/Symfony/Bundle/TwigBundle/composer.json index 98d93bb4d79b0..965167e1db2f8 100644 --- a/src/Symfony/Bundle/TwigBundle/composer.json +++ b/src/Symfony/Bundle/TwigBundle/composer.json @@ -49,7 +49,7 @@ "minimum-stability": "dev", "extra": { "branch-alias": { - "dev-master": "3.4-dev" + "dev-master": "4.0-dev" } } } diff --git a/src/Symfony/Bundle/WebProfilerBundle/composer.json b/src/Symfony/Bundle/WebProfilerBundle/composer.json index 151d5d2eee5ae..94c34257e5cf8 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/composer.json +++ b/src/Symfony/Bundle/WebProfilerBundle/composer.json @@ -44,7 +44,7 @@ "minimum-stability": "dev", "extra": { "branch-alias": { - "dev-master": "3.4-dev" + "dev-master": "4.0-dev" } } } diff --git a/src/Symfony/Bundle/WebServerBundle/composer.json b/src/Symfony/Bundle/WebServerBundle/composer.json index 95e4968da69f5..ec97bd6ff4676 100644 --- a/src/Symfony/Bundle/WebServerBundle/composer.json +++ b/src/Symfony/Bundle/WebServerBundle/composer.json @@ -33,7 +33,7 @@ "minimum-stability": "dev", "extra": { "branch-alias": { - "dev-master": "3.4-dev" + "dev-master": "4.0-dev" } } } diff --git a/src/Symfony/Component/Asset/composer.json b/src/Symfony/Component/Asset/composer.json index 01e0031216229..125aff8b97d18 100644 --- a/src/Symfony/Component/Asset/composer.json +++ b/src/Symfony/Component/Asset/composer.json @@ -34,7 +34,7 @@ "minimum-stability": "dev", "extra": { "branch-alias": { - "dev-master": "3.4-dev" + "dev-master": "4.0-dev" } } } diff --git a/src/Symfony/Component/BrowserKit/composer.json b/src/Symfony/Component/BrowserKit/composer.json index e6e07f1a3bff6..8a1e57db90943 100644 --- a/src/Symfony/Component/BrowserKit/composer.json +++ b/src/Symfony/Component/BrowserKit/composer.json @@ -35,7 +35,7 @@ "minimum-stability": "dev", "extra": { "branch-alias": { - "dev-master": "3.4-dev" + "dev-master": "4.0-dev" } } } diff --git a/src/Symfony/Component/Cache/composer.json b/src/Symfony/Component/Cache/composer.json index 677d5b0f32f93..4c448dd3459f2 100644 --- a/src/Symfony/Component/Cache/composer.json +++ b/src/Symfony/Component/Cache/composer.json @@ -46,7 +46,7 @@ "minimum-stability": "dev", "extra": { "branch-alias": { - "dev-master": "3.4-dev" + "dev-master": "4.0-dev" } } } diff --git a/src/Symfony/Component/ClassLoader/composer.json b/src/Symfony/Component/ClassLoader/composer.json index ebed7026fcade..540ed8a6d2ba8 100644 --- a/src/Symfony/Component/ClassLoader/composer.json +++ b/src/Symfony/Component/ClassLoader/composer.json @@ -34,7 +34,7 @@ }, "extra": { "branch-alias": { - "dev-master": "3.4-dev" + "dev-master": "4.0-dev" } } } diff --git a/src/Symfony/Component/Config/composer.json b/src/Symfony/Component/Config/composer.json index 407bc1eadbd00..bd1d9fe32da8b 100644 --- a/src/Symfony/Component/Config/composer.json +++ b/src/Symfony/Component/Config/composer.json @@ -38,7 +38,7 @@ "minimum-stability": "dev", "extra": { "branch-alias": { - "dev-master": "3.4-dev" + "dev-master": "4.0-dev" } } } diff --git a/src/Symfony/Component/Console/composer.json b/src/Symfony/Component/Console/composer.json index 9849b7b54ac4e..800004220aacf 100644 --- a/src/Symfony/Component/Console/composer.json +++ b/src/Symfony/Component/Console/composer.json @@ -46,7 +46,7 @@ "minimum-stability": "dev", "extra": { "branch-alias": { - "dev-master": "3.4-dev" + "dev-master": "4.0-dev" } } } diff --git a/src/Symfony/Component/CssSelector/composer.json b/src/Symfony/Component/CssSelector/composer.json index a4abde9bc8d9f..3b54f34d3c61c 100644 --- a/src/Symfony/Component/CssSelector/composer.json +++ b/src/Symfony/Component/CssSelector/composer.json @@ -31,7 +31,7 @@ "minimum-stability": "dev", "extra": { "branch-alias": { - "dev-master": "3.4-dev" + "dev-master": "4.0-dev" } } } diff --git a/src/Symfony/Component/Debug/composer.json b/src/Symfony/Component/Debug/composer.json index a9e58086d67d9..caac17e344612 100644 --- a/src/Symfony/Component/Debug/composer.json +++ b/src/Symfony/Component/Debug/composer.json @@ -34,7 +34,7 @@ "minimum-stability": "dev", "extra": { "branch-alias": { - "dev-master": "3.4-dev" + "dev-master": "4.0-dev" } } } diff --git a/src/Symfony/Component/DependencyInjection/composer.json b/src/Symfony/Component/DependencyInjection/composer.json index 7269eeb65c7ca..987cc708c0518 100644 --- a/src/Symfony/Component/DependencyInjection/composer.json +++ b/src/Symfony/Component/DependencyInjection/composer.json @@ -48,7 +48,7 @@ "minimum-stability": "dev", "extra": { "branch-alias": { - "dev-master": "3.4-dev" + "dev-master": "4.0-dev" } } } diff --git a/src/Symfony/Component/DomCrawler/composer.json b/src/Symfony/Component/DomCrawler/composer.json index bad9b5a7633e7..606c0ae96f8b3 100644 --- a/src/Symfony/Component/DomCrawler/composer.json +++ b/src/Symfony/Component/DomCrawler/composer.json @@ -34,7 +34,7 @@ "minimum-stability": "dev", "extra": { "branch-alias": { - "dev-master": "3.4-dev" + "dev-master": "4.0-dev" } } } diff --git a/src/Symfony/Component/Dotenv/composer.json b/src/Symfony/Component/Dotenv/composer.json index 99998756b7ecb..c9f5e1155858e 100644 --- a/src/Symfony/Component/Dotenv/composer.json +++ b/src/Symfony/Component/Dotenv/composer.json @@ -30,7 +30,7 @@ "minimum-stability": "dev", "extra": { "branch-alias": { - "dev-master": "3.4-dev" + "dev-master": "4.0-dev" } } } diff --git a/src/Symfony/Component/EventDispatcher/composer.json b/src/Symfony/Component/EventDispatcher/composer.json index 3c56010c0dbd5..5e0b606826723 100644 --- a/src/Symfony/Component/EventDispatcher/composer.json +++ b/src/Symfony/Component/EventDispatcher/composer.json @@ -41,7 +41,7 @@ "minimum-stability": "dev", "extra": { "branch-alias": { - "dev-master": "3.4-dev" + "dev-master": "4.0-dev" } } } diff --git a/src/Symfony/Component/ExpressionLanguage/composer.json b/src/Symfony/Component/ExpressionLanguage/composer.json index e0298e4c749c3..06b1e414f5427 100644 --- a/src/Symfony/Component/ExpressionLanguage/composer.json +++ b/src/Symfony/Component/ExpressionLanguage/composer.json @@ -28,7 +28,7 @@ "minimum-stability": "dev", "extra": { "branch-alias": { - "dev-master": "3.4-dev" + "dev-master": "4.0-dev" } } } diff --git a/src/Symfony/Component/Filesystem/composer.json b/src/Symfony/Component/Filesystem/composer.json index be3633d272001..289d3e63913b4 100644 --- a/src/Symfony/Component/Filesystem/composer.json +++ b/src/Symfony/Component/Filesystem/composer.json @@ -27,7 +27,7 @@ "minimum-stability": "dev", "extra": { "branch-alias": { - "dev-master": "3.4-dev" + "dev-master": "4.0-dev" } } } diff --git a/src/Symfony/Component/Finder/composer.json b/src/Symfony/Component/Finder/composer.json index fddd37d086fd7..410d92ba3db6b 100644 --- a/src/Symfony/Component/Finder/composer.json +++ b/src/Symfony/Component/Finder/composer.json @@ -27,7 +27,7 @@ "minimum-stability": "dev", "extra": { "branch-alias": { - "dev-master": "3.4-dev" + "dev-master": "4.0-dev" } } } diff --git a/src/Symfony/Component/Form/composer.json b/src/Symfony/Component/Form/composer.json index 4bd2b395ddbfe..cd8f95ad4abe6 100644 --- a/src/Symfony/Component/Form/composer.json +++ b/src/Symfony/Component/Form/composer.json @@ -57,7 +57,7 @@ "minimum-stability": "dev", "extra": { "branch-alias": { - "dev-master": "3.4-dev" + "dev-master": "4.0-dev" } } } diff --git a/src/Symfony/Component/HttpFoundation/composer.json b/src/Symfony/Component/HttpFoundation/composer.json index adf85e0fe5245..f46467e8f67f3 100644 --- a/src/Symfony/Component/HttpFoundation/composer.json +++ b/src/Symfony/Component/HttpFoundation/composer.json @@ -31,7 +31,7 @@ "minimum-stability": "dev", "extra": { "branch-alias": { - "dev-master": "3.4-dev" + "dev-master": "4.0-dev" } } } diff --git a/src/Symfony/Component/HttpKernel/Kernel.php b/src/Symfony/Component/HttpKernel/Kernel.php index a5e104de11131..ae31a46fc985f 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -61,15 +61,15 @@ abstract class Kernel implements KernelInterface, TerminableInterface private $projectDir; - const VERSION = '3.4.0-DEV'; - const VERSION_ID = 30400; - const MAJOR_VERSION = 3; - const MINOR_VERSION = 4; + const VERSION = '4.0.0-DEV'; + const VERSION_ID = 40000; + const MAJOR_VERSION = 0; + const MINOR_VERSION = 0; const RELEASE_VERSION = 0; const EXTRA_VERSION = 'DEV'; - const END_OF_MAINTENANCE = '11/2020'; - const END_OF_LIFE = '11/2021'; + const END_OF_MAINTENANCE = '07/2018'; + const END_OF_LIFE = '01/2019'; /** * Constructor. diff --git a/src/Symfony/Component/HttpKernel/composer.json b/src/Symfony/Component/HttpKernel/composer.json index c17a00950c638..8f5ebcbd08ec5 100644 --- a/src/Symfony/Component/HttpKernel/composer.json +++ b/src/Symfony/Component/HttpKernel/composer.json @@ -63,7 +63,7 @@ "minimum-stability": "dev", "extra": { "branch-alias": { - "dev-master": "3.4-dev" + "dev-master": "4.0-dev" } } } diff --git a/src/Symfony/Component/Inflector/composer.json b/src/Symfony/Component/Inflector/composer.json index 9f4e562bc695a..0f88a6c6295da 100644 --- a/src/Symfony/Component/Inflector/composer.json +++ b/src/Symfony/Component/Inflector/composer.json @@ -34,7 +34,7 @@ "minimum-stability": "dev", "extra": { "branch-alias": { - "dev-master": "3.4-dev" + "dev-master": "4.0-dev" } } } diff --git a/src/Symfony/Component/Intl/composer.json b/src/Symfony/Component/Intl/composer.json index 87c34b5f54ee5..fb2ee24103caa 100644 --- a/src/Symfony/Component/Intl/composer.json +++ b/src/Symfony/Component/Intl/composer.json @@ -43,7 +43,7 @@ "minimum-stability": "dev", "extra": { "branch-alias": { - "dev-master": "3.4-dev" + "dev-master": "4.0-dev" } } } diff --git a/src/Symfony/Component/Ldap/composer.json b/src/Symfony/Component/Ldap/composer.json index dbb5fbdd35af7..5579a6e21cd4c 100644 --- a/src/Symfony/Component/Ldap/composer.json +++ b/src/Symfony/Component/Ldap/composer.json @@ -30,7 +30,7 @@ "minimum-stability": "dev", "extra": { "branch-alias": { - "dev-master": "3.4-dev" + "dev-master": "4.0-dev" } } } diff --git a/src/Symfony/Component/OptionsResolver/composer.json b/src/Symfony/Component/OptionsResolver/composer.json index 7bb68ece4c27b..8f8ba964a2148 100644 --- a/src/Symfony/Component/OptionsResolver/composer.json +++ b/src/Symfony/Component/OptionsResolver/composer.json @@ -27,7 +27,7 @@ "minimum-stability": "dev", "extra": { "branch-alias": { - "dev-master": "3.4-dev" + "dev-master": "4.0-dev" } } } diff --git a/src/Symfony/Component/Process/composer.json b/src/Symfony/Component/Process/composer.json index 700cf6b68ec07..df2bce0a1bed6 100644 --- a/src/Symfony/Component/Process/composer.json +++ b/src/Symfony/Component/Process/composer.json @@ -27,7 +27,7 @@ "minimum-stability": "dev", "extra": { "branch-alias": { - "dev-master": "3.4-dev" + "dev-master": "4.0-dev" } } } diff --git a/src/Symfony/Component/PropertyAccess/composer.json b/src/Symfony/Component/PropertyAccess/composer.json index 2d0347cbcea84..15b385b4a037c 100644 --- a/src/Symfony/Component/PropertyAccess/composer.json +++ b/src/Symfony/Component/PropertyAccess/composer.json @@ -35,7 +35,7 @@ "minimum-stability": "dev", "extra": { "branch-alias": { - "dev-master": "3.4-dev" + "dev-master": "4.0-dev" } } } diff --git a/src/Symfony/Component/PropertyInfo/composer.json b/src/Symfony/Component/PropertyInfo/composer.json index 9f1956a3cd6b1..7c73959ce38f7 100644 --- a/src/Symfony/Component/PropertyInfo/composer.json +++ b/src/Symfony/Component/PropertyInfo/composer.json @@ -53,7 +53,7 @@ "minimum-stability": "dev", "extra": { "branch-alias": { - "dev-master": "3.4-dev" + "dev-master": "4.0-dev" } } } diff --git a/src/Symfony/Component/Routing/composer.json b/src/Symfony/Component/Routing/composer.json index e92517755581e..78d022f19a70f 100644 --- a/src/Symfony/Component/Routing/composer.json +++ b/src/Symfony/Component/Routing/composer.json @@ -50,7 +50,7 @@ "minimum-stability": "dev", "extra": { "branch-alias": { - "dev-master": "3.4-dev" + "dev-master": "4.0-dev" } } } diff --git a/src/Symfony/Component/Security/Core/composer.json b/src/Symfony/Component/Security/Core/composer.json index 8db108b3642f7..5f26102e4b449 100644 --- a/src/Symfony/Component/Security/Core/composer.json +++ b/src/Symfony/Component/Security/Core/composer.json @@ -43,7 +43,7 @@ "minimum-stability": "dev", "extra": { "branch-alias": { - "dev-master": "3.4-dev" + "dev-master": "4.0-dev" } } } diff --git a/src/Symfony/Component/Security/Csrf/composer.json b/src/Symfony/Component/Security/Csrf/composer.json index d360eefba2b8f..313e4df80f40d 100644 --- a/src/Symfony/Component/Security/Csrf/composer.json +++ b/src/Symfony/Component/Security/Csrf/composer.json @@ -36,7 +36,7 @@ "minimum-stability": "dev", "extra": { "branch-alias": { - "dev-master": "3.4-dev" + "dev-master": "4.0-dev" } } } diff --git a/src/Symfony/Component/Security/Guard/composer.json b/src/Symfony/Component/Security/Guard/composer.json index 9789ef59f8055..e04bea951910a 100644 --- a/src/Symfony/Component/Security/Guard/composer.json +++ b/src/Symfony/Component/Security/Guard/composer.json @@ -32,7 +32,7 @@ "minimum-stability": "dev", "extra": { "branch-alias": { - "dev-master": "3.4-dev" + "dev-master": "4.0-dev" } } } diff --git a/src/Symfony/Component/Security/Http/composer.json b/src/Symfony/Component/Security/Http/composer.json index 61643f4642167..d9fcb75f67d4f 100644 --- a/src/Symfony/Component/Security/Http/composer.json +++ b/src/Symfony/Component/Security/Http/composer.json @@ -43,7 +43,7 @@ "minimum-stability": "dev", "extra": { "branch-alias": { - "dev-master": "3.4-dev" + "dev-master": "4.0-dev" } } } diff --git a/src/Symfony/Component/Security/composer.json b/src/Symfony/Component/Security/composer.json index 202ee891ea3c8..3b2741cee6efd 100644 --- a/src/Symfony/Component/Security/composer.json +++ b/src/Symfony/Component/Security/composer.json @@ -56,7 +56,7 @@ "minimum-stability": "dev", "extra": { "branch-alias": { - "dev-master": "3.4-dev" + "dev-master": "4.0-dev" } } } diff --git a/src/Symfony/Component/Serializer/composer.json b/src/Symfony/Component/Serializer/composer.json index 6ca2534f24109..275ca26a90198 100644 --- a/src/Symfony/Component/Serializer/composer.json +++ b/src/Symfony/Component/Serializer/composer.json @@ -55,7 +55,7 @@ "minimum-stability": "dev", "extra": { "branch-alias": { - "dev-master": "3.4-dev" + "dev-master": "4.0-dev" } } } diff --git a/src/Symfony/Component/Stopwatch/composer.json b/src/Symfony/Component/Stopwatch/composer.json index 85dba6105e5a4..be5a2b16a9869 100644 --- a/src/Symfony/Component/Stopwatch/composer.json +++ b/src/Symfony/Component/Stopwatch/composer.json @@ -27,7 +27,7 @@ "minimum-stability": "dev", "extra": { "branch-alias": { - "dev-master": "3.4-dev" + "dev-master": "4.0-dev" } } } diff --git a/src/Symfony/Component/Templating/composer.json b/src/Symfony/Component/Templating/composer.json index 6890f7816bec3..85ebba399b790 100644 --- a/src/Symfony/Component/Templating/composer.json +++ b/src/Symfony/Component/Templating/composer.json @@ -33,7 +33,7 @@ "minimum-stability": "dev", "extra": { "branch-alias": { - "dev-master": "3.4-dev" + "dev-master": "4.0-dev" } } } diff --git a/src/Symfony/Component/Translation/composer.json b/src/Symfony/Component/Translation/composer.json index c6036de40efb9..df62d505d73f4 100644 --- a/src/Symfony/Component/Translation/composer.json +++ b/src/Symfony/Component/Translation/composer.json @@ -43,7 +43,7 @@ "minimum-stability": "dev", "extra": { "branch-alias": { - "dev-master": "3.4-dev" + "dev-master": "4.0-dev" } } } diff --git a/src/Symfony/Component/Validator/composer.json b/src/Symfony/Component/Validator/composer.json index 76fa66ef68108..4fa7c6eb6f6d5 100644 --- a/src/Symfony/Component/Validator/composer.json +++ b/src/Symfony/Component/Validator/composer.json @@ -58,7 +58,7 @@ "minimum-stability": "dev", "extra": { "branch-alias": { - "dev-master": "3.4-dev" + "dev-master": "4.0-dev" } } } diff --git a/src/Symfony/Component/VarDumper/composer.json b/src/Symfony/Component/VarDumper/composer.json index 441772151b990..7b0e5ca173fcb 100644 --- a/src/Symfony/Component/VarDumper/composer.json +++ b/src/Symfony/Component/VarDumper/composer.json @@ -40,7 +40,7 @@ "minimum-stability": "dev", "extra": { "branch-alias": { - "dev-master": "3.4-dev" + "dev-master": "4.0-dev" } } } diff --git a/src/Symfony/Component/WebLink/composer.json b/src/Symfony/Component/WebLink/composer.json index b5bb071ae095c..a556685a13621 100644 --- a/src/Symfony/Component/WebLink/composer.json +++ b/src/Symfony/Component/WebLink/composer.json @@ -37,7 +37,7 @@ "minimum-stability": "dev", "extra": { "branch-alias": { - "dev-master": "3.4-dev" + "dev-master": "4.0-dev" } } } diff --git a/src/Symfony/Component/Workflow/composer.json b/src/Symfony/Component/Workflow/composer.json index 0bbfdf660e901..311cc87664e5c 100644 --- a/src/Symfony/Component/Workflow/composer.json +++ b/src/Symfony/Component/Workflow/composer.json @@ -36,7 +36,7 @@ "minimum-stability": "dev", "extra": { "branch-alias": { - "dev-master": "3.4-dev" + "dev-master": "4.0-dev" } } } diff --git a/src/Symfony/Component/Yaml/composer.json b/src/Symfony/Component/Yaml/composer.json index d1272b3ce6139..1cfe57e522eb4 100644 --- a/src/Symfony/Component/Yaml/composer.json +++ b/src/Symfony/Component/Yaml/composer.json @@ -33,7 +33,7 @@ "minimum-stability": "dev", "extra": { "branch-alias": { - "dev-master": "3.4-dev" + "dev-master": "4.0-dev" } } } From 16da6861be359906f26b4212214ae0877b0eb094 Mon Sep 17 00:00:00 2001 From: David Maicher Date: Wed, 17 May 2017 20:41:55 +0200 Subject: [PATCH 0006/1099] [Security] fix switch user _exit without having current token --- .../Security/Http/Firewall/SwitchUserListener.php | 2 +- .../Http/Tests/Firewall/SwitchUserListenerTest.php | 11 +++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/Security/Http/Firewall/SwitchUserListener.php b/src/Symfony/Component/Security/Http/Firewall/SwitchUserListener.php index 7de83d2513369..606392de8a16c 100644 --- a/src/Symfony/Component/Security/Http/Firewall/SwitchUserListener.php +++ b/src/Symfony/Component/Security/Http/Firewall/SwitchUserListener.php @@ -158,7 +158,7 @@ private function attemptSwitchUser(Request $request) */ private function attemptExitUser(Request $request) { - if (false === $original = $this->getOriginalToken($this->tokenStorage->getToken())) { + if (null === ($currentToken = $this->tokenStorage->getToken()) || false === $original = $this->getOriginalToken($currentToken)) { throw new AuthenticationCredentialsNotFoundException('Could not find original Token object.'); } diff --git a/src/Symfony/Component/Security/Http/Tests/Firewall/SwitchUserListenerTest.php b/src/Symfony/Component/Security/Http/Tests/Firewall/SwitchUserListenerTest.php index 43013520c36ba..6b6cb246c985f 100644 --- a/src/Symfony/Component/Security/Http/Tests/Firewall/SwitchUserListenerTest.php +++ b/src/Symfony/Component/Security/Http/Tests/Firewall/SwitchUserListenerTest.php @@ -65,6 +65,17 @@ public function testEventIsIgnoredIfUsernameIsNotPassedWithTheRequest() $this->assertNull($this->tokenStorage->getToken()); } + /** + * @expectedException \Symfony\Component\Security\Core\Exception\AuthenticationCredentialsNotFoundException + */ + public function testExitUserThrowsAuthenticationExceptionIfNoCurrentToken() + { + $this->tokenStorage->setToken(null); + $this->request->query->set('_switch_user', '_exit'); + $listener = new SwitchUserListener($this->tokenStorage, $this->userProvider, $this->userChecker, 'provider123', $this->accessDecisionManager); + $listener->handle($this->event); + } + /** * @expectedException \Symfony\Component\Security\Core\Exception\AuthenticationCredentialsNotFoundException */ From aa223f5c6c7c6ae6876e5ed44b05797a6f3293da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Je=CC=81re=CC=81my=20Marodon?= Date: Thu, 18 May 2017 10:33:55 +0200 Subject: [PATCH 0007/1099] Fix the kernel version of 4.0 --- src/Symfony/Component/HttpKernel/Kernel.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/HttpKernel/Kernel.php b/src/Symfony/Component/HttpKernel/Kernel.php index ae31a46fc985f..02fe035c0b29d 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -63,7 +63,7 @@ abstract class Kernel implements KernelInterface, TerminableInterface const VERSION = '4.0.0-DEV'; const VERSION_ID = 40000; - const MAJOR_VERSION = 0; + const MAJOR_VERSION = 4; const MINOR_VERSION = 0; const RELEASE_VERSION = 0; const EXTRA_VERSION = 'DEV'; From bcc408cfad7a131dc14c877980a305f57c063c8a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Thu, 18 May 2017 08:33:50 +0200 Subject: [PATCH 0008/1099] Allow individual bridges, bundles and components to be used with 4.0 --- src/Symfony/Bridge/Doctrine/composer.json | 22 +++---- src/Symfony/Bridge/Monolog/composer.json | 8 +-- src/Symfony/Bridge/ProxyManager/composer.json | 4 +- src/Symfony/Bridge/Twig/composer.json | 28 ++++----- src/Symfony/Bundle/DebugBundle/composer.json | 12 ++-- .../Bundle/FrameworkBundle/composer.json | 58 +++++++++---------- .../Bundle/SecurityBundle/composer.json | 38 ++++++------ src/Symfony/Bundle/TwigBundle/composer.json | 22 +++---- .../Bundle/WebProfilerBundle/composer.json | 16 ++--- .../Bundle/WebServerBundle/composer.json | 6 +- src/Symfony/Component/Asset/composer.json | 4 +- .../Component/BrowserKit/composer.json | 6 +- .../Component/ClassLoader/composer.json | 2 +- src/Symfony/Component/Config/composer.json | 6 +- src/Symfony/Component/Console/composer.json | 12 ++-- src/Symfony/Component/Debug/composer.json | 2 +- .../DependencyInjection/composer.json | 6 +- .../Component/DomCrawler/composer.json | 2 +- src/Symfony/Component/Dotenv/composer.json | 2 +- .../Component/EventDispatcher/composer.json | 8 +-- .../ExpressionLanguage/composer.json | 2 +- src/Symfony/Component/Form/composer.json | 24 ++++---- .../Component/HttpFoundation/composer.json | 2 +- .../Component/HttpKernel/composer.json | 35 ++++++----- src/Symfony/Component/Intl/composer.json | 2 +- src/Symfony/Component/Ldap/composer.json | 2 +- .../Component/PropertyAccess/composer.json | 4 +- .../Component/PropertyInfo/composer.json | 8 +-- src/Symfony/Component/Routing/composer.json | 10 ++-- .../Component/Security/Core/composer.json | 10 ++-- .../Component/Security/Csrf/composer.json | 4 +- .../Component/Security/Guard/composer.json | 4 +- .../Component/Security/Http/composer.json | 14 ++--- src/Symfony/Component/Security/composer.json | 18 +++--- .../Component/Serializer/composer.json | 14 ++--- .../Component/Translation/composer.json | 6 +- src/Symfony/Component/Validator/composer.json | 16 ++--- src/Symfony/Component/WebLink/composer.json | 6 +- src/Symfony/Component/Workflow/composer.json | 10 ++-- src/Symfony/Component/Yaml/composer.json | 2 +- 40 files changed, 228 insertions(+), 229 deletions(-) diff --git a/src/Symfony/Bridge/Doctrine/composer.json b/src/Symfony/Bridge/Doctrine/composer.json index bfa3a495d8e58..f4da3ac162796 100644 --- a/src/Symfony/Bridge/Doctrine/composer.json +++ b/src/Symfony/Bridge/Doctrine/composer.json @@ -21,17 +21,17 @@ "symfony/polyfill-mbstring": "~1.0" }, "require-dev": { - "symfony/stopwatch": "~2.8|~3.0", - "symfony/dependency-injection": "~3.3", - "symfony/form": "^3.2.5", - "symfony/http-kernel": "~2.8|~3.0", - "symfony/property-access": "~2.8|~3.0", - "symfony/property-info": "~2.8|3.0", - "symfony/proxy-manager-bridge": "~2.8|~3.0", - "symfony/security": "~2.8|~3.0", - "symfony/expression-language": "~2.8|~3.0", - "symfony/validator": "^2.8.18|^3.2.5", - "symfony/translation": "~2.8|~3.0", + "symfony/stopwatch": "~2.8|~3.0|~4.0.0", + "symfony/dependency-injection": "~3.3|~4.0.0", + "symfony/form": "^3.2.5|~4.0.0", + "symfony/http-kernel": "~2.8|~3.0|~4.0.0", + "symfony/property-access": "~2.8|~3.0|~4.0.0", + "symfony/property-info": "~2.8|3.0|~4.0.0", + "symfony/proxy-manager-bridge": "~2.8|~3.0|~4.0.0", + "symfony/security": "~2.8|~3.0|~4.0.0", + "symfony/expression-language": "~2.8|~3.0|~4.0.0", + "symfony/validator": "^2.8.18|^3.2.5|~4.0.0", + "symfony/translation": "~2.8|~3.0|~4.0.0", "doctrine/data-fixtures": "1.0.*", "doctrine/dbal": "~2.4", "doctrine/orm": "^2.4.5" diff --git a/src/Symfony/Bridge/Monolog/composer.json b/src/Symfony/Bridge/Monolog/composer.json index ee82d5624927f..5622ce1b88b09 100644 --- a/src/Symfony/Bridge/Monolog/composer.json +++ b/src/Symfony/Bridge/Monolog/composer.json @@ -18,12 +18,12 @@ "require": { "php": ">=5.5.9", "monolog/monolog": "~1.19", - "symfony/http-kernel": "~2.8|~3.0" + "symfony/http-kernel": "~2.8|~3.0|~4.0.0" }, "require-dev": { - "symfony/console": "~2.8|~3.0", - "symfony/event-dispatcher": "~2.8|~3.0", - "symfony/var-dumper": "~3.3" + "symfony/console": "~2.8|~3.0|~4.0.0", + "symfony/event-dispatcher": "~2.8|~3.0|~4.0.0", + "symfony/var-dumper": "~3.3|~4.0.0" }, "conflict": { "symfony/http-foundation": "<3.3" diff --git a/src/Symfony/Bridge/ProxyManager/composer.json b/src/Symfony/Bridge/ProxyManager/composer.json index df96cae73c43d..a13589816c652 100644 --- a/src/Symfony/Bridge/ProxyManager/composer.json +++ b/src/Symfony/Bridge/ProxyManager/composer.json @@ -17,11 +17,11 @@ ], "require": { "php": ">=5.5.9", - "symfony/dependency-injection": "~2.8|~3.0", + "symfony/dependency-injection": "~2.8|~3.0|~4.0.0", "ocramius/proxy-manager": "~0.4|~1.0|~2.0" }, "require-dev": { - "symfony/config": "~2.8|~3.0" + "symfony/config": "~2.8|~3.0|~4.0.0" }, "autoload": { "psr-4": { "Symfony\\Bridge\\ProxyManager\\": "" }, diff --git a/src/Symfony/Bridge/Twig/composer.json b/src/Symfony/Bridge/Twig/composer.json index 9b431c04362e2..bbeeb4df45ee5 100644 --- a/src/Symfony/Bridge/Twig/composer.json +++ b/src/Symfony/Bridge/Twig/composer.json @@ -21,22 +21,22 @@ }, "require-dev": { "fig/link-util": "^1.0", - "symfony/asset": "~2.8|~3.0", - "symfony/finder": "~2.8|~3.0", - "symfony/form": "^3.2.7", - "symfony/http-kernel": "~3.2", + "symfony/asset": "~2.8|~3.0|~4.0.0", + "symfony/finder": "~2.8|~3.0|~4.0.0", + "symfony/form": "^3.2.7|~4.0.0", + "symfony/http-kernel": "~3.2|~4.0.0", "symfony/polyfill-intl-icu": "~1.0", - "symfony/routing": "~2.8|~3.0", - "symfony/templating": "~2.8|~3.0", - "symfony/translation": "~2.8|~3.0", - "symfony/yaml": "~2.8|~3.0", - "symfony/security": "~2.8|~3.0", + "symfony/routing": "~2.8|~3.0|~4.0.0", + "symfony/templating": "~2.8|~3.0|~4.0.0", + "symfony/translation": "~2.8|~3.0|~4.0.0", + "symfony/yaml": "~2.8|~3.0|~4.0.0", + "symfony/security": "~2.8|~3.0|~4.0.0", "symfony/security-acl": "~2.8|~3.0", - "symfony/stopwatch": "~2.8|~3.0", - "symfony/console": "~2.8|~3.0", - "symfony/var-dumper": "~2.8.10|~3.1.4|~3.2", - "symfony/expression-language": "~2.8|~3.0", - "symfony/web-link": "~3.3" + "symfony/stopwatch": "~2.8|~3.0|~4.0.0", + "symfony/console": "~2.8|~3.0|~4.0.0", + "symfony/var-dumper": "~2.8.10|~3.1.4|~3.2|~4.0.0", + "symfony/expression-language": "~2.8|~3.0|~4.0.0", + "symfony/web-link": "~3.3|~4.0.0" }, "suggest": { "symfony/finder": "", diff --git a/src/Symfony/Bundle/DebugBundle/composer.json b/src/Symfony/Bundle/DebugBundle/composer.json index f6a6e217a5ea6..e910d4d927e3c 100644 --- a/src/Symfony/Bundle/DebugBundle/composer.json +++ b/src/Symfony/Bundle/DebugBundle/composer.json @@ -17,14 +17,14 @@ ], "require": { "php": ">=5.5.9", - "symfony/http-kernel": "~2.8|~3.0", - "symfony/twig-bridge": "~2.8|~3.0", - "symfony/var-dumper": "~2.8|~3.0" + "symfony/http-kernel": "~2.8|~3.0|~4.0.0", + "symfony/twig-bridge": "~2.8|~3.0|~4.0.0", + "symfony/var-dumper": "~2.8|~3.0|~4.0.0" }, "require-dev": { - "symfony/config": "~3.3", - "symfony/dependency-injection": "~3.3", - "symfony/web-profiler-bundle": "~2.8|~3.0" + "symfony/config": "~3.3|~4.0.0", + "symfony/dependency-injection": "~3.3|~4.0.0", + "symfony/web-profiler-bundle": "~2.8|~3.0|~4.0.0" }, "suggest": { "symfony/config": "For service container configuration", diff --git a/src/Symfony/Bundle/FrameworkBundle/composer.json b/src/Symfony/Bundle/FrameworkBundle/composer.json index 63ad8d3246731..5355f61f31cc6 100644 --- a/src/Symfony/Bundle/FrameworkBundle/composer.json +++ b/src/Symfony/Bundle/FrameworkBundle/composer.json @@ -18,42 +18,42 @@ "require": { "php": ">=5.5.9", "ext-xml": "*", - "symfony/cache": "~3.3", + "symfony/cache": "~3.3|~4.0.0", "symfony/class-loader": "~3.2", - "symfony/dependency-injection": "~3.3-beta2", - "symfony/config": "~3.3", - "symfony/event-dispatcher": "~3.3", - "symfony/http-foundation": "~3.3", - "symfony/http-kernel": "~3.3", + "symfony/dependency-injection": "~3.3-beta2|~4.0.0", + "symfony/config": "~3.3|~4.0.0", + "symfony/event-dispatcher": "~3.3|~4.0.0", + "symfony/http-foundation": "~3.3|~4.0.0", + "symfony/http-kernel": "~3.3|~4.0.0", "symfony/polyfill-mbstring": "~1.0", - "symfony/filesystem": "~2.8|~3.0", - "symfony/finder": "~2.8|~3.0", - "symfony/routing": "~3.3", - "symfony/stopwatch": "~2.8|~3.0", + "symfony/filesystem": "~2.8|~3.0|~4.0.0", + "symfony/finder": "~2.8|~3.0|~4.0.0", + "symfony/routing": "~3.3|~4.0.0", + "symfony/stopwatch": "~2.8|~3.0|~4.0.0", "doctrine/cache": "~1.0" }, "require-dev": { "fig/link-util": "^1.0", - "symfony/asset": "~3.3", - "symfony/browser-kit": "~2.8|~3.0", - "symfony/console": "~3.3", - "symfony/css-selector": "~2.8|~3.0", - "symfony/dom-crawler": "~2.8|~3.0", + "symfony/asset": "~3.3|~4.0.0", + "symfony/browser-kit": "~2.8|~3.0|~4.0.0", + "symfony/console": "~3.3|~4.0.0", + "symfony/css-selector": "~2.8|~3.0|~4.0.0", + "symfony/dom-crawler": "~2.8|~3.0|~4.0.0", "symfony/polyfill-intl-icu": "~1.0", - "symfony/security": "~2.8|~3.0", - "symfony/form": "~3.3", - "symfony/expression-language": "~2.8|~3.0", - "symfony/process": "~2.8|~3.0", - "symfony/security-core": "~3.2", - "symfony/security-csrf": "~2.8|~3.0", - "symfony/serializer": "~3.3", - "symfony/translation": "~3.2", - "symfony/templating": "~2.8|~3.0", - "symfony/validator": "~3.3", - "symfony/workflow": "~3.3", - "symfony/yaml": "~3.2", - "symfony/property-info": "~3.3", - "symfony/web-link": "~3.3", + "symfony/security": "~2.8|~3.0|~4.0.0", + "symfony/form": "~3.3|~4.0.0", + "symfony/expression-language": "~2.8|~3.0|~4.0.0", + "symfony/process": "~2.8|~3.0|~4.0.0", + "symfony/security-core": "~3.2|~4.0.0", + "symfony/security-csrf": "~2.8|~3.0|~4.0.0", + "symfony/serializer": "~3.3|~4.0.0", + "symfony/translation": "~3.2|~4.0.0", + "symfony/templating": "~2.8|~3.0|~4.0.0", + "symfony/validator": "~3.3|~4.0.0", + "symfony/workflow": "~3.3|~4.0.0", + "symfony/yaml": "~3.2|~4.0.0", + "symfony/property-info": "~3.3|~4.0.0", + "symfony/web-link": "~3.3|~4.0.0", "doctrine/annotations": "~1.0", "phpdocumentor/reflection-docblock": "^3.0", "twig/twig": "~1.26|~2.0", diff --git a/src/Symfony/Bundle/SecurityBundle/composer.json b/src/Symfony/Bundle/SecurityBundle/composer.json index 84274f8167e99..275c7bbfce0d2 100644 --- a/src/Symfony/Bundle/SecurityBundle/composer.json +++ b/src/Symfony/Bundle/SecurityBundle/composer.json @@ -17,29 +17,29 @@ ], "require": { "php": ">=5.5.9", - "symfony/security": "~3.3", - "symfony/dependency-injection": "~3.3-beta2", - "symfony/http-kernel": "~3.3", + "symfony/security": "~3.3|~4.0.0", + "symfony/dependency-injection": "~3.3-beta2|~4.0.0", + "symfony/http-kernel": "~3.3|~4.0.0", "symfony/polyfill-php70": "~1.0" }, "require-dev": { - "symfony/asset": "~2.8|~3.0", - "symfony/browser-kit": "~2.8|~3.0", - "symfony/console": "~3.2", - "symfony/css-selector": "~2.8|~3.0", - "symfony/dom-crawler": "~2.8|~3.0", - "symfony/form": "^2.8.18|^3.2.5", - "symfony/framework-bundle": "^3.2.8", - "symfony/http-foundation": "~2.8|~3.0", + "symfony/asset": "~2.8|~3.0|~4.0.0", + "symfony/browser-kit": "~2.8|~3.0|~4.0.0", + "symfony/console": "~3.2|~4.0.0", + "symfony/css-selector": "~2.8|~3.0|~4.0.0", + "symfony/dom-crawler": "~2.8|~3.0|~4.0.0", + "symfony/form": "^2.8.18|^3.2.5|~4.0.0", + "symfony/framework-bundle": "^3.2.8|~4.0.0", + "symfony/http-foundation": "~2.8|~3.0|~4.0.0", "symfony/security-acl": "~2.8|~3.0", - "symfony/translation": "~2.8|~3.0", - "symfony/twig-bundle": "~2.8|~3.0", - "symfony/twig-bridge": "~2.8|~3.0", - "symfony/process": "~2.8|~3.0", - "symfony/validator": "^3.2.5", - "symfony/var-dumper": "~3.3", - "symfony/yaml": "~2.8|~3.0", - "symfony/expression-language": "~2.8|~3.0", + "symfony/translation": "~2.8|~3.0|~4.0.0", + "symfony/twig-bundle": "~2.8|~3.0|~4.0.0", + "symfony/twig-bridge": "~2.8|~3.0|~4.0.0", + "symfony/process": "~2.8|~3.0|~4.0.0", + "symfony/validator": "^3.2.5|~4.0.0", + "symfony/var-dumper": "~3.3|~4.0.0", + "symfony/yaml": "~2.8|~3.0|~4.0.0", + "symfony/expression-language": "~2.8|~3.0|~4.0.0", "doctrine/doctrine-bundle": "~1.4", "twig/twig": "~1.28|~2.0" }, diff --git a/src/Symfony/Bundle/TwigBundle/composer.json b/src/Symfony/Bundle/TwigBundle/composer.json index 98d93bb4d79b0..ece1c9160212b 100644 --- a/src/Symfony/Bundle/TwigBundle/composer.json +++ b/src/Symfony/Bundle/TwigBundle/composer.json @@ -24,17 +24,17 @@ "twig/twig": "^1.32|^2.2" }, "require-dev": { - "symfony/asset": "~2.8|~3.0", - "symfony/stopwatch": "~2.8|~3.0", - "symfony/dependency-injection": "~3.3", - "symfony/expression-language": "~2.8|~3.0", - "symfony/finder": "~2.8|~3.0", - "symfony/form": "~2.8|~3.0", - "symfony/routing": "~2.8|~3.0", - "symfony/templating": "~2.8|~3.0", - "symfony/yaml": "~2.8|~3.0", - "symfony/framework-bundle": "^3.2.8", - "symfony/web-link": "~3.3", + "symfony/asset": "~2.8|~3.0|~4.0.0", + "symfony/stopwatch": "~2.8|~3.0|~4.0.0", + "symfony/dependency-injection": "~3.3|~4.0.0", + "symfony/expression-language": "~2.8|~3.0|~4.0.0", + "symfony/finder": "~2.8|~3.0|~4.0.0", + "symfony/form": "~2.8|~3.0|~4.0.0", + "symfony/routing": "~2.8|~3.0|~4.0.0", + "symfony/templating": "~2.8|~3.0|~4.0.0", + "symfony/yaml": "~2.8|~3.0|~4.0.0", + "symfony/framework-bundle": "^3.2.8|~4.0.0", + "symfony/web-link": "~3.3|~4.0.0", "doctrine/annotations": "~1.0" }, "conflict": { diff --git a/src/Symfony/Bundle/WebProfilerBundle/composer.json b/src/Symfony/Bundle/WebProfilerBundle/composer.json index 151d5d2eee5ae..e1c148baf5912 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/composer.json +++ b/src/Symfony/Bundle/WebProfilerBundle/composer.json @@ -17,18 +17,18 @@ ], "require": { "php": ">=5.5.9", - "symfony/http-kernel": "~3.2", + "symfony/http-kernel": "~3.2|~4.0.0", "symfony/polyfill-php70": "~1.0", - "symfony/routing": "~2.8|~3.0", - "symfony/twig-bridge": "~2.8|~3.0", + "symfony/routing": "~2.8|~3.0|~4.0.0", + "symfony/twig-bridge": "~2.8|~3.0|~4.0.0", "twig/twig": "~1.28|~2.0", - "symfony/var-dumper": "~3.3" + "symfony/var-dumper": "~3.3|~4.0.0" }, "require-dev": { - "symfony/config": "~2.8|~3.0", - "symfony/console": "~2.8|~3.0", - "symfony/dependency-injection": "~3.3", - "symfony/stopwatch": "~2.8|~3.0" + "symfony/config": "~2.8|~3.0|~4.0.0", + "symfony/console": "~2.8|~3.0|~4.0.0", + "symfony/dependency-injection": "~3.3|~4.0.0", + "symfony/stopwatch": "~2.8|~3.0|~4.0.0" }, "conflict": { "symfony/dependency-injection": "<3.3", diff --git a/src/Symfony/Bundle/WebServerBundle/composer.json b/src/Symfony/Bundle/WebServerBundle/composer.json index 95e4968da69f5..cf6222295c8a0 100644 --- a/src/Symfony/Bundle/WebServerBundle/composer.json +++ b/src/Symfony/Bundle/WebServerBundle/composer.json @@ -17,9 +17,9 @@ ], "require": { "php": ">=5.5.9", - "symfony/console": "~2.8.8|~3.0.8|~3.1.2|~3.2", - "symfony/http-kernel": "~2.8|~3.0", - "symfony/process": "~2.8|~3.0" + "symfony/console": "~2.8.8|~3.0.8|~3.1.2|~3.2|~4.0.0", + "symfony/http-kernel": "~2.8|~3.0|~4.0.0", + "symfony/process": "~2.8|~3.0|~4.0.0" }, "autoload": { "psr-4": { "Symfony\\Bundle\\WebServerBundle\\": "" }, diff --git a/src/Symfony/Component/Asset/composer.json b/src/Symfony/Component/Asset/composer.json index 01e0031216229..ffdb80b0d45d3 100644 --- a/src/Symfony/Component/Asset/composer.json +++ b/src/Symfony/Component/Asset/composer.json @@ -22,8 +22,8 @@ "symfony/http-foundation": "" }, "require-dev": { - "symfony/http-foundation": "~2.8|~3.0", - "symfony/http-kernel": "~2.8|~3.0" + "symfony/http-foundation": "~2.8|~3.0|~4.0.0", + "symfony/http-kernel": "~2.8|~3.0|~4.0.0" }, "autoload": { "psr-4": { "Symfony\\Component\\Asset\\": "" }, diff --git a/src/Symfony/Component/BrowserKit/composer.json b/src/Symfony/Component/BrowserKit/composer.json index e6e07f1a3bff6..6a78ee846b276 100644 --- a/src/Symfony/Component/BrowserKit/composer.json +++ b/src/Symfony/Component/BrowserKit/composer.json @@ -17,11 +17,11 @@ ], "require": { "php": ">=5.5.9", - "symfony/dom-crawler": "~2.8|~3.0" + "symfony/dom-crawler": "~2.8|~3.0|~4.0.0" }, "require-dev": { - "symfony/process": "~2.8|~3.0", - "symfony/css-selector": "~2.8|~3.0" + "symfony/process": "~2.8|~3.0|~4.0.0", + "symfony/css-selector": "~2.8|~3.0|~4.0.0" }, "suggest": { "symfony/process": "" diff --git a/src/Symfony/Component/ClassLoader/composer.json b/src/Symfony/Component/ClassLoader/composer.json index ebed7026fcade..690032cbccc9b 100644 --- a/src/Symfony/Component/ClassLoader/composer.json +++ b/src/Symfony/Component/ClassLoader/composer.json @@ -20,7 +20,7 @@ "php": ">=5.5.9" }, "require-dev": { - "symfony/finder": "~2.8|~3.0", + "symfony/finder": "~2.8|~3.0|~4.0.0", "symfony/polyfill-apcu": "~1.1" }, "suggest": { diff --git a/src/Symfony/Component/Config/composer.json b/src/Symfony/Component/Config/composer.json index 407bc1eadbd00..5ba594cb34afc 100644 --- a/src/Symfony/Component/Config/composer.json +++ b/src/Symfony/Component/Config/composer.json @@ -17,11 +17,11 @@ ], "require": { "php": ">=5.5.9", - "symfony/filesystem": "~2.8|~3.0" + "symfony/filesystem": "~2.8|~3.0|~4.0.0" }, "require-dev": { - "symfony/yaml": "~3.0", - "symfony/dependency-injection": "~3.3" + "symfony/yaml": "~3.0|~4.0.0", + "symfony/dependency-injection": "~3.3|~4.0.0" }, "conflict": { "symfony/dependency-injection": "<3.3" diff --git a/src/Symfony/Component/Console/composer.json b/src/Symfony/Component/Console/composer.json index 9849b7b54ac4e..97cf6ae90b015 100644 --- a/src/Symfony/Component/Console/composer.json +++ b/src/Symfony/Component/Console/composer.json @@ -18,14 +18,14 @@ "require": { "php": ">=5.5.9", "symfony/polyfill-mbstring": "~1.0", - "symfony/debug": "~2.8|~3.0" + "symfony/debug": "~2.8|~3.0|~4.0.0" }, "require-dev": { - "symfony/http-kernel": "~2.8|~3.0", - "symfony/event-dispatcher": "~2.8|~3.0", - "symfony/dependency-injection": "~3.3", - "symfony/filesystem": "~2.8|~3.0", - "symfony/process": "~2.8|~3.0", + "symfony/http-kernel": "~2.8|~3.0|~4.0.0", + "symfony/event-dispatcher": "~2.8|~3.0|~4.0.0", + "symfony/dependency-injection": "~3.3|~4.0.0", + "symfony/filesystem": "~2.8|~3.0|~4.0.0", + "symfony/process": "~2.8|~3.0|~4.0.0", "psr/log": "~1.0" }, "suggest": { diff --git a/src/Symfony/Component/Debug/composer.json b/src/Symfony/Component/Debug/composer.json index a9e58086d67d9..3fb492be41821 100644 --- a/src/Symfony/Component/Debug/composer.json +++ b/src/Symfony/Component/Debug/composer.json @@ -23,7 +23,7 @@ "symfony/http-kernel": ">=2.3,<2.3.24|~2.4.0|>=2.5,<2.5.9|>=2.6,<2.6.2" }, "require-dev": { - "symfony/http-kernel": "~2.8|~3.0" + "symfony/http-kernel": "~2.8|~3.0|~4.0.0" }, "autoload": { "psr-4": { "Symfony\\Component\\Debug\\": "" }, diff --git a/src/Symfony/Component/DependencyInjection/composer.json b/src/Symfony/Component/DependencyInjection/composer.json index 7269eeb65c7ca..a682bfd007015 100644 --- a/src/Symfony/Component/DependencyInjection/composer.json +++ b/src/Symfony/Component/DependencyInjection/composer.json @@ -20,9 +20,9 @@ "psr/container": "^1.0" }, "require-dev": { - "symfony/yaml": "~3.3", - "symfony/config": "~3.3", - "symfony/expression-language": "~2.8|~3.0" + "symfony/yaml": "~3.3|~4.0.0", + "symfony/config": "~3.3|~4.0.0", + "symfony/expression-language": "~2.8|~3.0|~4.0.0" }, "suggest": { "symfony/yaml": "", diff --git a/src/Symfony/Component/DomCrawler/composer.json b/src/Symfony/Component/DomCrawler/composer.json index bad9b5a7633e7..dce2585d70506 100644 --- a/src/Symfony/Component/DomCrawler/composer.json +++ b/src/Symfony/Component/DomCrawler/composer.json @@ -20,7 +20,7 @@ "symfony/polyfill-mbstring": "~1.0" }, "require-dev": { - "symfony/css-selector": "~2.8|~3.0" + "symfony/css-selector": "~2.8|~3.0|~4.0.0" }, "suggest": { "symfony/css-selector": "" diff --git a/src/Symfony/Component/Dotenv/composer.json b/src/Symfony/Component/Dotenv/composer.json index 99998756b7ecb..48210c7bc3bca 100644 --- a/src/Symfony/Component/Dotenv/composer.json +++ b/src/Symfony/Component/Dotenv/composer.json @@ -19,7 +19,7 @@ "php": ">=5.5.9" }, "require-dev": { - "symfony/process": "^3.2" + "symfony/process": "~3.2|~4.0.0" }, "autoload": { "psr-4": { "Symfony\\Component\\Dotenv\\": "" }, diff --git a/src/Symfony/Component/EventDispatcher/composer.json b/src/Symfony/Component/EventDispatcher/composer.json index 3c56010c0dbd5..c9fb559fb6ec8 100644 --- a/src/Symfony/Component/EventDispatcher/composer.json +++ b/src/Symfony/Component/EventDispatcher/composer.json @@ -19,10 +19,10 @@ "php": ">=5.5.9" }, "require-dev": { - "symfony/dependency-injection": "~3.3", - "symfony/expression-language": "~2.8|~3.0", - "symfony/config": "~2.8|~3.0", - "symfony/stopwatch": "~2.8|~3.0", + "symfony/dependency-injection": "~3.3|~4.0.0", + "symfony/expression-language": "~2.8|~3.0|~4.0.0", + "symfony/config": "~2.8|~3.0|~4.0.0", + "symfony/stopwatch": "~2.8|~3.0|~4.0.0", "psr/log": "~1.0" }, "conflict": { diff --git a/src/Symfony/Component/ExpressionLanguage/composer.json b/src/Symfony/Component/ExpressionLanguage/composer.json index e0298e4c749c3..ffa6c0bc21212 100644 --- a/src/Symfony/Component/ExpressionLanguage/composer.json +++ b/src/Symfony/Component/ExpressionLanguage/composer.json @@ -17,7 +17,7 @@ ], "require": { "php": ">=5.5.9", - "symfony/cache": "~3.1" + "symfony/cache": "~3.1|~4.0.0" }, "autoload": { "psr-4": { "Symfony\\Component\\ExpressionLanguage\\": "" }, diff --git a/src/Symfony/Component/Form/composer.json b/src/Symfony/Component/Form/composer.json index 4bd2b395ddbfe..edd32cc9ed85a 100644 --- a/src/Symfony/Component/Form/composer.json +++ b/src/Symfony/Component/Form/composer.json @@ -17,22 +17,22 @@ ], "require": { "php": ">=5.5.9", - "symfony/event-dispatcher": "~2.8|~3.0", - "symfony/intl": "^2.8.18|^3.2.5", - "symfony/options-resolver": "~2.8|~3.0", + "symfony/event-dispatcher": "~2.8|~3.0|~4.0.0", + "symfony/intl": "^2.8.18|^3.2.5|~4.0.0", + "symfony/options-resolver": "~2.8|~3.0|~4.0.0", "symfony/polyfill-mbstring": "~1.0", - "symfony/property-access": "~2.8|~3.0" + "symfony/property-access": "~2.8|~3.0|~4.0.0" }, "require-dev": { "doctrine/collections": "~1.0", - "symfony/validator": "^2.8.18|^3.2.5", - "symfony/dependency-injection": "~3.3", - "symfony/config": "~2.7|~3.0", - "symfony/http-foundation": "~2.8|~3.0", - "symfony/http-kernel": "~2.8|~3.0", - "symfony/security-csrf": "~2.8|~3.0", - "symfony/translation": "~2.8|~3.0", - "symfony/var-dumper": "~3.3" + "symfony/validator": "^2.8.18|^3.2.5|~4.0.0", + "symfony/dependency-injection": "~3.3|~4.0.0", + "symfony/config": "~2.7|~3.0|~4.0.0", + "symfony/http-foundation": "~2.8|~3.0|~4.0.0", + "symfony/http-kernel": "~2.8|~3.0|~4.0.0", + "symfony/security-csrf": "~2.8|~3.0|~4.0.0", + "symfony/translation": "~2.8|~3.0|~4.0.0", + "symfony/var-dumper": "~3.3|~4.0.0" }, "conflict": { "phpunit/phpunit": "<4.8.35|<5.4.3,>=5.0", diff --git a/src/Symfony/Component/HttpFoundation/composer.json b/src/Symfony/Component/HttpFoundation/composer.json index adf85e0fe5245..7e0994993fe3c 100644 --- a/src/Symfony/Component/HttpFoundation/composer.json +++ b/src/Symfony/Component/HttpFoundation/composer.json @@ -20,7 +20,7 @@ "symfony/polyfill-mbstring": "~1.1" }, "require-dev": { - "symfony/expression-language": "~2.8|~3.0" + "symfony/expression-language": "~2.8|~3.0|~4.0.0" }, "autoload": { "psr-4": { "Symfony\\Component\\HttpFoundation\\": "" }, diff --git a/src/Symfony/Component/HttpKernel/composer.json b/src/Symfony/Component/HttpKernel/composer.json index c17a00950c638..fd5938b3b361f 100644 --- a/src/Symfony/Component/HttpKernel/composer.json +++ b/src/Symfony/Component/HttpKernel/composer.json @@ -17,27 +17,27 @@ ], "require": { "php": ">=5.5.9", - "symfony/event-dispatcher": "~2.8|~3.0", - "symfony/http-foundation": "~3.3", - "symfony/debug": "~2.8|~3.0", + "symfony/event-dispatcher": "~2.8|~3.0|~4.0.0", + "symfony/http-foundation": "~3.3|~4.0.0", + "symfony/debug": "~2.8|~3.0|~4.0.0", "psr/log": "~1.0" }, "require-dev": { - "symfony/browser-kit": "~2.8|~3.0", + "symfony/browser-kit": "~2.8|~3.0|~4.0.0", "symfony/class-loader": "~2.8|~3.0", - "symfony/config": "~2.8|~3.0", - "symfony/console": "~2.8|~3.0", - "symfony/css-selector": "~2.8|~3.0", - "symfony/dependency-injection": "~3.3", - "symfony/dom-crawler": "~2.8|~3.0", - "symfony/expression-language": "~2.8|~3.0", - "symfony/finder": "~2.8|~3.0", - "symfony/process": "~2.8|~3.0", - "symfony/routing": "~2.8|~3.0", - "symfony/stopwatch": "~2.8|~3.0", - "symfony/templating": "~2.8|~3.0", - "symfony/translation": "~2.8|~3.0", - "symfony/var-dumper": "~3.3", + "symfony/config": "~2.8|~3.0|~4.0.0", + "symfony/console": "~2.8|~3.0|~4.0.0", + "symfony/css-selector": "~2.8|~3.0|~4.0.0", + "symfony/dependency-injection": "~3.3|~4.0.0", + "symfony/dom-crawler": "~2.8|~3.0|~4.0.0", + "symfony/expression-language": "~2.8|~3.0|~4.0.0", + "symfony/finder": "~2.8|~3.0|~4.0.0", + "symfony/process": "~2.8|~3.0|~4.0.0", + "symfony/routing": "~2.8|~3.0|~4.0.0", + "symfony/stopwatch": "~2.8|~3.0|~4.0.0", + "symfony/templating": "~2.8|~3.0|~4.0.0", + "symfony/translation": "~2.8|~3.0|~4.0.0", + "symfony/var-dumper": "~3.3|~4.0.0", "psr/cache": "~1.0" }, "conflict": { @@ -47,7 +47,6 @@ }, "suggest": { "symfony/browser-kit": "", - "symfony/class-loader": "", "symfony/config": "", "symfony/console": "", "symfony/dependency-injection": "", diff --git a/src/Symfony/Component/Intl/composer.json b/src/Symfony/Component/Intl/composer.json index 87c34b5f54ee5..9bc914765c240 100644 --- a/src/Symfony/Component/Intl/composer.json +++ b/src/Symfony/Component/Intl/composer.json @@ -28,7 +28,7 @@ "symfony/polyfill-intl-icu": "~1.0" }, "require-dev": { - "symfony/filesystem": "~2.8|~3.0" + "symfony/filesystem": "~2.8|~3.0|~4.0.0" }, "suggest": { "ext-intl": "to use the component with locales other than \"en\"" diff --git a/src/Symfony/Component/Ldap/composer.json b/src/Symfony/Component/Ldap/composer.json index dbb5fbdd35af7..886cb502a0dd6 100644 --- a/src/Symfony/Component/Ldap/composer.json +++ b/src/Symfony/Component/Ldap/composer.json @@ -18,7 +18,7 @@ "require": { "php": ">=5.5.9", "symfony/polyfill-php56": "~1.0", - "symfony/options-resolver": "~2.8|~3.0", + "symfony/options-resolver": "~2.8|~3.0|~4.0.0", "ext-ldap": "*" }, "autoload": { diff --git a/src/Symfony/Component/PropertyAccess/composer.json b/src/Symfony/Component/PropertyAccess/composer.json index 2d0347cbcea84..b2dbedb1af9ac 100644 --- a/src/Symfony/Component/PropertyAccess/composer.json +++ b/src/Symfony/Component/PropertyAccess/composer.json @@ -18,10 +18,10 @@ "require": { "php": ">=5.5.9", "symfony/polyfill-php70": "~1.0", - "symfony/inflector": "~3.1" + "symfony/inflector": "~3.1|~4.0.0" }, "require-dev": { - "symfony/cache": "~3.1" + "symfony/cache": "~3.1|~4.0.0" }, "suggest": { "psr/cache-implementation": "To cache access methods." diff --git a/src/Symfony/Component/PropertyInfo/composer.json b/src/Symfony/Component/PropertyInfo/composer.json index 9f1956a3cd6b1..508b308daebf5 100644 --- a/src/Symfony/Component/PropertyInfo/composer.json +++ b/src/Symfony/Component/PropertyInfo/composer.json @@ -24,12 +24,12 @@ ], "require": { "php": ">=5.5.9", - "symfony/inflector": "~3.1" + "symfony/inflector": "~3.1|~4.0.0" }, "require-dev": { - "symfony/serializer": "~2.8|~3.0", - "symfony/cache": "~3.1", - "symfony/dependency-injection": "~3.3", + "symfony/serializer": "~2.8|~3.0|~4.0.0", + "symfony/cache": "~3.1|~4.0.0", + "symfony/dependency-injection": "~3.3|~4.0.0", "phpdocumentor/reflection-docblock": "^3.0", "doctrine/annotations": "~1.0" }, diff --git a/src/Symfony/Component/Routing/composer.json b/src/Symfony/Component/Routing/composer.json index e92517755581e..a9f192cd120a0 100644 --- a/src/Symfony/Component/Routing/composer.json +++ b/src/Symfony/Component/Routing/composer.json @@ -19,11 +19,11 @@ "php": ">=5.5.9" }, "require-dev": { - "symfony/config": "~2.8|~3.0", - "symfony/http-foundation": "~2.8|~3.0", - "symfony/yaml": "~3.3", - "symfony/expression-language": "~2.8|~3.0", - "symfony/dependency-injection": "~3.3", + "symfony/config": "~2.8|~3.0|~4.0.0", + "symfony/http-foundation": "~2.8|~3.0|~4.0.0", + "symfony/yaml": "~3.3|~4.0.0", + "symfony/expression-language": "~2.8|~3.0|~4.0.0", + "symfony/dependency-injection": "~3.3|~4.0.0", "doctrine/annotations": "~1.0", "doctrine/common": "~2.2", "psr/log": "~1.0" diff --git a/src/Symfony/Component/Security/Core/composer.json b/src/Symfony/Component/Security/Core/composer.json index 8db108b3642f7..81fa15414c953 100644 --- a/src/Symfony/Component/Security/Core/composer.json +++ b/src/Symfony/Component/Security/Core/composer.json @@ -20,11 +20,11 @@ "symfony/polyfill-php56": "~1.0" }, "require-dev": { - "symfony/event-dispatcher": "~2.8|~3.0", - "symfony/expression-language": "~2.8|~3.0", - "symfony/http-foundation": "~2.8|~3.0", - "symfony/ldap": "~3.1", - "symfony/validator": "^2.8.18|^3.2.5", + "symfony/event-dispatcher": "~2.8|~3.0|~4.0.0", + "symfony/expression-language": "~2.8|~3.0|~4.0.0", + "symfony/http-foundation": "~2.8|~3.0|~4.0.0", + "symfony/ldap": "~3.1|~4.0.0", + "symfony/validator": "^2.8.18|^3.2.5|~4.0.0", "psr/log": "~1.0" }, "suggest": { diff --git a/src/Symfony/Component/Security/Csrf/composer.json b/src/Symfony/Component/Security/Csrf/composer.json index d360eefba2b8f..f23354377dbd8 100644 --- a/src/Symfony/Component/Security/Csrf/composer.json +++ b/src/Symfony/Component/Security/Csrf/composer.json @@ -19,10 +19,10 @@ "php": ">=5.5.9", "symfony/polyfill-php56": "~1.0", "symfony/polyfill-php70": "~1.0", - "symfony/security-core": "~2.8|~3.0" + "symfony/security-core": "~2.8|~3.0|~4.0.0" }, "require-dev": { - "symfony/http-foundation": "~2.8|~3.0" + "symfony/http-foundation": "~2.8|~3.0|~4.0.0" }, "suggest": { "symfony/http-foundation": "For using the class SessionTokenStorage." diff --git a/src/Symfony/Component/Security/Guard/composer.json b/src/Symfony/Component/Security/Guard/composer.json index 9789ef59f8055..07d29f4df50f5 100644 --- a/src/Symfony/Component/Security/Guard/composer.json +++ b/src/Symfony/Component/Security/Guard/composer.json @@ -17,8 +17,8 @@ ], "require": { "php": ">=5.5.9", - "symfony/security-core": "~2.8|~3.0", - "symfony/security-http": "~3.1" + "symfony/security-core": "~2.8|~3.0|~4.0.0", + "symfony/security-http": "~3.1|~4.0.0" }, "require-dev": { "psr/log": "~1.0" diff --git a/src/Symfony/Component/Security/Http/composer.json b/src/Symfony/Component/Security/Http/composer.json index 61643f4642167..fc9aeec1d4d62 100644 --- a/src/Symfony/Component/Security/Http/composer.json +++ b/src/Symfony/Component/Security/Http/composer.json @@ -17,17 +17,17 @@ ], "require": { "php": ">=5.5.9", - "symfony/security-core": "~3.2", - "symfony/event-dispatcher": "~2.8|~3.0", - "symfony/http-foundation": "~2.8|~3.0", - "symfony/http-kernel": "~3.3", + "symfony/security-core": "~3.2|~4.0.0", + "symfony/event-dispatcher": "~2.8|~3.0|~4.0.0", + "symfony/http-foundation": "~2.8|~3.0|~4.0.0", + "symfony/http-kernel": "~3.3|~4.0.0", "symfony/polyfill-php56": "~1.0", "symfony/polyfill-php70": "~1.0", - "symfony/property-access": "~2.8|~3.0" + "symfony/property-access": "~2.8|~3.0|~4.0.0" }, "require-dev": { - "symfony/routing": "~2.8|~3.0", - "symfony/security-csrf": "~2.8|~3.0", + "symfony/routing": "~2.8|~3.0|~4.0.0", + "symfony/security-csrf": "~2.8|~3.0|~4.0.0", "psr/log": "~1.0" }, "suggest": { diff --git a/src/Symfony/Component/Security/composer.json b/src/Symfony/Component/Security/composer.json index 202ee891ea3c8..a0b91b459a584 100644 --- a/src/Symfony/Component/Security/composer.json +++ b/src/Symfony/Component/Security/composer.json @@ -17,13 +17,13 @@ ], "require": { "php": ">=5.5.9", - "symfony/event-dispatcher": "~2.8|~3.0", - "symfony/http-foundation": "~2.8|~3.0", - "symfony/http-kernel": "~3.3", + "symfony/event-dispatcher": "~2.8|~3.0|~4.0.0", + "symfony/http-foundation": "~2.8|~3.0|~4.0.0", + "symfony/http-kernel": "~3.3|~4.0.0", "symfony/polyfill-php56": "~1.0", "symfony/polyfill-php70": "~1.0", "symfony/polyfill-util": "~1.0", - "symfony/property-access": "~2.8|~3.0" + "symfony/property-access": "~2.8|~3.0|~4.0.0" }, "replace": { "symfony/security-core": "self.version", @@ -32,12 +32,12 @@ "symfony/security-http": "self.version" }, "require-dev": { - "symfony/finder": "~2.8|~3.0", + "symfony/finder": "~2.8|~3.0|~4.0.0", "symfony/polyfill-intl-icu": "~1.0", - "symfony/routing": "~2.8|~3.0", - "symfony/validator": "^2.8.18|^3.2.5", - "symfony/expression-language": "~2.8|~3.0", - "symfony/ldap": "~3.1", + "symfony/routing": "~2.8|~3.0|~4.0.0", + "symfony/validator": "^2.8.18|^3.2.5|~4.0.0", + "symfony/expression-language": "~2.8|~3.0|~4.0.0", + "symfony/ldap": "~3.1|~4.0.0", "psr/log": "~1.0" }, "suggest": { diff --git a/src/Symfony/Component/Serializer/composer.json b/src/Symfony/Component/Serializer/composer.json index 6ca2534f24109..fac63187e1344 100644 --- a/src/Symfony/Component/Serializer/composer.json +++ b/src/Symfony/Component/Serializer/composer.json @@ -19,14 +19,14 @@ "php": ">=5.5.9" }, "require-dev": { - "symfony/yaml": "~3.3", - "symfony/config": "~2.8|~3.0", - "symfony/property-access": "~2.8|~3.0", - "symfony/http-foundation": "~2.8|~3.0", - "symfony/cache": "~3.1", - "symfony/property-info": "~3.1", + "symfony/yaml": "~3.3|~4.0.0", + "symfony/config": "~2.8|~3.0|~4.0.0", + "symfony/property-access": "~2.8|~3.0|~4.0.0", + "symfony/http-foundation": "~2.8|~3.0|~4.0.0", + "symfony/cache": "~3.1|~4.0.0", + "symfony/property-info": "~3.1|~4.0.0", "doctrine/annotations": "~1.0", - "symfony/dependency-injection": "~3.2", + "symfony/dependency-injection": "~3.2|~4.0.0", "doctrine/cache": "~1.0", "phpdocumentor/reflection-docblock": "~3.0" }, diff --git a/src/Symfony/Component/Translation/composer.json b/src/Symfony/Component/Translation/composer.json index c6036de40efb9..966c41f23af39 100644 --- a/src/Symfony/Component/Translation/composer.json +++ b/src/Symfony/Component/Translation/composer.json @@ -20,9 +20,9 @@ "symfony/polyfill-mbstring": "~1.0" }, "require-dev": { - "symfony/config": "~2.8|~3.0", - "symfony/intl": "^2.8.18|^3.2.5", - "symfony/yaml": "~3.3", + "symfony/config": "~2.8|~3.0|~4.0.0", + "symfony/intl": "^2.8.18|^3.2.5|~4.0.0", + "symfony/yaml": "~3.3|~4.0.0", "psr/log": "~1.0" }, "conflict": { diff --git a/src/Symfony/Component/Validator/composer.json b/src/Symfony/Component/Validator/composer.json index 76fa66ef68108..ff44ba9126f60 100644 --- a/src/Symfony/Component/Validator/composer.json +++ b/src/Symfony/Component/Validator/composer.json @@ -18,16 +18,16 @@ "require": { "php": ">=5.5.9", "symfony/polyfill-mbstring": "~1.0", - "symfony/translation": "~2.8|~3.0" + "symfony/translation": "~2.8|~3.0|~4.0.0" }, "require-dev": { - "symfony/http-foundation": "~2.8|~3.0", - "symfony/intl": "^2.8.18|^3.2.5", - "symfony/yaml": "~3.3", - "symfony/config": "~2.8|~3.0", - "symfony/dependency-injection": "~3.3", - "symfony/expression-language": "~2.8|~3.0", - "symfony/cache": "~3.1", + "symfony/http-foundation": "~2.8|~3.0|~4.0.0", + "symfony/intl": "^2.8.18|^3.2.5|~4.0.0", + "symfony/yaml": "~3.3|~4.0.0", + "symfony/config": "~2.8|~3.0|~4.0.0", + "symfony/dependency-injection": "~3.3|~4.0.0", + "symfony/expression-language": "~2.8|~3.0|~4.0.0", + "symfony/cache": "~3.1|~4.0.0", "doctrine/annotations": "~1.0", "doctrine/cache": "~1.0", "egulias/email-validator": "^1.2.8|~2.0" diff --git a/src/Symfony/Component/WebLink/composer.json b/src/Symfony/Component/WebLink/composer.json index b5bb071ae095c..8db660c676e14 100644 --- a/src/Symfony/Component/WebLink/composer.json +++ b/src/Symfony/Component/WebLink/composer.json @@ -24,9 +24,9 @@ "symfony/http-kernel": "" }, "require-dev": { - "symfony/event-dispatcher": "^2.8|^3.0", - "symfony/http-foundation": "^2.8|^3.0", - "symfony/http-kernel": "^2.8|^3.0" + "symfony/event-dispatcher": "^2.8|^3.0|~4.0.0", + "symfony/http-foundation": "^2.8|^3.0|~4.0.0", + "symfony/http-kernel": "^2.8|^3.0|~4.0.0" }, "autoload": { "psr-4": { "Symfony\\Component\\WebLink\\": "" }, diff --git a/src/Symfony/Component/Workflow/composer.json b/src/Symfony/Component/Workflow/composer.json index 0bbfdf660e901..918bda4b99801 100644 --- a/src/Symfony/Component/Workflow/composer.json +++ b/src/Symfony/Component/Workflow/composer.json @@ -21,14 +21,14 @@ ], "require": { "php": ">=5.5.9", - "symfony/property-access": "~2.3|~3.0" + "symfony/property-access": "~2.3|~3.0|~4.0.0" }, "require-dev": { "psr/log": "~1.0", - "symfony/dependency-injection": "~2.8|~3.0", - "symfony/event-dispatcher": "~2.1|~3.0", - "symfony/expression-language": "~2.8|~3.0", - "symfony/security-core": "~2.8|~3.0" + "symfony/dependency-injection": "~2.8|~3.0|~4.0.0", + "symfony/event-dispatcher": "~2.1|~3.0|~4.0.0", + "symfony/expression-language": "~2.8|~3.0|~4.0.0", + "symfony/security-core": "~2.8|~3.0|~4.0.0" }, "autoload": { "psr-4": { "Symfony\\Component\\Workflow\\": "" } diff --git a/src/Symfony/Component/Yaml/composer.json b/src/Symfony/Component/Yaml/composer.json index d1272b3ce6139..8c218ac9ac35c 100644 --- a/src/Symfony/Component/Yaml/composer.json +++ b/src/Symfony/Component/Yaml/composer.json @@ -19,7 +19,7 @@ "php": ">=5.5.9" }, "require-dev": { - "symfony/console": "~2.8|~3.0" + "symfony/console": "~2.8|~3.0|~4.0.0" }, "suggest": { "symfony/console": "For validating YAML files using the lint command" From c85073370342aa6416b57177d980f6ab879cf894 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Wed, 17 May 2017 20:41:56 +0200 Subject: [PATCH 0009/1099] bumped minimum version to PHP 7.1 --- .travis.yml | 11 ++-- appveyor.yml | 4 -- composer.json | 2 +- src/Symfony/Bridge/Doctrine/composer.json | 24 +++---- src/Symfony/Bridge/Monolog/composer.json | 10 +-- src/Symfony/Bridge/ProxyManager/composer.json | 6 +- src/Symfony/Bridge/Twig/composer.json | 32 +++++----- src/Symfony/Bundle/DebugBundle/composer.json | 14 ++--- .../Bundle/FrameworkBundle/composer.json | 62 +++++++++---------- .../Bundle/SecurityBundle/composer.json | 43 +++++++------ src/Symfony/Bundle/TwigBundle/composer.json | 24 +++---- .../Bundle/WebProfilerBundle/composer.json | 21 +++---- .../Bundle/WebServerBundle/composer.json | 8 +-- src/Symfony/Component/Asset/composer.json | 6 +- .../Component/BrowserKit/composer.json | 8 +-- src/Symfony/Component/Cache/composer.json | 2 +- .../Component/ClassLoader/composer.json | 4 +- src/Symfony/Component/Config/composer.json | 8 +-- src/Symfony/Component/Console/composer.json | 14 ++--- .../Component/CssSelector/composer.json | 2 +- src/Symfony/Component/Debug/composer.json | 4 +- .../DependencyInjection/composer.json | 8 +-- .../Component/DomCrawler/composer.json | 4 +- src/Symfony/Component/Dotenv/composer.json | 4 +- .../Component/EventDispatcher/composer.json | 10 +-- .../ExpressionLanguage/composer.json | 4 +- .../Component/Filesystem/composer.json | 2 +- src/Symfony/Component/Finder/composer.json | 2 +- src/Symfony/Component/Form/composer.json | 26 ++++---- .../Component/HttpFoundation/composer.json | 4 +- src/Symfony/Component/HttpKernel/Kernel.php | 2 +- .../Component/HttpKernel/composer.json | 39 ++++++------ src/Symfony/Component/Inflector/composer.json | 2 +- src/Symfony/Component/Intl/composer.json | 4 +- src/Symfony/Component/Ldap/composer.json | 5 +- .../Component/OptionsResolver/composer.json | 2 +- src/Symfony/Component/Process/composer.json | 2 +- .../Component/PropertyAccess/composer.json | 7 +-- .../Component/PropertyInfo/composer.json | 10 +-- src/Symfony/Component/Routing/composer.json | 12 ++-- .../Component/Security/Core/composer.json | 13 ++-- .../Component/Security/Csrf/composer.json | 8 +-- .../Component/Security/Guard/composer.json | 6 +- .../Component/Security/Http/composer.json | 18 +++--- src/Symfony/Component/Security/composer.json | 23 +++---- .../Component/Serializer/composer.json | 16 ++--- src/Symfony/Component/Stopwatch/composer.json | 2 +- .../Component/Templating/composer.json | 2 +- .../Component/Translation/composer.json | 8 +-- src/Symfony/Component/Validator/composer.json | 18 +++--- src/Symfony/Component/VarDumper/composer.json | 2 +- src/Symfony/Component/WebLink/composer.json | 8 +-- src/Symfony/Component/Workflow/composer.json | 12 ++-- src/Symfony/Component/Yaml/composer.json | 4 +- 54 files changed, 291 insertions(+), 307 deletions(-) diff --git a/.travis.yml b/.travis.yml index 6668279015c13..da776a33b035b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -14,19 +14,18 @@ addons: env: global: - - MIN_PHP=5.5.9 - - SYMFONY_PROCESS_PHP_TEST_BINARY=~/.phpenv/versions/5.6/bin/php + - MIN_PHP=7.1.0 + - SYMFONY_PROCESS_PHP_TEST_BINARY=~/.phpenv/versions/7.1/bin/php matrix: include: # Use the newer stack for HHVM as HHVM does not support Precise anymore since a long time and so Precise has an outdated version - - php: hhvm-3.18 + - php: hhvm-stable sudo: required dist: trusty group: edge - - php: 5.5 - - php: 5.6 - - php: 7.0 + - php: 7.1.0 + - php: 7.1 env: deps=high - php: 7.1 env: deps=low diff --git a/appveyor.yml b/appveyor.yml index f6563e730a32e..c37c9bad46b44 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -17,8 +17,6 @@ init: install: - mkdir c:\php && cd c:\php - appveyor DownloadFile https://raw.githubusercontent.com/symfony/binary-utils/master/cacert.pem - - appveyor DownloadFile https://github.com/symfony/binary-utils/releases/download/v0.1/php-5.5.9-nts-Win32-VC11-x86.zip - - 7z x php-5.5.9-nts-Win32-VC11-x86.zip -y >nul - appveyor DownloadFile https://github.com/symfony/binary-utils/releases/download/v0.1/php-7.1.3-Win32-VC14-x64.zip - cd ext - appveyor DownloadFile https://github.com/symfony/binary-utils/releases/download/v0.1/php_apcu-4.0.10-5.5-nts-vc11-x86.zip @@ -59,8 +57,6 @@ test_script: - cd c:\php && 7z x php-7.1.3-Win32-VC14-x64.zip -y >nul && copy /Y php.ini-min php.ini - cd c:\projects\symfony - php phpunit src\Symfony --exclude-group benchmark,intl-data || SET X=!errorlevel! - - cd c:\php && 7z x php-5.5.9-nts-Win32-VC11-x86.zip -y >nul && copy /Y php.ini-min php.ini - - cd c:\projects\symfony - SET SYMFONY_PHPUNIT_SKIPPED_TESTS=phpunit.skipped - php phpunit src\Symfony --exclude-group benchmark,intl-data || SET X=!errorlevel! - copy /Y c:\php\php.ini-max c:\php\php.ini diff --git a/composer.json b/composer.json index d6649b4be41ae..744868ec50a46 100644 --- a/composer.json +++ b/composer.json @@ -16,7 +16,7 @@ } ], "require": { - "php": ">=5.5.9", + "php": "^7.1.0", "doctrine/common": "~2.4", "fig/link-util": "^1.0", "twig/twig": "~1.32|~2.2", diff --git a/src/Symfony/Bridge/Doctrine/composer.json b/src/Symfony/Bridge/Doctrine/composer.json index b89cee2e9b2af..6c83d3fd58d49 100644 --- a/src/Symfony/Bridge/Doctrine/composer.json +++ b/src/Symfony/Bridge/Doctrine/composer.json @@ -16,22 +16,22 @@ } ], "require": { - "php": ">=5.5.9", + "php": "^7.1.3", "doctrine/common": "~2.4", "symfony/polyfill-mbstring": "~1.0" }, "require-dev": { - "symfony/stopwatch": "~2.8|~3.0|~4.0.0", - "symfony/dependency-injection": "~3.3|~4.0.0", - "symfony/form": "^3.2.5|~4.0.0", - "symfony/http-kernel": "~2.8|~3.0|~4.0.0", - "symfony/property-access": "~2.8|~3.0|~4.0.0", - "symfony/property-info": "~2.8|3.0|~4.0.0", - "symfony/proxy-manager-bridge": "~2.8|~3.0|~4.0.0", - "symfony/security": "~2.8|~3.0|~4.0.0", - "symfony/expression-language": "~2.8|~3.0|~4.0.0", - "symfony/validator": "^2.8.18|^3.2.5|~4.0.0", - "symfony/translation": "~2.8|~3.0|~4.0.0", + "symfony/stopwatch": "~2.8|~3.0|~4.0", + "symfony/dependency-injection": "~3.3|~4.0", + "symfony/form": "^3.2.5|~4.0", + "symfony/http-kernel": "~2.8|~3.0|~4.0", + "symfony/property-access": "~2.8|~3.0|~4.0", + "symfony/property-info": "~2.8|3.0|~4.0", + "symfony/proxy-manager-bridge": "~2.8|~3.0|~4.0", + "symfony/security": "~2.8|~3.0|~4.0", + "symfony/expression-language": "~2.8|~3.0|~4.0", + "symfony/validator": "^2.8.18|^3.2.5|~4.0", + "symfony/translation": "~2.8|~3.0|~4.0", "doctrine/data-fixtures": "1.0.*", "doctrine/dbal": "~2.4", "doctrine/orm": "^2.4.5" diff --git a/src/Symfony/Bridge/Monolog/composer.json b/src/Symfony/Bridge/Monolog/composer.json index a7f5f85923118..8633d0044f73f 100644 --- a/src/Symfony/Bridge/Monolog/composer.json +++ b/src/Symfony/Bridge/Monolog/composer.json @@ -16,14 +16,14 @@ } ], "require": { - "php": ">=5.5.9", + "php": "^7.1.3", "monolog/monolog": "~1.19", - "symfony/http-kernel": "~2.8|~3.0|~4.0.0" + "symfony/http-kernel": "~2.8|~3.0|~4.0" }, "require-dev": { - "symfony/console": "~2.8|~3.0|~4.0.0", - "symfony/event-dispatcher": "~2.8|~3.0|~4.0.0", - "symfony/var-dumper": "~3.3|~4.0.0" + "symfony/console": "~2.8|~3.0|~4.0", + "symfony/event-dispatcher": "~2.8|~3.0|~4.0", + "symfony/var-dumper": "~3.3|~4.0" }, "conflict": { "symfony/http-foundation": "<3.3" diff --git a/src/Symfony/Bridge/ProxyManager/composer.json b/src/Symfony/Bridge/ProxyManager/composer.json index 208a1d0669d9c..0980cadb74f09 100644 --- a/src/Symfony/Bridge/ProxyManager/composer.json +++ b/src/Symfony/Bridge/ProxyManager/composer.json @@ -16,12 +16,12 @@ } ], "require": { - "php": ">=5.5.9", - "symfony/dependency-injection": "~2.8|~3.0|~4.0.0", + "php": "^7.1.3", + "symfony/dependency-injection": "~2.8|~3.0|~4.0", "ocramius/proxy-manager": "~0.4|~1.0|~2.0" }, "require-dev": { - "symfony/config": "~2.8|~3.0|~4.0.0" + "symfony/config": "~2.8|~3.0|~4.0" }, "autoload": { "psr-4": { "Symfony\\Bridge\\ProxyManager\\": "" }, diff --git a/src/Symfony/Bridge/Twig/composer.json b/src/Symfony/Bridge/Twig/composer.json index d7f6af318ea0a..80ee256d2e9c6 100644 --- a/src/Symfony/Bridge/Twig/composer.json +++ b/src/Symfony/Bridge/Twig/composer.json @@ -16,27 +16,27 @@ } ], "require": { - "php": ">=5.5.9", + "php": "^7.1.3", "twig/twig": "~1.28|~2.0" }, "require-dev": { "fig/link-util": "^1.0", - "symfony/asset": "~2.8|~3.0|~4.0.0", - "symfony/finder": "~2.8|~3.0|~4.0.0", - "symfony/form": "^3.2.7|~4.0.0", - "symfony/http-kernel": "~3.2|~4.0.0", + "symfony/asset": "~2.8|~3.0|~4.0", + "symfony/finder": "~2.8|~3.0|~4.0", + "symfony/form": "^3.2.7|~4.0", + "symfony/http-kernel": "~3.2|~4.0", "symfony/polyfill-intl-icu": "~1.0", - "symfony/routing": "~2.8|~3.0|~4.0.0", - "symfony/templating": "~2.8|~3.0|~4.0.0", - "symfony/translation": "~2.8|~3.0|~4.0.0", - "symfony/yaml": "~2.8|~3.0|~4.0.0", - "symfony/security": "~2.8|~3.0|~4.0.0", - "symfony/security-acl": "~2.8|~3.0", - "symfony/stopwatch": "~2.8|~3.0|~4.0.0", - "symfony/console": "~2.8|~3.0|~4.0.0", - "symfony/var-dumper": "~2.8.10|~3.1.4|~3.2|~4.0.0", - "symfony/expression-language": "~2.8|~3.0|~4.0.0", - "symfony/web-link": "~3.3|~4.0.0" + "symfony/routing": "~2.8|~3.0|~4.0", + "symfony/templating": "~2.8|~3.0|~4.0", + "symfony/translation": "~2.8|~3.0|~4.0", + "symfony/yaml": "~2.8|~3.0|~4.0", + "symfony/security": "~2.8|~3.0|~4.0", + "symfony/security-acl": "~2.8|~3.0|~4.0", + "symfony/stopwatch": "~2.8|~3.0|~4.0", + "symfony/console": "~2.8|~3.0|~4.0", + "symfony/var-dumper": "~2.8.10|~3.1.4|~3.2|~4.0", + "symfony/expression-language": "~2.8|~3.0|~4.0", + "symfony/web-link": "~3.3|~4.0" }, "suggest": { "symfony/finder": "", diff --git a/src/Symfony/Bundle/DebugBundle/composer.json b/src/Symfony/Bundle/DebugBundle/composer.json index c0064733f76d8..f8444aec6533e 100644 --- a/src/Symfony/Bundle/DebugBundle/composer.json +++ b/src/Symfony/Bundle/DebugBundle/composer.json @@ -16,15 +16,15 @@ } ], "require": { - "php": ">=5.5.9", - "symfony/http-kernel": "~2.8|~3.0|~4.0.0", - "symfony/twig-bridge": "~2.8|~3.0|~4.0.0", - "symfony/var-dumper": "~2.8|~3.0|~4.0.0" + "php": "^7.1.3", + "symfony/http-kernel": "~2.8|~3.0|~4.0", + "symfony/twig-bridge": "~2.8|~3.0|~4.0", + "symfony/var-dumper": "~2.8|~3.0|~4.0" }, "require-dev": { - "symfony/config": "~3.3|~4.0.0", - "symfony/dependency-injection": "~3.3|~4.0.0", - "symfony/web-profiler-bundle": "~2.8|~3.0|~4.0.0" + "symfony/config": "~3.3|~4.0", + "symfony/dependency-injection": "~3.3|~4.0", + "symfony/web-profiler-bundle": "~2.8|~3.0|~4.0" }, "suggest": { "symfony/config": "For service container configuration", diff --git a/src/Symfony/Bundle/FrameworkBundle/composer.json b/src/Symfony/Bundle/FrameworkBundle/composer.json index e23aeb19cade8..1d43ec6a4da72 100644 --- a/src/Symfony/Bundle/FrameworkBundle/composer.json +++ b/src/Symfony/Bundle/FrameworkBundle/composer.json @@ -16,44 +16,44 @@ } ], "require": { - "php": ">=5.5.9", + "php": "^7.1.3", "ext-xml": "*", - "symfony/cache": "~3.3|~4.0.0", - "symfony/class-loader": "~3.2", - "symfony/dependency-injection": "~3.3-beta2|~4.0.0", - "symfony/config": "~3.3|~4.0.0", - "symfony/event-dispatcher": "~3.3|~4.0.0", - "symfony/http-foundation": "~3.3|~4.0.0", - "symfony/http-kernel": "~3.3|~4.0.0", + "symfony/cache": "~3.3|~4.0", + "symfony/class-loader": "~3.2|~4.0", + "symfony/dependency-injection": "~3.3-beta2|~4.0", + "symfony/config": "~3.3|~4.0", + "symfony/event-dispatcher": "~3.3|~4.0", + "symfony/http-foundation": "~3.3|~4.0", + "symfony/http-kernel": "~3.3|~4.0", "symfony/polyfill-mbstring": "~1.0", - "symfony/filesystem": "~2.8|~3.0|~4.0.0", - "symfony/finder": "~2.8|~3.0|~4.0.0", - "symfony/routing": "~3.3|~4.0.0", - "symfony/stopwatch": "~2.8|~3.0|~4.0.0", + "symfony/filesystem": "~2.8|~3.0|~4.0", + "symfony/finder": "~2.8|~3.0|~4.0", + "symfony/routing": "~3.3|~4.0", + "symfony/stopwatch": "~2.8|~3.0|~4.0", "doctrine/cache": "~1.0" }, "require-dev": { "fig/link-util": "^1.0", - "symfony/asset": "~3.3|~4.0.0", - "symfony/browser-kit": "~2.8|~3.0|~4.0.0", - "symfony/console": "~3.3|~4.0.0", - "symfony/css-selector": "~2.8|~3.0|~4.0.0", - "symfony/dom-crawler": "~2.8|~3.0|~4.0.0", + "symfony/asset": "~3.3|~4.0", + "symfony/browser-kit": "~2.8|~3.0|~4.0", + "symfony/console": "~3.3|~4.0", + "symfony/css-selector": "~2.8|~3.0|~4.0", + "symfony/dom-crawler": "~2.8|~3.0|~4.0", "symfony/polyfill-intl-icu": "~1.0", - "symfony/security": "~2.8|~3.0|~4.0.0", - "symfony/form": "~3.3|~4.0.0", - "symfony/expression-language": "~2.8|~3.0|~4.0.0", - "symfony/process": "~2.8|~3.0|~4.0.0", - "symfony/security-core": "~3.2|~4.0.0", - "symfony/security-csrf": "~2.8|~3.0|~4.0.0", - "symfony/serializer": "~3.3|~4.0.0", - "symfony/translation": "~3.2|~4.0.0", - "symfony/templating": "~2.8|~3.0|~4.0.0", - "symfony/validator": "~3.3|~4.0.0", - "symfony/workflow": "~3.3|~4.0.0", - "symfony/yaml": "~3.2|~4.0.0", - "symfony/property-info": "~3.3|~4.0.0", - "symfony/web-link": "~3.3|~4.0.0", + "symfony/security": "~2.8|~3.0|~4.0", + "symfony/form": "~3.3|~4.0", + "symfony/expression-language": "~2.8|~3.0|~4.0", + "symfony/process": "~2.8|~3.0|~4.0", + "symfony/security-core": "~3.2|~4.0", + "symfony/security-csrf": "~2.8|~3.0|~4.0", + "symfony/serializer": "~3.3|~4.0", + "symfony/translation": "~3.2|~4.0", + "symfony/templating": "~2.8|~3.0|~4.0", + "symfony/validator": "~3.3|~4.0", + "symfony/workflow": "~3.3|~4.0", + "symfony/yaml": "~3.2|~4.0", + "symfony/property-info": "~3.3|~4.0", + "symfony/web-link": "~3.3|~4.0", "doctrine/annotations": "~1.0", "phpdocumentor/reflection-docblock": "^3.0", "twig/twig": "~1.26|~2.0", diff --git a/src/Symfony/Bundle/SecurityBundle/composer.json b/src/Symfony/Bundle/SecurityBundle/composer.json index 3611b1de6e476..61980a322972d 100644 --- a/src/Symfony/Bundle/SecurityBundle/composer.json +++ b/src/Symfony/Bundle/SecurityBundle/composer.json @@ -16,30 +16,29 @@ } ], "require": { - "php": ">=5.5.9", - "symfony/security": "~3.3|~4.0.0", - "symfony/dependency-injection": "~3.3-beta2|~4.0.0", - "symfony/http-kernel": "~3.3|~4.0.0", - "symfony/polyfill-php70": "~1.0" + "php": "^7.1.3", + "symfony/security": "~3.3|~4.0", + "symfony/dependency-injection": "~3.3-beta2|~4.0", + "symfony/http-kernel": "~3.3|~4.0" }, "require-dev": { - "symfony/asset": "~2.8|~3.0|~4.0.0", - "symfony/browser-kit": "~2.8|~3.0|~4.0.0", - "symfony/console": "~3.2|~4.0.0", - "symfony/css-selector": "~2.8|~3.0|~4.0.0", - "symfony/dom-crawler": "~2.8|~3.0|~4.0.0", - "symfony/form": "^2.8.18|^3.2.5|~4.0.0", - "symfony/framework-bundle": "^3.2.8|~4.0.0", - "symfony/http-foundation": "~2.8|~3.0|~4.0.0", - "symfony/security-acl": "~2.8|~3.0", - "symfony/translation": "~2.8|~3.0|~4.0.0", - "symfony/twig-bundle": "~2.8|~3.0|~4.0.0", - "symfony/twig-bridge": "~2.8|~3.0|~4.0.0", - "symfony/process": "~2.8|~3.0|~4.0.0", - "symfony/validator": "^3.2.5|~4.0.0", - "symfony/var-dumper": "~3.3|~4.0.0", - "symfony/yaml": "~2.8|~3.0|~4.0.0", - "symfony/expression-language": "~2.8|~3.0|~4.0.0", + "symfony/asset": "~2.8|~3.0|~4.0", + "symfony/browser-kit": "~2.8|~3.0|~4.0", + "symfony/console": "~3.2|~4.0", + "symfony/css-selector": "~2.8|~3.0|~4.0", + "symfony/dom-crawler": "~2.8|~3.0|~4.0", + "symfony/form": "^2.8.18|^3.2.5|~4.0", + "symfony/framework-bundle": "^3.2.8|~4.0", + "symfony/http-foundation": "~2.8|~3.0|~4.0", + "symfony/security-acl": "~2.8|~3.0|~4.0", + "symfony/translation": "~2.8|~3.0|~4.0", + "symfony/twig-bundle": "~2.8|~3.0|~4.0", + "symfony/twig-bridge": "~2.8|~3.0|~4.0", + "symfony/process": "~2.8|~3.0|~4.0", + "symfony/validator": "^3.2.5|~4.0", + "symfony/var-dumper": "~3.3|~4.0", + "symfony/yaml": "~2.8|~3.0|~4.0", + "symfony/expression-language": "~2.8|~3.0|~4.0", "doctrine/doctrine-bundle": "~1.4", "twig/twig": "~1.28|~2.0" }, diff --git a/src/Symfony/Bundle/TwigBundle/composer.json b/src/Symfony/Bundle/TwigBundle/composer.json index facbdfdb51e08..a951a24fec8ff 100644 --- a/src/Symfony/Bundle/TwigBundle/composer.json +++ b/src/Symfony/Bundle/TwigBundle/composer.json @@ -16,7 +16,7 @@ } ], "require": { - "php": ">=5.5.9", + "php": "^7.1.3", "symfony/config": "~3.2", "symfony/twig-bridge": "^3.3", "symfony/http-foundation": "~2.8|~3.0", @@ -24,17 +24,17 @@ "twig/twig": "^1.32|^2.2" }, "require-dev": { - "symfony/asset": "~2.8|~3.0|~4.0.0", - "symfony/stopwatch": "~2.8|~3.0|~4.0.0", - "symfony/dependency-injection": "~3.3|~4.0.0", - "symfony/expression-language": "~2.8|~3.0|~4.0.0", - "symfony/finder": "~2.8|~3.0|~4.0.0", - "symfony/form": "~2.8|~3.0|~4.0.0", - "symfony/routing": "~2.8|~3.0|~4.0.0", - "symfony/templating": "~2.8|~3.0|~4.0.0", - "symfony/yaml": "~2.8|~3.0|~4.0.0", - "symfony/framework-bundle": "^3.2.8|~4.0.0", - "symfony/web-link": "~3.3|~4.0.0", + "symfony/asset": "~2.8|~3.0|~4.0", + "symfony/stopwatch": "~2.8|~3.0|~4.0", + "symfony/dependency-injection": "~3.3|~4.0", + "symfony/expression-language": "~2.8|~3.0|~4.0", + "symfony/finder": "~2.8|~3.0|~4.0", + "symfony/form": "~2.8|~3.0|~4.0", + "symfony/routing": "~2.8|~3.0|~4.0", + "symfony/templating": "~2.8|~3.0|~4.0", + "symfony/yaml": "~2.8|~3.0|~4.0", + "symfony/framework-bundle": "^3.2.8|~4.0", + "symfony/web-link": "~3.3|~4.0", "doctrine/annotations": "~1.0" }, "conflict": { diff --git a/src/Symfony/Bundle/WebProfilerBundle/composer.json b/src/Symfony/Bundle/WebProfilerBundle/composer.json index 789b45dc310ef..219394c91d163 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/composer.json +++ b/src/Symfony/Bundle/WebProfilerBundle/composer.json @@ -16,19 +16,18 @@ } ], "require": { - "php": ">=5.5.9", - "symfony/http-kernel": "~3.2|~4.0.0", - "symfony/polyfill-php70": "~1.0", - "symfony/routing": "~2.8|~3.0|~4.0.0", - "symfony/twig-bridge": "~2.8|~3.0|~4.0.0", - "twig/twig": "~1.28|~2.0", - "symfony/var-dumper": "~3.3|~4.0.0" + "php": "^7.1.3", + "symfony/http-kernel": "~3.2|~4.0", + "symfony/routing": "~2.8|~3.0|~4.0", + "symfony/twig-bridge": "~2.8|~3.0|~4.0", + "symfony/var-dumper": "~3.3|~4.0", + "twig/twig": "~1.28|~2.0" }, "require-dev": { - "symfony/config": "~2.8|~3.0|~4.0.0", - "symfony/console": "~2.8|~3.0|~4.0.0", - "symfony/dependency-injection": "~3.3|~4.0.0", - "symfony/stopwatch": "~2.8|~3.0|~4.0.0" + "symfony/config": "~2.8|~3.0|~4.0", + "symfony/console": "~2.8|~3.0|~4.0", + "symfony/dependency-injection": "~3.3|~4.0", + "symfony/stopwatch": "~2.8|~3.0|~4.0" }, "conflict": { "symfony/dependency-injection": "<3.3", diff --git a/src/Symfony/Bundle/WebServerBundle/composer.json b/src/Symfony/Bundle/WebServerBundle/composer.json index b139a070a02e3..521b62c6ab547 100644 --- a/src/Symfony/Bundle/WebServerBundle/composer.json +++ b/src/Symfony/Bundle/WebServerBundle/composer.json @@ -16,10 +16,10 @@ } ], "require": { - "php": ">=5.5.9", - "symfony/console": "~2.8.8|~3.0.8|~3.1.2|~3.2|~4.0.0", - "symfony/http-kernel": "~2.8|~3.0|~4.0.0", - "symfony/process": "~2.8|~3.0|~4.0.0" + "php": "^7.1.3", + "symfony/console": "~2.8.8|~3.0.8|~3.1.2|~3.2|~4.0", + "symfony/http-kernel": "~2.8|~3.|~4.0", + "symfony/process": "~2.8|~3.0|~4.0" }, "autoload": { "psr-4": { "Symfony\\Bundle\\WebServerBundle\\": "" }, diff --git a/src/Symfony/Component/Asset/composer.json b/src/Symfony/Component/Asset/composer.json index adaaf36cd934b..0ab2db74a3a29 100644 --- a/src/Symfony/Component/Asset/composer.json +++ b/src/Symfony/Component/Asset/composer.json @@ -16,14 +16,14 @@ } ], "require": { - "php": ">=5.5.9" + "php": "^7.1.3" }, "suggest": { "symfony/http-foundation": "" }, "require-dev": { - "symfony/http-foundation": "~2.8|~3.0|~4.0.0", - "symfony/http-kernel": "~2.8|~3.0|~4.0.0" + "symfony/http-foundation": "~2.8|~3.0|~4.0", + "symfony/http-kernel": "~2.8|~3.0|~4.0" }, "autoload": { "psr-4": { "Symfony\\Component\\Asset\\": "" }, diff --git a/src/Symfony/Component/BrowserKit/composer.json b/src/Symfony/Component/BrowserKit/composer.json index 7bac2c117b2fa..79f644d5d9bdf 100644 --- a/src/Symfony/Component/BrowserKit/composer.json +++ b/src/Symfony/Component/BrowserKit/composer.json @@ -16,12 +16,12 @@ } ], "require": { - "php": ">=5.5.9", - "symfony/dom-crawler": "~2.8|~3.0|~4.0.0" + "php": "^7.1.3", + "symfony/dom-crawler": "~2.8|~3.0|~4.0" }, "require-dev": { - "symfony/process": "~2.8|~3.0|~4.0.0", - "symfony/css-selector": "~2.8|~3.0|~4.0.0" + "symfony/process": "~2.8|~3.0|~4.0", + "symfony/css-selector": "~2.8|~3.0|~4.0" }, "suggest": { "symfony/process": "" diff --git a/src/Symfony/Component/Cache/composer.json b/src/Symfony/Component/Cache/composer.json index 4c448dd3459f2..2efb85dd716f0 100644 --- a/src/Symfony/Component/Cache/composer.json +++ b/src/Symfony/Component/Cache/composer.json @@ -20,7 +20,7 @@ "psr/simple-cache-implementation": "1.0" }, "require": { - "php": ">=5.5.9", + "php": "^7.1.3", "psr/cache": "~1.0", "psr/log": "~1.0", "psr/simple-cache": "^1.0" diff --git a/src/Symfony/Component/ClassLoader/composer.json b/src/Symfony/Component/ClassLoader/composer.json index a3fa79c44211c..83be350a56638 100644 --- a/src/Symfony/Component/ClassLoader/composer.json +++ b/src/Symfony/Component/ClassLoader/composer.json @@ -17,10 +17,10 @@ ], "minimum-stability": "dev", "require": { - "php": ">=5.5.9" + "php": "^7.1.3" }, "require-dev": { - "symfony/finder": "~2.8|~3.0|~4.0.0", + "symfony/finder": "~2.8|~3.0|~4.0", "symfony/polyfill-apcu": "~1.1" }, "suggest": { diff --git a/src/Symfony/Component/Config/composer.json b/src/Symfony/Component/Config/composer.json index 2162bc19bee24..fda6a755ef377 100644 --- a/src/Symfony/Component/Config/composer.json +++ b/src/Symfony/Component/Config/composer.json @@ -16,12 +16,12 @@ } ], "require": { - "php": ">=5.5.9", - "symfony/filesystem": "~2.8|~3.0|~4.0.0" + "php": "^7.1.3", + "symfony/filesystem": "~2.8|~3.0|~4.0" }, "require-dev": { - "symfony/yaml": "~3.0|~4.0.0", - "symfony/dependency-injection": "~3.3|~4.0.0" + "symfony/yaml": "~3.0|~4.0", + "symfony/dependency-injection": "~3.3|~4.0" }, "conflict": { "symfony/dependency-injection": "<3.3" diff --git a/src/Symfony/Component/Console/composer.json b/src/Symfony/Component/Console/composer.json index 97bdeee548aaa..c7dca34b5fb8f 100644 --- a/src/Symfony/Component/Console/composer.json +++ b/src/Symfony/Component/Console/composer.json @@ -16,16 +16,16 @@ } ], "require": { - "php": ">=5.5.9", + "php": "^7.1.3", "symfony/polyfill-mbstring": "~1.0", - "symfony/debug": "~2.8|~3.0|~4.0.0" + "symfony/debug": "~2.8|~3.0|~4.0" }, "require-dev": { - "symfony/http-kernel": "~2.8|~3.0|~4.0.0", - "symfony/event-dispatcher": "~2.8|~3.0|~4.0.0", - "symfony/dependency-injection": "~3.3|~4.0.0", - "symfony/filesystem": "~2.8|~3.0|~4.0.0", - "symfony/process": "~2.8|~3.0|~4.0.0", + "symfony/http-kernel": "~2.8|~3.0|~4.0", + "symfony/event-dispatcher": "~2.8|~3.0|~4.0", + "symfony/dependency-injection": "~3.3|~4.0", + "symfony/filesystem": "~2.8|~3.0|~4.0", + "symfony/process": "~2.8|~3.0|~4.0", "psr/log": "~1.0" }, "suggest": { diff --git a/src/Symfony/Component/CssSelector/composer.json b/src/Symfony/Component/CssSelector/composer.json index 3b54f34d3c61c..f0b165170e659 100644 --- a/src/Symfony/Component/CssSelector/composer.json +++ b/src/Symfony/Component/CssSelector/composer.json @@ -20,7 +20,7 @@ } ], "require": { - "php": ">=5.5.9" + "php": "^7.1.3" }, "autoload": { "psr-4": { "Symfony\\Component\\CssSelector\\": "" }, diff --git a/src/Symfony/Component/Debug/composer.json b/src/Symfony/Component/Debug/composer.json index 0277bb5760621..ac7d6f8f2aa62 100644 --- a/src/Symfony/Component/Debug/composer.json +++ b/src/Symfony/Component/Debug/composer.json @@ -16,14 +16,14 @@ } ], "require": { - "php": ">=5.5.9", + "php": "^7.1.3", "psr/log": "~1.0" }, "conflict": { "symfony/http-kernel": ">=2.3,<2.3.24|~2.4.0|>=2.5,<2.5.9|>=2.6,<2.6.2" }, "require-dev": { - "symfony/http-kernel": "~2.8|~3.0|~4.0.0" + "symfony/http-kernel": "~2.8|~3.0|~4.0" }, "autoload": { "psr-4": { "Symfony\\Component\\Debug\\": "" }, diff --git a/src/Symfony/Component/DependencyInjection/composer.json b/src/Symfony/Component/DependencyInjection/composer.json index 95127f64abc55..cd07d2b6dcfc0 100644 --- a/src/Symfony/Component/DependencyInjection/composer.json +++ b/src/Symfony/Component/DependencyInjection/composer.json @@ -16,13 +16,13 @@ } ], "require": { - "php": ">=5.5.9", + "php": "^7.1.3", "psr/container": "^1.0" }, "require-dev": { - "symfony/yaml": "~3.3|~4.0.0", - "symfony/config": "~3.3|~4.0.0", - "symfony/expression-language": "~2.8|~3.0|~4.0.0" + "symfony/yaml": "~3.3|~4.0", + "symfony/config": "~3.3|~4.0", + "symfony/expression-language": "~2.8|~3.0|~4.0" }, "suggest": { "symfony/yaml": "", diff --git a/src/Symfony/Component/DomCrawler/composer.json b/src/Symfony/Component/DomCrawler/composer.json index cebe4e157be09..47ce2d2bed91e 100644 --- a/src/Symfony/Component/DomCrawler/composer.json +++ b/src/Symfony/Component/DomCrawler/composer.json @@ -16,11 +16,11 @@ } ], "require": { - "php": ">=5.5.9", + "php": "^7.1.3", "symfony/polyfill-mbstring": "~1.0" }, "require-dev": { - "symfony/css-selector": "~2.8|~3.0|~4.0.0" + "symfony/css-selector": "~2.8|~3.0|~4.0" }, "suggest": { "symfony/css-selector": "" diff --git a/src/Symfony/Component/Dotenv/composer.json b/src/Symfony/Component/Dotenv/composer.json index 4673837b315a2..729ef8afe834e 100644 --- a/src/Symfony/Component/Dotenv/composer.json +++ b/src/Symfony/Component/Dotenv/composer.json @@ -16,10 +16,10 @@ } ], "require": { - "php": ">=5.5.9" + "php": "^7.1.3" }, "require-dev": { - "symfony/process": "~3.2|~4.0.0" + "symfony/process": "~3.2|~4.0" }, "autoload": { "psr-4": { "Symfony\\Component\\Dotenv\\": "" }, diff --git a/src/Symfony/Component/EventDispatcher/composer.json b/src/Symfony/Component/EventDispatcher/composer.json index 10c08b7fe5d04..5b4a4db97c4b2 100644 --- a/src/Symfony/Component/EventDispatcher/composer.json +++ b/src/Symfony/Component/EventDispatcher/composer.json @@ -16,13 +16,13 @@ } ], "require": { - "php": ">=5.5.9" + "php": "^7.1.3" }, "require-dev": { - "symfony/dependency-injection": "~3.3|~4.0.0", - "symfony/expression-language": "~2.8|~3.0|~4.0.0", - "symfony/config": "~2.8|~3.0|~4.0.0", - "symfony/stopwatch": "~2.8|~3.0|~4.0.0", + "symfony/dependency-injection": "~3.3|~4.0", + "symfony/expression-language": "~2.8|~3.0|~4.0", + "symfony/config": "~2.8|~3.0|~4.0", + "symfony/stopwatch": "~2.8|~3.0|~4.0", "psr/log": "~1.0" }, "conflict": { diff --git a/src/Symfony/Component/ExpressionLanguage/composer.json b/src/Symfony/Component/ExpressionLanguage/composer.json index f62dad6fa44fa..3b8c0bcd44f4c 100644 --- a/src/Symfony/Component/ExpressionLanguage/composer.json +++ b/src/Symfony/Component/ExpressionLanguage/composer.json @@ -16,8 +16,8 @@ } ], "require": { - "php": ">=5.5.9", - "symfony/cache": "~3.1|~4.0.0" + "php": "^7.1.3", + "symfony/cache": "~3.1|~4.0" }, "autoload": { "psr-4": { "Symfony\\Component\\ExpressionLanguage\\": "" }, diff --git a/src/Symfony/Component/Filesystem/composer.json b/src/Symfony/Component/Filesystem/composer.json index 289d3e63913b4..bee959429f90c 100644 --- a/src/Symfony/Component/Filesystem/composer.json +++ b/src/Symfony/Component/Filesystem/composer.json @@ -16,7 +16,7 @@ } ], "require": { - "php": ">=5.5.9" + "php": "^7.1.3" }, "autoload": { "psr-4": { "Symfony\\Component\\Filesystem\\": "" }, diff --git a/src/Symfony/Component/Finder/composer.json b/src/Symfony/Component/Finder/composer.json index 410d92ba3db6b..906e1a6866426 100644 --- a/src/Symfony/Component/Finder/composer.json +++ b/src/Symfony/Component/Finder/composer.json @@ -16,7 +16,7 @@ } ], "require": { - "php": ">=5.5.9" + "php": "^7.1.3" }, "autoload": { "psr-4": { "Symfony\\Component\\Finder\\": "" }, diff --git a/src/Symfony/Component/Form/composer.json b/src/Symfony/Component/Form/composer.json index e5fa43030c566..d84d23a48cf25 100644 --- a/src/Symfony/Component/Form/composer.json +++ b/src/Symfony/Component/Form/composer.json @@ -16,23 +16,23 @@ } ], "require": { - "php": ">=5.5.9", - "symfony/event-dispatcher": "~2.8|~3.0|~4.0.0", - "symfony/intl": "^2.8.18|^3.2.5|~4.0.0", - "symfony/options-resolver": "~2.8|~3.0|~4.0.0", + "php": "^7.1.3", + "symfony/event-dispatcher": "~2.8|~3.0|~4.0", + "symfony/intl": "^2.8.18|^3.2.5|~4.0", + "symfony/options-resolver": "~2.8|~3.0|~4.0", "symfony/polyfill-mbstring": "~1.0", - "symfony/property-access": "~2.8|~3.0|~4.0.0" + "symfony/property-access": "~2.8|~3.0|~4.0" }, "require-dev": { "doctrine/collections": "~1.0", - "symfony/validator": "^2.8.18|^3.2.5|~4.0.0", - "symfony/dependency-injection": "~3.3|~4.0.0", - "symfony/config": "~2.7|~3.0|~4.0.0", - "symfony/http-foundation": "~2.8|~3.0|~4.0.0", - "symfony/http-kernel": "~2.8|~3.0|~4.0.0", - "symfony/security-csrf": "~2.8|~3.0|~4.0.0", - "symfony/translation": "~2.8|~3.0|~4.0.0", - "symfony/var-dumper": "~3.3|~4.0.0" + "symfony/validator": "^2.8.18|^3.2.5|~4.0", + "symfony/dependency-injection": "~3.3|~4.0", + "symfony/config": "~2.7|~3.0|~4.0", + "symfony/http-foundation": "~2.8|~3.0|~4.0", + "symfony/http-kernel": "~2.8|~3.0|~4.0", + "symfony/security-csrf": "~2.8|~3.0|~4.0", + "symfony/translation": "~2.8|~3.0|~4.0", + "symfony/var-dumper": "~3.3|~4.0" }, "conflict": { "phpunit/phpunit": "<4.8.35|<5.4.3,>=5.0", diff --git a/src/Symfony/Component/HttpFoundation/composer.json b/src/Symfony/Component/HttpFoundation/composer.json index fe66703fdd68c..4913aa85817a6 100644 --- a/src/Symfony/Component/HttpFoundation/composer.json +++ b/src/Symfony/Component/HttpFoundation/composer.json @@ -16,11 +16,11 @@ } ], "require": { - "php": ">=5.5.9", + "php": "^7.1.3", "symfony/polyfill-mbstring": "~1.1" }, "require-dev": { - "symfony/expression-language": "~2.8|~3.0|~4.0.0" + "symfony/expression-language": "~2.8|~3.0|~4.0" }, "autoload": { "psr-4": { "Symfony\\Component\\HttpFoundation\\": "" }, diff --git a/src/Symfony/Component/HttpKernel/Kernel.php b/src/Symfony/Component/HttpKernel/Kernel.php index 02fe035c0b29d..ae31a46fc985f 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -63,7 +63,7 @@ abstract class Kernel implements KernelInterface, TerminableInterface const VERSION = '4.0.0-DEV'; const VERSION_ID = 40000; - const MAJOR_VERSION = 4; + const MAJOR_VERSION = 0; const MINOR_VERSION = 0; const RELEASE_VERSION = 0; const EXTRA_VERSION = 'DEV'; diff --git a/src/Symfony/Component/HttpKernel/composer.json b/src/Symfony/Component/HttpKernel/composer.json index 53376a61db667..4a07946c9b7ea 100644 --- a/src/Symfony/Component/HttpKernel/composer.json +++ b/src/Symfony/Component/HttpKernel/composer.json @@ -16,28 +16,28 @@ } ], "require": { - "php": ">=5.5.9", - "symfony/event-dispatcher": "~2.8|~3.0|~4.0.0", - "symfony/http-foundation": "~3.3|~4.0.0", - "symfony/debug": "~2.8|~3.0|~4.0.0", + "php": "^7.1.3", + "symfony/event-dispatcher": "~2.8|~3.0|~4.0", + "symfony/http-foundation": "~3.3|~4.0", + "symfony/debug": "~2.8|~3.0|~4.0", "psr/log": "~1.0" }, "require-dev": { - "symfony/browser-kit": "~2.8|~3.0|~4.0.0", - "symfony/class-loader": "~2.8|~3.0", - "symfony/config": "~2.8|~3.0|~4.0.0", - "symfony/console": "~2.8|~3.0|~4.0.0", - "symfony/css-selector": "~2.8|~3.0|~4.0.0", - "symfony/dependency-injection": "~3.3|~4.0.0", - "symfony/dom-crawler": "~2.8|~3.0|~4.0.0", - "symfony/expression-language": "~2.8|~3.0|~4.0.0", - "symfony/finder": "~2.8|~3.0|~4.0.0", - "symfony/process": "~2.8|~3.0|~4.0.0", - "symfony/routing": "~2.8|~3.0|~4.0.0", - "symfony/stopwatch": "~2.8|~3.0|~4.0.0", - "symfony/templating": "~2.8|~3.0|~4.0.0", - "symfony/translation": "~2.8|~3.0|~4.0.0", - "symfony/var-dumper": "~3.3|~4.0.0", + "symfony/browser-kit": "~2.8|~3.0|~4.0", + "symfony/class-loader": "~2.8|~3.0|~4.0", + "symfony/config": "~2.8|~3.0|~4.0", + "symfony/console": "~2.8|~3.0|~4.0", + "symfony/css-selector": "~2.8|~3.0|~4.0", + "symfony/dependency-injection": "~3.3|~4.0", + "symfony/dom-crawler": "~2.8|~3.0|~4.0", + "symfony/expression-language": "~2.8|~3.0|~4.0", + "symfony/finder": "~2.8|~3.0|~4.0", + "symfony/process": "~2.8|~3.0|~4.0", + "symfony/routing": "~2.8|~3.0|~4.0", + "symfony/stopwatch": "~2.8|~3.0|~4.0", + "symfony/templating": "~2.8|~3.0|~4.0", + "symfony/translation": "~2.8|~3.0|~4.0", + "symfony/var-dumper": "~3.3|~4.0", "psr/cache": "~1.0" }, "conflict": { @@ -47,6 +47,7 @@ }, "suggest": { "symfony/browser-kit": "", + "symfony/class-loader": "", "symfony/config": "", "symfony/console": "", "symfony/dependency-injection": "", diff --git a/src/Symfony/Component/Inflector/composer.json b/src/Symfony/Component/Inflector/composer.json index 0f88a6c6295da..ebec32fadd30f 100644 --- a/src/Symfony/Component/Inflector/composer.json +++ b/src/Symfony/Component/Inflector/composer.json @@ -23,7 +23,7 @@ } ], "require": { - "php": ">=5.5.9" + "php": "^7.1.3" }, "autoload": { "psr-4": { "Symfony\\Component\\Inflector\\": "" }, diff --git a/src/Symfony/Component/Intl/composer.json b/src/Symfony/Component/Intl/composer.json index a1a1e93204552..7dabd6bf3bc2f 100644 --- a/src/Symfony/Component/Intl/composer.json +++ b/src/Symfony/Component/Intl/composer.json @@ -24,11 +24,11 @@ } ], "require": { - "php": ">=5.5.9", + "php": "^7.1.3", "symfony/polyfill-intl-icu": "~1.0" }, "require-dev": { - "symfony/filesystem": "~2.8|~3.0|~4.0.0" + "symfony/filesystem": "~2.8|~3.0|~4.0" }, "suggest": { "ext-intl": "to use the component with locales other than \"en\"" diff --git a/src/Symfony/Component/Ldap/composer.json b/src/Symfony/Component/Ldap/composer.json index 21d08167acc03..d0308feba9e58 100644 --- a/src/Symfony/Component/Ldap/composer.json +++ b/src/Symfony/Component/Ldap/composer.json @@ -16,9 +16,8 @@ } ], "require": { - "php": ">=5.5.9", - "symfony/polyfill-php56": "~1.0", - "symfony/options-resolver": "~2.8|~3.0|~4.0.0", + "php": "^7.1.3", + "symfony/options-resolver": "~2.8|~3.0|~4.0", "ext-ldap": "*" }, "autoload": { diff --git a/src/Symfony/Component/OptionsResolver/composer.json b/src/Symfony/Component/OptionsResolver/composer.json index 8f8ba964a2148..ec764e644fc2c 100644 --- a/src/Symfony/Component/OptionsResolver/composer.json +++ b/src/Symfony/Component/OptionsResolver/composer.json @@ -16,7 +16,7 @@ } ], "require": { - "php": ">=5.5.9" + "php": "^7.1.3" }, "autoload": { "psr-4": { "Symfony\\Component\\OptionsResolver\\": "" }, diff --git a/src/Symfony/Component/Process/composer.json b/src/Symfony/Component/Process/composer.json index df2bce0a1bed6..08e8b5a80dbfe 100644 --- a/src/Symfony/Component/Process/composer.json +++ b/src/Symfony/Component/Process/composer.json @@ -16,7 +16,7 @@ } ], "require": { - "php": ">=5.5.9" + "php": "^7.1.3" }, "autoload": { "psr-4": { "Symfony\\Component\\Process\\": "" }, diff --git a/src/Symfony/Component/PropertyAccess/composer.json b/src/Symfony/Component/PropertyAccess/composer.json index 01c3a8a0c9fe7..19b02bd730cd1 100644 --- a/src/Symfony/Component/PropertyAccess/composer.json +++ b/src/Symfony/Component/PropertyAccess/composer.json @@ -16,12 +16,11 @@ } ], "require": { - "php": ">=5.5.9", - "symfony/polyfill-php70": "~1.0", - "symfony/inflector": "~3.1|~4.0.0" + "php": "^7.1.3", + "symfony/inflector": "~3.1|~4.0" }, "require-dev": { - "symfony/cache": "~3.1|~4.0.0" + "symfony/cache": "~3.1|~4.0" }, "suggest": { "psr/cache-implementation": "To cache access methods." diff --git a/src/Symfony/Component/PropertyInfo/composer.json b/src/Symfony/Component/PropertyInfo/composer.json index 1d5cd2b830e33..8558b506a9d6a 100644 --- a/src/Symfony/Component/PropertyInfo/composer.json +++ b/src/Symfony/Component/PropertyInfo/composer.json @@ -23,13 +23,13 @@ } ], "require": { - "php": ">=5.5.9", - "symfony/inflector": "~3.1|~4.0.0" + "php": "^7.1.3", + "symfony/inflector": "~3.1|~4.0" }, "require-dev": { - "symfony/serializer": "~2.8|~3.0|~4.0.0", - "symfony/cache": "~3.1|~4.0.0", - "symfony/dependency-injection": "~3.3|~4.0.0", + "symfony/serializer": "~2.8|~3.0|~4.0", + "symfony/cache": "~3.1|~4.0", + "symfony/dependency-injection": "~3.3|~4.0", "phpdocumentor/reflection-docblock": "^3.0", "doctrine/annotations": "~1.0" }, diff --git a/src/Symfony/Component/Routing/composer.json b/src/Symfony/Component/Routing/composer.json index 33d4d711f0e89..c83761320eba3 100644 --- a/src/Symfony/Component/Routing/composer.json +++ b/src/Symfony/Component/Routing/composer.json @@ -16,14 +16,14 @@ } ], "require": { - "php": ">=5.5.9" + "php": "^7.1.3" }, "require-dev": { - "symfony/config": "~2.8|~3.0|~4.0.0", - "symfony/http-foundation": "~2.8|~3.0|~4.0.0", - "symfony/yaml": "~3.3|~4.0.0", - "symfony/expression-language": "~2.8|~3.0|~4.0.0", - "symfony/dependency-injection": "~3.3|~4.0.0", + "symfony/config": "~2.8|~3.0|~4.0", + "symfony/http-foundation": "~2.8|~3.0|~4.0", + "symfony/yaml": "~3.3|~4.0", + "symfony/expression-language": "~2.8|~3.0|~4.0", + "symfony/dependency-injection": "~3.3|~4.0", "doctrine/annotations": "~1.0", "doctrine/common": "~2.2", "psr/log": "~1.0" diff --git a/src/Symfony/Component/Security/Core/composer.json b/src/Symfony/Component/Security/Core/composer.json index c7271f9bd6feb..ad3fd1526bdd9 100644 --- a/src/Symfony/Component/Security/Core/composer.json +++ b/src/Symfony/Component/Security/Core/composer.json @@ -16,15 +16,14 @@ } ], "require": { - "php": ">=5.5.9", - "symfony/polyfill-php56": "~1.0" + "php": "^7.1.3" }, "require-dev": { - "symfony/event-dispatcher": "~2.8|~3.0|~4.0.0", - "symfony/expression-language": "~2.8|~3.0|~4.0.0", - "symfony/http-foundation": "~2.8|~3.0|~4.0.0", - "symfony/ldap": "~3.1|~4.0.0", - "symfony/validator": "^2.8.18|^3.2.5|~4.0.0", + "symfony/event-dispatcher": "~2.8|~3.0|~4.0", + "symfony/expression-language": "~2.8|~3.0|~4.0", + "symfony/http-foundation": "~2.8|~3.0|~4.0", + "symfony/ldap": "~3.1|~4.0", + "symfony/validator": "^2.8.18|^3.2.5|~4.0", "psr/log": "~1.0" }, "suggest": { diff --git a/src/Symfony/Component/Security/Csrf/composer.json b/src/Symfony/Component/Security/Csrf/composer.json index 87da31ffde31b..e1373f8eff21c 100644 --- a/src/Symfony/Component/Security/Csrf/composer.json +++ b/src/Symfony/Component/Security/Csrf/composer.json @@ -16,13 +16,11 @@ } ], "require": { - "php": ">=5.5.9", - "symfony/polyfill-php56": "~1.0", - "symfony/polyfill-php70": "~1.0", - "symfony/security-core": "~2.8|~3.0|~4.0.0" + "php": "^7.1.3", + "symfony/security-core": "~2.8|~3.0|~4.0" }, "require-dev": { - "symfony/http-foundation": "~2.8|~3.0|~4.0.0" + "symfony/http-foundation": "~2.8|~3.0|~4.0" }, "suggest": { "symfony/http-foundation": "For using the class SessionTokenStorage." diff --git a/src/Symfony/Component/Security/Guard/composer.json b/src/Symfony/Component/Security/Guard/composer.json index 85f622e1137a0..7d348a7db5940 100644 --- a/src/Symfony/Component/Security/Guard/composer.json +++ b/src/Symfony/Component/Security/Guard/composer.json @@ -16,9 +16,9 @@ } ], "require": { - "php": ">=5.5.9", - "symfony/security-core": "~2.8|~3.0|~4.0.0", - "symfony/security-http": "~3.1|~4.0.0" + "php": "^7.1.3", + "symfony/security-core": "~2.8|~3.0|~4.0", + "symfony/security-http": "~3.1|~4.0" }, "require-dev": { "psr/log": "~1.0" diff --git a/src/Symfony/Component/Security/Http/composer.json b/src/Symfony/Component/Security/Http/composer.json index 3171fb1980ca5..655ebfa0e174a 100644 --- a/src/Symfony/Component/Security/Http/composer.json +++ b/src/Symfony/Component/Security/Http/composer.json @@ -16,18 +16,16 @@ } ], "require": { - "php": ">=5.5.9", - "symfony/security-core": "~3.2|~4.0.0", - "symfony/event-dispatcher": "~2.8|~3.0|~4.0.0", - "symfony/http-foundation": "~2.8|~3.0|~4.0.0", - "symfony/http-kernel": "~3.3|~4.0.0", - "symfony/polyfill-php56": "~1.0", - "symfony/polyfill-php70": "~1.0", - "symfony/property-access": "~2.8|~3.0|~4.0.0" + "php": "^7.1.3", + "symfony/security-core": "~3.2|~4.0", + "symfony/event-dispatcher": "~2.8|~3.0|~4.0", + "symfony/http-foundation": "~2.8|~3.0|~4.0", + "symfony/http-kernel": "~3.3|~4.0", + "symfony/property-access": "~2.8|~3.0|~4.0" }, "require-dev": { - "symfony/routing": "~2.8|~3.0|~4.0.0", - "symfony/security-csrf": "~2.8|~3.0|~4.0.0", + "symfony/routing": "~2.8|~3.0|~4.0", + "symfony/security-csrf": "~2.8|~3.0|~4.0", "psr/log": "~1.0" }, "suggest": { diff --git a/src/Symfony/Component/Security/composer.json b/src/Symfony/Component/Security/composer.json index 9c1146f2acc4d..75ac0096f38d0 100644 --- a/src/Symfony/Component/Security/composer.json +++ b/src/Symfony/Component/Security/composer.json @@ -16,14 +16,11 @@ } ], "require": { - "php": ">=5.5.9", - "symfony/event-dispatcher": "~2.8|~3.0|~4.0.0", - "symfony/http-foundation": "~2.8|~3.0|~4.0.0", - "symfony/http-kernel": "~3.3|~4.0.0", - "symfony/polyfill-php56": "~1.0", - "symfony/polyfill-php70": "~1.0", - "symfony/polyfill-util": "~1.0", - "symfony/property-access": "~2.8|~3.0|~4.0.0" + "php": "^7.1.3", + "symfony/event-dispatcher": "~2.8|~3.0|~4.0", + "symfony/http-foundation": "~2.8|~3.0|~4.0", + "symfony/http-kernel": "~3.3|~4.0", + "symfony/property-access": "~2.8|~3.0|~4.0" }, "replace": { "symfony/security-core": "self.version", @@ -32,12 +29,12 @@ "symfony/security-http": "self.version" }, "require-dev": { - "symfony/finder": "~2.8|~3.0|~4.0.0", + "symfony/finder": "~2.8|~3.0|~4.0", "symfony/polyfill-intl-icu": "~1.0", - "symfony/routing": "~2.8|~3.0|~4.0.0", - "symfony/validator": "^2.8.18|^3.2.5|~4.0.0", - "symfony/expression-language": "~2.8|~3.0|~4.0.0", - "symfony/ldap": "~3.1|~4.0.0", + "symfony/routing": "~2.8|~3.0|~4.0", + "symfony/validator": "^2.8.18|^3.2.5|~4.0", + "symfony/expression-language": "~2.8|~3.0|~4.0", + "symfony/ldap": "~3.1|~4.0", "psr/log": "~1.0" }, "suggest": { diff --git a/src/Symfony/Component/Serializer/composer.json b/src/Symfony/Component/Serializer/composer.json index fe91bc70bc432..eeb67dce36c78 100644 --- a/src/Symfony/Component/Serializer/composer.json +++ b/src/Symfony/Component/Serializer/composer.json @@ -16,17 +16,17 @@ } ], "require": { - "php": ">=5.5.9" + "php": "^7.1.3" }, "require-dev": { - "symfony/yaml": "~3.3|~4.0.0", - "symfony/config": "~2.8|~3.0|~4.0.0", - "symfony/property-access": "~2.8|~3.0|~4.0.0", - "symfony/http-foundation": "~2.8|~3.0|~4.0.0", - "symfony/cache": "~3.1|~4.0.0", - "symfony/property-info": "~3.1|~4.0.0", + "symfony/yaml": "~3.3|~4.0", + "symfony/config": "~2.8|~3.0|~4.0", + "symfony/property-access": "~2.8|~3.0|~4.0", + "symfony/http-foundation": "~2.8|~3.0|~4.0", + "symfony/cache": "~3.1|~4.0", + "symfony/property-info": "~3.1|~4.0", "doctrine/annotations": "~1.0", - "symfony/dependency-injection": "~3.2|~4.0.0", + "symfony/dependency-injection": "~3.2|~4.0", "doctrine/cache": "~1.0", "phpdocumentor/reflection-docblock": "~3.0" }, diff --git a/src/Symfony/Component/Stopwatch/composer.json b/src/Symfony/Component/Stopwatch/composer.json index be5a2b16a9869..9f7f9675c45ec 100644 --- a/src/Symfony/Component/Stopwatch/composer.json +++ b/src/Symfony/Component/Stopwatch/composer.json @@ -16,7 +16,7 @@ } ], "require": { - "php": ">=5.5.9" + "php": "^7.1.3" }, "autoload": { "psr-4": { "Symfony\\Component\\Stopwatch\\": "" }, diff --git a/src/Symfony/Component/Templating/composer.json b/src/Symfony/Component/Templating/composer.json index 85ebba399b790..a64a3ed9774b9 100644 --- a/src/Symfony/Component/Templating/composer.json +++ b/src/Symfony/Component/Templating/composer.json @@ -16,7 +16,7 @@ } ], "require": { - "php": ">=5.5.9" + "php": "^7.1.3" }, "require-dev": { "psr/log": "~1.0" diff --git a/src/Symfony/Component/Translation/composer.json b/src/Symfony/Component/Translation/composer.json index 92d680e832352..e6feb29d09b40 100644 --- a/src/Symfony/Component/Translation/composer.json +++ b/src/Symfony/Component/Translation/composer.json @@ -16,13 +16,13 @@ } ], "require": { - "php": ">=5.5.9", + "php": "^7.1.3", "symfony/polyfill-mbstring": "~1.0" }, "require-dev": { - "symfony/config": "~2.8|~3.0|~4.0.0", - "symfony/intl": "^2.8.18|^3.2.5|~4.0.0", - "symfony/yaml": "~3.3|~4.0.0", + "symfony/config": "~2.8|~3.0|~4.0", + "symfony/intl": "^2.8.18|^3.2.5|~4.0", + "symfony/yaml": "~3.3|~4.0", "psr/log": "~1.0" }, "conflict": { diff --git a/src/Symfony/Component/Validator/composer.json b/src/Symfony/Component/Validator/composer.json index b84fff2b4aead..d934f40e77d3c 100644 --- a/src/Symfony/Component/Validator/composer.json +++ b/src/Symfony/Component/Validator/composer.json @@ -16,18 +16,18 @@ } ], "require": { - "php": ">=5.5.9", + "php": "^7.1.3", "symfony/polyfill-mbstring": "~1.0", - "symfony/translation": "~2.8|~3.0|~4.0.0" + "symfony/translation": "~2.8|~3.0|~4.0" }, "require-dev": { - "symfony/http-foundation": "~2.8|~3.0|~4.0.0", - "symfony/intl": "^2.8.18|^3.2.5|~4.0.0", - "symfony/yaml": "~3.3|~4.0.0", - "symfony/config": "~2.8|~3.0|~4.0.0", - "symfony/dependency-injection": "~3.3|~4.0.0", - "symfony/expression-language": "~2.8|~3.0|~4.0.0", - "symfony/cache": "~3.1|~4.0.0", + "symfony/http-foundation": "~2.8|~3.0|~4.0", + "symfony/intl": "^2.8.18|^3.2.5|~4.0", + "symfony/yaml": "~3.3|~4.0", + "symfony/config": "~2.8|~3.0|~4.0", + "symfony/dependency-injection": "~3.3|~4.0", + "symfony/expression-language": "~2.8|~3.0|~4.0", + "symfony/cache": "~3.1|~4.0", "doctrine/annotations": "~1.0", "doctrine/cache": "~1.0", "egulias/email-validator": "^1.2.8|~2.0" diff --git a/src/Symfony/Component/VarDumper/composer.json b/src/Symfony/Component/VarDumper/composer.json index 7b0e5ca173fcb..fcd3b3bb3c96d 100644 --- a/src/Symfony/Component/VarDumper/composer.json +++ b/src/Symfony/Component/VarDumper/composer.json @@ -16,7 +16,7 @@ } ], "require": { - "php": ">=5.5.9", + "php": "^7.1.3", "symfony/polyfill-mbstring": "~1.0" }, "require-dev": { diff --git a/src/Symfony/Component/WebLink/composer.json b/src/Symfony/Component/WebLink/composer.json index 6b8575800b9d7..0b15ffd27f673 100644 --- a/src/Symfony/Component/WebLink/composer.json +++ b/src/Symfony/Component/WebLink/composer.json @@ -16,7 +16,7 @@ } ], "require": { - "php": ">=5.5.9", + "php": "^7.1.3", "fig/link-util": "^1.0", "psr/link": "^1.0" }, @@ -24,9 +24,9 @@ "symfony/http-kernel": "" }, "require-dev": { - "symfony/event-dispatcher": "^2.8|^3.0|~4.0.0", - "symfony/http-foundation": "^2.8|^3.0|~4.0.0", - "symfony/http-kernel": "^2.8|^3.0|~4.0.0" + "symfony/event-dispatcher": "^2.8|^3.0|~4.0", + "symfony/http-foundation": "^2.8|^3.0|~4.0", + "symfony/http-kernel": "^2.8|^3.0|~4.0" }, "autoload": { "psr-4": { "Symfony\\Component\\WebLink\\": "" }, diff --git a/src/Symfony/Component/Workflow/composer.json b/src/Symfony/Component/Workflow/composer.json index 3583c4a4afac2..a3c0fd5f71209 100644 --- a/src/Symfony/Component/Workflow/composer.json +++ b/src/Symfony/Component/Workflow/composer.json @@ -20,15 +20,15 @@ } ], "require": { - "php": ">=5.5.9", - "symfony/property-access": "~2.3|~3.0|~4.0.0" + "php": "^7.1.3", + "symfony/property-access": "~2.3|~3.0|~4.0" }, "require-dev": { "psr/log": "~1.0", - "symfony/dependency-injection": "~2.8|~3.0|~4.0.0", - "symfony/event-dispatcher": "~2.1|~3.0|~4.0.0", - "symfony/expression-language": "~2.8|~3.0|~4.0.0", - "symfony/security-core": "~2.8|~3.0|~4.0.0" + "symfony/dependency-injection": "~2.8|~3.0|~4.0", + "symfony/event-dispatcher": "~2.1|~3.0|~4.0", + "symfony/expression-language": "~2.8|~3.0|~4.0", + "symfony/security-core": "~2.8|~3.0|~4.0" }, "autoload": { "psr-4": { "Symfony\\Component\\Workflow\\": "" } diff --git a/src/Symfony/Component/Yaml/composer.json b/src/Symfony/Component/Yaml/composer.json index ae7d73f80ab23..ec58648572f49 100644 --- a/src/Symfony/Component/Yaml/composer.json +++ b/src/Symfony/Component/Yaml/composer.json @@ -16,10 +16,10 @@ } ], "require": { - "php": ">=5.5.9" + "php": "^7.1.3" }, "require-dev": { - "symfony/console": "~2.8|~3.0|~4.0.0" + "symfony/console": "~2.8|~3.0|~4.0" }, "suggest": { "symfony/console": "For validating YAML files using the lint command" From 6633c8b8524b042362ddfff07c92b6b75a16b710 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Thu, 18 May 2017 08:33:50 +0200 Subject: [PATCH 0010/1099] Allow individual bridges, bundles and components to be used with 4.0 --- composer.json | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/composer.json b/composer.json index 744868ec50a46..91a5a88a17677 100644 --- a/composer.json +++ b/composer.json @@ -26,10 +26,7 @@ "psr/log": "~1.0", "psr/simple-cache": "^1.0", "symfony/polyfill-intl-icu": "~1.0", - "symfony/polyfill-mbstring": "~1.0", - "symfony/polyfill-php56": "~1.0", - "symfony/polyfill-php70": "~1.0", - "symfony/polyfill-util": "~1.0" + "symfony/polyfill-mbstring": "~1.0" }, "replace": { "symfony/asset": "self.version", From 4758c2c7b569bd74ab6ebc16ec2678c50449220f Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Thu, 18 May 2017 09:23:23 +0200 Subject: [PATCH 0011/1099] Tweak travis and appveyor for Symfony 4 --- .travis.yml | 27 +++---- appveyor.yml | 17 ++--- composer.json | 2 +- src/Symfony/Bridge/Doctrine/composer.json | 24 +++--- src/Symfony/Bridge/Monolog/composer.json | 10 +-- src/Symfony/Bridge/ProxyManager/composer.json | 4 +- src/Symfony/Bridge/Twig/composer.json | 30 ++++---- src/Symfony/Bundle/DebugBundle/composer.json | 12 +-- .../Bundle/FrameworkBundle/composer.json | 76 +++++++++---------- .../Bundle/SecurityBundle/composer.json | 42 +++++----- src/Symfony/Bundle/TwigBundle/composer.json | 24 +++--- .../Bundle/WebProfilerBundle/composer.json | 22 +++--- .../Bundle/WebServerBundle/composer.json | 8 +- src/Symfony/Component/Asset/composer.json | 4 +- .../Component/BrowserKit/composer.json | 6 +- src/Symfony/Component/Cache/composer.json | 2 +- .../Component/ClassLoader/composer.json | 2 +- src/Symfony/Component/Config/composer.json | 8 +- src/Symfony/Component/Console/composer.json | 14 ++-- src/Symfony/Component/Debug/composer.json | 4 +- .../DependencyInjection/composer.json | 12 +-- .../Component/DomCrawler/composer.json | 2 +- src/Symfony/Component/Dotenv/composer.json | 2 +- .../Component/EventDispatcher/composer.json | 10 +-- .../ExpressionLanguage/composer.json | 2 +- src/Symfony/Component/Form/composer.json | 34 ++++----- .../Component/HttpFoundation/composer.json | 2 +- .../Component/HttpKernel/composer.json | 43 +++++------ src/Symfony/Component/Intl/composer.json | 2 +- src/Symfony/Component/Ldap/composer.json | 2 +- .../Component/PropertyAccess/composer.json | 4 +- .../Component/PropertyInfo/composer.json | 10 +-- src/Symfony/Component/Routing/composer.json | 16 ++-- .../Component/Security/Core/composer.json | 10 +-- .../Component/Security/Csrf/composer.json | 4 +- .../Component/Security/Guard/composer.json | 4 +- .../Component/Security/Http/composer.json | 14 ++-- src/Symfony/Component/Security/composer.json | 18 ++--- .../Component/Serializer/composer.json | 22 +++--- .../Component/Translation/composer.json | 10 +-- src/Symfony/Component/Validator/composer.json | 20 ++--- src/Symfony/Component/WebLink/composer.json | 6 +- src/Symfony/Component/Workflow/composer.json | 10 +-- src/Symfony/Component/Yaml/composer.json | 2 +- 44 files changed, 291 insertions(+), 308 deletions(-) diff --git a/.travis.yml b/.travis.yml index da776a33b035b..7f875065f2402 100644 --- a/.travis.yml +++ b/.travis.yml @@ -14,17 +14,12 @@ addons: env: global: - - MIN_PHP=7.1.0 + - MIN_PHP=7.1.3 - SYMFONY_PROCESS_PHP_TEST_BINARY=~/.phpenv/versions/7.1/bin/php matrix: include: - # Use the newer stack for HHVM as HHVM does not support Precise anymore since a long time and so Precise has an outdated version - - php: hhvm-stable - sudo: required - dist: trusty - group: edge - - php: 7.1.0 + - php: 7.1.3 - php: 7.1 env: deps=high - php: 7.1 @@ -82,11 +77,10 @@ before_install: echo extension = ldap.so >> $INI echo extension = redis.so >> $INI echo extension = memcached.so >> $INI - [[ $PHP = 5.* ]] && echo extension = mongo.so >> $INI - [[ $PHP = 5.* ]] && echo extension = memcache.so >> $INI + #echo extension = mongodb.so >> $INI # Matrix lines for intermediate PHP versions are skipped for pull requests - if [[ ! $deps && ! $PHP = ${MIN_PHP%.*} && ! $PHP = hhvm* && $TRAVIS_PULL_REQUEST != false ]]; then + if [[ ! $deps && ! $PHP = $MIN_PHP && ! $PHP = hhvm* && $TRAVIS_PULL_REQUEST != false ]]; then deps=skip skip=1 else @@ -95,17 +89,14 @@ before_install: - | # Install sigchild-enabled PHP to test the Process component on the lowest PHP matrix line - if [[ ! $deps && $PHP = ${MIN_PHP%.*} && ! -d php-$MIN_PHP/sapi ]]; then - wget http://museum.php.net/php5/php-$MIN_PHP.tar.bz2 -O - | tar -xj && + if [[ ! $deps && $PHP = $MIN_PHP && ! -d php-$MIN_PHP/sapi ]]; then + wget http://php.net/get/php-$MIN_PHP.tar.bz2/from/this/mirror -O - | tar -xj && (cd php-$MIN_PHP && ./configure --enable-sigchild --enable-pcntl && make -j2) fi - | # Install extra PHP extensions - if [[ ! $skip && $PHP = 5.* ]]; then - ([[ $deps ]] || tfold ext.symfony_debug 'cd src/Symfony/Component/Debug/Resources/ext && phpize && ./configure && make && echo extension = $(pwd)/modules/symfony_debug.so >> '"$INI") && - tfold ext.apcu4 'echo yes | pecl install -f apcu-4.0.11' - elif [[ ! $skip && $PHP = 7.* ]]; then + if [[ ! $skip && $PHP = 7.* ]]; then tfold ext.apcu5 'echo yes | pecl install -f apcu-5.1.6' fi @@ -171,8 +162,8 @@ install: else echo "$COMPONENTS" | parallel --gnu "tfold {} $PHPUNIT_X {}" tfold tty-group $PHPUNIT --group tty - if [[ $PHP = ${MIN_PHP%.*} ]]; then - echo -e "1\\n0" | xargs -I{} bash -c "tfold src/Symfony/Component/Process.sigchild{} SYMFONY_DEPRECATIONS_HELPER=weak ENHANCE_SIGCHLD={} php-$MIN_PHP/sapi/cli/php .phpunit/phpunit-4.8/phpunit --colors=always src/Symfony/Component/Process/" + if [[ $PHP = $MIN_PHP ]]; then + echo -e "1\\n0" | xargs -I{} bash -c "tfold src/Symfony/Component/Process.sigchild{} SYMFONY_DEPRECATIONS_HELPER=weak ENHANCE_SIGCHLD={} php-$MIN_PHP/sapi/cli/php ./phpunit --colors=always src/Symfony/Component/Process/" fi fi } diff --git a/appveyor.yml b/appveyor.yml index c37c9bad46b44..db0b2d2381473 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -11,18 +11,15 @@ init: - SET COMPOSER_NO_INTERACTION=1 - SET SYMFONY_DEPRECATIONS_HELPER=strict - SET ANSICON=121x90 (121x90) - - SET SYMFONY_PHPUNIT_VERSION=4.8 - REG ADD "HKEY_CURRENT_USER\Software\Microsoft\Command Processor" /v DelayedExpansion /t REG_DWORD /d 1 /f install: - mkdir c:\php && cd c:\php - - appveyor DownloadFile https://raw.githubusercontent.com/symfony/binary-utils/master/cacert.pem - - appveyor DownloadFile https://github.com/symfony/binary-utils/releases/download/v0.1/php-7.1.3-Win32-VC14-x64.zip + - appveyor DownloadFile https://github.com/symfony/binary-utils/releases/download/v0.1/php-7.1.3-Win32-VC14-x86.zip + - 7z x php-7.1.3-Win32-VC14-x86.zip -y >nul - cd ext - - appveyor DownloadFile https://github.com/symfony/binary-utils/releases/download/v0.1/php_apcu-4.0.10-5.5-nts-vc11-x86.zip - - 7z x php_apcu-4.0.10-5.5-nts-vc11-x86.zip -y >nul - - appveyor DownloadFile https://github.com/symfony/binary-utils/releases/download/v0.1/php_memcache-3.0.8-5.5-nts-vc11-x86.zip - - 7z x php_memcache-3.0.8-5.5-nts-vc11-x86.zip -y >nul + - appveyor DownloadFile https://github.com/symfony/binary-utils/releases/download/v0.1/php_apcu-5.1.8-7.1-ts-vc14-x86.zip + - 7z x php_apcu-5.1.8-7.1-ts-vc14-x86.zip -y >nul - cd .. - copy /Y php.ini-development php.ini-min - echo serialize_precision=14 >> php.ini-min @@ -35,13 +32,11 @@ install: - echo extension=php_openssl.dll >> php.ini-max - echo extension=php_apcu.dll >> php.ini-max - echo apc.enable_cli=1 >> php.ini-max - - echo extension=php_memcache.dll >> php.ini-max - echo extension=php_intl.dll >> php.ini-max - echo extension=php_mbstring.dll >> php.ini-max - echo extension=php_fileinfo.dll >> php.ini-max - echo extension=php_pdo_sqlite.dll >> php.ini-max - echo extension=php_curl.dll >> php.ini-max - - echo curl.cainfo=c:\php\cacert.pem >> php.ini-max - copy /Y php.ini-max php.ini - cd c:\projects\symfony - IF NOT EXIST composer.phar (appveyor DownloadFile https://getcomposer.org/download/1.3.0/composer.phar) @@ -54,10 +49,8 @@ install: test_script: - SET X=0 - - cd c:\php && 7z x php-7.1.3-Win32-VC14-x64.zip -y >nul && copy /Y php.ini-min php.ini - - cd c:\projects\symfony - - php phpunit src\Symfony --exclude-group benchmark,intl-data || SET X=!errorlevel! - SET SYMFONY_PHPUNIT_SKIPPED_TESTS=phpunit.skipped + - copy /Y c:\php\php.ini-min c:\php\php.ini - php phpunit src\Symfony --exclude-group benchmark,intl-data || SET X=!errorlevel! - copy /Y c:\php\php.ini-max c:\php\php.ini - php phpunit src\Symfony --exclude-group benchmark,intl-data || SET X=!errorlevel! diff --git a/composer.json b/composer.json index 91a5a88a17677..b4664e545dd49 100644 --- a/composer.json +++ b/composer.json @@ -16,7 +16,7 @@ } ], "require": { - "php": "^7.1.0", + "php": "^7.1.3", "doctrine/common": "~2.4", "fig/link-util": "^1.0", "twig/twig": "~1.32|~2.2", diff --git a/src/Symfony/Bridge/Doctrine/composer.json b/src/Symfony/Bridge/Doctrine/composer.json index 6c83d3fd58d49..952e6aa639cbc 100644 --- a/src/Symfony/Bridge/Doctrine/composer.json +++ b/src/Symfony/Bridge/Doctrine/composer.json @@ -21,24 +21,24 @@ "symfony/polyfill-mbstring": "~1.0" }, "require-dev": { - "symfony/stopwatch": "~2.8|~3.0|~4.0", - "symfony/dependency-injection": "~3.3|~4.0", - "symfony/form": "^3.2.5|~4.0", - "symfony/http-kernel": "~2.8|~3.0|~4.0", - "symfony/property-access": "~2.8|~3.0|~4.0", - "symfony/property-info": "~2.8|3.0|~4.0", - "symfony/proxy-manager-bridge": "~2.8|~3.0|~4.0", - "symfony/security": "~2.8|~3.0|~4.0", - "symfony/expression-language": "~2.8|~3.0|~4.0", - "symfony/validator": "^2.8.18|^3.2.5|~4.0", - "symfony/translation": "~2.8|~3.0|~4.0", + "symfony/stopwatch": "~3.4|~4.0", + "symfony/dependency-injection": "~3.4|~4.0", + "symfony/form": "~3.4|~4.0", + "symfony/http-kernel": "~3.4|~4.0", + "symfony/property-access": "~3.4|~4.0", + "symfony/property-info": "~3.4|~4.0", + "symfony/proxy-manager-bridge": "~3.4|~4.0", + "symfony/security": "~3.4|~4.0", + "symfony/expression-language": "~3.4|~4.0", + "symfony/validator": "~3.4|~4.0", + "symfony/translation": "~3.4|~4.0", "doctrine/data-fixtures": "1.0.*", "doctrine/dbal": "~2.4", "doctrine/orm": "^2.4.5" }, "conflict": { "phpunit/phpunit": "<4.8.35|<5.4.3,>=5.0", - "symfony/dependency-injection": "<3.3" + "symfony/dependency-injection": "<3.4" }, "suggest": { "symfony/form": "", diff --git a/src/Symfony/Bridge/Monolog/composer.json b/src/Symfony/Bridge/Monolog/composer.json index 8633d0044f73f..0211a86469bc1 100644 --- a/src/Symfony/Bridge/Monolog/composer.json +++ b/src/Symfony/Bridge/Monolog/composer.json @@ -18,15 +18,15 @@ "require": { "php": "^7.1.3", "monolog/monolog": "~1.19", - "symfony/http-kernel": "~2.8|~3.0|~4.0" + "symfony/http-kernel": "~3.4|~4.0" }, "require-dev": { - "symfony/console": "~2.8|~3.0|~4.0", - "symfony/event-dispatcher": "~2.8|~3.0|~4.0", - "symfony/var-dumper": "~3.3|~4.0" + "symfony/console": "~3.4|~4.0", + "symfony/event-dispatcher": "~3.4|~4.0", + "symfony/var-dumper": "~3.4|~4.0" }, "conflict": { - "symfony/http-foundation": "<3.3" + "symfony/http-foundation": "<3.4" }, "suggest": { "symfony/http-kernel": "For using the debugging handlers together with the response life cycle of the HTTP kernel.", diff --git a/src/Symfony/Bridge/ProxyManager/composer.json b/src/Symfony/Bridge/ProxyManager/composer.json index 0980cadb74f09..a2ea35dd182ee 100644 --- a/src/Symfony/Bridge/ProxyManager/composer.json +++ b/src/Symfony/Bridge/ProxyManager/composer.json @@ -17,11 +17,11 @@ ], "require": { "php": "^7.1.3", - "symfony/dependency-injection": "~2.8|~3.0|~4.0", + "symfony/dependency-injection": "~3.4|~4.0", "ocramius/proxy-manager": "~0.4|~1.0|~2.0" }, "require-dev": { - "symfony/config": "~2.8|~3.0|~4.0" + "symfony/config": "~3.4|~4.0" }, "autoload": { "psr-4": { "Symfony\\Bridge\\ProxyManager\\": "" }, diff --git a/src/Symfony/Bridge/Twig/composer.json b/src/Symfony/Bridge/Twig/composer.json index 80ee256d2e9c6..89780bff748b5 100644 --- a/src/Symfony/Bridge/Twig/composer.json +++ b/src/Symfony/Bridge/Twig/composer.json @@ -21,22 +21,22 @@ }, "require-dev": { "fig/link-util": "^1.0", - "symfony/asset": "~2.8|~3.0|~4.0", - "symfony/finder": "~2.8|~3.0|~4.0", - "symfony/form": "^3.2.7|~4.0", - "symfony/http-kernel": "~3.2|~4.0", + "symfony/asset": "~3.4|~4.0", + "symfony/finder": "~3.4|~4.0", + "symfony/form": "~3.4|~4.0", + "symfony/http-kernel": "~3.4|~4.0", "symfony/polyfill-intl-icu": "~1.0", - "symfony/routing": "~2.8|~3.0|~4.0", - "symfony/templating": "~2.8|~3.0|~4.0", - "symfony/translation": "~2.8|~3.0|~4.0", - "symfony/yaml": "~2.8|~3.0|~4.0", - "symfony/security": "~2.8|~3.0|~4.0", - "symfony/security-acl": "~2.8|~3.0|~4.0", - "symfony/stopwatch": "~2.8|~3.0|~4.0", - "symfony/console": "~2.8|~3.0|~4.0", - "symfony/var-dumper": "~2.8.10|~3.1.4|~3.2|~4.0", - "symfony/expression-language": "~2.8|~3.0|~4.0", - "symfony/web-link": "~3.3|~4.0" + "symfony/routing": "~3.4|~4.0", + "symfony/templating": "~3.4|~4.0", + "symfony/translation": "~3.4|~4.0", + "symfony/yaml": "~3.4|~4.0", + "symfony/security": "~3.4|~4.0", + "symfony/security-acl": "~2.8|~3.0", + "symfony/stopwatch": "~3.4|~4.0", + "symfony/console": "~3.4|~4.0", + "symfony/var-dumper": "~3.4|~4.0", + "symfony/expression-language": "~3.4|~4.0", + "symfony/web-link": "~3.4|~4.0" }, "suggest": { "symfony/finder": "", diff --git a/src/Symfony/Bundle/DebugBundle/composer.json b/src/Symfony/Bundle/DebugBundle/composer.json index f8444aec6533e..ccfe8d6788e22 100644 --- a/src/Symfony/Bundle/DebugBundle/composer.json +++ b/src/Symfony/Bundle/DebugBundle/composer.json @@ -17,14 +17,14 @@ ], "require": { "php": "^7.1.3", - "symfony/http-kernel": "~2.8|~3.0|~4.0", - "symfony/twig-bridge": "~2.8|~3.0|~4.0", - "symfony/var-dumper": "~2.8|~3.0|~4.0" + "symfony/http-kernel": "~3.4|~4.0", + "symfony/twig-bridge": "~3.4|~4.0", + "symfony/var-dumper": "~3.4|~4.0" }, "require-dev": { - "symfony/config": "~3.3|~4.0", - "symfony/dependency-injection": "~3.3|~4.0", - "symfony/web-profiler-bundle": "~2.8|~3.0|~4.0" + "symfony/config": "~3.4|~4.0", + "symfony/dependency-injection": "~3.4|~4.0", + "symfony/web-profiler-bundle": "~3.4|~4.0" }, "suggest": { "symfony/config": "For service container configuration", diff --git a/src/Symfony/Bundle/FrameworkBundle/composer.json b/src/Symfony/Bundle/FrameworkBundle/composer.json index 1d43ec6a4da72..1ca10ad781a70 100644 --- a/src/Symfony/Bundle/FrameworkBundle/composer.json +++ b/src/Symfony/Bundle/FrameworkBundle/composer.json @@ -18,42 +18,42 @@ "require": { "php": "^7.1.3", "ext-xml": "*", - "symfony/cache": "~3.3|~4.0", - "symfony/class-loader": "~3.2|~4.0", - "symfony/dependency-injection": "~3.3-beta2|~4.0", - "symfony/config": "~3.3|~4.0", - "symfony/event-dispatcher": "~3.3|~4.0", - "symfony/http-foundation": "~3.3|~4.0", - "symfony/http-kernel": "~3.3|~4.0", + "symfony/cache": "~3.4|~4.0", + "symfony/class-loader": "~3.4|~4.0", + "symfony/dependency-injection": "~3.4|~4.0", + "symfony/config": "~3.4|~4.0", + "symfony/event-dispatcher": "~3.4|~4.0", + "symfony/http-foundation": "~3.4|~4.0", + "symfony/http-kernel": "~3.4|~4.0", "symfony/polyfill-mbstring": "~1.0", - "symfony/filesystem": "~2.8|~3.0|~4.0", - "symfony/finder": "~2.8|~3.0|~4.0", - "symfony/routing": "~3.3|~4.0", - "symfony/stopwatch": "~2.8|~3.0|~4.0", + "symfony/filesystem": "~3.4|~4.0", + "symfony/finder": "~3.4|~4.0", + "symfony/routing": "~3.4|~4.0", + "symfony/stopwatch": "~3.4|~4.0", "doctrine/cache": "~1.0" }, "require-dev": { "fig/link-util": "^1.0", - "symfony/asset": "~3.3|~4.0", - "symfony/browser-kit": "~2.8|~3.0|~4.0", - "symfony/console": "~3.3|~4.0", - "symfony/css-selector": "~2.8|~3.0|~4.0", - "symfony/dom-crawler": "~2.8|~3.0|~4.0", + "symfony/asset": "~3.4|~4.0", + "symfony/browser-kit": "~3.4|~4.0", + "symfony/console": "~3.4|~4.0", + "symfony/css-selector": "~3.4|~4.0", + "symfony/dom-crawler": "~3.4|~4.0", "symfony/polyfill-intl-icu": "~1.0", - "symfony/security": "~2.8|~3.0|~4.0", - "symfony/form": "~3.3|~4.0", - "symfony/expression-language": "~2.8|~3.0|~4.0", - "symfony/process": "~2.8|~3.0|~4.0", - "symfony/security-core": "~3.2|~4.0", - "symfony/security-csrf": "~2.8|~3.0|~4.0", - "symfony/serializer": "~3.3|~4.0", - "symfony/translation": "~3.2|~4.0", - "symfony/templating": "~2.8|~3.0|~4.0", - "symfony/validator": "~3.3|~4.0", - "symfony/workflow": "~3.3|~4.0", - "symfony/yaml": "~3.2|~4.0", - "symfony/property-info": "~3.3|~4.0", - "symfony/web-link": "~3.3|~4.0", + "symfony/security": "~3.4|~4.0", + "symfony/form": "~3.4|~4.0", + "symfony/expression-language": "~3.4|~4.0", + "symfony/process": "~3.4|~4.0", + "symfony/security-core": "~3.4|~4.0", + "symfony/security-csrf": "~3.4|~4.0", + "symfony/serializer": "~3.4|~4.0", + "symfony/translation": "~3.4|~4.0", + "symfony/templating": "~3.4|~4.0", + "symfony/validator": "~3.4|~4.0", + "symfony/workflow": "~3.4|~4.0", + "symfony/yaml": "~3.4|~4.0", + "symfony/property-info": "~3.4|~4.0", + "symfony/web-link": "~3.4|~4.0", "doctrine/annotations": "~1.0", "phpdocumentor/reflection-docblock": "^3.0", "twig/twig": "~1.26|~2.0", @@ -63,14 +63,14 @@ "phpdocumentor/reflection-docblock": "<3.0", "phpdocumentor/type-resolver": "<0.2.0", "phpunit/phpunit": "<4.8.35|<5.4.3,>=5.0", - "symfony/asset": "<3.3", - "symfony/console": "<3.3", - "symfony/form": "<3.3", - "symfony/property-info": "<3.3", - "symfony/serializer": "<3.3", - "symfony/translation": "<3.2", - "symfony/validator": "<3.3", - "symfony/workflow": "<3.3" + "symfony/asset": "<3.4", + "symfony/console": "<3.4", + "symfony/form": "<3.4", + "symfony/property-info": "<3.4", + "symfony/serializer": "<3.4", + "symfony/translation": "<3.4", + "symfony/validator": "<3.4", + "symfony/workflow": "<3.4" }, "suggest": { "ext-apcu": "For best performance of the system caches", diff --git a/src/Symfony/Bundle/SecurityBundle/composer.json b/src/Symfony/Bundle/SecurityBundle/composer.json index 61980a322972d..697bda1943fc9 100644 --- a/src/Symfony/Bundle/SecurityBundle/composer.json +++ b/src/Symfony/Bundle/SecurityBundle/composer.json @@ -17,33 +17,33 @@ ], "require": { "php": "^7.1.3", - "symfony/security": "~3.3|~4.0", - "symfony/dependency-injection": "~3.3-beta2|~4.0", - "symfony/http-kernel": "~3.3|~4.0" + "symfony/security": "~3.4|~4.0", + "symfony/dependency-injection": "~3.4|~4.0", + "symfony/http-kernel": "~3.4|~4.0" }, "require-dev": { - "symfony/asset": "~2.8|~3.0|~4.0", - "symfony/browser-kit": "~2.8|~3.0|~4.0", - "symfony/console": "~3.2|~4.0", - "symfony/css-selector": "~2.8|~3.0|~4.0", - "symfony/dom-crawler": "~2.8|~3.0|~4.0", - "symfony/form": "^2.8.18|^3.2.5|~4.0", - "symfony/framework-bundle": "^3.2.8|~4.0", - "symfony/http-foundation": "~2.8|~3.0|~4.0", - "symfony/security-acl": "~2.8|~3.0|~4.0", - "symfony/translation": "~2.8|~3.0|~4.0", - "symfony/twig-bundle": "~2.8|~3.0|~4.0", - "symfony/twig-bridge": "~2.8|~3.0|~4.0", - "symfony/process": "~2.8|~3.0|~4.0", - "symfony/validator": "^3.2.5|~4.0", - "symfony/var-dumper": "~3.3|~4.0", - "symfony/yaml": "~2.8|~3.0|~4.0", - "symfony/expression-language": "~2.8|~3.0|~4.0", + "symfony/asset": "~3.4|~4.0", + "symfony/browser-kit": "~3.4|~4.0", + "symfony/console": "~3.4|~4.0", + "symfony/css-selector": "~3.4|~4.0", + "symfony/dom-crawler": "~3.4|~4.0", + "symfony/form": "~3.4|~4.0", + "symfony/framework-bundle": "~3.4|~4.0", + "symfony/http-foundation": "~3.4|~4.0", + "symfony/security-acl": "~2.8|~3.0", + "symfony/translation": "~3.4|~4.0", + "symfony/twig-bundle": "~3.4|~4.0", + "symfony/twig-bridge": "~3.4|~4.0", + "symfony/process": "~3.4|~4.0", + "symfony/validator": "~3.4|~4.0", + "symfony/var-dumper": "~3.4|~4.0", + "symfony/yaml": "~3.4|~4.0", + "symfony/expression-language": "~3.4|~4.0", "doctrine/doctrine-bundle": "~1.4", "twig/twig": "~1.28|~2.0" }, "conflict": { - "symfony/var-dumper": "<3.3" + "symfony/var-dumper": "<3.4" }, "suggest": { "symfony/security-acl": "For using the ACL functionality of this bundle" diff --git a/src/Symfony/Bundle/TwigBundle/composer.json b/src/Symfony/Bundle/TwigBundle/composer.json index a951a24fec8ff..ec19e6080a463 100644 --- a/src/Symfony/Bundle/TwigBundle/composer.json +++ b/src/Symfony/Bundle/TwigBundle/composer.json @@ -24,21 +24,21 @@ "twig/twig": "^1.32|^2.2" }, "require-dev": { - "symfony/asset": "~2.8|~3.0|~4.0", - "symfony/stopwatch": "~2.8|~3.0|~4.0", - "symfony/dependency-injection": "~3.3|~4.0", - "symfony/expression-language": "~2.8|~3.0|~4.0", - "symfony/finder": "~2.8|~3.0|~4.0", - "symfony/form": "~2.8|~3.0|~4.0", - "symfony/routing": "~2.8|~3.0|~4.0", - "symfony/templating": "~2.8|~3.0|~4.0", - "symfony/yaml": "~2.8|~3.0|~4.0", - "symfony/framework-bundle": "^3.2.8|~4.0", - "symfony/web-link": "~3.3|~4.0", + "symfony/asset": "~3.4|~4.0", + "symfony/stopwatch": "~3.4|~4.0", + "symfony/dependency-injection": "~3.4|~4.0", + "symfony/expression-language": "~3.4|~4.0", + "symfony/finder": "~3.4|~4.0", + "symfony/form": "~3.4|~4.0", + "symfony/routing": "~3.4|~4.0", + "symfony/templating": "~3.4|~4.0", + "symfony/yaml": "~3.4|~4.0", + "symfony/framework-bundle": "~3.4|~4.0", + "symfony/web-link": "~3.4|~4.0", "doctrine/annotations": "~1.0" }, "conflict": { - "symfony/dependency-injection": "<3.3" + "symfony/dependency-injection": "<3.4" }, "autoload": { "psr-4": { "Symfony\\Bundle\\TwigBundle\\": "" }, diff --git a/src/Symfony/Bundle/WebProfilerBundle/composer.json b/src/Symfony/Bundle/WebProfilerBundle/composer.json index 219394c91d163..9841237066a98 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/composer.json +++ b/src/Symfony/Bundle/WebProfilerBundle/composer.json @@ -17,22 +17,22 @@ ], "require": { "php": "^7.1.3", - "symfony/http-kernel": "~3.2|~4.0", - "symfony/routing": "~2.8|~3.0|~4.0", - "symfony/twig-bridge": "~2.8|~3.0|~4.0", - "symfony/var-dumper": "~3.3|~4.0", + "symfony/http-kernel": "~3.4|~4.0", + "symfony/routing": "~3.4|~4.0", + "symfony/twig-bridge": "~3.4|~4.0", + "symfony/var-dumper": "~3.4|~4.0", "twig/twig": "~1.28|~2.0" }, "require-dev": { - "symfony/config": "~2.8|~3.0|~4.0", - "symfony/console": "~2.8|~3.0|~4.0", - "symfony/dependency-injection": "~3.3|~4.0", - "symfony/stopwatch": "~2.8|~3.0|~4.0" + "symfony/config": "~3.4|~4.0", + "symfony/console": "~3.4|~4.0", + "symfony/dependency-injection": "~3.4|~4.0", + "symfony/stopwatch": "~3.4|~4.0" }, "conflict": { - "symfony/dependency-injection": "<3.3", - "symfony/event-dispatcher": "<3.2", - "symfony/var-dumper": "<3.3" + "symfony/dependency-injection": "<3.4", + "symfony/event-dispatcher": "<3.4", + "symfony/var-dumper": "<3.4" }, "autoload": { "psr-4": { "Symfony\\Bundle\\WebProfilerBundle\\": "" }, diff --git a/src/Symfony/Bundle/WebServerBundle/composer.json b/src/Symfony/Bundle/WebServerBundle/composer.json index 521b62c6ab547..dda1c9245ffee 100644 --- a/src/Symfony/Bundle/WebServerBundle/composer.json +++ b/src/Symfony/Bundle/WebServerBundle/composer.json @@ -17,9 +17,9 @@ ], "require": { "php": "^7.1.3", - "symfony/console": "~2.8.8|~3.0.8|~3.1.2|~3.2|~4.0", - "symfony/http-kernel": "~2.8|~3.|~4.0", - "symfony/process": "~2.8|~3.0|~4.0" + "symfony/console": "~3.4|~4.0", + "symfony/http-kernel": "~3.4|~4.0", + "symfony/process": "~3.4|~4.0" }, "autoload": { "psr-4": { "Symfony\\Bundle\\WebServerBundle\\": "" }, @@ -28,7 +28,7 @@ ] }, "conflict": { - "symfony/dependency-injection": "<3.3" + "symfony/dependency-injection": "<3.4" }, "minimum-stability": "dev", "extra": { diff --git a/src/Symfony/Component/Asset/composer.json b/src/Symfony/Component/Asset/composer.json index 0ab2db74a3a29..e60d306d6d62b 100644 --- a/src/Symfony/Component/Asset/composer.json +++ b/src/Symfony/Component/Asset/composer.json @@ -22,8 +22,8 @@ "symfony/http-foundation": "" }, "require-dev": { - "symfony/http-foundation": "~2.8|~3.0|~4.0", - "symfony/http-kernel": "~2.8|~3.0|~4.0" + "symfony/http-foundation": "~3.4|~4.0", + "symfony/http-kernel": "~3.4|~4.0" }, "autoload": { "psr-4": { "Symfony\\Component\\Asset\\": "" }, diff --git a/src/Symfony/Component/BrowserKit/composer.json b/src/Symfony/Component/BrowserKit/composer.json index 79f644d5d9bdf..eda8a9d7c3acd 100644 --- a/src/Symfony/Component/BrowserKit/composer.json +++ b/src/Symfony/Component/BrowserKit/composer.json @@ -17,11 +17,11 @@ ], "require": { "php": "^7.1.3", - "symfony/dom-crawler": "~2.8|~3.0|~4.0" + "symfony/dom-crawler": "~3.4|~4.0" }, "require-dev": { - "symfony/process": "~2.8|~3.0|~4.0", - "symfony/css-selector": "~2.8|~3.0|~4.0" + "symfony/process": "~3.4|~4.0", + "symfony/css-selector": "~3.4|~4.0" }, "suggest": { "symfony/process": "" diff --git a/src/Symfony/Component/Cache/composer.json b/src/Symfony/Component/Cache/composer.json index 2efb85dd716f0..7a64053c4f8a3 100644 --- a/src/Symfony/Component/Cache/composer.json +++ b/src/Symfony/Component/Cache/composer.json @@ -32,7 +32,7 @@ "predis/predis": "~1.0" }, "conflict": { - "symfony/var-dumper": "<3.3" + "symfony/var-dumper": "<3.4" }, "suggest": { "symfony/polyfill-apcu": "For using ApcuAdapter on HHVM" diff --git a/src/Symfony/Component/ClassLoader/composer.json b/src/Symfony/Component/ClassLoader/composer.json index 83be350a56638..65f35cdb7394b 100644 --- a/src/Symfony/Component/ClassLoader/composer.json +++ b/src/Symfony/Component/ClassLoader/composer.json @@ -20,7 +20,7 @@ "php": "^7.1.3" }, "require-dev": { - "symfony/finder": "~2.8|~3.0|~4.0", + "symfony/finder": "~3.4|~4.0", "symfony/polyfill-apcu": "~1.1" }, "suggest": { diff --git a/src/Symfony/Component/Config/composer.json b/src/Symfony/Component/Config/composer.json index fda6a755ef377..79a7da14ffd52 100644 --- a/src/Symfony/Component/Config/composer.json +++ b/src/Symfony/Component/Config/composer.json @@ -17,14 +17,14 @@ ], "require": { "php": "^7.1.3", - "symfony/filesystem": "~2.8|~3.0|~4.0" + "symfony/filesystem": "~3.4|~4.0" }, "require-dev": { - "symfony/yaml": "~3.0|~4.0", - "symfony/dependency-injection": "~3.3|~4.0" + "symfony/yaml": "~3.4|~4.0", + "symfony/dependency-injection": "~3.4|~4.0" }, "conflict": { - "symfony/dependency-injection": "<3.3" + "symfony/dependency-injection": "<3.4" }, "suggest": { "symfony/yaml": "To use the yaml reference dumper" diff --git a/src/Symfony/Component/Console/composer.json b/src/Symfony/Component/Console/composer.json index c7dca34b5fb8f..8fb9bdf7d822b 100644 --- a/src/Symfony/Component/Console/composer.json +++ b/src/Symfony/Component/Console/composer.json @@ -18,14 +18,14 @@ "require": { "php": "^7.1.3", "symfony/polyfill-mbstring": "~1.0", - "symfony/debug": "~2.8|~3.0|~4.0" + "symfony/debug": "~3.4|~4.0" }, "require-dev": { - "symfony/http-kernel": "~2.8|~3.0|~4.0", - "symfony/event-dispatcher": "~2.8|~3.0|~4.0", - "symfony/dependency-injection": "~3.3|~4.0", - "symfony/filesystem": "~2.8|~3.0|~4.0", - "symfony/process": "~2.8|~3.0|~4.0", + "symfony/http-kernel": "~3.4|~4.0", + "symfony/event-dispatcher": "~3.4|~4.0", + "symfony/dependency-injection": "~3.4|~4.0", + "symfony/filesystem": "~3.4|~4.0", + "symfony/process": "~3.4|~4.0", "psr/log": "~1.0" }, "suggest": { @@ -35,7 +35,7 @@ "psr/log": "For using the console logger" }, "conflict": { - "symfony/dependency-injection": "<3.3" + "symfony/dependency-injection": "<3.4" }, "autoload": { "psr-4": { "Symfony\\Component\\Console\\": "" }, diff --git a/src/Symfony/Component/Debug/composer.json b/src/Symfony/Component/Debug/composer.json index ac7d6f8f2aa62..2e6fc173e71e2 100644 --- a/src/Symfony/Component/Debug/composer.json +++ b/src/Symfony/Component/Debug/composer.json @@ -20,10 +20,10 @@ "psr/log": "~1.0" }, "conflict": { - "symfony/http-kernel": ">=2.3,<2.3.24|~2.4.0|>=2.5,<2.5.9|>=2.6,<2.6.2" + "symfony/http-kernel": "<3.4" }, "require-dev": { - "symfony/http-kernel": "~2.8|~3.0|~4.0" + "symfony/http-kernel": "~3.4|~4.0" }, "autoload": { "psr-4": { "Symfony\\Component\\Debug\\": "" }, diff --git a/src/Symfony/Component/DependencyInjection/composer.json b/src/Symfony/Component/DependencyInjection/composer.json index cd07d2b6dcfc0..29b85343438ee 100644 --- a/src/Symfony/Component/DependencyInjection/composer.json +++ b/src/Symfony/Component/DependencyInjection/composer.json @@ -20,9 +20,9 @@ "psr/container": "^1.0" }, "require-dev": { - "symfony/yaml": "~3.3|~4.0", - "symfony/config": "~3.3|~4.0", - "symfony/expression-language": "~2.8|~3.0|~4.0" + "symfony/yaml": "~3.4|~4.0", + "symfony/config": "~3.4|~4.0", + "symfony/expression-language": "~3.4|~4.0" }, "suggest": { "symfony/yaml": "", @@ -32,9 +32,9 @@ "symfony/proxy-manager-bridge": "Generate service proxies to lazy load them" }, "conflict": { - "symfony/config": "<=3.3-beta1", - "symfony/finder": "<3.3", - "symfony/yaml": "<3.3" + "symfony/config": "<3.4", + "symfony/finder": "<3.4", + "symfony/yaml": "<3.4" }, "provide": { "psr/container-implementation": "1.0" diff --git a/src/Symfony/Component/DomCrawler/composer.json b/src/Symfony/Component/DomCrawler/composer.json index 47ce2d2bed91e..8c04c700168ae 100644 --- a/src/Symfony/Component/DomCrawler/composer.json +++ b/src/Symfony/Component/DomCrawler/composer.json @@ -20,7 +20,7 @@ "symfony/polyfill-mbstring": "~1.0" }, "require-dev": { - "symfony/css-selector": "~2.8|~3.0|~4.0" + "symfony/css-selector": "~3.4|~4.0" }, "suggest": { "symfony/css-selector": "" diff --git a/src/Symfony/Component/Dotenv/composer.json b/src/Symfony/Component/Dotenv/composer.json index 729ef8afe834e..ea62967631683 100644 --- a/src/Symfony/Component/Dotenv/composer.json +++ b/src/Symfony/Component/Dotenv/composer.json @@ -19,7 +19,7 @@ "php": "^7.1.3" }, "require-dev": { - "symfony/process": "~3.2|~4.0" + "symfony/process": "~3.4|~4.0" }, "autoload": { "psr-4": { "Symfony\\Component\\Dotenv\\": "" }, diff --git a/src/Symfony/Component/EventDispatcher/composer.json b/src/Symfony/Component/EventDispatcher/composer.json index 5b4a4db97c4b2..01f206c3b734f 100644 --- a/src/Symfony/Component/EventDispatcher/composer.json +++ b/src/Symfony/Component/EventDispatcher/composer.json @@ -19,14 +19,14 @@ "php": "^7.1.3" }, "require-dev": { - "symfony/dependency-injection": "~3.3|~4.0", - "symfony/expression-language": "~2.8|~3.0|~4.0", - "symfony/config": "~2.8|~3.0|~4.0", - "symfony/stopwatch": "~2.8|~3.0|~4.0", + "symfony/dependency-injection": "~3.4|~4.0", + "symfony/expression-language": "~3.4|~4.0", + "symfony/config": "~3.4|~4.0", + "symfony/stopwatch": "~3.4|~4.0", "psr/log": "~1.0" }, "conflict": { - "symfony/dependency-injection": "<3.3" + "symfony/dependency-injection": "<3.4" }, "suggest": { "symfony/dependency-injection": "", diff --git a/src/Symfony/Component/ExpressionLanguage/composer.json b/src/Symfony/Component/ExpressionLanguage/composer.json index 3b8c0bcd44f4c..e041ea0fd7f89 100644 --- a/src/Symfony/Component/ExpressionLanguage/composer.json +++ b/src/Symfony/Component/ExpressionLanguage/composer.json @@ -17,7 +17,7 @@ ], "require": { "php": "^7.1.3", - "symfony/cache": "~3.1|~4.0" + "symfony/cache": "~3.4|~4.0" }, "autoload": { "psr-4": { "Symfony\\Component\\ExpressionLanguage\\": "" }, diff --git a/src/Symfony/Component/Form/composer.json b/src/Symfony/Component/Form/composer.json index d84d23a48cf25..f85cec9e8a88c 100644 --- a/src/Symfony/Component/Form/composer.json +++ b/src/Symfony/Component/Form/composer.json @@ -17,30 +17,30 @@ ], "require": { "php": "^7.1.3", - "symfony/event-dispatcher": "~2.8|~3.0|~4.0", - "symfony/intl": "^2.8.18|^3.2.5|~4.0", - "symfony/options-resolver": "~2.8|~3.0|~4.0", + "symfony/event-dispatcher": "~3.4|~4.0", + "symfony/intl": "~3.4|~4.0", + "symfony/options-resolver": "~3.4|~4.0", "symfony/polyfill-mbstring": "~1.0", - "symfony/property-access": "~2.8|~3.0|~4.0" + "symfony/property-access": "~3.4|~4.0" }, "require-dev": { "doctrine/collections": "~1.0", - "symfony/validator": "^2.8.18|^3.2.5|~4.0", - "symfony/dependency-injection": "~3.3|~4.0", - "symfony/config": "~2.7|~3.0|~4.0", - "symfony/http-foundation": "~2.8|~3.0|~4.0", - "symfony/http-kernel": "~2.8|~3.0|~4.0", - "symfony/security-csrf": "~2.8|~3.0|~4.0", - "symfony/translation": "~2.8|~3.0|~4.0", - "symfony/var-dumper": "~3.3|~4.0" + "symfony/validator": "~3.4|~4.0", + "symfony/dependency-injection": "~3.4|~4.0", + "symfony/config": "~3.4|~4.0", + "symfony/http-foundation": "~3.4|~4.0", + "symfony/http-kernel": "~3.4|~4.0", + "symfony/security-csrf": "~3.4|~4.0", + "symfony/translation": "~3.4|~4.0", + "symfony/var-dumper": "~3.4|~4.0" }, "conflict": { "phpunit/phpunit": "<4.8.35|<5.4.3,>=5.0", - "symfony/dependency-injection": "<3.3", - "symfony/doctrine-bridge": "<2.7", - "symfony/framework-bundle": "<2.7", - "symfony/twig-bridge": "<2.7", - "symfony/var-dumper": "<3.3" + "symfony/dependency-injection": "<3.4", + "symfony/doctrine-bridge": "<3.4", + "symfony/framework-bundle": "<3.4", + "symfony/twig-bridge": "<3.4", + "symfony/var-dumper": "<3.4" }, "suggest": { "symfony/validator": "For form validation.", diff --git a/src/Symfony/Component/HttpFoundation/composer.json b/src/Symfony/Component/HttpFoundation/composer.json index 4913aa85817a6..fb84f3e9931e9 100644 --- a/src/Symfony/Component/HttpFoundation/composer.json +++ b/src/Symfony/Component/HttpFoundation/composer.json @@ -20,7 +20,7 @@ "symfony/polyfill-mbstring": "~1.1" }, "require-dev": { - "symfony/expression-language": "~2.8|~3.0|~4.0" + "symfony/expression-language": "~3.4|~4.0" }, "autoload": { "psr-4": { "Symfony\\Component\\HttpFoundation\\": "" }, diff --git a/src/Symfony/Component/HttpKernel/composer.json b/src/Symfony/Component/HttpKernel/composer.json index 4a07946c9b7ea..3c2e47b5a613a 100644 --- a/src/Symfony/Component/HttpKernel/composer.json +++ b/src/Symfony/Component/HttpKernel/composer.json @@ -17,37 +17,36 @@ ], "require": { "php": "^7.1.3", - "symfony/event-dispatcher": "~2.8|~3.0|~4.0", - "symfony/http-foundation": "~3.3|~4.0", - "symfony/debug": "~2.8|~3.0|~4.0", + "symfony/event-dispatcher": "~3.4|~4.0", + "symfony/http-foundation": "~3.4|~4.0", + "symfony/debug": "~3.4|~4.0", "psr/log": "~1.0" }, "require-dev": { - "symfony/browser-kit": "~2.8|~3.0|~4.0", - "symfony/class-loader": "~2.8|~3.0|~4.0", - "symfony/config": "~2.8|~3.0|~4.0", - "symfony/console": "~2.8|~3.0|~4.0", - "symfony/css-selector": "~2.8|~3.0|~4.0", - "symfony/dependency-injection": "~3.3|~4.0", - "symfony/dom-crawler": "~2.8|~3.0|~4.0", - "symfony/expression-language": "~2.8|~3.0|~4.0", - "symfony/finder": "~2.8|~3.0|~4.0", - "symfony/process": "~2.8|~3.0|~4.0", - "symfony/routing": "~2.8|~3.0|~4.0", - "symfony/stopwatch": "~2.8|~3.0|~4.0", - "symfony/templating": "~2.8|~3.0|~4.0", - "symfony/translation": "~2.8|~3.0|~4.0", - "symfony/var-dumper": "~3.3|~4.0", + "symfony/browser-kit": "~3.4|~4.0", + "symfony/class-loader": "~3.4|~4.0", + "symfony/config": "~3.4|~4.0", + "symfony/console": "~3.4|~4.0", + "symfony/css-selector": "~3.4|~4.0", + "symfony/dependency-injection": "~3.4|~4.0", + "symfony/dom-crawler": "~3.4|~4.0", + "symfony/expression-language": "~3.4|~4.0", + "symfony/finder": "~3.4|~4.0", + "symfony/process": "~3.4|~4.0", + "symfony/routing": "~3.4|~4.0", + "symfony/stopwatch": "~3.4|~4.0", + "symfony/templating": "~3.4|~4.0", + "symfony/translation": "~3.4|~4.0", + "symfony/var-dumper": "~3.4|~4.0", "psr/cache": "~1.0" }, "conflict": { - "symfony/config": "<2.8", - "symfony/dependency-injection": "<3.3", - "symfony/var-dumper": "<3.3" + "symfony/config": "<3.4", + "symfony/dependency-injection": "<3.4", + "symfony/var-dumper": "<3.4" }, "suggest": { "symfony/browser-kit": "", - "symfony/class-loader": "", "symfony/config": "", "symfony/console": "", "symfony/dependency-injection": "", diff --git a/src/Symfony/Component/Intl/composer.json b/src/Symfony/Component/Intl/composer.json index 7dabd6bf3bc2f..eb1cde0671ee3 100644 --- a/src/Symfony/Component/Intl/composer.json +++ b/src/Symfony/Component/Intl/composer.json @@ -28,7 +28,7 @@ "symfony/polyfill-intl-icu": "~1.0" }, "require-dev": { - "symfony/filesystem": "~2.8|~3.0|~4.0" + "symfony/filesystem": "~3.4|~4.0" }, "suggest": { "ext-intl": "to use the component with locales other than \"en\"" diff --git a/src/Symfony/Component/Ldap/composer.json b/src/Symfony/Component/Ldap/composer.json index d0308feba9e58..9a45391ae6f86 100644 --- a/src/Symfony/Component/Ldap/composer.json +++ b/src/Symfony/Component/Ldap/composer.json @@ -17,7 +17,7 @@ ], "require": { "php": "^7.1.3", - "symfony/options-resolver": "~2.8|~3.0|~4.0", + "symfony/options-resolver": "~3.4|~4.0", "ext-ldap": "*" }, "autoload": { diff --git a/src/Symfony/Component/PropertyAccess/composer.json b/src/Symfony/Component/PropertyAccess/composer.json index 19b02bd730cd1..94a7fd04251c1 100644 --- a/src/Symfony/Component/PropertyAccess/composer.json +++ b/src/Symfony/Component/PropertyAccess/composer.json @@ -17,10 +17,10 @@ ], "require": { "php": "^7.1.3", - "symfony/inflector": "~3.1|~4.0" + "symfony/inflector": "~3.4|~4.0" }, "require-dev": { - "symfony/cache": "~3.1|~4.0" + "symfony/cache": "~3.4|~4.0" }, "suggest": { "psr/cache-implementation": "To cache access methods." diff --git a/src/Symfony/Component/PropertyInfo/composer.json b/src/Symfony/Component/PropertyInfo/composer.json index 8558b506a9d6a..4050c8e1598c8 100644 --- a/src/Symfony/Component/PropertyInfo/composer.json +++ b/src/Symfony/Component/PropertyInfo/composer.json @@ -24,19 +24,19 @@ ], "require": { "php": "^7.1.3", - "symfony/inflector": "~3.1|~4.0" + "symfony/inflector": "~3.4|~4.0" }, "require-dev": { - "symfony/serializer": "~2.8|~3.0|~4.0", - "symfony/cache": "~3.1|~4.0", - "symfony/dependency-injection": "~3.3|~4.0", + "symfony/serializer": "~3.4|~4.0", + "symfony/cache": "~3.4|~4.0", + "symfony/dependency-injection": "~3.4|~4.0", "phpdocumentor/reflection-docblock": "^3.0", "doctrine/annotations": "~1.0" }, "conflict": { "phpdocumentor/reflection-docblock": "<3.0", "phpdocumentor/type-resolver": "<0.2.0", - "symfony/dependency-injection": "<3.3" + "symfony/dependency-injection": "<3.4" }, "suggest": { "psr/cache-implementation": "To cache results", diff --git a/src/Symfony/Component/Routing/composer.json b/src/Symfony/Component/Routing/composer.json index c83761320eba3..dc3d53ca32d04 100644 --- a/src/Symfony/Component/Routing/composer.json +++ b/src/Symfony/Component/Routing/composer.json @@ -19,19 +19,19 @@ "php": "^7.1.3" }, "require-dev": { - "symfony/config": "~2.8|~3.0|~4.0", - "symfony/http-foundation": "~2.8|~3.0|~4.0", - "symfony/yaml": "~3.3|~4.0", - "symfony/expression-language": "~2.8|~3.0|~4.0", - "symfony/dependency-injection": "~3.3|~4.0", + "symfony/config": "~3.4|~4.0", + "symfony/http-foundation": "~3.4|~4.0", + "symfony/yaml": "~3.4|~4.0", + "symfony/expression-language": "~3.4|~4.0", + "symfony/dependency-injection": "~3.4|~4.0", "doctrine/annotations": "~1.0", "doctrine/common": "~2.2", "psr/log": "~1.0" }, "conflict": { - "symfony/config": "<2.8", - "symfony/dependency-injection": "<3.3", - "symfony/yaml": "<3.3" + "symfony/config": "<3.4", + "symfony/dependency-injection": "<3.4", + "symfony/yaml": "<3.4" }, "suggest": { "symfony/http-foundation": "For using a Symfony Request object", diff --git a/src/Symfony/Component/Security/Core/composer.json b/src/Symfony/Component/Security/Core/composer.json index ad3fd1526bdd9..de972a1ddf5f9 100644 --- a/src/Symfony/Component/Security/Core/composer.json +++ b/src/Symfony/Component/Security/Core/composer.json @@ -19,11 +19,11 @@ "php": "^7.1.3" }, "require-dev": { - "symfony/event-dispatcher": "~2.8|~3.0|~4.0", - "symfony/expression-language": "~2.8|~3.0|~4.0", - "symfony/http-foundation": "~2.8|~3.0|~4.0", - "symfony/ldap": "~3.1|~4.0", - "symfony/validator": "^2.8.18|^3.2.5|~4.0", + "symfony/event-dispatcher": "~3.4|~4.0", + "symfony/expression-language": "~3.4|~4.0", + "symfony/http-foundation": "~3.4|~4.0", + "symfony/ldap": "~3.4|~4.0", + "symfony/validator": "~3.4|~4.0", "psr/log": "~1.0" }, "suggest": { diff --git a/src/Symfony/Component/Security/Csrf/composer.json b/src/Symfony/Component/Security/Csrf/composer.json index e1373f8eff21c..ee102a3c1fc49 100644 --- a/src/Symfony/Component/Security/Csrf/composer.json +++ b/src/Symfony/Component/Security/Csrf/composer.json @@ -17,10 +17,10 @@ ], "require": { "php": "^7.1.3", - "symfony/security-core": "~2.8|~3.0|~4.0" + "symfony/security-core": "~3.4|~4.0" }, "require-dev": { - "symfony/http-foundation": "~2.8|~3.0|~4.0" + "symfony/http-foundation": "~3.4|~4.0" }, "suggest": { "symfony/http-foundation": "For using the class SessionTokenStorage." diff --git a/src/Symfony/Component/Security/Guard/composer.json b/src/Symfony/Component/Security/Guard/composer.json index 7d348a7db5940..194eb6cf7e3b2 100644 --- a/src/Symfony/Component/Security/Guard/composer.json +++ b/src/Symfony/Component/Security/Guard/composer.json @@ -17,8 +17,8 @@ ], "require": { "php": "^7.1.3", - "symfony/security-core": "~2.8|~3.0|~4.0", - "symfony/security-http": "~3.1|~4.0" + "symfony/security-core": "~3.4|~4.0", + "symfony/security-http": "~3.4|~4.0" }, "require-dev": { "psr/log": "~1.0" diff --git a/src/Symfony/Component/Security/Http/composer.json b/src/Symfony/Component/Security/Http/composer.json index 655ebfa0e174a..c4b7a605f90a3 100644 --- a/src/Symfony/Component/Security/Http/composer.json +++ b/src/Symfony/Component/Security/Http/composer.json @@ -17,15 +17,15 @@ ], "require": { "php": "^7.1.3", - "symfony/security-core": "~3.2|~4.0", - "symfony/event-dispatcher": "~2.8|~3.0|~4.0", - "symfony/http-foundation": "~2.8|~3.0|~4.0", - "symfony/http-kernel": "~3.3|~4.0", - "symfony/property-access": "~2.8|~3.0|~4.0" + "symfony/security-core": "~3.4|~4.0", + "symfony/event-dispatcher": "~3.4|~4.0", + "symfony/http-foundation": "~3.4|~4.0", + "symfony/http-kernel": "~3.4|~4.0", + "symfony/property-access": "~3.4|~4.0" }, "require-dev": { - "symfony/routing": "~2.8|~3.0|~4.0", - "symfony/security-csrf": "~2.8|~3.0|~4.0", + "symfony/routing": "~3.4|~4.0", + "symfony/security-csrf": "~3.4|~4.0", "psr/log": "~1.0" }, "suggest": { diff --git a/src/Symfony/Component/Security/composer.json b/src/Symfony/Component/Security/composer.json index 75ac0096f38d0..3b2bb564e9ae9 100644 --- a/src/Symfony/Component/Security/composer.json +++ b/src/Symfony/Component/Security/composer.json @@ -17,10 +17,10 @@ ], "require": { "php": "^7.1.3", - "symfony/event-dispatcher": "~2.8|~3.0|~4.0", - "symfony/http-foundation": "~2.8|~3.0|~4.0", - "symfony/http-kernel": "~3.3|~4.0", - "symfony/property-access": "~2.8|~3.0|~4.0" + "symfony/event-dispatcher": "~3.4|~4.0", + "symfony/http-foundation": "~3.4|~4.0", + "symfony/http-kernel": "~3.4|~4.0", + "symfony/property-access": "~3.4|~4.0" }, "replace": { "symfony/security-core": "self.version", @@ -29,12 +29,12 @@ "symfony/security-http": "self.version" }, "require-dev": { - "symfony/finder": "~2.8|~3.0|~4.0", + "symfony/finder": "~3.4|~4.0", "symfony/polyfill-intl-icu": "~1.0", - "symfony/routing": "~2.8|~3.0|~4.0", - "symfony/validator": "^2.8.18|^3.2.5|~4.0", - "symfony/expression-language": "~2.8|~3.0|~4.0", - "symfony/ldap": "~3.1|~4.0", + "symfony/routing": "~3.4|~4.0", + "symfony/validator": "~3.4|~4.0", + "symfony/expression-language": "~3.4|~4.0", + "symfony/ldap": "~3.4|~4.0", "psr/log": "~1.0" }, "suggest": { diff --git a/src/Symfony/Component/Serializer/composer.json b/src/Symfony/Component/Serializer/composer.json index eeb67dce36c78..d7955fcf4cbfc 100644 --- a/src/Symfony/Component/Serializer/composer.json +++ b/src/Symfony/Component/Serializer/composer.json @@ -19,22 +19,22 @@ "php": "^7.1.3" }, "require-dev": { - "symfony/yaml": "~3.3|~4.0", - "symfony/config": "~2.8|~3.0|~4.0", - "symfony/property-access": "~2.8|~3.0|~4.0", - "symfony/http-foundation": "~2.8|~3.0|~4.0", - "symfony/cache": "~3.1|~4.0", - "symfony/property-info": "~3.1|~4.0", + "symfony/yaml": "~3.4|~4.0", + "symfony/config": "~3.4|~4.0", + "symfony/property-access": "~3.4|~4.0", + "symfony/http-foundation": "~3.4|~4.0", + "symfony/cache": "~3.4|~4.0", + "symfony/property-info": "~3.4|~4.0", "doctrine/annotations": "~1.0", - "symfony/dependency-injection": "~3.2|~4.0", + "symfony/dependency-injection": "~3.4|~4.0", "doctrine/cache": "~1.0", "phpdocumentor/reflection-docblock": "~3.0" }, "conflict": { - "symfony/dependency-injection": "<3.2", - "symfony/property-access": ">=3.0,<3.0.4|>=2.8,<2.8.4", - "symfony/property-info": "<3.1", - "symfony/yaml": "<3.3" + "symfony/dependency-injection": "<3.4", + "symfony/property-access": "<3.4", + "symfony/property-info": "<3.4", + "symfony/yaml": "<3.4" }, "suggest": { "psr/cache-implementation": "For using the metadata cache.", diff --git a/src/Symfony/Component/Translation/composer.json b/src/Symfony/Component/Translation/composer.json index e6feb29d09b40..046ca173fa31a 100644 --- a/src/Symfony/Component/Translation/composer.json +++ b/src/Symfony/Component/Translation/composer.json @@ -20,14 +20,14 @@ "symfony/polyfill-mbstring": "~1.0" }, "require-dev": { - "symfony/config": "~2.8|~3.0|~4.0", - "symfony/intl": "^2.8.18|^3.2.5|~4.0", - "symfony/yaml": "~3.3|~4.0", + "symfony/config": "~3.4|~4.0", + "symfony/intl": "~3.4|~4.0", + "symfony/yaml": "~3.4|~4.0", "psr/log": "~1.0" }, "conflict": { - "symfony/config": "<2.8", - "symfony/yaml": "<3.3" + "symfony/config": "<3.4", + "symfony/yaml": "<3.4" }, "suggest": { "symfony/config": "", diff --git a/src/Symfony/Component/Validator/composer.json b/src/Symfony/Component/Validator/composer.json index d934f40e77d3c..a51e9cad1a4d1 100644 --- a/src/Symfony/Component/Validator/composer.json +++ b/src/Symfony/Component/Validator/composer.json @@ -18,24 +18,24 @@ "require": { "php": "^7.1.3", "symfony/polyfill-mbstring": "~1.0", - "symfony/translation": "~2.8|~3.0|~4.0" + "symfony/translation": "~3.4|~4.0" }, "require-dev": { - "symfony/http-foundation": "~2.8|~3.0|~4.0", - "symfony/intl": "^2.8.18|^3.2.5|~4.0", - "symfony/yaml": "~3.3|~4.0", - "symfony/config": "~2.8|~3.0|~4.0", - "symfony/dependency-injection": "~3.3|~4.0", - "symfony/expression-language": "~2.8|~3.0|~4.0", - "symfony/cache": "~3.1|~4.0", + "symfony/http-foundation": "~3.4|~4.0", + "symfony/intl": "~3.4|~4.0", + "symfony/yaml": "~3.4|~4.0", + "symfony/config": "~3.4|~4.0", + "symfony/dependency-injection": "~3.4|~4.0", + "symfony/expression-language": "~3.4|~4.0", + "symfony/cache": "~3.4|~4.0", "doctrine/annotations": "~1.0", "doctrine/cache": "~1.0", "egulias/email-validator": "^1.2.8|~2.0" }, "conflict": { "phpunit/phpunit": "<4.8.35|<5.4.3,>=5.0", - "symfony/dependency-injection": "<3.3", - "symfony/yaml": "<3.3" + "symfony/dependency-injection": "<3.4", + "symfony/yaml": "<3.4" }, "suggest": { "psr/cache-implementation": "For using the metadata cache.", diff --git a/src/Symfony/Component/WebLink/composer.json b/src/Symfony/Component/WebLink/composer.json index 0b15ffd27f673..d1be20177d6bd 100644 --- a/src/Symfony/Component/WebLink/composer.json +++ b/src/Symfony/Component/WebLink/composer.json @@ -24,9 +24,9 @@ "symfony/http-kernel": "" }, "require-dev": { - "symfony/event-dispatcher": "^2.8|^3.0|~4.0", - "symfony/http-foundation": "^2.8|^3.0|~4.0", - "symfony/http-kernel": "^2.8|^3.0|~4.0" + "symfony/event-dispatcher": "~3.4|~4.0", + "symfony/http-foundation": "~3.4|~4.0", + "symfony/http-kernel": "~3.4|~4.0" }, "autoload": { "psr-4": { "Symfony\\Component\\WebLink\\": "" }, diff --git a/src/Symfony/Component/Workflow/composer.json b/src/Symfony/Component/Workflow/composer.json index a3c0fd5f71209..0c78dcd5a8a52 100644 --- a/src/Symfony/Component/Workflow/composer.json +++ b/src/Symfony/Component/Workflow/composer.json @@ -21,14 +21,14 @@ ], "require": { "php": "^7.1.3", - "symfony/property-access": "~2.3|~3.0|~4.0" + "symfony/property-access": "~3.4|~4.0" }, "require-dev": { "psr/log": "~1.0", - "symfony/dependency-injection": "~2.8|~3.0|~4.0", - "symfony/event-dispatcher": "~2.1|~3.0|~4.0", - "symfony/expression-language": "~2.8|~3.0|~4.0", - "symfony/security-core": "~2.8|~3.0|~4.0" + "symfony/dependency-injection": "~3.4|~4.0", + "symfony/event-dispatcher": "~3.4|~4.0", + "symfony/expression-language": "~3.4|~4.0", + "symfony/security-core": "~3.4|~4.0" }, "autoload": { "psr-4": { "Symfony\\Component\\Workflow\\": "" } diff --git a/src/Symfony/Component/Yaml/composer.json b/src/Symfony/Component/Yaml/composer.json index ec58648572f49..bbf84393497c9 100644 --- a/src/Symfony/Component/Yaml/composer.json +++ b/src/Symfony/Component/Yaml/composer.json @@ -19,7 +19,7 @@ "php": "^7.1.3" }, "require-dev": { - "symfony/console": "~2.8|~3.0|~4.0" + "symfony/console": "~3.4|~4.0" }, "suggest": { "symfony/console": "For validating YAML files using the lint command" From be951b7096ff7b9240c080cd8826062f897a4e97 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Thu, 18 May 2017 08:13:03 +0200 Subject: [PATCH 0012/1099] [Serializer] Remove deprecated DoctrineCache support --- .../Mapping/Factory/ClassMetadataFactory.php | 22 +------------ .../Factory/ClassMetadataFactoryTest.php | 31 ------------------- 2 files changed, 1 insertion(+), 52 deletions(-) diff --git a/src/Symfony/Component/Serializer/Mapping/Factory/ClassMetadataFactory.php b/src/Symfony/Component/Serializer/Mapping/Factory/ClassMetadataFactory.php index 6604430d190b8..448e61a6b6342 100644 --- a/src/Symfony/Component/Serializer/Mapping/Factory/ClassMetadataFactory.php +++ b/src/Symfony/Component/Serializer/Mapping/Factory/ClassMetadataFactory.php @@ -11,7 +11,6 @@ namespace Symfony\Component\Serializer\Mapping\Factory; -use Doctrine\Common\Cache\Cache; use Symfony\Component\Serializer\Exception\InvalidArgumentException; use Symfony\Component\Serializer\Mapping\ClassMetadata; use Symfony\Component\Serializer\Mapping\Loader\LoaderInterface; @@ -30,11 +29,6 @@ class ClassMetadataFactory implements ClassMetadataFactoryInterface */ private $loader; - /** - * @var Cache - */ - private $cache; - /** * @var array */ @@ -42,16 +36,10 @@ class ClassMetadataFactory implements ClassMetadataFactoryInterface /** * @param LoaderInterface $loader - * @param Cache|null $cache */ - public function __construct(LoaderInterface $loader, Cache $cache = null) + public function __construct(LoaderInterface $loader) { $this->loader = $loader; - $this->cache = $cache; - - if (null !== $cache) { - @trigger_error(sprintf('Passing a Doctrine Cache instance as 2nd parameter of the "%s" constructor is deprecated since version 3.1. This parameter will be removed in Symfony 4.0. Use the "%s" class instead.', __CLASS__, CacheClassMetadataFactory::class), E_USER_DEPRECATED); - } } /** @@ -65,10 +53,6 @@ public function getMetadataFor($value) return $this->loadedClasses[$class]; } - if ($this->cache && ($this->loadedClasses[$class] = $this->cache->fetch($class))) { - return $this->loadedClasses[$class]; - } - $classMetadata = new ClassMetadata($class); $this->loader->loadClassMetadata($classMetadata); @@ -84,10 +68,6 @@ public function getMetadataFor($value) $classMetadata->merge($this->getMetadataFor($interface->name)); } - if ($this->cache) { - $this->cache->save($class, $classMetadata); - } - return $this->loadedClasses[$class] = $classMetadata; } diff --git a/src/Symfony/Component/Serializer/Tests/Mapping/Factory/ClassMetadataFactoryTest.php b/src/Symfony/Component/Serializer/Tests/Mapping/Factory/ClassMetadataFactoryTest.php index 903cc04d1f49f..15aa621c298cd 100644 --- a/src/Symfony/Component/Serializer/Tests/Mapping/Factory/ClassMetadataFactoryTest.php +++ b/src/Symfony/Component/Serializer/Tests/Mapping/Factory/ClassMetadataFactoryTest.php @@ -45,35 +45,4 @@ public function testHasMetadataFor() $this->assertTrue($factory->hasMetadataFor('Symfony\Component\Serializer\Tests\Fixtures\GroupDummyInterface')); $this->assertFalse($factory->hasMetadataFor('Dunglas\Entity')); } - - /** - * @group legacy - */ - public function testCacheExists() - { - $cache = $this->getMockBuilder('Doctrine\Common\Cache\Cache')->getMock(); - $cache - ->expects($this->once()) - ->method('fetch') - ->will($this->returnValue('foo')) - ; - - $factory = new ClassMetadataFactory(new AnnotationLoader(new AnnotationReader()), $cache); - $this->assertEquals('foo', $factory->getMetadataFor('Symfony\Component\Serializer\Tests\Fixtures\GroupDummy')); - } - - /** - * @group legacy - */ - public function testCacheNotExists() - { - $cache = $this->getMockBuilder('Doctrine\Common\Cache\Cache')->getMock(); - $cache->method('fetch')->will($this->returnValue(false)); - $cache->method('save'); - - $factory = new ClassMetadataFactory(new AnnotationLoader(new AnnotationReader()), $cache); - $metadata = $factory->getMetadataFor('Symfony\Component\Serializer\Tests\Fixtures\GroupDummy'); - - $this->assertEquals(TestClassMetadataFactory::createClassMetadata(true, true), $metadata); - } } From 6425f8551a1c2f6a5967fb99a23b2cc2b00b3e4b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Thu, 18 May 2017 08:57:19 +0200 Subject: [PATCH 0013/1099] [Serializer] Remove a now useless call to method_exists --- .../Component/Serializer/Normalizer/AbstractNormalizer.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/Serializer/Normalizer/AbstractNormalizer.php b/src/Symfony/Component/Serializer/Normalizer/AbstractNormalizer.php index db55db06dea56..e4b764fbaf659 100644 --- a/src/Symfony/Component/Serializer/Normalizer/AbstractNormalizer.php +++ b/src/Symfony/Component/Serializer/Normalizer/AbstractNormalizer.php @@ -339,7 +339,7 @@ protected function instantiateObject(array &$data, $class, array &$context, \Ref $allowed = $allowedAttributes === false || in_array($paramName, $allowedAttributes); $ignored = !$this->isAllowedAttribute($class, $paramName, $format, $context); - if (method_exists($constructorParameter, 'isVariadic') && $constructorParameter->isVariadic()) { + if ($constructorParameter->isVariadic()) { if ($allowed && !$ignored && (isset($data[$key]) || array_key_exists($key, $data))) { if (!is_array($data[$paramName])) { throw new RuntimeException(sprintf('Cannot create an instance of %s from serialized data because the variadic parameter %s can only accept an array.', $class, $constructorParameter->name)); From b346e48adf7ba37d873f0335ab4a1672a7963423 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Thu, 18 May 2017 09:02:00 +0200 Subject: [PATCH 0014/1099] [PropertyInfo] Remove dead code with PHP 7+ --- .../Extractor/ReflectionExtractor.php | 33 ++++--------------- 1 file changed, 7 insertions(+), 26 deletions(-) diff --git a/src/Symfony/Component/PropertyInfo/Extractor/ReflectionExtractor.php b/src/Symfony/Component/PropertyInfo/Extractor/ReflectionExtractor.php index 228aa583e8feb..0d67b07611401 100644 --- a/src/Symfony/Component/PropertyInfo/Extractor/ReflectionExtractor.php +++ b/src/Symfony/Component/PropertyInfo/Extractor/ReflectionExtractor.php @@ -47,13 +47,6 @@ class ReflectionExtractor implements PropertyListExtractorInterface, PropertyTyp */ public static $arrayMutatorPrefixes = array('add', 'remove'); - private $supportsParameterType; - - public function __construct() - { - $this->supportsParameterType = method_exists('ReflectionParameter', 'getType'); - } - /** * {@inheritdoc} */ @@ -152,25 +145,13 @@ private function extractFromMutator($class, $property) $reflectionParameters = $reflectionMethod->getParameters(); $reflectionParameter = $reflectionParameters[0]; - if ($this->supportsParameterType) { - if (!$reflectionType = $reflectionParameter->getType()) { - return; - } - $type = $this->extractFromReflectionType($reflectionType); + if (!$reflectionType = $reflectionParameter->getType()) { + return; + } + $type = $this->extractFromReflectionType($reflectionType); - // HHVM reports variadics with "array" but not builtin type hints - if (!$reflectionType->isBuiltin() && Type::BUILTIN_TYPE_ARRAY === $type->getBuiltinType()) { - return; - } - } elseif (preg_match('/^(?:[^ ]++ ){4}([a-zA-Z_\x7F-\xFF][^ ]++)/', $reflectionParameter, $info)) { - if (Type::BUILTIN_TYPE_ARRAY === $info[1]) { - $type = new Type(Type::BUILTIN_TYPE_ARRAY, $reflectionParameter->allowsNull(), null, true); - } elseif (Type::BUILTIN_TYPE_CALLABLE === $info[1]) { - $type = new Type(Type::BUILTIN_TYPE_CALLABLE, $reflectionParameter->allowsNull()); - } else { - $type = new Type(Type::BUILTIN_TYPE_OBJECT, $reflectionParameter->allowsNull(), $info[1]); - } - } else { + // HHVM reports variadics with "array" but not builtin type hints + if (!$reflectionType->isBuiltin() && Type::BUILTIN_TYPE_ARRAY === $type->getBuiltinType()) { return; } @@ -196,7 +177,7 @@ private function extractFromAccessor($class, $property) return; } - if ($this->supportsParameterType && $reflectionType = $reflectionMethod->getReturnType()) { + if ($reflectionType = $reflectionMethod->getReturnType()) { return array($this->extractFromReflectionType($reflectionType)); } From 372e96e157e282e84dada0430c02dc5a76c2d9cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Thu, 18 May 2017 09:09:34 +0200 Subject: [PATCH 0015/1099] [DependencyInjection] Remove dead code with PHP 7+ --- .../DependencyInjection/Compiler/AutowirePass.php | 5 ++--- .../Compiler/FactoryReturnTypePass.php | 4 ---- .../DependencyInjection/LazyProxy/ProxyHelper.php | 14 +++----------- .../Tests/Compiler/FactoryReturnTypePassTest.php | 15 +++------------ 4 files changed, 8 insertions(+), 30 deletions(-) diff --git a/src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php b/src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php index 0a6a0dfc1b6b3..07ecdcb340137 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php @@ -250,7 +250,7 @@ private function autowireMethod(\ReflectionFunctionAbstract $reflectionMethod, a $class = $reflectionMethod instanceof \ReflectionMethod ? $reflectionMethod->class : $this->currentId; $method = $reflectionMethod->name; $parameters = $reflectionMethod->getParameters(); - if (method_exists('ReflectionMethod', 'isVariadic') && $reflectionMethod->isVariadic()) { + if ($reflectionMethod->isVariadic()) { array_pop($parameters); } @@ -533,11 +533,10 @@ private static function getResourceMetadataForMethod(\ReflectionMethod $method) $class = false; } - $isVariadic = method_exists($parameter, 'isVariadic') && $parameter->isVariadic(); $methodArgumentsMetadata[] = array( 'class' => $class, 'isOptional' => $parameter->isOptional(), - 'defaultValue' => ($parameter->isOptional() && !$isVariadic) ? $parameter->getDefaultValue() : null, + 'defaultValue' => ($parameter->isOptional() && !$parameter->isVariadic()) ? $parameter->getDefaultValue() : null, ); } diff --git a/src/Symfony/Component/DependencyInjection/Compiler/FactoryReturnTypePass.php b/src/Symfony/Component/DependencyInjection/Compiler/FactoryReturnTypePass.php index 3ba4a8caa02f2..84f9c6bc16e49 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/FactoryReturnTypePass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/FactoryReturnTypePass.php @@ -37,10 +37,6 @@ public function __construct(ResolveClassPass $resolveClassPass = null) */ public function process(ContainerBuilder $container) { - // works only since php 7.0 and hhvm 3.11 - if (!method_exists(\ReflectionMethod::class, 'getReturnType')) { - return; - } $resolveClassPassChanges = null !== $this->resolveClassPass ? $this->resolveClassPass->getChanges() : array(); foreach ($container->getDefinitions() as $id => $definition) { diff --git a/src/Symfony/Component/DependencyInjection/LazyProxy/ProxyHelper.php b/src/Symfony/Component/DependencyInjection/LazyProxy/ProxyHelper.php index 5f0c8772fef43..b6115ea7dc84c 100644 --- a/src/Symfony/Component/DependencyInjection/LazyProxy/ProxyHelper.php +++ b/src/Symfony/Component/DependencyInjection/LazyProxy/ProxyHelper.php @@ -28,7 +28,7 @@ public static function getSignature(\ReflectionFunctionAbstract $r, &$call = nul foreach ($r->getParameters() as $i => $p) { $k = '$'.$p->name; - if (method_exists($p, 'isVariadic') && $p->isVariadic()) { + if ($p->isVariadic()) { $k = '...'.$k; } $call[] = $k; @@ -72,17 +72,9 @@ public static function getSignature(\ReflectionFunctionAbstract $r, &$call = nul public static function getTypeHint(\ReflectionFunctionAbstract $r, \ReflectionParameter $p = null, $noBuiltin = false) { if ($p instanceof \ReflectionParameter) { - if (method_exists($p, 'getType')) { - $type = $p->getType(); - } elseif (preg_match('/^(?:[^ ]++ ){4}([a-zA-Z_\x7F-\xFF][^ ]++)/', $p, $type)) { - $name = $type = $type[1]; - - if ('callable' === $name || 'array' === $name) { - return $noBuiltin ? null : $name; - } - } + $type = $p->getType(); } else { - $type = method_exists($r, 'getReturnType') ? $r->getReturnType() : null; + $type = $r->getReturnType(); } if (!$type) { return; diff --git a/src/Symfony/Component/DependencyInjection/Tests/Compiler/FactoryReturnTypePassTest.php b/src/Symfony/Component/DependencyInjection/Tests/Compiler/FactoryReturnTypePassTest.php index f299463d5f44a..5d5f5339be22d 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Compiler/FactoryReturnTypePassTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Compiler/FactoryReturnTypePassTest.php @@ -44,13 +44,8 @@ public function testProcess() $pass = new FactoryReturnTypePass(); $pass->process($container); - if (method_exists(\ReflectionMethod::class, 'getReturnType')) { - $this->assertEquals(FactoryDummy::class, $factory->getClass()); - $this->assertEquals(\stdClass::class, $foo->getClass()); - } else { - $this->assertNull($factory->getClass()); - $this->assertNull($foo->getClass()); - } + $this->assertEquals(FactoryDummy::class, $factory->getClass()); + $this->assertEquals(\stdClass::class, $foo->getClass()); $this->assertEquals(__CLASS__, $bar->getClass()); } @@ -71,11 +66,7 @@ public function testReturnTypes($factory, $returnType, $hhvmSupport = true) $pass = new FactoryReturnTypePass(); $pass->process($container); - if (method_exists(\ReflectionMethod::class, 'getReturnType')) { - $this->assertEquals($returnType, $service->getClass()); - } else { - $this->assertNull($service->getClass()); - } + $this->assertEquals($returnType, $service->getClass()); } public function returnTypesProvider() From 854efce7cacfa299a1f09a9878c2d845b02703cb Mon Sep 17 00:00:00 2001 From: Hugo Hamon Date: Thu, 18 May 2017 10:14:39 +0200 Subject: [PATCH 0016/1099] [DependencyInjection] remove deprecated YAML configuration features and syntax --- .../Loader/YamlFileLoader.php | 18 ++++--------- .../Tests/Fixtures/yaml/bad_alias.yml | 11 ++++++++ ...invalid_definition.yml => bad_keyword.yml} | 0 .../Tests/Loader/YamlFileLoaderTest.php | 26 +++++++++++++++++-- 4 files changed, 40 insertions(+), 15 deletions(-) create mode 100644 src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/bad_alias.yml rename src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/{legacy_invalid_definition.yml => bad_keyword.yml} (100%) diff --git a/src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php b/src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php index c3e697c1b5207..19d919f2eda0e 100644 --- a/src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php +++ b/src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php @@ -315,8 +315,9 @@ private function isUsingShortSyntax(array $service) private function parseDefinition($id, $service, $file, array $defaults) { if (preg_match('/^_[a-zA-Z0-9_]*$/', $id)) { - @trigger_error(sprintf('Service names that start with an underscore are deprecated since Symfony 3.3 and will be reserved in 4.0. Rename the "%s" service or define it in XML instead.', $id), E_USER_DEPRECATED); + throw new InvalidArgumentException(sprintf('Service names that start with an underscore are reserved. Rename the "%s" service or define it in XML instead.', $id)); } + if (is_string($service) && 0 === strpos($service, '@')) { $public = isset($defaults['public']) ? $defaults['public'] : true; $this->container->setAlias($id, new Alias(substr($service, 1), $public)); @@ -344,7 +345,7 @@ private function parseDefinition($id, $service, $file, array $defaults) foreach ($service as $key => $value) { if (!in_array($key, array('alias', 'public'))) { - @trigger_error(sprintf('The configuration key "%s" is unsupported for the service "%s" which is defined as an alias in "%s". Allowed configuration keys for service aliases are "alias" and "public". The YamlFileLoader will raise an exception in Symfony 4.0, instead of silently ignoring unsupported attributes.', $key, $id, $file), E_USER_DEPRECATED); + throw new InvalidArgumentException(sprintf('The configuration key "%s" is unsupported for the service "%s" which is defined as an alias in "%s". Allowed configuration keys for service aliases are "alias" and "public".', $key, $id, $file)); } } @@ -740,11 +741,6 @@ private function resolveServices($value, $file, $isParameter = false) $invalidBehavior = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE; } - if ('=' === substr($value, -1)) { - @trigger_error(sprintf('The "=" suffix that used to disable strict references in Symfony 2.x is deprecated since 3.3 and will be unsupported in 4.0. Remove it in "%s".', $value), E_USER_DEPRECATED); - $value = substr($value, 0, -1); - } - if (null !== $invalidBehavior) { $value = new Reference($value, $invalidBehavior); } @@ -782,7 +778,7 @@ private function loadFromExtensions(array $content) */ private function checkDefinition($id, array $definition, $file) { - if ($throw = $this->isLoadingInstanceof) { + if ($this->isLoadingInstanceof) { $keywords = self::$instanceofKeywords; } elseif ($throw = isset($definition['resource'])) { $keywords = self::$prototypeKeywords; @@ -792,11 +788,7 @@ private function checkDefinition($id, array $definition, $file) foreach ($definition as $key => $value) { if (!isset($keywords[$key])) { - if ($throw) { - throw new InvalidArgumentException(sprintf('The configuration key "%s" is unsupported for definition "%s" in "%s". Allowed configuration keys are "%s".', $key, $id, $file, implode('", "', $keywords))); - } - - @trigger_error(sprintf('The configuration key "%s" is unsupported for service definition "%s" in "%s". Allowed configuration keys are "%s". The YamlFileLoader object will raise an exception instead in Symfony 4.0 when detecting an unsupported service configuration key.', $key, $id, $file, implode('", "', $keywords)), E_USER_DEPRECATED); + throw new InvalidArgumentException(sprintf('The configuration key "%s" is unsupported for definition "%s" in "%s". Allowed configuration keys are "%s".', $key, $id, $file, implode('", "', $keywords))); } } } diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/bad_alias.yml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/bad_alias.yml new file mode 100644 index 0000000000000..78975e5092866 --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/bad_alias.yml @@ -0,0 +1,11 @@ +services: + foo: + class: stdClass + public: false + + bar: + alias: foo + public: true + # keys other than "alias" and "public" are invalid when defining an alias. + calls: + - [doSomething] diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/legacy_invalid_definition.yml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/bad_keyword.yml similarity index 100% rename from src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/legacy_invalid_definition.yml rename to src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/bad_keyword.yml diff --git a/src/Symfony/Component/DependencyInjection/Tests/Loader/YamlFileLoaderTest.php b/src/Symfony/Component/DependencyInjection/Tests/Loader/YamlFileLoaderTest.php index 8de64d55f4486..037af216157c0 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Loader/YamlFileLoaderTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Loader/YamlFileLoaderTest.php @@ -510,8 +510,8 @@ public function testInvalidTagsWithDefaults() } /** - * @group legacy - * @expectedDeprecation Service names that start with an underscore are deprecated since Symfony 3.3 and will be reserved in 4.0. Rename the "_foo" service or define it in XML instead. + * @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException + * @expectedExceptionMessage Service names that start with an underscore are reserved. Rename the "_foo" service or define it in XML instead. */ public function testUnderscoreServiceId() { @@ -633,6 +633,28 @@ public function testEmptyInstanceofThrowsClearException() $loader = new YamlFileLoader($container, new FileLocator(self::$fixturesPath.'/yaml')); $loader->load('bad_empty_instanceof.yml'); } + + /** + * @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException + * @expectedExceptionMessageRegExp /^The configuration key "private" is unsupported for definition "bar"/ + */ + public function testUnsupportedKeywordThrowsException() + { + $container = new ContainerBuilder(); + $loader = new YamlFileLoader($container, new FileLocator(self::$fixturesPath.'/yaml')); + $loader->load('bad_keyword.yml'); + } + + /** + * @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException + * @expectedExceptionMessageRegExp /^The configuration key "calls" is unsupported for the service "bar" which is defined as an alias/ + */ + public function testUnsupportedKeywordInServiceAliasThrowsException() + { + $container = new ContainerBuilder(); + $loader = new YamlFileLoader($container, new FileLocator(self::$fixturesPath.'/yaml')); + $loader->load('bad_alias.yml'); + } } interface FooInterface From 9f14d06c11c2d3fc3028d354be99dcf9d7df139b Mon Sep 17 00:00:00 2001 From: Hugo Hamon Date: Fri, 19 May 2017 11:53:46 +0200 Subject: [PATCH 0017/1099] [FrameworkBundle] add forward compatibility layer when using FrameworkBundle in version 3.4 with DependencyInjection component in version 4.0 --- .../FrameworkBundle/Console/Descriptor/JsonDescriptor.php | 7 +++++-- .../Console/Descriptor/MarkdownDescriptor.php | 7 +++++-- .../FrameworkBundle/Console/Descriptor/TextDescriptor.php | 3 ++- 3 files changed, 12 insertions(+), 5 deletions(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/JsonDescriptor.php b/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/JsonDescriptor.php index d49c57adfec2e..31ca3a9aafc05 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/JsonDescriptor.php +++ b/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/JsonDescriptor.php @@ -231,8 +231,11 @@ private function getContainerDefinitionData(Definition $definition, $omitTags = 'autoconfigure' => $definition->isAutoconfigured(), ); - foreach ($definition->getAutowiringTypes(false) as $autowiringType) { - $data['autowiring_types'][] = $autowiringType; + // forward compatibility with DependencyInjection component in version 4.0 + if (method_exists($definition, 'getAutowiringTypes')) { + foreach ($definition->getAutowiringTypes(false) as $autowiringType) { + $data['autowiring_types'][] = $autowiringType; + } } if ($showArguments) { diff --git a/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/MarkdownDescriptor.php b/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/MarkdownDescriptor.php index 59e382d3a9cad..5703c108bccd3 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/MarkdownDescriptor.php +++ b/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/MarkdownDescriptor.php @@ -191,8 +191,11 @@ protected function describeContainerDefinition(Definition $definition, array $op ."\n".'- Autoconfigured: '.($definition->isAutoconfigured() ? 'yes' : 'no') ; - foreach ($definition->getAutowiringTypes(false) as $autowiringType) { - $output .= "\n".'- Autowiring Type: `'.$autowiringType.'`'; + // forward compatibility with DependencyInjection component in version 4.0 + if (method_exists($definition, 'getAutowiringTypes')) { + foreach ($definition->getAutowiringTypes(false) as $autowiringType) { + $output .= "\n".'- Autowiring Type: `'.$autowiringType.'`'; + } } if (isset($options['show_arguments']) && $options['show_arguments']) { diff --git a/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/TextDescriptor.php b/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/TextDescriptor.php index 64c38cdff759f..0abe5e8e398f8 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/TextDescriptor.php +++ b/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/TextDescriptor.php @@ -309,7 +309,8 @@ protected function describeContainerDefinition(Definition $definition, array $op $tableRows[] = array('Autowired', $definition->isAutowired() ? 'yes' : 'no'); $tableRows[] = array('Autoconfigured', $definition->isAutoconfigured() ? 'yes' : 'no'); - if ($autowiringTypes = $definition->getAutowiringTypes(false)) { + // forward compatibility with DependencyInjection component in version 4.0 + if (method_exists($definition, 'getAutowiringTypes') && $autowiringTypes = $definition->getAutowiringTypes(false)) { $tableRows[] = array('Autowiring Types', implode(', ', $autowiringTypes)); } From 1ccbe0bae25f91efe40815bef469c04c227850ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9goire=20Pineau?= Date: Fri, 19 May 2017 10:19:00 +0200 Subject: [PATCH 0018/1099] [Workflow] Removed class name support in `WorkflowRegistry::add()` as second parameter --- src/Symfony/Component/Workflow/CHANGELOG.md | 5 ++++ src/Symfony/Component/Workflow/Registry.php | 11 ++++----- .../Component/Workflow/Tests/RegistryTest.php | 23 ------------------- 3 files changed, 9 insertions(+), 30 deletions(-) diff --git a/src/Symfony/Component/Workflow/CHANGELOG.md b/src/Symfony/Component/Workflow/CHANGELOG.md index 51a52777dfa8e..f423bb25b9c00 100644 --- a/src/Symfony/Component/Workflow/CHANGELOG.md +++ b/src/Symfony/Component/Workflow/CHANGELOG.md @@ -1,6 +1,11 @@ CHANGELOG ========= +4.0.0 +----- + + * Removed class name support in `WorkflowRegistry::add()` as second parameter. + 3.3.0 ----- diff --git a/src/Symfony/Component/Workflow/Registry.php b/src/Symfony/Component/Workflow/Registry.php index 4bc806d200ba0..b10af2fbbc0a4 100644 --- a/src/Symfony/Component/Workflow/Registry.php +++ b/src/Symfony/Component/Workflow/Registry.php @@ -12,7 +12,6 @@ namespace Symfony\Component\Workflow; use Symfony\Component\Workflow\Exception\InvalidArgumentException; -use Symfony\Component\Workflow\SupportStrategy\ClassInstanceSupportStrategy; use Symfony\Component\Workflow\SupportStrategy\SupportStrategyInterface; /** @@ -24,15 +23,13 @@ class Registry private $workflows = array(); /** - * @param Workflow $workflow - * @param string|SupportStrategyInterface $supportStrategy + * @param Workflow $workflow + * @param SupportStrategyInterface $supportStrategy */ public function add(Workflow $workflow, $supportStrategy) { if (!$supportStrategy instanceof SupportStrategyInterface) { - @trigger_error('Support of class name string was deprecated after version 3.2 and won\'t work anymore in 4.0.', E_USER_DEPRECATED); - - $supportStrategy = new ClassInstanceSupportStrategy($supportStrategy); + throw new \InvalidArgumentException('The "supportStrategy" is not an instance of SupportStrategyInterface.'); } $this->workflows[] = array($workflow, $supportStrategy); @@ -64,7 +61,7 @@ public function get($subject, $workflowName = null) return $matched; } - private function supports(Workflow $workflow, $supportStrategy, $subject, $workflowName) + private function supports(Workflow $workflow, SupportStrategyInterface $supportStrategy, $subject, $workflowName) { if (null !== $workflowName && $workflowName !== $workflow->getName()) { return false; diff --git a/src/Symfony/Component/Workflow/Tests/RegistryTest.php b/src/Symfony/Component/Workflow/Tests/RegistryTest.php index 262e7cfe59ddf..a85dd74a732ff 100644 --- a/src/Symfony/Component/Workflow/Tests/RegistryTest.php +++ b/src/Symfony/Component/Workflow/Tests/RegistryTest.php @@ -65,29 +65,6 @@ public function testGetWithNoMatch() $this->assertSame('workflow1', $w1->getName()); } - /** - * @group legacy - */ - public function testGetWithSuccessLegacyStrategy() - { - $registry = new Registry(); - - $registry->add(new Workflow(new Definition(array(), array()), $this->getMockBuilder(MarkingStoreInterface::class)->getMock(), $this->getMockBuilder(EventDispatcherInterface::class)->getMock(), 'workflow1'), Subject1::class); - $registry->add(new Workflow(new Definition(array(), array()), $this->getMockBuilder(MarkingStoreInterface::class)->getMock(), $this->getMockBuilder(EventDispatcherInterface::class)->getMock(), 'workflow2'), Subject2::class); - - $workflow = $registry->get(new Subject1()); - $this->assertInstanceOf(Workflow::class, $workflow); - $this->assertSame('workflow1', $workflow->getName()); - - $workflow = $registry->get(new Subject1(), 'workflow1'); - $this->assertInstanceOf(Workflow::class, $workflow); - $this->assertSame('workflow1', $workflow->getName()); - - $workflow = $registry->get(new Subject2(), 'workflow2'); - $this->assertInstanceOf(Workflow::class, $workflow); - $this->assertSame('workflow2', $workflow->getName()); - } - private function createSupportStrategy($supportedClassName) { $strategy = $this->getMockBuilder(SupportStrategyInterface::class)->getMock(); From fd2577755d74338fb726b032c902f3f141896ac7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9goire=20Pineau?= Date: Fri, 19 May 2017 10:27:02 +0200 Subject: [PATCH 0019/1099] [Workflow] Removed FrameworkBundle/DependencyInjection/Compiler/ValidateWorkflowsPass --- .../Bundle/FrameworkBundle/CHANGELOG.md | 7 +++++- .../Compiler/ValidateWorkflowsPass.php | 25 ------------------- 2 files changed, 6 insertions(+), 26 deletions(-) delete mode 100644 src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/ValidateWorkflowsPass.php diff --git a/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md b/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md index df80163243c1c..c96f475abcd11 100644 --- a/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md +++ b/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md @@ -1,6 +1,11 @@ CHANGELOG ========= +4.0.0 +----- + +* Removed `ValidateWorkflowsPass` + 3.3.0 ----- @@ -47,7 +52,7 @@ CHANGELOG `Symfony\Component\Validator\DependencyInjection\AddValidatorInitializersPass` instead * Deprecated `AddConstraintValidatorsPass`, use `Symfony\Component\Validator\DependencyInjection\AddConstraintValidatorsPass` instead - * Deprecated `ValidateWorkflowsPass`, use + * Deprecated `ValidateWorkflowsPass`, use `Symfony\Component\Workflow\DependencyInjection\ValidateWorkflowsPass` instead 3.2.0 diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/ValidateWorkflowsPass.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/ValidateWorkflowsPass.php deleted file mode 100644 index 6599f1f1a0300..0000000000000 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/ValidateWorkflowsPass.php +++ /dev/null @@ -1,25 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler; - -use Symfony\Component\Workflow\DependencyInjection\ValidateWorkflowsPass as BaseValidateWorkflowsPass; - -@trigger_error(sprintf('The %s class is deprecated since version 3.3 and will be removed in 4.0. Use %s instead.', ValidateWorkflowsPass::class, BaseValidateWorkflowsPass::class), E_USER_DEPRECATED); - -/** - * @author Tobias Nyholm - * - * @deprecated since version 3.3, to be removed in 4.0. Use {@link BaseValidateWorkflowsPass} instead - */ -class ValidateWorkflowsPass extends BaseValidateWorkflowsPass -{ -} From 3bed8f61676c47a0e430c2346482a5d33c30b3e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9goire=20Pineau?= Date: Fri, 19 May 2017 10:31:21 +0200 Subject: [PATCH 0020/1099] [Workflow] The `type` option of the `framework.workflows.*` configuration entries is `state_machine` --- .../Bundle/FrameworkBundle/CHANGELOG.md | 3 ++- .../DependencyInjection/Configuration.php | 1 + .../FrameworkExtension.php | 4 --- .../Fixtures/php/workflows.php | 1 - .../Fixtures/php/workflows_without_type.php | 26 ------------------- .../Fixtures/xml/workflows.xml | 2 +- .../Fixtures/xml/workflows_without_type.xml | 21 --------------- .../Fixtures/yml/workflows.yml | 1 - .../Fixtures/yml/workflows_without_type.yml | 7 ----- .../FrameworkExtensionTest.php | 19 +++++--------- 10 files changed, 10 insertions(+), 75 deletions(-) delete mode 100644 src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/workflows_without_type.php delete mode 100644 src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/workflows_without_type.xml delete mode 100644 src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/workflows_without_type.yml diff --git a/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md b/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md index c96f475abcd11..fbc42260fb67d 100644 --- a/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md +++ b/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md @@ -4,7 +4,8 @@ CHANGELOG 4.0.0 ----- -* Removed `ValidateWorkflowsPass` + * Removed `ValidateWorkflowsPass` + * The default `type` option of the `framework.workflows.*` configuration entries is `state_machine` 3.3.0 ----- diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php index 87d722b91e4d6..9d09599d811ee 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php @@ -230,6 +230,7 @@ private function addWorkflowSection(ArrayNodeDefinition $rootNode) ->end() ->enumNode('type') ->values(array('workflow', 'state_machine')) + ->defaultValue('state_machine') ->end() ->arrayNode('marking_store') ->fixXmlConfig('argument') diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php index c65c1f8e740be..d9af9339e3d28 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php @@ -498,10 +498,6 @@ private function registerWorkflowConfiguration(array $workflows, ContainerBuilde $registryDefinition = $container->getDefinition('workflow.registry'); foreach ($workflows as $name => $workflow) { - if (!array_key_exists('type', $workflow)) { - $workflow['type'] = 'workflow'; - @trigger_error(sprintf('The "type" option of the "framework.workflows.%s" configuration entry must be defined since Symfony 3.3. The default value will be "state_machine" in Symfony 4.0.', $name), E_USER_DEPRECATED); - } $type = $workflow['type']; $transitions = array(); diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/workflows.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/workflows.php index c527606561ee9..3d3f4266b7eb5 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/workflows.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/workflows.php @@ -41,7 +41,6 @@ ), ), 'pull_request' => array( - 'type' => 'state_machine', 'marking_store' => array( 'type' => 'single_state', ), diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/workflows_without_type.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/workflows_without_type.php deleted file mode 100644 index 63e83170fca52..0000000000000 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/workflows_without_type.php +++ /dev/null @@ -1,26 +0,0 @@ -loadFromExtension('framework', array( - 'workflows' => array( - 'missing_type' => array( - 'marking_store' => array( - 'service' => 'workflow_service', - ), - 'supports' => array( - \stdClass::class, - ), - 'places' => array( - 'first', - 'last', - ), - 'transitions' => array( - 'go' => array( - 'from' => 'first', - 'to' => 'last', - ), - ), - ), - ), -)); diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/workflows.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/workflows.xml index be065c4558858..02f964bc3a434 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/workflows.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/workflows.xml @@ -39,7 +39,7 @@ - + Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\FrameworkExtensionTest start diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/workflows_without_type.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/workflows_without_type.xml deleted file mode 100644 index 2e6ebad552b74..0000000000000 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/workflows_without_type.xml +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - stdClass - first - last - - first - last - - - - diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/workflows.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/workflows.yml index 36b84f71e4582..8efb803c12ad9 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/workflows.yml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/workflows.yml @@ -28,7 +28,6 @@ framework: from: [approved_by_journalist, approved_by_spellchecker] to: [published] pull_request: - type: state_machine marking_store: type: single_state supports: diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/workflows_without_type.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/workflows_without_type.yml deleted file mode 100644 index 41b81683ba445..0000000000000 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/workflows_without_type.yml +++ /dev/null @@ -1,7 +0,0 @@ -framework: - workflows: - missing_type: - supports: stdClass - places: [ first, second ] - transitions: - go: {from: first, to: last } diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php index 4f86c85d4f8fb..a6a201350214b 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php @@ -154,8 +154,9 @@ public function testWorkflows() { $container = $this->createContainerFromFile('workflows'); - $this->assertTrue($container->hasDefinition('workflow.article', 'Workflow is registered as a service')); - $this->assertTrue($container->hasDefinition('workflow.article.definition', 'Workflow definition is registered as a service')); + $this->assertTrue($container->hasDefinition('workflow.article'), 'Workflow is registered as a service'); + $this->assertSame('workflow.abstract', $container->getDefinition('workflow.article')->getParent()); + $this->assertTrue($container->hasDefinition('workflow.article.definition'), 'Workflow definition is registered as a service'); $workflowDefinition = $container->getDefinition('workflow.article.definition'); @@ -173,8 +174,9 @@ public function testWorkflows() ); $this->assertSame(array('workflow.definition' => array(array('name' => 'article', 'type' => 'workflow', 'marking_store' => 'multiple_state'))), $workflowDefinition->getTags()); - $this->assertTrue($container->hasDefinition('state_machine.pull_request', 'State machine is registered as a service')); - $this->assertTrue($container->hasDefinition('state_machine.pull_request.definition', 'State machine definition is registered as a service')); + $this->assertTrue($container->hasDefinition('state_machine.pull_request'), 'State machine is registered as a service'); + $this->assertSame('state_machine.abstract', $container->getDefinition('state_machine.pull_request')->getParent()); + $this->assertTrue($container->hasDefinition('state_machine.pull_request.definition'), 'State machine definition is registered as a service'); $this->assertCount(4, $workflowDefinition->getArgument(1)); $this->assertSame('draft', $workflowDefinition->getArgument(2)); @@ -207,15 +209,6 @@ public function testWorkflows() $this->assertGreaterThan(0, count($registryDefinition->getMethodCalls())); } - /** - * @group legacy - * @expectedDeprecation The "type" option of the "framework.workflows.missing_type" configuration entry must be defined since Symfony 3.3. The default value will be "state_machine" in Symfony 4.0. - */ - public function testDeprecatedWorkflowMissingType() - { - $container = $this->createContainerFromFile('workflows_without_type'); - } - /** * @expectedException \Symfony\Component\Config\Definition\Exception\InvalidConfigurationException * @expectedExceptionMessage "type" and "service" cannot be used together. From f9c51a6098e88b7b452f1475a7eb66fab4d42c6a Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Fri, 19 May 2017 19:05:40 +0200 Subject: [PATCH 0021/1099] [Debug][VarDumper] Remove the symfony_debug C extension --- src/Symfony/Component/Debug/CHANGELOG.md | 5 + .../Debug/Exception/FatalErrorException.php | 5 - .../Component/Debug/Resources/ext/README.md | 134 --------- .../Component/Debug/Resources/ext/config.m4 | 63 ---- .../Component/Debug/Resources/ext/config.w32 | 13 - .../Debug/Resources/ext/php_symfony_debug.h | 60 ---- .../Debug/Resources/ext/symfony_debug.c | 283 ------------------ .../Debug/Resources/ext/tests/001.phpt | 153 ---------- .../Debug/Resources/ext/tests/002.phpt | 63 ---- .../Debug/Resources/ext/tests/002_1.phpt | 46 --- .../Debug/Resources/ext/tests/003.phpt | 85 ------ .../VarDumper/Cloner/AbstractCloner.php | 2 - .../Component/VarDumper/Cloner/VarCloner.php | 53 +--- .../VarDumper/Tests/Dumper/CliDumperTest.php | 6 +- src/Symfony/Component/VarDumper/composer.json | 3 +- 15 files changed, 23 insertions(+), 951 deletions(-) delete mode 100644 src/Symfony/Component/Debug/Resources/ext/README.md delete mode 100644 src/Symfony/Component/Debug/Resources/ext/config.m4 delete mode 100644 src/Symfony/Component/Debug/Resources/ext/config.w32 delete mode 100644 src/Symfony/Component/Debug/Resources/ext/php_symfony_debug.h delete mode 100644 src/Symfony/Component/Debug/Resources/ext/symfony_debug.c delete mode 100644 src/Symfony/Component/Debug/Resources/ext/tests/001.phpt delete mode 100644 src/Symfony/Component/Debug/Resources/ext/tests/002.phpt delete mode 100644 src/Symfony/Component/Debug/Resources/ext/tests/002_1.phpt delete mode 100644 src/Symfony/Component/Debug/Resources/ext/tests/003.phpt diff --git a/src/Symfony/Component/Debug/CHANGELOG.md b/src/Symfony/Component/Debug/CHANGELOG.md index a853b7a0a70a4..d61f8d8426d83 100644 --- a/src/Symfony/Component/Debug/CHANGELOG.md +++ b/src/Symfony/Component/Debug/CHANGELOG.md @@ -1,6 +1,11 @@ CHANGELOG ========= +4.0.0 +----- + +* removed the symfony_debug extension + 3.3.0 ----- diff --git a/src/Symfony/Component/Debug/Exception/FatalErrorException.php b/src/Symfony/Component/Debug/Exception/FatalErrorException.php index f24a54e77a6ac..8418c940a90a3 100644 --- a/src/Symfony/Component/Debug/Exception/FatalErrorException.php +++ b/src/Symfony/Component/Debug/Exception/FatalErrorException.php @@ -60,11 +60,6 @@ public function __construct($message, $code, $severity, $filename, $lineno, $tra unset($frame); $trace = array_reverse($trace); - } elseif (function_exists('symfony_debug_backtrace')) { - $trace = symfony_debug_backtrace(); - if (0 < $traceOffset) { - array_splice($trace, 0, $traceOffset); - } } else { $trace = array(); } diff --git a/src/Symfony/Component/Debug/Resources/ext/README.md b/src/Symfony/Component/Debug/Resources/ext/README.md deleted file mode 100644 index 25dccf0766470..0000000000000 --- a/src/Symfony/Component/Debug/Resources/ext/README.md +++ /dev/null @@ -1,134 +0,0 @@ -Symfony Debug Extension for PHP 5 -================================= - -This extension publishes several functions to help building powerful debugging tools. -It is compatible with PHP 5.3, 5.4, 5.5 and 5.6; with ZTS and non-ZTS modes. -It is not required thus not provided for PHP 7. - -symfony_zval_info() -------------------- - -- exposes zval_hash/refcounts, allowing e.g. efficient exploration of arbitrary structures in PHP, -- does work with references, preventing memory copying. - -Its behavior is about the same as: - -```php - gettype($array[$key]), - 'zval_hash' => /* hashed memory address of $array[$key] */, - 'zval_refcount' => /* internal zval refcount of $array[$key] */, - 'zval_isref' => /* is_ref status of $array[$key] */, - ); - - switch ($info['type']) { - case 'object': - $info += array( - 'object_class' => get_class($array[$key]), - 'object_refcount' => /* internal object refcount of $array[$key] */, - 'object_hash' => spl_object_hash($array[$key]), - 'object_handle' => /* internal object handle $array[$key] */, - ); - break; - - case 'resource': - $info += array( - 'resource_handle' => (int) $array[$key], - 'resource_type' => get_resource_type($array[$key]), - 'resource_refcount' => /* internal resource refcount of $array[$key] */, - ); - break; - - case 'array': - $info += array( - 'array_count' => count($array[$key]), - ); - break; - - case 'string': - $info += array( - 'strlen' => strlen($array[$key]), - ); - break; - } - - return $info; -} -``` - -symfony_debug_backtrace() -------------------------- - -This function works like debug_backtrace(), except that it can fetch the full backtrace in case of fatal errors: - -```php -function foo() { fatal(); } -function bar() { foo(); } - -function sd() { var_dump(symfony_debug_backtrace()); } - -register_shutdown_function('sd'); - -bar(); - -/* Will output -Fatal error: Call to undefined function fatal() in foo.php on line 42 -array(3) { - [0]=> - array(2) { - ["function"]=> - string(2) "sd" - ["args"]=> - array(0) { - } - } - [1]=> - array(4) { - ["file"]=> - string(7) "foo.php" - ["line"]=> - int(1) - ["function"]=> - string(3) "foo" - ["args"]=> - array(0) { - } - } - [2]=> - array(4) { - ["file"]=> - string(102) "foo.php" - ["line"]=> - int(2) - ["function"]=> - string(3) "bar" - ["args"]=> - array(0) { - } - } -} -*/ -``` - -Usage ------ - -To enable the extension from source, run: - -``` - phpize - ./configure - make - sudo make install -``` diff --git a/src/Symfony/Component/Debug/Resources/ext/config.m4 b/src/Symfony/Component/Debug/Resources/ext/config.m4 deleted file mode 100644 index 3c56047150569..0000000000000 --- a/src/Symfony/Component/Debug/Resources/ext/config.m4 +++ /dev/null @@ -1,63 +0,0 @@ -dnl $Id$ -dnl config.m4 for extension symfony_debug - -dnl Comments in this file start with the string 'dnl'. -dnl Remove where necessary. This file will not work -dnl without editing. - -dnl If your extension references something external, use with: - -dnl PHP_ARG_WITH(symfony_debug, for symfony_debug support, -dnl Make sure that the comment is aligned: -dnl [ --with-symfony_debug Include symfony_debug support]) - -dnl Otherwise use enable: - -PHP_ARG_ENABLE(symfony_debug, whether to enable symfony_debug support, -dnl Make sure that the comment is aligned: -[ --enable-symfony_debug Enable symfony_debug support]) - -if test "$PHP_SYMFONY_DEBUG" != "no"; then - dnl Write more examples of tests here... - - dnl # --with-symfony_debug -> check with-path - dnl SEARCH_PATH="/usr/local /usr" # you might want to change this - dnl SEARCH_FOR="/include/symfony_debug.h" # you most likely want to change this - dnl if test -r $PHP_SYMFONY_DEBUG/$SEARCH_FOR; then # path given as parameter - dnl SYMFONY_DEBUG_DIR=$PHP_SYMFONY_DEBUG - dnl else # search default path list - dnl AC_MSG_CHECKING([for symfony_debug files in default path]) - dnl for i in $SEARCH_PATH ; do - dnl if test -r $i/$SEARCH_FOR; then - dnl SYMFONY_DEBUG_DIR=$i - dnl AC_MSG_RESULT(found in $i) - dnl fi - dnl done - dnl fi - dnl - dnl if test -z "$SYMFONY_DEBUG_DIR"; then - dnl AC_MSG_RESULT([not found]) - dnl AC_MSG_ERROR([Please reinstall the symfony_debug distribution]) - dnl fi - - dnl # --with-symfony_debug -> add include path - dnl PHP_ADD_INCLUDE($SYMFONY_DEBUG_DIR/include) - - dnl # --with-symfony_debug -> check for lib and symbol presence - dnl LIBNAME=symfony_debug # you may want to change this - dnl LIBSYMBOL=symfony_debug # you most likely want to change this - - dnl PHP_CHECK_LIBRARY($LIBNAME,$LIBSYMBOL, - dnl [ - dnl PHP_ADD_LIBRARY_WITH_PATH($LIBNAME, $SYMFONY_DEBUG_DIR/lib, SYMFONY_DEBUG_SHARED_LIBADD) - dnl AC_DEFINE(HAVE_SYMFONY_DEBUGLIB,1,[ ]) - dnl ],[ - dnl AC_MSG_ERROR([wrong symfony_debug lib version or lib not found]) - dnl ],[ - dnl -L$SYMFONY_DEBUG_DIR/lib -lm - dnl ]) - dnl - dnl PHP_SUBST(SYMFONY_DEBUG_SHARED_LIBADD) - - PHP_NEW_EXTENSION(symfony_debug, symfony_debug.c, $ext_shared) -fi diff --git a/src/Symfony/Component/Debug/Resources/ext/config.w32 b/src/Symfony/Component/Debug/Resources/ext/config.w32 deleted file mode 100644 index 487e6913891cf..0000000000000 --- a/src/Symfony/Component/Debug/Resources/ext/config.w32 +++ /dev/null @@ -1,13 +0,0 @@ -// $Id$ -// vim:ft=javascript - -// If your extension references something external, use ARG_WITH -// ARG_WITH("symfony_debug", "for symfony_debug support", "no"); - -// Otherwise, use ARG_ENABLE -// ARG_ENABLE("symfony_debug", "enable symfony_debug support", "no"); - -if (PHP_SYMFONY_DEBUG != "no") { - EXTENSION("symfony_debug", "symfony_debug.c"); -} - diff --git a/src/Symfony/Component/Debug/Resources/ext/php_symfony_debug.h b/src/Symfony/Component/Debug/Resources/ext/php_symfony_debug.h deleted file mode 100644 index 26d0e8c012030..0000000000000 --- a/src/Symfony/Component/Debug/Resources/ext/php_symfony_debug.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -#ifndef PHP_SYMFONY_DEBUG_H -#define PHP_SYMFONY_DEBUG_H - -extern zend_module_entry symfony_debug_module_entry; -#define phpext_symfony_debug_ptr &symfony_debug_module_entry - -#define PHP_SYMFONY_DEBUG_VERSION "2.7" - -#ifdef PHP_WIN32 -# define PHP_SYMFONY_DEBUG_API __declspec(dllexport) -#elif defined(__GNUC__) && __GNUC__ >= 4 -# define PHP_SYMFONY_DEBUG_API __attribute__ ((visibility("default"))) -#else -# define PHP_SYMFONY_DEBUG_API -#endif - -#ifdef ZTS -#include "TSRM.h" -#endif - -ZEND_BEGIN_MODULE_GLOBALS(symfony_debug) - intptr_t req_rand_init; - void (*old_error_cb)(int type, const char *error_filename, const uint error_lineno, const char *format, va_list args); - zval *debug_bt; -ZEND_END_MODULE_GLOBALS(symfony_debug) - -PHP_MINIT_FUNCTION(symfony_debug); -PHP_MSHUTDOWN_FUNCTION(symfony_debug); -PHP_RINIT_FUNCTION(symfony_debug); -PHP_RSHUTDOWN_FUNCTION(symfony_debug); -PHP_MINFO_FUNCTION(symfony_debug); -PHP_GINIT_FUNCTION(symfony_debug); -PHP_GSHUTDOWN_FUNCTION(symfony_debug); - -PHP_FUNCTION(symfony_zval_info); -PHP_FUNCTION(symfony_debug_backtrace); - -static char *_symfony_debug_memory_address_hash(void * TSRMLS_DC); -static const char *_symfony_debug_zval_type(zval *); -static const char* _symfony_debug_get_resource_type(long TSRMLS_DC); -static int _symfony_debug_get_resource_refcount(long TSRMLS_DC); - -void symfony_debug_error_cb(int type, const char *error_filename, const uint error_lineno, const char *format, va_list args); - -#ifdef ZTS -#define SYMFONY_DEBUG_G(v) TSRMG(symfony_debug_globals_id, zend_symfony_debug_globals *, v) -#else -#define SYMFONY_DEBUG_G(v) (symfony_debug_globals.v) -#endif - -#endif /* PHP_SYMFONY_DEBUG_H */ diff --git a/src/Symfony/Component/Debug/Resources/ext/symfony_debug.c b/src/Symfony/Component/Debug/Resources/ext/symfony_debug.c deleted file mode 100644 index 0d7cb602320f9..0000000000000 --- a/src/Symfony/Component/Debug/Resources/ext/symfony_debug.c +++ /dev/null @@ -1,283 +0,0 @@ -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "php.h" -#ifdef ZTS -#include "TSRM.h" -#endif -#include "php_ini.h" -#include "ext/standard/info.h" -#include "php_symfony_debug.h" -#include "ext/standard/php_rand.h" -#include "ext/standard/php_lcg.h" -#include "ext/spl/php_spl.h" -#include "Zend/zend_gc.h" -#include "Zend/zend_builtin_functions.h" -#include "Zend/zend_extensions.h" /* for ZEND_EXTENSION_API_NO */ -#include "ext/standard/php_array.h" -#include "Zend/zend_interfaces.h" -#include "SAPI.h" - -#define IS_PHP_53 ZEND_EXTENSION_API_NO == 220090626 - -ZEND_DECLARE_MODULE_GLOBALS(symfony_debug) - -ZEND_BEGIN_ARG_INFO_EX(symfony_zval_arginfo, 0, 0, 2) - ZEND_ARG_INFO(0, key) - ZEND_ARG_ARRAY_INFO(0, array, 0) - ZEND_ARG_INFO(0, options) -ZEND_END_ARG_INFO() - -const zend_function_entry symfony_debug_functions[] = { - PHP_FE(symfony_zval_info, symfony_zval_arginfo) - PHP_FE(symfony_debug_backtrace, NULL) - PHP_FE_END -}; - -PHP_FUNCTION(symfony_debug_backtrace) -{ - if (zend_parse_parameters_none() == FAILURE) { - return; - } -#if IS_PHP_53 - zend_fetch_debug_backtrace(return_value, 1, 0 TSRMLS_CC); -#else - zend_fetch_debug_backtrace(return_value, 1, 0, 0 TSRMLS_CC); -#endif - - if (!SYMFONY_DEBUG_G(debug_bt)) { - return; - } - - php_array_merge(Z_ARRVAL_P(return_value), Z_ARRVAL_P(SYMFONY_DEBUG_G(debug_bt)), 0 TSRMLS_CC); -} - -PHP_FUNCTION(symfony_zval_info) -{ - zval *key = NULL, *arg = NULL; - zval **data = NULL; - HashTable *array = NULL; - long options = 0; - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zh|l", &key, &array, &options) == FAILURE) { - return; - } - - switch (Z_TYPE_P(key)) { - case IS_STRING: - if (zend_symtable_find(array, Z_STRVAL_P(key), Z_STRLEN_P(key) + 1, (void **)&data) == FAILURE) { - return; - } - break; - case IS_LONG: - if (zend_hash_index_find(array, Z_LVAL_P(key), (void **)&data)) { - return; - } - break; - } - - arg = *data; - - array_init(return_value); - - add_assoc_string(return_value, "type", (char *)_symfony_debug_zval_type(arg), 1); - add_assoc_stringl(return_value, "zval_hash", _symfony_debug_memory_address_hash((void *)arg TSRMLS_CC), 16, 0); - add_assoc_long(return_value, "zval_refcount", Z_REFCOUNT_P(arg)); - add_assoc_bool(return_value, "zval_isref", (zend_bool)Z_ISREF_P(arg)); - - if (Z_TYPE_P(arg) == IS_OBJECT) { - char hash[33] = {0}; - - php_spl_object_hash(arg, (char *)hash TSRMLS_CC); - add_assoc_stringl(return_value, "object_class", (char *)Z_OBJCE_P(arg)->name, Z_OBJCE_P(arg)->name_length, 1); - add_assoc_long(return_value, "object_refcount", EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(arg)].bucket.obj.refcount); - add_assoc_string(return_value, "object_hash", hash, 1); - add_assoc_long(return_value, "object_handle", Z_OBJ_HANDLE_P(arg)); - } else if (Z_TYPE_P(arg) == IS_ARRAY) { - add_assoc_long(return_value, "array_count", zend_hash_num_elements(Z_ARRVAL_P(arg))); - } else if(Z_TYPE_P(arg) == IS_RESOURCE) { - add_assoc_long(return_value, "resource_handle", Z_LVAL_P(arg)); - add_assoc_string(return_value, "resource_type", (char *)_symfony_debug_get_resource_type(Z_LVAL_P(arg) TSRMLS_CC), 1); - add_assoc_long(return_value, "resource_refcount", _symfony_debug_get_resource_refcount(Z_LVAL_P(arg) TSRMLS_CC)); - } else if (Z_TYPE_P(arg) == IS_STRING) { - add_assoc_long(return_value, "strlen", Z_STRLEN_P(arg)); - } -} - -void symfony_debug_error_cb(int type, const char *error_filename, const uint error_lineno, const char *format, va_list args) -{ - TSRMLS_FETCH(); - zval *retval; - - switch (type) { - case E_ERROR: - case E_PARSE: - case E_CORE_ERROR: - case E_CORE_WARNING: - case E_COMPILE_ERROR: - case E_COMPILE_WARNING: - ALLOC_INIT_ZVAL(retval); -#if IS_PHP_53 - zend_fetch_debug_backtrace(retval, 1, 0 TSRMLS_CC); -#else - zend_fetch_debug_backtrace(retval, 1, 0, 0 TSRMLS_CC); -#endif - SYMFONY_DEBUG_G(debug_bt) = retval; - } - - SYMFONY_DEBUG_G(old_error_cb)(type, error_filename, error_lineno, format, args); -} - -static const char* _symfony_debug_get_resource_type(long rsid TSRMLS_DC) -{ - const char *res_type; - res_type = zend_rsrc_list_get_rsrc_type(rsid TSRMLS_CC); - - if (!res_type) { - return "Unknown"; - } - - return res_type; -} - -static int _symfony_debug_get_resource_refcount(long rsid TSRMLS_DC) -{ - zend_rsrc_list_entry *le; - - if (zend_hash_index_find(&EG(regular_list), rsid, (void **) &le)==SUCCESS) { - return le->refcount; - } - - return 0; -} - -static char *_symfony_debug_memory_address_hash(void *address TSRMLS_DC) -{ - char *result = NULL; - intptr_t address_rand; - - if (!SYMFONY_DEBUG_G(req_rand_init)) { - if (!BG(mt_rand_is_seeded)) { - php_mt_srand(GENERATE_SEED() TSRMLS_CC); - } - SYMFONY_DEBUG_G(req_rand_init) = (intptr_t)php_mt_rand(TSRMLS_C); - } - - address_rand = (intptr_t)address ^ SYMFONY_DEBUG_G(req_rand_init); - - spprintf(&result, 17, "%016zx", address_rand); - - return result; -} - -static const char *_symfony_debug_zval_type(zval *zv) -{ - switch (Z_TYPE_P(zv)) { - case IS_NULL: - return "NULL"; - break; - - case IS_BOOL: - return "boolean"; - break; - - case IS_LONG: - return "integer"; - break; - - case IS_DOUBLE: - return "double"; - break; - - case IS_STRING: - return "string"; - break; - - case IS_ARRAY: - return "array"; - break; - - case IS_OBJECT: - return "object"; - - case IS_RESOURCE: - return "resource"; - - default: - return "unknown type"; - } -} - -zend_module_entry symfony_debug_module_entry = { - STANDARD_MODULE_HEADER, - "symfony_debug", - symfony_debug_functions, - PHP_MINIT(symfony_debug), - PHP_MSHUTDOWN(symfony_debug), - PHP_RINIT(symfony_debug), - PHP_RSHUTDOWN(symfony_debug), - PHP_MINFO(symfony_debug), - PHP_SYMFONY_DEBUG_VERSION, - PHP_MODULE_GLOBALS(symfony_debug), - PHP_GINIT(symfony_debug), - PHP_GSHUTDOWN(symfony_debug), - NULL, - STANDARD_MODULE_PROPERTIES_EX -}; - -#ifdef COMPILE_DL_SYMFONY_DEBUG -ZEND_GET_MODULE(symfony_debug) -#endif - -PHP_GINIT_FUNCTION(symfony_debug) -{ - memset(symfony_debug_globals, 0 , sizeof(*symfony_debug_globals)); -} - -PHP_GSHUTDOWN_FUNCTION(symfony_debug) -{ - -} - -PHP_MINIT_FUNCTION(symfony_debug) -{ - SYMFONY_DEBUG_G(old_error_cb) = zend_error_cb; - zend_error_cb = symfony_debug_error_cb; - - return SUCCESS; -} - -PHP_MSHUTDOWN_FUNCTION(symfony_debug) -{ - zend_error_cb = SYMFONY_DEBUG_G(old_error_cb); - - return SUCCESS; -} - -PHP_RINIT_FUNCTION(symfony_debug) -{ - return SUCCESS; -} - -PHP_RSHUTDOWN_FUNCTION(symfony_debug) -{ - return SUCCESS; -} - -PHP_MINFO_FUNCTION(symfony_debug) -{ - php_info_print_table_start(); - php_info_print_table_header(2, "Symfony Debug support", "enabled"); - php_info_print_table_header(2, "Symfony Debug version", PHP_SYMFONY_DEBUG_VERSION); - php_info_print_table_end(); -} diff --git a/src/Symfony/Component/Debug/Resources/ext/tests/001.phpt b/src/Symfony/Component/Debug/Resources/ext/tests/001.phpt deleted file mode 100644 index 15e183a70615c..0000000000000 --- a/src/Symfony/Component/Debug/Resources/ext/tests/001.phpt +++ /dev/null @@ -1,153 +0,0 @@ ---TEST-- -Test symfony_zval_info API ---SKIPIF-- - ---FILE-- - $int, - 'float' => $float, - 'str' => $str, - 'object' => $object, - 'array' => $array, - 'resource' => $resource, - 'null' => $null, - 'bool' => $bool, - 'refcount' => &$refcount2, -); - -var_dump(symfony_zval_info('int', $var)); -var_dump(symfony_zval_info('float', $var)); -var_dump(symfony_zval_info('str', $var)); -var_dump(symfony_zval_info('object', $var)); -var_dump(symfony_zval_info('array', $var)); -var_dump(symfony_zval_info('resource', $var)); -var_dump(symfony_zval_info('null', $var)); -var_dump(symfony_zval_info('bool', $var)); - -var_dump(symfony_zval_info('refcount', $var)); -var_dump(symfony_zval_info('not-exist', $var)); -?> ---EXPECTF-- -array(4) { - ["type"]=> - string(7) "integer" - ["zval_hash"]=> - string(16) "%s" - ["zval_refcount"]=> - int(2) - ["zval_isref"]=> - bool(false) -} -array(4) { - ["type"]=> - string(6) "double" - ["zval_hash"]=> - string(16) "%s" - ["zval_refcount"]=> - int(2) - ["zval_isref"]=> - bool(false) -} -array(5) { - ["type"]=> - string(6) "string" - ["zval_hash"]=> - string(16) "%s" - ["zval_refcount"]=> - int(2) - ["zval_isref"]=> - bool(false) - ["strlen"]=> - int(6) -} -array(8) { - ["type"]=> - string(6) "object" - ["zval_hash"]=> - string(16) "%s" - ["zval_refcount"]=> - int(2) - ["zval_isref"]=> - bool(false) - ["object_class"]=> - string(8) "stdClass" - ["object_refcount"]=> - int(1) - ["object_hash"]=> - string(32) "%s" - ["object_handle"]=> - int(%d) -} -array(5) { - ["type"]=> - string(5) "array" - ["zval_hash"]=> - string(16) "%s" - ["zval_refcount"]=> - int(2) - ["zval_isref"]=> - bool(false) - ["array_count"]=> - int(2) -} -array(7) { - ["type"]=> - string(8) "resource" - ["zval_hash"]=> - string(16) "%s" - ["zval_refcount"]=> - int(2) - ["zval_isref"]=> - bool(false) - ["resource_handle"]=> - int(%d) - ["resource_type"]=> - string(6) "stream" - ["resource_refcount"]=> - int(1) -} -array(4) { - ["type"]=> - string(4) "NULL" - ["zval_hash"]=> - string(16) "%s" - ["zval_refcount"]=> - int(2) - ["zval_isref"]=> - bool(false) -} -array(4) { - ["type"]=> - string(7) "boolean" - ["zval_hash"]=> - string(16) "%s" - ["zval_refcount"]=> - int(2) - ["zval_isref"]=> - bool(false) -} -array(4) { - ["type"]=> - string(7) "integer" - ["zval_hash"]=> - string(16) "%s" - ["zval_refcount"]=> - int(3) - ["zval_isref"]=> - bool(true) -} -NULL diff --git a/src/Symfony/Component/Debug/Resources/ext/tests/002.phpt b/src/Symfony/Component/Debug/Resources/ext/tests/002.phpt deleted file mode 100644 index 2bc6d71274d82..0000000000000 --- a/src/Symfony/Component/Debug/Resources/ext/tests/002.phpt +++ /dev/null @@ -1,63 +0,0 @@ ---TEST-- -Test symfony_debug_backtrace in case of fatal error ---SKIPIF-- - ---FILE-- - ---EXPECTF-- -Fatal error: Call to undefined function notexist() in %s on line %d -Array -( - [0] => Array - ( - [function] => bt - [args] => Array - ( - ) - - ) - - [1] => Array - ( - [file] => %s - [line] => %d - [function] => foo - [args] => Array - ( - ) - - ) - - [2] => Array - ( - [file] => %s - [line] => %d - [function] => bar - [args] => Array - ( - ) - - ) - -) diff --git a/src/Symfony/Component/Debug/Resources/ext/tests/002_1.phpt b/src/Symfony/Component/Debug/Resources/ext/tests/002_1.phpt deleted file mode 100644 index 4e9e34f1b2a40..0000000000000 --- a/src/Symfony/Component/Debug/Resources/ext/tests/002_1.phpt +++ /dev/null @@ -1,46 +0,0 @@ ---TEST-- -Test symfony_debug_backtrace in case of non fatal error ---SKIPIF-- - ---FILE-- - ---EXPECTF-- -Array -( - [0] => Array - ( - [file] => %s - [line] => %d - [function] => bt - [args] => Array - ( - ) - - ) - - [1] => Array - ( - [file] => %s - [line] => %d - [function] => bar - [args] => Array - ( - ) - - ) - -) diff --git a/src/Symfony/Component/Debug/Resources/ext/tests/003.phpt b/src/Symfony/Component/Debug/Resources/ext/tests/003.phpt deleted file mode 100644 index 2a494e27af2f1..0000000000000 --- a/src/Symfony/Component/Debug/Resources/ext/tests/003.phpt +++ /dev/null @@ -1,85 +0,0 @@ ---TEST-- -Test ErrorHandler in case of fatal error ---SKIPIF-- - ---FILE-- -setExceptionHandler('print_r'); - -if (function_exists('xdebug_disable')) { - xdebug_disable(); -} - -bar(); -?> ---EXPECTF-- -Fatal error: Call to undefined function Symfony\Component\Debug\notexist() in %s on line %d -Symfony\Component\Debug\Exception\UndefinedFunctionException Object -( - [message:protected] => Attempted to call function "notexist" from namespace "Symfony\Component\Debug". - [string:Exception:private] => - [code:protected] => 0 - [file:protected] => %s - [line:protected] => %d - [trace:Exception:private] => Array - ( - [0] => Array - ( -%A [function] => Symfony\Component\Debug\foo -%A [args] => Array - ( - ) - - ) - - [1] => Array - ( -%A [function] => Symfony\Component\Debug\bar -%A [args] => Array - ( - ) - - ) -%A - ) - - [previous:Exception:private] => - [severity:protected] => 1 -) diff --git a/src/Symfony/Component/VarDumper/Cloner/AbstractCloner.php b/src/Symfony/Component/VarDumper/Cloner/AbstractCloner.php index c07ae491c5dc0..fe4d4fa8ea369 100644 --- a/src/Symfony/Component/VarDumper/Cloner/AbstractCloner.php +++ b/src/Symfony/Component/VarDumper/Cloner/AbstractCloner.php @@ -127,7 +127,6 @@ abstract class AbstractCloner implements ClonerInterface protected $maxItems = 2500; protected $maxString = -1; - protected $useExt; private $casters = array(); private $prevErrorHandler; @@ -145,7 +144,6 @@ public function __construct(array $casters = null) $casters = static::$defaultCasters; } $this->addCasters($casters); - $this->useExt = extension_loaded('symfony_debug'); } /** diff --git a/src/Symfony/Component/VarDumper/Cloner/VarCloner.php b/src/Symfony/Component/VarDumper/Cloner/VarCloner.php index 6a3b451bda7f7..b6bf2412cb910 100644 --- a/src/Symfony/Component/VarDumper/Cloner/VarCloner.php +++ b/src/Symfony/Component/VarDumper/Cloner/VarCloner.php @@ -24,7 +24,6 @@ class VarCloner extends AbstractCloner */ protected function doClone($var) { - $useExt = $this->useExt; $len = 1; // Length of $queue $pos = 0; // Number of cloned items past the first level $refsCounter = 0; // Hard references counter @@ -71,20 +70,16 @@ protected function doClone($var) if ($fromObjCast) { $k = $j; } - if ($useExt) { - $zval = symfony_zval_info($k, $refs); - } else { - $refs[$k] = $cookie; - if ($zval['zval_isref'] = $vals[$k] === $cookie) { - $zval['zval_hash'] = $v instanceof Stub ? spl_object_hash($v) : null; - } - $zval['type'] = gettype($v); + $refs[$k] = $cookie; + if ($zval['zval_isref'] = $vals[$k] === $cookie) { + $zval['zval_hash'] = $v instanceof Stub ? spl_object_hash($v) : null; } + $zval['type'] = gettype($v); if ($zval['zval_isref']) { $vals[$k] = &$stub; // Break hard references to make $queue completely unset($stub); // independent from the original structure if (isset($hardRefs[$zval['zval_hash']])) { - $vals[$k] = $useExt ? ($v = $hardRefs[$zval['zval_hash']]) : ($refs[$k] = $v); + $vals[$k] = $refs[$k] = $v; if ($v->value instanceof Stub && (Stub::TYPE_OBJECT === $v->value->type || Stub::TYPE_RESOURCE === $v->value->type)) { ++$v->value->refCount; } @@ -156,13 +151,7 @@ protected function doClone($var) if (Stub::TYPE_OBJECT !== $stub->type || null === $stub->value) { break; } - if ($useExt) { - $zval['type'] = $stub->value; - $zval = symfony_zval_info('type', $zval); - $h = $zval['object_handle']; - } else { - $h = $hashMask ^ hexdec(substr(spl_object_hash($stub->value), $hashOffset, PHP_INT_SIZE)); - } + $h = $hashMask ^ hexdec(substr(spl_object_hash($stub->value), $hashOffset, PHP_INT_SIZE)); $stub->handle = $h; } $stub->value = null; @@ -210,16 +199,11 @@ protected function doClone($var) if (isset($stub)) { if ($zval['zval_isref']) { - if ($useExt) { - $vals[$k] = $hardRefs[$zval['zval_hash']] = $v = new Stub(); - $v->value = $stub; - } else { - $refs[$k] = new Stub(); - $refs[$k]->value = $stub; - $h = spl_object_hash($refs[$k]); - $vals[$k] = $hardRefs[$h] = &$refs[$k]; - $values[$h] = $v; - } + $refs[$k] = new Stub(); + $refs[$k]->value = $stub; + $h = spl_object_hash($refs[$k]); + $vals[$k] = $hardRefs[$h] = &$refs[$k]; + $values[$h] = $v; $vals[$k]->handle = ++$refsCounter; } else { $vals[$k] = $stub; @@ -249,16 +233,11 @@ protected function doClone($var) } $stub = $a = null; } elseif ($zval['zval_isref']) { - if ($useExt) { - $vals[$k] = $hardRefs[$zval['zval_hash']] = new Stub(); - $vals[$k]->value = $v; - } else { - $refs[$k] = $vals[$k] = new Stub(); - $refs[$k]->value = $v; - $h = spl_object_hash($refs[$k]); - $hardRefs[$h] = &$refs[$k]; - $values[$h] = $v; - } + $refs[$k] = $vals[$k] = new Stub(); + $refs[$k]->value = $v; + $h = spl_object_hash($refs[$k]); + $hardRefs[$h] = &$refs[$k]; + $values[$h] = $v; $vals[$k]->handle = ++$refsCounter; } } diff --git a/src/Symfony/Component/VarDumper/Tests/Dumper/CliDumperTest.php b/src/Symfony/Component/VarDumper/Tests/Dumper/CliDumperTest.php index 37d2bc87b1031..41785d4b563c6 100644 --- a/src/Symfony/Component/VarDumper/Tests/Dumper/CliDumperTest.php +++ b/src/Symfony/Component/VarDumper/Tests/Dumper/CliDumperTest.php @@ -432,7 +432,7 @@ public function testSpecialVars56() * @runInSeparateProcess * @preserveGlobalState disabled */ - public function testGlobalsNoExt() + public function testGlobals() { $var = $this->getSpecialVars(); unset($var[0]); @@ -446,10 +446,6 @@ public function testGlobalsNoExt() $dumper->setColors(false); $cloner = new VarCloner(); - $refl = new \ReflectionProperty($cloner, 'useExt'); - $refl->setAccessible(true); - $refl->setValue($cloner, false); - $data = $cloner->cloneVar($var); $dumper->dump($data); diff --git a/src/Symfony/Component/VarDumper/composer.json b/src/Symfony/Component/VarDumper/composer.json index fcd3b3bb3c96d..c8139b4eb0763 100644 --- a/src/Symfony/Component/VarDumper/composer.json +++ b/src/Symfony/Component/VarDumper/composer.json @@ -27,8 +27,7 @@ "phpunit/phpunit": "<4.8.35|<5.4.3,>=5.0" }, "suggest": { - "ext-iconv": "To convert non-UTF-8 strings to UTF-8 (or symfony/polyfill-iconv in case ext-iconv cannot be used).", - "ext-symfony_debug": "" + "ext-iconv": "To convert non-UTF-8 strings to UTF-8 (or symfony/polyfill-iconv in case ext-iconv cannot be used)." }, "autoload": { "files": [ "Resources/functions/dump.php" ], From ba78b7b62a3a283f84d747c5ee02834eea549ffb Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Fri, 19 May 2017 19:48:07 +0200 Subject: [PATCH 0022/1099] [DoctrineBridge] remove deprecated features --- .../DoctrineParserCache.php | 56 ---------------- .../Form/ChoiceList/DoctrineChoiceLoader.php | 14 +--- .../MergeDoctrineCollectionListener.php | 31 --------- .../Bridge/Doctrine/ManagerRegistry.php | 6 +- .../DoctrineParserCacheTest.php | 64 ------------------- .../ChoiceList/DoctrineChoiceLoaderTest.php | 31 --------- .../MergeDoctrineCollectionListenerTest.php | 33 ---------- 7 files changed, 2 insertions(+), 233 deletions(-) delete mode 100644 src/Symfony/Bridge/Doctrine/ExpressionLanguage/DoctrineParserCache.php delete mode 100644 src/Symfony/Bridge/Doctrine/Tests/ExpressionLanguage/DoctrineParserCacheTest.php diff --git a/src/Symfony/Bridge/Doctrine/ExpressionLanguage/DoctrineParserCache.php b/src/Symfony/Bridge/Doctrine/ExpressionLanguage/DoctrineParserCache.php deleted file mode 100644 index e2eb6e664557b..0000000000000 --- a/src/Symfony/Bridge/Doctrine/ExpressionLanguage/DoctrineParserCache.php +++ /dev/null @@ -1,56 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bridge\Doctrine\ExpressionLanguage; - -@trigger_error('The '.__NAMESPACE__.'\DoctrineParserCache class is deprecated since version 3.2 and will be removed in 4.0. Use the Symfony\Component\Cache\Adapter\DoctrineAdapter class instead.', E_USER_DEPRECATED); - -use Doctrine\Common\Cache\Cache; -use Symfony\Component\ExpressionLanguage\ParsedExpression; -use Symfony\Component\ExpressionLanguage\ParserCache\ParserCacheInterface; - -/** - * @author Adrien Brault - * - * @deprecated DoctrineParserCache class is deprecated since version 3.2 and will be removed in 4.0. Use the Symfony\Component\Cache\Adapter\DoctrineAdapter class instead. - */ -class DoctrineParserCache implements ParserCacheInterface -{ - /** - * @var Cache - */ - private $cache; - - public function __construct(Cache $cache) - { - $this->cache = $cache; - } - - /** - * {@inheritdoc} - */ - public function fetch($key) - { - if (false === $value = $this->cache->fetch($key)) { - return; - } - - return $value; - } - - /** - * {@inheritdoc} - */ - public function save($key, ParsedExpression $expression) - { - $this->cache->save($key, $expression); - } -} diff --git a/src/Symfony/Bridge/Doctrine/Form/ChoiceList/DoctrineChoiceLoader.php b/src/Symfony/Bridge/Doctrine/Form/ChoiceList/DoctrineChoiceLoader.php index f199f16265fac..76e174ba256b4 100644 --- a/src/Symfony/Bridge/Doctrine/Form/ChoiceList/DoctrineChoiceLoader.php +++ b/src/Symfony/Bridge/Doctrine/Form/ChoiceList/DoctrineChoiceLoader.php @@ -65,20 +65,8 @@ class DoctrineChoiceLoader implements ChoiceLoaderInterface * @param ChoiceListFactoryInterface $factory The factory for creating * the loaded choice list */ - public function __construct($manager, $class, $idReader = null, $objectLoader = null, $factory = null) + public function __construct(ObjectManager $manager, $class, $idReader = null, $objectLoader = null, $factory = null) { - // BC to be removed and replace with type hints in 4.0 - if ($manager instanceof ChoiceListFactoryInterface) { - @trigger_error(sprintf('Passing a ChoiceListFactoryInterface to %s is deprecated since version 3.1 and will no longer be supported in 4.0. You should either call "%s::loadChoiceList" or override it to return a ChoiceListInterface.', __CLASS__, __CLASS__), E_USER_DEPRECATED); - - // Provide a BC layer since $factory has changed - // form first to last argument as of 3.1 - $manager = $class; - $class = $idReader; - $idReader = $objectLoader; - $objectLoader = $factory; - } - $classMetadata = $manager->getClassMetadata($class); $this->manager = $manager; diff --git a/src/Symfony/Bridge/Doctrine/Form/EventListener/MergeDoctrineCollectionListener.php b/src/Symfony/Bridge/Doctrine/Form/EventListener/MergeDoctrineCollectionListener.php index ca837e64283ae..81ee5cf405eab 100644 --- a/src/Symfony/Bridge/Doctrine/Form/EventListener/MergeDoctrineCollectionListener.php +++ b/src/Symfony/Bridge/Doctrine/Form/EventListener/MergeDoctrineCollectionListener.php @@ -27,17 +27,12 @@ */ class MergeDoctrineCollectionListener implements EventSubscriberInterface { - // Keep BC. To be removed in 4.0 - private $bc = true; - private $bcLayer = false; - public static function getSubscribedEvents() { // Higher priority than core MergeCollectionListener so that this one // is called before return array( FormEvents::SUBMIT => array( - array('onBind', 10), // deprecated array('onSubmit', 5), ), ); @@ -45,16 +40,6 @@ public static function getSubscribedEvents() public function onSubmit(FormEvent $event) { - if ($this->bc) { - // onBind() has been overridden from a child class - @trigger_error('The onBind() method is deprecated since version 3.1 and will be removed in 4.0. Use the onSubmit() method instead.', E_USER_DEPRECATED); - - if (!$this->bcLayer) { - // If parent::onBind() has not been called, then logic has been executed - return; - } - } - $collection = $event->getForm()->getData(); $data = $event->getData(); @@ -64,20 +49,4 @@ public function onSubmit(FormEvent $event) $collection->clear(); } } - - /** - * Alias of {@link onSubmit()}. - * - * @deprecated since version 3.1, to be removed in 4.0. - * Use {@link onSubmit()} instead. - */ - public function onBind(FormEvent $event) - { - if (__CLASS__ === get_class($this)) { - $this->bc = false; - } else { - // parent::onBind() has been called - $this->bcLayer = true; - } - } } diff --git a/src/Symfony/Bridge/Doctrine/ManagerRegistry.php b/src/Symfony/Bridge/Doctrine/ManagerRegistry.php index d602bfc2acaad..40a39efc8882b 100644 --- a/src/Symfony/Bridge/Doctrine/ManagerRegistry.php +++ b/src/Symfony/Bridge/Doctrine/ManagerRegistry.php @@ -45,11 +45,7 @@ protected function resetService($name) $manager = $this->container->get($name); if (!$manager instanceof LazyLoadingInterface) { - @trigger_error(sprintf('Resetting a non-lazy manager service is deprecated since Symfony 3.2 and will throw an exception in version 4.0. Set the "%s" service as lazy and require "symfony/proxy-manager-bridge" in your composer.json file instead.', $name), E_USER_DEPRECATED); - - $this->container->set($name, null); - - return; + throw new \LogicException(sprintf('Resetting a non-lazy manager service is not supported. Set the "%s" service as lazy and require "symfony/proxy-manager-bridge" in your composer.json file instead.', $name)); } $manager->setProxyInitializer(\Closure::bind( function (&$wrappedInstance, LazyLoadingInterface $manager) use ($name) { diff --git a/src/Symfony/Bridge/Doctrine/Tests/ExpressionLanguage/DoctrineParserCacheTest.php b/src/Symfony/Bridge/Doctrine/Tests/ExpressionLanguage/DoctrineParserCacheTest.php deleted file mode 100644 index 394b1b0dfe9a2..0000000000000 --- a/src/Symfony/Bridge/Doctrine/Tests/ExpressionLanguage/DoctrineParserCacheTest.php +++ /dev/null @@ -1,64 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bridge\Doctrine\Tests\ExpressionLanguage; - -use PHPUnit\Framework\TestCase; -use Symfony\Bridge\Doctrine\ExpressionLanguage\DoctrineParserCache; - -/** - * @group legacy - */ -class DoctrineParserCacheTest extends TestCase -{ - public function testFetch() - { - $doctrineCacheMock = $this->getMockBuilder('Doctrine\Common\Cache\Cache')->getMock(); - $parserCache = new DoctrineParserCache($doctrineCacheMock); - - $doctrineCacheMock->expects($this->once()) - ->method('fetch') - ->will($this->returnValue('bar')); - - $result = $parserCache->fetch('foo'); - - $this->assertEquals('bar', $result); - } - - public function testFetchUnexisting() - { - $doctrineCacheMock = $this->getMockBuilder('Doctrine\Common\Cache\Cache')->getMock(); - $parserCache = new DoctrineParserCache($doctrineCacheMock); - - $doctrineCacheMock - ->expects($this->once()) - ->method('fetch') - ->will($this->returnValue(false)); - - $this->assertNull($parserCache->fetch('')); - } - - public function testSave() - { - $doctrineCacheMock = $this->getMockBuilder('Doctrine\Common\Cache\Cache')->getMock(); - $parserCache = new DoctrineParserCache($doctrineCacheMock); - - $expression = $this->getMockBuilder('Symfony\Component\ExpressionLanguage\ParsedExpression') - ->disableOriginalConstructor() - ->getMock(); - - $doctrineCacheMock->expects($this->once()) - ->method('save') - ->with('foo', $expression); - - $parserCache->save('foo', $expression); - } -} diff --git a/src/Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/DoctrineChoiceLoaderTest.php b/src/Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/DoctrineChoiceLoaderTest.php index dfe2b00cdfd56..4999bda42ef57 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/DoctrineChoiceLoaderTest.php +++ b/src/Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/DoctrineChoiceLoaderTest.php @@ -113,37 +113,6 @@ public function testLoadChoiceList() $this->assertEquals($choiceList, $loader->loadChoiceList($value)); } - /** - * @group legacy - */ - public function testLegacyLoadChoiceList() - { - $factory = $this->getMockBuilder('Symfony\Component\Form\ChoiceList\Factory\ChoiceListFactoryInterface')->getMock(); - $loader = new DoctrineChoiceLoader( - $factory, - $this->om, - $this->class, - $this->idReader - ); - - $choices = array($this->obj1, $this->obj2, $this->obj3); - $value = function () {}; - $choiceList = new ArrayChoiceList($choices, $value); - - $this->repository->expects($this->once()) - ->method('findAll') - ->willReturn($choices); - - $factory->expects($this->never()) - ->method('createListFromChoices'); - - $this->assertEquals($choiceList, $loaded = $loader->loadChoiceList($value)); - - // no further loads on subsequent calls - - $this->assertSame($loaded, $loader->loadChoiceList($value)); - } - public function testLoadChoiceListUsesObjectLoaderIfAvailable() { $loader = new DoctrineChoiceLoader( diff --git a/src/Symfony/Bridge/Doctrine/Tests/Form/EventListener/MergeDoctrineCollectionListenerTest.php b/src/Symfony/Bridge/Doctrine/Tests/Form/EventListener/MergeDoctrineCollectionListenerTest.php index dbcbc0f325e4b..52ea54dfefbc5 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/Form/EventListener/MergeDoctrineCollectionListenerTest.php +++ b/src/Symfony/Bridge/Doctrine/Tests/Form/EventListener/MergeDoctrineCollectionListenerTest.php @@ -78,37 +78,4 @@ public function testOnSubmitNullClearCollection() $this->assertTrue($this->collection->isEmpty()); } - - /** - * @group legacy - */ - public function testLegacyChildClassOnSubmitCallParent() - { - $form = $this->getBuilder('name') - ->setData($this->collection) - ->addEventSubscriber(new TestClassExtendingMergeDoctrineCollectionListener()) - ->getForm(); - $submittedData = array(); - $event = new FormEvent($form, $submittedData); - - $this->dispatcher->dispatch(FormEvents::SUBMIT, $event); - - $this->assertTrue($this->collection->isEmpty()); - $this->assertTrue(TestClassExtendingMergeDoctrineCollectionListener::$onBindCalled); - } -} - -/** - * @group legacy - */ -class TestClassExtendingMergeDoctrineCollectionListener extends MergeDoctrineCollectionListener -{ - public static $onBindCalled = false; - - public function onBind(FormEvent $event) - { - self::$onBindCalled = true; - - parent::onBind($event); - } } From 64ac6e5d1fa400ea5c82f02d816d50c09699f1fe Mon Sep 17 00:00:00 2001 From: Iltar van der Berg Date: Fri, 19 May 2017 15:44:14 +0200 Subject: [PATCH 0023/1099] [4.0][BC Break] Removed BC layers for ControllerResolver::getArguments() --- .../Resources/config/debug.xml | 1 - src/Symfony/Component/HttpKernel/CHANGELOG.md | 8 + .../Controller/ControllerResolver.php | 86 +--------- .../ControllerResolverInterface.php | 14 -- .../TraceableControllerResolver.php | 34 +--- .../Component/HttpKernel/HttpKernel.php | 4 +- .../Controller/ControllerResolverTest.php | 147 ------------------ .../Fragment/InlineFragmentRendererTest.php | 21 --- 8 files changed, 14 insertions(+), 301 deletions(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/debug.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/debug.xml index 58a086b2129bf..10081f4eca71a 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/debug.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/debug.xml @@ -21,7 +21,6 @@ - diff --git a/src/Symfony/Component/HttpKernel/CHANGELOG.md b/src/Symfony/Component/HttpKernel/CHANGELOG.md index 15c61d3829c0c..4ed98e227d6a9 100644 --- a/src/Symfony/Component/HttpKernel/CHANGELOG.md +++ b/src/Symfony/Component/HttpKernel/CHANGELOG.md @@ -1,6 +1,14 @@ CHANGELOG ========= +4.0.0 +----- + + * removed `ControllerResolverInterface::getArguments()` + * removed `TraceableControllerResolver::getArguments()` + * removed `ControllerResolver::getArguments()` and the ability to resolve arguments + * removed the `argument_resolver` service dependency from the `debug.controller_resolver` + 3.3.0 ----- diff --git a/src/Symfony/Component/HttpKernel/Controller/ControllerResolver.php b/src/Symfony/Component/HttpKernel/Controller/ControllerResolver.php index f51a5a8efb1c1..b2273358aa45d 100644 --- a/src/Symfony/Component/HttpKernel/Controller/ControllerResolver.php +++ b/src/Symfony/Component/HttpKernel/Controller/ControllerResolver.php @@ -23,26 +23,10 @@ * * @author Fabien Potencier */ -class ControllerResolver implements ArgumentResolverInterface, ControllerResolverInterface +class ControllerResolver implements ControllerResolverInterface { private $logger; - /** - * If the ...$arg functionality is available. - * - * Requires at least PHP 5.6.0 or HHVM 3.9.1 - * - * @var bool - */ - private $supportsVariadic; - - /** - * If scalar types exists. - * - * @var bool - */ - private $supportsScalarTypes; - /** * Constructor. * @@ -51,9 +35,6 @@ class ControllerResolver implements ArgumentResolverInterface, ControllerResolve public function __construct(LoggerInterface $logger = null) { $this->logger = $logger; - - $this->supportsVariadic = method_exists('ReflectionParameter', 'isVariadic'); - $this->supportsScalarTypes = method_exists('ReflectionParameter', 'getType'); } /** @@ -101,71 +82,6 @@ public function getController(Request $request) return $callable; } - /** - * {@inheritdoc} - * - * @deprecated This method is deprecated as of 3.1 and will be removed in 4.0. Implement the ArgumentResolverInterface and inject it in the HttpKernel instead. - */ - public function getArguments(Request $request, $controller) - { - @trigger_error(sprintf('%s is deprecated as of 3.1 and will be removed in 4.0. Implement the %s and inject it in the HttpKernel instead.', __METHOD__, ArgumentResolverInterface::class), E_USER_DEPRECATED); - - if (is_array($controller)) { - $r = new \ReflectionMethod($controller[0], $controller[1]); - } elseif (is_object($controller) && !$controller instanceof \Closure) { - $r = new \ReflectionObject($controller); - $r = $r->getMethod('__invoke'); - } else { - $r = new \ReflectionFunction($controller); - } - - return $this->doGetArguments($request, $controller, $r->getParameters()); - } - - /** - * @param Request $request - * @param callable $controller - * @param \ReflectionParameter[] $parameters - * - * @return array The arguments to use when calling the action - * - * @deprecated This method is deprecated as of 3.1 and will be removed in 4.0. Implement the ArgumentResolverInterface and inject it in the HttpKernel instead. - */ - protected function doGetArguments(Request $request, $controller, array $parameters) - { - @trigger_error(sprintf('%s is deprecated as of 3.1 and will be removed in 4.0. Implement the %s and inject it in the HttpKernel instead.', __METHOD__, ArgumentResolverInterface::class), E_USER_DEPRECATED); - - $attributes = $request->attributes->all(); - $arguments = array(); - foreach ($parameters as $param) { - if (array_key_exists($param->name, $attributes)) { - if ($this->supportsVariadic && $param->isVariadic() && is_array($attributes[$param->name])) { - $arguments = array_merge($arguments, array_values($attributes[$param->name])); - } else { - $arguments[] = $attributes[$param->name]; - } - } elseif ($param->getClass() && $param->getClass()->isInstance($request)) { - $arguments[] = $request; - } elseif ($param->isDefaultValueAvailable()) { - $arguments[] = $param->getDefaultValue(); - } elseif ($this->supportsScalarTypes && $param->hasType() && $param->allowsNull()) { - $arguments[] = null; - } else { - if (is_array($controller)) { - $repr = sprintf('%s::%s()', get_class($controller[0]), $controller[1]); - } elseif (is_object($controller)) { - $repr = get_class($controller); - } else { - $repr = $controller; - } - - throw new \RuntimeException(sprintf('Controller "%s" requires that you provide a value for the "$%s" argument (because there is no default value or because there is a non optional argument after this one).', $repr, $param->name)); - } - } - - return $arguments; - } - /** * Returns a callable for the given controller. * diff --git a/src/Symfony/Component/HttpKernel/Controller/ControllerResolverInterface.php b/src/Symfony/Component/HttpKernel/Controller/ControllerResolverInterface.php index 0dd7cce96d905..ee2028c33d4b9 100644 --- a/src/Symfony/Component/HttpKernel/Controller/ControllerResolverInterface.php +++ b/src/Symfony/Component/HttpKernel/Controller/ControllerResolverInterface.php @@ -42,18 +42,4 @@ interface ControllerResolverInterface * @throws \LogicException If the controller can't be found */ public function getController(Request $request); - - /** - * Returns the arguments to pass to the controller. - * - * @param Request $request A Request instance - * @param callable $controller A PHP callable - * - * @return array An array of arguments to pass to the controller - * - * @throws \RuntimeException When value for argument given is not provided - * - * @deprecated This method is deprecated as of 3.1 and will be removed in 4.0. Please use the {@see ArgumentResolverInterface} instead. - */ - public function getArguments(Request $request, $controller); } diff --git a/src/Symfony/Component/HttpKernel/Controller/TraceableControllerResolver.php b/src/Symfony/Component/HttpKernel/Controller/TraceableControllerResolver.php index ce291b1e3e269..73671887bbfb1 100644 --- a/src/Symfony/Component/HttpKernel/Controller/TraceableControllerResolver.php +++ b/src/Symfony/Component/HttpKernel/Controller/TraceableControllerResolver.php @@ -19,33 +19,21 @@ * * @author Fabien Potencier */ -class TraceableControllerResolver implements ControllerResolverInterface, ArgumentResolverInterface +class TraceableControllerResolver implements ControllerResolverInterface { private $resolver; private $stopwatch; - private $argumentResolver; /** * Constructor. * - * @param ControllerResolverInterface $resolver A ControllerResolverInterface instance - * @param Stopwatch $stopwatch A Stopwatch instance - * @param ArgumentResolverInterface $argumentResolver Only required for BC + * @param ControllerResolverInterface $resolver A ControllerResolverInterface instance + * @param Stopwatch $stopwatch A Stopwatch instance */ - public function __construct(ControllerResolverInterface $resolver, Stopwatch $stopwatch, ArgumentResolverInterface $argumentResolver = null) + public function __construct(ControllerResolverInterface $resolver, Stopwatch $stopwatch) { $this->resolver = $resolver; $this->stopwatch = $stopwatch; - $this->argumentResolver = $argumentResolver; - - // BC - if (null === $this->argumentResolver) { - $this->argumentResolver = $resolver; - } - - if (!$this->argumentResolver instanceof TraceableArgumentResolver) { - $this->argumentResolver = new TraceableArgumentResolver($this->argumentResolver, $this->stopwatch); - } } /** @@ -61,18 +49,4 @@ public function getController(Request $request) return $ret; } - - /** - * {@inheritdoc} - * - * @deprecated This method is deprecated as of 3.1 and will be removed in 4.0. - */ - public function getArguments(Request $request, $controller) - { - @trigger_error(sprintf('The %s method is deprecated as of 3.1 and will be removed in 4.0. Please use the %s instead.', __METHOD__, TraceableArgumentResolver::class), E_USER_DEPRECATED); - - $ret = $this->argumentResolver->getArguments($request, $controller); - - return $ret; - } } diff --git a/src/Symfony/Component/HttpKernel/HttpKernel.php b/src/Symfony/Component/HttpKernel/HttpKernel.php index 8d55ccde1c648..228ddb7fea795 100644 --- a/src/Symfony/Component/HttpKernel/HttpKernel.php +++ b/src/Symfony/Component/HttpKernel/HttpKernel.php @@ -51,9 +51,7 @@ public function __construct(EventDispatcherInterface $dispatcher, ControllerReso $this->argumentResolver = $argumentResolver; if (null === $this->argumentResolver) { - @trigger_error(sprintf('As of 3.1 an %s is used to resolve arguments. In 4.0 the $argumentResolver becomes the %s if no other is provided instead of using the $resolver argument.', ArgumentResolverInterface::class, ArgumentResolver::class), E_USER_DEPRECATED); - // fallback in case of deprecations - $this->argumentResolver = $resolver; + $this->argumentResolver = new ArgumentResolver(); } } diff --git a/src/Symfony/Component/HttpKernel/Tests/Controller/ControllerResolverTest.php b/src/Symfony/Component/HttpKernel/Tests/Controller/ControllerResolverTest.php index 190e15ad67bca..203a162fa815f 100644 --- a/src/Symfony/Component/HttpKernel/Tests/Controller/ControllerResolverTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/Controller/ControllerResolverTest.php @@ -14,8 +14,6 @@ use PHPUnit\Framework\TestCase; use Psr\Log\LoggerInterface; use Symfony\Component\HttpKernel\Controller\ControllerResolver; -use Symfony\Component\HttpKernel\Tests\Fixtures\Controller\NullableController; -use Symfony\Component\HttpKernel\Tests\Fixtures\Controller\VariadicController; use Symfony\Component\HttpFoundation\Request; class ControllerResolverTest extends TestCase @@ -144,139 +142,6 @@ public function getUndefinedControllers() ); } - /** - * @group legacy - */ - public function testGetArguments() - { - $resolver = $this->createControllerResolver(); - - $request = Request::create('/'); - $controller = array(new self(), 'testGetArguments'); - $this->assertEquals(array(), $resolver->getArguments($request, $controller), '->getArguments() returns an empty array if the method takes no arguments'); - - $request = Request::create('/'); - $request->attributes->set('foo', 'foo'); - $controller = array(new self(), 'controllerMethod1'); - $this->assertEquals(array('foo'), $resolver->getArguments($request, $controller), '->getArguments() returns an array of arguments for the controller method'); - - $request = Request::create('/'); - $request->attributes->set('foo', 'foo'); - $controller = array(new self(), 'controllerMethod2'); - $this->assertEquals(array('foo', null), $resolver->getArguments($request, $controller), '->getArguments() uses default values if present'); - - $request->attributes->set('bar', 'bar'); - $this->assertEquals(array('foo', 'bar'), $resolver->getArguments($request, $controller), '->getArguments() overrides default values if provided in the request attributes'); - - $request = Request::create('/'); - $request->attributes->set('foo', 'foo'); - $controller = function ($foo) {}; - $this->assertEquals(array('foo'), $resolver->getArguments($request, $controller)); - - $request = Request::create('/'); - $request->attributes->set('foo', 'foo'); - $controller = function ($foo, $bar = 'bar') {}; - $this->assertEquals(array('foo', 'bar'), $resolver->getArguments($request, $controller)); - - $request = Request::create('/'); - $request->attributes->set('foo', 'foo'); - $controller = new self(); - $this->assertEquals(array('foo', null), $resolver->getArguments($request, $controller)); - $request->attributes->set('bar', 'bar'); - $this->assertEquals(array('foo', 'bar'), $resolver->getArguments($request, $controller)); - - $request = Request::create('/'); - $request->attributes->set('foo', 'foo'); - $request->attributes->set('foobar', 'foobar'); - $controller = 'Symfony\Component\HttpKernel\Tests\Controller\some_controller_function'; - $this->assertEquals(array('foo', 'foobar'), $resolver->getArguments($request, $controller)); - - $request = Request::create('/'); - $request->attributes->set('foo', 'foo'); - $request->attributes->set('foobar', 'foobar'); - $controller = array(new self(), 'controllerMethod3'); - - try { - $resolver->getArguments($request, $controller); - $this->fail('->getArguments() throws a \RuntimeException exception if it cannot determine the argument value'); - } catch (\Exception $e) { - $this->assertInstanceOf('\RuntimeException', $e, '->getArguments() throws a \RuntimeException exception if it cannot determine the argument value'); - } - - $request = Request::create('/'); - $controller = array(new self(), 'controllerMethod5'); - $this->assertEquals(array($request), $resolver->getArguments($request, $controller), '->getArguments() injects the request'); - } - - /** - * @requires PHP 5.6 - * @group legacy - */ - public function testGetVariadicArguments() - { - $resolver = new ControllerResolver(); - - $request = Request::create('/'); - $request->attributes->set('foo', 'foo'); - $request->attributes->set('bar', array('foo', 'bar')); - $controller = array(new VariadicController(), 'action'); - $this->assertEquals(array('foo', 'foo', 'bar'), $resolver->getArguments($request, $controller)); - } - - public function testCreateControllerCanReturnAnyCallable() - { - $mock = $this->getMockBuilder('Symfony\Component\HttpKernel\Controller\ControllerResolver')->setMethods(array('createController'))->getMock(); - $mock->expects($this->once())->method('createController')->will($this->returnValue('Symfony\Component\HttpKernel\Tests\Controller\some_controller_function')); - - $request = Request::create('/'); - $request->attributes->set('_controller', 'foobar'); - $mock->getController($request); - } - - /** - * @expectedException \RuntimeException - * @group legacy - */ - public function testIfExceptionIsThrownWhenMissingAnArgument() - { - $resolver = new ControllerResolver(); - $request = Request::create('/'); - - $controller = array($this, 'controllerMethod1'); - - $resolver->getArguments($request, $controller); - } - - /** - * @requires PHP 7.1 - * @group legacy - */ - public function testGetNullableArguments() - { - $resolver = new ControllerResolver(); - - $request = Request::create('/'); - $request->attributes->set('foo', 'foo'); - $request->attributes->set('bar', new \stdClass()); - $request->attributes->set('mandatory', 'mandatory'); - $controller = array(new NullableController(), 'action'); - $this->assertEquals(array('foo', new \stdClass(), 'value', 'mandatory'), $resolver->getArguments($request, $controller)); - } - - /** - * @requires PHP 7.1 - * @group legacy - */ - public function testGetNullableArgumentsWithDefaults() - { - $resolver = new ControllerResolver(); - - $request = Request::create('/'); - $request->attributes->set('mandatory', 'mandatory'); - $controller = array(new NullableController(), 'action'); - $this->assertEquals(array(null, null, 'value', 'mandatory'), $resolver->getArguments($request, $controller)); - } - protected function createControllerResolver(LoggerInterface $logger = null) { return new ControllerResolver($logger); @@ -290,21 +155,9 @@ public function controllerMethod1($foo) { } - protected function controllerMethod2($foo, $bar = null) - { - } - - protected function controllerMethod3($foo, $bar, $foobar) - { - } - protected static function controllerMethod4() { } - - protected function controllerMethod5(Request $request) - { - } } function some_controller_function($foo, $foobar) diff --git a/src/Symfony/Component/HttpKernel/Tests/Fragment/InlineFragmentRendererTest.php b/src/Symfony/Component/HttpKernel/Tests/Fragment/InlineFragmentRendererTest.php index 18e55a5be0df2..ee556fa6e5ba6 100644 --- a/src/Symfony/Component/HttpKernel/Tests/Fragment/InlineFragmentRendererTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/Fragment/InlineFragmentRendererTest.php @@ -53,27 +53,6 @@ public function testRenderWithObjectsAsAttributes() $this->assertSame('foo', $strategy->render(new ControllerReference('main_controller', array('object' => $object), array()), Request::create('/'))->getContent()); } - /** - * @group legacy - */ - public function testRenderWithObjectsAsAttributesPassedAsObjectsInTheControllerLegacy() - { - $resolver = $this->getMockBuilder('Symfony\\Component\\HttpKernel\\Controller\\ControllerResolver')->setMethods(array('getController'))->getMock(); - $resolver - ->expects($this->once()) - ->method('getController') - ->will($this->returnValue(function (\stdClass $object, Bar $object1) { - return new Response($object1->getBar()); - })) - ; - - $kernel = new HttpKernel(new EventDispatcher(), $resolver, new RequestStack()); - $renderer = new InlineFragmentRenderer($kernel); - - $response = $renderer->render(new ControllerReference('main_controller', array('object' => new \stdClass(), 'object1' => new Bar()), array()), Request::create('/')); - $this->assertEquals('bar', $response->getContent()); - } - /** * @group legacy */ From 37ac9457c9a6739eaff4818e47d09ed9a95652ec Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Sat, 20 May 2017 08:30:04 +0200 Subject: [PATCH 0024/1099] [ExpressionLanguage] remove deprecated features --- src/Symfony/Bridge/Doctrine/CHANGELOG.md | 5 + .../DoctrineParserCache.php | 56 ------- .../DoctrineParserCacheTest.php | 64 -------- .../Component/ExpressionLanguage/CHANGELOG.md | 8 + .../ExpressionLanguage/ExpressionLanguage.php | 13 +- .../ParserCache/ArrayParserCache.php | 45 ------ .../ParserCache/ParserCacheAdapter.php | 120 --------------- .../ParserCache/ParserCacheInterface.php | 41 ----- .../Tests/ExpressionLanguageTest.php | 41 ----- .../ParserCache/ParserCacheAdapterTest.php | 140 ------------------ 10 files changed, 14 insertions(+), 519 deletions(-) delete mode 100644 src/Symfony/Bridge/Doctrine/ExpressionLanguage/DoctrineParserCache.php delete mode 100644 src/Symfony/Bridge/Doctrine/Tests/ExpressionLanguage/DoctrineParserCacheTest.php delete mode 100644 src/Symfony/Component/ExpressionLanguage/ParserCache/ArrayParserCache.php delete mode 100644 src/Symfony/Component/ExpressionLanguage/ParserCache/ParserCacheAdapter.php delete mode 100644 src/Symfony/Component/ExpressionLanguage/ParserCache/ParserCacheInterface.php delete mode 100644 src/Symfony/Component/ExpressionLanguage/Tests/ParserCache/ParserCacheAdapterTest.php diff --git a/src/Symfony/Bridge/Doctrine/CHANGELOG.md b/src/Symfony/Bridge/Doctrine/CHANGELOG.md index 3dcb8770ec8cc..2cfb583d81884 100644 --- a/src/Symfony/Bridge/Doctrine/CHANGELOG.md +++ b/src/Symfony/Bridge/Doctrine/CHANGELOG.md @@ -1,6 +1,11 @@ CHANGELOG ========= +4.0.0 +----- + + * removed the `DoctrineParserCache` class + 3.1.0 ----- diff --git a/src/Symfony/Bridge/Doctrine/ExpressionLanguage/DoctrineParserCache.php b/src/Symfony/Bridge/Doctrine/ExpressionLanguage/DoctrineParserCache.php deleted file mode 100644 index e2eb6e664557b..0000000000000 --- a/src/Symfony/Bridge/Doctrine/ExpressionLanguage/DoctrineParserCache.php +++ /dev/null @@ -1,56 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bridge\Doctrine\ExpressionLanguage; - -@trigger_error('The '.__NAMESPACE__.'\DoctrineParserCache class is deprecated since version 3.2 and will be removed in 4.0. Use the Symfony\Component\Cache\Adapter\DoctrineAdapter class instead.', E_USER_DEPRECATED); - -use Doctrine\Common\Cache\Cache; -use Symfony\Component\ExpressionLanguage\ParsedExpression; -use Symfony\Component\ExpressionLanguage\ParserCache\ParserCacheInterface; - -/** - * @author Adrien Brault - * - * @deprecated DoctrineParserCache class is deprecated since version 3.2 and will be removed in 4.0. Use the Symfony\Component\Cache\Adapter\DoctrineAdapter class instead. - */ -class DoctrineParserCache implements ParserCacheInterface -{ - /** - * @var Cache - */ - private $cache; - - public function __construct(Cache $cache) - { - $this->cache = $cache; - } - - /** - * {@inheritdoc} - */ - public function fetch($key) - { - if (false === $value = $this->cache->fetch($key)) { - return; - } - - return $value; - } - - /** - * {@inheritdoc} - */ - public function save($key, ParsedExpression $expression) - { - $this->cache->save($key, $expression); - } -} diff --git a/src/Symfony/Bridge/Doctrine/Tests/ExpressionLanguage/DoctrineParserCacheTest.php b/src/Symfony/Bridge/Doctrine/Tests/ExpressionLanguage/DoctrineParserCacheTest.php deleted file mode 100644 index 394b1b0dfe9a2..0000000000000 --- a/src/Symfony/Bridge/Doctrine/Tests/ExpressionLanguage/DoctrineParserCacheTest.php +++ /dev/null @@ -1,64 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bridge\Doctrine\Tests\ExpressionLanguage; - -use PHPUnit\Framework\TestCase; -use Symfony\Bridge\Doctrine\ExpressionLanguage\DoctrineParserCache; - -/** - * @group legacy - */ -class DoctrineParserCacheTest extends TestCase -{ - public function testFetch() - { - $doctrineCacheMock = $this->getMockBuilder('Doctrine\Common\Cache\Cache')->getMock(); - $parserCache = new DoctrineParserCache($doctrineCacheMock); - - $doctrineCacheMock->expects($this->once()) - ->method('fetch') - ->will($this->returnValue('bar')); - - $result = $parserCache->fetch('foo'); - - $this->assertEquals('bar', $result); - } - - public function testFetchUnexisting() - { - $doctrineCacheMock = $this->getMockBuilder('Doctrine\Common\Cache\Cache')->getMock(); - $parserCache = new DoctrineParserCache($doctrineCacheMock); - - $doctrineCacheMock - ->expects($this->once()) - ->method('fetch') - ->will($this->returnValue(false)); - - $this->assertNull($parserCache->fetch('')); - } - - public function testSave() - { - $doctrineCacheMock = $this->getMockBuilder('Doctrine\Common\Cache\Cache')->getMock(); - $parserCache = new DoctrineParserCache($doctrineCacheMock); - - $expression = $this->getMockBuilder('Symfony\Component\ExpressionLanguage\ParsedExpression') - ->disableOriginalConstructor() - ->getMock(); - - $doctrineCacheMock->expects($this->once()) - ->method('save') - ->with('foo', $expression); - - $parserCache->save('foo', $expression); - } -} diff --git a/src/Symfony/Component/ExpressionLanguage/CHANGELOG.md b/src/Symfony/Component/ExpressionLanguage/CHANGELOG.md index d00d17c776dc2..6c50b2ea424df 100644 --- a/src/Symfony/Component/ExpressionLanguage/CHANGELOG.md +++ b/src/Symfony/Component/ExpressionLanguage/CHANGELOG.md @@ -1,6 +1,14 @@ CHANGELOG ========= +4.0.0 +----- + + * the first argument of the `ExpressionLanguage` constructor must be an instance + of `CacheItemPoolInterface` + * removed the `ArrayParserCache` and `ParserCacheAdapter` classes + * removed the `ParserCacheInterface` + 2.6.0 ----- diff --git a/src/Symfony/Component/ExpressionLanguage/ExpressionLanguage.php b/src/Symfony/Component/ExpressionLanguage/ExpressionLanguage.php index 9aeefce672c59..64f4dd17371d5 100644 --- a/src/Symfony/Component/ExpressionLanguage/ExpressionLanguage.php +++ b/src/Symfony/Component/ExpressionLanguage/ExpressionLanguage.php @@ -13,8 +13,6 @@ use Psr\Cache\CacheItemPoolInterface; use Symfony\Component\Cache\Adapter\ArrayAdapter; -use Symfony\Component\ExpressionLanguage\ParserCache\ParserCacheAdapter; -use Symfony\Component\ExpressionLanguage\ParserCache\ParserCacheInterface; /** * Allows to compile and evaluate expressions written in your own DSL. @@ -37,17 +35,8 @@ class ExpressionLanguage * @param CacheItemPoolInterface $cache * @param ExpressionFunctionProviderInterface[] $providers */ - public function __construct($cache = null, array $providers = array()) + public function __construct(CacheItemPoolInterface $cache = null, array $providers = array()) { - if (null !== $cache) { - if ($cache instanceof ParserCacheInterface) { - @trigger_error(sprintf('Passing an instance of %s as constructor argument for %s is deprecated as of 3.2 and will be removed in 4.0. Pass an instance of %s instead.', ParserCacheInterface::class, self::class, CacheItemPoolInterface::class), E_USER_DEPRECATED); - $cache = new ParserCacheAdapter($cache); - } elseif (!$cache instanceof CacheItemPoolInterface) { - throw new \InvalidArgumentException(sprintf('Cache argument has to implement %s.', CacheItemPoolInterface::class)); - } - } - $this->cache = $cache ?: new ArrayAdapter(); $this->registerFunctions(); foreach ($providers as $provider) { diff --git a/src/Symfony/Component/ExpressionLanguage/ParserCache/ArrayParserCache.php b/src/Symfony/Component/ExpressionLanguage/ParserCache/ArrayParserCache.php deleted file mode 100644 index 777de421703f7..0000000000000 --- a/src/Symfony/Component/ExpressionLanguage/ParserCache/ArrayParserCache.php +++ /dev/null @@ -1,45 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\ExpressionLanguage\ParserCache; - -@trigger_error('The '.__NAMESPACE__.'\ArrayParserCache class is deprecated since version 3.2 and will be removed in 4.0. Use the Symfony\Component\Cache\Adapter\ArrayAdapter class instead.', E_USER_DEPRECATED); - -use Symfony\Component\ExpressionLanguage\ParsedExpression; - -/** - * @author Adrien Brault - * - * @deprecated ArrayParserCache class is deprecated since version 3.2 and will be removed in 4.0. Use the Symfony\Component\Cache\Adapter\ArrayAdapter class instead. - */ -class ArrayParserCache implements ParserCacheInterface -{ - /** - * @var array - */ - private $cache = array(); - - /** - * {@inheritdoc} - */ - public function fetch($key) - { - return isset($this->cache[$key]) ? $this->cache[$key] : null; - } - - /** - * {@inheritdoc} - */ - public function save($key, ParsedExpression $expression) - { - $this->cache[$key] = $expression; - } -} diff --git a/src/Symfony/Component/ExpressionLanguage/ParserCache/ParserCacheAdapter.php b/src/Symfony/Component/ExpressionLanguage/ParserCache/ParserCacheAdapter.php deleted file mode 100644 index 2867aa3d4841b..0000000000000 --- a/src/Symfony/Component/ExpressionLanguage/ParserCache/ParserCacheAdapter.php +++ /dev/null @@ -1,120 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\ExpressionLanguage\ParserCache; - -use Psr\Cache\CacheItemInterface; -use Psr\Cache\CacheItemPoolInterface; -use Symfony\Component\Cache\CacheItem; - -/** - * @author Alexandre GESLIN - * - * @internal This class should be removed in Symfony 4.0. - */ -class ParserCacheAdapter implements CacheItemPoolInterface -{ - private $pool; - private $createCacheItem; - - public function __construct(ParserCacheInterface $pool) - { - $this->pool = $pool; - - $this->createCacheItem = \Closure::bind( - function ($key, $value, $isHit) { - $item = new CacheItem(); - $item->key = $key; - $item->value = $value; - $item->isHit = $isHit; - - return $item; - }, - null, - CacheItem::class - ); - } - - /** - * {@inheritdoc} - */ - public function getItem($key) - { - $value = $this->pool->fetch($key); - $f = $this->createCacheItem; - - return $f($key, $value, null !== $value); - } - - /** - * {@inheritdoc} - */ - public function save(CacheItemInterface $item) - { - $this->pool->save($item->getKey(), $item->get()); - } - - /** - * {@inheritdoc} - */ - public function getItems(array $keys = array()) - { - throw new \BadMethodCallException('Not implemented'); - } - - /** - * {@inheritdoc} - */ - public function hasItem($key) - { - throw new \BadMethodCallException('Not implemented'); - } - - /** - * {@inheritdoc} - */ - public function clear() - { - throw new \BadMethodCallException('Not implemented'); - } - - /** - * {@inheritdoc} - */ - public function deleteItem($key) - { - throw new \BadMethodCallException('Not implemented'); - } - - /** - * {@inheritdoc} - */ - public function deleteItems(array $keys) - { - throw new \BadMethodCallException('Not implemented'); - } - - /** - * {@inheritdoc} - */ - public function saveDeferred(CacheItemInterface $item) - { - throw new \BadMethodCallException('Not implemented'); - } - - /** - * {@inheritdoc} - */ - public function commit() - { - throw new \BadMethodCallException('Not implemented'); - } -} diff --git a/src/Symfony/Component/ExpressionLanguage/ParserCache/ParserCacheInterface.php b/src/Symfony/Component/ExpressionLanguage/ParserCache/ParserCacheInterface.php deleted file mode 100644 index 1e10cb419a485..0000000000000 --- a/src/Symfony/Component/ExpressionLanguage/ParserCache/ParserCacheInterface.php +++ /dev/null @@ -1,41 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\ExpressionLanguage\ParserCache; - -@trigger_error('The '.__NAMESPACE__.'\ParserCacheInterface interface is deprecated since version 3.2 and will be removed in 4.0. Use Psr\Cache\CacheItemPoolInterface instead.', E_USER_DEPRECATED); - -use Symfony\Component\ExpressionLanguage\ParsedExpression; - -/** - * @author Adrien Brault - * - * @deprecated since version 3.2, to be removed in 4.0. Use Psr\Cache\CacheItemPoolInterface instead. - */ -interface ParserCacheInterface -{ - /** - * Saves an expression in the cache. - * - * @param string $key The cache key - * @param ParsedExpression $expression A ParsedExpression instance to store in the cache - */ - public function save($key, ParsedExpression $expression); - - /** - * Fetches an expression from the cache. - * - * @param string $key The cache key - * - * @return ParsedExpression|null - */ - public function fetch($key); -} diff --git a/src/Symfony/Component/ExpressionLanguage/Tests/ExpressionLanguageTest.php b/src/Symfony/Component/ExpressionLanguage/Tests/ExpressionLanguageTest.php index 82f1c439b9f47..085acbf370a9a 100644 --- a/src/Symfony/Component/ExpressionLanguage/Tests/ExpressionLanguageTest.php +++ b/src/Symfony/Component/ExpressionLanguage/Tests/ExpressionLanguageTest.php @@ -63,47 +63,6 @@ public function testCachedParse() $this->assertSame($savedParsedExpression, $parsedExpression); } - /** - * @group legacy - */ - public function testCachedParseWithDeprecatedParserCacheInterface() - { - $cacheMock = $this->getMockBuilder('Symfony\Component\ExpressionLanguage\ParserCache\ParserCacheInterface')->getMock(); - - $cacheItemMock = $this->getMockBuilder('Psr\Cache\CacheItemInterface')->getMock(); - $savedParsedExpression = null; - $expressionLanguage = new ExpressionLanguage($cacheMock); - - $cacheMock - ->expects($this->exactly(1)) - ->method('fetch') - ->with('1%20%2B%201%2F%2F') - ->willReturn($savedParsedExpression) - ; - - $cacheMock - ->expects($this->exactly(1)) - ->method('save') - ->with('1%20%2B%201%2F%2F', $this->isInstanceOf(ParsedExpression::class)) - ->will($this->returnCallback(function ($key, $expression) use (&$savedParsedExpression) { - $savedParsedExpression = $expression; - })) - ; - - $parsedExpression = $expressionLanguage->parse('1 + 1', array()); - $this->assertSame($savedParsedExpression, $parsedExpression); - } - - /** - * @expectedException \InvalidArgumentException - * @expectedExceptionMessage Cache argument has to implement Psr\Cache\CacheItemPoolInterface. - */ - public function testWrongCacheImplementation() - { - $cacheMock = $this->getMockBuilder('Psr\Cache\CacheItemSpoolInterface')->getMock(); - $expressionLanguage = new ExpressionLanguage($cacheMock); - } - public function testConstantFunction() { $expressionLanguage = new ExpressionLanguage(); diff --git a/src/Symfony/Component/ExpressionLanguage/Tests/ParserCache/ParserCacheAdapterTest.php b/src/Symfony/Component/ExpressionLanguage/Tests/ParserCache/ParserCacheAdapterTest.php deleted file mode 100644 index 447316111b840..0000000000000 --- a/src/Symfony/Component/ExpressionLanguage/Tests/ParserCache/ParserCacheAdapterTest.php +++ /dev/null @@ -1,140 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\ExpressionLanguage\Tests; - -use PHPUnit\Framework\TestCase; -use Symfony\Component\ExpressionLanguage\ParsedExpression; -use Symfony\Component\ExpressionLanguage\ParserCache\ParserCacheAdapter; -use Symfony\Component\ExpressionLanguage\Node\Node; - -/** - * @group legacy - */ -class ParserCacheAdapterTest extends TestCase -{ - public function testGetItem() - { - $poolMock = $this->getMockBuilder('Symfony\Component\ExpressionLanguage\ParserCache\ParserCacheInterface')->getMock(); - - $key = 'key'; - $value = 'value'; - $parserCacheAdapter = new ParserCacheAdapter($poolMock); - - $poolMock - ->expects($this->once()) - ->method('fetch') - ->with($key) - ->willReturn($value) - ; - - $cacheItem = $parserCacheAdapter->getItem($key); - - $this->assertEquals($cacheItem->get(), $value); - $this->assertEquals($cacheItem->isHit(), true); - } - - public function testSave() - { - $poolMock = $this->getMockBuilder('Symfony\Component\ExpressionLanguage\ParserCache\ParserCacheInterface')->getMock(); - $cacheItemMock = $this->getMockBuilder('Psr\Cache\CacheItemInterface')->getMock(); - $key = 'key'; - $value = new ParsedExpression('1 + 1', new Node(array(), array())); - $parserCacheAdapter = new ParserCacheAdapter($poolMock); - - $poolMock - ->expects($this->once()) - ->method('save') - ->with($key, $value) - ; - - $cacheItemMock - ->expects($this->once()) - ->method('getKey') - ->willReturn($key) - ; - - $cacheItemMock - ->expects($this->once()) - ->method('get') - ->willReturn($value) - ; - - $cacheItem = $parserCacheAdapter->save($cacheItemMock); - } - - public function testGetItems() - { - $poolMock = $this->getMockBuilder('Symfony\Component\ExpressionLanguage\ParserCache\ParserCacheInterface')->getMock(); - $parserCacheAdapter = new ParserCacheAdapter($poolMock); - $this->{method_exists($this, $_ = 'expectException') ? $_ : 'setExpectedException'}(\BadMethodCallException::class); - - $parserCacheAdapter->getItems(); - } - - public function testHasItem() - { - $poolMock = $this->getMockBuilder('Symfony\Component\ExpressionLanguage\ParserCache\ParserCacheInterface')->getMock(); - $key = 'key'; - $parserCacheAdapter = new ParserCacheAdapter($poolMock); - $this->{method_exists($this, $_ = 'expectException') ? $_ : 'setExpectedException'}(\BadMethodCallException::class); - - $parserCacheAdapter->hasItem($key); - } - - public function testClear() - { - $poolMock = $this->getMockBuilder('Symfony\Component\ExpressionLanguage\ParserCache\ParserCacheInterface')->getMock(); - $parserCacheAdapter = new ParserCacheAdapter($poolMock); - $this->{method_exists($this, $_ = 'expectException') ? $_ : 'setExpectedException'}(\BadMethodCallException::class); - - $parserCacheAdapter->clear(); - } - - public function testDeleteItem() - { - $poolMock = $this->getMockBuilder('Symfony\Component\ExpressionLanguage\ParserCache\ParserCacheInterface')->getMock(); - $key = 'key'; - $parserCacheAdapter = new ParserCacheAdapter($poolMock); - $this->{method_exists($this, $_ = 'expectException') ? $_ : 'setExpectedException'}(\BadMethodCallException::class); - - $parserCacheAdapter->deleteItem($key); - } - - public function testDeleteItems() - { - $poolMock = $this->getMockBuilder('Symfony\Component\ExpressionLanguage\ParserCache\ParserCacheInterface')->getMock(); - $keys = array('key'); - $parserCacheAdapter = new ParserCacheAdapter($poolMock); - $this->{method_exists($this, $_ = 'expectException') ? $_ : 'setExpectedException'}(\BadMethodCallException::class); - - $parserCacheAdapter->deleteItems($keys); - } - - public function testSaveDeferred() - { - $poolMock = $this->getMockBuilder('Symfony\Component\ExpressionLanguage\ParserCache\ParserCacheInterface')->getMock(); - $parserCacheAdapter = new ParserCacheAdapter($poolMock); - $cacheItemMock = $this->getMockBuilder('Psr\Cache\CacheItemInterface')->getMock(); - $this->{method_exists($this, $_ = 'expectException') ? $_ : 'setExpectedException'}(\BadMethodCallException::class); - - $parserCacheAdapter->saveDeferred($cacheItemMock); - } - - public function testCommit() - { - $poolMock = $this->getMockBuilder('Symfony\Component\ExpressionLanguage\ParserCache\ParserCacheInterface')->getMock(); - $parserCacheAdapter = new ParserCacheAdapter($poolMock); - $this->{method_exists($this, $_ = 'expectException') ? $_ : 'setExpectedException'}(\BadMethodCallException::class); - - $parserCacheAdapter->commit(); - } -} From b7c76f7147249e33508467917b07fd470585ee9f Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Sun, 21 May 2017 09:51:07 +0200 Subject: [PATCH 0025/1099] [FrameworkBundle] FC with EventDispatcher 4.0 --- .../DependencyInjection/FrameworkExtension.php | 9 +++++++++ .../Tests/Functional/AutowiringTypesTest.php | 8 +++++++- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php index c65c1f8e740be..993bae7f4a7f8 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php @@ -32,6 +32,8 @@ use Symfony\Component\DependencyInjection\Loader\XmlFileLoader; use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\DependencyInjection\ServiceSubscriberInterface; +use Symfony\Component\EventDispatcher\ContainerAwareEventDispatcher; +use Symfony\Component\EventDispatcher\EventDispatcher; use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\ExpressionLanguage\ExpressionLanguage; use Symfony\Component\Finder\Finder; @@ -94,6 +96,13 @@ public function load(array $configs, ContainerBuilder $container) $loader->load('web.xml'); $loader->load('services.xml'); + // forward compatibility with Symfony 4.0 where the ContainerAwareEventDispatcher class is removed + if (!class_exists(ContainerAwareEventDispatcher::class)) { + $definition = $container->getDefinition('event_dispatcher'); + $definition->setClass(EventDispatcher::class); + $definition->setArguments(array()); + } + if (PHP_VERSION_ID < 70000) { $definition = $container->getDefinition('kernel.class_cache.cache_warmer'); $definition->addTag('kernel.cache_warmer'); diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/AutowiringTypesTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/AutowiringTypesTest.php index fa92514a9c14c..057a522fb3f95 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/AutowiringTypesTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/AutowiringTypesTest.php @@ -14,6 +14,7 @@ use Doctrine\Common\Annotations\AnnotationReader; use Doctrine\Common\Annotations\CachedReader; use Symfony\Component\Cache\Adapter\FilesystemAdapter; +use Symfony\Component\EventDispatcher\EventDispatcher; use Symfony\Component\Templating\EngineInterface as ComponentEngineInterface; use Symfony\Component\HttpKernel\Debug\TraceableEventDispatcher; use Symfony\Component\EventDispatcher\ContainerAwareEventDispatcher; @@ -55,7 +56,12 @@ public function testEventDispatcherAutowiring() $container = static::$kernel->getContainer(); $autowiredServices = $container->get('test.autowiring_types.autowired_services'); - $this->assertInstanceOf(ContainerAwareEventDispatcher::class, $autowiredServices->getDispatcher(), 'The event_dispatcher service should be injected if the debug is not enabled'); + + if (class_exists(ContainerAwareEventDispatcher::class)) { + $this->assertInstanceOf(ContainerAwareEventDispatcher::class, $autowiredServices->getDispatcher(), 'The event_dispatcher service should be injected if the debug is not enabled'); + } else { + $this->assertInstanceOf(EventDispatcher::class, $autowiredServices->getDispatcher(), 'The event_dispatcher service should be injected if the debug is not enabled'); + } static::bootKernel(array('debug' => true)); $container = static::$kernel->getContainer(); From f20885eefee8845d1c917b02edb992780e856a90 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Sat, 20 May 2017 09:17:05 +0200 Subject: [PATCH 0026/1099] do not used deprecated validator test case class --- .../Validator/Constraints/UniqueEntityValidatorTest.php | 6 ++---- src/Symfony/Bridge/Doctrine/composer.json | 2 +- .../Extension/Validator/Constraints/FormValidatorTest.php | 6 ++---- src/Symfony/Component/Form/composer.json | 2 +- .../Validator/Constraints/UserPasswordValidatorTest.php | 4 ++-- src/Symfony/Component/Security/Core/composer.json | 2 +- src/Symfony/Component/Security/composer.json | 2 +- 7 files changed, 10 insertions(+), 14 deletions(-) diff --git a/src/Symfony/Bridge/Doctrine/Tests/Validator/Constraints/UniqueEntityValidatorTest.php b/src/Symfony/Bridge/Doctrine/Tests/Validator/Constraints/UniqueEntityValidatorTest.php index 0045e76cbca83..5091624bfc99d 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/Validator/Constraints/UniqueEntityValidatorTest.php +++ b/src/Symfony/Bridge/Doctrine/Tests/Validator/Constraints/UniqueEntityValidatorTest.php @@ -31,15 +31,13 @@ use Symfony\Bridge\Doctrine\Tests\Fixtures\Type\StringWrapper; use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity; use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntityValidator; -use Symfony\Component\Validator\Tests\Constraints\AbstractConstraintValidatorTest; +use Symfony\Component\Validator\Test\ConstraintValidatorTestCase; use Doctrine\ORM\Tools\SchemaTool; /** * @author Bernhard Schussek - * - * @todo use ConstraintValidatorTestCase when symfony/validator ~3.2 is required. */ -class UniqueEntityValidatorTest extends AbstractConstraintValidatorTest +class UniqueEntityValidatorTest extends ConstraintValidatorTestCase { const EM_NAME = 'foo'; diff --git a/src/Symfony/Bridge/Doctrine/composer.json b/src/Symfony/Bridge/Doctrine/composer.json index f4da3ac162796..28fb8491d49f0 100644 --- a/src/Symfony/Bridge/Doctrine/composer.json +++ b/src/Symfony/Bridge/Doctrine/composer.json @@ -30,7 +30,7 @@ "symfony/proxy-manager-bridge": "~2.8|~3.0|~4.0.0", "symfony/security": "~2.8|~3.0|~4.0.0", "symfony/expression-language": "~2.8|~3.0|~4.0.0", - "symfony/validator": "^2.8.18|^3.2.5|~4.0.0", + "symfony/validator": "^3.2.5|~4.0.0", "symfony/translation": "~2.8|~3.0|~4.0.0", "doctrine/data-fixtures": "1.0.*", "doctrine/dbal": "~2.4", diff --git a/src/Symfony/Component/Form/Tests/Extension/Validator/Constraints/FormValidatorTest.php b/src/Symfony/Component/Form/Tests/Extension/Validator/Constraints/FormValidatorTest.php index 49e32435f11e3..998a1324364c1 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Validator/Constraints/FormValidatorTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Validator/Constraints/FormValidatorTest.php @@ -22,14 +22,12 @@ use Symfony\Component\Validator\Constraints\NotNull; use Symfony\Component\Validator\Constraints\NotBlank; use Symfony\Component\Validator\Constraints\Valid; -use Symfony\Component\Validator\Tests\Constraints\AbstractConstraintValidatorTest; +use Symfony\Component\Validator\Test\ConstraintValidatorTestCase; /** * @author Bernhard Schussek - * - * @todo use ConstraintValidatorTestCase when symfony/validator ~3.2 is required. */ -class FormValidatorTest extends AbstractConstraintValidatorTest +class FormValidatorTest extends ConstraintValidatorTestCase { /** * @var \PHPUnit_Framework_MockObject_MockObject diff --git a/src/Symfony/Component/Form/composer.json b/src/Symfony/Component/Form/composer.json index edd32cc9ed85a..a1e42ca025620 100644 --- a/src/Symfony/Component/Form/composer.json +++ b/src/Symfony/Component/Form/composer.json @@ -25,7 +25,7 @@ }, "require-dev": { "doctrine/collections": "~1.0", - "symfony/validator": "^2.8.18|^3.2.5|~4.0.0", + "symfony/validator": "^3.2.5|~4.0.0", "symfony/dependency-injection": "~3.3|~4.0.0", "symfony/config": "~2.7|~3.0|~4.0.0", "symfony/http-foundation": "~2.8|~3.0|~4.0.0", diff --git a/src/Symfony/Component/Security/Core/Tests/Validator/Constraints/UserPasswordValidatorTest.php b/src/Symfony/Component/Security/Core/Tests/Validator/Constraints/UserPasswordValidatorTest.php index 7ebe65c647d99..f9ac5a4ded69a 100644 --- a/src/Symfony/Component/Security/Core/Tests/Validator/Constraints/UserPasswordValidatorTest.php +++ b/src/Symfony/Component/Security/Core/Tests/Validator/Constraints/UserPasswordValidatorTest.php @@ -16,12 +16,12 @@ use Symfony\Component\Security\Core\Encoder\PasswordEncoderInterface; use Symfony\Component\Security\Core\Validator\Constraints\UserPassword; use Symfony\Component\Security\Core\Validator\Constraints\UserPasswordValidator; -use Symfony\Component\Validator\Tests\Constraints\AbstractConstraintValidatorTest; +use Symfony\Component\Validator\Test\ConstraintValidatorTestCase; /** * @author Bernhard Schussek */ -abstract class UserPasswordValidatorTest extends AbstractConstraintValidatorTest +abstract class UserPasswordValidatorTest extends ConstraintValidatorTestCase { const PASSWORD = 's3Cr3t'; diff --git a/src/Symfony/Component/Security/Core/composer.json b/src/Symfony/Component/Security/Core/composer.json index 81fa15414c953..1fa423cd4479e 100644 --- a/src/Symfony/Component/Security/Core/composer.json +++ b/src/Symfony/Component/Security/Core/composer.json @@ -24,7 +24,7 @@ "symfony/expression-language": "~2.8|~3.0|~4.0.0", "symfony/http-foundation": "~2.8|~3.0|~4.0.0", "symfony/ldap": "~3.1|~4.0.0", - "symfony/validator": "^2.8.18|^3.2.5|~4.0.0", + "symfony/validator": "^3.2.5|~4.0.0", "psr/log": "~1.0" }, "suggest": { diff --git a/src/Symfony/Component/Security/composer.json b/src/Symfony/Component/Security/composer.json index a0b91b459a584..2d7c69b985b86 100644 --- a/src/Symfony/Component/Security/composer.json +++ b/src/Symfony/Component/Security/composer.json @@ -35,7 +35,7 @@ "symfony/finder": "~2.8|~3.0|~4.0.0", "symfony/polyfill-intl-icu": "~1.0", "symfony/routing": "~2.8|~3.0|~4.0.0", - "symfony/validator": "^2.8.18|^3.2.5|~4.0.0", + "symfony/validator": "^3.2.5|~4.0.0", "symfony/expression-language": "~2.8|~3.0|~4.0.0", "symfony/ldap": "~3.1|~4.0.0", "psr/log": "~1.0" From 9b4a0c7af4b3a0b6d29eaf98c43438019172e89a Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Sun, 21 May 2017 10:35:28 +0200 Subject: [PATCH 0027/1099] bug #22814 [FrameworkBundle] FC with EventDispatcher 4.0 (xabbuh) This PR was merged into the 4.0-dev branch. Discussion ---------- [FrameworkBundle] FC with EventDispatcher 4.0 | Q | A | ------------- | --- | Branch? | 3.4 | Bug fix? | yes | New feature? | no | BC breaks? | no | Deprecations? | no | Tests pass? | yes | Fixed tickets | https://github.com/symfony/symfony/pull/22796#issuecomment-302875580 | License | MIT | Doc PR | Commits ------- b7c76f7 [FrameworkBundle] FC with EventDispatcher 4.0 --- .../DependencyInjection/FrameworkExtension.php | 9 +++++++++ .../Tests/Functional/AutowiringTypesTest.php | 8 +++++++- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php index c65c1f8e740be..993bae7f4a7f8 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php @@ -32,6 +32,8 @@ use Symfony\Component\DependencyInjection\Loader\XmlFileLoader; use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\DependencyInjection\ServiceSubscriberInterface; +use Symfony\Component\EventDispatcher\ContainerAwareEventDispatcher; +use Symfony\Component\EventDispatcher\EventDispatcher; use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\ExpressionLanguage\ExpressionLanguage; use Symfony\Component\Finder\Finder; @@ -94,6 +96,13 @@ public function load(array $configs, ContainerBuilder $container) $loader->load('web.xml'); $loader->load('services.xml'); + // forward compatibility with Symfony 4.0 where the ContainerAwareEventDispatcher class is removed + if (!class_exists(ContainerAwareEventDispatcher::class)) { + $definition = $container->getDefinition('event_dispatcher'); + $definition->setClass(EventDispatcher::class); + $definition->setArguments(array()); + } + if (PHP_VERSION_ID < 70000) { $definition = $container->getDefinition('kernel.class_cache.cache_warmer'); $definition->addTag('kernel.cache_warmer'); diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/AutowiringTypesTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/AutowiringTypesTest.php index fa92514a9c14c..057a522fb3f95 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/AutowiringTypesTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/AutowiringTypesTest.php @@ -14,6 +14,7 @@ use Doctrine\Common\Annotations\AnnotationReader; use Doctrine\Common\Annotations\CachedReader; use Symfony\Component\Cache\Adapter\FilesystemAdapter; +use Symfony\Component\EventDispatcher\EventDispatcher; use Symfony\Component\Templating\EngineInterface as ComponentEngineInterface; use Symfony\Component\HttpKernel\Debug\TraceableEventDispatcher; use Symfony\Component\EventDispatcher\ContainerAwareEventDispatcher; @@ -55,7 +56,12 @@ public function testEventDispatcherAutowiring() $container = static::$kernel->getContainer(); $autowiredServices = $container->get('test.autowiring_types.autowired_services'); - $this->assertInstanceOf(ContainerAwareEventDispatcher::class, $autowiredServices->getDispatcher(), 'The event_dispatcher service should be injected if the debug is not enabled'); + + if (class_exists(ContainerAwareEventDispatcher::class)) { + $this->assertInstanceOf(ContainerAwareEventDispatcher::class, $autowiredServices->getDispatcher(), 'The event_dispatcher service should be injected if the debug is not enabled'); + } else { + $this->assertInstanceOf(EventDispatcher::class, $autowiredServices->getDispatcher(), 'The event_dispatcher service should be injected if the debug is not enabled'); + } static::bootKernel(array('debug' => true)); $container = static::$kernel->getContainer(); From 0813e14289b1d451a4286018f08e1548df6a8cca Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Sat, 20 May 2017 08:34:47 +0200 Subject: [PATCH 0028/1099] [Ldap] remove deprecated features --- src/Symfony/Component/Ldap/CHANGELOG.md | 5 + src/Symfony/Component/Ldap/LdapClient.php | 127 ---------- .../Component/Ldap/LdapClientInterface.php | 36 --- .../Component/Ldap/Tests/LdapClientTest.php | 229 ------------------ 4 files changed, 5 insertions(+), 392 deletions(-) delete mode 100644 src/Symfony/Component/Ldap/LdapClient.php delete mode 100644 src/Symfony/Component/Ldap/LdapClientInterface.php delete mode 100644 src/Symfony/Component/Ldap/Tests/LdapClientTest.php diff --git a/src/Symfony/Component/Ldap/CHANGELOG.md b/src/Symfony/Component/Ldap/CHANGELOG.md index 61af4adf151a2..e70e61c45ed85 100644 --- a/src/Symfony/Component/Ldap/CHANGELOG.md +++ b/src/Symfony/Component/Ldap/CHANGELOG.md @@ -1,6 +1,11 @@ CHANGELOG ========= +4.0.0 +----- + + * removed the `LdapClient` class and the `LdapClientInterface` + 3.1.0 ----- diff --git a/src/Symfony/Component/Ldap/LdapClient.php b/src/Symfony/Component/Ldap/LdapClient.php deleted file mode 100644 index b20c7ea4828d5..0000000000000 --- a/src/Symfony/Component/Ldap/LdapClient.php +++ /dev/null @@ -1,127 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Ldap; - -@trigger_error('The '.__NAMESPACE__.'\LdapClient class is deprecated since version 3.1 and will be removed in 4.0. Use the Ldap class directly instead.', E_USER_DEPRECATED); - -/** - * @author Grégoire Pineau - * @author Francis Besset - * @author Charles Sarrazin - * - * @deprecated since version 3.1, to be removed in 4.0. Use the Ldap class instead. - */ -final class LdapClient implements LdapClientInterface -{ - private $ldap; - - public function __construct($host = null, $port = 389, $version = 3, $useSsl = false, $useStartTls = false, $optReferrals = false, LdapInterface $ldap = null) - { - $config = $this->normalizeConfig($host, $port, $version, $useSsl, $useStartTls, $optReferrals); - - $this->ldap = null !== $ldap ? $ldap : Ldap::create('ext_ldap', $config); - } - - /** - * {@inheritdoc} - */ - public function bind($dn = null, $password = null) - { - $this->ldap->bind($dn, $password); - } - - /** - * {@inheritdoc} - */ - public function query($dn, $query, array $options = array()) - { - return $this->ldap->query($dn, $query, $options); - } - - /** - * {@inheritdoc} - */ - public function getEntryManager() - { - return $this->ldap->getEntryManager(); - } - - /** - * {@inheritdoc} - */ - public function find($dn, $query, $filter = '*') - { - @trigger_error('The "find" method is deprecated since version 3.1 and will be removed in 4.0. Use the "query" method instead.', E_USER_DEPRECATED); - - $query = $this->ldap->query($dn, $query, array('filter' => $filter)); - $entries = $query->execute(); - $result = array( - 'count' => 0, - ); - - foreach ($entries as $entry) { - $resultEntry = array(); - - foreach ($entry->getAttributes() as $attribute => $values) { - $resultAttribute = array( - 'count' => count($values), - ); - - foreach ($values as $val) { - $resultAttribute[] = $val; - } - $attributeName = strtolower($attribute); - - $resultAttribute['count'] = count($values); - $resultEntry[$attributeName] = $resultAttribute; - $resultEntry[] = $attributeName; - } - - $resultEntry['count'] = count($resultEntry) / 2; - $resultEntry['dn'] = $entry->getDn(); - $result[] = $resultEntry; - } - - $result['count'] = count($result) - 1; - - return $result; - } - - /** - * {@inheritdoc} - */ - public function escape($subject, $ignore = '', $flags = 0) - { - return $this->ldap->escape($subject, $ignore, $flags); - } - - private function normalizeConfig($host, $port, $version, $useSsl, $useStartTls, $optReferrals) - { - if ((bool) $useSsl) { - $encryption = 'ssl'; - } elseif ((bool) $useStartTls) { - $encryption = 'tls'; - } else { - $encryption = 'none'; - } - - return array( - 'host' => $host, - 'port' => $port, - 'encryption' => $encryption, - 'options' => array( - 'protocol_version' => $version, - 'referrals' => (bool) $optReferrals, - ), - ); - } -} diff --git a/src/Symfony/Component/Ldap/LdapClientInterface.php b/src/Symfony/Component/Ldap/LdapClientInterface.php deleted file mode 100644 index 0872ee082e813..0000000000000 --- a/src/Symfony/Component/Ldap/LdapClientInterface.php +++ /dev/null @@ -1,36 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Ldap; - -/** - * Ldap interface. - * - * This interface is used for the BC layer with branch 2.8 and 3.0. - * - * @author Grégoire Pineau - * @author Charles Sarrazin - * - * @deprecated since version 3.1, to be removed in 4.0. Use the LdapInterface instead. - */ -interface LdapClientInterface extends LdapInterface -{ - /** - * Find a username into ldap connection. - * - * @param string $dn - * @param string $query - * @param mixed $filter - * - * @return array|null - */ - public function find($dn, $query, $filter = '*'); -} diff --git a/src/Symfony/Component/Ldap/Tests/LdapClientTest.php b/src/Symfony/Component/Ldap/Tests/LdapClientTest.php deleted file mode 100644 index 176c8f16f9320..0000000000000 --- a/src/Symfony/Component/Ldap/Tests/LdapClientTest.php +++ /dev/null @@ -1,229 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Ldap\Tests; - -use Symfony\Component\Ldap\Adapter\CollectionInterface; -use Symfony\Component\Ldap\Adapter\QueryInterface; -use Symfony\Component\Ldap\Entry; -use Symfony\Component\Ldap\LdapClient; -use Symfony\Component\Ldap\LdapInterface; - -/** - * @group legacy - */ -class LdapClientTest extends LdapTestCase -{ - /** @var LdapClient */ - private $client; - /** @var \PHPUnit_Framework_MockObject_MockObject */ - private $ldap; - - protected function setUp() - { - $this->ldap = $this->getMockBuilder(LdapInterface::class)->getMock(); - - $this->client = new LdapClient(null, 389, 3, false, false, false, $this->ldap); - } - - public function testLdapBind() - { - $this->ldap - ->expects($this->once()) - ->method('bind') - ->with('foo', 'bar') - ; - $this->client->bind('foo', 'bar'); - } - - public function testLdapEscape() - { - $this->ldap - ->expects($this->once()) - ->method('escape') - ->with('foo', 'bar', 'baz') - ; - $this->client->escape('foo', 'bar', 'baz'); - } - - public function testLdapQuery() - { - $this->ldap - ->expects($this->once()) - ->method('query') - ->with('foo', 'bar', array('baz')) - ; - $this->client->query('foo', 'bar', array('baz')); - } - - public function testLdapFind() - { - $collection = $this->getMockBuilder(CollectionInterface::class)->getMock(); - $collection - ->expects($this->once()) - ->method('getIterator') - ->will($this->returnValue(new \ArrayIterator(array( - new Entry('cn=qux,dc=foo,dc=com', array( - 'cn' => array('qux'), - 'dc' => array('com', 'foo'), - 'givenName' => array('Qux'), - )), - new Entry('cn=baz,dc=foo,dc=com', array( - 'cn' => array('baz'), - 'dc' => array('com', 'foo'), - 'givenName' => array('Baz'), - )), - )))) - ; - $query = $this->getMockBuilder(QueryInterface::class)->getMock(); - $query - ->expects($this->once()) - ->method('execute') - ->will($this->returnValue($collection)) - ; - $this->ldap - ->expects($this->once()) - ->method('query') - ->with('dc=foo,dc=com', 'bar', array('filter' => 'baz')) - ->willReturn($query) - ; - - $expected = array( - 'count' => 2, - 0 => array( - 'count' => 3, - 0 => 'cn', - 'cn' => array( - 'count' => 1, - 0 => 'qux', - ), - 1 => 'dc', - 'dc' => array( - 'count' => 2, - 0 => 'com', - 1 => 'foo', - ), - 2 => 'givenname', - 'givenname' => array( - 'count' => 1, - 0 => 'Qux', - ), - 'dn' => 'cn=qux,dc=foo,dc=com', - ), - 1 => array( - 'count' => 3, - 0 => 'cn', - 'cn' => array( - 'count' => 1, - 0 => 'baz', - ), - 1 => 'dc', - 'dc' => array( - 'count' => 2, - 0 => 'com', - 1 => 'foo', - ), - 2 => 'givenname', - 'givenname' => array( - 'count' => 1, - 0 => 'Baz', - ), - 'dn' => 'cn=baz,dc=foo,dc=com', - ), - ); - $this->assertEquals($expected, $this->client->find('dc=foo,dc=com', 'bar', 'baz')); - } - - /** - * @dataProvider provideConfig - */ - public function testLdapClientConfig($args, $expected) - { - $reflObj = new \ReflectionObject($this->client); - $reflMethod = $reflObj->getMethod('normalizeConfig'); - $reflMethod->setAccessible(true); - array_unshift($args, $this->client); - $this->assertEquals($expected, call_user_func_array(array($reflMethod, 'invoke'), $args)); - } - - /** - * @group functional - * @requires extension ldap - */ - public function testLdapClientFunctional() - { - $config = $this->getLdapConfig(); - $ldap = new LdapClient($config['host'], $config['port']); - $ldap->bind('cn=admin,dc=symfony,dc=com', 'symfony'); - $result = $ldap->find('dc=symfony,dc=com', '(&(objectclass=person)(ou=Maintainers))'); - - $con = @ldap_connect($config['host'], $config['port']); - @ldap_bind($con, 'cn=admin,dc=symfony,dc=com', 'symfony'); - $search = @ldap_search($con, 'dc=symfony,dc=com', '(&(objectclass=person)(ou=Maintainers))', array('*')); - $expected = @ldap_get_entries($con, $search); - - $this->assertSame($expected, $result); - } - - public function provideConfig() - { - return array( - array( - array('localhost', 389, 3, true, false, false), - array( - 'host' => 'localhost', - 'port' => 389, - 'encryption' => 'ssl', - 'options' => array( - 'protocol_version' => 3, - 'referrals' => false, - ), - ), - ), - array( - array('localhost', 389, 3, false, true, false), - array( - 'host' => 'localhost', - 'port' => 389, - 'encryption' => 'tls', - 'options' => array( - 'protocol_version' => 3, - 'referrals' => false, - ), - ), - ), - array( - array('localhost', 389, 3, false, false, false), - array( - 'host' => 'localhost', - 'port' => 389, - 'encryption' => 'none', - 'options' => array( - 'protocol_version' => 3, - 'referrals' => false, - ), - ), - ), - array( - array('localhost', 389, 3, false, false, false), - array( - 'host' => 'localhost', - 'port' => 389, - 'encryption' => 'none', - 'options' => array( - 'protocol_version' => 3, - 'referrals' => false, - ), - ), - ), - ); - } -} From 598bec44a2dc3665e30d604d6b7dd6d17d5d9466 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Sat, 20 May 2017 08:26:28 +0200 Subject: [PATCH 0029/1099] [EventDispatcher] remove deprecated features --- .../FrameworkExtension.php | 10 - .../Resources/config/services.xml | 4 +- .../Tests/Functional/AutowiringTypesTest.php | 8 +- .../DependencyInjection/ContainerBuilder.php | 6 +- .../Component/EventDispatcher/CHANGELOG.md | 5 + .../ContainerAwareEventDispatcher.php | 211 ------------------ .../ContainerAwareEventDispatcherTest.php | 210 ----------------- 7 files changed, 8 insertions(+), 446 deletions(-) delete mode 100644 src/Symfony/Component/EventDispatcher/ContainerAwareEventDispatcher.php delete mode 100644 src/Symfony/Component/EventDispatcher/Tests/ContainerAwareEventDispatcherTest.php diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php index 661eb9bc78a39..d81cfe88c0502 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php @@ -32,8 +32,6 @@ use Symfony\Component\DependencyInjection\Loader\XmlFileLoader; use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\DependencyInjection\ServiceSubscriberInterface; -use Symfony\Component\EventDispatcher\ContainerAwareEventDispatcher; -use Symfony\Component\EventDispatcher\EventDispatcher; use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\ExpressionLanguage\ExpressionLanguage; use Symfony\Component\Finder\Finder; @@ -98,13 +96,6 @@ public function load(array $configs, ContainerBuilder $container) $loader->load('web.xml'); $loader->load('services.xml'); - // forward compatibility with Symfony 4.0 where the ContainerAwareEventDispatcher class is removed - if (!class_exists(ContainerAwareEventDispatcher::class)) { - $definition = $container->getDefinition('event_dispatcher'); - $definition->setClass(EventDispatcher::class); - $definition->setArguments(array()); - } - if (PHP_VERSION_ID < 70000) { $definition = $container->getDefinition('kernel.class_cache.cache_warmer'); $definition->addTag('kernel.cache_warmer'); @@ -309,7 +300,6 @@ public function load(array $configs, ContainerBuilder $container) 'Symfony\\Component\\DependencyInjection\\Container', 'Symfony\\Component\\EventDispatcher\\Event', - 'Symfony\\Component\\EventDispatcher\\ContainerAwareEventDispatcher', 'Symfony\\Component\\HttpKernel\\EventListener\\ResponseListener', 'Symfony\\Component\\HttpKernel\\EventListener\\RouterListener', diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/services.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/services.xml index 7c935a6bd0198..6babacc0eb06a 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/services.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/services.xml @@ -7,9 +7,7 @@ - - - + diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/AutowiringTypesTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/AutowiringTypesTest.php index 057a522fb3f95..0a7d2391d55e9 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/AutowiringTypesTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/AutowiringTypesTest.php @@ -17,7 +17,6 @@ use Symfony\Component\EventDispatcher\EventDispatcher; use Symfony\Component\Templating\EngineInterface as ComponentEngineInterface; use Symfony\Component\HttpKernel\Debug\TraceableEventDispatcher; -use Symfony\Component\EventDispatcher\ContainerAwareEventDispatcher; use Symfony\Bundle\FrameworkBundle\Templating\EngineInterface as FrameworkBundleEngineInterface; class AutowiringTypesTest extends WebTestCase @@ -56,12 +55,7 @@ public function testEventDispatcherAutowiring() $container = static::$kernel->getContainer(); $autowiredServices = $container->get('test.autowiring_types.autowired_services'); - - if (class_exists(ContainerAwareEventDispatcher::class)) { - $this->assertInstanceOf(ContainerAwareEventDispatcher::class, $autowiredServices->getDispatcher(), 'The event_dispatcher service should be injected if the debug is not enabled'); - } else { - $this->assertInstanceOf(EventDispatcher::class, $autowiredServices->getDispatcher(), 'The event_dispatcher service should be injected if the debug is not enabled'); - } + $this->assertInstanceOf(EventDispatcher::class, $autowiredServices->getDispatcher(), 'The event_dispatcher service should be injected if the debug is not enabled'); static::bootKernel(array('debug' => true)); $container = static::$kernel->getContainer(); diff --git a/src/Symfony/Component/DependencyInjection/ContainerBuilder.php b/src/Symfony/Component/DependencyInjection/ContainerBuilder.php index 0a2d673c789df..e73539e8a2664 100644 --- a/src/Symfony/Component/DependencyInjection/ContainerBuilder.php +++ b/src/Symfony/Component/DependencyInjection/ContainerBuilder.php @@ -39,7 +39,6 @@ use Symfony\Component\DependencyInjection\LazyProxy\Instantiator\InstantiatorInterface; use Symfony\Component\DependencyInjection\LazyProxy\Instantiator\RealServiceInstantiator; use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface; -use Symfony\Component\EventDispatcher\ContainerAwareEventDispatcher; use Symfony\Component\ExpressionLanguage\Expression; use Symfony\Component\ExpressionLanguage\ExpressionFunctionProviderInterface; @@ -1076,11 +1075,8 @@ private function createService(Definition $definition, $id, $tryProxy = true) $r = new \ReflectionClass($class = $parameterBag->resolveValue($definition->getClass())); $service = null === $r->getConstructor() ? $r->newInstance() : $r->newInstanceArgs($arguments); - // don't trigger deprecations for internal uses - // @deprecated since version 3.3, to be removed in 4.0 along with the deprecated class - $deprecationWhitelist = array('event_dispatcher' => ContainerAwareEventDispatcher::class); - if (!$definition->isDeprecated() && 0 < strpos($r->getDocComment(), "\n * @deprecated ") && (!isset($deprecationWhitelist[$id]) || $deprecationWhitelist[$id] !== $class)) { + if (!$definition->isDeprecated() && 0 < strpos($r->getDocComment(), "\n * @deprecated ")) { @trigger_error(sprintf('The "%s" service relies on the deprecated "%s" class. It should either be deprecated or its implementation upgraded.', $id, $r->name), E_USER_DEPRECATED); } } diff --git a/src/Symfony/Component/EventDispatcher/CHANGELOG.md b/src/Symfony/Component/EventDispatcher/CHANGELOG.md index 51c1d919bb4df..a0613e89417ce 100644 --- a/src/Symfony/Component/EventDispatcher/CHANGELOG.md +++ b/src/Symfony/Component/EventDispatcher/CHANGELOG.md @@ -1,6 +1,11 @@ CHANGELOG ========= +4.0.0 +----- + + * removed the `ContainerAwareEventDispatcher` class + 3.3.0 ----- diff --git a/src/Symfony/Component/EventDispatcher/ContainerAwareEventDispatcher.php b/src/Symfony/Component/EventDispatcher/ContainerAwareEventDispatcher.php deleted file mode 100644 index 195acf2e0b6e6..0000000000000 --- a/src/Symfony/Component/EventDispatcher/ContainerAwareEventDispatcher.php +++ /dev/null @@ -1,211 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\EventDispatcher; - -use Symfony\Component\DependencyInjection\ContainerInterface; - -/** - * Lazily loads listeners and subscribers from the dependency injection - * container. - * - * @author Fabien Potencier - * @author Bernhard Schussek - * @author Jordan Alliot - * - * @deprecated since 3.3, to be removed in 4.0. Use EventDispatcher with closure-proxy injection instead. - */ -class ContainerAwareEventDispatcher extends EventDispatcher -{ - /** - * The container from where services are loaded. - * - * @var ContainerInterface - */ - private $container; - - /** - * The service IDs of the event listeners and subscribers. - * - * @var array - */ - private $listenerIds = array(); - - /** - * The services registered as listeners. - * - * @var array - */ - private $listeners = array(); - - /** - * Constructor. - * - * @param ContainerInterface $container A ContainerInterface instance - */ - public function __construct(ContainerInterface $container) - { - $this->container = $container; - - $class = get_class($this); - if ($this instanceof \PHPUnit_Framework_MockObject_MockObject || $this instanceof \Prophecy\Doubler\DoubleInterface) { - $class = get_parent_class($class); - } - if (__CLASS__ !== $class) { - @trigger_error(sprintf('The %s class is deprecated since version 3.3 and will be removed in 4.0. Use EventDispatcher with closure-proxy injection instead.', __CLASS__), E_USER_DEPRECATED); - } - } - - /** - * Adds a service as event listener. - * - * @param string $eventName Event for which the listener is added - * @param array $callback The service ID of the listener service & the method - * name that has to be called - * @param int $priority The higher this value, the earlier an event listener - * will be triggered in the chain. - * Defaults to 0. - * - * @throws \InvalidArgumentException - */ - public function addListenerService($eventName, $callback, $priority = 0) - { - @trigger_error(sprintf('The %s class is deprecated since version 3.3 and will be removed in 4.0. Use EventDispatcher with closure-proxy injection instead.', __CLASS__), E_USER_DEPRECATED); - - if (!is_array($callback) || 2 !== count($callback)) { - throw new \InvalidArgumentException('Expected an array("service", "method") argument'); - } - - $this->listenerIds[$eventName][] = array($callback[0], $callback[1], $priority); - } - - public function removeListener($eventName, $listener) - { - $this->lazyLoad($eventName); - - if (isset($this->listenerIds[$eventName])) { - foreach ($this->listenerIds[$eventName] as $i => list($serviceId, $method, $priority)) { - $key = $serviceId.'.'.$method; - if (isset($this->listeners[$eventName][$key]) && $listener === array($this->listeners[$eventName][$key], $method)) { - unset($this->listeners[$eventName][$key]); - if (empty($this->listeners[$eventName])) { - unset($this->listeners[$eventName]); - } - unset($this->listenerIds[$eventName][$i]); - if (empty($this->listenerIds[$eventName])) { - unset($this->listenerIds[$eventName]); - } - } - } - } - - parent::removeListener($eventName, $listener); - } - - /** - * {@inheritdoc} - */ - public function hasListeners($eventName = null) - { - if (null === $eventName) { - return (bool) count($this->listenerIds) || (bool) count($this->listeners); - } - - if (isset($this->listenerIds[$eventName])) { - return true; - } - - return parent::hasListeners($eventName); - } - - /** - * {@inheritdoc} - */ - public function getListeners($eventName = null) - { - if (null === $eventName) { - foreach ($this->listenerIds as $serviceEventName => $args) { - $this->lazyLoad($serviceEventName); - } - } else { - $this->lazyLoad($eventName); - } - - return parent::getListeners($eventName); - } - - /** - * {@inheritdoc} - */ - public function getListenerPriority($eventName, $listener) - { - $this->lazyLoad($eventName); - - return parent::getListenerPriority($eventName, $listener); - } - - /** - * Adds a service as event subscriber. - * - * @param string $serviceId The service ID of the subscriber service - * @param string $class The service's class name (which must implement EventSubscriberInterface) - */ - public function addSubscriberService($serviceId, $class) - { - @trigger_error(sprintf('The %s class is deprecated since version 3.3 and will be removed in 4.0. Use EventDispatcher with closure-proxy injection instead.', __CLASS__), E_USER_DEPRECATED); - - foreach ($class::getSubscribedEvents() as $eventName => $params) { - if (is_string($params)) { - $this->listenerIds[$eventName][] = array($serviceId, $params, 0); - } elseif (is_string($params[0])) { - $this->listenerIds[$eventName][] = array($serviceId, $params[0], isset($params[1]) ? $params[1] : 0); - } else { - foreach ($params as $listener) { - $this->listenerIds[$eventName][] = array($serviceId, $listener[0], isset($listener[1]) ? $listener[1] : 0); - } - } - } - } - - public function getContainer() - { - @trigger_error('The '.__METHOD__.'() method is deprecated since version 3.3 as its class will be removed in 4.0. Inject the container or the services you need in your listeners/subscribers instead.', E_USER_DEPRECATED); - - return $this->container; - } - - /** - * Lazily loads listeners for this event from the dependency injection - * container. - * - * @param string $eventName The name of the event to dispatch. The name of - * the event is the name of the method that is - * invoked on listeners. - */ - protected function lazyLoad($eventName) - { - if (isset($this->listenerIds[$eventName])) { - foreach ($this->listenerIds[$eventName] as list($serviceId, $method, $priority)) { - $listener = $this->container->get($serviceId); - - $key = $serviceId.'.'.$method; - if (!isset($this->listeners[$eventName][$key])) { - $this->addListener($eventName, array($listener, $method), $priority); - } elseif ($listener !== $this->listeners[$eventName][$key]) { - parent::removeListener($eventName, array($this->listeners[$eventName][$key], $method)); - $this->addListener($eventName, array($listener, $method), $priority); - } - - $this->listeners[$eventName][$key] = $listener; - } - } - } -} diff --git a/src/Symfony/Component/EventDispatcher/Tests/ContainerAwareEventDispatcherTest.php b/src/Symfony/Component/EventDispatcher/Tests/ContainerAwareEventDispatcherTest.php deleted file mode 100644 index 180556149268c..0000000000000 --- a/src/Symfony/Component/EventDispatcher/Tests/ContainerAwareEventDispatcherTest.php +++ /dev/null @@ -1,210 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\EventDispatcher\Tests; - -use Symfony\Component\DependencyInjection\Container; -use Symfony\Component\EventDispatcher\ContainerAwareEventDispatcher; -use Symfony\Component\EventDispatcher\Event; -use Symfony\Component\EventDispatcher\EventSubscriberInterface; - -/** - * @group legacy - */ -class ContainerAwareEventDispatcherTest extends AbstractEventDispatcherTest -{ - protected function createEventDispatcher() - { - $container = new Container(); - - return new ContainerAwareEventDispatcher($container); - } - - public function testAddAListenerService() - { - $event = new Event(); - - $service = $this->getMockBuilder('Symfony\Component\EventDispatcher\Tests\Service')->getMock(); - - $service - ->expects($this->once()) - ->method('onEvent') - ->with($event) - ; - - $container = new Container(); - $container->set('service.listener', $service); - - $dispatcher = new ContainerAwareEventDispatcher($container); - $dispatcher->addListenerService('onEvent', array('service.listener', 'onEvent')); - - $dispatcher->dispatch('onEvent', $event); - } - - public function testAddASubscriberService() - { - $event = new Event(); - - $service = $this->getMockBuilder('Symfony\Component\EventDispatcher\Tests\SubscriberService')->getMock(); - - $service - ->expects($this->once()) - ->method('onEvent') - ->with($event) - ; - - $service - ->expects($this->once()) - ->method('onEventWithPriority') - ->with($event) - ; - - $service - ->expects($this->once()) - ->method('onEventNested') - ->with($event) - ; - - $container = new Container(); - $container->set('service.subscriber', $service); - - $dispatcher = new ContainerAwareEventDispatcher($container); - $dispatcher->addSubscriberService('service.subscriber', 'Symfony\Component\EventDispatcher\Tests\SubscriberService'); - - $dispatcher->dispatch('onEvent', $event); - $dispatcher->dispatch('onEventWithPriority', $event); - $dispatcher->dispatch('onEventNested', $event); - } - - public function testPreventDuplicateListenerService() - { - $event = new Event(); - - $service = $this->getMockBuilder('Symfony\Component\EventDispatcher\Tests\Service')->getMock(); - - $service - ->expects($this->once()) - ->method('onEvent') - ->with($event) - ; - - $container = new Container(); - $container->set('service.listener', $service); - - $dispatcher = new ContainerAwareEventDispatcher($container); - $dispatcher->addListenerService('onEvent', array('service.listener', 'onEvent'), 5); - $dispatcher->addListenerService('onEvent', array('service.listener', 'onEvent'), 10); - - $dispatcher->dispatch('onEvent', $event); - } - - public function testHasListenersOnLazyLoad() - { - $event = new Event(); - - $service = $this->getMockBuilder('Symfony\Component\EventDispatcher\Tests\Service')->getMock(); - - $container = new Container(); - $container->set('service.listener', $service); - - $dispatcher = new ContainerAwareEventDispatcher($container); - $dispatcher->addListenerService('onEvent', array('service.listener', 'onEvent')); - - $service - ->expects($this->once()) - ->method('onEvent') - ->with($event) - ; - - $this->assertTrue($dispatcher->hasListeners()); - - if ($dispatcher->hasListeners('onEvent')) { - $dispatcher->dispatch('onEvent'); - } - } - - public function testGetListenersOnLazyLoad() - { - $service = $this->getMockBuilder('Symfony\Component\EventDispatcher\Tests\Service')->getMock(); - - $container = new Container(); - $container->set('service.listener', $service); - - $dispatcher = new ContainerAwareEventDispatcher($container); - $dispatcher->addListenerService('onEvent', array('service.listener', 'onEvent')); - - $listeners = $dispatcher->getListeners(); - - $this->assertTrue(isset($listeners['onEvent'])); - - $this->assertCount(1, $dispatcher->getListeners('onEvent')); - } - - public function testRemoveAfterDispatch() - { - $service = $this->getMockBuilder('Symfony\Component\EventDispatcher\Tests\Service')->getMock(); - - $container = new Container(); - $container->set('service.listener', $service); - - $dispatcher = new ContainerAwareEventDispatcher($container); - $dispatcher->addListenerService('onEvent', array('service.listener', 'onEvent')); - - $dispatcher->dispatch('onEvent', new Event()); - $dispatcher->removeListener('onEvent', array($container->get('service.listener'), 'onEvent')); - $this->assertFalse($dispatcher->hasListeners('onEvent')); - } - - public function testRemoveBeforeDispatch() - { - $service = $this->getMockBuilder('Symfony\Component\EventDispatcher\Tests\Service')->getMock(); - - $container = new Container(); - $container->set('service.listener', $service); - - $dispatcher = new ContainerAwareEventDispatcher($container); - $dispatcher->addListenerService('onEvent', array('service.listener', 'onEvent')); - - $dispatcher->removeListener('onEvent', array($container->get('service.listener'), 'onEvent')); - $this->assertFalse($dispatcher->hasListeners('onEvent')); - } -} - -class Service -{ - public function onEvent(Event $e) - { - } -} - -class SubscriberService implements EventSubscriberInterface -{ - public static function getSubscribedEvents() - { - return array( - 'onEvent' => 'onEvent', - 'onEventWithPriority' => array('onEventWithPriority', 10), - 'onEventNested' => array(array('onEventNested')), - ); - } - - public function onEvent(Event $e) - { - } - - public function onEventWithPriority(Event $e) - { - } - - public function onEventNested(Event $e) - { - } -} From 16a2fcf978380bf7261b8b63bfab6766a0a5c042 Mon Sep 17 00:00:00 2001 From: Robin Chalas Date: Thu, 18 May 2017 09:47:18 +0200 Subject: [PATCH 0030/1099] Remove deprecated container injections and compiler passes --- .../Bundle/FrameworkBundle/CHANGELOG.md | 7 +- .../Compiler/AddConsoleCommandPass.php | 27 --- .../Compiler/AddConstraintValidatorsPass.php | 23 -- .../Compiler/AddValidatorInitializersPass.php | 23 -- .../Compiler/CompilerDebugDumpPass.php | 46 ---- .../Compiler/ConfigCachePass.php | 28 --- .../ControllerArgumentValueResolverPass.php | 27 --- .../DependencyInjection/Compiler/FormPass.php | 88 ------- .../Compiler/PropertyInfoPass.php | 27 --- .../Compiler/RoutingResolverPass.php | 27 --- .../Compiler/SerializerPass.php | 28 --- .../EventListener/SessionListener.php | 43 ---- .../EventListener/TestSessionListener.php | 43 ---- .../Compiler/AddConsoleCommandPassTest.php | 129 ---------- .../AddConstraintValidatorsPassTest.php | 83 ------- .../Compiler/ConfigCachePassTest.php | 56 ----- ...ontrollerArgumentValueResolverPassTest.php | 70 ------ .../Compiler/FormPassTest.php | 220 ------------------ .../Compiler/PropertyInfoPassTest.php | 80 ------- .../Compiler/SerializerPassTest.php | 95 -------- .../Tests/Translation/TranslatorTest.php | 151 ------------ .../Translation/Translator.php | 24 +- .../Bundle/SecurityBundle/CHANGELOG.md | 6 + .../Security/FirewallContext.php | 10 - .../SecurityBundle/Security/FirewallMap.php | 83 +------ .../Tests/Security/FirewallContextTest.php | 12 - src/Symfony/Bundle/TwigBundle/CHANGELOG.md | 5 + .../ContainerAwareRuntimeLoader.php | 52 ----- .../Tests/ContainerAwareRuntimeLoaderTest.php | 41 ---- src/Symfony/Component/HttpKernel/CHANGELOG.md | 4 +- .../CacheClearer/Psr6CacheClearer.php | 9 - .../LazyLoadingFragmentHandler.php | 27 --- .../CacheClearer/Psr6CacheClearerTest.php | 21 -- .../LazyLoadingFragmentHandlerTest.php | 25 -- 34 files changed, 27 insertions(+), 1613 deletions(-) delete mode 100644 src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/AddConsoleCommandPass.php delete mode 100644 src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/AddConstraintValidatorsPass.php delete mode 100644 src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/AddValidatorInitializersPass.php delete mode 100644 src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/CompilerDebugDumpPass.php delete mode 100644 src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/ConfigCachePass.php delete mode 100644 src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/ControllerArgumentValueResolverPass.php delete mode 100644 src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/FormPass.php delete mode 100644 src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/PropertyInfoPass.php delete mode 100644 src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/RoutingResolverPass.php delete mode 100644 src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/SerializerPass.php delete mode 100644 src/Symfony/Bundle/FrameworkBundle/EventListener/SessionListener.php delete mode 100644 src/Symfony/Bundle/FrameworkBundle/EventListener/TestSessionListener.php delete mode 100644 src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/AddConsoleCommandPassTest.php delete mode 100644 src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/AddConstraintValidatorsPassTest.php delete mode 100644 src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/ConfigCachePassTest.php delete mode 100644 src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/ControllerArgumentValueResolverPassTest.php delete mode 100644 src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/FormPassTest.php delete mode 100644 src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/PropertyInfoPassTest.php delete mode 100644 src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/SerializerPassTest.php delete mode 100644 src/Symfony/Bundle/TwigBundle/ContainerAwareRuntimeLoader.php delete mode 100644 src/Symfony/Bundle/TwigBundle/Tests/ContainerAwareRuntimeLoaderTest.php diff --git a/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md b/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md index fbc42260fb67d..e7af6de4c027f 100644 --- a/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md +++ b/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md @@ -4,8 +4,13 @@ CHANGELOG 4.0.0 ----- - * Removed `ValidateWorkflowsPass` * The default `type` option of the `framework.workflows.*` configuration entries is `state_machine` + * removed `AddConsoleCommandPass`, `AddConstraintValidatorsPass`, + `AddValidatorInitializersPass`, `CompilerDebugDumpPass`, `ConfigCachePass`, + `ControllerArgumentValueResolverPass`, `FormPass`, `PropertyInfoPass`, + `RoutingResolverPass`, `SerializerPass`, `ValidateWorkflowsPass` + * made `Translator::__construct()` `$defaultLocale` argument required + * removed `SessionListener`, `TestSessionListener` 3.3.0 ----- diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/AddConsoleCommandPass.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/AddConsoleCommandPass.php deleted file mode 100644 index d423648d05b1a..0000000000000 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/AddConsoleCommandPass.php +++ /dev/null @@ -1,27 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler; - -@trigger_error(sprintf('%s is deprecated since version 3.3 and will be removed in 4.0. Use Symfony\Component\Console\DependencyInjection\AddConsoleCommandPass instead.', AddConsoleCommandPass::class), E_USER_DEPRECATED); - -use Symfony\Component\Console\DependencyInjection\AddConsoleCommandPass as BaseAddConsoleCommandPass; - -/** - * Registers console commands. - * - * @author Grégoire Pineau - * - * @deprecated since version 3.3, to be removed in 4.0. Use Symfony\Component\Console\DependencyInjection\AddConsoleCommandPass instead. - */ -class AddConsoleCommandPass extends BaseAddConsoleCommandPass -{ -} diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/AddConstraintValidatorsPass.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/AddConstraintValidatorsPass.php deleted file mode 100644 index 3b89fa2651a80..0000000000000 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/AddConstraintValidatorsPass.php +++ /dev/null @@ -1,23 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler; - -use Symfony\Component\Validator\DependencyInjection\AddConstraintValidatorsPass as BaseAddConstraintValidatorsPass; - -@trigger_error(sprintf('The %s class is deprecated since version 3.3 and will be removed in 4.0. Use %s instead.', AddConstraintValidatorsPass::class, BaseAddConstraintValidatorsPass::class), E_USER_DEPRECATED); - -/** - * @deprecated since version 3.3, to be removed in 4.0. Use {@link BaseAddConstraintValidatorsPass} instead - */ -class AddConstraintValidatorsPass extends BaseAddConstraintValidatorsPass -{ -} diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/AddValidatorInitializersPass.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/AddValidatorInitializersPass.php deleted file mode 100644 index d71d87c1faad4..0000000000000 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/AddValidatorInitializersPass.php +++ /dev/null @@ -1,23 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler; - -use Symfony\Component\Validator\DependencyInjection\AddValidatorInitializersPass as BaseAddValidatorsInitializerPass; - -@trigger_error(sprintf('The %s class is deprecated since version 3.3 and will be removed in 4.0. Use %s instead.', AddValidatorInitializersPass::class, BaseAddValidatorsInitializerPass::class), E_USER_DEPRECATED); - -/** - * @deprecated since version 3.3, to be removed in 4.0. Use {@link BaseAddValidatorInitializersPass} instead - */ -class AddValidatorInitializersPass extends BaseAddValidatorsInitializerPass -{ -} diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/CompilerDebugDumpPass.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/CompilerDebugDumpPass.php deleted file mode 100644 index 714d01d01d5e5..0000000000000 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/CompilerDebugDumpPass.php +++ /dev/null @@ -1,46 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler; - -@trigger_error(sprintf('The %s class is deprecated since version 3.3 and will be removed in 4.0.', CompilerDebugDumpPass::class), E_USER_DEPRECATED); - -use Symfony\Component\DependencyInjection\ContainerInterface; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; -use Symfony\Component\Filesystem\Exception\IOException; -use Symfony\Component\Filesystem\Filesystem; - -/** - * @deprecated since version 3.3, to be removed in 4.0. - */ -class CompilerDebugDumpPass implements CompilerPassInterface -{ - public function process(ContainerBuilder $container) - { - $filename = self::getCompilerLogFilename($container); - - $filesystem = new Filesystem(); - $filesystem->dumpFile($filename, implode("\n", $container->getCompiler()->getLog()), null); - try { - $filesystem->chmod($filename, 0666, umask()); - } catch (IOException $e) { - // discard chmod failure (some filesystem may not support it) - } - } - - public static function getCompilerLogFilename(ContainerInterface $container) - { - $class = $container->getParameter('kernel.container_class'); - - return $container->getParameter('kernel.cache_dir').'/'.$class.'Compiler.log'; - } -} diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/ConfigCachePass.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/ConfigCachePass.php deleted file mode 100644 index 7fcea3b0e555d..0000000000000 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/ConfigCachePass.php +++ /dev/null @@ -1,28 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler; - -use Symfony\Component\Config\DependencyInjection\ConfigCachePass as BaseConfigCachePass; - -@trigger_error(sprintf('The %s class is deprecated since version 3.3 and will be removed in 4.0. Use Symfony\Component\Config\DependencyInjection\ConfigCachePass instead.', ConfigCachePass::class), E_USER_DEPRECATED); - -/** - * Adds services tagged config_cache.resource_checker to the config_cache_factory service, ordering them by priority. - * - * @deprecated since version 3.3, to be removed in 4.0. Use {@link BaseConfigCachePass} instead. - * - * @author Matthias Pigulla - * @author Benjamin Klotz - */ -class ConfigCachePass extends BaseConfigCachePass -{ -} diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/ControllerArgumentValueResolverPass.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/ControllerArgumentValueResolverPass.php deleted file mode 100644 index 3f2baf6871c13..0000000000000 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/ControllerArgumentValueResolverPass.php +++ /dev/null @@ -1,27 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler; - -use Symfony\Component\HttpKernel\DependencyInjection\ControllerArgumentValueResolverPass as BaseControllerArgumentValueResolverPass; - -@trigger_error(sprintf('The %s class is deprecated since version 3.3 and will be removed in 4.0. Use %s instead.', ControllerArgumentValueResolverPass::class, BaseControllerArgumentValueResolverPass::class), E_USER_DEPRECATED); - -/** - * Gathers and configures the argument value resolvers. - * - * @author Iltar van der Berg - * - * @deprecated since version 3.3, to be removed in 4.0. Use {@link BaseControllerArgumentValueResolverPass} - */ -class ControllerArgumentValueResolverPass extends BaseControllerArgumentValueResolverPass -{ -} diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/FormPass.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/FormPass.php deleted file mode 100644 index fdbfd4297b225..0000000000000 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/FormPass.php +++ /dev/null @@ -1,88 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler; - -@trigger_error(sprintf('The %s class is deprecated since version 3.3 and will be removed in 4.0. Use Symfony\Component\Form\DependencyInjection\FormPass instead.', FormPass::class), E_USER_DEPRECATED); - -use Symfony\Component\DependencyInjection\Compiler\PriorityTaggedServiceTrait; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; -use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; - -/** - * Adds all services with the tags "form.type" and "form.type_guesser" as - * arguments of the "form.extension" service. - * - * @author Bernhard Schussek - * - * @deprecated since version 3.3, to be removed in 4.0. Use FormPass in the Form component instead. - */ -class FormPass implements CompilerPassInterface -{ - use PriorityTaggedServiceTrait; - - public function process(ContainerBuilder $container) - { - if (!$container->hasDefinition('form.extension')) { - return; - } - - $definition = $container->getDefinition('form.extension'); - - // Builds an array with fully-qualified type class names as keys and service IDs as values - $types = array(); - - foreach ($container->findTaggedServiceIds('form.type') as $serviceId => $tag) { - $serviceDefinition = $container->getDefinition($serviceId); - if (!$serviceDefinition->isPublic()) { - $serviceDefinition->setPublic(true); - } - - // Support type access by FQCN - $types[$serviceDefinition->getClass()] = $serviceId; - } - - $definition->replaceArgument(1, $types); - - $typeExtensions = array(); - - foreach ($this->findAndSortTaggedServices('form.type_extension', $container) as $reference) { - $serviceId = (string) $reference; - $serviceDefinition = $container->getDefinition($serviceId); - if (!$serviceDefinition->isPublic()) { - $serviceDefinition->setPublic(true); - } - - $tag = $serviceDefinition->getTag('form.type_extension'); - if (isset($tag[0]['extended_type'])) { - $extendedType = $tag[0]['extended_type']; - } else { - throw new InvalidArgumentException(sprintf('Tagged form type extension must have the extended type configured using the extended_type/extended-type attribute, none was configured for the "%s" service.', $serviceId)); - } - - $typeExtensions[$extendedType][] = $serviceId; - } - - $definition->replaceArgument(2, $typeExtensions); - - // Find all services annotated with "form.type_guesser" - $guessers = array_keys($container->findTaggedServiceIds('form.type_guesser')); - foreach ($guessers as $serviceId) { - $serviceDefinition = $container->getDefinition($serviceId); - if (!$serviceDefinition->isPublic()) { - $serviceDefinition->setPublic(true); - } - } - - $definition->replaceArgument(3, $guessers); - } -} diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/PropertyInfoPass.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/PropertyInfoPass.php deleted file mode 100644 index 3c73f9bf49507..0000000000000 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/PropertyInfoPass.php +++ /dev/null @@ -1,27 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler; - -@trigger_error(sprintf('The %s class is deprecated since version 3.3 and will be removed in 4.0. Use Symfony\Component\PropertyInfo\DependencyInjection\PropertyInfoPass instead.', PropertyInfoPass::class), E_USER_DEPRECATED); - -use Symfony\Component\PropertyInfo\DependencyInjection\PropertyInfoPass as BasePropertyInfoPass; - -/** - * Adds extractors to the property_info service. - * - * @author Kévin Dunglas - * - * @deprecated since version 3.3, to be removed in 4.0. Use {@link BasePropertyInfoPass instead}. - */ -class PropertyInfoPass extends BasePropertyInfoPass -{ -} diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/RoutingResolverPass.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/RoutingResolverPass.php deleted file mode 100644 index bac782115b557..0000000000000 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/RoutingResolverPass.php +++ /dev/null @@ -1,27 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler; - -use Symfony\Component\Routing\DependencyInjection\RoutingResolverPass as BaseRoutingResolverPass; - -@trigger_error(sprintf('The %s class is deprecated since version 3.3 and will be removed in 4.0. Use %s instead.', RoutingResolverPass::class, BaseRoutingResolverPass::class), E_USER_DEPRECATED); - -/** - * Adds tagged routing.loader services to routing.resolver service. - * - * @author Fabien Potencier - * - * @deprecated since version 3.3, to be removed in 4.0. Use {@link BaseRoutingResolverPass} - */ -class RoutingResolverPass extends BaseRoutingResolverPass -{ -} diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/SerializerPass.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/SerializerPass.php deleted file mode 100644 index d30e8eba43a17..0000000000000 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/SerializerPass.php +++ /dev/null @@ -1,28 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler; - -@trigger_error(sprintf('The %s class is deprecated since version 3.3 and will be removed in 4.0. Use Symfony\Component\Serializer\DependencyInjection\SerializerPass instead.', SerializerPass::class), E_USER_DEPRECATED); - -use Symfony\Component\Serializer\DependencyInjection\SerializerPass as BaseSerializerPass; - -/** - * Adds all services with the tags "serializer.encoder" and "serializer.normalizer" as - * encoders and normalizers to the Serializer service. - * - * @deprecated since version 3.3, to be removed in 4.0. Use {@link BaseSerializerPass} instead. - * - * @author Javier Lopez - */ -class SerializerPass extends BaseSerializerPass -{ -} diff --git a/src/Symfony/Bundle/FrameworkBundle/EventListener/SessionListener.php b/src/Symfony/Bundle/FrameworkBundle/EventListener/SessionListener.php deleted file mode 100644 index 92db8ece73ee1..0000000000000 --- a/src/Symfony/Bundle/FrameworkBundle/EventListener/SessionListener.php +++ /dev/null @@ -1,43 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\EventListener; - -use Symfony\Component\DependencyInjection\ContainerInterface; -use Symfony\Component\HttpKernel\EventListener\AbstractSessionListener; - -@trigger_error(sprintf('The %s class is deprecated since version 3.3 and will be removed in 4.0. Use Symfony\Component\HttpKernel\EventListener\SessionListener instead.', SessionListener::class), E_USER_DEPRECATED); - -/** - * Sets the session in the request. - * - * @author Fabien Potencier - * - * @deprecated since version 3.3, to be removed in 4.0. Use Symfony\Component\HttpKernel\EventListener\SessionListener instead - */ -class SessionListener extends AbstractSessionListener -{ - private $container; - - public function __construct(ContainerInterface $container) - { - $this->container = $container; - } - - protected function getSession() - { - if (!$this->container->has('session')) { - return; - } - - return $this->container->get('session'); - } -} diff --git a/src/Symfony/Bundle/FrameworkBundle/EventListener/TestSessionListener.php b/src/Symfony/Bundle/FrameworkBundle/EventListener/TestSessionListener.php deleted file mode 100644 index 703be8ff3beda..0000000000000 --- a/src/Symfony/Bundle/FrameworkBundle/EventListener/TestSessionListener.php +++ /dev/null @@ -1,43 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\EventListener; - -@trigger_error(sprintf('The %s class is deprecated since version 3.3 and will be removed in 4.0. Use Symfony\Component\HttpKernel\EventListener\TestSessionListener instead.', TestSessionListener::class), E_USER_DEPRECATED); - -use Symfony\Component\HttpKernel\EventListener\AbstractTestSessionListener; -use Symfony\Component\DependencyInjection\ContainerInterface; - -/** - * TestSessionListener. - * - * @author Fabien Potencier - * - * @deprecated since version 3.3, to be removed in 4.0. - */ -class TestSessionListener extends AbstractTestSessionListener -{ - protected $container; - - public function __construct(ContainerInterface $container) - { - $this->container = $container; - } - - protected function getSession() - { - if (!$this->container->has('session')) { - return; - } - - return $this->container->get('session'); - } -} diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/AddConsoleCommandPassTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/AddConsoleCommandPassTest.php deleted file mode 100644 index 58a0da41c3d91..0000000000000 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/AddConsoleCommandPassTest.php +++ /dev/null @@ -1,129 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\Compiler; - -use PHPUnit\Framework\TestCase; -use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\AddConsoleCommandPass; -use Symfony\Component\Console\Command\Command; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Definition; -use Symfony\Component\HttpKernel\Bundle\Bundle; - -/** - * @group legacy - */ -class AddConsoleCommandPassTest extends TestCase -{ - /** - * @dataProvider visibilityProvider - */ - public function testProcess($public) - { - $container = new ContainerBuilder(); - $container->addCompilerPass(new AddConsoleCommandPass()); - $container->setParameter('my-command.class', 'Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\Compiler\MyCommand'); - - $definition = new Definition('%my-command.class%'); - $definition->setPublic($public); - $definition->addTag('console.command'); - $container->setDefinition('my-command', $definition); - - $container->compile(); - - $alias = 'console.command.symfony_bundle_frameworkbundle_tests_dependencyinjection_compiler_mycommand'; - - if ($public) { - $this->assertFalse($container->hasAlias($alias)); - $id = 'my-command'; - } else { - $id = $alias; - // The alias is replaced by a Definition by the ReplaceAliasByActualDefinitionPass - // in case the original service is private - $this->assertFalse($container->hasDefinition('my-command')); - $this->assertTrue($container->hasDefinition($alias)); - } - - $this->assertTrue($container->hasParameter('console.command.ids')); - $this->assertSame(array($alias => $id), $container->getParameter('console.command.ids')); - } - - public function visibilityProvider() - { - return array( - array(true), - array(false), - ); - } - - /** - * @expectedException \InvalidArgumentException - * @expectedExceptionMessage The service "my-command" tagged "console.command" must not be abstract. - */ - public function testProcessThrowAnExceptionIfTheServiceIsAbstract() - { - $container = new ContainerBuilder(); - $container->addCompilerPass(new AddConsoleCommandPass()); - - $definition = new Definition('Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\Compiler\MyCommand'); - $definition->addTag('console.command'); - $definition->setAbstract(true); - $container->setDefinition('my-command', $definition); - - $container->compile(); - } - - /** - * @expectedException \InvalidArgumentException - * @expectedExceptionMessage The service "my-command" tagged "console.command" must be a subclass of "Symfony\Component\Console\Command\Command". - */ - public function testProcessThrowAnExceptionIfTheServiceIsNotASubclassOfCommand() - { - $container = new ContainerBuilder(); - $container->addCompilerPass(new AddConsoleCommandPass()); - - $definition = new Definition('SplObjectStorage'); - $definition->addTag('console.command'); - $container->setDefinition('my-command', $definition); - - $container->compile(); - } - - public function testProcessPrivateServicesWithSameCommand() - { - $container = new ContainerBuilder(); - $className = 'Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\Compiler\MyCommand'; - - $definition1 = new Definition($className); - $definition1->addTag('console.command')->setPublic(false); - - $definition2 = new Definition($className); - $definition2->addTag('console.command')->setPublic(false); - - $container->setDefinition('my-command1', $definition1); - $container->setDefinition('my-command2', $definition2); - - (new AddConsoleCommandPass())->process($container); - - $alias1 = 'console.command.symfony_bundle_frameworkbundle_tests_dependencyinjection_compiler_mycommand'; - $alias2 = $alias1.'_my-command2'; - $this->assertTrue($container->hasAlias($alias1)); - $this->assertTrue($container->hasAlias($alias2)); - } -} - -class MyCommand extends Command -{ -} - -class ExtensionPresentBundle extends Bundle -{ -} diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/AddConstraintValidatorsPassTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/AddConstraintValidatorsPassTest.php deleted file mode 100644 index d9065e46d5693..0000000000000 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/AddConstraintValidatorsPassTest.php +++ /dev/null @@ -1,83 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\Compiler; - -use PHPUnit\Framework\TestCase; -use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\AddConstraintValidatorsPass; -use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Definition; -use Symfony\Component\DependencyInjection\Reference; -use Symfony\Component\DependencyInjection\ServiceLocator; - -/** - * @group legacy - */ -class AddConstraintValidatorsPassTest extends TestCase -{ - public function testThatConstraintValidatorServicesAreProcessed() - { - $container = new ContainerBuilder(); - $validatorFactory = $container->register('validator.validator_factory') - ->addArgument(array()); - - $container->register('my_constraint_validator_service1', Validator1::class) - ->addTag('validator.constraint_validator', array('alias' => 'my_constraint_validator_alias1')); - $container->register('my_constraint_validator_service2', Validator2::class) - ->addTag('validator.constraint_validator'); - - $addConstraintValidatorsPass = new AddConstraintValidatorsPass(); - $addConstraintValidatorsPass->process($container); - - $expected = (new Definition(ServiceLocator::class, array(array( - Validator1::class => new ServiceClosureArgument(new Reference('my_constraint_validator_service1')), - 'my_constraint_validator_alias1' => new ServiceClosureArgument(new Reference('my_constraint_validator_service1')), - Validator2::class => new ServiceClosureArgument(new Reference('my_constraint_validator_service2')), - ))))->addTag('container.service_locator')->setPublic(false); - $this->assertEquals($expected, $container->getDefinition((string) $validatorFactory->getArgument(0))); - } - - /** - * @expectedException \InvalidArgumentException - * @expectedExceptionMessage The service "my_abstract_constraint_validator" tagged "validator.constraint_validator" must not be abstract. - */ - public function testAbstractConstraintValidator() - { - $container = new ContainerBuilder(); - $validatorFactory = $container->register('validator.validator_factory') - ->addArgument(array()); - - $container->register('my_abstract_constraint_validator') - ->setAbstract(true) - ->addTag('validator.constraint_validator'); - - $addConstraintValidatorsPass = new AddConstraintValidatorsPass(); - $addConstraintValidatorsPass->process($container); - } - - public function testThatCompilerPassIsIgnoredIfThereIsNoConstraintValidatorFactoryDefinition() - { - $definition = $this->getMockBuilder('Symfony\Component\DependencyInjection\Definition')->getMock(); - $container = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerBuilder')->setMethods(array('hasDefinition', 'findTaggedServiceIds', 'getDefinition'))->getMock(); - - $container->expects($this->never())->method('findTaggedServiceIds'); - $container->expects($this->never())->method('getDefinition'); - $container->expects($this->atLeastOnce()) - ->method('hasDefinition') - ->with('validator.validator_factory') - ->will($this->returnValue(false)); - $definition->expects($this->never())->method('replaceArgument'); - - $addConstraintValidatorsPass = new AddConstraintValidatorsPass(); - $addConstraintValidatorsPass->process($container); - } -} diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/ConfigCachePassTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/ConfigCachePassTest.php deleted file mode 100644 index e2348972d09c7..0000000000000 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/ConfigCachePassTest.php +++ /dev/null @@ -1,56 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\Compiler; - -use PHPUnit\Framework\TestCase; -use Symfony\Component\DependencyInjection\Argument\IteratorArgument; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Reference; -use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\ConfigCachePass; - -/** - * @group legacy - */ -class ConfigCachePassTest extends TestCase -{ - public function testThatCheckersAreProcessedInPriorityOrder() - { - $container = new ContainerBuilder(); - - $definition = $container->register('config_cache_factory')->addArgument(null); - $container->register('checker_2')->addTag('config_cache.resource_checker', array('priority' => 100)); - $container->register('checker_1')->addTag('config_cache.resource_checker', array('priority' => 200)); - $container->register('checker_3')->addTag('config_cache.resource_checker'); - - $pass = new ConfigCachePass(); - $pass->process($container); - - $expected = new IteratorArgument(array( - new Reference('checker_1'), - new Reference('checker_2'), - new Reference('checker_3'), - )); - $this->assertEquals($expected, $definition->getArgument(0)); - } - - public function testThatCheckersCanBeMissing() - { - $container = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerBuilder')->setMethods(array('findTaggedServiceIds'))->getMock(); - - $container->expects($this->atLeastOnce()) - ->method('findTaggedServiceIds') - ->will($this->returnValue(array())); - - $pass = new ConfigCachePass(); - $pass->process($container); - } -} diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/ControllerArgumentValueResolverPassTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/ControllerArgumentValueResolverPassTest.php deleted file mode 100644 index 1adfdf2734f0c..0000000000000 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/ControllerArgumentValueResolverPassTest.php +++ /dev/null @@ -1,70 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\Compiler; - -use PHPUnit\Framework\TestCase; -use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\ControllerArgumentValueResolverPass; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Definition; -use Symfony\Component\DependencyInjection\Reference; -use Symfony\Component\HttpKernel\Controller\ArgumentResolver; - -/** - * @group legacy - */ -class ControllerArgumentValueResolverPassTest extends TestCase -{ - public function testServicesAreOrderedAccordingToPriority() - { - $services = array( - 'n3' => array(array()), - 'n1' => array(array('priority' => 200)), - 'n2' => array(array('priority' => 100)), - ); - - $expected = array( - new Reference('n1'), - new Reference('n2'), - new Reference('n3'), - ); - - $definition = new Definition(ArgumentResolver::class, array(null, array())); - $container = new ContainerBuilder(); - $container->setDefinition('argument_resolver', $definition); - - foreach ($services as $id => list($tag)) { - $container->register($id)->addTag('controller.argument_value_resolver', $tag); - } - - (new ControllerArgumentValueResolverPass())->process($container); - $this->assertEquals($expected, $definition->getArgument(1)->getValues()); - } - - public function testReturningEmptyArrayWhenNoService() - { - $definition = new Definition(ArgumentResolver::class, array(null, array())); - $container = new ContainerBuilder(); - $container->setDefinition('argument_resolver', $definition); - - (new ControllerArgumentValueResolverPass())->process($container); - $this->assertEquals(array(), $definition->getArgument(1)->getValues()); - } - - public function testNoArgumentResolver() - { - $container = new ContainerBuilder(); - - (new ControllerArgumentValueResolverPass())->process($container); - - $this->assertFalse($container->hasDefinition('argument_resolver')); - } -} diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/FormPassTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/FormPassTest.php deleted file mode 100644 index 9adbaf8da9062..0000000000000 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/FormPassTest.php +++ /dev/null @@ -1,220 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\Compiler; - -use PHPUnit\Framework\TestCase; -use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\FormPass; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Definition; -use Symfony\Component\DependencyInjection\Reference; -use Symfony\Component\Form\AbstractType; - -/** - * @group legacy - * - * @author Bernhard Schussek - */ -class FormPassTest extends TestCase -{ - public function testDoNothingIfFormExtensionNotLoaded() - { - $container = new ContainerBuilder(); - $container->addCompilerPass(new FormPass()); - - $container->compile(); - - $this->assertFalse($container->hasDefinition('form.extension')); - } - - public function testAddTaggedTypes() - { - $container = new ContainerBuilder(); - $container->addCompilerPass(new FormPass()); - - $extDefinition = new Definition('Symfony\Component\Form\Extension\DependencyInjection\DependencyInjectionExtension'); - $extDefinition->setArguments(array( - new Reference('service_container'), - array(), - array(), - array(), - )); - - $container->setDefinition('form.extension', $extDefinition); - $container->register('my.type1', __CLASS__.'_Type1')->addTag('form.type'); - $container->register('my.type2', __CLASS__.'_Type2')->addTag('form.type'); - - $container->compile(); - - $extDefinition = $container->getDefinition('form.extension'); - - $this->assertEquals(array( - __CLASS__.'_Type1' => 'my.type1', - __CLASS__.'_Type2' => 'my.type2', - ), $extDefinition->getArgument(1)); - } - - /** - * @dataProvider addTaggedTypeExtensionsDataProvider - */ - public function testAddTaggedTypeExtensions(array $extensions, array $expectedRegisteredExtensions) - { - $container = new ContainerBuilder(); - $container->addCompilerPass(new FormPass()); - - $extDefinition = new Definition('Symfony\Component\Form\Extension\DependencyInjection\DependencyInjectionExtension', array( - new Reference('service_container'), - array(), - array(), - array(), - )); - - $container->setDefinition('form.extension', $extDefinition); - - foreach ($extensions as $serviceId => $tag) { - $container->register($serviceId, 'stdClass')->addTag('form.type_extension', $tag); - } - - $container->compile(); - - $extDefinition = $container->getDefinition('form.extension'); - $this->assertSame($expectedRegisteredExtensions, $extDefinition->getArgument(2)); - } - - /** - * @return array - */ - public function addTaggedTypeExtensionsDataProvider() - { - return array( - array( - array( - 'my.type_extension1' => array('extended_type' => 'type1'), - 'my.type_extension2' => array('extended_type' => 'type1'), - 'my.type_extension3' => array('extended_type' => 'type2'), - ), - array( - 'type1' => array('my.type_extension1', 'my.type_extension2'), - 'type2' => array('my.type_extension3'), - ), - ), - array( - array( - 'my.type_extension1' => array('extended_type' => 'type1', 'priority' => 1), - 'my.type_extension2' => array('extended_type' => 'type1', 'priority' => 2), - 'my.type_extension3' => array('extended_type' => 'type1', 'priority' => -1), - 'my.type_extension4' => array('extended_type' => 'type2', 'priority' => 2), - 'my.type_extension5' => array('extended_type' => 'type2', 'priority' => 1), - 'my.type_extension6' => array('extended_type' => 'type2', 'priority' => 1), - ), - array( - 'type1' => array('my.type_extension2', 'my.type_extension1', 'my.type_extension3'), - 'type2' => array('my.type_extension4', 'my.type_extension5', 'my.type_extension6'), - ), - ), - ); - } - - /** - * @expectedException \InvalidArgumentException - * @expectedExceptionMessage extended-type attribute, none was configured for the "my.type_extension" service - */ - public function testAddTaggedFormTypeExtensionWithoutExtendedTypeAttribute() - { - $container = new ContainerBuilder(); - $container->addCompilerPass(new FormPass()); - - $extDefinition = new Definition('Symfony\Component\Form\Extension\DependencyInjection\DependencyInjectionExtension', array( - new Reference('service_container'), - array(), - array(), - array(), - )); - - $container->setDefinition('form.extension', $extDefinition); - $container->register('my.type_extension', 'stdClass') - ->addTag('form.type_extension'); - - $container->compile(); - } - - public function testAddTaggedGuessers() - { - $container = new ContainerBuilder(); - $container->addCompilerPass(new FormPass()); - - $extDefinition = new Definition('Symfony\Component\Form\Extension\DependencyInjection\DependencyInjectionExtension'); - $extDefinition->setArguments(array( - new Reference('service_container'), - array(), - array(), - array(), - )); - - $definition1 = new Definition('stdClass'); - $definition1->addTag('form.type_guesser'); - $definition2 = new Definition('stdClass'); - $definition2->addTag('form.type_guesser'); - - $container->setDefinition('form.extension', $extDefinition); - $container->setDefinition('my.guesser1', $definition1); - $container->setDefinition('my.guesser2', $definition2); - - $container->compile(); - - $extDefinition = $container->getDefinition('form.extension'); - - $this->assertSame(array( - 'my.guesser1', - 'my.guesser2', - ), $extDefinition->getArgument(3)); - } - - /** - * @dataProvider privateTaggedServicesProvider - */ - public function testPrivateTaggedServices($id, $tagName) - { - $container = new ContainerBuilder(); - $container->addCompilerPass(new FormPass()); - - $extDefinition = new Definition('Symfony\Component\Form\Extension\DependencyInjection\DependencyInjectionExtension'); - $extDefinition->setArguments(array( - new Reference('service_container'), - array(), - array(), - array(), - )); - - $container->setDefinition('form.extension', $extDefinition); - $container->register($id, 'stdClass')->setPublic(false)->addTag($tagName, array('extended_type' => 'Foo')); - - $container->compile(); - $this->assertTrue($container->getDefinition($id)->isPublic()); - } - - public function privateTaggedServicesProvider() - { - return array( - array('my.type', 'form.type'), - array('my.type_extension', 'form.type_extension'), - array('my.guesser', 'form.type_guesser'), - ); - } -} - -class FormPassTest_Type1 extends AbstractType -{ -} - -class FormPassTest_Type2 extends AbstractType -{ -} diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/PropertyInfoPassTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/PropertyInfoPassTest.php deleted file mode 100644 index 19b25bccb9729..0000000000000 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/PropertyInfoPassTest.php +++ /dev/null @@ -1,80 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\Compiler; - -use PHPUnit\Framework\TestCase; -use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\PropertyInfoPass; -use Symfony\Component\DependencyInjection\Argument\IteratorArgument; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Reference; - -/** - * @group legacy - */ -class PropertyInfoPassTest extends TestCase -{ - /** - * @dataProvider provideTags - */ - public function testServicesAreOrderedAccordingToPriority($index, $tag) - { - $container = new ContainerBuilder(); - - $definition = $container->register('property_info')->setArguments(array(null, null, null, null)); - $container->register('n2')->addTag($tag, array('priority' => 100)); - $container->register('n1')->addTag($tag, array('priority' => 200)); - $container->register('n3')->addTag($tag); - - $propertyInfoPass = new PropertyInfoPass(); - $propertyInfoPass->process($container); - - $expected = new IteratorArgument(array( - new Reference('n1'), - new Reference('n2'), - new Reference('n3'), - )); - $this->assertEquals($expected, $definition->getArgument($index)); - } - - public function provideTags() - { - return array( - array(0, 'property_info.list_extractor'), - array(1, 'property_info.type_extractor'), - array(2, 'property_info.description_extractor'), - array(3, 'property_info.access_extractor'), - ); - } - - public function testReturningEmptyArrayWhenNoService() - { - $container = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerBuilder')->setMethods(array('findTaggedServiceIds'))->getMock(); - - $container - ->expects($this->any()) - ->method('findTaggedServiceIds') - ->will($this->returnValue(array())) - ; - - $propertyInfoPass = new PropertyInfoPass(); - - $method = new \ReflectionMethod( - 'Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\PropertyInfoPass', - 'findAndSortTaggedServices' - ); - $method->setAccessible(true); - - $actual = $method->invoke($propertyInfoPass, 'tag', $container); - - $this->assertEquals(array(), $actual); - } -} diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/SerializerPassTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/SerializerPassTest.php deleted file mode 100644 index 8ad759e834592..0000000000000 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/SerializerPassTest.php +++ /dev/null @@ -1,95 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\Compiler; - -use PHPUnit\Framework\TestCase; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Reference; -use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\SerializerPass; - -/** - * Tests for the SerializerPass class. - * - * @group legacy - * - * @author Javier Lopez - */ -class SerializerPassTest extends TestCase -{ - public function testThrowExceptionWhenNoNormalizers() - { - $container = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerBuilder')->setMethods(array('hasDefinition', 'findTaggedServiceIds'))->getMock(); - - $container->expects($this->once()) - ->method('hasDefinition') - ->with('serializer') - ->will($this->returnValue(true)); - - $container->expects($this->once()) - ->method('findTaggedServiceIds') - ->with('serializer.normalizer') - ->will($this->returnValue(array())); - - $this->{method_exists($this, $_ = 'expectException') ? $_ : 'setExpectedException'}('RuntimeException'); - - $serializerPass = new SerializerPass(); - $serializerPass->process($container); - } - - public function testThrowExceptionWhenNoEncoders() - { - $definition = $this->getMockBuilder('Symfony\Component\DependencyInjection\Definition')->getMock(); - $container = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerBuilder')->setMethods(array('hasDefinition', 'findTaggedServiceIds', 'getDefinition'))->getMock(); - - $container->expects($this->once()) - ->method('hasDefinition') - ->with('serializer') - ->will($this->returnValue(true)); - - $container->expects($this->any()) - ->method('findTaggedServiceIds') - ->will($this->onConsecutiveCalls( - array('n' => array('serializer.normalizer')), - array() - )); - - $container->expects($this->any()) - ->method('getDefinition') - ->will($this->returnValue($definition)); - - $this->{method_exists($this, $_ = 'expectException') ? $_ : 'setExpectedException'}('RuntimeException'); - - $serializerPass = new SerializerPass(); - $serializerPass->process($container); - } - - public function testServicesAreOrderedAccordingToPriority() - { - $container = new ContainerBuilder(); - - $definition = $container->register('serializer')->setArguments(array(null, null)); - $container->register('n2')->addTag('serializer.normalizer', array('priority' => 100))->addTag('serializer.encoder', array('priority' => 100)); - $container->register('n1')->addTag('serializer.normalizer', array('priority' => 200))->addTag('serializer.encoder', array('priority' => 200)); - $container->register('n3')->addTag('serializer.normalizer')->addTag('serializer.encoder'); - - $serializerPass = new SerializerPass(); - $serializerPass->process($container); - - $expected = array( - new Reference('n1'), - new Reference('n2'), - new Reference('n3'), - ); - $this->assertEquals($expected, $definition->getArgument(0)); - $this->assertEquals($expected, $definition->getArgument(1)); - } -} diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Translation/TranslatorTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Translation/TranslatorTest.php index ef6fa9330b0d8..8479aed4639d7 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Translation/TranslatorTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Translation/TranslatorTest.php @@ -43,157 +43,6 @@ protected function deleteTmpDir() $fs->remove($dir); } - /** - * @group legacy - * @expectedDeprecation Method Symfony\Bundle\FrameworkBundle\Translation\Translator::__construct() takes the default locale as 3rd argument since version 3.3. Not passing it is deprecated and will trigger an error in 4.0. - */ - public function testTransWithoutCachingOmittingLocale() - { - $translator = $this->getTranslator($this->getLoader(), array(), 'loader', '\Symfony\Bundle\FrameworkBundle\Translation\Translator', null); - $translator->setLocale('fr'); - $translator->setFallbackLocales(array('en', 'es', 'pt-PT', 'pt_BR', 'fr.UTF-8', 'sr@latin')); - - $this->assertEquals('foo (FR)', $translator->trans('foo')); - $this->assertEquals('bar (EN)', $translator->trans('bar')); - $this->assertEquals('foobar (ES)', $translator->trans('foobar')); - $this->assertEquals('choice 0 (EN)', $translator->transChoice('choice', 0)); - $this->assertEquals('no translation', $translator->trans('no translation')); - $this->assertEquals('foobarfoo (PT-PT)', $translator->trans('foobarfoo')); - $this->assertEquals('other choice 1 (PT-BR)', $translator->transChoice('other choice', 1)); - $this->assertEquals('foobarbaz (fr.UTF-8)', $translator->trans('foobarbaz')); - $this->assertEquals('foobarbax (sr@latin)', $translator->trans('foobarbax')); - } - - /** - * @group legacy - * @expectedDeprecation Method Symfony\Bundle\FrameworkBundle\Translation\Translator::__construct() takes the default locale as 3rd argument since version 3.3. Not passing it is deprecated and will trigger an error in 4.0. - */ - public function testTransWithCachingOmittingLocale() - { - // prime the cache - $translator = $this->getTranslator($this->getLoader(), array('cache_dir' => $this->tmpDir), 'loader', '\Symfony\Bundle\FrameworkBundle\Translation\Translator', null); - $translator->setLocale('fr'); - $translator->setFallbackLocales(array('en', 'es', 'pt-PT', 'pt_BR', 'fr.UTF-8', 'sr@latin')); - - $this->assertEquals('foo (FR)', $translator->trans('foo')); - $this->assertEquals('bar (EN)', $translator->trans('bar')); - $this->assertEquals('foobar (ES)', $translator->trans('foobar')); - $this->assertEquals('choice 0 (EN)', $translator->transChoice('choice', 0)); - $this->assertEquals('no translation', $translator->trans('no translation')); - $this->assertEquals('foobarfoo (PT-PT)', $translator->trans('foobarfoo')); - $this->assertEquals('other choice 1 (PT-BR)', $translator->transChoice('other choice', 1)); - $this->assertEquals('foobarbaz (fr.UTF-8)', $translator->trans('foobarbaz')); - $this->assertEquals('foobarbax (sr@latin)', $translator->trans('foobarbax')); - - // do it another time as the cache is primed now - $loader = $this->getMockBuilder('Symfony\Component\Translation\Loader\LoaderInterface')->getMock(); - $loader->expects($this->never())->method('load'); - - $translator = $this->getTranslator($loader, array('cache_dir' => $this->tmpDir), 'loader', '\Symfony\Bundle\FrameworkBundle\Translation\Translator', null); - $translator->setLocale('fr'); - $translator->setFallbackLocales(array('en', 'es', 'pt-PT', 'pt_BR', 'fr.UTF-8', 'sr@latin')); - - $this->assertEquals('foo (FR)', $translator->trans('foo')); - $this->assertEquals('bar (EN)', $translator->trans('bar')); - $this->assertEquals('foobar (ES)', $translator->trans('foobar')); - $this->assertEquals('choice 0 (EN)', $translator->transChoice('choice', 0)); - $this->assertEquals('no translation', $translator->trans('no translation')); - $this->assertEquals('foobarfoo (PT-PT)', $translator->trans('foobarfoo')); - $this->assertEquals('other choice 1 (PT-BR)', $translator->transChoice('other choice', 1)); - $this->assertEquals('foobarbaz (fr.UTF-8)', $translator->trans('foobarbaz')); - $this->assertEquals('foobarbax (sr@latin)', $translator->trans('foobarbax')); - } - - /** - * @group legacy - * @expectedDeprecation Method Symfony\Bundle\FrameworkBundle\Translation\Translator::__construct() takes the default locale as 3rd argument since version 3.3. Not passing it is deprecated and will trigger an error in 4.0. - * @expectedException \InvalidArgumentException - */ - public function testTransWithCachingWithInvalidLocaleOmittingLocale() - { - $loader = $this->getMockBuilder('Symfony\Component\Translation\Loader\LoaderInterface')->getMock(); - $translator = $this->getTranslator($loader, array('cache_dir' => $this->tmpDir), 'loader', '\Symfony\Bundle\FrameworkBundle\Tests\Translation\TranslatorWithInvalidLocale', null); - - $translator->trans('foo'); - } - - /** - * @group legacy - * @expectedDeprecation Method Symfony\Bundle\FrameworkBundle\Translation\Translator::__construct() takes the default locale as 3rd argument since version 3.3. Not passing it is deprecated and will trigger an error in 4.0. - */ - public function testLoadResourcesWithoutCachingOmittingLocale() - { - $loader = new \Symfony\Component\Translation\Loader\YamlFileLoader(); - $resourceFiles = array( - 'fr' => array( - __DIR__.'/../Fixtures/Resources/translations/messages.fr.yml', - ), - ); - - $translator = $this->getTranslator($loader, array('resource_files' => $resourceFiles), 'yml', '\Symfony\Bundle\FrameworkBundle\Translation\Translator', null); - $translator->setLocale('fr'); - - $this->assertEquals('répertoire', $translator->trans('folder')); - } - - /** - * @group legacy - * @expectedDeprecation Method Symfony\Bundle\FrameworkBundle\Translation\Translator::__construct() takes the default locale as 3rd argument since version 3.3. Not passing it is deprecated and will trigger an error in 4.0. - */ - public function testGetDefaultLocaleOmittingLocale() - { - $container = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerInterface')->getMock(); - $container - ->expects($this->once()) - ->method('getParameter') - ->with('kernel.default_locale') - ->will($this->returnValue('en')) - ; - $translator = new Translator($container, new MessageSelector()); - - $this->assertSame('en', $translator->getLocale()); - } - - /** - * @group legacy - * @expectedException \InvalidArgumentException - * @expectedExceptionMessage Missing third $defaultLocale argument. - */ - public function testGetDefaultLocaleOmittingLocaleWithPsrContainer() - { - $container = $this->getMockBuilder(ContainerInterface::class)->getMock(); - $translator = new Translator($container, new MessageSelector()); - } - - /** - * @group legacy - * @expectedDeprecation Method Symfony\Bundle\FrameworkBundle\Translation\Translator::__construct() takes the default locale as 3rd argument since version 3.3. Not passing it is deprecated and will trigger an error in 4.0. - */ - public function testWarmupOmittingLocale() - { - $loader = new \Symfony\Component\Translation\Loader\YamlFileLoader(); - $resourceFiles = array( - 'fr' => array( - __DIR__.'/../Fixtures/Resources/translations/messages.fr.yml', - ), - ); - - // prime the cache - $translator = $this->getTranslator($loader, array('cache_dir' => $this->tmpDir, 'resource_files' => $resourceFiles), 'yml', '\Symfony\Bundle\FrameworkBundle\Translation\Translator', null); - $translator->setFallbackLocales(array('fr')); - $translator->warmup($this->tmpDir); - - $loader = $this->getMockBuilder('Symfony\Component\Translation\Loader\LoaderInterface')->getMock(); - $loader - ->expects($this->never()) - ->method('load'); - - $translator = $this->getTranslator($loader, array('cache_dir' => $this->tmpDir, 'resource_files' => $resourceFiles), 'yml', '\Symfony\Bundle\FrameworkBundle\Translation\Translator', null); - $translator->setLocale('fr'); - $translator->setFallbackLocales(array('fr')); - $this->assertEquals('répertoire', $translator->trans('folder')); - } - public function testTransWithoutCaching() { $translator = $this->getTranslator($this->getLoader()); diff --git a/src/Symfony/Bundle/FrameworkBundle/Translation/Translator.php b/src/Symfony/Bundle/FrameworkBundle/Translation/Translator.php index 6bcbaa8e97416..7b4d89cbbe479 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Translation/Translator.php +++ b/src/Symfony/Bundle/FrameworkBundle/Translation/Translator.php @@ -12,7 +12,6 @@ namespace Symfony\Bundle\FrameworkBundle\Translation; use Psr\Container\ContainerInterface; -use Symfony\Component\DependencyInjection\ContainerInterface as SymfonyContainerInterface; use Symfony\Component\HttpKernel\CacheWarmer\WarmableInterface; use Symfony\Component\Translation\Translator as BaseTranslator; use Symfony\Component\Translation\MessageSelector; @@ -48,27 +47,16 @@ class Translator extends BaseTranslator implements WarmableInterface * * debug: Whether to enable debugging or not (false by default) * * resource_files: List of translation resources available grouped by locale. * - * @param ContainerInterface $container A ContainerInterface instance - * @param MessageSelector $selector The message selector for pluralization - * @param array $loaderIds An array of loader Ids - * @param array $options An array of options + * @param ContainerInterface $container A ContainerInterface instance + * @param MessageSelector $selector The message selector for pluralization + * @param string $defaultLocale + * @param array $loaderIds An array of loader Ids + * @param array $options An array of options * * @throws InvalidArgumentException */ - public function __construct(ContainerInterface $container, MessageSelector $selector, $defaultLocale = null, array $loaderIds = array(), array $options = array()) + public function __construct(ContainerInterface $container, MessageSelector $selector, string $defaultLocale, array $loaderIds = array(), array $options = array()) { - // BC 3.x, to be removed in 4.0 along with the $defaultLocale default value - if (is_array($defaultLocale) || 3 > func_num_args()) { - if (!$container instanceof SymfonyContainerInterface) { - throw new \InvalidArgumentException('Missing third $defaultLocale argument.'); - } - - $options = $loaderIds; - $loaderIds = $defaultLocale; - $defaultLocale = $container->getParameter('kernel.default_locale'); - @trigger_error(sprintf('Method %s() takes the default locale as 3rd argument since version 3.3. Not passing it is deprecated and will trigger an error in 4.0.', __METHOD__), E_USER_DEPRECATED); - } - $this->container = $container; $this->loaderIds = $loaderIds; diff --git a/src/Symfony/Bundle/SecurityBundle/CHANGELOG.md b/src/Symfony/Bundle/SecurityBundle/CHANGELOG.md index 9691e5af03c16..c3a6336c44ac8 100644 --- a/src/Symfony/Bundle/SecurityBundle/CHANGELOG.md +++ b/src/Symfony/Bundle/SecurityBundle/CHANGELOG.md @@ -1,6 +1,12 @@ CHANGELOG ========= +4.0.0 +----- + + * removed `FirewallContext::getContext()` + * made `FirewallMap::$container` and `::$map` private + 3.3.0 ----- diff --git a/src/Symfony/Bundle/SecurityBundle/Security/FirewallContext.php b/src/Symfony/Bundle/SecurityBundle/Security/FirewallContext.php index 02f2739ed8a2f..18e006ee9f1eb 100644 --- a/src/Symfony/Bundle/SecurityBundle/Security/FirewallContext.php +++ b/src/Symfony/Bundle/SecurityBundle/Security/FirewallContext.php @@ -37,16 +37,6 @@ public function getConfig() return $this->config; } - /** - * @deprecated since version 3.3, will be removed in 4.0. Use {@link getListeners()} and/or {@link getExceptionListener()} instead. - */ - public function getContext() - { - @trigger_error(sprintf('Method %s() is deprecated since version 3.3 and will be removed in 4.0. Use %s::getListeners/getExceptionListener() instead.', __METHOD__, __CLASS__), E_USER_DEPRECATED); - - return array($this->getListeners(), $this->getExceptionListener()); - } - public function getListeners() { return $this->listeners; diff --git a/src/Symfony/Bundle/SecurityBundle/Security/FirewallMap.php b/src/Symfony/Bundle/SecurityBundle/Security/FirewallMap.php index 55272ec3043bd..a5fd42484d6ab 100644 --- a/src/Symfony/Bundle/SecurityBundle/Security/FirewallMap.php +++ b/src/Symfony/Bundle/SecurityBundle/Security/FirewallMap.php @@ -22,88 +22,7 @@ * * @author Johannes M. Schmitt */ -class FirewallMap extends _FirewallMap implements FirewallMapInterface -{ - /** - * @deprecated since version 3.3, to be removed in 4.0 alongside with magic methods below - */ - private $container; - - /** - * @deprecated since version 3.3, to be removed in 4.0 alongside with magic methods below - */ - private $map; - - public function __construct(ContainerInterface $container, $map) - { - parent::__construct($container, $map); - $this->container = $container; - $this->map = $map; - } - - /** - * @internal - */ - public function __get($name) - { - if ('map' === $name || 'container' === $name) { - @trigger_error(sprintf('Using the "%s::$%s" property is deprecated since version 3.3 as it will be removed/private in 4.0.', __CLASS__, $name), E_USER_DEPRECATED); - - if ('map' === $name && $this->map instanceof \Traversable) { - $this->map = iterator_to_array($this->map); - } - } - - return $this->$name; - } - - /** - * @internal - */ - public function __set($name, $value) - { - if ('map' === $name || 'container' === $name) { - @trigger_error(sprintf('Using the "%s::$%s" property is deprecated since version 3.3 as it will be removed/private in 4.0.', __CLASS__, $name), E_USER_DEPRECATED); - - $set = \Closure::bind(function ($name, $value) { $this->$name = $value; }, $this, parent::class); - $set($name, $value); - } - - $this->$name = $value; - } - - /** - * @internal - */ - public function __isset($name) - { - if ('map' === $name || 'container' === $name) { - @trigger_error(sprintf('Using the "%s::$%s" property is deprecated since version 3.3 as it will be removed/private in 4.0.', __CLASS__, $name), E_USER_DEPRECATED); - } - - return isset($this->$name); - } - - /** - * @internal - */ - public function __unset($name) - { - if ('map' === $name || 'container' === $name) { - @trigger_error(sprintf('Using the "%s::$%s" property is deprecated since version 3.3 as it will be removed/private in 4.0.', __CLASS__, $name), E_USER_DEPRECATED); - - $unset = \Closure::bind(function ($name) { unset($this->$name); }, $this, parent::class); - $unset($name); - } - - unset($this->$name); - } -} - -/** - * @internal to be removed in 4.0 - */ -class _FirewallMap +class FirewallMap implements FirewallMapInterface { private $container; private $map; diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Security/FirewallContextTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/Security/FirewallContextTest.php index 22be0fd081655..983e8288214a2 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/Security/FirewallContextTest.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/Security/FirewallContextTest.php @@ -37,18 +37,6 @@ public function testGetters() $this->assertEquals($config, $context->getConfig()); } - /** - * @expectedDeprecation Method Symfony\Bundle\SecurityBundle\Security\FirewallContext::getContext() is deprecated since version 3.3 and will be removed in 4.0. Use Symfony\Bundle\SecurityBundle\Security\FirewallContext::getListeners/getExceptionListener() instead. - * @group legacy - */ - public function testGetContext() - { - $context = (new FirewallContext($listeners = array(), $exceptionListener = $this->getExceptionListenerMock(), new FirewallConfig('main', 'request_matcher', 'user_checker'))) - ->getContext(); - - $this->assertEquals(array($listeners, $exceptionListener), $context); - } - private function getExceptionListenerMock() { return $this diff --git a/src/Symfony/Bundle/TwigBundle/CHANGELOG.md b/src/Symfony/Bundle/TwigBundle/CHANGELOG.md index 9f666dbc29dd7..a84aaed1f8c3e 100644 --- a/src/Symfony/Bundle/TwigBundle/CHANGELOG.md +++ b/src/Symfony/Bundle/TwigBundle/CHANGELOG.md @@ -1,6 +1,11 @@ CHANGELOG ========= +4.4.0 +----- + + * removed `ContainerAwareRuntimeLoader` + 3.3.0 ----- diff --git a/src/Symfony/Bundle/TwigBundle/ContainerAwareRuntimeLoader.php b/src/Symfony/Bundle/TwigBundle/ContainerAwareRuntimeLoader.php deleted file mode 100644 index e2988f3aae5e0..0000000000000 --- a/src/Symfony/Bundle/TwigBundle/ContainerAwareRuntimeLoader.php +++ /dev/null @@ -1,52 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\TwigBundle; - -@trigger_error(sprintf('The %s class is deprecated since version 3.3 and will be removed in 4.0. Use the Twig_ContainerRuntimeLoader class instead.', ContainerAwareRuntimeLoader::class), E_USER_DEPRECATED); - -use Psr\Log\LoggerInterface; -use Symfony\Component\DependencyInjection\ContainerInterface; - -/** - * Loads Twig extension runtimes via the service container. - * - * @author Fabien Potencier - * - * @deprecated since version 3.3, will be removed in 4.0. Use \Twig_ContainerRuntimeLoader instead. - */ -class ContainerAwareRuntimeLoader implements \Twig_RuntimeLoaderInterface -{ - private $container; - private $mapping; - private $logger; - - public function __construct(ContainerInterface $container, array $mapping, LoggerInterface $logger = null) - { - $this->container = $container; - $this->mapping = $mapping; - $this->logger = $logger; - } - - /** - * {@inheritdoc} - */ - public function load($class) - { - if (isset($this->mapping[$class])) { - return $this->container->get($this->mapping[$class]); - } - - if (null !== $this->logger) { - $this->logger->warning(sprintf('Class "%s" is not configured as a Twig runtime. Add the "twig.runtime" tag to the related service in the container.', $class)); - } - } -} diff --git a/src/Symfony/Bundle/TwigBundle/Tests/ContainerAwareRuntimeLoaderTest.php b/src/Symfony/Bundle/TwigBundle/Tests/ContainerAwareRuntimeLoaderTest.php deleted file mode 100644 index 93202ca987b16..0000000000000 --- a/src/Symfony/Bundle/TwigBundle/Tests/ContainerAwareRuntimeLoaderTest.php +++ /dev/null @@ -1,41 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\TwigBundle\Tests; - -use Psr\Log\LoggerInterface; -use Symfony\Component\DependencyInjection\ContainerInterface; -use Symfony\Bundle\TwigBundle\ContainerAwareRuntimeLoader; - -/** - * @group legacy - */ -class ContainerAwareRuntimeLoaderTest extends TestCase -{ - public function testLoad() - { - $container = $this->getMockBuilder(ContainerInterface::class)->getMock(); - $container->expects($this->once())->method('get')->with('foo'); - - $loader = new ContainerAwareRuntimeLoader($container, array( - 'FooClass' => 'foo', - )); - $loader->load('FooClass'); - } - - public function testLoadWithoutAMatch() - { - $logger = $this->getMockBuilder(LoggerInterface::class)->getMock(); - $logger->expects($this->once())->method('warning')->with('Class "BarClass" is not configured as a Twig runtime. Add the "twig.runtime" tag to the related service in the container.'); - $loader = new ContainerAwareRuntimeLoader($this->getMockBuilder(ContainerInterface::class)->getMock(), array(), $logger); - $this->assertNull($loader->load('BarClass')); - } -} diff --git a/src/Symfony/Component/HttpKernel/CHANGELOG.md b/src/Symfony/Component/HttpKernel/CHANGELOG.md index 4ed98e227d6a9..2f7b7527ffeea 100644 --- a/src/Symfony/Component/HttpKernel/CHANGELOG.md +++ b/src/Symfony/Component/HttpKernel/CHANGELOG.md @@ -3,11 +3,13 @@ CHANGELOG 4.0.0 ----- - + * removed `ControllerResolverInterface::getArguments()` * removed `TraceableControllerResolver::getArguments()` * removed `ControllerResolver::getArguments()` and the ability to resolve arguments * removed the `argument_resolver` service dependency from the `debug.controller_resolver` + * removed `LazyLoadingFragmentHandler::addRendererService()` + * removed `Psr6CacheClearer::addPool()` 3.3.0 ----- diff --git a/src/Symfony/Component/HttpKernel/CacheClearer/Psr6CacheClearer.php b/src/Symfony/Component/HttpKernel/CacheClearer/Psr6CacheClearer.php index 2336b18a29980..f54ca96e994e7 100644 --- a/src/Symfony/Component/HttpKernel/CacheClearer/Psr6CacheClearer.php +++ b/src/Symfony/Component/HttpKernel/CacheClearer/Psr6CacheClearer.php @@ -11,8 +11,6 @@ namespace Symfony\Component\HttpKernel\CacheClearer; -use Psr\Cache\CacheItemPoolInterface; - /** * @author Nicolas Grekas */ @@ -25,13 +23,6 @@ public function __construct(array $pools = array()) $this->pools = $pools; } - public function addPool(CacheItemPoolInterface $pool) - { - @trigger_error(sprintf('The %s() method is deprecated since version 3.3 and will be removed in 4.0. Pass an array of pools indexed by name to the constructor instead.', __METHOD__), E_USER_DEPRECATED); - - $this->pools[] = $pool; - } - public function hasPool($name) { return isset($this->pools[$name]); diff --git a/src/Symfony/Component/HttpKernel/DependencyInjection/LazyLoadingFragmentHandler.php b/src/Symfony/Component/HttpKernel/DependencyInjection/LazyLoadingFragmentHandler.php index d6f4dab1418c0..f0f83f8a7b3d0 100644 --- a/src/Symfony/Component/HttpKernel/DependencyInjection/LazyLoadingFragmentHandler.php +++ b/src/Symfony/Component/HttpKernel/DependencyInjection/LazyLoadingFragmentHandler.php @@ -23,10 +23,6 @@ class LazyLoadingFragmentHandler extends FragmentHandler { private $container; - /** - * @deprecated since version 3.3, to be removed in 4.0 - */ - private $rendererIds = array(); private $initialized = array(); /** @@ -43,34 +39,11 @@ public function __construct(ContainerInterface $container, RequestStack $request parent::__construct($requestStack, array(), $debug); } - /** - * Adds a service as a fragment renderer. - * - * @param string $name The service name - * @param string $renderer The render service id - * - * @deprecated since version 3.3, to be removed in 4.0 - */ - public function addRendererService($name, $renderer) - { - @trigger_error(sprintf('The %s() method is deprecated since version 3.3 and will be removed in 4.0.', __METHOD__), E_USER_DEPRECATED); - - $this->rendererIds[$name] = $renderer; - } - /** * {@inheritdoc} */ public function render($uri, $renderer = 'inline', array $options = array()) { - // BC 3.x, to be removed in 4.0 - if (isset($this->rendererIds[$renderer])) { - $this->addRenderer($this->container->get($this->rendererIds[$renderer])); - unset($this->rendererIds[$renderer]); - - return parent::render($uri, $renderer, $options); - } - if (!isset($this->initialized[$renderer]) && $this->container->has($renderer)) { $this->addRenderer($this->container->get($renderer)); $this->initialized[$renderer] = true; diff --git a/src/Symfony/Component/HttpKernel/Tests/CacheClearer/Psr6CacheClearerTest.php b/src/Symfony/Component/HttpKernel/Tests/CacheClearer/Psr6CacheClearerTest.php index a5d9b6ef4d1ef..588fd3007e465 100644 --- a/src/Symfony/Component/HttpKernel/Tests/CacheClearer/Psr6CacheClearerTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/CacheClearer/Psr6CacheClearerTest.php @@ -45,25 +45,4 @@ public function testClearPoolThrowsExceptionOnUnreferencedPool() { (new Psr6CacheClearer())->clearPool('unknown'); } - - /** - * @group legacy - * @expectedDeprecation The Symfony\Component\HttpKernel\CacheClearer\Psr6CacheClearer::addPool() method is deprecated since version 3.3 and will be removed in 4.0. Pass an array of pools indexed by name to the constructor instead. - */ - public function testClearPoolsInjectedByAdder() - { - $pool1 = $this->getMockBuilder(CacheItemPoolInterface::class)->getMock(); - $pool1 - ->expects($this->once()) - ->method('clear'); - - $pool2 = $this->getMockBuilder(CacheItemPoolInterface::class)->getMock(); - $pool2 - ->expects($this->once()) - ->method('clear'); - - $clearer = new Psr6CacheClearer(array('pool1' => $pool1)); - $clearer->addPool($pool2); - $clearer->clear(''); - } } diff --git a/src/Symfony/Component/HttpKernel/Tests/DependencyInjection/LazyLoadingFragmentHandlerTest.php b/src/Symfony/Component/HttpKernel/Tests/DependencyInjection/LazyLoadingFragmentHandlerTest.php index 0406345d96d68..7e664954dd6dc 100644 --- a/src/Symfony/Component/HttpKernel/Tests/DependencyInjection/LazyLoadingFragmentHandlerTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/DependencyInjection/LazyLoadingFragmentHandlerTest.php @@ -18,31 +18,6 @@ class LazyLoadingFragmentHandlerTest extends TestCase { - /** - * @group legacy - * @expectedDeprecation The Symfony\Component\HttpKernel\DependencyInjection\LazyLoadingFragmentHandler::addRendererService() method is deprecated since version 3.3 and will be removed in 4.0. - */ - public function testRenderWithLegacyMapping() - { - $renderer = $this->getMockBuilder('Symfony\Component\HttpKernel\Fragment\FragmentRendererInterface')->getMock(); - $renderer->expects($this->once())->method('getName')->will($this->returnValue('foo')); - $renderer->expects($this->any())->method('render')->will($this->returnValue(new Response())); - - $requestStack = $this->getMockBuilder('Symfony\Component\HttpFoundation\RequestStack')->getMock(); - $requestStack->expects($this->any())->method('getCurrentRequest')->will($this->returnValue(Request::create('/'))); - - $container = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerInterface')->getMock(); - $container->expects($this->once())->method('get')->will($this->returnValue($renderer)); - - $handler = new LazyLoadingFragmentHandler($container, $requestStack, false); - $handler->addRendererService('foo', 'foo'); - - $handler->render('/foo', 'foo'); - - // second call should not lazy-load anymore (see once() above on the get() method) - $handler->render('/foo', 'foo'); - } - public function testRender() { $renderer = $this->getMockBuilder('Symfony\Component\HttpKernel\Fragment\FragmentRendererInterface')->getMock(); From 55fe07b7a9aad9b3bcc9ad505833bb1a020d2df2 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Sun, 21 May 2017 12:04:50 +0200 Subject: [PATCH 0031/1099] [PropertyAccess] remove deprecated features --- .../Component/PropertyAccess/CHANGELOG.md | 6 +++ .../Component/PropertyAccess/StringUtil.php | 51 ------------------- .../PropertyAccess/Tests/StringUtilTest.php | 45 ---------------- 3 files changed, 6 insertions(+), 96 deletions(-) delete mode 100644 src/Symfony/Component/PropertyAccess/StringUtil.php delete mode 100644 src/Symfony/Component/PropertyAccess/Tests/StringUtilTest.php diff --git a/src/Symfony/Component/PropertyAccess/CHANGELOG.md b/src/Symfony/Component/PropertyAccess/CHANGELOG.md index 574106e521075..8e1781506b4bd 100644 --- a/src/Symfony/Component/PropertyAccess/CHANGELOG.md +++ b/src/Symfony/Component/PropertyAccess/CHANGELOG.md @@ -1,6 +1,12 @@ CHANGELOG ========= +4.0.0 +----- + + * removed the `StringUtil` class, use `Symfony\Component\Inflector\Inflector` + instead + 2.7.0 ------ diff --git a/src/Symfony/Component/PropertyAccess/StringUtil.php b/src/Symfony/Component/PropertyAccess/StringUtil.php deleted file mode 100644 index 6765dd776b2be..0000000000000 --- a/src/Symfony/Component/PropertyAccess/StringUtil.php +++ /dev/null @@ -1,51 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\PropertyAccess; - -use Symfony\Component\Inflector\Inflector; - -/** - * Creates singulars from plurals. - * - * @author Bernhard Schussek - * - * @deprecated since version 3.1, to be removed in 4.0. Use {@see Symfony\Component\Inflector\Inflector} instead. - */ -class StringUtil -{ - /** - * This class should not be instantiated. - */ - private function __construct() - { - } - - /** - * Returns the singular form of a word. - * - * If the method can't determine the form with certainty, an array of the - * possible singulars is returned. - * - * @param string $plural A word in plural form - * - * @return string|array The singular form or an array of possible singular - * forms - * - * @deprecated since version 3.1, to be removed in 4.0. Use {@see Symfony\Component\Inflector\Inflector::singularize} instead. - */ - public static function singularify($plural) - { - @trigger_error('StringUtil::singularify() is deprecated since version 3.1 and will be removed in 4.0. Use Symfony\Component\Inflector\Inflector::singularize instead.', E_USER_DEPRECATED); - - return Inflector::singularize($plural); - } -} diff --git a/src/Symfony/Component/PropertyAccess/Tests/StringUtilTest.php b/src/Symfony/Component/PropertyAccess/Tests/StringUtilTest.php deleted file mode 100644 index 7728e15f834c8..0000000000000 --- a/src/Symfony/Component/PropertyAccess/Tests/StringUtilTest.php +++ /dev/null @@ -1,45 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\PropertyAccess\Tests; - -use PHPUnit\Framework\TestCase; -use Symfony\Component\PropertyAccess\StringUtil; - -/** - * @group legacy - */ -class StringUtilTest extends TestCase -{ - public function singularifyProvider() - { - // This is only a stub to make sure the BC layer works - // Actual tests are in the Symfony Inflector component - return array( - array('axes', array('ax', 'axe', 'axis')), - ); - } - - /** - * @dataProvider singularifyProvider - */ - public function testSingularify($plural, $singular) - { - $single = StringUtil::singularify($plural); - if (is_string($singular) && is_array($single)) { - $this->fail("--- Expected\n`string`: ".$singular."\n+++ Actual\n`array`: ".implode(', ', $single)); - } elseif (is_array($singular) && is_string($single)) { - $this->fail("--- Expected\n`array`: ".implode(', ', $singular)."\n+++ Actual\n`string`: ".$single); - } - - $this->assertEquals($singular, $single); - } -} From 4f8916cb592bd5847b6bc06c0228679de9d5b147 Mon Sep 17 00:00:00 2001 From: Maxime Steinhausser Date: Fri, 19 May 2017 19:56:12 +0200 Subject: [PATCH 0032/1099] [ClassLoader][HttpKernel] Remove ClassCollectionLoader & Kernel::loadClassCache BC layer --- .../CacheWarmer/ClassCacheCacheWarmer.php | 67 --- .../FrameworkExtension.php | 108 ----- .../Resources/config/services.xml | 12 - .../CacheWarmer/ClassCacheCacheWarmerTest.php | 51 -- .../DependencyInjection/SecurityExtension.php | 22 - .../DependencyInjection/TwigExtension.php | 13 - .../ClassLoader/ClassCollectionLoader.php | 450 ------------------ .../Tests/ClassCollectionLoaderTest.php | 319 ------------- .../Tests/Fixtures/ClassesWithParents/A.php | 7 - .../Fixtures/ClassesWithParents/ATrait.php | 7 - .../Tests/Fixtures/ClassesWithParents/B.php | 7 - .../Fixtures/ClassesWithParents/BTrait.php | 8 - .../ClassesWithParents/CInterface.php | 7 - .../Fixtures/ClassesWithParents/CTrait.php | 7 - .../Tests/Fixtures/ClassesWithParents/D.php | 8 - .../Tests/Fixtures/ClassesWithParents/E.php | 8 - .../Tests/Fixtures/ClassesWithParents/F.php | 8 - .../Tests/Fixtures/ClassesWithParents/G.php | 8 - .../ClassesWithParents/GInterface.php | 7 - .../Tests/Fixtures/deps/traits.php | 37 -- src/Symfony/Component/HttpKernel/CHANGELOG.md | 2 + .../AddAnnotatedClassesToCachePass.php | 8 - .../AddClassesToCachePass.php | 25 - .../DependencyInjection/Extension.php | 27 -- src/Symfony/Component/HttpKernel/Kernel.php | 57 --- .../Component/HttpKernel/Tests/KernelTest.php | 25 - 26 files changed, 2 insertions(+), 1303 deletions(-) delete mode 100644 src/Symfony/Bundle/FrameworkBundle/CacheWarmer/ClassCacheCacheWarmer.php delete mode 100644 src/Symfony/Bundle/FrameworkBundle/Tests/CacheWarmer/ClassCacheCacheWarmerTest.php delete mode 100644 src/Symfony/Component/ClassLoader/ClassCollectionLoader.php delete mode 100644 src/Symfony/Component/ClassLoader/Tests/ClassCollectionLoaderTest.php delete mode 100644 src/Symfony/Component/ClassLoader/Tests/Fixtures/ClassesWithParents/A.php delete mode 100644 src/Symfony/Component/ClassLoader/Tests/Fixtures/ClassesWithParents/ATrait.php delete mode 100644 src/Symfony/Component/ClassLoader/Tests/Fixtures/ClassesWithParents/B.php delete mode 100644 src/Symfony/Component/ClassLoader/Tests/Fixtures/ClassesWithParents/BTrait.php delete mode 100644 src/Symfony/Component/ClassLoader/Tests/Fixtures/ClassesWithParents/CInterface.php delete mode 100644 src/Symfony/Component/ClassLoader/Tests/Fixtures/ClassesWithParents/CTrait.php delete mode 100644 src/Symfony/Component/ClassLoader/Tests/Fixtures/ClassesWithParents/D.php delete mode 100644 src/Symfony/Component/ClassLoader/Tests/Fixtures/ClassesWithParents/E.php delete mode 100644 src/Symfony/Component/ClassLoader/Tests/Fixtures/ClassesWithParents/F.php delete mode 100644 src/Symfony/Component/ClassLoader/Tests/Fixtures/ClassesWithParents/G.php delete mode 100644 src/Symfony/Component/ClassLoader/Tests/Fixtures/ClassesWithParents/GInterface.php delete mode 100644 src/Symfony/Component/ClassLoader/Tests/Fixtures/deps/traits.php delete mode 100644 src/Symfony/Component/HttpKernel/DependencyInjection/AddClassesToCachePass.php diff --git a/src/Symfony/Bundle/FrameworkBundle/CacheWarmer/ClassCacheCacheWarmer.php b/src/Symfony/Bundle/FrameworkBundle/CacheWarmer/ClassCacheCacheWarmer.php deleted file mode 100644 index 1240f14c5b749..0000000000000 --- a/src/Symfony/Bundle/FrameworkBundle/CacheWarmer/ClassCacheCacheWarmer.php +++ /dev/null @@ -1,67 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\CacheWarmer; - -use Symfony\Component\ClassLoader\ClassCollectionLoader; -use Symfony\Component\HttpKernel\CacheWarmer\CacheWarmerInterface; - -/** - * Generates the Class Cache (classes.php) file. - * - * @author Tugdual Saunier - * - * @deprecated since version 3.3, to be removed in 4.0. - */ -class ClassCacheCacheWarmer implements CacheWarmerInterface -{ - private $declaredClasses; - - public function __construct(array $declaredClasses = null) - { - if (PHP_VERSION_ID >= 70000) { - @trigger_error('The '.__CLASS__.' class is deprecated since version 3.3 and will be removed in 4.0.', E_USER_DEPRECATED); - } - - $this->declaredClasses = $declaredClasses; - } - - /** - * Warms up the cache. - * - * @param string $cacheDir The cache directory - */ - public function warmUp($cacheDir) - { - $classmap = $cacheDir.'/classes.map'; - - if (!is_file($classmap)) { - return; - } - - if (file_exists($cacheDir.'/classes.php')) { - return; - } - $declared = null !== $this->declaredClasses ? $this->declaredClasses : array_merge(get_declared_classes(), get_declared_interfaces(), get_declared_traits()); - - ClassCollectionLoader::inline(include($classmap), $cacheDir.'/classes.php', $declared); - } - - /** - * Checks whether this warmer is optional or not. - * - * @return bool always true - */ - public function isOptional() - { - return true; - } -} diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php index d81cfe88c0502..7ab3a4b680a57 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php @@ -95,14 +95,6 @@ public function load(array $configs, ContainerBuilder $container) $loader->load('web.xml'); $loader->load('services.xml'); - - if (PHP_VERSION_ID < 70000) { - $definition = $container->getDefinition('kernel.class_cache.cache_warmer'); - $definition->addTag('kernel.cache_warmer'); - // Ignore deprecation for PHP versions below 7.0 - $definition->setDeprecated(false); - } - $loader->load('fragment_renderer.xml'); if (class_exists(Application::class)) { @@ -288,46 +280,6 @@ public function load(array $configs, ContainerBuilder $container) ->addTag('validator.constraint_validator'); $container->registerForAutoconfiguration(ObjectInitializerInterface::class) ->addTag('validator.initializer'); - - if (PHP_VERSION_ID < 70000) { - $this->addClassesToCompile(array( - 'Symfony\\Component\\Config\\ConfigCache', - 'Symfony\\Component\\Config\\FileLocator', - - 'Symfony\\Component\\Debug\\ErrorHandler', - - 'Symfony\\Component\\DependencyInjection\\ContainerAwareInterface', - 'Symfony\\Component\\DependencyInjection\\Container', - - 'Symfony\\Component\\EventDispatcher\\Event', - - 'Symfony\\Component\\HttpKernel\\EventListener\\ResponseListener', - 'Symfony\\Component\\HttpKernel\\EventListener\\RouterListener', - 'Symfony\\Component\\HttpKernel\\Bundle\\Bundle', - 'Symfony\\Component\\HttpKernel\\Controller\\ControllerResolver', - 'Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolver', - 'Symfony\\Component\\HttpKernel\\ControllerMetadata\\ArgumentMetadata', - 'Symfony\\Component\\HttpKernel\\ControllerMetadata\\ArgumentMetadataFactory', - 'Symfony\\Component\\HttpKernel\\Event\\KernelEvent', - 'Symfony\\Component\\HttpKernel\\Event\\FilterControllerEvent', - 'Symfony\\Component\\HttpKernel\\Event\\FilterResponseEvent', - 'Symfony\\Component\\HttpKernel\\Event\\GetResponseEvent', - 'Symfony\\Component\\HttpKernel\\Event\\GetResponseForControllerResultEvent', - 'Symfony\\Component\\HttpKernel\\Event\\GetResponseForExceptionEvent', - 'Symfony\\Component\\HttpKernel\\HttpKernel', - 'Symfony\\Component\\HttpKernel\\KernelEvents', - 'Symfony\\Component\\HttpKernel\\Config\\FileLocator', - - 'Symfony\\Bundle\\FrameworkBundle\\Controller\\ControllerNameParser', - 'Symfony\\Bundle\\FrameworkBundle\\Controller\\ControllerResolver', - - // Cannot be included because annotations will parse the big compiled class file - // 'Symfony\\Bundle\\FrameworkBundle\\Controller\\Controller', - - // cannot be included as commands are discovered based on the path to this class via Reflection - // 'Symfony\\Bundle\\FrameworkBundle\\FrameworkBundle', - )); - } } /** @@ -668,16 +620,6 @@ private function registerRouterConfiguration(array $config, ContainerBuilder $co $container->setParameter('request_listener.http_port', $config['http_port']); $container->setParameter('request_listener.https_port', $config['https_port']); - - if (PHP_VERSION_ID < 70000) { - $this->addClassesToCompile(array( - 'Symfony\\Component\\Routing\\Generator\\UrlGenerator', - 'Symfony\\Component\\Routing\\RequestContext', - 'Symfony\\Component\\Routing\\Router', - 'Symfony\\Bundle\\FrameworkBundle\\Routing\\RedirectableUrlMatcher', - $container->findDefinition('router.default')->getClass(), - )); - } } /** @@ -720,24 +662,6 @@ private function registerSessionConfiguration(array $config, ContainerBuilder $c $container->setParameter('session.save_path', $config['save_path']); - if (PHP_VERSION_ID < 70000) { - $this->addClassesToCompile(array( - 'Symfony\\Component\\HttpKernel\\EventListener\\SessionListener', - 'Symfony\\Component\\HttpFoundation\\Session\\Storage\\NativeSessionStorage', - 'Symfony\\Component\\HttpFoundation\\Session\\Storage\\PhpBridgeSessionStorage', - 'Symfony\\Component\\HttpFoundation\\Session\\Storage\\Handler\\NativeFileSessionHandler', - 'Symfony\\Component\\HttpFoundation\\Session\\Storage\\Proxy\\AbstractProxy', - 'Symfony\\Component\\HttpFoundation\\Session\\Storage\\Proxy\\SessionHandlerProxy', - $container->getDefinition('session')->getClass(), - )); - - if ($container->hasDefinition($config['storage_id'])) { - $this->addClassesToCompile(array( - $container->findDefinition('session.storage')->getClass(), - )); - } - } - $container->setParameter('session.metadata.update_threshold', $config['metadata_update_threshold']); } @@ -805,15 +729,6 @@ private function registerTemplatingConfiguration(array $config, ContainerBuilder $container->setDefinition('templating.loader', $loaderCache); } - if (PHP_VERSION_ID < 70000) { - $this->addClassesToCompile(array( - 'Symfony\\Bundle\\FrameworkBundle\\Templating\\GlobalVariables', - 'Symfony\\Bundle\\FrameworkBundle\\Templating\\TemplateReference', - 'Symfony\\Bundle\\FrameworkBundle\\Templating\\TemplateNameParser', - $container->findDefinition('templating.locator')->getClass(), - )); - } - $container->setParameter('templating.engines', $config['engines']); $engines = array_map(function ($engine) { return new Reference('templating.engine.'.$engine); }, $config['engines']); @@ -845,14 +760,6 @@ private function registerTemplatingConfiguration(array $config, ContainerBuilder $container->setAlias('debug.templating.engine.php', 'templating.engine.php'); } - if (PHP_VERSION_ID < 70000) { - $this->addClassesToCompile(array( - 'Symfony\\Component\\Templating\\Storage\\FileStorage', - 'Symfony\\Bundle\\FrameworkBundle\\Templating\\PhpEngine', - 'Symfony\\Bundle\\FrameworkBundle\\Templating\\Loader\\FilesystemLoader', - )); - } - if ($container->has('assets.packages')) { $container->getDefinition('templating.helper.assets')->replaceArgument(0, new Reference('assets.packages')); } else { @@ -1185,13 +1092,6 @@ private function registerAnnotationsConfiguration(array $config, ContainerBuilde // Enable warmer only if PHP array is used for cache $definition = $container->findDefinition('annotations.cache_warmer'); $definition->addTag('kernel.cache_warmer'); - - if (PHP_VERSION_ID < 70000) { - $this->addClassesToCompile(array( - 'Symfony\Component\Cache\Adapter\PhpArrayAdapter', - 'Symfony\Component\Cache\DoctrineProvider', - )); - } } elseif ('file' === $config['cache']) { $cacheDir = $container->getParameterBag()->resolveValue($config['file_cache_dir']); @@ -1442,14 +1342,6 @@ private function registerCacheConfiguration(array $config, ContainerBuilder $con $propertyAccessDefinition->setArguments(array(0, false)); } } - - if (PHP_VERSION_ID < 70000) { - $this->addClassesToCompile(array( - 'Symfony\Component\Cache\Adapter\ApcuAdapter', - 'Symfony\Component\Cache\Adapter\FilesystemAdapter', - 'Symfony\Component\Cache\CacheItem', - )); - } } /** diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/services.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/services.xml index 6babacc0eb06a..00f6420ae7574 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/services.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/services.xml @@ -25,18 +25,6 @@ - - - Symfony\Component\HttpFoundation\ParameterBag - Symfony\Component\HttpFoundation\HeaderBag - Symfony\Component\HttpFoundation\FileBag - Symfony\Component\HttpFoundation\ServerBag - Symfony\Component\HttpFoundation\Request - Symfony\Component\HttpKernel\Kernel - - The "%service_id%" option is deprecated since version 3.3, to be removed in 4.0. - - diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/CacheWarmer/ClassCacheCacheWarmerTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/CacheWarmer/ClassCacheCacheWarmerTest.php deleted file mode 100644 index 5e442d662f12a..0000000000000 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/CacheWarmer/ClassCacheCacheWarmerTest.php +++ /dev/null @@ -1,51 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\Tests\CacheWarmer; - -use Symfony\Bundle\FrameworkBundle\CacheWarmer\ClassCacheCacheWarmer; -use Symfony\Bundle\FrameworkBundle\Tests\Fixtures\DeclaredClass; -use Symfony\Bundle\FrameworkBundle\Tests\Fixtures\WarmedClass; -use Symfony\Bundle\FrameworkBundle\Tests\TestCase; - -/** - * @group legacy - */ -class ClassCacheCacheWarmerTest extends TestCase -{ - public function testWithDeclaredClasses() - { - $this->assertTrue(class_exists(WarmedClass::class, true)); - - $dir = sys_get_temp_dir(); - @unlink($dir.'/classes.php'); - file_put_contents($dir.'/classes.map', sprintf('warmUp($dir); - - $this->assertSame(<<<'EOTXT' -registerForAutoconfiguration(VoterInterface::class) ->addTag('security.voter'); - - if (PHP_VERSION_ID < 70000) { - // add some required classes for compilation - $this->addClassesToCompile(array( - 'Symfony\Component\Security\Http\Firewall', - 'Symfony\Component\Security\Core\User\UserProviderInterface', - 'Symfony\Component\Security\Core\Authentication\AuthenticationProviderManager', - 'Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage', - 'Symfony\Component\Security\Core\Authorization\AccessDecisionManager', - 'Symfony\Component\Security\Core\Authorization\AuthorizationChecker', - 'Symfony\Component\Security\Core\Authorization\Voter\VoterInterface', - 'Symfony\Bundle\SecurityBundle\Security\FirewallConfig', - 'Symfony\Bundle\SecurityBundle\Security\FirewallContext', - 'Symfony\Component\HttpFoundation\RequestMatcher', - )); - } } private function aclLoad($config, ContainerBuilder $container) @@ -204,12 +188,6 @@ private function createAuthorization($config, ContainerBuilder $container) return; } - if (PHP_VERSION_ID < 70000) { - $this->addClassesToCompile(array( - 'Symfony\\Component\\Security\\Http\\AccessMap', - )); - } - foreach ($config['access_control'] as $access) { $matcher = $this->createRequestMatcher( $container, diff --git a/src/Symfony/Bundle/TwigBundle/DependencyInjection/TwigExtension.php b/src/Symfony/Bundle/TwigBundle/DependencyInjection/TwigExtension.php index 916ca53c74da5..42306f499a31f 100644 --- a/src/Symfony/Bundle/TwigBundle/DependencyInjection/TwigExtension.php +++ b/src/Symfony/Bundle/TwigBundle/DependencyInjection/TwigExtension.php @@ -148,19 +148,6 @@ public function load(array $configs, ContainerBuilder $container) ->addTag('twig.extension'); $container->registerForAutoconfiguration(\Twig_LoaderInterface::class) ->addTag('twig.loader'); - - if (PHP_VERSION_ID < 70000) { - $this->addClassesToCompile(array( - 'Twig_Environment', - 'Twig_Extension', - 'Twig_Extension_Core', - 'Twig_Extension_Escaper', - 'Twig_Extension_Optimizer', - 'Twig_LoaderInterface', - 'Twig_Markup', - 'Twig_Template', - )); - } } private function getBundleHierarchy(ContainerBuilder $container) diff --git a/src/Symfony/Component/ClassLoader/ClassCollectionLoader.php b/src/Symfony/Component/ClassLoader/ClassCollectionLoader.php deleted file mode 100644 index 0079e8a7981a7..0000000000000 --- a/src/Symfony/Component/ClassLoader/ClassCollectionLoader.php +++ /dev/null @@ -1,450 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\ClassLoader; - -if (PHP_VERSION_ID >= 70000) { - @trigger_error('The '.__NAMESPACE__.'\ClassCollectionLoader class is deprecated since version 3.3 and will be removed in 4.0.', E_USER_DEPRECATED); -} - -/** - * ClassCollectionLoader. - * - * @author Fabien Potencier - * - * @deprecated since version 3.3, to be removed in 4.0. - */ -class ClassCollectionLoader -{ - private static $loaded; - private static $seen; - private static $useTokenizer = true; - - /** - * Loads a list of classes and caches them in one big file. - * - * @param array $classes An array of classes to load - * @param string $cacheDir A cache directory - * @param string $name The cache name prefix - * @param bool $autoReload Whether to flush the cache when the cache is stale or not - * @param bool $adaptive Whether to remove already declared classes or not - * @param string $extension File extension of the resulting file - * - * @throws \InvalidArgumentException When class can't be loaded - */ - public static function load($classes, $cacheDir, $name, $autoReload, $adaptive = false, $extension = '.php') - { - // each $name can only be loaded once per PHP process - if (isset(self::$loaded[$name])) { - return; - } - - self::$loaded[$name] = true; - - if ($adaptive) { - $declared = array_merge(get_declared_classes(), get_declared_interfaces(), get_declared_traits()); - - // don't include already declared classes - $classes = array_diff($classes, $declared); - - // the cache is different depending on which classes are already declared - $name = $name.'-'.substr(hash('sha256', implode('|', $classes)), 0, 5); - } - - $classes = array_unique($classes); - - // cache the core classes - if (!is_dir($cacheDir) && !@mkdir($cacheDir, 0777, true) && !is_dir($cacheDir)) { - throw new \RuntimeException(sprintf('Class Collection Loader was not able to create directory "%s"', $cacheDir)); - } - $cacheDir = rtrim(realpath($cacheDir) ?: $cacheDir, '/'.DIRECTORY_SEPARATOR); - $cache = $cacheDir.'/'.$name.$extension; - - // auto-reload - $reload = false; - if ($autoReload) { - $metadata = $cache.'.meta'; - if (!is_file($metadata) || !is_file($cache)) { - $reload = true; - } else { - $time = filemtime($cache); - $meta = unserialize(file_get_contents($metadata)); - - sort($meta[1]); - sort($classes); - - if ($meta[1] != $classes) { - $reload = true; - } else { - foreach ($meta[0] as $resource) { - if (!is_file($resource) || filemtime($resource) > $time) { - $reload = true; - - break; - } - } - } - } - } - - if (!$reload && file_exists($cache)) { - require_once $cache; - - return; - } - if (!$adaptive) { - $declared = array_merge(get_declared_classes(), get_declared_interfaces(), get_declared_traits()); - } - - $files = self::inline($classes, $cache, $declared); - - if ($autoReload) { - // save the resources - self::writeCacheFile($metadata, serialize(array(array_values($files), $classes))); - } - } - - /** - * Generates a file where classes and their parents are inlined. - * - * @param array $classes An array of classes to load - * @param string $cache The file where classes are inlined - * @param array $excluded An array of classes that won't be inlined - * - * @return array The source map of inlined classes, with classes as keys and files as values - * - * @throws \RuntimeException When class can't be loaded - */ - public static function inline($classes, $cache, array $excluded) - { - $declared = array(); - foreach (self::getOrderedClasses($excluded) as $class) { - $declared[$class->getName()] = true; - } - - // cache the core classes - $cacheDir = dirname($cache); - if (!is_dir($cacheDir) && !@mkdir($cacheDir, 0777, true) && !is_dir($cacheDir)) { - throw new \RuntimeException(sprintf('Class Collection Loader was not able to create directory "%s"', $cacheDir)); - } - - $spacesRegex = '(?:\s*+(?:(?:\#|//)[^\n]*+\n|/\*(?:(?getName()])) { - continue; - } - $declared[$class->getName()] = true; - - $files[$class->getName()] = $file = $class->getFileName(); - $c = file_get_contents($file); - - if (preg_match($dontInlineRegex, $c)) { - $file = explode('/', str_replace(DIRECTORY_SEPARATOR, '/', $file)); - - for ($i = 0; isset($file[$i], $cacheDir[$i]); ++$i) { - if ($file[$i] !== $cacheDir[$i]) { - break; - } - } - if (1 >= $i) { - $file = var_export(implode('/', $file), true); - } else { - $file = array_slice($file, $i); - $file = str_repeat('../', count($cacheDir) - $i).implode('/', $file); - $file = '__DIR__.'.var_export('/'.$file, true); - } - - $c = "\nnamespace {require $file;}"; - } else { - $c = preg_replace(array('/^\s*<\?php/', '/\?>\s*$/'), '', $c); - - // fakes namespace declaration for global code - if (!$class->inNamespace()) { - $c = "\nnamespace\n{\n".$c."\n}\n"; - } - - $c = self::fixNamespaceDeclarations('= 70000) { - // PHP 7 memory manager will not release after token_get_all(), see https://bugs.php.net/70098 - unset($tokens, $rawChunk); - gc_mem_caches(); - } - - return $output; - } - - /** - * This method is only useful for testing. - */ - public static function enableTokenizer($bool) - { - self::$useTokenizer = (bool) $bool; - } - - /** - * Strips leading & trailing ws, multiple EOL, multiple ws. - * - * @param string $code Original PHP code - * - * @return string compressed code - */ - private static function compressCode($code) - { - return preg_replace( - array('/^\s+/m', '/\s+$/m', '/([\n\r]+ *[\n\r]+)+/', '/[ \t]+/'), - array('', '', "\n", ' '), - $code - ); - } - - /** - * Writes a cache file. - * - * @param string $file Filename - * @param string $content Temporary file content - * - * @throws \RuntimeException when a cache file cannot be written - */ - private static function writeCacheFile($file, $content) - { - $dir = dirname($file); - if (!is_writable($dir)) { - throw new \RuntimeException(sprintf('Cache directory "%s" is not writable.', $dir)); - } - - $tmpFile = tempnam($dir, basename($file)); - - if (false !== @file_put_contents($tmpFile, $content) && @rename($tmpFile, $file)) { - @chmod($file, 0666 & ~umask()); - - return; - } - - throw new \RuntimeException(sprintf('Failed to write cache file "%s".', $file)); - } - - /** - * Gets an ordered array of passed classes including all their dependencies. - * - * @param array $classes - * - * @return \ReflectionClass[] An array of sorted \ReflectionClass instances (dependencies added if needed) - * - * @throws \InvalidArgumentException When a class can't be loaded - */ - private static function getOrderedClasses(array $classes) - { - $map = array(); - self::$seen = array(); - foreach ($classes as $class) { - try { - $reflectionClass = new \ReflectionClass($class); - } catch (\ReflectionException $e) { - throw new \InvalidArgumentException(sprintf('Unable to load class "%s"', $class)); - } - - $map = array_merge($map, self::getClassHierarchy($reflectionClass)); - } - - return $map; - } - - private static function getClassHierarchy(\ReflectionClass $class) - { - if (isset(self::$seen[$class->getName()])) { - return array(); - } - - self::$seen[$class->getName()] = true; - - $classes = array($class); - $parent = $class; - while (($parent = $parent->getParentClass()) && $parent->isUserDefined() && !isset(self::$seen[$parent->getName()])) { - self::$seen[$parent->getName()] = true; - - array_unshift($classes, $parent); - } - - $traits = array(); - - foreach ($classes as $c) { - foreach (self::resolveDependencies(self::computeTraitDeps($c), $c) as $trait) { - if ($trait !== $c) { - $traits[] = $trait; - } - } - } - - return array_merge(self::getInterfaces($class), $traits, $classes); - } - - private static function getInterfaces(\ReflectionClass $class) - { - $classes = array(); - - foreach ($class->getInterfaces() as $interface) { - $classes = array_merge($classes, self::getInterfaces($interface)); - } - - if ($class->isUserDefined() && $class->isInterface() && !isset(self::$seen[$class->getName()])) { - self::$seen[$class->getName()] = true; - - $classes[] = $class; - } - - return $classes; - } - - private static function computeTraitDeps(\ReflectionClass $class) - { - $traits = $class->getTraits(); - $deps = array($class->getName() => $traits); - while ($trait = array_pop($traits)) { - if ($trait->isUserDefined() && !isset(self::$seen[$trait->getName()])) { - self::$seen[$trait->getName()] = true; - $traitDeps = $trait->getTraits(); - $deps[$trait->getName()] = $traitDeps; - $traits = array_merge($traits, $traitDeps); - } - } - - return $deps; - } - - /** - * Dependencies resolution. - * - * This function does not check for circular dependencies as it should never - * occur with PHP traits. - * - * @param array $tree The dependency tree - * @param \ReflectionClass $node The node - * @param \ArrayObject $resolved An array of already resolved dependencies - * @param \ArrayObject $unresolved An array of dependencies to be resolved - * - * @return \ArrayObject The dependencies for the given node - * - * @throws \RuntimeException if a circular dependency is detected - */ - private static function resolveDependencies(array $tree, $node, \ArrayObject $resolved = null, \ArrayObject $unresolved = null) - { - if (null === $resolved) { - $resolved = new \ArrayObject(); - } - if (null === $unresolved) { - $unresolved = new \ArrayObject(); - } - $nodeName = $node->getName(); - - if (isset($tree[$nodeName])) { - $unresolved[$nodeName] = $node; - foreach ($tree[$nodeName] as $dependency) { - if (!$resolved->offsetExists($dependency->getName())) { - self::resolveDependencies($tree, $dependency, $resolved, $unresolved); - } - } - $resolved[$nodeName] = $node; - unset($unresolved[$nodeName]); - } - - return $resolved; - } -} diff --git a/src/Symfony/Component/ClassLoader/Tests/ClassCollectionLoaderTest.php b/src/Symfony/Component/ClassLoader/Tests/ClassCollectionLoaderTest.php deleted file mode 100644 index da34082bea864..0000000000000 --- a/src/Symfony/Component/ClassLoader/Tests/ClassCollectionLoaderTest.php +++ /dev/null @@ -1,319 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\ClassLoader\Tests; - -use PHPUnit\Framework\TestCase; -use Symfony\Component\ClassLoader\ClassCollectionLoader; -use Symfony\Component\ClassLoader\Tests\Fixtures\DeclaredClass; -use Symfony\Component\ClassLoader\Tests\Fixtures\WarmedClass; - -require_once __DIR__.'/Fixtures/ClassesWithParents/GInterface.php'; -require_once __DIR__.'/Fixtures/ClassesWithParents/CInterface.php'; -require_once __DIR__.'/Fixtures/ClassesWithParents/B.php'; -require_once __DIR__.'/Fixtures/ClassesWithParents/A.php'; - -/** - * @group legacy - */ -class ClassCollectionLoaderTest extends TestCase -{ - public function testTraitDependencies() - { - require_once __DIR__.'/Fixtures/deps/traits.php'; - - $r = new \ReflectionClass('Symfony\Component\ClassLoader\ClassCollectionLoader'); - $m = $r->getMethod('getOrderedClasses'); - $m->setAccessible(true); - - $ordered = $m->invoke(null, array('CTFoo')); - - $this->assertEquals( - array('TD', 'TC', 'TB', 'TA', 'TZ', 'CTFoo'), - array_map(function ($class) { return $class->getName(); }, $ordered) - ); - - $ordered = $m->invoke(null, array('CTBar')); - - $this->assertEquals( - array('TD', 'TZ', 'TC', 'TB', 'TA', 'CTBar'), - array_map(function ($class) { return $class->getName(); }, $ordered) - ); - } - - /** - * @dataProvider getDifferentOrders - */ - public function testClassReordering(array $classes) - { - $expected = array( - 'ClassesWithParents\\GInterface', - 'ClassesWithParents\\CInterface', - 'ClassesWithParents\\B', - 'ClassesWithParents\\A', - ); - - $r = new \ReflectionClass('Symfony\Component\ClassLoader\ClassCollectionLoader'); - $m = $r->getMethod('getOrderedClasses'); - $m->setAccessible(true); - - $ordered = $m->invoke(null, $classes); - - $this->assertEquals($expected, array_map(function ($class) { return $class->getName(); }, $ordered)); - } - - public function getDifferentOrders() - { - return array( - array(array( - 'ClassesWithParents\\A', - 'ClassesWithParents\\CInterface', - 'ClassesWithParents\\GInterface', - 'ClassesWithParents\\B', - )), - array(array( - 'ClassesWithParents\\B', - 'ClassesWithParents\\A', - 'ClassesWithParents\\CInterface', - )), - array(array( - 'ClassesWithParents\\CInterface', - 'ClassesWithParents\\B', - 'ClassesWithParents\\A', - )), - array(array( - 'ClassesWithParents\\A', - )), - ); - } - - /** - * @dataProvider getDifferentOrdersForTraits - */ - public function testClassWithTraitsReordering(array $classes) - { - require_once __DIR__.'/Fixtures/ClassesWithParents/ATrait.php'; - require_once __DIR__.'/Fixtures/ClassesWithParents/BTrait.php'; - require_once __DIR__.'/Fixtures/ClassesWithParents/CTrait.php'; - require_once __DIR__.'/Fixtures/ClassesWithParents/D.php'; - require_once __DIR__.'/Fixtures/ClassesWithParents/E.php'; - - $expected = array( - 'ClassesWithParents\\GInterface', - 'ClassesWithParents\\CInterface', - 'ClassesWithParents\\ATrait', - 'ClassesWithParents\\BTrait', - 'ClassesWithParents\\CTrait', - 'ClassesWithParents\\B', - 'ClassesWithParents\\A', - 'ClassesWithParents\\D', - 'ClassesWithParents\\E', - ); - - $r = new \ReflectionClass('Symfony\Component\ClassLoader\ClassCollectionLoader'); - $m = $r->getMethod('getOrderedClasses'); - $m->setAccessible(true); - - $ordered = $m->invoke(null, $classes); - - $this->assertEquals($expected, array_map(function ($class) { return $class->getName(); }, $ordered)); - } - - public function getDifferentOrdersForTraits() - { - return array( - array(array( - 'ClassesWithParents\\E', - 'ClassesWithParents\\ATrait', - )), - array(array( - 'ClassesWithParents\\E', - )), - ); - } - - public function testFixClassWithTraitsOrdering() - { - require_once __DIR__.'/Fixtures/ClassesWithParents/CTrait.php'; - require_once __DIR__.'/Fixtures/ClassesWithParents/F.php'; - require_once __DIR__.'/Fixtures/ClassesWithParents/G.php'; - - $classes = array( - 'ClassesWithParents\\F', - 'ClassesWithParents\\G', - ); - - $expected = array( - 'ClassesWithParents\\CTrait', - 'ClassesWithParents\\F', - 'ClassesWithParents\\G', - ); - - $r = new \ReflectionClass('Symfony\Component\ClassLoader\ClassCollectionLoader'); - $m = $r->getMethod('getOrderedClasses'); - $m->setAccessible(true); - - $ordered = $m->invoke(null, $classes); - - $this->assertEquals($expected, array_map(function ($class) { return $class->getName(); }, $ordered)); - } - - /** - * @dataProvider getFixNamespaceDeclarationsData - */ - public function testFixNamespaceDeclarations($source, $expected) - { - $this->assertEquals('assertEquals('assertEquals(<<<'EOF' -namespace Namespaced -{ -class WithComments -{ -public static $loaded = true; -} -$string ='string should not be modified {$string}'; -$heredoc = (<<assertTrue(class_exists(WarmedClass::class, true)); - - @unlink($cache = sys_get_temp_dir().'/inline.php'); - - $classes = array(WarmedClass::class); - $excluded = array(DeclaredClass::class); - - ClassCollectionLoader::inline($classes, $cache, $excluded); - - $this->assertSame(<<<'EOTXT' -getExtensions() as $extension) { if ($extension instanceof Extension) { - if (PHP_VERSION_ID < 70000) { - $classes = array_merge($classes, $extension->getClassesToCompile()); - } $annotatedClasses = array_merge($annotatedClasses, $extension->getAnnotatedClassesToCompile()); } } $existingClasses = $this->getClassesInComposerClassMaps(); - if (PHP_VERSION_ID < 70000) { - $classes = $container->getParameterBag()->resolveValue($classes); - $this->kernel->setClassCache($this->expandClasses($classes, $existingClasses)); - } $annotatedClasses = $container->getParameterBag()->resolveValue($annotatedClasses); $this->kernel->setAnnotatedClassCache($this->expandClasses($annotatedClasses, $existingClasses)); } diff --git a/src/Symfony/Component/HttpKernel/DependencyInjection/AddClassesToCachePass.php b/src/Symfony/Component/HttpKernel/DependencyInjection/AddClassesToCachePass.php deleted file mode 100644 index 4ffa17511d889..0000000000000 --- a/src/Symfony/Component/HttpKernel/DependencyInjection/AddClassesToCachePass.php +++ /dev/null @@ -1,25 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\DependencyInjection; - -@trigger_error('The '.__NAMESPACE__.'\AddClassesToCachePass class is deprecated since version 3.3 and will be removed in 4.0.', E_USER_DEPRECATED); - -/** - * Sets the classes to compile in the cache for the container. - * - * @author Fabien Potencier - * - * @deprecated since version 3.3, to be removed in 4.0. - */ -class AddClassesToCachePass extends AddAnnotatedClassesToCachePass -{ -} diff --git a/src/Symfony/Component/HttpKernel/DependencyInjection/Extension.php b/src/Symfony/Component/HttpKernel/DependencyInjection/Extension.php index 99ae0d4b90109..647875554b00c 100644 --- a/src/Symfony/Component/HttpKernel/DependencyInjection/Extension.php +++ b/src/Symfony/Component/HttpKernel/DependencyInjection/Extension.php @@ -20,19 +20,8 @@ */ abstract class Extension extends BaseExtension { - private $classes = array(); private $annotatedClasses = array(); - /** - * Gets the classes to cache. - * - * @return array An array of classes - */ - public function getClassesToCompile() - { - return $this->classes; - } - /** * Gets the annotated classes to cache. * @@ -43,22 +32,6 @@ public function getAnnotatedClassesToCompile() return $this->annotatedClasses; } - /** - * Adds classes to the class cache. - * - * @param array $classes An array of class patterns - * - * @deprecated since version 3.3, to be removed in 4.0. - */ - public function addClassesToCompile(array $classes) - { - if (PHP_VERSION_ID >= 70000) { - @trigger_error(__METHOD__.'() is deprecated since version 3.3, to be removed in 4.0.', E_USER_DEPRECATED); - } - - $this->classes = array_merge($this->classes, $classes); - } - /** * Adds annotated classes to the class cache. * diff --git a/src/Symfony/Component/HttpKernel/Kernel.php b/src/Symfony/Component/HttpKernel/Kernel.php index ae31a46fc985f..2af2ae3b640e6 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -33,7 +33,6 @@ use Symfony\Component\Config\Loader\LoaderResolver; use Symfony\Component\Config\Loader\DelegatingLoader; use Symfony\Component\Config\ConfigCache; -use Symfony\Component\ClassLoader\ClassCollectionLoader; /** * The Kernel is the heart of the Symfony system. @@ -57,7 +56,6 @@ abstract class Kernel implements KernelInterface, TerminableInterface protected $booted = false; protected $name; protected $startTime; - protected $loadClassCache; private $projectDir; @@ -109,10 +107,6 @@ public function boot() return; } - if ($this->loadClassCache) { - $this->doLoadClassCache($this->loadClassCache[0], $this->loadClassCache[1]); - } - // init bundles $this->initializeBundles(); @@ -339,43 +333,6 @@ public function getContainer() return $this->container; } - /** - * Loads the PHP class cache. - * - * This methods only registers the fact that you want to load the cache classes. - * The cache will actually only be loaded when the Kernel is booted. - * - * That optimization is mainly useful when using the HttpCache class in which - * case the class cache is not loaded if the Response is in the cache. - * - * @param string $name The cache name prefix - * @param string $extension File extension of the resulting file - * - * @deprecated since version 3.3, to be removed in 4.0. - */ - public function loadClassCache($name = 'classes', $extension = '.php') - { - if (PHP_VERSION_ID >= 70000) { - @trigger_error(__METHOD__.'() is deprecated since version 3.3, to be removed in 4.0.', E_USER_DEPRECATED); - } - - $this->loadClassCache = array($name, $extension); - } - - /** - * @internal - * - * @deprecated since version 3.3, to be removed in 4.0. - */ - public function setClassCache(array $classes) - { - if (PHP_VERSION_ID >= 70000) { - @trigger_error(__METHOD__.'() is deprecated since version 3.3, to be removed in 4.0.', E_USER_DEPRECATED); - } - - file_put_contents($this->getCacheDir().'/classes.map', sprintf('= 70000) { - @trigger_error(__METHOD__.'() is deprecated since version 3.3, to be removed in 4.0.', E_USER_DEPRECATED); - } - - if (!$this->booted && is_file($this->getCacheDir().'/classes.map')) { - ClassCollectionLoader::load(include($this->getCacheDir().'/classes.map'), $this->getCacheDir(), $name, $this->debug, false, $extension); - } - } - /** * Initializes the data structures related to the bundle management. * diff --git a/src/Symfony/Component/HttpKernel/Tests/KernelTest.php b/src/Symfony/Component/HttpKernel/Tests/KernelTest.php index 4cc31d49903b1..32166687ed2ea 100644 --- a/src/Symfony/Component/HttpKernel/Tests/KernelTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/KernelTest.php @@ -87,20 +87,6 @@ public function testBootSetsTheBootedFlagToTrue() $this->assertTrue($kernel->isBooted()); } - /** - * @group legacy - */ - public function testClassCacheIsLoaded() - { - $kernel = $this->getKernel(array('initializeBundles', 'initializeContainer', 'doLoadClassCache')); - $kernel->loadClassCache('name', '.extension'); - $kernel->expects($this->once()) - ->method('doLoadClassCache') - ->with('name', '.extension'); - - $kernel->boot(); - } - public function testClassCacheIsNotLoadedByDefault() { $kernel = $this->getKernel(array('initializeBundles', 'initializeContainer', 'doLoadClassCache')); @@ -110,17 +96,6 @@ public function testClassCacheIsNotLoadedByDefault() $kernel->boot(); } - /** - * @group legacy - */ - public function testClassCacheIsNotLoadedWhenKernelIsNotBooted() - { - $kernel = $this->getKernel(array('initializeBundles', 'initializeContainer', 'doLoadClassCache')); - $kernel->loadClassCache(); - $kernel->expects($this->never()) - ->method('doLoadClassCache'); - } - public function testEnvParametersResourceIsAdded() { $container = new ContainerBuilder(); From 551aaefcae897271edcc97b73747b4c93c492cf2 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Sat, 20 May 2017 07:54:41 +0200 Subject: [PATCH 0033/1099] [ClassLoader] remove the component (cherry picked from commit c365ae2) --- composer.json | 1 - .../Bundle/FrameworkBundle/composer.json | 1 - src/Symfony/Component/ClassLoader/.gitignore | 3 - .../Component/ClassLoader/ApcClassLoader.php | 145 ----------- .../Component/ClassLoader/CHANGELOG.md | 41 --- .../Component/ClassLoader/ClassLoader.php | 207 --------------- .../ClassLoader/ClassMapGenerator.php | 160 ------------ src/Symfony/Component/ClassLoader/LICENSE | 19 -- .../Component/ClassLoader/MapClassLoader.php | 72 ------ .../Component/ClassLoader/Psr4ClassLoader.php | 97 ------- src/Symfony/Component/ClassLoader/README.md | 14 -- .../ClassLoader/Tests/ApcClassLoaderTest.php | 200 --------------- .../ClassLoader/Tests/ClassLoaderTest.php | 238 ------------------ .../Tests/ClassMapGeneratorTest.php | 151 ----------- .../Tests/Fixtures/Apc/Namespaced/Bar.php | 17 -- .../Tests/Fixtures/Apc/Namespaced/Baz.php | 17 -- .../Tests/Fixtures/Apc/Namespaced/Foo.php | 17 -- .../Tests/Fixtures/Apc/Namespaced/FooBar.php | 17 -- .../Tests/Fixtures/Apc/Pearlike/Bar.php | 6 - .../Tests/Fixtures/Apc/Pearlike/Baz.php | 6 - .../Tests/Fixtures/Apc/Pearlike/Foo.php | 6 - .../alpha/Apc/ApcPrefixCollision/A/Bar.php | 6 - .../alpha/Apc/ApcPrefixCollision/A/Foo.php | 6 - .../alpha/Apc/NamespaceCollision/A/Bar.php | 17 -- .../alpha/Apc/NamespaceCollision/A/Foo.php | 17 -- .../beta/Apc/ApcPrefixCollision/A/B/Bar.php | 6 - .../beta/Apc/ApcPrefixCollision/A/B/Foo.php | 6 - .../beta/Apc/NamespaceCollision/A/B/Bar.php | 17 -- .../beta/Apc/NamespaceCollision/A/B/Foo.php | 17 -- .../Apc/fallback/Apc/Pearlike/FooBar.php | 6 - .../Apc/fallback/Namespaced/FooBar.php | 17 -- .../Tests/Fixtures/DeclaredClass.php | 7 - .../Tests/Fixtures/DeclaredInterface.php | 7 - .../Tests/Fixtures/Namespaced/Bar.php | 17 -- .../Tests/Fixtures/Namespaced/Baz.php | 17 -- .../Tests/Fixtures/Namespaced/Foo.php | 17 -- .../Fixtures/Namespaced/WithComments.php | 37 --- .../Fixtures/Namespaced/WithDirMagic.php | 15 -- .../Fixtures/Namespaced/WithFileMagic.php | 15 -- .../Fixtures/Namespaced/WithHaltCompiler.php | 18 -- .../Fixtures/Namespaced/WithStrictTypes.php | 13 - .../Tests/Fixtures/Namespaced2/Bar.php | 8 - .../Tests/Fixtures/Namespaced2/Baz.php | 8 - .../Tests/Fixtures/Namespaced2/Foo.php | 8 - .../Tests/Fixtures/Pearlike/Bar.php | 6 - .../Tests/Fixtures/Pearlike/Baz.php | 6 - .../Tests/Fixtures/Pearlike/Foo.php | 6 - .../Tests/Fixtures/Pearlike/WithComments.php | 16 -- .../Tests/Fixtures/Pearlike2/Bar.php | 6 - .../Tests/Fixtures/Pearlike2/Baz.php | 6 - .../Tests/Fixtures/Pearlike2/Foo.php | 6 - .../Tests/Fixtures/WarmedClass.php | 7 - .../Tests/Fixtures/WarmedInterface.php | 7 - .../alpha/NamespaceCollision/A/Bar.php | 17 -- .../alpha/NamespaceCollision/A/Foo.php | 17 -- .../alpha/NamespaceCollision/C/Bar.php | 8 - .../alpha/NamespaceCollision/C/Foo.php | 8 - .../Fixtures/alpha/PrefixCollision/A/Bar.php | 6 - .../Fixtures/alpha/PrefixCollision/A/Foo.php | 6 - .../Fixtures/alpha/PrefixCollision/C/Bar.php | 6 - .../Fixtures/alpha/PrefixCollision/C/Foo.php | 6 - .../beta/NamespaceCollision/A/B/Bar.php | 17 -- .../beta/NamespaceCollision/A/B/Foo.php | 17 -- .../beta/NamespaceCollision/C/B/Bar.php | 8 - .../beta/NamespaceCollision/C/B/Foo.php | 8 - .../Fixtures/beta/PrefixCollision/A/B/Bar.php | 6 - .../Fixtures/beta/PrefixCollision/A/B/Foo.php | 6 - .../Fixtures/beta/PrefixCollision/C/B/Bar.php | 6 - .../Fixtures/beta/PrefixCollision/C/B/Foo.php | 6 - .../Tests/Fixtures/classmap/SomeClass.php | 16 -- .../Tests/Fixtures/classmap/SomeInterface.php | 16 -- .../Tests/Fixtures/classmap/SomeParent.php | 16 -- .../Tests/Fixtures/classmap/multipleNs.php | 25 -- .../Tests/Fixtures/classmap/notAClass.php | 3 - .../Tests/Fixtures/classmap/notPhpFile.md | 1 - .../classmap/sameNsMultipleClasses.php | 19 -- .../Fixtures/fallback/Namespaced/FooBar.php | 17 -- .../Fixtures/fallback/Namespaced2/FooBar.php | 8 - .../Fixtures/fallback/Pearlike/FooBar.php | 6 - .../Fixtures/fallback/Pearlike2/FooBar.php | 6 - .../Tests/Fixtures/includepath/Foo.php | 5 - .../Tests/Fixtures/php5.4/traits.php | 32 --- .../Tests/Fixtures/php5.5/class_cons.php | 11 - .../Fixtures/psr-4/Class_With_Underscores.php | 7 - .../ClassLoader/Tests/Fixtures/psr-4/Foo.php | 7 - .../Lets/Go/Deeper/Class_With_Underscores.php | 7 - .../Fixtures/psr-4/Lets/Go/Deeper/Foo.php | 7 - .../ClassLoader/Tests/Psr4ClassLoaderTest.php | 75 ------ .../ClassLoader/WinCacheClassLoader.php | 144 ----------- .../ClassLoader/XcacheClassLoader.php | 145 ----------- .../Component/ClassLoader/composer.json | 40 --- .../Component/ClassLoader/phpunit.xml.dist | 31 --- src/Symfony/Component/Debug/Debug.php | 3 - 93 files changed, 2598 deletions(-) delete mode 100644 src/Symfony/Component/ClassLoader/.gitignore delete mode 100644 src/Symfony/Component/ClassLoader/ApcClassLoader.php delete mode 100644 src/Symfony/Component/ClassLoader/CHANGELOG.md delete mode 100644 src/Symfony/Component/ClassLoader/ClassLoader.php delete mode 100644 src/Symfony/Component/ClassLoader/ClassMapGenerator.php delete mode 100644 src/Symfony/Component/ClassLoader/LICENSE delete mode 100644 src/Symfony/Component/ClassLoader/MapClassLoader.php delete mode 100644 src/Symfony/Component/ClassLoader/Psr4ClassLoader.php delete mode 100644 src/Symfony/Component/ClassLoader/README.md delete mode 100644 src/Symfony/Component/ClassLoader/Tests/ApcClassLoaderTest.php delete mode 100644 src/Symfony/Component/ClassLoader/Tests/ClassLoaderTest.php delete mode 100644 src/Symfony/Component/ClassLoader/Tests/ClassMapGeneratorTest.php delete mode 100644 src/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/Namespaced/Bar.php delete mode 100644 src/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/Namespaced/Baz.php delete mode 100644 src/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/Namespaced/Foo.php delete mode 100644 src/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/Namespaced/FooBar.php delete mode 100644 src/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/Pearlike/Bar.php delete mode 100644 src/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/Pearlike/Baz.php delete mode 100644 src/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/Pearlike/Foo.php delete mode 100644 src/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/alpha/Apc/ApcPrefixCollision/A/Bar.php delete mode 100644 src/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/alpha/Apc/ApcPrefixCollision/A/Foo.php delete mode 100644 src/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/alpha/Apc/NamespaceCollision/A/Bar.php delete mode 100644 src/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/alpha/Apc/NamespaceCollision/A/Foo.php delete mode 100644 src/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/beta/Apc/ApcPrefixCollision/A/B/Bar.php delete mode 100644 src/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/beta/Apc/ApcPrefixCollision/A/B/Foo.php delete mode 100644 src/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/beta/Apc/NamespaceCollision/A/B/Bar.php delete mode 100644 src/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/beta/Apc/NamespaceCollision/A/B/Foo.php delete mode 100644 src/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/fallback/Apc/Pearlike/FooBar.php delete mode 100644 src/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/fallback/Namespaced/FooBar.php delete mode 100644 src/Symfony/Component/ClassLoader/Tests/Fixtures/DeclaredClass.php delete mode 100644 src/Symfony/Component/ClassLoader/Tests/Fixtures/DeclaredInterface.php delete mode 100644 src/Symfony/Component/ClassLoader/Tests/Fixtures/Namespaced/Bar.php delete mode 100644 src/Symfony/Component/ClassLoader/Tests/Fixtures/Namespaced/Baz.php delete mode 100644 src/Symfony/Component/ClassLoader/Tests/Fixtures/Namespaced/Foo.php delete mode 100644 src/Symfony/Component/ClassLoader/Tests/Fixtures/Namespaced/WithComments.php delete mode 100644 src/Symfony/Component/ClassLoader/Tests/Fixtures/Namespaced/WithDirMagic.php delete mode 100644 src/Symfony/Component/ClassLoader/Tests/Fixtures/Namespaced/WithFileMagic.php delete mode 100644 src/Symfony/Component/ClassLoader/Tests/Fixtures/Namespaced/WithHaltCompiler.php delete mode 100644 src/Symfony/Component/ClassLoader/Tests/Fixtures/Namespaced/WithStrictTypes.php delete mode 100644 src/Symfony/Component/ClassLoader/Tests/Fixtures/Namespaced2/Bar.php delete mode 100644 src/Symfony/Component/ClassLoader/Tests/Fixtures/Namespaced2/Baz.php delete mode 100644 src/Symfony/Component/ClassLoader/Tests/Fixtures/Namespaced2/Foo.php delete mode 100644 src/Symfony/Component/ClassLoader/Tests/Fixtures/Pearlike/Bar.php delete mode 100644 src/Symfony/Component/ClassLoader/Tests/Fixtures/Pearlike/Baz.php delete mode 100644 src/Symfony/Component/ClassLoader/Tests/Fixtures/Pearlike/Foo.php delete mode 100644 src/Symfony/Component/ClassLoader/Tests/Fixtures/Pearlike/WithComments.php delete mode 100644 src/Symfony/Component/ClassLoader/Tests/Fixtures/Pearlike2/Bar.php delete mode 100644 src/Symfony/Component/ClassLoader/Tests/Fixtures/Pearlike2/Baz.php delete mode 100644 src/Symfony/Component/ClassLoader/Tests/Fixtures/Pearlike2/Foo.php delete mode 100644 src/Symfony/Component/ClassLoader/Tests/Fixtures/WarmedClass.php delete mode 100644 src/Symfony/Component/ClassLoader/Tests/Fixtures/WarmedInterface.php delete mode 100644 src/Symfony/Component/ClassLoader/Tests/Fixtures/alpha/NamespaceCollision/A/Bar.php delete mode 100644 src/Symfony/Component/ClassLoader/Tests/Fixtures/alpha/NamespaceCollision/A/Foo.php delete mode 100644 src/Symfony/Component/ClassLoader/Tests/Fixtures/alpha/NamespaceCollision/C/Bar.php delete mode 100644 src/Symfony/Component/ClassLoader/Tests/Fixtures/alpha/NamespaceCollision/C/Foo.php delete mode 100644 src/Symfony/Component/ClassLoader/Tests/Fixtures/alpha/PrefixCollision/A/Bar.php delete mode 100644 src/Symfony/Component/ClassLoader/Tests/Fixtures/alpha/PrefixCollision/A/Foo.php delete mode 100644 src/Symfony/Component/ClassLoader/Tests/Fixtures/alpha/PrefixCollision/C/Bar.php delete mode 100644 src/Symfony/Component/ClassLoader/Tests/Fixtures/alpha/PrefixCollision/C/Foo.php delete mode 100644 src/Symfony/Component/ClassLoader/Tests/Fixtures/beta/NamespaceCollision/A/B/Bar.php delete mode 100644 src/Symfony/Component/ClassLoader/Tests/Fixtures/beta/NamespaceCollision/A/B/Foo.php delete mode 100644 src/Symfony/Component/ClassLoader/Tests/Fixtures/beta/NamespaceCollision/C/B/Bar.php delete mode 100644 src/Symfony/Component/ClassLoader/Tests/Fixtures/beta/NamespaceCollision/C/B/Foo.php delete mode 100644 src/Symfony/Component/ClassLoader/Tests/Fixtures/beta/PrefixCollision/A/B/Bar.php delete mode 100644 src/Symfony/Component/ClassLoader/Tests/Fixtures/beta/PrefixCollision/A/B/Foo.php delete mode 100644 src/Symfony/Component/ClassLoader/Tests/Fixtures/beta/PrefixCollision/C/B/Bar.php delete mode 100644 src/Symfony/Component/ClassLoader/Tests/Fixtures/beta/PrefixCollision/C/B/Foo.php delete mode 100644 src/Symfony/Component/ClassLoader/Tests/Fixtures/classmap/SomeClass.php delete mode 100644 src/Symfony/Component/ClassLoader/Tests/Fixtures/classmap/SomeInterface.php delete mode 100644 src/Symfony/Component/ClassLoader/Tests/Fixtures/classmap/SomeParent.php delete mode 100644 src/Symfony/Component/ClassLoader/Tests/Fixtures/classmap/multipleNs.php delete mode 100644 src/Symfony/Component/ClassLoader/Tests/Fixtures/classmap/notAClass.php delete mode 100644 src/Symfony/Component/ClassLoader/Tests/Fixtures/classmap/notPhpFile.md delete mode 100644 src/Symfony/Component/ClassLoader/Tests/Fixtures/classmap/sameNsMultipleClasses.php delete mode 100644 src/Symfony/Component/ClassLoader/Tests/Fixtures/fallback/Namespaced/FooBar.php delete mode 100644 src/Symfony/Component/ClassLoader/Tests/Fixtures/fallback/Namespaced2/FooBar.php delete mode 100644 src/Symfony/Component/ClassLoader/Tests/Fixtures/fallback/Pearlike/FooBar.php delete mode 100644 src/Symfony/Component/ClassLoader/Tests/Fixtures/fallback/Pearlike2/FooBar.php delete mode 100644 src/Symfony/Component/ClassLoader/Tests/Fixtures/includepath/Foo.php delete mode 100644 src/Symfony/Component/ClassLoader/Tests/Fixtures/php5.4/traits.php delete mode 100644 src/Symfony/Component/ClassLoader/Tests/Fixtures/php5.5/class_cons.php delete mode 100644 src/Symfony/Component/ClassLoader/Tests/Fixtures/psr-4/Class_With_Underscores.php delete mode 100644 src/Symfony/Component/ClassLoader/Tests/Fixtures/psr-4/Foo.php delete mode 100644 src/Symfony/Component/ClassLoader/Tests/Fixtures/psr-4/Lets/Go/Deeper/Class_With_Underscores.php delete mode 100644 src/Symfony/Component/ClassLoader/Tests/Fixtures/psr-4/Lets/Go/Deeper/Foo.php delete mode 100644 src/Symfony/Component/ClassLoader/Tests/Psr4ClassLoaderTest.php delete mode 100644 src/Symfony/Component/ClassLoader/WinCacheClassLoader.php delete mode 100644 src/Symfony/Component/ClassLoader/XcacheClassLoader.php delete mode 100644 src/Symfony/Component/ClassLoader/composer.json delete mode 100644 src/Symfony/Component/ClassLoader/phpunit.xml.dist diff --git a/composer.json b/composer.json index b4664e545dd49..6624073bf8e16 100644 --- a/composer.json +++ b/composer.json @@ -32,7 +32,6 @@ "symfony/asset": "self.version", "symfony/browser-kit": "self.version", "symfony/cache": "self.version", - "symfony/class-loader": "self.version", "symfony/config": "self.version", "symfony/console": "self.version", "symfony/css-selector": "self.version", diff --git a/src/Symfony/Bundle/FrameworkBundle/composer.json b/src/Symfony/Bundle/FrameworkBundle/composer.json index 1ca10ad781a70..f979ea9734d1d 100644 --- a/src/Symfony/Bundle/FrameworkBundle/composer.json +++ b/src/Symfony/Bundle/FrameworkBundle/composer.json @@ -19,7 +19,6 @@ "php": "^7.1.3", "ext-xml": "*", "symfony/cache": "~3.4|~4.0", - "symfony/class-loader": "~3.4|~4.0", "symfony/dependency-injection": "~3.4|~4.0", "symfony/config": "~3.4|~4.0", "symfony/event-dispatcher": "~3.4|~4.0", diff --git a/src/Symfony/Component/ClassLoader/.gitignore b/src/Symfony/Component/ClassLoader/.gitignore deleted file mode 100644 index c49a5d8df5c65..0000000000000 --- a/src/Symfony/Component/ClassLoader/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -vendor/ -composer.lock -phpunit.xml diff --git a/src/Symfony/Component/ClassLoader/ApcClassLoader.php b/src/Symfony/Component/ClassLoader/ApcClassLoader.php deleted file mode 100644 index 0d899842b3c96..0000000000000 --- a/src/Symfony/Component/ClassLoader/ApcClassLoader.php +++ /dev/null @@ -1,145 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\ClassLoader; - -@trigger_error('The '.__NAMESPACE__.'\ApcClassLoader class is deprecated since version 3.3 and will be removed in 4.0. Use `composer install --apcu-autoloader` instead.', E_USER_DEPRECATED); - -/** - * ApcClassLoader implements a wrapping autoloader cached in APC for PHP 5.3. - * - * It expects an object implementing a findFile method to find the file. This - * allows using it as a wrapper around the other loaders of the component (the - * ClassLoader for instance) but also around any other autoloaders following - * this convention (the Composer one for instance). - * - * // with a Symfony autoloader - * use Symfony\Component\ClassLoader\ClassLoader; - * - * $loader = new ClassLoader(); - * $loader->addPrefix('Symfony\Component', __DIR__.'/component'); - * $loader->addPrefix('Symfony', __DIR__.'/framework'); - * - * // or with a Composer autoloader - * use Composer\Autoload\ClassLoader; - * - * $loader = new ClassLoader(); - * $loader->add('Symfony\Component', __DIR__.'/component'); - * $loader->add('Symfony', __DIR__.'/framework'); - * - * $cachedLoader = new ApcClassLoader('my_prefix', $loader); - * - * // activate the cached autoloader - * $cachedLoader->register(); - * - * // eventually deactivate the non-cached loader if it was registered previously - * // to be sure to use the cached one. - * $loader->unregister(); - * - * @author Fabien Potencier - * @author Kris Wallsmith - * - * @deprecated since version 3.3, to be removed in 4.0. Use `composer install --apcu-autoloader` instead. - */ -class ApcClassLoader -{ - private $prefix; - - /** - * A class loader object that implements the findFile() method. - * - * @var object - */ - protected $decorated; - - /** - * Constructor. - * - * @param string $prefix The APC namespace prefix to use - * @param object $decorated A class loader object that implements the findFile() method - * - * @throws \RuntimeException - * @throws \InvalidArgumentException - */ - public function __construct($prefix, $decorated) - { - if (!function_exists('apcu_fetch')) { - throw new \RuntimeException('Unable to use ApcClassLoader as APC is not installed.'); - } - - if (!method_exists($decorated, 'findFile')) { - throw new \InvalidArgumentException('The class finder must implement a "findFile" method.'); - } - - $this->prefix = $prefix; - $this->decorated = $decorated; - } - - /** - * Registers this instance as an autoloader. - * - * @param bool $prepend Whether to prepend the autoloader or not - */ - public function register($prepend = false) - { - spl_autoload_register(array($this, 'loadClass'), true, $prepend); - } - - /** - * Unregisters this instance as an autoloader. - */ - public function unregister() - { - spl_autoload_unregister(array($this, 'loadClass')); - } - - /** - * Loads the given class or interface. - * - * @param string $class The name of the class - * - * @return bool|null True, if loaded - */ - public function loadClass($class) - { - if ($file = $this->findFile($class)) { - require $file; - - return true; - } - } - - /** - * Finds a file by class name while caching lookups to APC. - * - * @param string $class A class name to resolve to file - * - * @return string|null - */ - public function findFile($class) - { - $file = apcu_fetch($this->prefix.$class, $success); - - if (!$success) { - apcu_store($this->prefix.$class, $file = $this->decorated->findFile($class) ?: null); - } - - return $file; - } - - /** - * Passes through all unknown calls onto the decorated object. - */ - public function __call($method, $args) - { - return call_user_func_array(array($this->decorated, $method), $args); - } -} diff --git a/src/Symfony/Component/ClassLoader/CHANGELOG.md b/src/Symfony/Component/ClassLoader/CHANGELOG.md deleted file mode 100644 index 203ec9eede785..0000000000000 --- a/src/Symfony/Component/ClassLoader/CHANGELOG.md +++ /dev/null @@ -1,41 +0,0 @@ -CHANGELOG -========= - -3.3.0 ------ - - * deprecated the component: use Composer instead - -3.0.0 ------ - - * The DebugClassLoader class has been removed - * The DebugUniversalClassLoader class has been removed - * The UniversalClassLoader class has been removed - * The ApcUniversalClassLoader class has been removed - -2.4.0 ------ - - * deprecated the UniversalClassLoader in favor of the ClassLoader class instead - * deprecated the ApcUniversalClassLoader in favor of the ApcClassLoader class instead - * deprecated the DebugUniversalClassLoader in favor of the DebugClassLoader class from the Debug component - * deprecated the DebugClassLoader as it has been moved to the Debug component instead - -2.3.0 ------ - - * added a WinCacheClassLoader for WinCache - -2.1.0 ------ - - * added a DebugClassLoader able to wrap any autoloader providing a findFile - method - * added a new ApcClassLoader and XcacheClassLoader using composition to wrap - other loaders - * added a new ClassLoader which does not distinguish between namespaced and - pear-like classes (as the PEAR convention is a subset of PSR-0) and - supports using Composer's namespace maps - * added a class map generator - * added support for loading globally-installed PEAR packages diff --git a/src/Symfony/Component/ClassLoader/ClassLoader.php b/src/Symfony/Component/ClassLoader/ClassLoader.php deleted file mode 100644 index 0a72d2833a581..0000000000000 --- a/src/Symfony/Component/ClassLoader/ClassLoader.php +++ /dev/null @@ -1,207 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\ClassLoader; - -@trigger_error('The '.__NAMESPACE__.'\ClassLoader class is deprecated since version 3.3 and will be removed in 4.0. Use Composer instead.', E_USER_DEPRECATED); - -/** - * ClassLoader implements an PSR-0 class loader. - * - * See https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-0.md - * - * $loader = new ClassLoader(); - * - * // register classes with namespaces - * $loader->addPrefix('Symfony\Component', __DIR__.'/component'); - * $loader->addPrefix('Symfony', __DIR__.'/framework'); - * - * // activate the autoloader - * $loader->register(); - * - * // to enable searching the include path (e.g. for PEAR packages) - * $loader->setUseIncludePath(true); - * - * In this example, if you try to use a class in the Symfony\Component - * namespace or one of its children (Symfony\Component\Console for instance), - * the autoloader will first look for the class under the component/ - * directory, and it will then fallback to the framework/ directory if not - * found before giving up. - * - * @author Fabien Potencier - * @author Jordi Boggiano - * - * @deprecated since version 3.3, to be removed in 4.0. - */ -class ClassLoader -{ - private $prefixes = array(); - private $fallbackDirs = array(); - private $useIncludePath = false; - - /** - * Returns prefixes. - * - * @return array - */ - public function getPrefixes() - { - return $this->prefixes; - } - - /** - * Returns fallback directories. - * - * @return array - */ - public function getFallbackDirs() - { - return $this->fallbackDirs; - } - - /** - * Adds prefixes. - * - * @param array $prefixes Prefixes to add - */ - public function addPrefixes(array $prefixes) - { - foreach ($prefixes as $prefix => $path) { - $this->addPrefix($prefix, $path); - } - } - - /** - * Registers a set of classes. - * - * @param string $prefix The classes prefix - * @param array|string $paths The location(s) of the classes - */ - public function addPrefix($prefix, $paths) - { - if (!$prefix) { - foreach ((array) $paths as $path) { - $this->fallbackDirs[] = $path; - } - - return; - } - if (isset($this->prefixes[$prefix])) { - if (is_array($paths)) { - $this->prefixes[$prefix] = array_unique(array_merge( - $this->prefixes[$prefix], - $paths - )); - } elseif (!in_array($paths, $this->prefixes[$prefix])) { - $this->prefixes[$prefix][] = $paths; - } - } else { - $this->prefixes[$prefix] = array_unique((array) $paths); - } - } - - /** - * Turns on searching the include for class files. - * - * @param bool $useIncludePath - */ - public function setUseIncludePath($useIncludePath) - { - $this->useIncludePath = (bool) $useIncludePath; - } - - /** - * Can be used to check if the autoloader uses the include path to check - * for classes. - * - * @return bool - */ - public function getUseIncludePath() - { - return $this->useIncludePath; - } - - /** - * Registers this instance as an autoloader. - * - * @param bool $prepend Whether to prepend the autoloader or not - */ - public function register($prepend = false) - { - spl_autoload_register(array($this, 'loadClass'), true, $prepend); - } - - /** - * Unregisters this instance as an autoloader. - */ - public function unregister() - { - spl_autoload_unregister(array($this, 'loadClass')); - } - - /** - * Loads the given class or interface. - * - * @param string $class The name of the class - * - * @return bool|null True, if loaded - */ - public function loadClass($class) - { - if ($file = $this->findFile($class)) { - require $file; - - return true; - } - } - - /** - * Finds the path to the file where the class is defined. - * - * @param string $class The name of the class - * - * @return string|null The path, if found - */ - public function findFile($class) - { - if (false !== $pos = strrpos($class, '\\')) { - // namespaced class name - $classPath = str_replace('\\', DIRECTORY_SEPARATOR, substr($class, 0, $pos)).DIRECTORY_SEPARATOR; - $className = substr($class, $pos + 1); - } else { - // PEAR-like class name - $classPath = null; - $className = $class; - } - - $classPath .= str_replace('_', DIRECTORY_SEPARATOR, $className).'.php'; - - foreach ($this->prefixes as $prefix => $dirs) { - if ($class === strstr($class, $prefix)) { - foreach ($dirs as $dir) { - if (file_exists($dir.DIRECTORY_SEPARATOR.$classPath)) { - return $dir.DIRECTORY_SEPARATOR.$classPath; - } - } - } - } - - foreach ($this->fallbackDirs as $dir) { - if (file_exists($dir.DIRECTORY_SEPARATOR.$classPath)) { - return $dir.DIRECTORY_SEPARATOR.$classPath; - } - } - - if ($this->useIncludePath && $file = stream_resolve_include_path($classPath)) { - return $file; - } - } -} diff --git a/src/Symfony/Component/ClassLoader/ClassMapGenerator.php b/src/Symfony/Component/ClassLoader/ClassMapGenerator.php deleted file mode 100644 index 69df0e1f41672..0000000000000 --- a/src/Symfony/Component/ClassLoader/ClassMapGenerator.php +++ /dev/null @@ -1,160 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\ClassLoader; - -@trigger_error('The '.__NAMESPACE__.'\ClassMapGenerator class is deprecated since version 3.3 and will be removed in 4.0. Use Composer instead.', E_USER_DEPRECATED); - -/** - * ClassMapGenerator. - * - * @author Gyula Sallai - * - * @deprecated since version 3.3, to be removed in 4.0. - */ -class ClassMapGenerator -{ - /** - * Generate a class map file. - * - * @param array|string $dirs Directories or a single path to search in - * @param string $file The name of the class map file - */ - public static function dump($dirs, $file) - { - $dirs = (array) $dirs; - $maps = array(); - - foreach ($dirs as $dir) { - $maps = array_merge($maps, static::createMap($dir)); - } - - file_put_contents($file, sprintf('isFile()) { - continue; - } - - $path = $file->getRealPath() ?: $file->getPathname(); - - if (pathinfo($path, PATHINFO_EXTENSION) !== 'php') { - continue; - } - - $classes = self::findClasses($path); - - if (PHP_VERSION_ID >= 70000) { - // PHP 7 memory manager will not release after token_get_all(), see https://bugs.php.net/70098 - gc_mem_caches(); - } - - foreach ($classes as $class) { - $map[$class] = $path; - } - } - - return $map; - } - - /** - * Extract the classes in the given file. - * - * @param string $path The file to check - * - * @return array The found classes - */ - private static function findClasses($path) - { - $contents = file_get_contents($path); - $tokens = token_get_all($contents); - - $classes = array(); - - $namespace = ''; - for ($i = 0; isset($tokens[$i]); ++$i) { - $token = $tokens[$i]; - - if (!isset($token[1])) { - continue; - } - - $class = ''; - - switch ($token[0]) { - case T_NAMESPACE: - $namespace = ''; - // If there is a namespace, extract it - while (isset($tokens[++$i][1])) { - if (in_array($tokens[$i][0], array(T_STRING, T_NS_SEPARATOR))) { - $namespace .= $tokens[$i][1]; - } - } - $namespace .= '\\'; - break; - case T_CLASS: - case T_INTERFACE: - case T_TRAIT: - // Skip usage of ::class constant - $isClassConstant = false; - for ($j = $i - 1; $j > 0; --$j) { - if (!isset($tokens[$j][1])) { - break; - } - - if (T_DOUBLE_COLON === $tokens[$j][0]) { - $isClassConstant = true; - break; - } elseif (!in_array($tokens[$j][0], array(T_WHITESPACE, T_DOC_COMMENT, T_COMMENT))) { - break; - } - } - - if ($isClassConstant) { - break; - } - - // Find the classname - while (isset($tokens[++$i][1])) { - $t = $tokens[$i]; - if (T_STRING === $t[0]) { - $class .= $t[1]; - } elseif ('' !== $class && T_WHITESPACE === $t[0]) { - break; - } - } - - $classes[] = ltrim($namespace.$class, '\\'); - break; - default: - break; - } - } - - return $classes; - } -} diff --git a/src/Symfony/Component/ClassLoader/LICENSE b/src/Symfony/Component/ClassLoader/LICENSE deleted file mode 100644 index 17d16a13367dd..0000000000000 --- a/src/Symfony/Component/ClassLoader/LICENSE +++ /dev/null @@ -1,19 +0,0 @@ -Copyright (c) 2004-2017 Fabien Potencier - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is furnished -to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/src/Symfony/Component/ClassLoader/MapClassLoader.php b/src/Symfony/Component/ClassLoader/MapClassLoader.php deleted file mode 100644 index 43f1cd03e3b71..0000000000000 --- a/src/Symfony/Component/ClassLoader/MapClassLoader.php +++ /dev/null @@ -1,72 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\ClassLoader; - -@trigger_error('The '.__NAMESPACE__.'\MapClassLoader class is deprecated since version 3.3 and will be removed in 4.0. Use Composer instead.', E_USER_DEPRECATED); - -/** - * A class loader that uses a mapping file to look up paths. - * - * @author Fabien Potencier - * - * @deprecated since version 3.3, to be removed in 4.0. - */ -class MapClassLoader -{ - private $map = array(); - - /** - * Constructor. - * - * @param array $map A map where keys are classes and values the absolute file path - */ - public function __construct(array $map) - { - $this->map = $map; - } - - /** - * Registers this instance as an autoloader. - * - * @param bool $prepend Whether to prepend the autoloader or not - */ - public function register($prepend = false) - { - spl_autoload_register(array($this, 'loadClass'), true, $prepend); - } - - /** - * Loads the given class or interface. - * - * @param string $class The name of the class - */ - public function loadClass($class) - { - if (isset($this->map[$class])) { - require $this->map[$class]; - } - } - - /** - * Finds the path to the file where the class is defined. - * - * @param string $class The name of the class - * - * @return string|null The path, if found - */ - public function findFile($class) - { - if (isset($this->map[$class])) { - return $this->map[$class]; - } - } -} diff --git a/src/Symfony/Component/ClassLoader/Psr4ClassLoader.php b/src/Symfony/Component/ClassLoader/Psr4ClassLoader.php deleted file mode 100644 index ee3d7cf4023c1..0000000000000 --- a/src/Symfony/Component/ClassLoader/Psr4ClassLoader.php +++ /dev/null @@ -1,97 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\ClassLoader; - -@trigger_error('The '.__NAMESPACE__.'\Psr4ClassLoader class is deprecated since version 3.3 and will be removed in 4.0. Use Composer instead.', E_USER_DEPRECATED); - -/** - * A PSR-4 compatible class loader. - * - * See http://www.php-fig.org/psr/psr-4/ - * - * @author Alexander M. Turek - * - * @deprecated since version 3.3, to be removed in 4.0. - */ -class Psr4ClassLoader -{ - /** - * @var array - */ - private $prefixes = array(); - - /** - * @param string $prefix - * @param string $baseDir - */ - public function addPrefix($prefix, $baseDir) - { - $prefix = trim($prefix, '\\').'\\'; - $baseDir = rtrim($baseDir, DIRECTORY_SEPARATOR).DIRECTORY_SEPARATOR; - $this->prefixes[] = array($prefix, $baseDir); - } - - /** - * @param string $class - * - * @return string|null - */ - public function findFile($class) - { - $class = ltrim($class, '\\'); - - foreach ($this->prefixes as list($currentPrefix, $currentBaseDir)) { - if (0 === strpos($class, $currentPrefix)) { - $classWithoutPrefix = substr($class, strlen($currentPrefix)); - $file = $currentBaseDir.str_replace('\\', DIRECTORY_SEPARATOR, $classWithoutPrefix).'.php'; - if (file_exists($file)) { - return $file; - } - } - } - } - - /** - * @param string $class - * - * @return bool - */ - public function loadClass($class) - { - $file = $this->findFile($class); - if (null !== $file) { - require $file; - - return true; - } - - return false; - } - - /** - * Registers this instance as an autoloader. - * - * @param bool $prepend - */ - public function register($prepend = false) - { - spl_autoload_register(array($this, 'loadClass'), true, $prepend); - } - - /** - * Removes this instance from the registered autoloaders. - */ - public function unregister() - { - spl_autoload_unregister(array($this, 'loadClass')); - } -} diff --git a/src/Symfony/Component/ClassLoader/README.md b/src/Symfony/Component/ClassLoader/README.md deleted file mode 100644 index d61992b6a80e7..0000000000000 --- a/src/Symfony/Component/ClassLoader/README.md +++ /dev/null @@ -1,14 +0,0 @@ -ClassLoader Component -===================== - -The ClassLoader component provides tools to autoload your classes and cache -their locations for performance. - -Resources ---------- - - * [Documentation](https://symfony.com/doc/current/components/class_loader/index.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) - in the [main Symfony repository](https://github.com/symfony/symfony) diff --git a/src/Symfony/Component/ClassLoader/Tests/ApcClassLoaderTest.php b/src/Symfony/Component/ClassLoader/Tests/ApcClassLoaderTest.php deleted file mode 100644 index bd02f546bbb6c..0000000000000 --- a/src/Symfony/Component/ClassLoader/Tests/ApcClassLoaderTest.php +++ /dev/null @@ -1,200 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\ClassLoader\Tests; - -use PHPUnit\Framework\TestCase; -use Symfony\Component\ClassLoader\ApcClassLoader; -use Symfony\Component\ClassLoader\ClassLoader; - -/** - * @group legacy - */ -class ApcClassLoaderTest extends TestCase -{ - protected function setUp() - { - if (!(ini_get('apc.enabled') && ini_get('apc.enable_cli'))) { - $this->markTestSkipped('The apc extension is not enabled.'); - } else { - apcu_clear_cache(); - } - } - - protected function tearDown() - { - if (ini_get('apc.enabled') && ini_get('apc.enable_cli')) { - apcu_clear_cache(); - } - } - - public function testConstructor() - { - $loader = new ClassLoader(); - $loader->addPrefix('Apc\Namespaced', __DIR__.DIRECTORY_SEPARATOR.'Fixtures'); - - $loader = new ApcClassLoader('test.prefix.', $loader); - - $this->assertEquals($loader->findFile('\Apc\Namespaced\FooBar'), apcu_fetch('test.prefix.\Apc\Namespaced\FooBar'), '__construct() takes a prefix as its first argument'); - } - - /** - * @dataProvider getLoadClassTests - */ - public function testLoadClass($className, $testClassName, $message) - { - $loader = new ClassLoader(); - $loader->addPrefix('Apc\Namespaced', __DIR__.DIRECTORY_SEPARATOR.'Fixtures'); - $loader->addPrefix('Apc_Pearlike_', __DIR__.DIRECTORY_SEPARATOR.'Fixtures'); - - $loader = new ApcClassLoader('test.prefix.', $loader); - $loader->loadClass($testClassName); - $this->assertTrue(class_exists($className), $message); - } - - public function getLoadClassTests() - { - return array( - array('\\Apc\\Namespaced\\Foo', 'Apc\\Namespaced\\Foo', '->loadClass() loads Apc\Namespaced\Foo class'), - array('Apc_Pearlike_Foo', 'Apc_Pearlike_Foo', '->loadClass() loads Apc_Pearlike_Foo class'), - ); - } - - /** - * @dataProvider getLoadClassFromFallbackTests - */ - public function testLoadClassFromFallback($className, $testClassName, $message) - { - $loader = new ClassLoader(); - $loader->addPrefix('Apc\Namespaced', __DIR__.DIRECTORY_SEPARATOR.'Fixtures'); - $loader->addPrefix('Apc_Pearlike_', __DIR__.DIRECTORY_SEPARATOR.'Fixtures'); - $loader->addPrefix('', array(__DIR__.DIRECTORY_SEPARATOR.'Fixtures/Apc/fallback')); - - $loader = new ApcClassLoader('test.prefix.fallback', $loader); - $loader->loadClass($testClassName); - - $this->assertTrue(class_exists($className), $message); - } - - public function getLoadClassFromFallbackTests() - { - return array( - array('\\Apc\\Namespaced\\Baz', 'Apc\\Namespaced\\Baz', '->loadClass() loads Apc\Namespaced\Baz class'), - array('Apc_Pearlike_Baz', 'Apc_Pearlike_Baz', '->loadClass() loads Apc_Pearlike_Baz class'), - array('\\Apc\\Namespaced\\FooBar', 'Apc\\Namespaced\\FooBar', '->loadClass() loads Apc\Namespaced\Baz class from fallback dir'), - array('Apc_Pearlike_FooBar', 'Apc_Pearlike_FooBar', '->loadClass() loads Apc_Pearlike_Baz class from fallback dir'), - ); - } - - /** - * @dataProvider getLoadClassNamespaceCollisionTests - */ - public function testLoadClassNamespaceCollision($namespaces, $className, $message) - { - $loader = new ClassLoader(); - $loader->addPrefixes($namespaces); - - $loader = new ApcClassLoader('test.prefix.collision.', $loader); - $loader->loadClass($className); - - $this->assertTrue(class_exists($className), $message); - } - - public function getLoadClassNamespaceCollisionTests() - { - return array( - array( - array( - 'Apc\\NamespaceCollision\\A' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/Apc/alpha', - 'Apc\\NamespaceCollision\\A\\B' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/Apc/beta', - ), - 'Apc\NamespaceCollision\A\Foo', - '->loadClass() loads NamespaceCollision\A\Foo from alpha.', - ), - array( - array( - 'Apc\\NamespaceCollision\\A\\B' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/Apc/beta', - 'Apc\\NamespaceCollision\\A' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/Apc/alpha', - ), - 'Apc\NamespaceCollision\A\Bar', - '->loadClass() loads NamespaceCollision\A\Bar from alpha.', - ), - array( - array( - 'Apc\\NamespaceCollision\\A' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/Apc/alpha', - 'Apc\\NamespaceCollision\\A\\B' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/Apc/beta', - ), - 'Apc\NamespaceCollision\A\B\Foo', - '->loadClass() loads NamespaceCollision\A\B\Foo from beta.', - ), - array( - array( - 'Apc\\NamespaceCollision\\A\\B' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/Apc/beta', - 'Apc\\NamespaceCollision\\A' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/Apc/alpha', - ), - 'Apc\NamespaceCollision\A\B\Bar', - '->loadClass() loads NamespaceCollision\A\B\Bar from beta.', - ), - ); - } - - /** - * @dataProvider getLoadClassPrefixCollisionTests - */ - public function testLoadClassPrefixCollision($prefixes, $className, $message) - { - $loader = new ClassLoader(); - $loader->addPrefixes($prefixes); - - $loader = new ApcClassLoader('test.prefix.collision.', $loader); - $loader->loadClass($className); - - $this->assertTrue(class_exists($className), $message); - } - - public function getLoadClassPrefixCollisionTests() - { - return array( - array( - array( - 'ApcPrefixCollision_A_' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/Apc/alpha/Apc', - 'ApcPrefixCollision_A_B_' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/Apc/beta/Apc', - ), - 'ApcPrefixCollision_A_Foo', - '->loadClass() loads ApcPrefixCollision_A_Foo from alpha.', - ), - array( - array( - 'ApcPrefixCollision_A_B_' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/Apc/beta/Apc', - 'ApcPrefixCollision_A_' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/Apc/alpha/Apc', - ), - 'ApcPrefixCollision_A_Bar', - '->loadClass() loads ApcPrefixCollision_A_Bar from alpha.', - ), - array( - array( - 'ApcPrefixCollision_A_' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/Apc/alpha/Apc', - 'ApcPrefixCollision_A_B_' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/Apc/beta/Apc', - ), - 'ApcPrefixCollision_A_B_Foo', - '->loadClass() loads ApcPrefixCollision_A_B_Foo from beta.', - ), - array( - array( - 'ApcPrefixCollision_A_B_' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/Apc/beta/Apc', - 'ApcPrefixCollision_A_' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/Apc/alpha/Apc', - ), - 'ApcPrefixCollision_A_B_Bar', - '->loadClass() loads ApcPrefixCollision_A_B_Bar from beta.', - ), - ); - } -} diff --git a/src/Symfony/Component/ClassLoader/Tests/ClassLoaderTest.php b/src/Symfony/Component/ClassLoader/Tests/ClassLoaderTest.php deleted file mode 100644 index 0e3ec646a4308..0000000000000 --- a/src/Symfony/Component/ClassLoader/Tests/ClassLoaderTest.php +++ /dev/null @@ -1,238 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\ClassLoader\Tests; - -use PHPUnit\Framework\TestCase; -use Symfony\Component\ClassLoader\ClassLoader; - -/** - * @group legacy - */ -class ClassLoaderTest extends TestCase -{ - public function testGetPrefixes() - { - $loader = new ClassLoader(); - $loader->addPrefix('Foo', __DIR__.DIRECTORY_SEPARATOR.'Fixtures'); - $loader->addPrefix('Bar', __DIR__.DIRECTORY_SEPARATOR.'Fixtures'); - $loader->addPrefix('Bas', __DIR__.DIRECTORY_SEPARATOR.'Fixtures'); - $prefixes = $loader->getPrefixes(); - $this->assertArrayHasKey('Foo', $prefixes); - $this->assertArrayNotHasKey('Foo1', $prefixes); - $this->assertArrayHasKey('Bar', $prefixes); - $this->assertArrayHasKey('Bas', $prefixes); - } - - public function testGetFallbackDirs() - { - $loader = new ClassLoader(); - $loader->addPrefix(null, __DIR__.DIRECTORY_SEPARATOR.'Fixtures'); - $loader->addPrefix(null, __DIR__.DIRECTORY_SEPARATOR.'Fixtures'); - $fallback_dirs = $loader->getFallbackDirs(); - $this->assertCount(2, $fallback_dirs); - } - - /** - * @dataProvider getLoadClassTests - */ - public function testLoadClass($className, $testClassName, $message) - { - $loader = new ClassLoader(); - $loader->addPrefix('Namespaced2\\', __DIR__.DIRECTORY_SEPARATOR.'Fixtures'); - $loader->addPrefix('Pearlike2_', __DIR__.DIRECTORY_SEPARATOR.'Fixtures'); - $loader->loadClass($testClassName); - $this->assertTrue(class_exists($className), $message); - } - - public function getLoadClassTests() - { - return array( - array('\\Namespaced2\\Foo', 'Namespaced2\\Foo', '->loadClass() loads Namespaced2\Foo class'), - array('\\Pearlike2_Foo', 'Pearlike2_Foo', '->loadClass() loads Pearlike2_Foo class'), - ); - } - - /** - * @dataProvider getLoadNonexistentClassTests - */ - public function testLoadNonexistentClass($className, $testClassName, $message) - { - $loader = new ClassLoader(); - $loader->addPrefix('Namespaced2\\', __DIR__.DIRECTORY_SEPARATOR.'Fixtures'); - $loader->addPrefix('Pearlike2_', __DIR__.DIRECTORY_SEPARATOR.'Fixtures'); - $loader->loadClass($testClassName); - $this->assertFalse(class_exists($className), $message); - } - - public function getLoadNonexistentClassTests() - { - return array( - array('\\Pearlike3_Bar', '\\Pearlike3_Bar', '->loadClass() loads non existing Pearlike3_Bar class with a leading slash'), - ); - } - - public function testAddPrefixSingle() - { - $loader = new ClassLoader(); - $loader->addPrefix('Foo', __DIR__.DIRECTORY_SEPARATOR.'Fixtures'); - $loader->addPrefix('Foo', __DIR__.DIRECTORY_SEPARATOR.'Fixtures'); - $prefixes = $loader->getPrefixes(); - $this->assertArrayHasKey('Foo', $prefixes); - $this->assertCount(1, $prefixes['Foo']); - } - - public function testAddPrefixesSingle() - { - $loader = new ClassLoader(); - $loader->addPrefixes(array('Foo' => array('foo', 'foo'))); - $loader->addPrefixes(array('Foo' => array('foo'))); - $prefixes = $loader->getPrefixes(); - $this->assertArrayHasKey('Foo', $prefixes); - $this->assertCount(1, $prefixes['Foo'], print_r($prefixes, true)); - } - - public function testAddPrefixMulti() - { - $loader = new ClassLoader(); - $loader->addPrefix('Foo', 'foo'); - $loader->addPrefix('Foo', 'bar'); - $prefixes = $loader->getPrefixes(); - $this->assertArrayHasKey('Foo', $prefixes); - $this->assertCount(2, $prefixes['Foo']); - $this->assertContains('foo', $prefixes['Foo']); - $this->assertContains('bar', $prefixes['Foo']); - } - - public function testUseIncludePath() - { - $loader = new ClassLoader(); - $this->assertFalse($loader->getUseIncludePath()); - - $this->assertNull($loader->findFile('Foo')); - - $includePath = get_include_path(); - - $loader->setUseIncludePath(true); - $this->assertTrue($loader->getUseIncludePath()); - - set_include_path(__DIR__.'/Fixtures/includepath'.PATH_SEPARATOR.$includePath); - - $this->assertEquals(__DIR__.DIRECTORY_SEPARATOR.'Fixtures'.DIRECTORY_SEPARATOR.'includepath'.DIRECTORY_SEPARATOR.'Foo.php', $loader->findFile('Foo')); - - set_include_path($includePath); - } - - /** - * @dataProvider getLoadClassFromFallbackTests - */ - public function testLoadClassFromFallback($className, $testClassName, $message) - { - $loader = new ClassLoader(); - $loader->addPrefix('Namespaced2\\', __DIR__.DIRECTORY_SEPARATOR.'Fixtures'); - $loader->addPrefix('Pearlike2_', __DIR__.DIRECTORY_SEPARATOR.'Fixtures'); - $loader->addPrefix('', array(__DIR__.DIRECTORY_SEPARATOR.'Fixtures/fallback')); - $loader->loadClass($testClassName); - $this->assertTrue(class_exists($className), $message); - } - - public function getLoadClassFromFallbackTests() - { - return array( - array('\\Namespaced2\\Baz', 'Namespaced2\\Baz', '->loadClass() loads Namespaced2\Baz class'), - array('\\Pearlike2_Baz', 'Pearlike2_Baz', '->loadClass() loads Pearlike2_Baz class'), - array('\\Namespaced2\\FooBar', 'Namespaced2\\FooBar', '->loadClass() loads Namespaced2\Baz class from fallback dir'), - array('\\Pearlike2_FooBar', 'Pearlike2_FooBar', '->loadClass() loads Pearlike2_Baz class from fallback dir'), - ); - } - - /** - * @dataProvider getLoadClassNamespaceCollisionTests - */ - public function testLoadClassNamespaceCollision($namespaces, $className, $message) - { - $loader = new ClassLoader(); - $loader->addPrefixes($namespaces); - - $loader->loadClass($className); - $this->assertTrue(class_exists($className), $message); - } - - public function getLoadClassNamespaceCollisionTests() - { - return array( - array( - array( - 'NamespaceCollision\\C' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/alpha', - 'NamespaceCollision\\C\\B' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/beta', - ), - 'NamespaceCollision\C\Foo', - '->loadClass() loads NamespaceCollision\C\Foo from alpha.', - ), - array( - array( - 'NamespaceCollision\\C\\B' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/beta', - 'NamespaceCollision\\C' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/alpha', - ), - 'NamespaceCollision\C\Bar', - '->loadClass() loads NamespaceCollision\C\Bar from alpha.', - ), - array( - array( - 'NamespaceCollision\\C' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/alpha', - 'NamespaceCollision\\C\\B' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/beta', - ), - 'NamespaceCollision\C\B\Foo', - '->loadClass() loads NamespaceCollision\C\B\Foo from beta.', - ), - array( - array( - 'NamespaceCollision\\C\\B' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/beta', - 'NamespaceCollision\\C' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/alpha', - ), - 'NamespaceCollision\C\B\Bar', - '->loadClass() loads NamespaceCollision\C\B\Bar from beta.', - ), - array( - array( - 'PrefixCollision_C_' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/alpha', - 'PrefixCollision_C_B_' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/beta', - ), - 'PrefixCollision_C_Foo', - '->loadClass() loads PrefixCollision_C_Foo from alpha.', - ), - array( - array( - 'PrefixCollision_C_B_' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/beta', - 'PrefixCollision_C_' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/alpha', - ), - 'PrefixCollision_C_Bar', - '->loadClass() loads PrefixCollision_C_Bar from alpha.', - ), - array( - array( - 'PrefixCollision_C_' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/alpha', - 'PrefixCollision_C_B_' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/beta', - ), - 'PrefixCollision_C_B_Foo', - '->loadClass() loads PrefixCollision_C_B_Foo from beta.', - ), - array( - array( - 'PrefixCollision_C_B_' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/beta', - 'PrefixCollision_C_' => __DIR__.DIRECTORY_SEPARATOR.'Fixtures/alpha', - ), - 'PrefixCollision_C_B_Bar', - '->loadClass() loads PrefixCollision_C_B_Bar from beta.', - ), - ); - } -} diff --git a/src/Symfony/Component/ClassLoader/Tests/ClassMapGeneratorTest.php b/src/Symfony/Component/ClassLoader/Tests/ClassMapGeneratorTest.php deleted file mode 100644 index 69b1e61594e35..0000000000000 --- a/src/Symfony/Component/ClassLoader/Tests/ClassMapGeneratorTest.php +++ /dev/null @@ -1,151 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\ClassLoader\Tests; - -use PHPUnit\Framework\TestCase; -use Symfony\Component\ClassLoader\ClassMapGenerator; - -/** - * @group legacy - */ -class ClassMapGeneratorTest extends TestCase -{ - /** - * @var string|null - */ - private $workspace = null; - - public function prepare_workspace() - { - $this->workspace = sys_get_temp_dir().'/'.microtime(true).'.'.mt_rand(); - mkdir($this->workspace, 0777, true); - $this->workspace = realpath($this->workspace); - } - - /** - * @param string $file - */ - private function clean($file) - { - if (is_dir($file) && !is_link($file)) { - $dir = new \FilesystemIterator($file); - foreach ($dir as $childFile) { - $this->clean($childFile); - } - - rmdir($file); - } else { - unlink($file); - } - } - - /** - * @dataProvider getTestCreateMapTests - */ - public function testDump($directory) - { - $this->prepare_workspace(); - - $file = $this->workspace.'/file'; - - $generator = new ClassMapGenerator(); - $generator->dump($directory, $file); - $this->assertFileExists($file); - - $this->clean($this->workspace); - } - - /** - * @dataProvider getTestCreateMapTests - */ - public function testCreateMap($directory, $expected) - { - $this->assertEqualsNormalized($expected, ClassMapGenerator::createMap($directory)); - } - - public function getTestCreateMapTests() - { - $data = array( - array(__DIR__.'/Fixtures/Namespaced', array( - 'Namespaced\\Bar' => realpath(__DIR__).'/Fixtures/Namespaced/Bar.php', - 'Namespaced\\Foo' => realpath(__DIR__).'/Fixtures/Namespaced/Foo.php', - 'Namespaced\\Baz' => realpath(__DIR__).'/Fixtures/Namespaced/Baz.php', - 'Namespaced\\WithComments' => realpath(__DIR__).'/Fixtures/Namespaced/WithComments.php', - 'Namespaced\\WithStrictTypes' => realpath(__DIR__).'/Fixtures/Namespaced/WithStrictTypes.php', - 'Namespaced\\WithHaltCompiler' => realpath(__DIR__).'/Fixtures/Namespaced/WithHaltCompiler.php', - 'Namespaced\\WithDirMagic' => realpath(__DIR__).'/Fixtures/Namespaced/WithDirMagic.php', - 'Namespaced\\WithFileMagic' => realpath(__DIR__).'/Fixtures/Namespaced/WithFileMagic.php', - )), - array(__DIR__.'/Fixtures/beta/NamespaceCollision', array( - 'NamespaceCollision\\A\\B\\Bar' => realpath(__DIR__).'/Fixtures/beta/NamespaceCollision/A/B/Bar.php', - 'NamespaceCollision\\A\\B\\Foo' => realpath(__DIR__).'/Fixtures/beta/NamespaceCollision/A/B/Foo.php', - 'NamespaceCollision\\C\\B\\Bar' => realpath(__DIR__).'/Fixtures/beta/NamespaceCollision/C/B/Bar.php', - 'NamespaceCollision\\C\\B\\Foo' => realpath(__DIR__).'/Fixtures/beta/NamespaceCollision/C/B/Foo.php', - )), - array(__DIR__.'/Fixtures/Pearlike', array( - 'Pearlike_Foo' => realpath(__DIR__).'/Fixtures/Pearlike/Foo.php', - 'Pearlike_Bar' => realpath(__DIR__).'/Fixtures/Pearlike/Bar.php', - 'Pearlike_Baz' => realpath(__DIR__).'/Fixtures/Pearlike/Baz.php', - 'Pearlike_WithComments' => realpath(__DIR__).'/Fixtures/Pearlike/WithComments.php', - )), - array(__DIR__.'/Fixtures/classmap', array( - 'Foo\\Bar\\A' => realpath(__DIR__).'/Fixtures/classmap/sameNsMultipleClasses.php', - 'Foo\\Bar\\B' => realpath(__DIR__).'/Fixtures/classmap/sameNsMultipleClasses.php', - 'A' => realpath(__DIR__).'/Fixtures/classmap/multipleNs.php', - 'Alpha\\A' => realpath(__DIR__).'/Fixtures/classmap/multipleNs.php', - 'Alpha\\B' => realpath(__DIR__).'/Fixtures/classmap/multipleNs.php', - 'Beta\\A' => realpath(__DIR__).'/Fixtures/classmap/multipleNs.php', - 'Beta\\B' => realpath(__DIR__).'/Fixtures/classmap/multipleNs.php', - 'ClassMap\\SomeInterface' => realpath(__DIR__).'/Fixtures/classmap/SomeInterface.php', - 'ClassMap\\SomeParent' => realpath(__DIR__).'/Fixtures/classmap/SomeParent.php', - 'ClassMap\\SomeClass' => realpath(__DIR__).'/Fixtures/classmap/SomeClass.php', - )), - array(__DIR__.'/Fixtures/php5.4', array( - 'TFoo' => __DIR__.'/Fixtures/php5.4/traits.php', - 'CFoo' => __DIR__.'/Fixtures/php5.4/traits.php', - 'Foo\\TBar' => __DIR__.'/Fixtures/php5.4/traits.php', - 'Foo\\IBar' => __DIR__.'/Fixtures/php5.4/traits.php', - 'Foo\\TFooBar' => __DIR__.'/Fixtures/php5.4/traits.php', - 'Foo\\CBar' => __DIR__.'/Fixtures/php5.4/traits.php', - )), - array(__DIR__.'/Fixtures/php5.5', array( - 'ClassCons\\Foo' => __DIR__.'/Fixtures/php5.5/class_cons.php', - )), - ); - - return $data; - } - - public function testCreateMapFinderSupport() - { - $finder = new \Symfony\Component\Finder\Finder(); - $finder->files()->in(__DIR__.'/Fixtures/beta/NamespaceCollision'); - - $this->assertEqualsNormalized(array( - 'NamespaceCollision\\A\\B\\Bar' => realpath(__DIR__).'/Fixtures/beta/NamespaceCollision/A/B/Bar.php', - 'NamespaceCollision\\A\\B\\Foo' => realpath(__DIR__).'/Fixtures/beta/NamespaceCollision/A/B/Foo.php', - 'NamespaceCollision\\C\\B\\Bar' => realpath(__DIR__).'/Fixtures/beta/NamespaceCollision/C/B/Bar.php', - 'NamespaceCollision\\C\\B\\Foo' => realpath(__DIR__).'/Fixtures/beta/NamespaceCollision/C/B/Foo.php', - ), ClassMapGenerator::createMap($finder)); - } - - protected function assertEqualsNormalized($expected, $actual, $message = null) - { - foreach ($expected as $ns => $path) { - $expected[$ns] = str_replace('\\', '/', $path); - } - foreach ($actual as $ns => $path) { - $actual[$ns] = str_replace('\\', '/', $path); - } - $this->assertEquals($expected, $actual, $message); - } -} diff --git a/src/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/Namespaced/Bar.php b/src/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/Namespaced/Bar.php deleted file mode 100644 index 4259f1451e2c9..0000000000000 --- a/src/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/Namespaced/Bar.php +++ /dev/null @@ -1,17 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Apc\Namespaced; - -class Bar -{ - public static $loaded = true; -} diff --git a/src/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/Namespaced/Baz.php b/src/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/Namespaced/Baz.php deleted file mode 100644 index 3ddb595e25164..0000000000000 --- a/src/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/Namespaced/Baz.php +++ /dev/null @@ -1,17 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Apc\Namespaced; - -class Baz -{ - public static $loaded = true; -} diff --git a/src/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/Namespaced/Foo.php b/src/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/Namespaced/Foo.php deleted file mode 100644 index cf0a4b741fd9f..0000000000000 --- a/src/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/Namespaced/Foo.php +++ /dev/null @@ -1,17 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Apc\Namespaced; - -class Foo -{ - public static $loaded = true; -} diff --git a/src/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/Namespaced/FooBar.php b/src/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/Namespaced/FooBar.php deleted file mode 100644 index bbbc81515a80f..0000000000000 --- a/src/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/Namespaced/FooBar.php +++ /dev/null @@ -1,17 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Apc\Namespaced; - -class FooBar -{ - public static $loaded = true; -} diff --git a/src/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/Pearlike/Bar.php b/src/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/Pearlike/Bar.php deleted file mode 100644 index e774cb9bfbbae..0000000000000 --- a/src/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/Pearlike/Bar.php +++ /dev/null @@ -1,6 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Apc\NamespaceCollision\A; - -class Bar -{ - public static $loaded = true; -} diff --git a/src/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/alpha/Apc/NamespaceCollision/A/Foo.php b/src/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/alpha/Apc/NamespaceCollision/A/Foo.php deleted file mode 100644 index 184a1b1daf159..0000000000000 --- a/src/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/alpha/Apc/NamespaceCollision/A/Foo.php +++ /dev/null @@ -1,17 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Apc\NamespaceCollision\A; - -class Foo -{ - public static $loaded = true; -} diff --git a/src/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/beta/Apc/ApcPrefixCollision/A/B/Bar.php b/src/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/beta/Apc/ApcPrefixCollision/A/B/Bar.php deleted file mode 100644 index 3892f70683deb..0000000000000 --- a/src/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/beta/Apc/ApcPrefixCollision/A/B/Bar.php +++ /dev/null @@ -1,6 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Apc\NamespaceCollision\A\B; - -class Bar -{ - public static $loaded = true; -} diff --git a/src/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/beta/Apc/NamespaceCollision/A/B/Foo.php b/src/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/beta/Apc/NamespaceCollision/A/B/Foo.php deleted file mode 100644 index 450eeb50b9e34..0000000000000 --- a/src/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/beta/Apc/NamespaceCollision/A/B/Foo.php +++ /dev/null @@ -1,17 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Apc\NamespaceCollision\A\B; - -class Foo -{ - public static $loaded = true; -} diff --git a/src/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/fallback/Apc/Pearlike/FooBar.php b/src/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/fallback/Apc/Pearlike/FooBar.php deleted file mode 100644 index 96f2f76c6f94d..0000000000000 --- a/src/Symfony/Component/ClassLoader/Tests/Fixtures/Apc/fallback/Apc/Pearlike/FooBar.php +++ /dev/null @@ -1,6 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Apc\Namespaced; - -class FooBar -{ - public static $loaded = true; -} diff --git a/src/Symfony/Component/ClassLoader/Tests/Fixtures/DeclaredClass.php b/src/Symfony/Component/ClassLoader/Tests/Fixtures/DeclaredClass.php deleted file mode 100644 index bf975661e1058..0000000000000 --- a/src/Symfony/Component/ClassLoader/Tests/Fixtures/DeclaredClass.php +++ /dev/null @@ -1,7 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Namespaced; - -class Bar -{ - public static $loaded = true; -} diff --git a/src/Symfony/Component/ClassLoader/Tests/Fixtures/Namespaced/Baz.php b/src/Symfony/Component/ClassLoader/Tests/Fixtures/Namespaced/Baz.php deleted file mode 100644 index 0b0bbd057c44a..0000000000000 --- a/src/Symfony/Component/ClassLoader/Tests/Fixtures/Namespaced/Baz.php +++ /dev/null @@ -1,17 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Namespaced; - -class Baz -{ - public static $loaded = true; -} diff --git a/src/Symfony/Component/ClassLoader/Tests/Fixtures/Namespaced/Foo.php b/src/Symfony/Component/ClassLoader/Tests/Fixtures/Namespaced/Foo.php deleted file mode 100644 index df5e1f4ce2ec3..0000000000000 --- a/src/Symfony/Component/ClassLoader/Tests/Fixtures/Namespaced/Foo.php +++ /dev/null @@ -1,17 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Namespaced; - -class Foo -{ - public static $loaded = true; -} diff --git a/src/Symfony/Component/ClassLoader/Tests/Fixtures/Namespaced/WithComments.php b/src/Symfony/Component/ClassLoader/Tests/Fixtures/Namespaced/WithComments.php deleted file mode 100644 index 361e53de1c4ee..0000000000000 --- a/src/Symfony/Component/ClassLoader/Tests/Fixtures/Namespaced/WithComments.php +++ /dev/null @@ -1,37 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Namespaced; - -class WithComments -{ - /** @Boolean */ - public static $loaded = true; -} - -$string = 'string should not be modified {$string}'; - -$heredoc = (<< - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -class Pearlike_WithComments -{ - /** @Boolean */ - public static $loaded = true; -} diff --git a/src/Symfony/Component/ClassLoader/Tests/Fixtures/Pearlike2/Bar.php b/src/Symfony/Component/ClassLoader/Tests/Fixtures/Pearlike2/Bar.php deleted file mode 100644 index 7f5f7977308b7..0000000000000 --- a/src/Symfony/Component/ClassLoader/Tests/Fixtures/Pearlike2/Bar.php +++ /dev/null @@ -1,6 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace NamespaceCollision\A; - -class Bar -{ - public static $loaded = true; -} diff --git a/src/Symfony/Component/ClassLoader/Tests/Fixtures/alpha/NamespaceCollision/A/Foo.php b/src/Symfony/Component/ClassLoader/Tests/Fixtures/alpha/NamespaceCollision/A/Foo.php deleted file mode 100644 index aee6a080dfb76..0000000000000 --- a/src/Symfony/Component/ClassLoader/Tests/Fixtures/alpha/NamespaceCollision/A/Foo.php +++ /dev/null @@ -1,17 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace NamespaceCollision\A; - -class Foo -{ - public static $loaded = true; -} diff --git a/src/Symfony/Component/ClassLoader/Tests/Fixtures/alpha/NamespaceCollision/C/Bar.php b/src/Symfony/Component/ClassLoader/Tests/Fixtures/alpha/NamespaceCollision/C/Bar.php deleted file mode 100644 index c1b8dd65ddfa3..0000000000000 --- a/src/Symfony/Component/ClassLoader/Tests/Fixtures/alpha/NamespaceCollision/C/Bar.php +++ /dev/null @@ -1,8 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace NamespaceCollision\A\B; - -class Bar -{ - public static $loaded = true; -} diff --git a/src/Symfony/Component/ClassLoader/Tests/Fixtures/beta/NamespaceCollision/A/B/Foo.php b/src/Symfony/Component/ClassLoader/Tests/Fixtures/beta/NamespaceCollision/A/B/Foo.php deleted file mode 100644 index f5f2d727ef5e6..0000000000000 --- a/src/Symfony/Component/ClassLoader/Tests/Fixtures/beta/NamespaceCollision/A/B/Foo.php +++ /dev/null @@ -1,17 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace NamespaceCollision\A\B; - -class Foo -{ - public static $loaded = true; -} diff --git a/src/Symfony/Component/ClassLoader/Tests/Fixtures/beta/NamespaceCollision/C/B/Bar.php b/src/Symfony/Component/ClassLoader/Tests/Fixtures/beta/NamespaceCollision/C/B/Bar.php deleted file mode 100644 index 4bb03dc7fd65a..0000000000000 --- a/src/Symfony/Component/ClassLoader/Tests/Fixtures/beta/NamespaceCollision/C/B/Bar.php +++ /dev/null @@ -1,8 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace ClassMap; - -class SomeClass extends SomeParent implements SomeInterface -{ -} diff --git a/src/Symfony/Component/ClassLoader/Tests/Fixtures/classmap/SomeInterface.php b/src/Symfony/Component/ClassLoader/Tests/Fixtures/classmap/SomeInterface.php deleted file mode 100644 index 1fe5e09aa1f50..0000000000000 --- a/src/Symfony/Component/ClassLoader/Tests/Fixtures/classmap/SomeInterface.php +++ /dev/null @@ -1,16 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace ClassMap; - -interface SomeInterface -{ -} diff --git a/src/Symfony/Component/ClassLoader/Tests/Fixtures/classmap/SomeParent.php b/src/Symfony/Component/ClassLoader/Tests/Fixtures/classmap/SomeParent.php deleted file mode 100644 index ce2f9fc6c478c..0000000000000 --- a/src/Symfony/Component/ClassLoader/Tests/Fixtures/classmap/SomeParent.php +++ /dev/null @@ -1,16 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace ClassMap; - -abstract class SomeParent -{ -} diff --git a/src/Symfony/Component/ClassLoader/Tests/Fixtures/classmap/multipleNs.php b/src/Symfony/Component/ClassLoader/Tests/Fixtures/classmap/multipleNs.php deleted file mode 100644 index c7cec646f5f25..0000000000000 --- a/src/Symfony/Component/ClassLoader/Tests/Fixtures/classmap/multipleNs.php +++ /dev/null @@ -1,25 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Foo\Bar; - -class A -{ -} -class B -{ -} diff --git a/src/Symfony/Component/ClassLoader/Tests/Fixtures/fallback/Namespaced/FooBar.php b/src/Symfony/Component/ClassLoader/Tests/Fixtures/fallback/Namespaced/FooBar.php deleted file mode 100644 index 0fd29efbb236b..0000000000000 --- a/src/Symfony/Component/ClassLoader/Tests/Fixtures/fallback/Namespaced/FooBar.php +++ /dev/null @@ -1,17 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Namespaced; - -class FooBar -{ - public static $loaded = true; -} diff --git a/src/Symfony/Component/ClassLoader/Tests/Fixtures/fallback/Namespaced2/FooBar.php b/src/Symfony/Component/ClassLoader/Tests/Fixtures/fallback/Namespaced2/FooBar.php deleted file mode 100644 index 1036d43590065..0000000000000 --- a/src/Symfony/Component/ClassLoader/Tests/Fixtures/fallback/Namespaced2/FooBar.php +++ /dev/null @@ -1,8 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\ClassLoader\Tests; - -use PHPUnit\Framework\TestCase; -use Symfony\Component\ClassLoader\Psr4ClassLoader; - -/** - * @group legacy - */ -class Psr4ClassLoaderTest extends TestCase -{ - /** - * @param string $className - * @dataProvider getLoadClassTests - */ - public function testLoadClass($className) - { - $loader = new Psr4ClassLoader(); - $loader->addPrefix( - 'Acme\\DemoLib', - __DIR__.DIRECTORY_SEPARATOR.'Fixtures'.DIRECTORY_SEPARATOR.'psr-4' - ); - $loader->loadClass($className); - $this->assertTrue(class_exists($className), sprintf('loadClass() should load %s', $className)); - } - - /** - * @return array - */ - public function getLoadClassTests() - { - return array( - array('Acme\\DemoLib\\Foo'), - array('Acme\\DemoLib\\Class_With_Underscores'), - array('Acme\\DemoLib\\Lets\\Go\\Deeper\\Foo'), - array('Acme\\DemoLib\\Lets\\Go\\Deeper\\Class_With_Underscores'), - ); - } - - /** - * @param string $className - * @dataProvider getLoadNonexistentClassTests - */ - public function testLoadNonexistentClass($className) - { - $loader = new Psr4ClassLoader(); - $loader->addPrefix( - 'Acme\\DemoLib', - __DIR__.DIRECTORY_SEPARATOR.'Fixtures'.DIRECTORY_SEPARATOR.'psr-4' - ); - $loader->loadClass($className); - $this->assertFalse(class_exists($className), sprintf('loadClass() should not load %s', $className)); - } - - /** - * @return array - */ - public function getLoadNonexistentClassTests() - { - return array( - array('Acme\\DemoLib\\I_Do_Not_Exist'), - array('UnknownVendor\\SomeLib\\I_Do_Not_Exist'), - ); - } -} diff --git a/src/Symfony/Component/ClassLoader/WinCacheClassLoader.php b/src/Symfony/Component/ClassLoader/WinCacheClassLoader.php deleted file mode 100644 index 76b13d39a4d84..0000000000000 --- a/src/Symfony/Component/ClassLoader/WinCacheClassLoader.php +++ /dev/null @@ -1,144 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\ClassLoader; - -@trigger_error('The '.__NAMESPACE__.'\WinCacheClassLoader class is deprecated since version 3.3 and will be removed in 4.0. Use `composer install --apcu-autoloader` instead.', E_USER_DEPRECATED); - -/** - * WinCacheClassLoader implements a wrapping autoloader cached in WinCache. - * - * It expects an object implementing a findFile method to find the file. This - * allow using it as a wrapper around the other loaders of the component (the - * ClassLoader for instance) but also around any other autoloaders following - * this convention (the Composer one for instance). - * - * // with a Symfony autoloader - * $loader = new ClassLoader(); - * $loader->addPrefix('Symfony\Component', __DIR__.'/component'); - * $loader->addPrefix('Symfony', __DIR__.'/framework'); - * - * // or with a Composer autoloader - * use Composer\Autoload\ClassLoader; - * - * $loader = new ClassLoader(); - * $loader->add('Symfony\Component', __DIR__.'/component'); - * $loader->add('Symfony', __DIR__.'/framework'); - * - * $cachedLoader = new WinCacheClassLoader('my_prefix', $loader); - * - * // activate the cached autoloader - * $cachedLoader->register(); - * - * // eventually deactivate the non-cached loader if it was registered previously - * // to be sure to use the cached one. - * $loader->unregister(); - * - * @author Fabien Potencier - * @author Kris Wallsmith - * @author Artem Ryzhkov - * - * @deprecated since version 3.3, to be removed in 4.0. Use `composer install --apcu-autoloader` instead. - */ -class WinCacheClassLoader -{ - private $prefix; - - /** - * A class loader object that implements the findFile() method. - * - * @var object - */ - protected $decorated; - - /** - * Constructor. - * - * @param string $prefix The WinCache namespace prefix to use - * @param object $decorated A class loader object that implements the findFile() method - * - * @throws \RuntimeException - * @throws \InvalidArgumentException - */ - public function __construct($prefix, $decorated) - { - if (!extension_loaded('wincache')) { - throw new \RuntimeException('Unable to use WinCacheClassLoader as WinCache is not enabled.'); - } - - if (!method_exists($decorated, 'findFile')) { - throw new \InvalidArgumentException('The class finder must implement a "findFile" method.'); - } - - $this->prefix = $prefix; - $this->decorated = $decorated; - } - - /** - * Registers this instance as an autoloader. - * - * @param bool $prepend Whether to prepend the autoloader or not - */ - public function register($prepend = false) - { - spl_autoload_register(array($this, 'loadClass'), true, $prepend); - } - - /** - * Unregisters this instance as an autoloader. - */ - public function unregister() - { - spl_autoload_unregister(array($this, 'loadClass')); - } - - /** - * Loads the given class or interface. - * - * @param string $class The name of the class - * - * @return bool|null True, if loaded - */ - public function loadClass($class) - { - if ($file = $this->findFile($class)) { - require $file; - - return true; - } - } - - /** - * Finds a file by class name while caching lookups to WinCache. - * - * @param string $class A class name to resolve to file - * - * @return string|null - */ - public function findFile($class) - { - $file = wincache_ucache_get($this->prefix.$class, $success); - - if (!$success) { - wincache_ucache_set($this->prefix.$class, $file = $this->decorated->findFile($class) ?: null, 0); - } - - return $file; - } - - /** - * Passes through all unknown calls onto the decorated object. - */ - public function __call($method, $args) - { - return call_user_func_array(array($this->decorated, $method), $args); - } -} diff --git a/src/Symfony/Component/ClassLoader/XcacheClassLoader.php b/src/Symfony/Component/ClassLoader/XcacheClassLoader.php deleted file mode 100644 index d3ea09b2c0bdf..0000000000000 --- a/src/Symfony/Component/ClassLoader/XcacheClassLoader.php +++ /dev/null @@ -1,145 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\ClassLoader; - -@trigger_error('The '.__NAMESPACE__.'\XcacheClassLoader class is deprecated since version 3.3 and will be removed in 4.0. Use `composer install --apcu-autoloader` instead.', E_USER_DEPRECATED); - -/** - * XcacheClassLoader implements a wrapping autoloader cached in XCache for PHP 5.3. - * - * It expects an object implementing a findFile method to find the file. This - * allows using it as a wrapper around the other loaders of the component (the - * ClassLoader for instance) but also around any other autoloaders following - * this convention (the Composer one for instance). - * - * // with a Symfony autoloader - * $loader = new ClassLoader(); - * $loader->addPrefix('Symfony\Component', __DIR__.'/component'); - * $loader->addPrefix('Symfony', __DIR__.'/framework'); - * - * // or with a Composer autoloader - * use Composer\Autoload\ClassLoader; - * - * $loader = new ClassLoader(); - * $loader->add('Symfony\Component', __DIR__.'/component'); - * $loader->add('Symfony', __DIR__.'/framework'); - * - * $cachedLoader = new XcacheClassLoader('my_prefix', $loader); - * - * // activate the cached autoloader - * $cachedLoader->register(); - * - * // eventually deactivate the non-cached loader if it was registered previously - * // to be sure to use the cached one. - * $loader->unregister(); - * - * @author Fabien Potencier - * @author Kris Wallsmith - * @author Kim Hemsø Rasmussen - * - * @deprecated since version 3.3, to be removed in 4.0. Use `composer install --apcu-autoloader` instead. - */ -class XcacheClassLoader -{ - private $prefix; - - /** - * A class loader object that implements the findFile() method. - * - * @var object - */ - private $decorated; - - /** - * Constructor. - * - * @param string $prefix The XCache namespace prefix to use - * @param object $decorated A class loader object that implements the findFile() method - * - * @throws \RuntimeException - * @throws \InvalidArgumentException - */ - public function __construct($prefix, $decorated) - { - if (!extension_loaded('xcache')) { - throw new \RuntimeException('Unable to use XcacheClassLoader as XCache is not enabled.'); - } - - if (!method_exists($decorated, 'findFile')) { - throw new \InvalidArgumentException('The class finder must implement a "findFile" method.'); - } - - $this->prefix = $prefix; - $this->decorated = $decorated; - } - - /** - * Registers this instance as an autoloader. - * - * @param bool $prepend Whether to prepend the autoloader or not - */ - public function register($prepend = false) - { - spl_autoload_register(array($this, 'loadClass'), true, $prepend); - } - - /** - * Unregisters this instance as an autoloader. - */ - public function unregister() - { - spl_autoload_unregister(array($this, 'loadClass')); - } - - /** - * Loads the given class or interface. - * - * @param string $class The name of the class - * - * @return bool|null True, if loaded - */ - public function loadClass($class) - { - if ($file = $this->findFile($class)) { - require $file; - - return true; - } - } - - /** - * Finds a file by class name while caching lookups to Xcache. - * - * @param string $class A class name to resolve to file - * - * @return string|null - */ - public function findFile($class) - { - if (xcache_isset($this->prefix.$class)) { - $file = xcache_get($this->prefix.$class); - } else { - $file = $this->decorated->findFile($class) ?: null; - xcache_set($this->prefix.$class, $file); - } - - return $file; - } - - /** - * Passes through all unknown calls onto the decorated object. - */ - public function __call($method, $args) - { - return call_user_func_array(array($this->decorated, $method), $args); - } -} diff --git a/src/Symfony/Component/ClassLoader/composer.json b/src/Symfony/Component/ClassLoader/composer.json deleted file mode 100644 index 65f35cdb7394b..0000000000000 --- a/src/Symfony/Component/ClassLoader/composer.json +++ /dev/null @@ -1,40 +0,0 @@ -{ - "name": "symfony/class-loader", - "type": "library", - "description": "Symfony ClassLoader Component", - "keywords": [], - "homepage": "https://symfony.com", - "license": "MIT", - "authors": [ - { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" - } - ], - "minimum-stability": "dev", - "require": { - "php": "^7.1.3" - }, - "require-dev": { - "symfony/finder": "~3.4|~4.0", - "symfony/polyfill-apcu": "~1.1" - }, - "suggest": { - "symfony/polyfill-apcu": "For using ApcClassLoader on HHVM" - }, - "autoload": { - "psr-4": { "Symfony\\Component\\ClassLoader\\": "" }, - "exclude-from-classmap": [ - "/Tests/" - ] - }, - "extra": { - "branch-alias": { - "dev-master": "4.0-dev" - } - } -} diff --git a/src/Symfony/Component/ClassLoader/phpunit.xml.dist b/src/Symfony/Component/ClassLoader/phpunit.xml.dist deleted file mode 100644 index 5158b22f27c88..0000000000000 --- a/src/Symfony/Component/ClassLoader/phpunit.xml.dist +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - - - - - ./Tests/ - - - - - - ./ - - ./Resources - ./Tests - ./vendor - - - - diff --git a/src/Symfony/Component/Debug/Debug.php b/src/Symfony/Component/Debug/Debug.php index e3665ae5f40c8..09a3e7502226a 100644 --- a/src/Symfony/Component/Debug/Debug.php +++ b/src/Symfony/Component/Debug/Debug.php @@ -25,9 +25,6 @@ class Debug * * This method registers an error handler and an exception handler. * - * If the Symfony ClassLoader component is available, a special - * class loader is also registered. - * * @param int $errorReportingLevel The level of error reporting you want * @param bool $displayErrors Whether to display errors (for development) or just log them (for production) */ From da202feb71a97b519c24891b2576b255db7823dd Mon Sep 17 00:00:00 2001 From: Maxime Steinhausser Date: Thu, 18 May 2017 07:25:38 +0200 Subject: [PATCH 0034/1099] [SecurityBundle][Security][Finder] Remove deprecated code paths - [Finder] Removed `ExceptionInterface` - [SecurityBundle] remove `UserPasswordEncoderCommand` BC layer - [Security] remove `LogoutUrlGenerator::registerListener` BC layer --- .../Bundle/SecurityBundle/CHANGELOG.md | 2 ++ .../Command/UserPasswordEncoderCommand.php | 30 +++---------------- .../UserPasswordEncoderCommandTest.php | 22 -------------- src/Symfony/Component/Finder/CHANGELOG.md | 5 ++++ .../Finder/Exception/ExceptionInterface.php | 25 ---------------- src/Symfony/Component/Security/CHANGELOG.md | 5 ++++ .../Http/Logout/LogoutUrlGenerator.php | 15 +--------- 7 files changed, 17 insertions(+), 87 deletions(-) delete mode 100644 src/Symfony/Component/Finder/Exception/ExceptionInterface.php diff --git a/src/Symfony/Bundle/SecurityBundle/CHANGELOG.md b/src/Symfony/Bundle/SecurityBundle/CHANGELOG.md index c3a6336c44ac8..468b053b7646c 100644 --- a/src/Symfony/Bundle/SecurityBundle/CHANGELOG.md +++ b/src/Symfony/Bundle/SecurityBundle/CHANGELOG.md @@ -6,6 +6,8 @@ CHANGELOG * removed `FirewallContext::getContext()` * made `FirewallMap::$container` and `::$map` private + * made the first `UserPasswordEncoderCommand::_construct()` argument mandatory + * `UserPasswordEncoderCommand` does not extend `ContainerAwareCommand` anymore 3.3.0 ----- diff --git a/src/Symfony/Bundle/SecurityBundle/Command/UserPasswordEncoderCommand.php b/src/Symfony/Bundle/SecurityBundle/Command/UserPasswordEncoderCommand.php index a588bdd331e96..c307dca1f7871 100644 --- a/src/Symfony/Bundle/SecurityBundle/Command/UserPasswordEncoderCommand.php +++ b/src/Symfony/Bundle/SecurityBundle/Command/UserPasswordEncoderCommand.php @@ -11,7 +11,7 @@ namespace Symfony\Bundle\SecurityBundle\Command; -use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand; +use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; @@ -19,43 +19,27 @@ use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Question\Question; use Symfony\Component\Console\Style\SymfonyStyle; -use Symfony\Component\DependencyInjection\ContainerAwareInterface; use Symfony\Component\Security\Core\Encoder\BCryptPasswordEncoder; use Symfony\Component\Security\Core\Encoder\EncoderFactoryInterface; -use Symfony\Component\Security\Core\User\User; /** * Encode a user's password. * * @author Sarah Khalil */ -class UserPasswordEncoderCommand extends ContainerAwareCommand +class UserPasswordEncoderCommand extends Command { private $encoderFactory; private $userClasses; - public function __construct(EncoderFactoryInterface $encoderFactory = null, array $userClasses = array()) + public function __construct(EncoderFactoryInterface $encoderFactory, array $userClasses = array()) { - if (null === $encoderFactory) { - @trigger_error(sprintf('Passing null as the first argument of "%s" is deprecated since version 3.3 and will be removed in 4.0. If the command was registered by convention, make it a service instead.', __METHOD__), E_USER_DEPRECATED); - } - $this->encoderFactory = $encoderFactory; $this->userClasses = $userClasses; parent::__construct(); } - /** - * {@inheritdoc} - */ - protected function getContainer() - { - @trigger_error(sprintf('Method "%s" is deprecated since version 3.3 and "%s" won\'t implement "%s" anymore in 4.0.', __METHOD__, __CLASS__, ContainerAwareInterface::class), E_USER_DEPRECATED); - - return parent::getContainer(); - } - /** * {@inheritdoc} */ @@ -123,8 +107,7 @@ protected function execute(InputInterface $input, OutputInterface $output) $userClass = $this->getUserClass($input, $io); $emptySalt = $input->getOption('empty-salt'); - $encoderFactory = $this->encoderFactory ?: parent::getContainer()->get('security.encoder_factory'); - $encoder = $encoderFactory->getEncoder($userClass); + $encoder = $this->encoderFactory->getEncoder($userClass); $bcryptWithoutEmptySalt = !$emptySalt && $encoder instanceof BCryptPasswordEncoder; if ($bcryptWithoutEmptySalt) { @@ -206,11 +189,6 @@ private function getUserClass(InputInterface $input, SymfonyStyle $io) } if (empty($this->userClasses)) { - if (null === $this->encoderFactory) { - // BC to be removed and simply keep the exception whenever there is no configured user classes in 4.0 - return User::class; - } - throw new \RuntimeException('There are no configured encoders for the "security" extension.'); } diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/UserPasswordEncoderCommandTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/UserPasswordEncoderCommandTest.php index 0710f94b5b094..f7360a1effcd2 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/UserPasswordEncoderCommandTest.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/UserPasswordEncoderCommandTest.php @@ -193,28 +193,6 @@ public function testThrowsExceptionOnNoConfiguredEncoders() ), array('interactive' => false)); } - /** - * @group legacy - * @expectedDeprecation Passing null as the first argument of "Symfony\Bundle\SecurityBundle\Command\UserPasswordEncoderCommand::__construct" is deprecated since version 3.3 and will be removed in 4.0. If the command was registered by convention, make it a service instead. - */ - public function testLegacy() - { - $application = new ConsoleApplication(); - $application->add(new UserPasswordEncoderCommand()); - - $passwordEncoderCommand = $application->find('security:encode-password'); - self::bootKernel(array('test_case' => 'PasswordEncode')); - $passwordEncoderCommand->setContainer(self::$kernel->getContainer()); - - $tester = new CommandTester($passwordEncoderCommand); - $tester->execute(array( - 'command' => 'security:encode-password', - 'password' => 'password', - ), array('interactive' => false)); - - $this->assertContains('Encoder used Symfony\Component\Security\Core\Encoder\PlaintextPasswordEncoder', $tester->getDisplay()); - } - protected function setUp() { putenv('COLUMNS='.(119 + strlen(PHP_EOL))); diff --git a/src/Symfony/Component/Finder/CHANGELOG.md b/src/Symfony/Component/Finder/CHANGELOG.md index cf19de6930ed5..7c81389390374 100644 --- a/src/Symfony/Component/Finder/CHANGELOG.md +++ b/src/Symfony/Component/Finder/CHANGELOG.md @@ -1,6 +1,11 @@ CHANGELOG ========= +4.0.0 +----- + + * removed `ExceptionInterface` + 3.3.0 ----- diff --git a/src/Symfony/Component/Finder/Exception/ExceptionInterface.php b/src/Symfony/Component/Finder/Exception/ExceptionInterface.php deleted file mode 100644 index 161e9686d2b70..0000000000000 --- a/src/Symfony/Component/Finder/Exception/ExceptionInterface.php +++ /dev/null @@ -1,25 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Finder\Exception; - -/** - * @author Jean-François Simon - * - * @deprecated since 3.3, to be removed in 4.0. - */ -interface ExceptionInterface -{ - /** - * @return \Symfony\Component\Finder\Adapter\AdapterInterface - */ - public function getAdapter(); -} diff --git a/src/Symfony/Component/Security/CHANGELOG.md b/src/Symfony/Component/Security/CHANGELOG.md index 69cdd285282fa..a8ec0d017e026 100644 --- a/src/Symfony/Component/Security/CHANGELOG.md +++ b/src/Symfony/Component/Security/CHANGELOG.md @@ -1,6 +1,11 @@ CHANGELOG ========= +4.0.0 +----- + + * added a sixth `string $context` argument to`LogoutUrlGenerator::registerListener()` + 3.3.0 ----- diff --git a/src/Symfony/Component/Security/Http/Logout/LogoutUrlGenerator.php b/src/Symfony/Component/Security/Http/Logout/LogoutUrlGenerator.php index 3f2def8d735cc..9bda9816ba11c 100644 --- a/src/Symfony/Component/Security/Http/Logout/LogoutUrlGenerator.php +++ b/src/Symfony/Component/Security/Http/Logout/LogoutUrlGenerator.php @@ -48,21 +48,8 @@ public function __construct(RequestStack $requestStack = null, UrlGeneratorInter * @param CsrfTokenManagerInterface|null $csrfTokenManager A CsrfTokenManagerInterface instance * @param string|null $context The listener context */ - public function registerListener($key, $logoutPath, $csrfTokenId, $csrfParameter, CsrfTokenManagerInterface $csrfTokenManager = null/*, string $context = null*/) + public function registerListener($key, $logoutPath, $csrfTokenId, $csrfParameter, CsrfTokenManagerInterface $csrfTokenManager = null, string $context = null) { - if (func_num_args() >= 6) { - $context = func_get_arg(5); - } else { - if (__CLASS__ !== get_class($this)) { - $r = new \ReflectionMethod($this, __FUNCTION__); - if (__CLASS__ !== $r->getDeclaringClass()->getName()) { - @trigger_error(sprintf('Method %s() will have a sixth `string $context = null` argument in version 4.0. Not defining it is deprecated since 3.3.', __METHOD__), E_USER_DEPRECATED); - } - } - - $context = null; - } - $this->listeners[$key] = array($logoutPath, $csrfTokenId, $csrfParameter, $csrfTokenManager, $context); } From bbd656b4581fe40147ab1391194c2d7b3b45201c Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Sat, 20 May 2017 08:46:02 +0200 Subject: [PATCH 0035/1099] [Validator] remove deprecated features --- src/Symfony/Component/Validator/CHANGELOG.md | 8 +++ .../Validator/Constraints/Choice.php | 2 +- .../Validator/Constraints/ChoiceValidator.php | 6 +- .../Constraints/DateTimeValidator.php | 5 -- .../AbstractConstraintValidatorTest.php | 21 ------- .../Tests/Constraints/ChoiceValidatorTest.php | 58 +++---------------- 6 files changed, 19 insertions(+), 81 deletions(-) delete mode 100644 src/Symfony/Component/Validator/Tests/Constraints/AbstractConstraintValidatorTest.php diff --git a/src/Symfony/Component/Validator/CHANGELOG.md b/src/Symfony/Component/Validator/CHANGELOG.md index 7099496cfa1d2..5b88f627646ba 100644 --- a/src/Symfony/Component/Validator/CHANGELOG.md +++ b/src/Symfony/Component/Validator/CHANGELOG.md @@ -1,6 +1,14 @@ CHANGELOG ========= +4.0.0 +----- + + * Setting the `strict` option of the `Choice` constraint to anything but `true` + is not supported anymore. + * removed the `DateTimeValidator::PATTERN` constant + * removed the `AbstractConstraintValidatorTest` class + 3.3.0 ----- diff --git a/src/Symfony/Component/Validator/Constraints/Choice.php b/src/Symfony/Component/Validator/Constraints/Choice.php index 4b93c70e4a5f4..8c4c23ad0ed65 100644 --- a/src/Symfony/Component/Validator/Constraints/Choice.php +++ b/src/Symfony/Component/Validator/Constraints/Choice.php @@ -34,7 +34,7 @@ class Choice extends Constraint public $choices; public $callback; public $multiple = false; - public $strict = false; + public $strict = true; public $min; public $max; public $message = 'The value you selected is not a valid choice.'; diff --git a/src/Symfony/Component/Validator/Constraints/ChoiceValidator.php b/src/Symfony/Component/Validator/Constraints/ChoiceValidator.php index 6c81b3b4e0b22..4d9b687f6fd88 100644 --- a/src/Symfony/Component/Validator/Constraints/ChoiceValidator.php +++ b/src/Symfony/Component/Validator/Constraints/ChoiceValidator.php @@ -59,12 +59,12 @@ public function validate($value, Constraint $constraint) } if (false === $constraint->strict) { - @trigger_error('Setting the strict option of the Choice constraint to false is deprecated since version 3.2 and will be removed in 4.0.', E_USER_DEPRECATED); + throw new \RuntimeException('The "strict" option of the Choice constraint should not be used.'); } if ($constraint->multiple) { foreach ($value as $_value) { - if (!in_array($_value, $choices, $constraint->strict)) { + if (!in_array($_value, $choices, true)) { $this->context->buildViolation($constraint->multipleMessage) ->setParameter('{{ value }}', $this->formatValue($_value)) ->setCode(Choice::NO_SUCH_CHOICE_ERROR) @@ -96,7 +96,7 @@ public function validate($value, Constraint $constraint) return; } - } elseif (!in_array($value, $choices, $constraint->strict)) { + } elseif (!in_array($value, $choices, true)) { $this->context->buildViolation($constraint->message) ->setParameter('{{ value }}', $this->formatValue($value)) ->setCode(Choice::NO_SUCH_CHOICE_ERROR) diff --git a/src/Symfony/Component/Validator/Constraints/DateTimeValidator.php b/src/Symfony/Component/Validator/Constraints/DateTimeValidator.php index af956ee06b583..63c6a7b903008 100644 --- a/src/Symfony/Component/Validator/Constraints/DateTimeValidator.php +++ b/src/Symfony/Component/Validator/Constraints/DateTimeValidator.php @@ -20,11 +20,6 @@ */ class DateTimeValidator extends DateValidator { - /** - * @deprecated since version 3.1, to be removed in 4.0. - */ - const PATTERN = '/^(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})$/'; - /** * {@inheritdoc} */ diff --git a/src/Symfony/Component/Validator/Tests/Constraints/AbstractConstraintValidatorTest.php b/src/Symfony/Component/Validator/Tests/Constraints/AbstractConstraintValidatorTest.php deleted file mode 100644 index 52af8991fe0fc..0000000000000 --- a/src/Symfony/Component/Validator/Tests/Constraints/AbstractConstraintValidatorTest.php +++ /dev/null @@ -1,21 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Validator\Tests\Constraints; - -use Symfony\Component\Validator\Test\ConstraintValidatorTestCase; - -/** - * @deprecated Since Symfony 3.2, use ConstraintValidatorTestCase instead. - */ -abstract class AbstractConstraintValidatorTest extends ConstraintValidatorTestCase -{ -} diff --git a/src/Symfony/Component/Validator/Tests/Constraints/ChoiceValidatorTest.php b/src/Symfony/Component/Validator/Tests/Constraints/ChoiceValidatorTest.php index 01483161c9fc4..38607bb9a8891 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/ChoiceValidatorTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/ChoiceValidatorTest.php @@ -45,7 +45,6 @@ public function testExpectArrayIfMultipleIsTrue() $constraint = new Choice(array( 'choices' => array('foo', 'bar'), 'multiple' => true, - 'strict' => true, )); $this->validator->validate('asdf', $constraint); @@ -58,7 +57,6 @@ public function testNullIsValid() new Choice( array( 'choices' => array('foo', 'bar'), - 'strict' => true, ) ) ); @@ -71,7 +69,7 @@ public function testNullIsValid() */ public function testChoicesOrCallbackExpected() { - $this->validator->validate('foobar', new Choice(array('strict' => true))); + $this->validator->validate('foobar', new Choice()); } /** @@ -79,12 +77,12 @@ public function testChoicesOrCallbackExpected() */ public function testValidCallbackExpected() { - $this->validator->validate('foobar', new Choice(array('callback' => 'abcd', 'strict' => true))); + $this->validator->validate('foobar', new Choice(array('callback' => 'abcd'))); } public function testValidChoiceArray() { - $constraint = new Choice(array('choices' => array('foo', 'bar'), 'strict' => true)); + $constraint = new Choice(array('choices' => array('foo', 'bar'))); $this->validator->validate('bar', $constraint); @@ -93,7 +91,7 @@ public function testValidChoiceArray() public function testValidChoiceCallbackFunction() { - $constraint = new Choice(array('callback' => __NAMESPACE__.'\choice_callback', 'strict' => true)); + $constraint = new Choice(array('callback' => __NAMESPACE__.'\choice_callback')); $this->validator->validate('bar', $constraint); @@ -104,7 +102,6 @@ public function testValidChoiceCallbackClosure() { $constraint = new Choice( array( - 'strict' => true, 'callback' => function () { return array('foo', 'bar'); }, @@ -118,7 +115,7 @@ public function testValidChoiceCallbackClosure() public function testValidChoiceCallbackStaticMethod() { - $constraint = new Choice(array('callback' => array(__CLASS__, 'staticCallback'), 'strict' => true)); + $constraint = new Choice(array('callback' => array(__CLASS__, 'staticCallback'))); $this->validator->validate('bar', $constraint); @@ -130,7 +127,7 @@ public function testValidChoiceCallbackContextMethod() // search $this for "staticCallback" $this->setObject($this); - $constraint = new Choice(array('callback' => 'staticCallback', 'strict' => true)); + $constraint = new Choice(array('callback' => 'staticCallback')); $this->validator->validate('bar', $constraint); @@ -142,7 +139,7 @@ public function testValidChoiceCallbackContextObjectMethod() // search $this for "objectMethodCallback" $this->setObject($this); - $constraint = new Choice(array('callback' => 'objectMethodCallback', 'strict' => true)); + $constraint = new Choice(array('callback' => 'objectMethodCallback')); $this->validator->validate('bar', $constraint); @@ -154,7 +151,6 @@ public function testMultipleChoices() $constraint = new Choice(array( 'choices' => array('foo', 'bar', 'baz'), 'multiple' => true, - 'strict' => true, )); $this->validator->validate(array('baz', 'bar'), $constraint); @@ -167,7 +163,6 @@ public function testInvalidChoice() $constraint = new Choice(array( 'choices' => array('foo', 'bar'), 'message' => 'myMessage', - 'strict' => true, )); $this->validator->validate('baz', $constraint); @@ -185,7 +180,6 @@ public function testInvalidChoiceEmptyChoices() // the DB or the model 'choices' => array(), 'message' => 'myMessage', - 'strict' => true, )); $this->validator->validate('baz', $constraint); @@ -202,7 +196,6 @@ public function testInvalidChoiceMultiple() 'choices' => array('foo', 'bar'), 'multipleMessage' => 'myMessage', 'multiple' => true, - 'strict' => true, )); $this->validator->validate(array('foo', 'baz'), $constraint); @@ -221,7 +214,6 @@ public function testTooFewChoices() 'multiple' => true, 'min' => 2, 'minMessage' => 'myMessage', - 'strict' => true, )); $value = array('foo'); @@ -245,7 +237,6 @@ public function testTooManyChoices() 'multiple' => true, 'max' => 2, 'maxMessage' => 'myMessage', - 'strict' => true, )); $value = array('foo', 'bar', 'moo'); @@ -262,27 +253,10 @@ public function testTooManyChoices() ->assertRaised(); } - /** - * @group legacy - */ - public function testNonStrict() - { - $constraint = new Choice(array( - 'choices' => array(1, 2), - 'strict' => false, - )); - - $this->validator->validate('2', $constraint); - $this->validator->validate(2, $constraint); - - $this->assertNoViolation(); - } - public function testStrictAllowsExactValue() { $constraint = new Choice(array( 'choices' => array(1, 2), - 'strict' => true, )); $this->validator->validate(2, $constraint); @@ -294,7 +268,6 @@ public function testStrictDisallowsDifferentType() { $constraint = new Choice(array( 'choices' => array(1, 2), - 'strict' => true, 'message' => 'myMessage', )); @@ -306,28 +279,11 @@ public function testStrictDisallowsDifferentType() ->assertRaised(); } - /** - * @group legacy - */ - public function testNonStrictWithMultipleChoices() - { - $constraint = new Choice(array( - 'choices' => array(1, 2, 3), - 'multiple' => true, - 'strict' => false, - )); - - $this->validator->validate(array('2', 3), $constraint); - - $this->assertNoViolation(); - } - public function testStrictWithMultipleChoices() { $constraint = new Choice(array( 'choices' => array(1, 2, 3), 'multiple' => true, - 'strict' => true, 'multipleMessage' => 'myMessage', )); From 4cde3b9fcb00602eeafb119defb4a65841a93cfc Mon Sep 17 00:00:00 2001 From: Robin Chalas Date: Sat, 20 May 2017 12:17:46 +0200 Subject: [PATCH 0036/1099] [Console] Remove deprecated features --- src/Symfony/Component/Console/Application.php | 70 ---- src/Symfony/Component/Console/CHANGELOG.md | 7 + .../Console/Helper/QuestionHelper.php | 41 -- .../Console/Tests/ApplicationTest.php | 18 - .../Tests/Helper/QuestionHelperTest.php | 351 ------------------ 5 files changed, 7 insertions(+), 480 deletions(-) diff --git a/src/Symfony/Component/Console/Application.php b/src/Symfony/Component/Console/Application.php index fd15fb4cb26aa..aed8615e53741 100644 --- a/src/Symfony/Component/Console/Application.php +++ b/src/Symfony/Component/Console/Application.php @@ -733,70 +733,6 @@ public function renderException(\Exception $e, OutputInterface $output) } } - /** - * Tries to figure out the terminal width in which this application runs. - * - * @return int|null - * - * @deprecated since version 3.2, to be removed in 4.0. Create a Terminal instance instead. - */ - protected function getTerminalWidth() - { - @trigger_error(sprintf('%s is deprecated as of 3.2 and will be removed in 4.0. Create a Terminal instance instead.', __METHOD__), E_USER_DEPRECATED); - - return $this->terminal->getWidth(); - } - - /** - * Tries to figure out the terminal height in which this application runs. - * - * @return int|null - * - * @deprecated since version 3.2, to be removed in 4.0. Create a Terminal instance instead. - */ - protected function getTerminalHeight() - { - @trigger_error(sprintf('%s is deprecated as of 3.2 and will be removed in 4.0. Create a Terminal instance instead.', __METHOD__), E_USER_DEPRECATED); - - return $this->terminal->getHeight(); - } - - /** - * Tries to figure out the terminal dimensions based on the current environment. - * - * @return array Array containing width and height - * - * @deprecated since version 3.2, to be removed in 4.0. Create a Terminal instance instead. - */ - public function getTerminalDimensions() - { - @trigger_error(sprintf('%s is deprecated as of 3.2 and will be removed in 4.0. Create a Terminal instance instead.', __METHOD__), E_USER_DEPRECATED); - - return array($this->terminal->getWidth(), $this->terminal->getHeight()); - } - - /** - * Sets terminal dimensions. - * - * Can be useful to force terminal dimensions for functional tests. - * - * @param int $width The width - * @param int $height The height - * - * @return $this - * - * @deprecated since version 3.2, to be removed in 4.0. Set the COLUMNS and LINES env vars instead. - */ - public function setTerminalDimensions($width, $height) - { - @trigger_error(sprintf('%s is deprecated as of 3.2 and will be removed in 4.0. Set the COLUMNS and LINES env vars instead.', __METHOD__), E_USER_DEPRECATED); - - putenv('COLUMNS='.$width); - putenv('LINES='.$height); - - return $this; - } - /** * Configures the input and output instances based on the user arguments and options. * @@ -820,12 +756,6 @@ protected function configureIO(InputInterface $input, OutputInterface $output) $inputStream = $input->getStream(); } - // This check ensures that calling QuestionHelper::setInputStream() works - // To be removed in 4.0 (in the same time as QuestionHelper::setInputStream) - if (!$inputStream && $this->getHelperSet()->has('question')) { - $inputStream = $this->getHelperSet()->get('question')->getInputStream(false); - } - if (!@posix_isatty($inputStream) && false === getenv('SHELL_INTERACTIVE')) { $input->setInteractive(false); } diff --git a/src/Symfony/Component/Console/CHANGELOG.md b/src/Symfony/Component/Console/CHANGELOG.md index f8539491d264b..5b1c378868ced 100644 --- a/src/Symfony/Component/Console/CHANGELOG.md +++ b/src/Symfony/Component/Console/CHANGELOG.md @@ -1,6 +1,13 @@ CHANGELOG ========= +4.0.0 +----- + + * removed `QuestionHelper::setInputStream()/getInputStream()` + * removed `Application::getTerminalWidth()/getTerminalHeight()` and + `Application::setTerminalDimensions()/getTerminalDimensions()` + 3.3.0 ----- diff --git a/src/Symfony/Component/Console/Helper/QuestionHelper.php b/src/Symfony/Component/Console/Helper/QuestionHelper.php index dd89105f6c935..44dd872c7f5b6 100644 --- a/src/Symfony/Component/Console/Helper/QuestionHelper.php +++ b/src/Symfony/Component/Console/Helper/QuestionHelper.php @@ -11,7 +11,6 @@ namespace Symfony\Component\Console\Helper; -use Symfony\Component\Console\Exception\InvalidArgumentException; use Symfony\Component\Console\Exception\RuntimeException; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\StreamableInputInterface; @@ -68,46 +67,6 @@ public function ask(InputInterface $input, OutputInterface $output, Question $qu return $this->validateAttempts($interviewer, $output, $question); } - /** - * Sets the input stream to read from when interacting with the user. - * - * This is mainly useful for testing purpose. - * - * @deprecated since version 3.2, to be removed in 4.0. Use - * StreamableInputInterface::setStream() instead. - * - * @param resource $stream The input stream - * - * @throws InvalidArgumentException In case the stream is not a resource - */ - public function setInputStream($stream) - { - @trigger_error(sprintf('The %s() method is deprecated since version 3.2 and will be removed in 4.0. Use %s::setStream() instead.', __METHOD__, StreamableInputInterface::class), E_USER_DEPRECATED); - - if (!is_resource($stream)) { - throw new InvalidArgumentException('Input stream must be a valid resource.'); - } - - $this->inputStream = $stream; - } - - /** - * Returns the helper's input stream. - * - * @deprecated since version 3.2, to be removed in 4.0. Use - * StreamableInputInterface::getStream() instead. - * - * @return resource - */ - public function getInputStream() - { - if (0 === func_num_args() || func_get_arg(0)) { - @trigger_error(sprintf('The %s() method is deprecated since version 3.2 and will be removed in 4.0. Use %s::getStream() instead.', __METHOD__, StreamableInputInterface::class), E_USER_DEPRECATED); - } - - return $this->inputStream; - } - /** * {@inheritdoc} */ diff --git a/src/Symfony/Component/Console/Tests/ApplicationTest.php b/src/Symfony/Component/Console/Tests/ApplicationTest.php index 34d9cb0c0d780..5d0d5cce6351b 100644 --- a/src/Symfony/Component/Console/Tests/ApplicationTest.php +++ b/src/Symfony/Component/Console/Tests/ApplicationTest.php @@ -1287,24 +1287,6 @@ public function testRunWithDispatcherAddingInputOptions() $this->assertEquals('some test value', $extraValue); } - /** - * @group legacy - */ - public function testTerminalDimensions() - { - $application = new Application(); - $originalDimensions = $application->getTerminalDimensions(); - $this->assertCount(2, $originalDimensions); - - $width = 80; - if ($originalDimensions[0] == $width) { - $width = 100; - } - - $application->setTerminalDimensions($width, 80); - $this->assertSame(array($width, 80), $application->getTerminalDimensions()); - } - public function testSetRunCustomDefaultCommand() { $command = new \FooCommand(); diff --git a/src/Symfony/Component/Console/Tests/Helper/QuestionHelperTest.php b/src/Symfony/Component/Console/Tests/Helper/QuestionHelperTest.php index 700bfe240d253..dc3617b10bfc8 100644 --- a/src/Symfony/Component/Console/Tests/Helper/QuestionHelperTest.php +++ b/src/Symfony/Component/Console/Tests/Helper/QuestionHelperTest.php @@ -393,357 +393,6 @@ public function testChoiceOutputFormattingQuestionForUtf8Keys() $dialog->ask($this->createStreamableInputInterfaceMock($this->getInputStream("\n")), $output, $question); } - /** - * @group legacy - */ - public function testLegacyAskChoice() - { - $questionHelper = new QuestionHelper(); - - $helperSet = new HelperSet(array(new FormatterHelper())); - $questionHelper->setHelperSet($helperSet); - - $heroes = array('Superman', 'Batman', 'Spiderman'); - - $questionHelper->setInputStream($this->getInputStream("\n1\n 1 \nFabien\n1\nFabien\n1\n0,2\n 0 , 2 \n\n\n")); - - $question = new ChoiceQuestion('What is your favorite superhero?', $heroes, '2'); - $question->setMaxAttempts(1); - // first answer is an empty answer, we're supposed to receive the default value - $this->assertEquals('Spiderman', $questionHelper->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question)); - - $question = new ChoiceQuestion('What is your favorite superhero?', $heroes); - $question->setMaxAttempts(1); - $this->assertEquals('Batman', $questionHelper->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question)); - $this->assertEquals('Batman', $questionHelper->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question)); - - $question = new ChoiceQuestion('What is your favorite superhero?', $heroes); - $question->setErrorMessage('Input "%s" is not a superhero!'); - $question->setMaxAttempts(2); - $this->assertEquals('Batman', $questionHelper->ask($this->createInputInterfaceMock(), $output = $this->createOutputInterface(), $question)); - - rewind($output->getStream()); - $stream = stream_get_contents($output->getStream()); - $this->assertContains('Input "Fabien" is not a superhero!', $stream); - - try { - $question = new ChoiceQuestion('What is your favorite superhero?', $heroes, '1'); - $question->setMaxAttempts(1); - $questionHelper->ask($this->createInputInterfaceMock(), $output = $this->createOutputInterface(), $question); - $this->fail(); - } catch (\InvalidArgumentException $e) { - $this->assertEquals('Value "Fabien" is invalid', $e->getMessage()); - } - - $question = new ChoiceQuestion('What is your favorite superhero?', $heroes, null); - $question->setMaxAttempts(1); - $question->setMultiselect(true); - - $this->assertEquals(array('Batman'), $questionHelper->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question)); - $this->assertEquals(array('Superman', 'Spiderman'), $questionHelper->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question)); - $this->assertEquals(array('Superman', 'Spiderman'), $questionHelper->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question)); - - $question = new ChoiceQuestion('What is your favorite superhero?', $heroes, '0,1'); - $question->setMaxAttempts(1); - $question->setMultiselect(true); - - $this->assertEquals(array('Superman', 'Batman'), $questionHelper->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question)); - - $question = new ChoiceQuestion('What is your favorite superhero?', $heroes, ' 0 , 1 '); - $question->setMaxAttempts(1); - $question->setMultiselect(true); - - $this->assertEquals(array('Superman', 'Batman'), $questionHelper->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question)); - } - - /** - * @group legacy - */ - public function testLegacyAsk() - { - $dialog = new QuestionHelper(); - - $dialog->setInputStream($this->getInputStream("\n8AM\n")); - - $question = new Question('What time is it?', '2PM'); - $this->assertEquals('2PM', $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question)); - - $question = new Question('What time is it?', '2PM'); - $this->assertEquals('8AM', $dialog->ask($this->createInputInterfaceMock(), $output = $this->createOutputInterface(), $question)); - - rewind($output->getStream()); - $this->assertEquals('What time is it?', stream_get_contents($output->getStream())); - } - - /** - * @group legacy - */ - public function testLegacyAskWithAutocomplete() - { - if (!$this->hasSttyAvailable()) { - $this->markTestSkipped('`stty` is required to test autocomplete functionality'); - } - - // Acm - // AcsTest - // - // - // Test - // - // S - // F00oo - $inputStream = $this->getInputStream("Acm\nAc\177\177s\tTest\n\n\033[A\033[A\n\033[A\033[A\033[A\033[A\033[A\tTest\n\033[B\nS\177\177\033[B\033[B\nF00\177\177oo\t\n"); - - $dialog = new QuestionHelper(); - $dialog->setInputStream($inputStream); - $helperSet = new HelperSet(array(new FormatterHelper())); - $dialog->setHelperSet($helperSet); - - $question = new Question('Please select a bundle', 'FrameworkBundle'); - $question->setAutocompleterValues(array('AcmeDemoBundle', 'AsseticBundle', 'SecurityBundle', 'FooBundle')); - - $this->assertEquals('AcmeDemoBundle', $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question)); - $this->assertEquals('AsseticBundleTest', $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question)); - $this->assertEquals('FrameworkBundle', $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question)); - $this->assertEquals('SecurityBundle', $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question)); - $this->assertEquals('FooBundleTest', $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question)); - $this->assertEquals('AcmeDemoBundle', $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question)); - $this->assertEquals('AsseticBundle', $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question)); - $this->assertEquals('FooBundle', $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question)); - } - - /** - * @group legacy - */ - public function testLegacyAskWithAutocompleteWithNonSequentialKeys() - { - if (!$this->hasSttyAvailable()) { - $this->markTestSkipped('`stty` is required to test autocomplete functionality'); - } - - // - $inputStream = $this->getInputStream("\033[A\033[A\n\033[B\033[B\n"); - - $dialog = new QuestionHelper(); - $dialog->setInputStream($inputStream); - $dialog->setHelperSet(new HelperSet(array(new FormatterHelper()))); - - $question = new ChoiceQuestion('Please select a bundle', array(1 => 'AcmeDemoBundle', 4 => 'AsseticBundle')); - $question->setMaxAttempts(1); - - $this->assertEquals('AcmeDemoBundle', $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question)); - $this->assertEquals('AsseticBundle', $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question)); - } - - /** - * @group legacy - */ - public function testLegacyAskHiddenResponse() - { - if ('\\' === DIRECTORY_SEPARATOR) { - $this->markTestSkipped('This test is not supported on Windows'); - } - - $dialog = new QuestionHelper(); - $dialog->setInputStream($this->getInputStream("8AM\n")); - - $question = new Question('What time is it?'); - $question->setHidden(true); - - $this->assertEquals('8AM', $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question)); - } - - /** - * @group legacy - * @dataProvider getAskConfirmationData - */ - public function testLegacyAskConfirmation($question, $expected, $default = true) - { - $dialog = new QuestionHelper(); - - $dialog->setInputStream($this->getInputStream($question."\n")); - $question = new ConfirmationQuestion('Do you like French fries?', $default); - $this->assertEquals($expected, $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question), 'confirmation question should '.($expected ? 'pass' : 'cancel')); - } - - /** - * @group legacy - */ - public function testLegacyAskConfirmationWithCustomTrueAnswer() - { - $dialog = new QuestionHelper(); - - $dialog->setInputStream($this->getInputStream("j\ny\n")); - $question = new ConfirmationQuestion('Do you like French fries?', false, '/^(j|y)/i'); - $this->assertTrue($dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question)); - $question = new ConfirmationQuestion('Do you like French fries?', false, '/^(j|y)/i'); - $this->assertTrue($dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question)); - } - - /** - * @group legacy - */ - public function testLegacyAskAndValidate() - { - $dialog = new QuestionHelper(); - $helperSet = new HelperSet(array(new FormatterHelper())); - $dialog->setHelperSet($helperSet); - - $error = 'This is not a color!'; - $validator = function ($color) use ($error) { - if (!in_array($color, array('white', 'black'))) { - throw new \InvalidArgumentException($error); - } - - return $color; - }; - - $question = new Question('What color was the white horse of Henry IV?', 'white'); - $question->setValidator($validator); - $question->setMaxAttempts(2); - - $dialog->setInputStream($this->getInputStream("\nblack\n")); - $this->assertEquals('white', $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question)); - $this->assertEquals('black', $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question)); - - $dialog->setInputStream($this->getInputStream("green\nyellow\norange\n")); - try { - $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question); - $this->fail(); - } catch (\InvalidArgumentException $e) { - $this->assertEquals($error, $e->getMessage()); - } - } - - /** - * @group legacy - * @dataProvider simpleAnswerProvider - */ - public function testLegacySelectChoiceFromSimpleChoices($providedAnswer, $expectedValue) - { - $possibleChoices = array( - 'My environment 1', - 'My environment 2', - 'My environment 3', - ); - - $dialog = new QuestionHelper(); - $dialog->setInputStream($this->getInputStream($providedAnswer."\n")); - $helperSet = new HelperSet(array(new FormatterHelper())); - $dialog->setHelperSet($helperSet); - - $question = new ChoiceQuestion('Please select the environment to load', $possibleChoices); - $question->setMaxAttempts(1); - $answer = $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question); - - $this->assertSame($expectedValue, $answer); - } - - /** - * @group legacy - * @dataProvider mixedKeysChoiceListAnswerProvider - */ - public function testLegacyChoiceFromChoicelistWithMixedKeys($providedAnswer, $expectedValue) - { - $possibleChoices = array( - '0' => 'No environment', - '1' => 'My environment 1', - 'env_2' => 'My environment 2', - 3 => 'My environment 3', - ); - - $dialog = new QuestionHelper(); - $dialog->setInputStream($this->getInputStream($providedAnswer."\n")); - $helperSet = new HelperSet(array(new FormatterHelper())); - $dialog->setHelperSet($helperSet); - - $question = new ChoiceQuestion('Please select the environment to load', $possibleChoices); - $question->setMaxAttempts(1); - $answer = $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question); - - $this->assertSame($expectedValue, $answer); - } - - /** - * @group legacy - * @dataProvider answerProvider - */ - public function testLegacySelectChoiceFromChoiceList($providedAnswer, $expectedValue) - { - $possibleChoices = array( - 'env_1' => 'My environment 1', - 'env_2' => 'My environment', - 'env_3' => 'My environment', - ); - - $dialog = new QuestionHelper(); - $dialog->setInputStream($this->getInputStream($providedAnswer."\n")); - $helperSet = new HelperSet(array(new FormatterHelper())); - $dialog->setHelperSet($helperSet); - - $question = new ChoiceQuestion('Please select the environment to load', $possibleChoices); - $question->setMaxAttempts(1); - $answer = $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question); - - $this->assertSame($expectedValue, $answer); - } - - /** - * @group legacy - * @expectedException \InvalidArgumentException - * @expectedExceptionMessage The provided answer is ambiguous. Value should be one of env_2 or env_3. - */ - public function testLegacyAmbiguousChoiceFromChoicelist() - { - $possibleChoices = array( - 'env_1' => 'My first environment', - 'env_2' => 'My environment', - 'env_3' => 'My environment', - ); - - $dialog = new QuestionHelper(); - $dialog->setInputStream($this->getInputStream("My environment\n")); - $helperSet = new HelperSet(array(new FormatterHelper())); - $dialog->setHelperSet($helperSet); - - $question = new ChoiceQuestion('Please select the environment to load', $possibleChoices); - $question->setMaxAttempts(1); - - $dialog->ask($this->createInputInterfaceMock(), $this->createOutputInterface(), $question); - } - - /** - * @requires function mb_strwidth - * @group legacy - */ - public function testLegacyChoiceOutputFormattingQuestionForUtf8Keys() - { - $question = 'Lorem ipsum?'; - $possibleChoices = array( - 'foo' => 'foo', - 'żółw' => 'bar', - 'łabądź' => 'baz', - ); - $outputShown = array( - $question, - ' [foo ] foo', - ' [żółw ] bar', - ' [łabądź] baz', - ); - $output = $this->getMockBuilder('\Symfony\Component\Console\Output\OutputInterface')->getMock(); - $output->method('getFormatter')->willReturn(new OutputFormatter()); - - $dialog = new QuestionHelper(); - $dialog->setInputStream($this->getInputStream("\n")); - $helperSet = new HelperSet(array(new FormatterHelper())); - $dialog->setHelperSet($helperSet); - - $output->expects($this->once())->method('writeln')->with($this->equalTo($outputShown)); - - $question = new ChoiceQuestion($question, $possibleChoices, 'foo'); - $dialog->ask($this->createInputInterfaceMock(), $output, $question); - } - /** * @expectedException \Symfony\Component\Console\Exception\RuntimeException * @expectedExceptionMessage Aborted From a820b42a2df7ded77026d5dd267eb93a65c6d8cd Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Sun, 21 May 2017 12:28:38 +0200 Subject: [PATCH 0037/1099] improve strict option value deprecation --- UPGRADE-3.4.md | 8 ++++++++ UPGRADE-4.0.md | 3 +++ src/Symfony/Component/Validator/CHANGELOG.md | 6 ++++++ .../Component/Validator/Constraints/ChoiceValidator.php | 4 ++-- 4 files changed, 19 insertions(+), 2 deletions(-) create mode 100644 UPGRADE-3.4.md diff --git a/UPGRADE-3.4.md b/UPGRADE-3.4.md new file mode 100644 index 0000000000000..27a069cb1883b --- /dev/null +++ b/UPGRADE-3.4.md @@ -0,0 +1,8 @@ +UPGRADE FROM 3.3 to 3.4 +======================= + +Validator +--------- + + * not setting the `strict` option of the `Choice` constraint to `true` is + deprecated and will throw an exception in Symfony 4.0 diff --git a/UPGRADE-4.0.md b/UPGRADE-4.0.md index 4b040fd20318f..ecfd8b090ed93 100644 --- a/UPGRADE-4.0.md +++ b/UPGRADE-4.0.md @@ -507,6 +507,9 @@ TwigBridge Validator --------- + * The default value of the `strict` option of the `Choice` constraint was changed + to `true`. Using any other value will throw an exception. + * The `DateTimeValidator::PATTERN` constant was removed. * `Tests\Constraints\AbstractConstraintValidatorTest` has been removed in diff --git a/src/Symfony/Component/Validator/CHANGELOG.md b/src/Symfony/Component/Validator/CHANGELOG.md index 7099496cfa1d2..e0e132938d0b3 100644 --- a/src/Symfony/Component/Validator/CHANGELOG.md +++ b/src/Symfony/Component/Validator/CHANGELOG.md @@ -1,6 +1,12 @@ CHANGELOG ========= +3.4.0 +----- + + * not setting the `strict` option of the `Choice` constraint to `true` is + deprecated and will throw an exception in Symfony 4.0 + 3.3.0 ----- diff --git a/src/Symfony/Component/Validator/Constraints/ChoiceValidator.php b/src/Symfony/Component/Validator/Constraints/ChoiceValidator.php index 6c81b3b4e0b22..ca114a4fef7fa 100644 --- a/src/Symfony/Component/Validator/Constraints/ChoiceValidator.php +++ b/src/Symfony/Component/Validator/Constraints/ChoiceValidator.php @@ -58,8 +58,8 @@ public function validate($value, Constraint $constraint) $choices = $constraint->choices; } - if (false === $constraint->strict) { - @trigger_error('Setting the strict option of the Choice constraint to false is deprecated since version 3.2 and will be removed in 4.0.', E_USER_DEPRECATED); + if (true !== $constraint->strict) { + @trigger_error('Not setting the strict option of the Choice constraint to true is deprecated since version 3.4 and will throw an exception in 4.0.', E_USER_DEPRECATED); } if ($constraint->multiple) { From 531156e0039ecafb165a9b330bb27dc917da61a9 Mon Sep 17 00:00:00 2001 From: Maxime Steinhausser Date: Sat, 20 May 2017 11:00:43 +0200 Subject: [PATCH 0038/1099] [FrameworkBundle] Remove deprecated code --- .../Bundle/FrameworkBundle/CHANGELOG.md | 6 + .../Command/CacheClearCommand.php | 197 +----------------- .../DependencyInjection/Configuration.php | 6 - .../FrameworkExtension.php | 13 +- .../FrameworkBundle/FrameworkBundle.php | 8 - .../FrameworkBundle/Resources/config/form.xml | 101 --------- .../Resources/config/form_csrf.xml | 7 - .../Resources/config/routing.xml | 24 +-- .../Resources/config/serializer.xml | 11 - .../Templating/TemplateNameParser.php | 13 +- .../CacheClearCommandTest.php | 39 +--- .../FrameworkExtensionTest.php | 15 -- .../Templating/TemplateNameParserTest.php | 25 --- .../Validator/ConstraintValidatorFactory.php | 4 +- 14 files changed, 26 insertions(+), 443 deletions(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md b/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md index e7af6de4c027f..d046346861617 100644 --- a/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md +++ b/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md @@ -11,6 +11,12 @@ CHANGELOG `RoutingResolverPass`, `SerializerPass`, `ValidateWorkflowsPass` * made `Translator::__construct()` `$defaultLocale` argument required * removed `SessionListener`, `TestSessionListener` + * Removed `cache:clear` warmup part along with the `--no-optional-warmers` option + * Removed core form types services registration when unnecessary + * Removed `framework.serializer.cache` option and `serializer.mapping.cache.apc`, `serializer.mapping.cache.doctrine.apc` services + * Removed `ConstraintValidatorFactory::$validators` and `ConstraintValidatorFactory::$container` protected properties + * Removed class parameters related to routing + * Removed absolute template paths support in the template name parser 3.3.0 ----- diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/CacheClearCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/CacheClearCommand.php index 49284270e6e34..0a70d9a859119 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/CacheClearCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/CacheClearCommand.php @@ -15,8 +15,6 @@ use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Style\SymfonyStyle; -use Symfony\Component\HttpKernel\KernelInterface; -use Symfony\Component\Finder\Finder; /** * Clear and Warmup the cache. @@ -34,8 +32,7 @@ protected function configure() $this ->setName('cache:clear') ->setDefinition(array( - new InputOption('no-warmup', '', InputOption::VALUE_NONE, 'Do not warm up the cache'), - new InputOption('no-optional-warmers', '', InputOption::VALUE_NONE, 'Skip optional cache warmers (faster)'), + new InputOption('no-warmup', '', InputOption::VALUE_NONE, 'Noop. Will be deprecated in 4.1 to be removed in 5.0.'), )) ->setDescription('Clears the cache') ->setHelp(<<<'EOF' @@ -56,37 +53,22 @@ protected function execute(InputInterface $input, OutputInterface $output) { $io = new SymfonyStyle($input, $output); - $realCacheDir = $this->getContainer()->getParameter('kernel.cache_dir'); - // the old cache dir name must not be longer than the real one to avoid exceeding - // the maximum length of a directory or file path within it (esp. Windows MAX_PATH) - $oldCacheDir = substr($realCacheDir, 0, -1).('~' === substr($realCacheDir, -1) ? '+' : '~'); + $cacheDir = $this->getContainer()->getParameter('kernel.cache_dir'); $filesystem = $this->getContainer()->get('filesystem'); - if (!is_writable($realCacheDir)) { - throw new \RuntimeException(sprintf('Unable to write in the "%s" directory', $realCacheDir)); - } - - if ($filesystem->exists($oldCacheDir)) { - $filesystem->remove($oldCacheDir); + if (!is_writable($cacheDir)) { + throw new \RuntimeException(sprintf('Unable to write in the "%s" directory', $cacheDir)); } $kernel = $this->getContainer()->get('kernel'); $io->comment(sprintf('Clearing the cache for the %s environment with debug %s', $kernel->getEnvironment(), var_export($kernel->isDebug(), true))); - $this->getContainer()->get('cache_clearer')->clear($realCacheDir); - - if ($input->getOption('no-warmup')) { - $filesystem->rename($realCacheDir, $oldCacheDir); - } else { - @trigger_error('Calling cache:clear without the --no-warmup option is deprecated since version 3.3. Cache warmup should be done with the cache:warmup command instead.', E_USER_DEPRECATED); - - $this->warmupCache($input, $output, $realCacheDir, $oldCacheDir); - } + $this->getContainer()->get('cache_clearer')->clear($cacheDir); if ($output->isVerbose()) { $io->comment('Removing old cache directory...'); } - $filesystem->remove($oldCacheDir); + $filesystem->remove($cacheDir); if ($output->isVerbose()) { $io->comment('Finished'); @@ -94,171 +76,4 @@ protected function execute(InputInterface $input, OutputInterface $output) $io->success(sprintf('Cache for the "%s" environment (debug=%s) was successfully cleared.', $kernel->getEnvironment(), var_export($kernel->isDebug(), true))); } - - private function warmupCache(InputInterface $input, OutputInterface $output, $realCacheDir, $oldCacheDir) - { - $filesystem = $this->getContainer()->get('filesystem'); - $io = new SymfonyStyle($input, $output); - - // the warmup cache dir name must have the same length than the real one - // to avoid the many problems in serialized resources files - $realCacheDir = realpath($realCacheDir); - $warmupDir = substr($realCacheDir, 0, -1).('_' === substr($realCacheDir, -1) ? '-' : '_'); - - if ($filesystem->exists($warmupDir)) { - if ($output->isVerbose()) { - $io->comment('Clearing outdated warmup directory...'); - } - $filesystem->remove($warmupDir); - } - - if ($output->isVerbose()) { - $io->comment('Warming up cache...'); - } - $this->warmup($warmupDir, $realCacheDir, !$input->getOption('no-optional-warmers')); - - $filesystem->rename($realCacheDir, $oldCacheDir); - if ('\\' === DIRECTORY_SEPARATOR) { - sleep(1); // workaround for Windows PHP rename bug - } - $filesystem->rename($warmupDir, $realCacheDir); - } - - /** - * @param string $warmupDir - * @param string $realCacheDir - * @param bool $enableOptionalWarmers - * - * @internal to be removed in 4.0 - */ - protected function warmup($warmupDir, $realCacheDir, $enableOptionalWarmers = true) - { - // create a temporary kernel - $realKernel = $this->getContainer()->get('kernel'); - $realKernelClass = get_class($realKernel); - $namespace = ''; - if (false !== $pos = strrpos($realKernelClass, '\\')) { - $namespace = substr($realKernelClass, 0, $pos); - $realKernelClass = substr($realKernelClass, $pos + 1); - } - $tempKernel = $this->getTempKernel($realKernel, $namespace, $realKernelClass, $warmupDir); - $tempKernel->boot(); - - $tempKernelReflection = new \ReflectionObject($tempKernel); - $tempKernelFile = $tempKernelReflection->getFileName(); - - // warmup temporary dir - $warmer = $tempKernel->getContainer()->get('cache_warmer'); - if ($enableOptionalWarmers) { - $warmer->enableOptionalWarmers(); - } - $warmer->warmUp($warmupDir); - - // fix references to the Kernel in .meta files - $safeTempKernel = str_replace('\\', '\\\\', get_class($tempKernel)); - $realKernelFQN = get_class($realKernel); - - foreach (Finder::create()->files()->name('*.meta')->in($warmupDir) as $file) { - file_put_contents($file, preg_replace( - '/(C\:\d+\:)"'.$safeTempKernel.'"/', - sprintf('$1"%s"', $realKernelFQN), - file_get_contents($file) - )); - } - - // fix references to cached files with the real cache directory name - $search = array($warmupDir, str_replace('\\', '\\\\', $warmupDir)); - $replace = str_replace('\\', '/', $realCacheDir); - foreach (Finder::create()->files()->in($warmupDir) as $file) { - $content = str_replace($search, $replace, file_get_contents($file)); - file_put_contents($file, $content); - } - - // fix references to container's class - $tempContainerClass = get_class($tempKernel->getContainer()); - $realContainerClass = get_class($realKernel->getContainer()); - foreach (Finder::create()->files()->name($tempContainerClass.'*')->in($warmupDir) as $file) { - $content = str_replace($tempContainerClass, $realContainerClass, file_get_contents($file)); - file_put_contents($file, $content); - rename($file, str_replace(DIRECTORY_SEPARATOR.$tempContainerClass, DIRECTORY_SEPARATOR.$realContainerClass, $file)); - } - - // remove temp kernel file after cache warmed up - @unlink($tempKernelFile); - } - - /** - * @param KernelInterface $parent - * @param string $namespace - * @param string $parentClass - * @param string $warmupDir - * - * @return KernelInterface - * - * @internal to be removed in 4.0 - */ - protected function getTempKernel(KernelInterface $parent, $namespace, $parentClass, $warmupDir) - { - $cacheDir = var_export($warmupDir, true); - $rootDir = var_export(realpath($parent->getRootDir()), true); - $logDir = var_export(realpath($parent->getLogDir()), true); - // the temp kernel class name must have the same length than the real one - // to avoid the many problems in serialized resources files - $class = substr($parentClass, 0, -1).'_'; - // the temp container class must be changed too - $containerClass = var_export(substr(get_class($parent->getContainer()), 0, -1).'_', true); - $code = <<getResources(); - \$filteredResources = array(); - foreach (\$resources as \$resource) { - if ((string) \$resource !== __FILE__) { - \$filteredResources[] = \$resource; - } - } - - \$container->setResources(\$filteredResources); - - return \$container; - } - } -} -EOF; - $this->getContainer()->get('filesystem')->mkdir($warmupDir); - file_put_contents($file = $warmupDir.'/kernel.tmp', $code); - require_once $file; - $class = "$namespace\\$class"; - - return new $class($parent->getEnvironment(), $parent->isDebug()); - } } diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php index 9d09599d811ee..e4fed3d17df08 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php @@ -65,12 +65,6 @@ public function getConfigTreeBuilder() ->info("Set true to enable support for the '_method' request parameter to determine the intended HTTP method on POST requests. Note: When using the HttpCache, you need to call the method in your front controller instead") ->defaultTrue() ->end() - ->arrayNode('trusted_proxies') // @deprecated in version 3.3, to be removed in 4.0 - ->beforeNormalization() - ->always() - ->thenInvalid('The "framework.trusted_proxies" configuration key has been removed in Symfony 3.3. Use the Request::setTrustedProxies() method in your front controller instead.') - ->end() - ->end() ->scalarNode('ide')->defaultNull()->end() ->booleanNode('test')->end() ->scalarNode('default_locale')->defaultValue('en')->end() diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php index 7ab3a4b680a57..a06858343abc1 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php @@ -1242,18 +1242,7 @@ private function registerSerializerConfiguration(array $config, ContainerBuilder $chainLoader->replaceArgument(0, $serializerLoaders); $container->getDefinition('serializer.mapping.cache_warmer')->replaceArgument(0, $serializerLoaders); - if (isset($config['cache']) && $config['cache']) { - @trigger_error('The "framework.serializer.cache" option is deprecated since Symfony 3.1 and will be removed in 4.0. Configure the "cache.serializer" service under "framework.cache.pools" instead.', E_USER_DEPRECATED); - - $container->setParameter( - 'serializer.mapping.cache.prefix', - 'serializer_'.$this->getKernelRootHash($container) - ); - - $container->getDefinition('serializer.mapping.class_metadata_factory')->replaceArgument( - 1, new Reference($config['cache']) - ); - } elseif (!$container->getParameter('kernel.debug') && class_exists(CacheClassMetadataFactory::class)) { + if (!$container->getParameter('kernel.debug') && class_exists(CacheClassMetadataFactory::class)) { $cacheMetadataFactory = new Definition( CacheClassMetadataFactory::class, array( diff --git a/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php b/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php index 1844f9b4a4391..d085059f4afe4 100644 --- a/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php +++ b/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php @@ -60,14 +60,6 @@ public function boot() { ErrorHandler::register(null, false)->throwAt($this->container->getParameter('debug.error_handler.throw_at'), true); - if ($this->container->hasParameter('kernel.trusted_proxies')) { - @trigger_error('The "kernel.trusted_proxies" parameter is deprecated since version 3.3 and will be removed in 4.0. Use the Request::setTrustedProxies() method in your front controller instead.', E_USER_DEPRECATED); - - if ($trustedProxies = $this->container->getParameter('kernel.trusted_proxies')) { - Request::setTrustedProxies($trustedProxies, Request::getTrustedHeaderSet()); - } - } - if ($this->container->getParameter('kernel.http_method_override')) { Request::enableHttpMethodParameterOverride(); } diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/form.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/form.xml index 642d8d4ee7bfc..ae0be68d1e439 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/form.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/form.xml @@ -67,97 +67,10 @@ - - The "%service_id%" service is deprecated since Symfony 3.1 and will be removed in 4.0. - - - The "%service_id%" service is deprecated since Symfony 3.1 and will be removed in 4.0. - - - The "%service_id%" service is deprecated since Symfony 3.1 and will be removed in 4.0. - - - The "%service_id%" service is deprecated since Symfony 3.1 and will be removed in 4.0. - - - The "%service_id%" service is deprecated since Symfony 3.1 and will be removed in 4.0. - - - The "%service_id%" service is deprecated since Symfony 3.1 and will be removed in 4.0. - - - The "%service_id%" service is deprecated since Symfony 3.1 and will be removed in 4.0. - - - The "%service_id%" service is deprecated since Symfony 3.1 and will be removed in 4.0. - - - The "%service_id%" service is deprecated since Symfony 3.1 and will be removed in 4.0. - - - The "%service_id%" service is deprecated since Symfony 3.1 and will be removed in 4.0. - - - The "%service_id%" service is deprecated since Symfony 3.1 and will be removed in 4.0. - - - The "%service_id%" service is deprecated since Symfony 3.1 and will be removed in 4.0. - - - The "%service_id%" service is deprecated since Symfony 3.1 and will be removed in 4.0. - - - The "%service_id%" service is deprecated since Symfony 3.1 and will be removed in 4.0. - - - The "%service_id%" service is deprecated since Symfony 3.1 and will be removed in 4.0. - - - The "%service_id%" service is deprecated since Symfony 3.1 and will be removed in 4.0. - - - The "%service_id%" service is deprecated since Symfony 3.1 and will be removed in 4.0. - - - The "%service_id%" service is deprecated since Symfony 3.1 and will be removed in 4.0. - - - The "%service_id%" service is deprecated since Symfony 3.1 and will be removed in 4.0. - - - The "%service_id%" service is deprecated since Symfony 3.1 and will be removed in 4.0. - - - The "%service_id%" service is deprecated since Symfony 3.1 and will be removed in 4.0. - - - The "%service_id%" service is deprecated since Symfony 3.1 and will be removed in 4.0. - - - The "%service_id%" service is deprecated since Symfony 3.1 and will be removed in 4.0. - - - The "%service_id%" service is deprecated since Symfony 3.1 and will be removed in 4.0. - - - The "%service_id%" service is deprecated since Symfony 3.1 and will be removed in 4.0. - - - The "%service_id%" service is deprecated since Symfony 3.1 and will be removed in 4.0. - - - The "%service_id%" service is deprecated since Symfony 3.1 and will be removed in 4.0. - - - The "%service_id%" service is deprecated since Symfony 3.1 and will be removed in 4.0. - - - The "%service_id%" service is deprecated since Symfony 3.1 and will be removed in 4.0. - @@ -190,19 +103,5 @@ %validator.translation_domain% - - - - - - - - - - - - - The service "%service_id%" is internal and deprecated since Symfony 3.3 and will be removed in Symfony 4.0 - diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/form_csrf.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/form_csrf.xml index 5beec83ccce02..cae1c84aa774a 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/form_csrf.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/form_csrf.xml @@ -16,12 +16,5 @@ %validator.translation_domain% - - - - - - The service "%service_id%" is internal and deprecated since Symfony 3.3 and will be removed in Symfony 4.0 - diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/routing.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/routing.xml index 1278a0cb2208e..a5403ba6a533a 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/routing.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/routing.xml @@ -5,14 +5,6 @@ xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd"> - Symfony\Component\Routing\Generator\UrlGenerator - Symfony\Component\Routing\Generator\UrlGenerator - Symfony\Component\Routing\Generator\Dumper\PhpGeneratorDumper - Symfony\Bundle\FrameworkBundle\Routing\RedirectableUrlMatcher - Symfony\Bundle\FrameworkBundle\Routing\RedirectableUrlMatcher - Symfony\Component\Routing\Matcher\Dumper\PhpMatcherDumper - %router.cache_class_prefix%UrlMatcher - %router.cache_class_prefix%UrlGenerator localhost http @@ -65,14 +57,14 @@ %kernel.cache_dir% %kernel.debug% - %router.options.generator_class% - %router.options.generator_base_class% - %router.options.generator_dumper_class% - %router.options.generator.cache_class% - %router.options.matcher_class% - %router.options.matcher_base_class% - %router.options.matcher_dumper_class% - %router.options.matcher.cache_class% + Symfony\Component\Routing\Generator\UrlGenerator + Symfony\Component\Routing\Generator\UrlGenerator + Symfony\Component\Routing\Generator\Dumper\PhpGeneratorDumper + %router.cache_class_prefix%UrlGenerator + Symfony\Bundle\FrameworkBundle\Routing\RedirectableUrlMatcher + Symfony\Bundle\FrameworkBundle\Routing\RedirectableUrlMatcher + Symfony\Component\Routing\Matcher\Dumper\PhpMatcherDumper + %router.cache_class_prefix%UrlMatcher diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/serializer.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/serializer.xml index d350091a01820..ced92835ae4d7 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/serializer.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/serializer.xml @@ -66,17 +66,6 @@ - - - %serializer.mapping.cache.prefix% - - The "%service_id%" service is deprecated since Symfony 3.2 and will be removed in 4.0. APCu should now be automatically used when available. - - - - The "%service_id%" service is deprecated since Symfony 3.1 and will be removed in 4.0. APCu should now be automatically used when available. - - diff --git a/src/Symfony/Bundle/FrameworkBundle/Templating/TemplateNameParser.php b/src/Symfony/Bundle/FrameworkBundle/Templating/TemplateNameParser.php index c16365ff187bf..a98e2e7627f5e 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Templating/TemplateNameParser.php +++ b/src/Symfony/Bundle/FrameworkBundle/Templating/TemplateNameParser.php @@ -55,7 +55,7 @@ public function parse($name) throw new \RuntimeException(sprintf('Template name "%s" contains invalid characters.', $name)); } - if ($this->isAbsolutePath($name) || !preg_match('/^(?:([^:]*):([^:]*):)?(.+)\.([^\.]+)\.([^\.]+)$/', $name, $matches) || 0 === strpos($name, '@')) { + if (!preg_match('/^(?:([^:]*):([^:]*):)?(.+)\.([^\.]+)\.([^\.]+)$/', $name, $matches) || 0 === strpos($name, '@')) { return parent::parse($name); } @@ -71,15 +71,4 @@ public function parse($name) return $this->cache[$name] = $template; } - - private function isAbsolutePath($file) - { - $isAbsolute = (bool) preg_match('#^(?:/|[a-zA-Z]:)#', $file); - - if ($isAbsolute) { - @trigger_error('Absolute template path support is deprecated since Symfony 3.1 and will be removed in 4.0.', E_USER_DEPRECATED); - } - - return $isAbsolute; - } } diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/CacheClearCommand/CacheClearCommandTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/CacheClearCommand/CacheClearCommandTest.php index b9fe63ec5bbab..5aef68d6e14aa 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/CacheClearCommand/CacheClearCommandTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/CacheClearCommand/CacheClearCommandTest.php @@ -14,12 +14,9 @@ use Symfony\Bundle\FrameworkBundle\Console\Application; use Symfony\Bundle\FrameworkBundle\Tests\Command\CacheClearCommand\Fixture\TestAppKernel; use Symfony\Bundle\FrameworkBundle\Tests\TestCase; -use Symfony\Component\Config\ConfigCacheFactory; -use Symfony\Component\Config\Resource\ResourceInterface; use Symfony\Component\Console\Input\ArrayInput; use Symfony\Component\Console\Output\NullOutput; use Symfony\Component\Filesystem\Filesystem; -use Symfony\Component\Finder\Finder; class CacheClearCommandTest extends TestCase { @@ -43,10 +40,7 @@ protected function tearDown() $this->fs->remove($this->rootDir); } - /** - * @group legacy - */ - public function testCacheIsFreshAfterCacheClearedWithWarmup() + public function testCacheIsCleared() { $input = new ArrayInput(array('cache:clear')); $application = new Application($this->kernel); @@ -54,35 +48,6 @@ public function testCacheIsFreshAfterCacheClearedWithWarmup() $application->doRun($input, new NullOutput()); - // Ensure that all *.meta files are fresh - $finder = new Finder(); - $metaFiles = $finder->files()->in($this->kernel->getCacheDir())->name('*.php.meta'); - // simply check that cache is warmed up - $this->assertGreaterThanOrEqual(1, count($metaFiles)); - $configCacheFactory = new ConfigCacheFactory(true); - - foreach ($metaFiles as $file) { - $configCacheFactory->cache(substr($file, 0, -5), function () use ($file) { - $this->fail(sprintf('Meta file "%s" is not fresh', (string) $file)); - }); - } - - // check that app kernel file present in meta file of container's cache - $containerRef = new \ReflectionObject($this->kernel->getContainer()); - $containerFile = $containerRef->getFileName(); - $containerMetaFile = $containerFile.'.meta'; - $kernelRef = new \ReflectionObject($this->kernel); - $kernelFile = $kernelRef->getFileName(); - /** @var ResourceInterface[] $meta */ - $meta = unserialize(file_get_contents($containerMetaFile)); - $found = false; - foreach ($meta as $resource) { - if ((string) $resource === $kernelFile) { - $found = true; - break; - } - } - $this->assertTrue($found, 'Kernel file should present as resource'); - $this->assertRegExp(sprintf('/\'kernel.container_class\'\s*=>\s*\'%s\'/', get_class($this->kernel->getContainer())), file_get_contents($containerFile), 'kernel.container_class is properly set on the dumped container'); + $this->assertDirectoryNotExists($this->kernel->getCacheDir()); } } diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php index a6a201350214b..397afb2265a18 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php @@ -788,21 +788,6 @@ public function testSerializerCacheDisabled() $this->assertFalse($container->hasDefinition('serializer.mapping.cache_class_metadata_factory')); } - /** - * @group legacy - * @expectedDeprecation The "framework.serializer.cache" option is deprecated %s. - */ - public function testDeprecatedSerializerCacheOption() - { - $container = $this->createContainerFromFile('serializer_legacy_cache', array('kernel.debug' => true, 'kernel.container_class' => __CLASS__)); - - $this->assertFalse($container->hasDefinition('serializer.mapping.cache_class_metadata_factory')); - $this->assertTrue($container->hasDefinition('serializer.mapping.class_metadata_factory')); - - $cache = $container->getDefinition('serializer.mapping.class_metadata_factory')->getArgument(1); - $this->assertEquals(new Reference('foo'), $cache); - } - public function testSerializerMapping() { $container = $this->createContainerFromFile('serializer_mapping', array('kernel.bundles_metadata' => array('TestBundle' => array('namespace' => 'Symfony\\Bundle\\FrameworkBundle\\Tests', 'path' => __DIR__.'/Fixtures/TestBundle', 'parent' => null)))); diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Templating/TemplateNameParserTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Templating/TemplateNameParserTest.php index 3e162d167d23e..7f7829b9c0f91 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Templating/TemplateNameParserTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Templating/TemplateNameParserTest.php @@ -81,29 +81,4 @@ public function testParseValidNameWithNotFoundBundle() { $this->parser->parse('BarBundle:Post:index.html.php'); } - - /** - * @group legacy - * @dataProvider provideAbsolutePaths - * @expectedDeprecation Absolute template path support is deprecated since Symfony 3.1 and will be removed in 4.0. - */ - public function testAbsolutePathsAreDeprecated($name, $logicalName, $path, $ref) - { - $template = $this->parser->parse($name); - - $this->assertSame($ref->getLogicalName(), $template->getLogicalName()); - $this->assertSame($logicalName, $template->getLogicalName()); - $this->assertSame($path, $template->getPath()); - } - - public function provideAbsolutePaths() - { - return array( - array('/path/to/section/index.html.php', '/path/to/section/index.html.php', '/path/to/section/index.html.php', new BaseTemplateReference('/path/to/section/index.html.php', 'php')), - array('C:\\path\\to\\section\\name.html.php', 'C:path/to/section/name.html.php', 'C:path/to/section/name.html.php', new BaseTemplateReference('C:path/to/section/name.html.php', 'php')), - array('C:\\path\\to\\section\\name:foo.html.php', 'C:path/to/section/name:foo.html.php', 'C:path/to/section/name:foo.html.php', new BaseTemplateReference('C:path/to/section/name:foo.html.php', 'php')), - array('\\path\\to\\section\\name.html.php', '/path/to/section/name.html.php', '/path/to/section/name.html.php', new BaseTemplateReference('/path/to/section/name.html.php', 'php')), - array('/path/to/section/name.php', '/path/to/section/name.php', '/path/to/section/name.php', new BaseTemplateReference('/path/to/section/name.php', 'php')), - ); - } } diff --git a/src/Symfony/Bundle/FrameworkBundle/Validator/ConstraintValidatorFactory.php b/src/Symfony/Bundle/FrameworkBundle/Validator/ConstraintValidatorFactory.php index aba02e0944e22..dfa6fae646376 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Validator/ConstraintValidatorFactory.php +++ b/src/Symfony/Bundle/FrameworkBundle/Validator/ConstraintValidatorFactory.php @@ -42,8 +42,8 @@ */ class ConstraintValidatorFactory implements ConstraintValidatorFactoryInterface { - protected $container; - protected $validators; + private $container; + private $validators; /** * Constructor. From e3091a50e987e951d1c089726bdd21674418ff46 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Sun, 21 May 2017 13:14:12 +0200 Subject: [PATCH 0039/1099] [DoctrineBridge] add missing changelog entries --- src/Symfony/Bridge/Doctrine/CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/Symfony/Bridge/Doctrine/CHANGELOG.md b/src/Symfony/Bridge/Doctrine/CHANGELOG.md index 2cfb583d81884..8ac901e27fc3f 100644 --- a/src/Symfony/Bridge/Doctrine/CHANGELOG.md +++ b/src/Symfony/Bridge/Doctrine/CHANGELOG.md @@ -4,6 +4,11 @@ CHANGELOG 4.0.0 ----- + * the first constructor argument of the `DoctrineChoiceLoader` class must be + an `ObjectManager` implementation + * removed the `MergeDoctrineCollectionListener::onBind()` method + * trying to reset a non-lazy manager service using the `ManagerRegistry::resetService()` + method throws an exception * removed the `DoctrineParserCache` class 3.1.0 From 731065a2e146546e8e65c749a4ae2734cef89cba Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Sat, 20 May 2017 07:49:03 +0200 Subject: [PATCH 0040/1099] [MonologBridge] remove deprecated features --- src/Symfony/Bridge/Monolog/CHANGELOG.md | 8 +++ .../Monolog/Formatter/ConsoleFormatter.php | 18 +----- .../Bridge/Monolog/Handler/DebugHandler.php | 64 ------------------- .../Bridge/Monolog/Tests/LoggerTest.php | 50 --------------- 4 files changed, 9 insertions(+), 131 deletions(-) delete mode 100644 src/Symfony/Bridge/Monolog/Handler/DebugHandler.php diff --git a/src/Symfony/Bridge/Monolog/CHANGELOG.md b/src/Symfony/Bridge/Monolog/CHANGELOG.md index f91d4c5d9a224..e024b186e79ee 100644 --- a/src/Symfony/Bridge/Monolog/CHANGELOG.md +++ b/src/Symfony/Bridge/Monolog/CHANGELOG.md @@ -1,6 +1,14 @@ CHANGELOG ========= +4.0.0 +----- + + * the `$format`, `$dateFormat`, `$allowInlineLineBreaks`, and `$ignoreEmptyContextAndExtra` + constructor arguments of the `ConsoleFormatter` class have been removed, use + `$options` instead + * the `DebugHandler` class has been removed + 3.3.0 ----- diff --git a/src/Symfony/Bridge/Monolog/Formatter/ConsoleFormatter.php b/src/Symfony/Bridge/Monolog/Formatter/ConsoleFormatter.php index 9b372d6e22749..3d5b70dc21c49 100644 --- a/src/Symfony/Bridge/Monolog/Formatter/ConsoleFormatter.php +++ b/src/Symfony/Bridge/Monolog/Formatter/ConsoleFormatter.php @@ -55,24 +55,8 @@ class ConsoleFormatter implements FormatterInterface * * colors: If true, the log string contains ANSI code to add color; * * multiline: If false, "context" and "extra" are dumped on one line. */ - public function __construct($options = array()) + public function __construct(array $options = array()) { - // BC Layer - if (!is_array($options)) { - @trigger_error(sprintf('The constructor arguments $format, $dateFormat, $allowInlineLineBreaks, $ignoreEmptyContextAndExtra of "%s" are deprecated since 3.3 and will be removed in 4.0. Use $options instead.', self::class), E_USER_DEPRECATED); - $args = func_get_args(); - $options = array(); - if (isset($args[0])) { - $options['format'] = $args[0]; - } - if (isset($args[1])) { - $options['date_format'] = $args[1]; - } - if (isset($args[2])) { - $options['multiline'] = $args[2]; - } - } - $this->options = array_replace(array( 'format' => self::SIMPLE_FORMAT, 'date_format' => self::SIMPLE_DATE, diff --git a/src/Symfony/Bridge/Monolog/Handler/DebugHandler.php b/src/Symfony/Bridge/Monolog/Handler/DebugHandler.php deleted file mode 100644 index 6032750ff6422..0000000000000 --- a/src/Symfony/Bridge/Monolog/Handler/DebugHandler.php +++ /dev/null @@ -1,64 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bridge\Monolog\Handler; - -@trigger_error('The '.__NAMESPACE__.'\DebugHandler class is deprecated since version 3.2 and will be removed in 4.0. Use Symfony\Bridge\Monolog\Processor\DebugProcessor instead.', E_USER_DEPRECATED); - -use Monolog\Logger; -use Monolog\Handler\TestHandler; -use Symfony\Component\HttpKernel\Log\DebugLoggerInterface; - -/** - * DebugLogger. - * - * @author Jordi Boggiano - * - * @deprecated since version 3.2, to be removed in 4.0. Use Symfony\Bridge\Monolog\Processor\DebugProcessor instead. - */ -class DebugHandler extends TestHandler implements DebugLoggerInterface -{ - /** - * {@inheritdoc} - */ - public function getLogs() - { - $records = array(); - foreach ($this->records as $record) { - $records[] = array( - 'timestamp' => $record['datetime']->getTimestamp(), - 'message' => $record['message'], - 'priority' => $record['level'], - 'priorityName' => $record['level_name'], - 'context' => $record['context'], - 'channel' => isset($record['channel']) ? $record['channel'] : '', - ); - } - - return $records; - } - - /** - * {@inheritdoc} - */ - public function countErrors() - { - $cnt = 0; - $levels = array(Logger::ERROR, Logger::CRITICAL, Logger::ALERT, Logger::EMERGENCY); - foreach ($levels as $level) { - if (isset($this->recordsByLevel[$level])) { - $cnt += count($this->recordsByLevel[$level]); - } - } - - return $cnt; - } -} diff --git a/src/Symfony/Bridge/Monolog/Tests/LoggerTest.php b/src/Symfony/Bridge/Monolog/Tests/LoggerTest.php index c24c7a4133baf..6c04762404f33 100644 --- a/src/Symfony/Bridge/Monolog/Tests/LoggerTest.php +++ b/src/Symfony/Bridge/Monolog/Tests/LoggerTest.php @@ -13,24 +13,11 @@ use Monolog\Handler\TestHandler; use PHPUnit\Framework\TestCase; -use Symfony\Bridge\Monolog\Handler\DebugHandler; use Symfony\Bridge\Monolog\Processor\DebugProcessor; use Symfony\Bridge\Monolog\Logger; class LoggerTest extends TestCase { - /** - * @group legacy - */ - public function testGetLogsWithDebugHandler() - { - $handler = new DebugHandler(); - $logger = new Logger(__METHOD__, array($handler)); - - $this->assertTrue($logger->error('error message')); - $this->assertSame(1, count($logger->getLogs())); - } - public function testGetLogsWithoutDebugProcessor() { $handler = new TestHandler(); @@ -40,43 +27,6 @@ public function testGetLogsWithoutDebugProcessor() $this->assertSame(array(), $logger->getLogs()); } - /** - * @group legacy - */ - public function testCountErrorsWithDebugHandler() - { - $handler = new DebugHandler(); - $logger = new Logger(__METHOD__, array($handler)); - - $this->assertTrue($logger->debug('test message')); - $this->assertTrue($logger->info('test message')); - $this->assertTrue($logger->notice('test message')); - $this->assertTrue($logger->warning('test message')); - - $this->assertTrue($logger->error('test message')); - $this->assertTrue($logger->critical('test message')); - $this->assertTrue($logger->alert('test message')); - $this->assertTrue($logger->emergency('test message')); - - $this->assertSame(4, $logger->countErrors()); - } - - /** - * @group legacy - */ - public function testGetLogsWithDebugHandler2() - { - $logger = new Logger('test'); - $logger->pushHandler(new DebugHandler()); - - $logger->addInfo('test'); - $this->assertCount(1, $logger->getLogs()); - list($record) = $logger->getLogs(); - - $this->assertEquals('test', $record['message']); - $this->assertEquals(Logger::INFO, $record['priority']); - } - public function testCountErrorsWithoutDebugProcessor() { $handler = new TestHandler(); From 80f329c3302394e5f93a7dd5e500e11f012fa1ee Mon Sep 17 00:00:00 2001 From: Michael Babker Date: Fri, 19 May 2017 07:11:15 -0500 Subject: [PATCH 0041/1099] Remove deprecated console.exception event --- src/Symfony/Component/Console/Application.php | 14 ---- src/Symfony/Component/Console/CHANGELOG.md | 2 + .../Component/Console/ConsoleEvents.php | 15 ---- .../Console/Event/ConsoleExceptionEvent.php | 71 ------------------- .../Console/Tests/ApplicationTest.php | 28 -------- 5 files changed, 2 insertions(+), 128 deletions(-) delete mode 100644 src/Symfony/Component/Console/Event/ConsoleExceptionEvent.php diff --git a/src/Symfony/Component/Console/Application.php b/src/Symfony/Component/Console/Application.php index aed8615e53741..14887c75e44c7 100644 --- a/src/Symfony/Component/Console/Application.php +++ b/src/Symfony/Component/Console/Application.php @@ -35,7 +35,6 @@ use Symfony\Component\Console\Helper\FormatterHelper; use Symfony\Component\Console\Event\ConsoleCommandEvent; use Symfony\Component\Console\Event\ConsoleErrorEvent; -use Symfony\Component\Console\Event\ConsoleExceptionEvent; use Symfony\Component\Console\Event\ConsoleTerminateEvent; use Symfony\Component\Console\Exception\CommandNotFoundException; use Symfony\Component\Console\Exception\LogicException; @@ -119,10 +118,6 @@ public function run(InputInterface $input = null, OutputInterface $output = null $output = new ConsoleOutput(); } - if (null !== $this->dispatcher && $this->dispatcher->hasListeners(ConsoleEvents::EXCEPTION)) { - @trigger_error(sprintf('The "ConsoleEvents::EXCEPTION" event is deprecated since Symfony 3.3 and will be removed in 4.0. Listen to the "ConsoleEvents::ERROR" event instead.'), E_USER_DEPRECATED); - } - $this->configureIO($input, $output); try { @@ -822,15 +817,6 @@ protected function doRunCommand(Command $command, InputInterface $input, OutputI } catch (\Throwable $e) { } if (null !== $e) { - if ($this->dispatcher->hasListeners(ConsoleEvents::EXCEPTION)) { - $x = $e instanceof \Exception ? $e : new FatalThrowableError($e); - $event = new ConsoleExceptionEvent($command, $input, $output, $x, $x->getCode()); - $this->dispatcher->dispatch(ConsoleEvents::EXCEPTION, $event); - - if ($x !== $event->getException()) { - $e = $event->getException(); - } - } $event = new ConsoleErrorEvent($input, $output, $e, $command); $this->dispatcher->dispatch(ConsoleEvents::ERROR, $event); $e = $event->getError(); diff --git a/src/Symfony/Component/Console/CHANGELOG.md b/src/Symfony/Component/Console/CHANGELOG.md index 5b1c378868ced..3952997e64ee0 100644 --- a/src/Symfony/Component/Console/CHANGELOG.md +++ b/src/Symfony/Component/Console/CHANGELOG.md @@ -7,6 +7,8 @@ CHANGELOG * removed `QuestionHelper::setInputStream()/getInputStream()` * removed `Application::getTerminalWidth()/getTerminalHeight()` and `Application::setTerminalDimensions()/getTerminalDimensions()` +* removed `ConsoleExceptionEvent` +* removed `ConsoleEvents::EXCEPTION` 3.3.0 ----- diff --git a/src/Symfony/Component/Console/ConsoleEvents.php b/src/Symfony/Component/Console/ConsoleEvents.php index 7f7d4a3f28ff0..a777936fbc677 100644 --- a/src/Symfony/Component/Console/ConsoleEvents.php +++ b/src/Symfony/Component/Console/ConsoleEvents.php @@ -39,21 +39,6 @@ final class ConsoleEvents */ const TERMINATE = 'console.terminate'; - /** - * The EXCEPTION event occurs when an uncaught exception appears - * while executing Command#run(). - * - * This event allows you to deal with the exception or - * to modify the thrown exception. - * - * @Event("Symfony\Component\Console\Event\ConsoleExceptionEvent") - * - * @var string - * - * @deprecated The console.exception event is deprecated since version 3.3 and will be removed in 4.0. Use the console.error event instead. - */ - const EXCEPTION = 'console.exception'; - /** * The ERROR event occurs when an uncaught exception or error appears. * diff --git a/src/Symfony/Component/Console/Event/ConsoleExceptionEvent.php b/src/Symfony/Component/Console/Event/ConsoleExceptionEvent.php deleted file mode 100644 index a31797fa35038..0000000000000 --- a/src/Symfony/Component/Console/Event/ConsoleExceptionEvent.php +++ /dev/null @@ -1,71 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Event; - -@trigger_error(sprintf('The "%s" class is deprecated since version 3.3 and will be removed in 4.0. Use the ConsoleErrorEvent instead.', ConsoleExceptionEvent::class), E_USER_DEPRECATED); - -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Output\OutputInterface; - -/** - * Allows to handle exception thrown in a command. - * - * @author Fabien Potencier - * - * @deprecated since version 3.3, to be removed in 4.0. Use ConsoleErrorEvent instead. - */ -class ConsoleExceptionEvent extends ConsoleEvent -{ - private $exception; - private $exitCode; - - public function __construct(Command $command, InputInterface $input, OutputInterface $output, \Exception $exception, $exitCode) - { - parent::__construct($command, $input, $output); - - $this->setException($exception); - $this->exitCode = (int) $exitCode; - } - - /** - * Returns the thrown exception. - * - * @return \Exception The thrown exception - */ - public function getException() - { - return $this->exception; - } - - /** - * Replaces the thrown exception. - * - * This exception will be thrown if no response is set in the event. - * - * @param \Exception $exception The thrown exception - */ - public function setException(\Exception $exception) - { - $this->exception = $exception; - } - - /** - * Gets the exit code. - * - * @return int The command exit code - */ - public function getExitCode() - { - return $this->exitCode; - } -} diff --git a/src/Symfony/Component/Console/Tests/ApplicationTest.php b/src/Symfony/Component/Console/Tests/ApplicationTest.php index 5d0d5cce6351b..ea74f28a4d031 100644 --- a/src/Symfony/Component/Console/Tests/ApplicationTest.php +++ b/src/Symfony/Component/Console/Tests/ApplicationTest.php @@ -28,7 +28,6 @@ use Symfony\Component\Console\Tester\ApplicationTester; use Symfony\Component\Console\Event\ConsoleCommandEvent; use Symfony\Component\Console\Event\ConsoleErrorEvent; -use Symfony\Component\Console\Event\ConsoleExceptionEvent; use Symfony\Component\Console\Event\ConsoleTerminateEvent; use Symfony\Component\Console\Exception\CommandNotFoundException; use Symfony\Component\EventDispatcher\EventDispatcher; @@ -1107,33 +1106,6 @@ public function testConsoleErrorEventIsTriggeredOnCommandNotFound() $this->assertEquals(1, $tester->getStatusCode()); } - /** - * @group legacy - * @expectedDeprecation The "ConsoleEvents::EXCEPTION" event is deprecated since Symfony 3.3 and will be removed in 4.0. Listen to the "ConsoleEvents::ERROR" event instead. - */ - public function testLegacyExceptionListenersAreStillTriggered() - { - $dispatcher = $this->getDispatcher(); - $dispatcher->addListener('console.exception', function (ConsoleExceptionEvent $event) { - $event->getOutput()->write('caught.'); - - $event->setException(new \RuntimeException('replaced in caught.')); - }); - - $application = new Application(); - $application->setDispatcher($dispatcher); - $application->setAutoExit(false); - - $application->register('foo')->setCode(function (InputInterface $input, OutputInterface $output) { - throw new \RuntimeException('foo'); - }); - - $tester = new ApplicationTester($application); - $tester->run(array('command' => 'foo')); - $this->assertContains('before.caught.error.after.', $tester->getDisplay()); - $this->assertContains('replaced in caught.', $tester->getDisplay()); - } - /** * @requires PHP 7 */ From c783e1e7f09dc50825dd0565c64fd5ed3a142ab5 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Sun, 21 May 2017 15:20:06 +0200 Subject: [PATCH 0042/1099] forward compatibility with Symfony 4 --- .../DataCollector/SecurityDataCollector.php | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Bundle/SecurityBundle/DataCollector/SecurityDataCollector.php b/src/Symfony/Bundle/SecurityBundle/DataCollector/SecurityDataCollector.php index 6831e94d047af..508d98b52f67e 100644 --- a/src/Symfony/Bundle/SecurityBundle/DataCollector/SecurityDataCollector.php +++ b/src/Symfony/Bundle/SecurityBundle/DataCollector/SecurityDataCollector.php @@ -12,6 +12,7 @@ namespace Symfony\Bundle\SecurityBundle\DataCollector; use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface; +use Symfony\Component\Security\Core\Role\Role; use Symfony\Component\Security\Core\Role\RoleHierarchyInterface; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; @@ -110,6 +111,14 @@ public function collect(Request $request, Response $response, \Exception $except // fail silently when the logout URL cannot be generated } + $extractRoles = function ($role) { + if (!$role instanceof RoleInterface && !$role instanceof Role) { + throw new \InvalidArgumentException(sprintf('Roles must be instances of %s or %s (%s given).', RoleInterface::class, Role::class, is_object($role) ? get_class($role) : gettype($role))); + } + + return $role->getRole(); + }; + $this->data = array( 'enabled' => true, 'authenticated' => $token->isAuthenticated(), @@ -117,8 +126,8 @@ public function collect(Request $request, Response $response, \Exception $except 'token_class' => $this->hasVarDumper ? new ClassStub(get_class($token)) : get_class($token), 'logout_url' => $logoutUrl, 'user' => $token->getUsername(), - 'roles' => array_map(function (RoleInterface $role) { return $role->getRole(); }, $assignedRoles), - 'inherited_roles' => array_map(function (RoleInterface $role) { return $role->getRole(); }, $inheritedRoles), + 'roles' => array_map($extractRoles, $assignedRoles), + 'inherited_roles' => array_map($extractRoles, $inheritedRoles), 'supports_role_hierarchy' => null !== $this->roleHierarchy, ); } From 946066cc2982146fcd51786678f7509b1cfb4eae Mon Sep 17 00:00:00 2001 From: Maxime Steinhausser Date: Sun, 21 May 2017 14:08:16 +0200 Subject: [PATCH 0043/1099] [Finder] Deprecate FilterIterator --- UPGRADE-3.4.md | 7 +++++++ UPGRADE-4.0.md | 2 ++ src/Symfony/Component/Finder/CHANGELOG.md | 5 +++++ src/Symfony/Component/Finder/Iterator/FilterIterator.php | 2 ++ .../Component/Finder/Tests/Iterator/FilterIteratorTest.php | 2 ++ 5 files changed, 18 insertions(+) diff --git a/UPGRADE-3.4.md b/UPGRADE-3.4.md index 27a069cb1883b..29a810c8703e5 100644 --- a/UPGRADE-3.4.md +++ b/UPGRADE-3.4.md @@ -1,6 +1,13 @@ UPGRADE FROM 3.3 to 3.4 ======================= +Finder +------ + + * The `Symfony\Component\Finder\Iterator\FilterIterator` class has been + deprecated and will be removed in 4.0 as it used to fix a bug which existed + before version 5.5.23/5.6.7 + Validator --------- diff --git a/UPGRADE-4.0.md b/UPGRADE-4.0.md index ecfd8b090ed93..e4d9df88d675b 100644 --- a/UPGRADE-4.0.md +++ b/UPGRADE-4.0.md @@ -145,6 +145,8 @@ Finder ------ * The `ExceptionInterface` has been removed. + * The `Symfony\Component\Finder\Iterator\FilterIterator` class has been + removed as it used to fix a bug which existed before version 5.5.23/5.6.7 Form ---- diff --git a/src/Symfony/Component/Finder/CHANGELOG.md b/src/Symfony/Component/Finder/CHANGELOG.md index cf19de6930ed5..1c6419658bff5 100644 --- a/src/Symfony/Component/Finder/CHANGELOG.md +++ b/src/Symfony/Component/Finder/CHANGELOG.md @@ -1,6 +1,11 @@ CHANGELOG ========= +3.4.0 +----- + + * deprecated `Symfony\Component\Finder\Iterator\FilterIterator` + 3.3.0 ----- diff --git a/src/Symfony/Component/Finder/Iterator/FilterIterator.php b/src/Symfony/Component/Finder/Iterator/FilterIterator.php index 3c3c3fbec0218..a182f10eb8ded 100644 --- a/src/Symfony/Component/Finder/Iterator/FilterIterator.php +++ b/src/Symfony/Component/Finder/Iterator/FilterIterator.php @@ -18,6 +18,8 @@ * @see https://bugs.php.net/68557 * * @author Alex Bogomazov + * + * @deprecated since 3.4, to be removed in 4.0. */ abstract class FilterIterator extends \FilterIterator { diff --git a/src/Symfony/Component/Finder/Tests/Iterator/FilterIteratorTest.php b/src/Symfony/Component/Finder/Tests/Iterator/FilterIteratorTest.php index 4f12d142e7f27..8b1a4482bae2e 100644 --- a/src/Symfony/Component/Finder/Tests/Iterator/FilterIteratorTest.php +++ b/src/Symfony/Component/Finder/Tests/Iterator/FilterIteratorTest.php @@ -13,6 +13,8 @@ /** * @author Alex Bogomazov + * + * @group legacy */ class FilterIteratorTest extends RealIteratorTestCase { From 8baa6894dae1c286b607ec5e8c16a1d82416750b Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Sat, 20 May 2017 07:52:00 +0200 Subject: [PATCH 0044/1099] [PhpUnitBridge] remove deprecated features --- src/Symfony/Bridge/PhpUnit/CHANGELOG.md | 13 ++++++++++ .../Legacy/SymfonyTestsListenerTrait.php | 25 ------------------- 2 files changed, 13 insertions(+), 25 deletions(-) create mode 100644 src/Symfony/Bridge/PhpUnit/CHANGELOG.md diff --git a/src/Symfony/Bridge/PhpUnit/CHANGELOG.md b/src/Symfony/Bridge/PhpUnit/CHANGELOG.md new file mode 100644 index 0000000000000..b4ef6edbf5796 --- /dev/null +++ b/src/Symfony/Bridge/PhpUnit/CHANGELOG.md @@ -0,0 +1,13 @@ +CHANGELOG +========= + +4.0.0 +----- + + * support for the `testLegacy` prefix in method names to mark a test as legacy + has been dropped, use the `@group legacy` notation instead + * support for the `Legacy` prefix in class names to mark tests as legacy has + been dropped, use the `@group legacy` notation instead + * support for passing an array of mocked namespaces not indexed by the mock + feature to the constructor of the `SymfonyTestsListenerTrait` class was + dropped diff --git a/src/Symfony/Bridge/PhpUnit/Legacy/SymfonyTestsListenerTrait.php b/src/Symfony/Bridge/PhpUnit/Legacy/SymfonyTestsListenerTrait.php index 173a0fa82fd93..83a6ff7d5c27a 100644 --- a/src/Symfony/Bridge/PhpUnit/Legacy/SymfonyTestsListenerTrait.php +++ b/src/Symfony/Bridge/PhpUnit/Legacy/SymfonyTestsListenerTrait.php @@ -56,16 +56,10 @@ public function __construct(array $mockedNamespaces = array()) Blacklist::$blacklistedClassNames['\Symfony\Bridge\PhpUnit\Legacy\SymfonyTestsListenerTrait'] = 1; } - $warn = false; foreach ($mockedNamespaces as $type => $namespaces) { if (!is_array($namespaces)) { $namespaces = array($namespaces); } - if (is_int($type)) { - // @deprecated BC with v2.8 to v3.0 - $type = 'time-sensitive'; - $warn = true; - } if ('time-sensitive' === $type) { foreach ($namespaces as $ns) { ClockMock::register($ns.'\DummyClass'); @@ -81,9 +75,6 @@ public function __construct(array $mockedNamespaces = array()) $this->state = -2; } else { self::$globallyEnabled = true; - if ($warn) { - echo "Clock-mocked namespaces for SymfonyTestsListener need to be nested in a \"time-sensitive\" key. This will be enforced in Symfony 4.0.\n"; - } } } @@ -285,22 +276,6 @@ public function endTest($test, $time) DnsMock::withMockedHosts(array()); } } - - if (($test instanceof \PHPUnit_Framework_TestCase || $test instanceof TestCase) && 0 === strpos($test->getName(), 'testLegacy') && !isset($this->testsWithWarnings[$test->getName()]) && !in_array('legacy', $groups, true)) { - $result = $test->getTestResultObject(); - - if (method_exists($result, 'addWarning')) { - $result->addWarning($test, new $Warning('Using the "testLegacy" prefix to mark tests as legacy is deprecated since version 3.3 and will be removed in 4.0. Use the "@group legacy" notation instead to add the test to the legacy group.'), $time); - } - } - - if (($test instanceof \PHPUnit_Framework_TestCase || $test instanceof TestCase) && strpos($className, '\Legacy') && !isset($this->testsWithWarnings[$test->getName()]) && !in_array('legacy', $classGroups, true)) { - $result = $test->getTestResultObject(); - - if (method_exists($result, 'addWarning')) { - $result->addWarning($test, new $Warning('Using the "Legacy" prefix to mark all tests of a class as legacy is deprecated since version 3.3 and will be removed in 4.0. Use the "@group legacy" notation instead to add the test to the legacy group.'), $time); - } - } } public function handleError($type, $msg, $file, $line, $context) From ce519b6e444abb12174fbd57ec0936ea4961ab56 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Sun, 21 May 2017 08:14:41 +0200 Subject: [PATCH 0045/1099] fixed typo --- src/Symfony/Component/HttpKernel/Kernel.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/HttpKernel/Kernel.php b/src/Symfony/Component/HttpKernel/Kernel.php index 2af2ae3b640e6..69b27194ddb48 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -61,7 +61,7 @@ abstract class Kernel implements KernelInterface, TerminableInterface const VERSION = '4.0.0-DEV'; const VERSION_ID = 40000; - const MAJOR_VERSION = 0; + const MAJOR_VERSION = 4; const MINOR_VERSION = 0; const RELEASE_VERSION = 0; const EXTRA_VERSION = 'DEV'; From 23975048f88e58d1e1b17a00e7f3f80722237278 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Sun, 21 May 2017 11:46:47 +0200 Subject: [PATCH 0046/1099] [Security] remove deprecated features --- .../DataCollector/SecurityDataCollector.php | 13 +---- src/Symfony/Component/Security/CHANGELOG.md | 4 ++ .../Authentication/Token/AbstractToken.php | 7 +-- .../Token/PreAuthenticatedToken.php | 8 +-- .../Authentication/Token/TokenInterface.php | 4 +- .../Token/UsernamePasswordToken.php | 8 +-- .../Authorization/AccessDecisionManager.php | 14 ----- .../DebugAccessDecisionManager.php | 36 ------------ .../TraceableAccessDecisionManager.php | 17 ------ .../Core/Authorization/Voter/RoleVoter.php | 4 +- .../Component/Security/Core/Role/Role.php | 6 +- .../Core/Role/RoleHierarchyInterface.php | 4 +- .../Security/Core/Role/RoleInterface.php | 37 ------------ .../AbstractFormLoginAuthenticator.php | 33 ----------- .../FormLoginAuthenticatorTest.php | 58 ++----------------- 15 files changed, 32 insertions(+), 221 deletions(-) delete mode 100644 src/Symfony/Component/Security/Core/Authorization/DebugAccessDecisionManager.php delete mode 100644 src/Symfony/Component/Security/Core/Role/RoleInterface.php diff --git a/src/Symfony/Bundle/SecurityBundle/DataCollector/SecurityDataCollector.php b/src/Symfony/Bundle/SecurityBundle/DataCollector/SecurityDataCollector.php index 508d98b52f67e..0fcf71a99f358 100644 --- a/src/Symfony/Bundle/SecurityBundle/DataCollector/SecurityDataCollector.php +++ b/src/Symfony/Bundle/SecurityBundle/DataCollector/SecurityDataCollector.php @@ -18,7 +18,6 @@ use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\DataCollector\DataCollector; use Symfony\Component\HttpKernel\DataCollector\LateDataCollectorInterface; -use Symfony\Component\Security\Core\Role\RoleInterface; use Symfony\Component\Security\Http\Logout\LogoutUrlGenerator; use Symfony\Component\Security\Core\Authorization\AccessDecisionManagerInterface; use Symfony\Component\Security\Core\Authorization\TraceableAccessDecisionManager; @@ -111,14 +110,6 @@ public function collect(Request $request, Response $response, \Exception $except // fail silently when the logout URL cannot be generated } - $extractRoles = function ($role) { - if (!$role instanceof RoleInterface && !$role instanceof Role) { - throw new \InvalidArgumentException(sprintf('Roles must be instances of %s or %s (%s given).', RoleInterface::class, Role::class, is_object($role) ? get_class($role) : gettype($role))); - } - - return $role->getRole(); - }; - $this->data = array( 'enabled' => true, 'authenticated' => $token->isAuthenticated(), @@ -126,8 +117,8 @@ public function collect(Request $request, Response $response, \Exception $except 'token_class' => $this->hasVarDumper ? new ClassStub(get_class($token)) : get_class($token), 'logout_url' => $logoutUrl, 'user' => $token->getUsername(), - 'roles' => array_map($extractRoles, $assignedRoles), - 'inherited_roles' => array_map($extractRoles, $inheritedRoles), + 'roles' => array_map(function (Role $role) { return $role->getRole(); }, $assignedRoles), + 'inherited_roles' => array_map(function (Role $role) { return $role->getRole(); }, $inheritedRoles), 'supports_role_hierarchy' => null !== $this->roleHierarchy, ); } diff --git a/src/Symfony/Component/Security/CHANGELOG.md b/src/Symfony/Component/Security/CHANGELOG.md index a8ec0d017e026..905c499194b7c 100644 --- a/src/Symfony/Component/Security/CHANGELOG.md +++ b/src/Symfony/Component/Security/CHANGELOG.md @@ -4,6 +4,10 @@ CHANGELOG 4.0.0 ----- + * The `AbstractFormLoginAuthenticator::onAuthenticationSuccess()` was removed. + You should implement this method yourself in your concrete authenticator. + * removed the `AccessDecisionManager::setVoters()` method + * removed the `RoleInterface` * added a sixth `string $context` argument to`LogoutUrlGenerator::registerListener()` 3.3.0 diff --git a/src/Symfony/Component/Security/Core/Authentication/Token/AbstractToken.php b/src/Symfony/Component/Security/Core/Authentication/Token/AbstractToken.php index 0eee6d94a41c6..d8aca92109300 100644 --- a/src/Symfony/Component/Security/Core/Authentication/Token/AbstractToken.php +++ b/src/Symfony/Component/Security/Core/Authentication/Token/AbstractToken.php @@ -11,7 +11,6 @@ namespace Symfony\Component\Security\Core\Authentication\Token; -use Symfony\Component\Security\Core\Role\RoleInterface; use Symfony\Component\Security\Core\Role\Role; use Symfony\Component\Security\Core\User\UserInterface; use Symfony\Component\Security\Core\User\AdvancedUserInterface; @@ -33,7 +32,7 @@ abstract class AbstractToken implements TokenInterface /** * Constructor. * - * @param (RoleInterface|string)[] $roles An array of roles + * @param (Role|string)[] $roles An array of roles * * @throws \InvalidArgumentException */ @@ -42,8 +41,8 @@ public function __construct(array $roles = array()) foreach ($roles as $role) { if (is_string($role)) { $role = new Role($role); - } elseif (!$role instanceof RoleInterface) { - throw new \InvalidArgumentException(sprintf('$roles must be an array of strings, or RoleInterface instances, but got %s.', gettype($role))); + } elseif (!$role instanceof Role) { + throw new \InvalidArgumentException(sprintf('$roles must be an array of strings, or Role instances, but got %s.', gettype($role))); } $this->roles[] = $role; diff --git a/src/Symfony/Component/Security/Core/Authentication/Token/PreAuthenticatedToken.php b/src/Symfony/Component/Security/Core/Authentication/Token/PreAuthenticatedToken.php index 395706cb288d8..2d0a22b025505 100644 --- a/src/Symfony/Component/Security/Core/Authentication/Token/PreAuthenticatedToken.php +++ b/src/Symfony/Component/Security/Core/Authentication/Token/PreAuthenticatedToken.php @@ -24,10 +24,10 @@ class PreAuthenticatedToken extends AbstractToken /** * Constructor. * - * @param string|object $user The user can be a UserInterface instance, or an object implementing a __toString method or the username as a regular string - * @param mixed $credentials The user credentials - * @param string $providerKey The provider key - * @param (RoleInterface|string)[] $roles An array of roles + * @param string|object $user The user can be a UserInterface instance, or an object implementing a __toString method or the username as a regular string + * @param mixed $credentials The user credentials + * @param string $providerKey The provider key + * @param (Role|string)[] $roles An array of roles */ public function __construct($user, $credentials, $providerKey, array $roles = array()) { diff --git a/src/Symfony/Component/Security/Core/Authentication/Token/TokenInterface.php b/src/Symfony/Component/Security/Core/Authentication/Token/TokenInterface.php index 4e1dd7b2fc46b..bb5711ee89107 100644 --- a/src/Symfony/Component/Security/Core/Authentication/Token/TokenInterface.php +++ b/src/Symfony/Component/Security/Core/Authentication/Token/TokenInterface.php @@ -11,7 +11,7 @@ namespace Symfony\Component\Security\Core\Authentication\Token; -use Symfony\Component\Security\Core\Role\RoleInterface; +use Symfony\Component\Security\Core\Role\Role; /** * TokenInterface is the interface for the user authentication information. @@ -33,7 +33,7 @@ public function __toString(); /** * Returns the user roles. * - * @return RoleInterface[] An array of RoleInterface instances + * @return Role[] An array of Role instances */ public function getRoles(); diff --git a/src/Symfony/Component/Security/Core/Authentication/Token/UsernamePasswordToken.php b/src/Symfony/Component/Security/Core/Authentication/Token/UsernamePasswordToken.php index 980a8139939c7..50a7519d89100 100644 --- a/src/Symfony/Component/Security/Core/Authentication/Token/UsernamePasswordToken.php +++ b/src/Symfony/Component/Security/Core/Authentication/Token/UsernamePasswordToken.php @@ -24,10 +24,10 @@ class UsernamePasswordToken extends AbstractToken /** * Constructor. * - * @param string|object $user The username (like a nickname, email address, etc.), or a UserInterface instance or an object implementing a __toString method - * @param string $credentials This usually is the password of the user - * @param string $providerKey The provider key - * @param (RoleInterface|string)[] $roles An array of roles + * @param string|object $user The username (like a nickname, email address, etc.), or a UserInterface instance or an object implementing a __toString method + * @param string $credentials This usually is the password of the user + * @param string $providerKey The provider key + * @param (Role|string)[] $roles An array of roles * * @throws \InvalidArgumentException */ diff --git a/src/Symfony/Component/Security/Core/Authorization/AccessDecisionManager.php b/src/Symfony/Component/Security/Core/Authorization/AccessDecisionManager.php index 431597940dd9a..96900da87fa2b 100644 --- a/src/Symfony/Component/Security/Core/Authorization/AccessDecisionManager.php +++ b/src/Symfony/Component/Security/Core/Authorization/AccessDecisionManager.php @@ -52,20 +52,6 @@ public function __construct($voters = array(), $strategy = self::STRATEGY_AFFIRM $this->allowIfEqualGrantedDeniedDecisions = (bool) $allowIfEqualGrantedDeniedDecisions; } - /** - * Configures the voters. - * - * @param VoterInterface[] $voters An array of VoterInterface instances - * - * @deprecated since version 3.3, to be removed in 4.0. Pass the voters to the constructor instead. - */ - public function setVoters(array $voters) - { - @trigger_error(sprintf('The %s() method is deprecated since version 3.3 and will be removed in 4.0. Pass the voters to the constructor instead.', __METHOD__), E_USER_DEPRECATED); - - $this->voters = $voters; - } - /** * {@inheritdoc} */ diff --git a/src/Symfony/Component/Security/Core/Authorization/DebugAccessDecisionManager.php b/src/Symfony/Component/Security/Core/Authorization/DebugAccessDecisionManager.php deleted file mode 100644 index aaf04a4fb00cc..0000000000000 --- a/src/Symfony/Component/Security/Core/Authorization/DebugAccessDecisionManager.php +++ /dev/null @@ -1,36 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Security\Core\Authorization; - -use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; - -class_exists(TraceableAccessDecisionManager::class); - -if (false) { - /** - * This is a placeholder for the old class, that got renamed; this is not a BC break since the class is internal, this - * placeholder is here just to help backward compatibility with older SecurityBundle versions. - * - * @deprecated The DebugAccessDecisionManager class has been renamed and is deprecated since version 3.3 and will be removed in 4.0. Use the TraceableAccessDecisionManager class instead. - * - * @internal - */ - class DebugAccessDecisionManager implements AccessDecisionManagerInterface - { - /** - * {@inheritdoc} - */ - public function decide(TokenInterface $token, array $attributes, $object = null) - { - } - } -} diff --git a/src/Symfony/Component/Security/Core/Authorization/TraceableAccessDecisionManager.php b/src/Symfony/Component/Security/Core/Authorization/TraceableAccessDecisionManager.php index 1e3ed546c8aee..8430c861a96fa 100644 --- a/src/Symfony/Component/Security/Core/Authorization/TraceableAccessDecisionManager.php +++ b/src/Symfony/Component/Security/Core/Authorization/TraceableAccessDecisionManager.php @@ -60,23 +60,6 @@ public function decide(TokenInterface $token, array $attributes, $object = null) return $result; } - /** - * {@inheritdoc} - * - * @deprecated since version 3.3, to be removed in 4.0. Pass voters to the decorated AccessDecisionManager instead. - */ - public function setVoters(array $voters) - { - @trigger_error(sprintf('The %s() method is deprecated since version 3.3 and will be removed in 4.0. Pass voters to the decorated AccessDecisionManager instead.', __METHOD__), E_USER_DEPRECATED); - - if (!method_exists($this->manager, 'setVoters')) { - return; - } - - $this->voters = $voters; - $this->manager->setVoters($voters); - } - /** * @return string */ diff --git a/src/Symfony/Component/Security/Core/Authorization/Voter/RoleVoter.php b/src/Symfony/Component/Security/Core/Authorization/Voter/RoleVoter.php index d5f31760793d8..047224e50349a 100644 --- a/src/Symfony/Component/Security/Core/Authorization/Voter/RoleVoter.php +++ b/src/Symfony/Component/Security/Core/Authorization/Voter/RoleVoter.php @@ -12,7 +12,7 @@ namespace Symfony\Component\Security\Core\Authorization\Voter; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; -use Symfony\Component\Security\Core\Role\RoleInterface; +use Symfony\Component\Security\Core\Role\Role; /** * RoleVoter votes if any attribute starts with a given prefix. @@ -42,7 +42,7 @@ public function vote(TokenInterface $token, $subject, array $attributes) $roles = $this->extractRoles($token); foreach ($attributes as $attribute) { - if ($attribute instanceof RoleInterface) { + if ($attribute instanceof Role) { $attribute = $attribute->getRole(); } diff --git a/src/Symfony/Component/Security/Core/Role/Role.php b/src/Symfony/Component/Security/Core/Role/Role.php index 7cb4698ea84a2..d2e25d9958ccc 100644 --- a/src/Symfony/Component/Security/Core/Role/Role.php +++ b/src/Symfony/Component/Security/Core/Role/Role.php @@ -16,7 +16,7 @@ * * @author Fabien Potencier */ -class Role implements RoleInterface +class Role { private $role; @@ -31,7 +31,9 @@ public function __construct($role) } /** - * {@inheritdoc} + * Returns a string representation of the role. + * + * @return string */ public function getRole() { diff --git a/src/Symfony/Component/Security/Core/Role/RoleHierarchyInterface.php b/src/Symfony/Component/Security/Core/Role/RoleHierarchyInterface.php index c994009cb4b40..1a86db9901603 100644 --- a/src/Symfony/Component/Security/Core/Role/RoleHierarchyInterface.php +++ b/src/Symfony/Component/Security/Core/Role/RoleHierarchyInterface.php @@ -24,9 +24,9 @@ interface RoleHierarchyInterface * Reachable roles are the roles directly assigned but also all roles that * are transitively reachable from them in the role hierarchy. * - * @param RoleInterface[] $roles An array of directly assigned roles + * @param Role[] $roles An array of directly assigned roles * - * @return RoleInterface[] An array of all reachable roles + * @return Role[] An array of all reachable roles */ public function getReachableRoles(array $roles); } diff --git a/src/Symfony/Component/Security/Core/Role/RoleInterface.php b/src/Symfony/Component/Security/Core/Role/RoleInterface.php deleted file mode 100644 index a0621baa6b4be..0000000000000 --- a/src/Symfony/Component/Security/Core/Role/RoleInterface.php +++ /dev/null @@ -1,37 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Security\Core\Role; - -/** - * RoleInterface represents a role granted to a user. - * - * A role must either have a string representation or it needs to be explicitly - * supported by at least one AccessDecisionManager. - * - * @author Fabien Potencier - * - * @deprecated The RoleInterface is deprecated since version 3.3 and will be removed in 4.0. Extend the Symfony\Component\Security\Core\Role\Role class instead. - */ -interface RoleInterface -{ - /** - * Returns the role. - * - * This method returns a string representation whenever possible. - * - * When the role cannot be represented with sufficient precision by a - * string, it should return null. - * - * @return string|null A string representation of the role, or null - */ - public function getRole(); -} diff --git a/src/Symfony/Component/Security/Guard/Authenticator/AbstractFormLoginAuthenticator.php b/src/Symfony/Component/Security/Guard/Authenticator/AbstractFormLoginAuthenticator.php index f99900b175ef4..4496969139e78 100644 --- a/src/Symfony/Component/Security/Guard/Authenticator/AbstractFormLoginAuthenticator.php +++ b/src/Symfony/Component/Security/Guard/Authenticator/AbstractFormLoginAuthenticator.php @@ -15,7 +15,6 @@ use Symfony\Component\Security\Guard\AbstractGuardAuthenticator; use Symfony\Component\HttpFoundation\RedirectResponse; use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; use Symfony\Component\Security\Core\Exception\AuthenticationException; use Symfony\Component\Security\Core\Security; use Symfony\Component\Security\Http\Util\TargetPathTrait; @@ -55,38 +54,6 @@ public function onAuthenticationFailure(Request $request, AuthenticationExceptio return new RedirectResponse($url); } - /** - * Override to change what happens after successful authentication. - * - * @param Request $request - * @param TokenInterface $token - * @param string $providerKey - * - * @return RedirectResponse - */ - 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); - - if (!method_exists($this, 'getDefaultSuccessRedirectUrl')) { - throw new \Exception(sprintf('You must implement onAuthenticationSuccess() or getDefaultSuccessRedirectUrl() in %s.', get_class($this))); - } - - $targetPath = null; - - // if the user hit a secure page and start() was called, this was - // the URL they were on, and probably where you want to redirect to - if ($request->getSession() instanceof SessionInterface) { - $targetPath = $this->getTargetPath($request->getSession(), $providerKey); - } - - if (!$targetPath) { - $targetPath = $this->getDefaultSuccessRedirectUrl(); - } - - return new RedirectResponse($targetPath); - } - public function supportsRememberMe() { return true; diff --git a/src/Symfony/Component/Security/Guard/Tests/Authenticator/FormLoginAuthenticatorTest.php b/src/Symfony/Component/Security/Guard/Tests/Authenticator/FormLoginAuthenticatorTest.php index 77d7194280c1b..1789b95d8c4ed 100644 --- a/src/Symfony/Component/Security/Guard/Tests/Authenticator/FormLoginAuthenticatorTest.php +++ b/src/Symfony/Component/Security/Guard/Tests/Authenticator/FormLoginAuthenticatorTest.php @@ -13,6 +13,7 @@ use PHPUnit\Framework\TestCase; use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; use Symfony\Component\Security\Core\Exception\AuthenticationException; use Symfony\Component\Security\Core\User\UserInterface; use Symfony\Component\Security\Core\User\UserProviderInterface; @@ -51,59 +52,6 @@ public function testAuthenticationFailureWithSession() $this->assertEquals(self::LOGIN_URL, $failureResponse->getTargetUrl()); } - /** - * @group legacy - */ - public function testAuthenticationSuccessWithoutSession() - { - $token = $this->getMockBuilder('Symfony\\Component\\Security\\Core\\Authentication\\Token\\TokenInterface') - ->disableOriginalConstructor() - ->getMock(); - - $redirectResponse = $this->authenticator->onAuthenticationSuccess($this->requestWithoutSession, $token, 'providerkey'); - - $this->assertInstanceOf('Symfony\\Component\\HttpFoundation\\RedirectResponse', $redirectResponse); - $this->assertEquals(self::DEFAULT_SUCCESS_URL, $redirectResponse->getTargetUrl()); - } - - /** - * @group legacy - */ - public function testAuthenticationSuccessWithSessionButEmpty() - { - $token = $this->getMockBuilder('Symfony\\Component\\Security\\Core\\Authentication\\Token\\TokenInterface') - ->disableOriginalConstructor() - ->getMock(); - $this->requestWithSession->getSession() - ->expects($this->once()) - ->method('get') - ->will($this->returnValue(null)); - - $redirectResponse = $this->authenticator->onAuthenticationSuccess($this->requestWithSession, $token, 'providerkey'); - - $this->assertInstanceOf('Symfony\\Component\\HttpFoundation\\RedirectResponse', $redirectResponse); - $this->assertEquals(self::DEFAULT_SUCCESS_URL, $redirectResponse->getTargetUrl()); - } - - /** - * @group legacy - */ - public function testAuthenticationSuccessWithSessionAndTarget() - { - $token = $this->getMockBuilder('Symfony\\Component\\Security\\Core\\Authentication\\Token\\TokenInterface') - ->disableOriginalConstructor() - ->getMock(); - $this->requestWithSession->getSession() - ->expects($this->once()) - ->method('get') - ->will($this->returnValue(self::CUSTOM_SUCCESS_URL)); - - $redirectResponse = $this->authenticator->onAuthenticationSuccess($this->requestWithSession, $token, 'providerkey'); - - $this->assertInstanceOf('Symfony\\Component\\HttpFoundation\\RedirectResponse', $redirectResponse); - $this->assertEquals(self::CUSTOM_SUCCESS_URL, $redirectResponse->getTargetUrl()); - } - public function testRememberMe() { $doSupport = $this->authenticator->supportsRememberMe(); @@ -156,6 +104,10 @@ class TestFormLoginAuthenticator extends AbstractFormLoginAuthenticator private $loginUrl; private $defaultSuccessRedirectUrl; + public function onAuthenticationSuccess(Request $request, TokenInterface $token, $providerKey) + { + } + /** * @param mixed $defaultSuccessRedirectUrl * From b70471a94ef58f14c4aa6ad2399143c58e20502d Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Sun, 21 May 2017 20:41:14 +0200 Subject: [PATCH 0047/1099] [VarDumper] remove deprecated features --- src/Symfony/Component/VarDumper/CHANGELOG.md | 7 +++++++ src/Symfony/Component/VarDumper/Caster/Caster.php | 5 ----- src/Symfony/Component/VarDumper/Cloner/Data.php | 12 ------------ 3 files changed, 7 insertions(+), 17 deletions(-) diff --git a/src/Symfony/Component/VarDumper/CHANGELOG.md b/src/Symfony/Component/VarDumper/CHANGELOG.md index 6b08aa77ac7b1..b763756aed02d 100644 --- a/src/Symfony/Component/VarDumper/CHANGELOG.md +++ b/src/Symfony/Component/VarDumper/CHANGELOG.md @@ -1,6 +1,13 @@ CHANGELOG ========= +4.0.0 +----- + + * support for passing `\ReflectionClass` instances to the `Caster::castObject()` + method has been dropped, pass class names as strings instead + * the `Data::getRawData()` method has been removed + 2.7.0 ----- diff --git a/src/Symfony/Component/VarDumper/Caster/Caster.php b/src/Symfony/Component/VarDumper/Caster/Caster.php index a0efa651b9258..cb62d5e31064c 100644 --- a/src/Symfony/Component/VarDumper/Caster/Caster.php +++ b/src/Symfony/Component/VarDumper/Caster/Caster.php @@ -48,11 +48,6 @@ class Caster */ public static function castObject($obj, $class, $hasDebugInfo = false) { - if ($class instanceof \ReflectionClass) { - @trigger_error(sprintf('Passing a ReflectionClass to %s() is deprecated since version 3.3 and will be unsupported in 4.0. Pass the class name as string instead.', __METHOD__), E_USER_DEPRECATED); - $hasDebugInfo = $class->hasMethod('__debugInfo'); - $class = $class->name; - } if ($hasDebugInfo) { $a = $obj->__debugInfo(); } elseif ($obj instanceof \Closure) { diff --git a/src/Symfony/Component/VarDumper/Cloner/Data.php b/src/Symfony/Component/VarDumper/Cloner/Data.php index 5a6997cf251cb..8351c3c223e74 100644 --- a/src/Symfony/Component/VarDumper/Cloner/Data.php +++ b/src/Symfony/Component/VarDumper/Cloner/Data.php @@ -165,18 +165,6 @@ public function __toString() return sprintf('%s (count=%d)', $this->getType(), count($value)); } - /** - * @return array The raw data structure - * - * @deprecated since version 3.3. Use array or object access instead. - */ - public function getRawData() - { - @trigger_error(sprintf('The %s() method is deprecated since version 3.3 and will be removed in 4.0. Use the array or object access instead.', __METHOD__)); - - return $this->data; - } - /** * Returns a depth limited clone of $this. * From 04b39a3a206db36f440e6b23d8ce52a15ad065f5 Mon Sep 17 00:00:00 2001 From: Roland Franssen Date: Thu, 18 May 2017 21:41:19 +0200 Subject: [PATCH 0048/1099] [DI] Remove deprecated isFrozen() --- .../Component/DependencyInjection/CHANGELOG.md | 5 +++++ .../Component/DependencyInjection/Container.php | 14 -------------- .../DependencyInjection/Dumper/PhpDumper.php | 10 ---------- .../DependencyInjection/Tests/ContainerTest.php | 13 ------------- .../Tests/Fixtures/php/services1-1.php | 10 ---------- .../Tests/Fixtures/php/services1.php | 10 ---------- .../Tests/Fixtures/php/services10.php | 10 ---------- .../Tests/Fixtures/php/services12.php | 10 ---------- .../Tests/Fixtures/php/services13.php | 10 ---------- .../Tests/Fixtures/php/services19.php | 10 ---------- .../Tests/Fixtures/php/services24.php | 10 ---------- .../Tests/Fixtures/php/services26.php | 10 ---------- .../Tests/Fixtures/php/services31.php | 10 ---------- .../Tests/Fixtures/php/services32.php | 10 ---------- .../Tests/Fixtures/php/services33.php | 10 ---------- .../Tests/Fixtures/php/services8.php | 10 ---------- .../Tests/Fixtures/php/services9_compiled.php | 10 ---------- .../services_dump_proxy_with_void_return_type.php | 10 ---------- .../Tests/Fixtures/php/services_locator.php | 10 ---------- .../Tests/Fixtures/php/services_private_frozen.php | 10 ---------- .../Tests/Fixtures/php/services_subscriber.php | 10 ---------- 21 files changed, 5 insertions(+), 207 deletions(-) diff --git a/src/Symfony/Component/DependencyInjection/CHANGELOG.md b/src/Symfony/Component/DependencyInjection/CHANGELOG.md index 7e03a508561de..f13b825ce79a0 100644 --- a/src/Symfony/Component/DependencyInjection/CHANGELOG.md +++ b/src/Symfony/Component/DependencyInjection/CHANGELOG.md @@ -1,6 +1,11 @@ CHANGELOG ========= +4.0.0 +----- + + * removed `Container::isFrozen` + 3.3.0 ----- diff --git a/src/Symfony/Component/DependencyInjection/Container.php b/src/Symfony/Component/DependencyInjection/Container.php index 05e038ac5cb63..5a8c6eda3420e 100644 --- a/src/Symfony/Component/DependencyInjection/Container.php +++ b/src/Symfony/Component/DependencyInjection/Container.php @@ -114,20 +114,6 @@ public function isCompiled() return $this->compiled; } - /** - * Returns true if the container parameter bag are frozen. - * - * Deprecated since 3.3, to be removed in 4.0. - * - * @return bool true if the container parameter bag are frozen, false otherwise - */ - public function isFrozen() - { - @trigger_error(sprintf('The %s() method is deprecated since version 3.3 and will be removed in 4.0. Use the isCompiled() method instead.', __METHOD__), E_USER_DEPRECATED); - - return $this->parameterBag instanceof FrozenParameterBag; - } - /** * Gets the service container parameter bag. * diff --git a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php index 66a6c56bf5cc9..4f627171be02d 100644 --- a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php +++ b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php @@ -920,16 +920,6 @@ public function isCompiled() return true; } - /*{$this->docStar} - * {@inheritdoc} - */ - public function isFrozen() - { - @trigger_error(sprintf('The %s() method is deprecated since version 3.3 and will be removed in 4.0. Use the isCompiled() method instead.', __METHOD__), E_USER_DEPRECATED); - - return true; - } - EOF; } diff --git a/src/Symfony/Component/DependencyInjection/Tests/ContainerTest.php b/src/Symfony/Component/DependencyInjection/Tests/ContainerTest.php index 99419201c6389..1fc18126393af 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/ContainerTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/ContainerTest.php @@ -83,19 +83,6 @@ public function testCompile() $this->assertEquals(array('foo' => 'bar'), $sc->getParameterBag()->all(), '->compile() copies the current parameters to the new parameter bag'); } - /** - * @group legacy - * @expectedDeprecation The Symfony\Component\DependencyInjection\Container::isFrozen() method is deprecated since version 3.3 and will be removed in 4.0. Use the isCompiled() method instead. - * @expectedDeprecation The Symfony\Component\DependencyInjection\Container::isFrozen() method is deprecated since version 3.3 and will be removed in 4.0. Use the isCompiled() method instead. - */ - public function testIsFrozen() - { - $sc = new Container(new ParameterBag(array('foo' => 'bar'))); - $this->assertFalse($sc->isFrozen(), '->isFrozen() returns false if the parameters are not frozen'); - $sc->compile(); - $this->assertTrue($sc->isFrozen(), '->isFrozen() returns true if the parameters are frozen'); - } - public function testIsCompiled() { $sc = new Container(new ParameterBag(array('foo' => 'bar'))); diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services1-1.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services1-1.php index 44631328ce606..32f488e8f342b 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services1-1.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services1-1.php @@ -48,14 +48,4 @@ public function isCompiled() { return true; } - - /** - * {@inheritdoc} - */ - public function isFrozen() - { - @trigger_error(sprintf('The %s() method is deprecated since version 3.3 and will be removed in 4.0. Use the isCompiled() method instead.', __METHOD__), E_USER_DEPRECATED); - - return true; - } } diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services1.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services1.php index 9ad021ece802b..baa1874a9ab4e 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services1.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services1.php @@ -46,14 +46,4 @@ public function isCompiled() { return true; } - - /** - * {@inheritdoc} - */ - public function isFrozen() - { - @trigger_error(sprintf('The %s() method is deprecated since version 3.3 and will be removed in 4.0. Use the isCompiled() method instead.', __METHOD__), E_USER_DEPRECATED); - - return true; - } } diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services10.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services10.php index 1cc1cc3d1644b..c4192697b16cc 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services10.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services10.php @@ -52,16 +52,6 @@ public function isCompiled() return true; } - /** - * {@inheritdoc} - */ - public function isFrozen() - { - @trigger_error(sprintf('The %s() method is deprecated since version 3.3 and will be removed in 4.0. Use the isCompiled() method instead.', __METHOD__), E_USER_DEPRECATED); - - return true; - } - /** * Gets the 'test' service. * diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services12.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services12.php index 511127c1008d3..3c20aa41a99df 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services12.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services12.php @@ -56,16 +56,6 @@ public function isCompiled() return true; } - /** - * {@inheritdoc} - */ - public function isFrozen() - { - @trigger_error(sprintf('The %s() method is deprecated since version 3.3 and will be removed in 4.0. Use the isCompiled() method instead.', __METHOD__), E_USER_DEPRECATED); - - return true; - } - /** * Gets the 'test' service. * diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services13.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services13.php index 1cffb23b7b878..da30f18e5fe82 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services13.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services13.php @@ -50,16 +50,6 @@ public function isCompiled() return true; } - /** - * {@inheritdoc} - */ - public function isFrozen() - { - @trigger_error(sprintf('The %s() method is deprecated since version 3.3 and will be removed in 4.0. Use the isCompiled() method instead.', __METHOD__), E_USER_DEPRECATED); - - return true; - } - /** * Gets the 'bar' service. * diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services19.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services19.php index 8718efe078d3d..81ab4a6ca6bf9 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services19.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services19.php @@ -51,16 +51,6 @@ public function isCompiled() return true; } - /** - * {@inheritdoc} - */ - public function isFrozen() - { - @trigger_error(sprintf('The %s() method is deprecated since version 3.3 and will be removed in 4.0. Use the isCompiled() method instead.', __METHOD__), E_USER_DEPRECATED); - - return true; - } - /** * Gets the 'service_from_anonymous_factory' service. * diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services24.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services24.php index 6ccbbd31949f6..f64c99f5d081d 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services24.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services24.php @@ -50,16 +50,6 @@ public function isCompiled() return true; } - /** - * {@inheritdoc} - */ - public function isFrozen() - { - @trigger_error(sprintf('The %s() method is deprecated since version 3.3 and will be removed in 4.0. Use the isCompiled() method instead.', __METHOD__), E_USER_DEPRECATED); - - return true; - } - /** * Gets the 'foo' service. * diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services26.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services26.php index 809d70da5e52a..08e54eed089e8 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services26.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services26.php @@ -52,16 +52,6 @@ public function isCompiled() return true; } - /** - * {@inheritdoc} - */ - public function isFrozen() - { - @trigger_error(sprintf('The %s() method is deprecated since version 3.3 and will be removed in 4.0. Use the isCompiled() method instead.', __METHOD__), E_USER_DEPRECATED); - - return true; - } - /** * Gets the 'test' service. * diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services31.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services31.php index d22a130cd0514..045b3c8e61347 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services31.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services31.php @@ -51,16 +51,6 @@ public function isCompiled() return true; } - /** - * {@inheritdoc} - */ - public function isFrozen() - { - @trigger_error(sprintf('The %s() method is deprecated since version 3.3 and will be removed in 4.0. Use the isCompiled() method instead.', __METHOD__), E_USER_DEPRECATED); - - return true; - } - /** * Gets the 'bar' service. * diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services32.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services32.php index 08ca63092a6a6..c18b3f5d4421d 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services32.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services32.php @@ -51,16 +51,6 @@ public function isCompiled() return true; } - /** - * {@inheritdoc} - */ - public function isFrozen() - { - @trigger_error(sprintf('The %s() method is deprecated since version 3.3 and will be removed in 4.0. Use the isCompiled() method instead.', __METHOD__), E_USER_DEPRECATED); - - return true; - } - /** * Gets the 'bar' service. * diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services33.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services33.php index fe0510cc2602c..76787db068b24 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services33.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services33.php @@ -53,16 +53,6 @@ public function isCompiled() return true; } - /** - * {@inheritdoc} - */ - public function isFrozen() - { - @trigger_error(sprintf('The %s() method is deprecated since version 3.3 and will be removed in 4.0. Use the isCompiled() method instead.', __METHOD__), E_USER_DEPRECATED); - - return true; - } - /** * Gets the 'Symfony\Component\DependencyInjection\Tests\Fixtures\Container33\Foo' service. * diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services8.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services8.php index bfc1d68bd1ef6..a21d47d21bced 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services8.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services8.php @@ -49,16 +49,6 @@ public function isCompiled() return true; } - /** - * {@inheritdoc} - */ - public function isFrozen() - { - @trigger_error(sprintf('The %s() method is deprecated since version 3.3 and will be removed in 4.0. Use the isCompiled() method instead.', __METHOD__), E_USER_DEPRECATED); - - return true; - } - /** * {@inheritdoc} */ diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_compiled.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_compiled.php index f35ca89f03e18..da2accd3687c0 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_compiled.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_compiled.php @@ -73,16 +73,6 @@ public function isCompiled() return true; } - /** - * {@inheritdoc} - */ - public function isFrozen() - { - @trigger_error(sprintf('The %s() method is deprecated since version 3.3 and will be removed in 4.0. Use the isCompiled() method instead.', __METHOD__), E_USER_DEPRECATED); - - return true; - } - /** * Gets the 'bar' service. * diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_dump_proxy_with_void_return_type.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_dump_proxy_with_void_return_type.php index ec6af7fc2c8c5..f09561d8f4e1f 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_dump_proxy_with_void_return_type.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_dump_proxy_with_void_return_type.php @@ -51,16 +51,6 @@ public function isCompiled() return true; } - /** - * {@inheritdoc} - */ - public function isFrozen() - { - @trigger_error(sprintf('The %s() method is deprecated since version 3.3 and will be removed in 4.0. Use the isCompiled() method instead.', __METHOD__), E_USER_DEPRECATED); - - return true; - } - /** * Gets the 'bar' service. * diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_locator.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_locator.php index d623194c3ee6e..651547430bcf7 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_locator.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_locator.php @@ -61,16 +61,6 @@ public function isCompiled() return true; } - /** - * {@inheritdoc} - */ - public function isFrozen() - { - @trigger_error(sprintf('The %s() method is deprecated since version 3.3 and will be removed in 4.0. Use the isCompiled() method instead.', __METHOD__), E_USER_DEPRECATED); - - return true; - } - /** * Gets the 'bar_service' service. * diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_private_frozen.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_private_frozen.php index 1fbfc52e4a077..d6e0e57205f47 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_private_frozen.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_private_frozen.php @@ -55,16 +55,6 @@ public function isCompiled() return true; } - /** - * {@inheritdoc} - */ - public function isFrozen() - { - @trigger_error(sprintf('The %s() method is deprecated since version 3.3 and will be removed in 4.0. Use the isCompiled() method instead.', __METHOD__), E_USER_DEPRECATED); - - return true; - } - /** * Gets the 'bar_service' service. * diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_subscriber.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_subscriber.php index df5603572497f..9179b270b1419 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_subscriber.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_subscriber.php @@ -59,16 +59,6 @@ public function isCompiled() return true; } - /** - * {@inheritdoc} - */ - public function isFrozen() - { - @trigger_error(sprintf('The %s() method is deprecated since version 3.3 and will be removed in 4.0. Use the isCompiled() method instead.', __METHOD__), E_USER_DEPRECATED); - - return true; - } - /** * Gets the 'Symfony\Component\DependencyInjection\Tests\Fixtures\TestServiceSubscriber' service. * From 7091fb4df5c73413f8a6d490bf0f738bc39dfeb9 Mon Sep 17 00:00:00 2001 From: Maxime Steinhausser Date: Sun, 21 May 2017 11:14:40 +0200 Subject: [PATCH 0049/1099] Remove PHP < 7.1.3 code --- .../Twig/DataCollector/TwigDataCollector.php | 6 +- .../Bridge/Twig/Tests/Node/DumpNodeTest.php | 12 +--- .../Bridge/Twig/Tests/Node/FormThemeTest.php | 6 +- .../Node/SearchAndRenderBlockNodeTest.php | 6 +- .../Bridge/Twig/Tests/Node/TransNodeTest.php | 12 +--- .../Translation/PhpExtractor.php | 6 +- .../Cache/Adapter/PhpArrayAdapter.php | 8 +-- .../Component/Cache/Simple/PhpArrayCache.php | 6 +- .../Resource/ReflectionClassResourceTest.php | 8 +-- .../Component/Console/Command/Command.php | 10 +--- .../Component/Console/Input/ArgvInput.php | 5 -- .../Console/Tests/ApplicationTest.php | 6 -- .../Console/Tests/Command/CommandTest.php | 8 +-- .../Component/Debug/DebugClassLoader.php | 5 +- .../Debug/Tests/DebugClassLoaderTest.php | 58 +----------------- .../Debug/Tests/ErrorHandlerTest.php | 3 - .../Tests/Exception/FlattenExceptionTest.php | 3 - .../Config/AutowireServiceResource.php | 6 +- .../DependencyInjection/Dumper/PhpDumper.php | 13 ++-- .../LazyProxy/ProxyHelper.php | 4 -- .../Tests/Compiler/AutowirePassTest.php | 3 - .../Tests/Dumper/PhpDumperTest.php | 6 -- .../Tests/Fixtures/php/services31.php | 6 +- .../Tests/Fixtures/php/services32.php | 6 +- .../Tests/Fixtures/php/services9.php | 32 +++++----- .../Tests/Fixtures/php/services9_compiled.php | 22 +++---- ...vices_dump_proxy_with_void_return_type.php | 2 +- .../Tests/Fixtures/php/services_locator.php | 18 +++--- .../Fixtures/php/services_private_frozen.php | 4 +- .../Fixtures/php/services_subscriber.php | 16 ++--- .../Tests/Loader/IniFileLoaderTest.php | 1 - src/Symfony/Component/Finder/CHANGELOG.md | 1 + .../Finder/Iterator/CustomFilterIterator.php | 2 +- .../Iterator/DateRangeFilterIterator.php | 2 +- .../Iterator/DepthRangeFilterIterator.php | 2 +- .../ExcludeDirectoryFilterIterator.php | 2 +- .../Iterator/FileTypeFilterIterator.php | 2 +- .../Finder/Iterator/FilterIterator.php | 60 ------------------- .../Iterator/MultiplePcreFilterIterator.php | 2 +- .../Iterator/RecursiveDirectoryIterator.php | 5 -- .../Iterator/SizeRangeFilterIterator.php | 2 +- .../Tests/Iterator/FilterIteratorTest.php | 53 ---------------- .../DateTimeToStringTransformer.php | 2 - src/Symfony/Component/Form/FormError.php | 6 +- .../Component/HttpFoundation/Request.php | 3 - .../HttpFoundation/Tests/CookieTest.php | 3 - .../HttpFoundation/Tests/RequestTest.php | 16 ----- .../Config/EnvParametersResource.php | 6 +- .../ArgumentMetadataFactory.php | 48 +++------------ .../HttpKernel/Debug/FileLinkFormatter.php | 6 +- src/Symfony/Component/HttpKernel/Kernel.php | 8 +-- .../Tests/Controller/ArgumentResolverTest.php | 11 ---- .../ArgumentMetadataFactoryTest.php | 9 --- .../AbstractIntlDateFormatterTest.php | 8 +-- .../PropertyAccess/PropertyAccessor.php | 4 -- .../Extractors/ReflectionExtractorTest.php | 2 - .../Component/Routing/CompiledRoute.php | 6 +- .../Routing/Loader/AnnotationFileLoader.php | 7 +-- src/Symfony/Component/Routing/Route.php | 6 +- .../Tests/Loader/AnnotationFileLoaderTest.php | 6 -- .../Serializer/Encoder/JsonDecode.php | 2 +- .../Normalizer/GetSetMethodNormalizerTest.php | 6 -- .../Translation/Dumper/JsonFileDumper.php | 2 +- .../Component/VarDumper/Caster/ArgsStub.php | 2 +- .../VarDumper/Caster/ReflectionCaster.php | 16 ++--- .../VarDumper/Tests/Caster/CasterTest.php | 3 - .../Tests/Caster/ReflectionCasterTest.php | 9 --- .../VarDumper/Tests/Dumper/CliDumperTest.php | 42 ------------- .../Component/Yaml/Tests/InlineTest.php | 7 +-- 69 files changed, 119 insertions(+), 567 deletions(-) delete mode 100644 src/Symfony/Component/Finder/Iterator/FilterIterator.php delete mode 100644 src/Symfony/Component/Finder/Tests/Iterator/FilterIteratorTest.php diff --git a/src/Symfony/Bridge/Twig/DataCollector/TwigDataCollector.php b/src/Symfony/Bridge/Twig/DataCollector/TwigDataCollector.php index f075709654c95..30d0aff1bb102 100644 --- a/src/Symfony/Bridge/Twig/DataCollector/TwigDataCollector.php +++ b/src/Symfony/Bridge/Twig/DataCollector/TwigDataCollector.php @@ -93,11 +93,7 @@ public function getHtmlCallGraph() public function getProfile() { if (null === $this->profile) { - if (PHP_VERSION_ID >= 70000) { - $this->profile = unserialize($this->data['profile'], array('allowed_classes' => array('Twig_Profiler_Profile'))); - } else { - $this->profile = unserialize($this->data['profile']); - } + $this->profile = unserialize($this->data['profile'], array('allowed_classes' => array('Twig_Profiler_Profile'))); } return $this->profile; diff --git a/src/Symfony/Bridge/Twig/Tests/Node/DumpNodeTest.php b/src/Symfony/Bridge/Twig/Tests/Node/DumpNodeTest.php index 5e589c2db11db..bc4c6a5ae1637 100644 --- a/src/Symfony/Bridge/Twig/Tests/Node/DumpNodeTest.php +++ b/src/Symfony/Bridge/Twig/Tests/Node/DumpNodeTest.php @@ -82,11 +82,7 @@ public function testOneVar() EOTXT; - if (PHP_VERSION_ID >= 70000) { - $expected = preg_replace('/%(.*?)%/', '($context["$1"] ?? null)', $expected); - } else { - $expected = preg_replace('/%(.*?)%/', '(isset($context["$1"]) ? $context["$1"] : null)', $expected); - } + $expected = preg_replace('/%(.*?)%/', '($context["$1"] ?? null)', $expected); $this->assertSame($expected, $compiler->compile($node)->getSource()); } @@ -113,11 +109,7 @@ public function testMultiVars() EOTXT; - if (PHP_VERSION_ID >= 70000) { - $expected = preg_replace('/%(.*?)%/', '($context["$1"] ?? null)', $expected); - } else { - $expected = preg_replace('/%(.*?)%/', '(isset($context["$1"]) ? $context["$1"] : null)', $expected); - } + $expected = preg_replace('/%(.*?)%/', '($context["$1"] ?? null)', $expected); $this->assertSame($expected, $compiler->compile($node)->getSource()); } diff --git a/src/Symfony/Bridge/Twig/Tests/Node/FormThemeTest.php b/src/Symfony/Bridge/Twig/Tests/Node/FormThemeTest.php index 9d3576e0b4430..33acc0cff5aa2 100644 --- a/src/Symfony/Bridge/Twig/Tests/Node/FormThemeTest.php +++ b/src/Symfony/Bridge/Twig/Tests/Node/FormThemeTest.php @@ -67,10 +67,6 @@ public function testCompile() protected function getVariableGetter($name) { - if (PHP_VERSION_ID >= 70000) { - return sprintf('($context["%s"] ?? null)', $name, $name); - } - - return sprintf('(isset($context["%s"]) ? $context["%s"] : null)', $name, $name); + return sprintf('($context["%s"] ?? null)', $name, $name); } } diff --git a/src/Symfony/Bridge/Twig/Tests/Node/SearchAndRenderBlockNodeTest.php b/src/Symfony/Bridge/Twig/Tests/Node/SearchAndRenderBlockNodeTest.php index b292ef63f8555..322e78f1fd188 100644 --- a/src/Symfony/Bridge/Twig/Tests/Node/SearchAndRenderBlockNodeTest.php +++ b/src/Symfony/Bridge/Twig/Tests/Node/SearchAndRenderBlockNodeTest.php @@ -264,10 +264,6 @@ public function testCompileLabelWithLabelThatEvaluatesToNullAndAttributes() protected function getVariableGetter($name) { - if (PHP_VERSION_ID >= 70000) { - return sprintf('($context["%s"] ?? null)', $name, $name); - } - - return sprintf('(isset($context["%s"]) ? $context["%s"] : null)', $name, $name); + return sprintf('($context["%s"] ?? null)', $name, $name); } } diff --git a/src/Symfony/Bridge/Twig/Tests/Node/TransNodeTest.php b/src/Symfony/Bridge/Twig/Tests/Node/TransNodeTest.php index 5862006f3826a..5108db26cf788 100644 --- a/src/Symfony/Bridge/Twig/Tests/Node/TransNodeTest.php +++ b/src/Symfony/Bridge/Twig/Tests/Node/TransNodeTest.php @@ -40,11 +40,7 @@ public function testCompileStrict() protected function getVariableGetterWithoutStrictCheck($name) { - if (PHP_VERSION_ID >= 70000) { - return sprintf('($context["%s"] ?? null)', $name, $name); - } - - return sprintf('(isset($context["%s"]) ? $context["%s"] : null)', $name, $name); + return sprintf('($context["%s"] ?? null)', $name, $name); } protected function getVariableGetterWithStrictCheck($name) @@ -53,10 +49,6 @@ protected function getVariableGetterWithStrictCheck($name) return sprintf('(isset($context["%s"]) || array_key_exists("%s", $context) ? $context["%s"] : (function () { throw new Twig_Error_Runtime(\'Variable "%s" does not exist.\', 0, $this->getSourceContext()); })())', $name, $name, $name, $name); } - if (PHP_VERSION_ID >= 70000) { - return sprintf('($context["%s"] ?? $this->getContext($context, "%s"))', $name, $name, $name); - } - - return sprintf('(isset($context["%s"]) ? $context["%s"] : $this->getContext($context, "%s"))', $name, $name, $name); + return sprintf('($context["%s"] ?? $this->getContext($context, "%s"))', $name, $name, $name); } } diff --git a/src/Symfony/Bundle/FrameworkBundle/Translation/PhpExtractor.php b/src/Symfony/Bundle/FrameworkBundle/Translation/PhpExtractor.php index 97c94fdd14bf9..7af04086622a2 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Translation/PhpExtractor.php +++ b/src/Symfony/Bundle/FrameworkBundle/Translation/PhpExtractor.php @@ -85,10 +85,8 @@ public function extract($resource, MessageCatalogue $catalog) foreach ($files as $file) { $this->parseTokens(token_get_all(file_get_contents($file)), $catalog); - if (PHP_VERSION_ID >= 70000) { - // PHP 7 memory manager will not release after token_get_all(), see https://bugs.php.net/70098 - gc_mem_caches(); - } + // PHP 7 memory manager will not release after token_get_all(), see https://bugs.php.net/70098 + gc_mem_caches(); } } diff --git a/src/Symfony/Component/Cache/Adapter/PhpArrayAdapter.php b/src/Symfony/Component/Cache/Adapter/PhpArrayAdapter.php index 8ddfa27f3868f..08cd4731ba93c 100644 --- a/src/Symfony/Component/Cache/Adapter/PhpArrayAdapter.php +++ b/src/Symfony/Component/Cache/Adapter/PhpArrayAdapter.php @@ -53,19 +53,17 @@ function ($key, $value, $isHit) { } /** - * This adapter should only be used on PHP 7.0+ to take advantage of how PHP - * stores arrays in its latest versions. This factory method decorates the given - * fallback pool with this adapter only if the current PHP version is supported. + * This adapter to take advantage of how PHP stores arrays in its latest versions. * * @param string $file The PHP file were values are cached - * @param CacheItemPoolInterface $fallbackPool Fallback for old PHP versions or opcache disabled + * @param CacheItemPoolInterface $fallbackPool Fallback when opcache is disabled * * @return CacheItemPoolInterface */ public static function create($file, CacheItemPoolInterface $fallbackPool) { // Shared memory is available in PHP 7.0+ with OPCache enabled and in HHVM - if ((PHP_VERSION_ID >= 70000 && ini_get('opcache.enable')) || defined('HHVM_VERSION')) { + if (ini_get('opcache.enable') || defined('HHVM_VERSION')) { if (!$fallbackPool instanceof AdapterInterface) { $fallbackPool = new ProxyAdapter($fallbackPool); } diff --git a/src/Symfony/Component/Cache/Simple/PhpArrayCache.php b/src/Symfony/Component/Cache/Simple/PhpArrayCache.php index 3c61f5e8f645e..40d37051820f1 100644 --- a/src/Symfony/Component/Cache/Simple/PhpArrayCache.php +++ b/src/Symfony/Component/Cache/Simple/PhpArrayCache.php @@ -37,9 +37,7 @@ public function __construct($file, CacheInterface $fallbackPool) } /** - * This adapter should only be used on PHP 7.0+ to take advantage of how PHP - * stores arrays in its latest versions. This factory method decorates the given - * fallback pool with this adapter only if the current PHP version is supported. + * This adapter to take advantage of how PHP stores arrays in its latest versions. * * @param string $file The PHP file were values are cached * @@ -48,7 +46,7 @@ public function __construct($file, CacheInterface $fallbackPool) public static function create($file, CacheInterface $fallbackPool) { // Shared memory is available in PHP 7.0+ with OPCache enabled and in HHVM - if ((PHP_VERSION_ID >= 70000 && ini_get('opcache.enable')) || defined('HHVM_VERSION')) { + if (ini_get('opcache.enable') || defined('HHVM_VERSION')) { return new static($file, $fallbackPool); } diff --git a/src/Symfony/Component/Config/Tests/Resource/ReflectionClassResourceTest.php b/src/Symfony/Component/Config/Tests/Resource/ReflectionClassResourceTest.php index 8fd0adc592abd..299b593d71dff 100644 --- a/src/Symfony/Component/Config/Tests/Resource/ReflectionClassResourceTest.php +++ b/src/Symfony/Component/Config/Tests/Resource/ReflectionClassResourceTest.php @@ -124,12 +124,8 @@ public function provideHashedSignature() yield array(0, 8, '/** priv docblock */'); yield array(0, 9, 'private $priv = 123;'); yield array(1, 10, '/** pub docblock */'); - if (PHP_VERSION_ID >= 50600) { - yield array(1, 11, 'public function pub(...$arg) {}'); - } - if (PHP_VERSION_ID >= 70000) { - yield array(1, 11, 'public function pub($arg = null): Foo {}'); - } + yield array(1, 11, 'public function pub(...$arg) {}'); + yield array(1, 11, 'public function pub($arg = null): Foo {}'); yield array(0, 11, "public function pub(\$arg = null) {\nreturn 123;\n}"); yield array(1, 12, '/** prot docblock */'); yield array(1, 13, 'protected function prot($a = array(123)) {}'); diff --git a/src/Symfony/Component/Console/Command/Command.php b/src/Symfony/Component/Console/Command/Command.php index 2359677515659..14430308d1151 100644 --- a/src/Symfony/Component/Console/Command/Command.php +++ b/src/Symfony/Component/Console/Command/Command.php @@ -286,15 +286,7 @@ public function setCode(callable $code) if ($code instanceof \Closure) { $r = new \ReflectionFunction($code); if (null === $r->getClosureThis()) { - if (PHP_VERSION_ID < 70000) { - // Bug in PHP5: https://bugs.php.net/bug.php?id=64761 - // This means that we cannot bind static closures and therefore we must - // ignore any errors here. There is no way to test if the closure is - // bindable. - $code = @\Closure::bind($code, $this); - } else { - $code = \Closure::bind($code, $this); - } + $code = \Closure::bind($code, $this); } } diff --git a/src/Symfony/Component/Console/Input/ArgvInput.php b/src/Symfony/Component/Console/Input/ArgvInput.php index 85cd779849b73..6195c0535afa8 100644 --- a/src/Symfony/Component/Console/Input/ArgvInput.php +++ b/src/Symfony/Component/Console/Input/ArgvInput.php @@ -148,11 +148,6 @@ private function parseLongOption($token) if (false !== $pos = strpos($name, '=')) { if (0 === strlen($value = substr($name, $pos + 1))) { - // if no value after "=" then substr() returns "" since php7 only, false before - // see http://php.net/manual/fr/migration70.incompatible.php#119151 - if (PHP_VERSION_ID < 70000 && false === $value) { - $value = ''; - } array_unshift($this->parsed, $value); } $this->addLongOption(substr($name, 0, $pos), $value); diff --git a/src/Symfony/Component/Console/Tests/ApplicationTest.php b/src/Symfony/Component/Console/Tests/ApplicationTest.php index ea74f28a4d031..b970ea43aa79d 100644 --- a/src/Symfony/Component/Console/Tests/ApplicationTest.php +++ b/src/Symfony/Component/Console/Tests/ApplicationTest.php @@ -1106,9 +1106,6 @@ public function testConsoleErrorEventIsTriggeredOnCommandNotFound() $this->assertEquals(1, $tester->getStatusCode()); } - /** - * @requires PHP 7 - */ public function testErrorIsRethrownIfNotHandledByConsoleErrorEvent() { $application = new Application(); @@ -1342,9 +1339,6 @@ protected function getDispatcher($skipCommand = false) return $dispatcher; } - /** - * @requires PHP 7 - */ public function testErrorIsRethrownIfNotHandledByConsoleErrorEventWithCatchingEnabled() { $application = new Application(); diff --git a/src/Symfony/Component/Console/Tests/Command/CommandTest.php b/src/Symfony/Component/Console/Tests/Command/CommandTest.php index a8048aeaf813b..b1963918324a6 100644 --- a/src/Symfony/Component/Console/Tests/Command/CommandTest.php +++ b/src/Symfony/Component/Console/Tests/Command/CommandTest.php @@ -392,13 +392,7 @@ public function testSetCodeWithStaticClosure() $tester = new CommandTester($command); $tester->execute(array()); - if (PHP_VERSION_ID < 70000) { - // Cannot bind static closures in PHP 5 - $this->assertEquals('interact called'.PHP_EOL.'not bound'.PHP_EOL, $tester->getDisplay()); - } else { - // Can bind static closures in PHP 7 - $this->assertEquals('interact called'.PHP_EOL.'bound'.PHP_EOL, $tester->getDisplay()); - } + $this->assertEquals('interact called'.PHP_EOL.'bound'.PHP_EOL, $tester->getDisplay()); } private static function createClosure() diff --git a/src/Symfony/Component/Debug/DebugClassLoader.php b/src/Symfony/Component/Debug/DebugClassLoader.php index 2e1d71808e132..c943f7b4e0cb2 100644 --- a/src/Symfony/Component/Debug/DebugClassLoader.php +++ b/src/Symfony/Component/Debug/DebugClassLoader.php @@ -30,7 +30,6 @@ class DebugClassLoader private static $final = array(); private static $finalMethods = array(); private static $deprecated = array(); - private static $php7Reserved = array('int', 'float', 'bool', 'string', 'true', 'false', 'null'); private static $darwinCache = array('/' => array('/', array())); /** @@ -201,9 +200,7 @@ public function loadClass($class) } } - if (in_array(strtolower($refl->getShortName()), self::$php7Reserved)) { - @trigger_error(sprintf('The "%s" class uses the reserved name "%s", it will break on PHP 7 and higher', $name, $refl->getShortName()), E_USER_DEPRECATED); - } elseif (preg_match('#\n \* @deprecated (.*?)\r?\n \*(?: @|/$)#s', $refl->getDocComment(), $notice)) { + if (preg_match('#\n \* @deprecated (.*?)\r?\n \*(?: @|/$)#s', $refl->getDocComment(), $notice)) { self::$deprecated[$name] = preg_replace('#\s*\r?\n \* +#', ' ', $notice[1]); } else { // Don't trigger deprecations for classes in the same vendor diff --git a/src/Symfony/Component/Debug/Tests/DebugClassLoaderTest.php b/src/Symfony/Component/Debug/Tests/DebugClassLoaderTest.php index 765e8d9b86bfd..3f21b2a0adb24 100644 --- a/src/Symfony/Component/Debug/Tests/DebugClassLoaderTest.php +++ b/src/Symfony/Component/Debug/Tests/DebugClassLoaderTest.php @@ -59,29 +59,6 @@ public function testIdempotence() $this->fail('DebugClassLoader did not register'); } - public function testUnsilencing() - { - if (PHP_VERSION_ID >= 70000) { - $this->markTestSkipped('PHP7 throws exceptions, unsilencing is not required anymore.'); - } - if (defined('HHVM_VERSION')) { - $this->markTestSkipped('HHVM is not handled in this test case.'); - } - - ob_start(); - - $this->iniSet('log_errors', 0); - $this->iniSet('display_errors', 1); - - // See below: this will fail with parse error - // but this should not be @-silenced. - @class_exists(__NAMESPACE__.'\TestingUnsilencing', true); - - $output = ob_get_clean(); - - $this->assertStringMatchesFormat('%aParse error%a', $output); - } - public function testStacking() { // the ContextErrorException must not be loaded to test the workaround @@ -109,13 +86,8 @@ class ChildTestingStacking extends TestingStacking { function foo($bar) {} } } catch (\ErrorException $exception) { // if an exception is thrown, the test passed $this->assertStringStartsWith(__FILE__, $exception->getFile()); - if (PHP_VERSION_ID < 70000) { - $this->assertRegExp('/^Runtime Notice: Declaration/', $exception->getMessage()); - $this->assertEquals(E_STRICT, $exception->getSeverity()); - } else { - $this->assertRegExp('/^Warning: Declaration/', $exception->getMessage()); - $this->assertEquals(E_WARNING, $exception->getSeverity()); - } + $this->assertRegExp('/^Warning: Declaration/', $exception->getMessage()); + $this->assertEquals(E_WARNING, $exception->getSeverity()); } finally { restore_error_handler(); restore_exception_handler(); @@ -243,32 +215,6 @@ class_exists('Symfony\Bridge\Debug\Tests\Fixtures\ExtendsDeprecatedParent', true $this->assertSame($xError, $lastError); } - public function testReservedForPhp7() - { - if (PHP_VERSION_ID >= 70000) { - $this->markTestSkipped('PHP7 already prevents using reserved names.'); - } - - set_error_handler(function () { return false; }); - $e = error_reporting(0); - trigger_error('', E_USER_NOTICE); - - class_exists('Test\\'.__NAMESPACE__.'\\Float', true); - - error_reporting($e); - restore_error_handler(); - - $lastError = error_get_last(); - unset($lastError['file'], $lastError['line']); - - $xError = array( - 'type' => E_USER_DEPRECATED, - 'message' => 'The "Test\Symfony\Component\Debug\Tests\Float" class uses the reserved name "Float", it will break on PHP 7 and higher', - ); - - $this->assertSame($xError, $lastError); - } - public function testExtendedFinalClass() { set_error_handler(function () { return false; }); diff --git a/src/Symfony/Component/Debug/Tests/ErrorHandlerTest.php b/src/Symfony/Component/Debug/Tests/ErrorHandlerTest.php index 2fccf2dbe7a9b..eada140ccab7e 100644 --- a/src/Symfony/Component/Debug/Tests/ErrorHandlerTest.php +++ b/src/Symfony/Component/Debug/Tests/ErrorHandlerTest.php @@ -475,9 +475,6 @@ public function testHandleFatalError() } } - /** - * @requires PHP 7 - */ public function testHandleErrorException() { $exception = new \Error("Class 'Foo' not found"); diff --git a/src/Symfony/Component/Debug/Tests/Exception/FlattenExceptionTest.php b/src/Symfony/Component/Debug/Tests/Exception/FlattenExceptionTest.php index e7762bdec8edd..4a0e6cbe4f234 100644 --- a/src/Symfony/Component/Debug/Tests/Exception/FlattenExceptionTest.php +++ b/src/Symfony/Component/Debug/Tests/Exception/FlattenExceptionTest.php @@ -138,9 +138,6 @@ public function testPrevious(\Exception $exception, $statusCode) $this->assertSame(array($flattened2), $flattened->getAllPrevious()); } - /** - * @requires PHP 7.0 - */ public function testPreviousError() { $exception = new \Exception('test', 123, new \ParseError('Oh noes!', 42)); diff --git a/src/Symfony/Component/DependencyInjection/Config/AutowireServiceResource.php b/src/Symfony/Component/DependencyInjection/Config/AutowireServiceResource.php index f49a1eb78e16c..8b507efe82eec 100644 --- a/src/Symfony/Component/DependencyInjection/Config/AutowireServiceResource.php +++ b/src/Symfony/Component/DependencyInjection/Config/AutowireServiceResource.php @@ -65,11 +65,7 @@ public function serialize() public function unserialize($serialized) { - if (PHP_VERSION_ID >= 70000) { - list($this->class, $this->filePath, $this->autowiringMetadata) = unserialize($serialized, array('allowed_classes' => false)); - } else { - list($this->class, $this->filePath, $this->autowiringMetadata) = unserialize($serialized); - } + list($this->class, $this->filePath, $this->autowiringMetadata) = unserialize($serialized, array('allowed_classes' => false)); } /** diff --git a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php index 09f695ee810b9..12e43ab635c5e 100644 --- a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php +++ b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php @@ -1409,13 +1409,14 @@ private function dumpValue($value, $interpolate = true) $value = $value->getValues()[0]; $code = $this->dumpValue($value, $interpolate); + $returnedType = ''; if ($value instanceof TypedReference) { - $code = sprintf('$f = function (\\%s $v%s) { return $v; }; return $f(%s);', $value->getType(), ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE !== $value->getInvalidBehavior() ? ' = null' : '', $code); - } else { - $code = sprintf('return %s;', $code); + $returnedType = sprintf(': %s\%s', ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE === $value->getInvalidBehavior() ? '' : '?', $value->getType()); } - return sprintf("function () {\n %s\n }", $code); + $code = sprintf('return %s;', $code); + + return sprintf("function ()%s {\n %s\n }", $returnedType, $code); } if ($value instanceof IteratorArgument) { @@ -1628,9 +1629,7 @@ private function getServiceCall($id, Reference $reference = null) } if ($this->container->hasDefinition($id) && (!$this->container->getDefinition($id)->isPublic() || $this->container->getDefinition($id)->isShared())) { - // The following is PHP 5.5 syntax for what could be written as "(\$this->services['$id'] ?? $code)" on PHP>=7.0 - - $code = "\${(\$_ = isset(\$this->services['$id']) ? \$this->services['$id'] : $code) && false ?: '_'}"; + $code = "(\$this->services['$id'] ?? $code)"; } return $code; diff --git a/src/Symfony/Component/DependencyInjection/LazyProxy/ProxyHelper.php b/src/Symfony/Component/DependencyInjection/LazyProxy/ProxyHelper.php index b6115ea7dc84c..9a82937252904 100644 --- a/src/Symfony/Component/DependencyInjection/LazyProxy/ProxyHelper.php +++ b/src/Symfony/Component/DependencyInjection/LazyProxy/ProxyHelper.php @@ -49,10 +49,6 @@ public static function getSignature(\ReflectionFunctionAbstract $r, &$call = nul $k = substr($k, 1); } } catch (\ReflectionException $e) { - if ($type && $p->allowsNull() && !class_exists('ReflectionNamedType', false)) { - $k .= ' = null'; - $k = substr($k, 1); - } } $signature[] = $k; diff --git a/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowirePassTest.php b/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowirePassTest.php index e2ba9ec4e4b97..0b4f80b3629e1 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowirePassTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowirePassTest.php @@ -40,9 +40,6 @@ public function testProcess() $this->assertEquals(Foo::class, (string) $container->getDefinition('bar')->getArgument(0)); } - /** - * @requires PHP 5.6 - */ public function testProcessVariadic() { $container = new ContainerBuilder(); diff --git a/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php b/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php index 744384b136f3a..aea09d916ac6b 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php @@ -482,9 +482,6 @@ public function testClosureProxy() $this->assertSame('reflection.Symfony\Component\DependencyInjection\Tests\Fixtures\Container31\Foo', (string) array_pop($res)); } - /** - * @requires PHP 7.1 - */ public function testClosureProxyWithVoidReturnType() { $container = include self::$fixturesPath.'/containers/container_dump_proxy_with_void_return_type.php'; @@ -497,9 +494,6 @@ public function testClosureProxyWithVoidReturnType() $this->assertSame('reflection.Symfony\Component\DependencyInjection\Tests\Fixtures\ContainerVoid\Foo', (string) array_pop($res)); } - /** - * @requires PHP 7.1 - */ public function testClosureProxyPhp71() { $container = include self::$fixturesPath.'/containers/container32.php'; diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services31.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services31.php index 045b3c8e61347..8f05da5df6b67 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services31.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services31.php @@ -64,11 +64,11 @@ protected function getBarService() $this->services['bar'] = $instance = new \stdClass(); $instance->foo = array(0 => /** @closure-proxy Symfony\Component\DependencyInjection\Tests\Fixtures\Container31\Foo::withNoArgs */ function () { - return ${($_ = isset($this->services['foo']) ? $this->services['foo'] : $this->get('foo')) && false ?: '_'}->withNoArgs(); + return ($this->services['foo'] ?? $this->get('foo'))->withNoArgs(); }, 1 => /** @closure-proxy Symfony\Component\DependencyInjection\Tests\Fixtures\Container31\Foo::withArgs */ function ($a, \Symfony\Component\DependencyInjection\Tests\Fixtures\Container31\Foo $b = NULL, $c = array(0 => 123)) { - return ${($_ = isset($this->services['foo']) ? $this->services['foo'] : $this->get('foo')) && false ?: '_'}->withArgs($a, $b, $c); + return ($this->services['foo'] ?? $this->get('foo'))->withArgs($a, $b, $c); }, 2 => /** @closure-proxy Symfony\Component\DependencyInjection\Tests\Fixtures\Container31\Foo::withRefs */ function &(&$a = NULL, &$b) { - return ${($_ = isset($this->services['foo']) ? $this->services['foo'] : $this->get('foo')) && false ?: '_'}->withRefs($a, $b); + return ($this->services['foo'] ?? $this->get('foo'))->withRefs($a, $b); }); return $instance; diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services32.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services32.php index c18b3f5d4421d..96ec4c73f6a66 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services32.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services32.php @@ -64,11 +64,11 @@ protected function getBarService() $this->services['bar'] = $instance = new \stdClass(); $instance->foo = array(0 => /** @closure-proxy Symfony\Component\DependencyInjection\Tests\Fixtures\Container32\Foo::withVariadic */ function ($a, &...$c) { - return ${($_ = isset($this->services['foo']) ? $this->services['foo'] : $this->get('foo')) && false ?: '_'}->withVariadic($a, ...$c); + return ($this->services['foo'] ?? $this->get('foo'))->withVariadic($a, ...$c); }, 1 => /** @closure-proxy Symfony\Component\DependencyInjection\Tests\Fixtures\Container32\Foo::withNullable */ function (?int $a) { - return ${($_ = isset($this->services['foo']) ? $this->services['foo'] : $this->get('foo')) && false ?: '_'}->withNullable($a); + return ($this->services['foo'] ?? $this->get('foo'))->withNullable($a); }, 2 => /** @closure-proxy Symfony\Component\DependencyInjection\Tests\Fixtures\Container32\Foo::withReturnType */ function (): \Bar { - return ${($_ = isset($this->services['foo']) ? $this->services['foo'] : $this->get('foo')) && false ?: '_'}->withReturnType(); + return ($this->services['foo'] ?? $this->get('foo'))->withReturnType(); }); return $instance; diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9.php index b8d5aeafacf24..9e3013dcafb3b 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9.php @@ -83,7 +83,7 @@ public function __construct() */ protected function getBarService() { - $a = ${($_ = isset($this->services['foo.baz']) ? $this->services['foo.baz'] : $this->get('foo.baz')) && false ?: '_'}; + $a = ($this->services['foo.baz'] ?? $this->get('foo.baz')); $this->services['bar'] = $instance = new \Bar\FooClass('foo', $a, $this->getParameter('foo_bar')); @@ -104,7 +104,7 @@ protected function getBazService() { $this->services['baz'] = $instance = new \Baz(); - $instance->setFoo(${($_ = isset($this->services['foo_with_inline']) ? $this->services['foo_with_inline'] : $this->get('foo_with_inline')) && false ?: '_'}); + $instance->setFoo(($this->services['foo_with_inline'] ?? $this->get('foo_with_inline'))); return $instance; } @@ -120,7 +120,7 @@ protected function getBazService() protected function getClosureProxyService() { return $this->services['closure_proxy'] = new \BarClass(/** @closure-proxy BarClass::getBaz */ function () { - return ${($_ = isset($this->services['closure_proxy']) ? $this->services['closure_proxy'] : $this->get('closure_proxy')) && false ?: '_'}->getBaz(); + return ($this->services['closure_proxy'] ?? $this->get('closure_proxy'))->getBaz(); }); } @@ -136,7 +136,7 @@ protected function getConfiguredServiceService() { $this->services['configured_service'] = $instance = new \stdClass(); - ${($_ = isset($this->services['configurator_service']) ? $this->services['configurator_service'] : $this->getConfiguratorServiceService()) && false ?: '_'}->configureStdClass($instance); + ($this->services['configurator_service'] ?? $this->getConfiguratorServiceService())->configureStdClass($instance); return $instance; } @@ -153,7 +153,7 @@ protected function getConfiguredServiceSimpleService() { $this->services['configured_service_simple'] = $instance = new \stdClass(); - ${($_ = isset($this->services['configurator_service_simple']) ? $this->services['configurator_service_simple'] : $this->getConfiguratorServiceSimpleService()) && false ?: '_'}->configureStdClass($instance); + ($this->services['configurator_service_simple'] ?? $this->getConfiguratorServiceSimpleService())->configureStdClass($instance); return $instance; } @@ -224,7 +224,7 @@ protected function getDeprecatedServiceService() */ protected function getFactoryServiceService() { - return $this->services['factory_service'] = ${($_ = isset($this->services['foo.baz']) ? $this->services['foo.baz'] : $this->get('foo.baz')) && false ?: '_'}->getInstance(); + return $this->services['factory_service'] = ($this->services['foo.baz'] ?? $this->get('foo.baz'))->getInstance(); } /** @@ -237,7 +237,7 @@ protected function getFactoryServiceService() */ protected function getFactoryServiceSimpleService() { - return $this->services['factory_service_simple'] = ${($_ = isset($this->services['factory_simple']) ? $this->services['factory_simple'] : $this->getFactorySimpleService()) && false ?: '_'}->getInstance(); + return $this->services['factory_service_simple'] = ($this->services['factory_simple'] ?? $this->getFactorySimpleService())->getInstance(); } /** @@ -250,14 +250,14 @@ protected function getFactoryServiceSimpleService() */ protected function getFooService() { - $a = ${($_ = isset($this->services['foo.baz']) ? $this->services['foo.baz'] : $this->get('foo.baz')) && false ?: '_'}; + $a = ($this->services['foo.baz'] ?? $this->get('foo.baz')); $this->services['foo'] = $instance = \Bar\FooClass::getInstance('foo', $a, array($this->getParameter('foo') => 'foo is '.$this->getParameter('foo').'', 'foobar' => $this->getParameter('foo')), true, $this); $instance->foo = 'bar'; $instance->moo = $a; $instance->qux = array($this->getParameter('foo') => 'foo is '.$this->getParameter('foo').'', 'foobar' => $this->getParameter('foo')); - $instance->setBar(${($_ = isset($this->services['bar']) ? $this->services['bar'] : $this->get('bar')) && false ?: '_'}); + $instance->setBar(($this->services['bar'] ?? $this->get('bar'))); $instance->initialize(); sc_configure($instance); @@ -305,7 +305,7 @@ protected function getFooWithInlineService() { $this->services['foo_with_inline'] = $instance = new \Foo(); - $instance->setBar(${($_ = isset($this->services['inlined']) ? $this->services['inlined'] : $this->getInlinedService()) && false ?: '_'}); + $instance->setBar(($this->services['inlined'] ?? $this->getInlinedService())); return $instance; } @@ -321,7 +321,7 @@ protected function getFooWithInlineService() protected function getLazyContextService() { return $this->services['lazy_context'] = new \LazyContext(new RewindableGenerator(function () { - yield 'k1' => ${($_ = isset($this->services['foo.baz']) ? $this->services['foo.baz'] : $this->get('foo.baz')) && false ?: '_'}; + yield 'k1' => ($this->services['foo.baz'] ?? $this->get('foo.baz')); yield 'k2' => $this; }, 2), new RewindableGenerator(function () { return new \EmptyIterator(); @@ -339,7 +339,7 @@ protected function getLazyContextService() protected function getLazyContextIgnoreInvalidRefService() { return $this->services['lazy_context_ignore_invalid_ref'] = new \LazyContext(new RewindableGenerator(function () { - yield 0 => ${($_ = isset($this->services['foo.baz']) ? $this->services['foo.baz'] : $this->get('foo.baz')) && false ?: '_'}; + yield 0 => ($this->services['foo.baz'] ?? $this->get('foo.baz')); if ($this->has('invalid')) { yield 1 => $this->get('invalid', ContainerInterface::NULL_ON_INVALID_REFERENCE); } @@ -364,7 +364,7 @@ protected function getMethodCall1Service() $this->services['method_call1'] = $instance = new \Bar\FooClass(); - $instance->setBar(${($_ = isset($this->services['foo']) ? $this->services['foo'] : $this->get('foo')) && false ?: '_'}); + $instance->setBar(($this->services['foo'] ?? $this->get('foo'))); $instance->setBar($this->get('foo2', ContainerInterface::NULL_ON_INVALID_REFERENCE)); if ($this->has('foo3')) { $instance->setBar($this->get('foo3', ContainerInterface::NULL_ON_INVALID_REFERENCE)); @@ -387,7 +387,7 @@ protected function getMethodCall1Service() */ protected function getNewFactoryServiceService() { - $this->services['new_factory_service'] = $instance = ${($_ = isset($this->services['new_factory']) ? $this->services['new_factory'] : $this->getNewFactoryService()) && false ?: '_'}->getInstance(); + $this->services['new_factory_service'] = $instance = ($this->services['new_factory'] ?? $this->getNewFactoryService())->getInstance(); $instance->foo = 'bar'; @@ -423,7 +423,7 @@ protected function getConfiguratorServiceService() { $this->services['configurator_service'] = $instance = new \ConfClass(); - $instance->setFoo(${($_ = isset($this->services['baz']) ? $this->services['baz'] : $this->get('baz')) && false ?: '_'}); + $instance->setFoo(($this->services['baz'] ?? $this->get('baz'))); return $instance; } @@ -479,7 +479,7 @@ protected function getInlinedService() $this->services['inlined'] = $instance = new \Bar(); $instance->pub = 'pub'; - $instance->setBaz(${($_ = isset($this->services['baz']) ? $this->services['baz'] : $this->get('baz')) && false ?: '_'}); + $instance->setBaz(($this->services['baz'] ?? $this->get('baz'))); return $instance; } diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_compiled.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_compiled.php index 78d1e15edbf5a..58e61f712f52b 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_compiled.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_compiled.php @@ -83,7 +83,7 @@ public function isCompiled() */ protected function getBarService() { - $a = ${($_ = isset($this->services['foo.baz']) ? $this->services['foo.baz'] : $this->get('foo.baz')) && false ?: '_'}; + $a = ($this->services['foo.baz'] ?? $this->get('foo.baz')); $this->services['bar'] = $instance = new \Bar\FooClass('foo', $a, $this->getParameter('foo_bar')); @@ -104,7 +104,7 @@ protected function getBazService() { $this->services['baz'] = $instance = new \Baz(); - $instance->setFoo(${($_ = isset($this->services['foo_with_inline']) ? $this->services['foo_with_inline'] : $this->get('foo_with_inline')) && false ?: '_'}); + $instance->setFoo(($this->services['foo_with_inline'] ?? $this->get('foo_with_inline'))); return $instance; } @@ -120,7 +120,7 @@ protected function getBazService() protected function getClosureProxyService() { return $this->services['closure_proxy'] = new \BarClass(/** @closure-proxy BarClass::getBaz */ function () { - return ${($_ = isset($this->services['closure_proxy']) ? $this->services['closure_proxy'] : $this->get('closure_proxy')) && false ?: '_'}->getBaz(); + return ($this->services['closure_proxy'] ?? $this->get('closure_proxy'))->getBaz(); }); } @@ -135,7 +135,7 @@ protected function getClosureProxyService() protected function getConfiguredServiceService() { $a = new \ConfClass(); - $a->setFoo(${($_ = isset($this->services['baz']) ? $this->services['baz'] : $this->get('baz')) && false ?: '_'}); + $a->setFoo(($this->services['baz'] ?? $this->get('baz'))); $this->services['configured_service'] = $instance = new \stdClass(); @@ -214,7 +214,7 @@ protected function getDeprecatedServiceService() */ protected function getFactoryServiceService() { - return $this->services['factory_service'] = ${($_ = isset($this->services['foo.baz']) ? $this->services['foo.baz'] : $this->get('foo.baz')) && false ?: '_'}->getInstance(); + return $this->services['factory_service'] = ($this->services['foo.baz'] ?? $this->get('foo.baz'))->getInstance(); } /** @@ -240,14 +240,14 @@ protected function getFactoryServiceSimpleService() */ protected function getFooService() { - $a = ${($_ = isset($this->services['foo.baz']) ? $this->services['foo.baz'] : $this->get('foo.baz')) && false ?: '_'}; + $a = ($this->services['foo.baz'] ?? $this->get('foo.baz')); $this->services['foo'] = $instance = \Bar\FooClass::getInstance('foo', $a, array('bar' => 'foo is bar', 'foobar' => 'bar'), true, $this); $instance->foo = 'bar'; $instance->moo = $a; $instance->qux = array('bar' => 'foo is bar', 'foobar' => 'bar'); - $instance->setBar(${($_ = isset($this->services['bar']) ? $this->services['bar'] : $this->get('bar')) && false ?: '_'}); + $instance->setBar(($this->services['bar'] ?? $this->get('bar'))); $instance->initialize(); sc_configure($instance); @@ -296,7 +296,7 @@ protected function getFooWithInlineService() $this->services['foo_with_inline'] = $instance = new \Foo(); $a->pub = 'pub'; - $a->setBaz(${($_ = isset($this->services['baz']) ? $this->services['baz'] : $this->get('baz')) && false ?: '_'}); + $a->setBaz(($this->services['baz'] ?? $this->get('baz'))); $instance->setBar($a); @@ -314,7 +314,7 @@ protected function getFooWithInlineService() protected function getLazyContextService() { return $this->services['lazy_context'] = new \LazyContext(new RewindableGenerator(function () { - yield 'k1' => ${($_ = isset($this->services['foo.baz']) ? $this->services['foo.baz'] : $this->get('foo.baz')) && false ?: '_'}; + yield 'k1' => ($this->services['foo.baz'] ?? $this->get('foo.baz')); yield 'k2' => $this; }, 2), new RewindableGenerator(function () { return new \EmptyIterator(); @@ -332,7 +332,7 @@ protected function getLazyContextService() protected function getLazyContextIgnoreInvalidRefService() { return $this->services['lazy_context_ignore_invalid_ref'] = new \LazyContext(new RewindableGenerator(function () { - yield 0 => ${($_ = isset($this->services['foo.baz']) ? $this->services['foo.baz'] : $this->get('foo.baz')) && false ?: '_'}; + yield 0 => ($this->services['foo.baz'] ?? $this->get('foo.baz')); }, 1), new RewindableGenerator(function () { return new \EmptyIterator(); }, 0)); @@ -352,7 +352,7 @@ protected function getMethodCall1Service() $this->services['method_call1'] = $instance = new \Bar\FooClass(); - $instance->setBar(${($_ = isset($this->services['foo']) ? $this->services['foo'] : $this->get('foo')) && false ?: '_'}); + $instance->setBar(($this->services['foo'] ?? $this->get('foo'))); $instance->setBar(NULL); $instance->setBar(($this->get("foo")->foo() . (($this->hasParameter("foo")) ? ($this->getParameter("foo")) : ("default")))); diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_dump_proxy_with_void_return_type.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_dump_proxy_with_void_return_type.php index f09561d8f4e1f..4d282d1a6ddd1 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_dump_proxy_with_void_return_type.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_dump_proxy_with_void_return_type.php @@ -64,7 +64,7 @@ protected function getBarService() $this->services['bar'] = $instance = new \stdClass(); $instance->foo = array(0 => /** @closure-proxy Symfony\Component\DependencyInjection\Tests\Fixtures\ContainerVoid\Foo::withVoid */ function (): void { - ${($_ = isset($this->services['foo']) ? $this->services['foo'] : $this->get('foo')) && false ?: '_'}->withVoid(); + ($this->services['foo'] ?? $this->get('foo'))->withVoid(); }); return $instance; diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_locator.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_locator.php index 651547430bcf7..98305c1a1df6d 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_locator.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_locator.php @@ -71,7 +71,7 @@ public function isCompiled() */ protected function getBarServiceService() { - return $this->services['bar_service'] = new \stdClass(${($_ = isset($this->services['baz_service']) ? $this->services['baz_service'] : $this->getBazServiceService()) && false ?: '_'}); + return $this->services['bar_service'] = new \stdClass(($this->services['baz_service'] ?? $this->getBazServiceService())); } /** @@ -85,9 +85,9 @@ protected function getBarServiceService() protected function getFooServiceService() { return $this->services['foo_service'] = new \Symfony\Component\DependencyInjection\ServiceLocator(array('bar' => function () { - return ${($_ = isset($this->services['bar_service']) ? $this->services['bar_service'] : $this->get('bar_service')) && false ?: '_'}; - }, 'baz' => function () { - $f = function (\stdClass $v) { return $v; }; return $f(${($_ = isset($this->services['baz_service']) ? $this->services['baz_service'] : $this->getBazServiceService()) && false ?: '_'}); + return ($this->services['bar_service'] ?? $this->get('bar_service')); + }, 'baz' => function (): \stdClass { + return ($this->services['baz_service'] ?? $this->getBazServiceService()); }, 'nil' => function () { return NULL; })); @@ -143,7 +143,7 @@ protected function getTranslator_Loader3Service() protected function getTranslator1Service() { return $this->services['translator_1'] = new \Symfony\Component\DependencyInjection\Tests\Fixtures\StubbedTranslator(new \Symfony\Component\DependencyInjection\ServiceLocator(array('translator.loader_1' => function () { - return ${($_ = isset($this->services['translator.loader_1']) ? $this->services['translator.loader_1'] : $this->get('translator.loader_1')) && false ?: '_'}; + return ($this->services['translator.loader_1'] ?? $this->get('translator.loader_1')); }))); } @@ -158,10 +158,10 @@ protected function getTranslator1Service() protected function getTranslator2Service() { $this->services['translator_2'] = $instance = new \Symfony\Component\DependencyInjection\Tests\Fixtures\StubbedTranslator(new \Symfony\Component\DependencyInjection\ServiceLocator(array('translator.loader_2' => function () { - return ${($_ = isset($this->services['translator.loader_2']) ? $this->services['translator.loader_2'] : $this->get('translator.loader_2')) && false ?: '_'}; + return ($this->services['translator.loader_2'] ?? $this->get('translator.loader_2')); }))); - $instance->addResource('db', ${($_ = isset($this->services['translator.loader_2']) ? $this->services['translator.loader_2'] : $this->get('translator.loader_2')) && false ?: '_'}, 'nl'); + $instance->addResource('db', ($this->services['translator.loader_2'] ?? $this->get('translator.loader_2')), 'nl'); return $instance; } @@ -176,10 +176,10 @@ protected function getTranslator2Service() */ protected function getTranslator3Service() { - $a = ${($_ = isset($this->services['translator.loader_3']) ? $this->services['translator.loader_3'] : $this->get('translator.loader_3')) && false ?: '_'}; + $a = ($this->services['translator.loader_3'] ?? $this->get('translator.loader_3')); $this->services['translator_3'] = $instance = new \Symfony\Component\DependencyInjection\Tests\Fixtures\StubbedTranslator(new \Symfony\Component\DependencyInjection\ServiceLocator(array('translator.loader_3' => function () { - return ${($_ = isset($this->services['translator.loader_3']) ? $this->services['translator.loader_3'] : $this->get('translator.loader_3')) && false ?: '_'}; + return ($this->services['translator.loader_3'] ?? $this->get('translator.loader_3')); }))); $instance->addResource('db', $a, 'nl'); diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_private_frozen.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_private_frozen.php index d6e0e57205f47..1df28c328a58a 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_private_frozen.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_private_frozen.php @@ -65,7 +65,7 @@ public function isCompiled() */ protected function getBarServiceService() { - return $this->services['bar_service'] = new \stdClass(${($_ = isset($this->services['baz_service']) ? $this->services['baz_service'] : $this->getBazServiceService()) && false ?: '_'}); + return $this->services['bar_service'] = new \stdClass(($this->services['baz_service'] ?? $this->getBazServiceService())); } /** @@ -78,7 +78,7 @@ protected function getBarServiceService() */ protected function getFooServiceService() { - return $this->services['foo_service'] = new \stdClass(${($_ = isset($this->services['baz_service']) ? $this->services['baz_service'] : $this->getBazServiceService()) && false ?: '_'}); + return $this->services['foo_service'] = new \stdClass(($this->services['baz_service'] ?? $this->getBazServiceService())); } /** diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_subscriber.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_subscriber.php index 9179b270b1419..81506dae44a0d 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_subscriber.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_subscriber.php @@ -84,14 +84,14 @@ protected function getSymfony_Component_DependencyInjection_Tests_Fixtures_TestS */ protected function getFooServiceService() { - return $this->services['foo_service'] = new \Symfony\Component\DependencyInjection\Tests\Fixtures\TestServiceSubscriber(new \Symfony\Component\DependencyInjection\ServiceLocator(array('Symfony\\Component\\DependencyInjection\\Tests\\Fixtures\\CustomDefinition' => function () { - $f = function (\Symfony\Component\DependencyInjection\Tests\Fixtures\CustomDefinition $v) { return $v; }; return $f(${($_ = isset($this->services['autowired.Symfony\Component\DependencyInjection\Tests\Fixtures\CustomDefinition']) ? $this->services['autowired.Symfony\Component\DependencyInjection\Tests\Fixtures\CustomDefinition'] : $this->getAutowired_Symfony_Component_DependencyInjection_Tests_Fixtures_CustomDefinitionService()) && false ?: '_'}); - }, 'Symfony\\Component\\DependencyInjection\\Tests\\Fixtures\\TestServiceSubscriber' => function () { - $f = function (\Symfony\Component\DependencyInjection\Tests\Fixtures\TestServiceSubscriber $v) { return $v; }; return $f(${($_ = isset($this->services['Symfony\Component\DependencyInjection\Tests\Fixtures\TestServiceSubscriber']) ? $this->services['Symfony\Component\DependencyInjection\Tests\Fixtures\TestServiceSubscriber'] : $this->get('Symfony\Component\DependencyInjection\Tests\Fixtures\TestServiceSubscriber')) && false ?: '_'}); - }, 'bar' => function () { - $f = function (\Symfony\Component\DependencyInjection\Tests\Fixtures\CustomDefinition $v) { return $v; }; return $f(${($_ = isset($this->services['Symfony\Component\DependencyInjection\Tests\Fixtures\TestServiceSubscriber']) ? $this->services['Symfony\Component\DependencyInjection\Tests\Fixtures\TestServiceSubscriber'] : $this->get('Symfony\Component\DependencyInjection\Tests\Fixtures\TestServiceSubscriber')) && false ?: '_'}); - }, 'baz' => function () { - $f = function (\Symfony\Component\DependencyInjection\Tests\Fixtures\CustomDefinition $v) { return $v; }; return $f(${($_ = isset($this->services['autowired.Symfony\Component\DependencyInjection\Tests\Fixtures\CustomDefinition']) ? $this->services['autowired.Symfony\Component\DependencyInjection\Tests\Fixtures\CustomDefinition'] : $this->getAutowired_Symfony_Component_DependencyInjection_Tests_Fixtures_CustomDefinitionService()) && false ?: '_'}); + return $this->services['foo_service'] = new \Symfony\Component\DependencyInjection\Tests\Fixtures\TestServiceSubscriber(new \Symfony\Component\DependencyInjection\ServiceLocator(array('Symfony\\Component\\DependencyInjection\\Tests\\Fixtures\\CustomDefinition' => function (): \Symfony\Component\DependencyInjection\Tests\Fixtures\CustomDefinition { + return ($this->services['autowired.Symfony\Component\DependencyInjection\Tests\Fixtures\CustomDefinition'] ?? $this->getAutowired_Symfony_Component_DependencyInjection_Tests_Fixtures_CustomDefinitionService()); + }, 'Symfony\\Component\\DependencyInjection\\Tests\\Fixtures\\TestServiceSubscriber' => function (): \Symfony\Component\DependencyInjection\Tests\Fixtures\TestServiceSubscriber { + return ($this->services['Symfony\Component\DependencyInjection\Tests\Fixtures\TestServiceSubscriber'] ?? $this->get('Symfony\Component\DependencyInjection\Tests\Fixtures\TestServiceSubscriber')); + }, 'bar' => function (): \Symfony\Component\DependencyInjection\Tests\Fixtures\CustomDefinition { + return ($this->services['Symfony\Component\DependencyInjection\Tests\Fixtures\TestServiceSubscriber'] ?? $this->get('Symfony\Component\DependencyInjection\Tests\Fixtures\TestServiceSubscriber')); + }, 'baz' => function (): \Symfony\Component\DependencyInjection\Tests\Fixtures\CustomDefinition { + return ($this->services['autowired.Symfony\Component\DependencyInjection\Tests\Fixtures\CustomDefinition'] ?? $this->getAutowired_Symfony_Component_DependencyInjection_Tests_Fixtures_CustomDefinitionService()); }))); } diff --git a/src/Symfony/Component/DependencyInjection/Tests/Loader/IniFileLoaderTest.php b/src/Symfony/Component/DependencyInjection/Tests/Loader/IniFileLoaderTest.php index 003cd714b1fa9..66fe419b9d806 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Loader/IniFileLoaderTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Loader/IniFileLoaderTest.php @@ -45,7 +45,6 @@ public function testTypeConversions($key, $value, $supported) /** * @dataProvider getTypeConversions - * @requires PHP 5.6.1 * This test illustrates where our conversions differs from INI_SCANNER_TYPED introduced in PHP 5.6.1 */ public function testTypeConversionsWithNativePhp($key, $value, $supported) diff --git a/src/Symfony/Component/Finder/CHANGELOG.md b/src/Symfony/Component/Finder/CHANGELOG.md index 9b88b452ffc04..7361fb1940798 100644 --- a/src/Symfony/Component/Finder/CHANGELOG.md +++ b/src/Symfony/Component/Finder/CHANGELOG.md @@ -5,6 +5,7 @@ CHANGELOG ----- * removed `ExceptionInterface` + * removed `Symfony\Component\Finder\Iterator\FilterIterator` 3.4.0 ----- diff --git a/src/Symfony/Component/Finder/Iterator/CustomFilterIterator.php b/src/Symfony/Component/Finder/Iterator/CustomFilterIterator.php index b43b88d98df79..db6d4f2db07e1 100644 --- a/src/Symfony/Component/Finder/Iterator/CustomFilterIterator.php +++ b/src/Symfony/Component/Finder/Iterator/CustomFilterIterator.php @@ -19,7 +19,7 @@ * * @author Fabien Potencier */ -class CustomFilterIterator extends FilterIterator +class CustomFilterIterator extends \FilterIterator { private $filters = array(); diff --git a/src/Symfony/Component/Finder/Iterator/DateRangeFilterIterator.php b/src/Symfony/Component/Finder/Iterator/DateRangeFilterIterator.php index 0f2d48f39ef99..2ccaf93f319e1 100644 --- a/src/Symfony/Component/Finder/Iterator/DateRangeFilterIterator.php +++ b/src/Symfony/Component/Finder/Iterator/DateRangeFilterIterator.php @@ -18,7 +18,7 @@ * * @author Fabien Potencier */ -class DateRangeFilterIterator extends FilterIterator +class DateRangeFilterIterator extends \FilterIterator { private $comparators = array(); diff --git a/src/Symfony/Component/Finder/Iterator/DepthRangeFilterIterator.php b/src/Symfony/Component/Finder/Iterator/DepthRangeFilterIterator.php index f78c71ed415cc..1c956e97b5e65 100644 --- a/src/Symfony/Component/Finder/Iterator/DepthRangeFilterIterator.php +++ b/src/Symfony/Component/Finder/Iterator/DepthRangeFilterIterator.php @@ -16,7 +16,7 @@ * * @author Fabien Potencier */ -class DepthRangeFilterIterator extends FilterIterator +class DepthRangeFilterIterator extends \FilterIterator { private $minDepth = 0; diff --git a/src/Symfony/Component/Finder/Iterator/ExcludeDirectoryFilterIterator.php b/src/Symfony/Component/Finder/Iterator/ExcludeDirectoryFilterIterator.php index 3f5a5dfeb133c..8e240f9fe6ae3 100644 --- a/src/Symfony/Component/Finder/Iterator/ExcludeDirectoryFilterIterator.php +++ b/src/Symfony/Component/Finder/Iterator/ExcludeDirectoryFilterIterator.php @@ -16,7 +16,7 @@ * * @author Fabien Potencier */ -class ExcludeDirectoryFilterIterator extends FilterIterator implements \RecursiveIterator +class ExcludeDirectoryFilterIterator extends \FilterIterator implements \RecursiveIterator { private $iterator; private $isRecursive; diff --git a/src/Symfony/Component/Finder/Iterator/FileTypeFilterIterator.php b/src/Symfony/Component/Finder/Iterator/FileTypeFilterIterator.php index f50fd82c345f4..d1c0ebaca6f64 100644 --- a/src/Symfony/Component/Finder/Iterator/FileTypeFilterIterator.php +++ b/src/Symfony/Component/Finder/Iterator/FileTypeFilterIterator.php @@ -16,7 +16,7 @@ * * @author Fabien Potencier */ -class FileTypeFilterIterator extends FilterIterator +class FileTypeFilterIterator extends \FilterIterator { const ONLY_FILES = 1; const ONLY_DIRECTORIES = 2; diff --git a/src/Symfony/Component/Finder/Iterator/FilterIterator.php b/src/Symfony/Component/Finder/Iterator/FilterIterator.php deleted file mode 100644 index a182f10eb8ded..0000000000000 --- a/src/Symfony/Component/Finder/Iterator/FilterIterator.php +++ /dev/null @@ -1,60 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Finder\Iterator; - -/** - * This iterator just overrides the rewind method in order to correct a PHP bug, - * which existed before version 5.5.23/5.6.7. - * - * @see https://bugs.php.net/68557 - * - * @author Alex Bogomazov - * - * @deprecated since 3.4, to be removed in 4.0. - */ -abstract class FilterIterator extends \FilterIterator -{ - /** - * This is a workaround for the problem with \FilterIterator leaving inner \FilesystemIterator in wrong state after - * rewind in some cases. - * - * @see FilterIterator::rewind() - */ - public function rewind() - { - if (PHP_VERSION_ID > 50607 || (PHP_VERSION_ID > 50523 && PHP_VERSION_ID < 50600)) { - parent::rewind(); - - return; - } - - $iterator = $this; - while ($iterator instanceof \OuterIterator) { - $innerIterator = $iterator->getInnerIterator(); - - if ($innerIterator instanceof RecursiveDirectoryIterator) { - // this condition is necessary for iterators to work properly with non-local filesystems like ftp - if ($innerIterator->isRewindable()) { - $innerIterator->next(); - $innerIterator->rewind(); - } - } elseif ($innerIterator instanceof \FilesystemIterator) { - $innerIterator->next(); - $innerIterator->rewind(); - } - - $iterator = $innerIterator; - } - - parent::rewind(); - } -} diff --git a/src/Symfony/Component/Finder/Iterator/MultiplePcreFilterIterator.php b/src/Symfony/Component/Finder/Iterator/MultiplePcreFilterIterator.php index 162dc1410b979..44f4fb35cb98b 100644 --- a/src/Symfony/Component/Finder/Iterator/MultiplePcreFilterIterator.php +++ b/src/Symfony/Component/Finder/Iterator/MultiplePcreFilterIterator.php @@ -16,7 +16,7 @@ * * @author Fabien Potencier */ -abstract class MultiplePcreFilterIterator extends FilterIterator +abstract class MultiplePcreFilterIterator extends \FilterIterator { protected $matchRegexps = array(); protected $noMatchRegexps = array(); diff --git a/src/Symfony/Component/Finder/Iterator/RecursiveDirectoryIterator.php b/src/Symfony/Component/Finder/Iterator/RecursiveDirectoryIterator.php index 5bea38e69a772..f56990aa70d31 100644 --- a/src/Symfony/Component/Finder/Iterator/RecursiveDirectoryIterator.php +++ b/src/Symfony/Component/Finder/Iterator/RecursiveDirectoryIterator.php @@ -118,11 +118,6 @@ public function rewind() return; } - // @see https://bugs.php.net/68557 - if (PHP_VERSION_ID < 50523 || PHP_VERSION_ID >= 50600 && PHP_VERSION_ID < 50607) { - parent::next(); - } - parent::rewind(); } diff --git a/src/Symfony/Component/Finder/Iterator/SizeRangeFilterIterator.php b/src/Symfony/Component/Finder/Iterator/SizeRangeFilterIterator.php index 3d3140a6ae45a..9262a38e663b7 100644 --- a/src/Symfony/Component/Finder/Iterator/SizeRangeFilterIterator.php +++ b/src/Symfony/Component/Finder/Iterator/SizeRangeFilterIterator.php @@ -18,7 +18,7 @@ * * @author Fabien Potencier */ -class SizeRangeFilterIterator extends FilterIterator +class SizeRangeFilterIterator extends \FilterIterator { private $comparators = array(); diff --git a/src/Symfony/Component/Finder/Tests/Iterator/FilterIteratorTest.php b/src/Symfony/Component/Finder/Tests/Iterator/FilterIteratorTest.php deleted file mode 100644 index 8b1a4482bae2e..0000000000000 --- a/src/Symfony/Component/Finder/Tests/Iterator/FilterIteratorTest.php +++ /dev/null @@ -1,53 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Finder\Tests\Iterator; - -/** - * @author Alex Bogomazov - * - * @group legacy - */ -class FilterIteratorTest extends RealIteratorTestCase -{ - public function testFilterFilesystemIterators() - { - $i = new \FilesystemIterator($this->toAbsolute()); - - // it is expected that there are test.py test.php in the tmpDir - $i = $this->getMockForAbstractClass('Symfony\Component\Finder\Iterator\FilterIterator', array($i)); - $i->expects($this->any()) - ->method('accept') - ->will($this->returnCallback(function () use ($i) { - return (bool) preg_match('/\.php/', (string) $i->current()); - }) - ); - - $c = 0; - foreach ($i as $item) { - ++$c; - } - - $this->assertEquals(1, $c); - - $i->rewind(); - - $c = 0; - foreach ($i as $item) { - ++$c; - } - - // This would fail in php older than 5.5.23/5.6.7 with \FilterIterator - // but works with Symfony\Component\Finder\Iterator\FilterIterator - // see https://bugs.php.net/68557 - $this->assertEquals(1, $c); - } -} diff --git a/src/Symfony/Component/Form/Extension/Core/DataTransformer/DateTimeToStringTransformer.php b/src/Symfony/Component/Form/Extension/Core/DataTransformer/DateTimeToStringTransformer.php index 7d29b6b88c1af..c9c1854e3aef9 100644 --- a/src/Symfony/Component/Form/Extension/Core/DataTransformer/DateTimeToStringTransformer.php +++ b/src/Symfony/Component/Form/Extension/Core/DataTransformer/DateTimeToStringTransformer.php @@ -43,8 +43,6 @@ class DateTimeToStringTransformer extends BaseDateTimeTransformer /** * Whether to parse by appending a pipe "|" to the parse format. * - * This only works as of PHP 5.3.7. - * * @var bool */ private $parseUsingPipe; diff --git a/src/Symfony/Component/Form/FormError.php b/src/Symfony/Component/Form/FormError.php index e4e50a873c942..88a4ad6ceec55 100644 --- a/src/Symfony/Component/Form/FormError.php +++ b/src/Symfony/Component/Form/FormError.php @@ -185,10 +185,6 @@ public function serialize() */ public function unserialize($serialized) { - if (PHP_VERSION_ID >= 70000) { - list($this->message, $this->messageTemplate, $this->messageParameters, $this->messagePluralization, $this->cause) = unserialize($serialized, array('allowed_classes' => false)); - } else { - list($this->message, $this->messageTemplate, $this->messageParameters, $this->messagePluralization, $this->cause) = unserialize($serialized); - } + list($this->message, $this->messageTemplate, $this->messageParameters, $this->messagePluralization, $this->cause) = unserialize($serialized, array('allowed_classes' => false)); } } diff --git a/src/Symfony/Component/HttpFoundation/Request.php b/src/Symfony/Component/HttpFoundation/Request.php index 4962256376d71..536e110788946 100644 --- a/src/Symfony/Component/HttpFoundation/Request.php +++ b/src/Symfony/Component/HttpFoundation/Request.php @@ -1576,9 +1576,6 @@ public function isMethodCacheable() public function getContent($asResource = false) { $currentContentIsResource = is_resource($this->content); - if (PHP_VERSION_ID < 50600 && false === $this->content) { - throw new \LogicException('getContent() can only be called once when using the resource return type and PHP below 5.6.'); - } if (true === $asResource) { if ($currentContentIsResource) { diff --git a/src/Symfony/Component/HttpFoundation/Tests/CookieTest.php b/src/Symfony/Component/HttpFoundation/Tests/CookieTest.php index edaed2533b1bd..29fac6adaf989 100644 --- a/src/Symfony/Component/HttpFoundation/Tests/CookieTest.php +++ b/src/Symfony/Component/HttpFoundation/Tests/CookieTest.php @@ -104,9 +104,6 @@ public function testConstructorWithDateTime() $this->assertEquals($expire->format('U'), $cookie->getExpiresTime(), '->getExpiresTime() returns the expire date'); } - /** - * @requires PHP 5.5 - */ public function testConstructorWithDateTimeImmutable() { $expire = new \DateTimeImmutable(); diff --git a/src/Symfony/Component/HttpFoundation/Tests/RequestTest.php b/src/Symfony/Component/HttpFoundation/Tests/RequestTest.php index dfc37459ab971..7cb59dc1cd819 100644 --- a/src/Symfony/Component/HttpFoundation/Tests/RequestTest.php +++ b/src/Symfony/Component/HttpFoundation/Tests/RequestTest.php @@ -1051,21 +1051,6 @@ public function testContentAsResource() $this->assertEquals('My other content', $req->getContent()); } - /** - * @expectedException \LogicException - * @dataProvider getContentCantBeCalledTwiceWithResourcesProvider - */ - public function testGetContentCantBeCalledTwiceWithResources($first, $second) - { - if (PHP_VERSION_ID >= 50600) { - $this->markTestSkipped('PHP >= 5.6 allows to open php://input several times.'); - } - - $req = new Request(); - $req->getContent($first); - $req->getContent($second); - } - public function getContentCantBeCalledTwiceWithResourcesProvider() { return array( @@ -1076,7 +1061,6 @@ public function getContentCantBeCalledTwiceWithResourcesProvider() /** * @dataProvider getContentCanBeCalledTwiceWithResourcesProvider - * @requires PHP 5.6 */ public function testGetContentCanBeCalledTwiceWithResources($first, $second) { diff --git a/src/Symfony/Component/HttpKernel/Config/EnvParametersResource.php b/src/Symfony/Component/HttpKernel/Config/EnvParametersResource.php index fd53f0bcef3b3..3bb574b5ffa58 100644 --- a/src/Symfony/Component/HttpKernel/Config/EnvParametersResource.php +++ b/src/Symfony/Component/HttpKernel/Config/EnvParametersResource.php @@ -72,11 +72,7 @@ public function serialize() public function unserialize($serialized) { - if (PHP_VERSION_ID >= 70000) { - $unserialized = unserialize($serialized, array('allowed_classes' => false)); - } else { - $unserialized = unserialize($serialized); - } + $unserialized = unserialize($serialized, array('allowed_classes' => false)); $this->prefix = $unserialized['prefix']; $this->variables = $unserialized['variables']; diff --git a/src/Symfony/Component/HttpKernel/ControllerMetadata/ArgumentMetadataFactory.php b/src/Symfony/Component/HttpKernel/ControllerMetadata/ArgumentMetadataFactory.php index d1e7af206804b..a86a5675e3321 100644 --- a/src/Symfony/Component/HttpKernel/ControllerMetadata/ArgumentMetadataFactory.php +++ b/src/Symfony/Component/HttpKernel/ControllerMetadata/ArgumentMetadataFactory.php @@ -18,30 +18,6 @@ */ final class ArgumentMetadataFactory implements ArgumentMetadataFactoryInterface { - /** - * If the ...$arg functionality is available. - * - * Requires at least PHP 5.6.0 or HHVM 3.9.1 - * - * @var bool - */ - private $supportsVariadic; - - /** - * If the reflection supports the getType() method to resolve types. - * - * Requires at least PHP 7.0.0 or HHVM 3.11.0 - * - * @var bool - */ - private $supportsParameterType; - - public function __construct() - { - $this->supportsVariadic = method_exists('ReflectionParameter', 'isVariadic'); - $this->supportsParameterType = method_exists('ReflectionParameter', 'getType'); - } - /** * {@inheritdoc} */ @@ -73,7 +49,7 @@ public function createArgumentMetadata($controller) */ private function isVariadic(\ReflectionParameter $parameter) { - return $this->supportsVariadic && $parameter->isVariadic(); + return $parameter->isVariadic(); } /** @@ -109,21 +85,15 @@ private function getDefaultValue(\ReflectionParameter $parameter) */ private function getType(\ReflectionParameter $parameter) { - if ($this->supportsParameterType) { - if (!$type = $parameter->getType()) { - return; - } - $typeName = $type instanceof \ReflectionNamedType ? $type->getName() : $type->__toString(); - if ('array' === $typeName && !$type->isBuiltin()) { - // Special case for HHVM with variadics - return; - } - - return $typeName; + if (!$type = $parameter->getType()) { + return; } - - if (preg_match('/^(?:[^ ]++ ){4}([a-zA-Z_\x7F-\xFF][^ ]++)/', $parameter, $info)) { - return $info[1]; + $typeName = $type instanceof \ReflectionNamedType ? $type->getName() : $type->__toString(); + if ('array' === $typeName && !$type->isBuiltin()) { + // Special case for HHVM with variadics + return; } + + return $typeName; } } diff --git a/src/Symfony/Component/HttpKernel/Debug/FileLinkFormatter.php b/src/Symfony/Component/HttpKernel/Debug/FileLinkFormatter.php index 9eefba210a41b..6f70f0d5072b0 100644 --- a/src/Symfony/Component/HttpKernel/Debug/FileLinkFormatter.php +++ b/src/Symfony/Component/HttpKernel/Debug/FileLinkFormatter.php @@ -63,11 +63,7 @@ public function serialize() public function unserialize($serialized) { - if (PHP_VERSION_ID >= 70000) { - $this->fileLinkFormat = unserialize($serialized, array('allowed_classes' => false)); - } else { - $this->fileLinkFormat = unserialize($serialized); - } + $this->fileLinkFormat = unserialize($serialized, array('allowed_classes' => false)); } private function getFileLinkFormat() diff --git a/src/Symfony/Component/HttpKernel/Kernel.php b/src/Symfony/Component/HttpKernel/Kernel.php index 69b27194ddb48..2c6e3250f7935 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -766,11 +766,9 @@ public static function stripComments($source) $output .= $rawChunk; - if (PHP_VERSION_ID >= 70000) { - // PHP 7 memory manager will not release after token_get_all(), see https://bugs.php.net/70098 - unset($tokens, $rawChunk); - gc_mem_caches(); - } + // PHP 7 memory manager will not release after token_get_all(), see https://bugs.php.net/70098 + unset($tokens, $rawChunk); + gc_mem_caches(); return $output; } diff --git a/src/Symfony/Component/HttpKernel/Tests/Controller/ArgumentResolverTest.php b/src/Symfony/Component/HttpKernel/Tests/Controller/ArgumentResolverTest.php index 0804139030128..6a5926f85c7e3 100644 --- a/src/Symfony/Component/HttpKernel/Tests/Controller/ArgumentResolverTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/Controller/ArgumentResolverTest.php @@ -152,9 +152,6 @@ public function testGetArgumentsInjectsExtendingRequest() $this->assertEquals(array($request), self::$resolver->getArguments($request, $controller), '->getArguments() injects the request when extended'); } - /** - * @requires PHP 5.6 - */ public function testGetVariadicArguments() { $request = Request::create('/'); @@ -166,7 +163,6 @@ public function testGetVariadicArguments() } /** - * @requires PHP 5.6 * @expectedException \InvalidArgumentException */ public function testGetVariadicArgumentsWithoutArrayInRequest() @@ -180,7 +176,6 @@ public function testGetVariadicArgumentsWithoutArrayInRequest() } /** - * @requires PHP 5.6 * @expectedException \InvalidArgumentException */ public function testGetArgumentWithoutArray() @@ -210,9 +205,6 @@ public function testIfExceptionIsThrownWhenMissingAnArgument() self::$resolver->getArguments($request, $controller); } - /** - * @requires PHP 7.1 - */ public function testGetNullableArguments() { $request = Request::create('/'); @@ -224,9 +216,6 @@ public function testGetNullableArguments() $this->assertEquals(array('foo', new \stdClass(), 'value', 'mandatory'), self::$resolver->getArguments($request, $controller)); } - /** - * @requires PHP 7.1 - */ public function testGetNullableArgumentsWithDefaults() { $request = Request::create('/'); diff --git a/src/Symfony/Component/HttpKernel/Tests/ControllerMetadata/ArgumentMetadataFactoryTest.php b/src/Symfony/Component/HttpKernel/Tests/ControllerMetadata/ArgumentMetadataFactoryTest.php index b4b449f358611..2ddc6e7a5ee10 100644 --- a/src/Symfony/Component/HttpKernel/Tests/ControllerMetadata/ArgumentMetadataFactoryTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/ControllerMetadata/ArgumentMetadataFactoryTest.php @@ -84,9 +84,6 @@ public function testSignature5() ), $arguments); } - /** - * @requires PHP 5.6 - */ public function testVariadicSignature() { $arguments = $this->factory->createArgumentMetadata(array(new VariadicController(), 'action')); @@ -97,9 +94,6 @@ public function testVariadicSignature() ), $arguments); } - /** - * @requires PHP 7.0 - */ public function testBasicTypesSignature() { $arguments = $this->factory->createArgumentMetadata(array(new BasicTypesController(), 'action')); @@ -111,9 +105,6 @@ public function testBasicTypesSignature() ), $arguments); } - /** - * @requires PHP 7.1 - */ public function testNullableTypesSignature() { $arguments = $this->factory->createArgumentMetadata(array(new NullableController(), 'action')); diff --git a/src/Symfony/Component/Intl/Tests/DateFormatter/AbstractIntlDateFormatterTest.php b/src/Symfony/Component/Intl/Tests/DateFormatter/AbstractIntlDateFormatterTest.php index 35a377da2e899..9c5cd9fdd11c0 100644 --- a/src/Symfony/Component/Intl/Tests/DateFormatter/AbstractIntlDateFormatterTest.php +++ b/src/Symfony/Component/Intl/Tests/DateFormatter/AbstractIntlDateFormatterTest.php @@ -243,9 +243,6 @@ public function formatProvider() return $formatData; } - /** - * @requires PHP 5.5.10 - */ public function testFormatUtcAndGmtAreSplit() { $pattern = "yyyy.MM.dd 'at' HH:mm:ss zzz"; @@ -318,7 +315,6 @@ public function formatWithTimezoneProvider() /** * @dataProvider formatTimezoneProvider - * @requires PHP 5.5 */ public function testFormatTimezone($pattern, $timezone, $expected) { @@ -432,8 +428,8 @@ public function testFormatWithDateTimeZoneGmt() public function testFormatWithDateTimeZoneGmtOffset() { - if (defined('HHVM_VERSION_ID') || PHP_VERSION_ID <= 50509) { - $this->markTestSkipped('DateTimeZone GMT offsets are supported since 5.5.10. See https://github.com/facebook/hhvm/issues/5875 for HHVM.'); + if (defined('HHVM_VERSION_ID')) { + $this->markTestSkipped('See https://github.com/facebook/hhvm/issues/5875'); } $formatter = $this->getDateFormatter('en', IntlDateFormatter::MEDIUM, IntlDateFormatter::SHORT, new \DateTimeZone('GMT+03:00'), IntlDateFormatter::GREGORIAN, 'zzzz'); diff --git a/src/Symfony/Component/PropertyAccess/PropertyAccessor.php b/src/Symfony/Component/PropertyAccess/PropertyAccessor.php index 6019544a19e8c..975824b5057e0 100644 --- a/src/Symfony/Component/PropertyAccess/PropertyAccessor.php +++ b/src/Symfony/Component/PropertyAccess/PropertyAccessor.php @@ -195,10 +195,6 @@ public function setValue(&$objectOrArray, $propertyPath, $value) $overwrite = true; try { - if (PHP_VERSION_ID < 70000 && false === self::$previousErrorHandler) { - self::$previousErrorHandler = set_error_handler(self::$errorHandler); - } - for ($i = count($propertyValues) - 1; 0 <= $i; --$i) { $zval = $propertyValues[$i]; unset($propertyValues[$i]); diff --git a/src/Symfony/Component/PropertyInfo/Tests/Extractors/ReflectionExtractorTest.php b/src/Symfony/Component/PropertyInfo/Tests/Extractors/ReflectionExtractorTest.php index 573528c012f55..4a2cf3fc836e2 100644 --- a/src/Symfony/Component/PropertyInfo/Tests/Extractors/ReflectionExtractorTest.php +++ b/src/Symfony/Component/PropertyInfo/Tests/Extractors/ReflectionExtractorTest.php @@ -85,7 +85,6 @@ public function typesProvider() /** * @dataProvider php7TypesProvider - * @requires PHP 7.0 */ public function testExtractPhp7Type($property, array $type = null) { @@ -104,7 +103,6 @@ public function php7TypesProvider() /** * @dataProvider php71TypesProvider - * @requires PHP 7.1 */ public function testExtractPhp71Type($property, array $type = null) { diff --git a/src/Symfony/Component/Routing/CompiledRoute.php b/src/Symfony/Component/Routing/CompiledRoute.php index a3cbdd056f37c..4805bdaee1c1b 100644 --- a/src/Symfony/Component/Routing/CompiledRoute.php +++ b/src/Symfony/Component/Routing/CompiledRoute.php @@ -73,11 +73,7 @@ public function serialize() */ public function unserialize($serialized) { - if (PHP_VERSION_ID >= 70000) { - $data = unserialize($serialized, array('allowed_classes' => false)); - } else { - $data = unserialize($serialized); - } + $data = unserialize($serialized, array('allowed_classes' => false)); $this->variables = $data['vars']; $this->staticPrefix = $data['path_prefix']; diff --git a/src/Symfony/Component/Routing/Loader/AnnotationFileLoader.php b/src/Symfony/Component/Routing/Loader/AnnotationFileLoader.php index 4dc41e16cd392..b5e02e23b329c 100644 --- a/src/Symfony/Component/Routing/Loader/AnnotationFileLoader.php +++ b/src/Symfony/Component/Routing/Loader/AnnotationFileLoader.php @@ -64,10 +64,9 @@ public function load($file, $type = null) $collection->addResource(new FileResource($path)); $collection->addCollection($this->loader->load($class, $type)); } - if (PHP_VERSION_ID >= 70000) { - // PHP 7 memory manager will not release after token_get_all(), see https://bugs.php.net/70098 - gc_mem_caches(); - } + + // PHP 7 memory manager will not release after token_get_all(), see https://bugs.php.net/70098 + gc_mem_caches(); return $collection; } diff --git a/src/Symfony/Component/Routing/Route.php b/src/Symfony/Component/Routing/Route.php index 137d97548d20d..6d1b1fbec9f8f 100644 --- a/src/Symfony/Component/Routing/Route.php +++ b/src/Symfony/Component/Routing/Route.php @@ -116,11 +116,7 @@ public function serialize() */ public function unserialize($serialized) { - if (PHP_VERSION_ID >= 70000) { - $data = unserialize($serialized, array('allowed_classes' => array(CompiledRoute::class))); - } else { - $data = unserialize($serialized); - } + $data = unserialize($serialized, array('allowed_classes' => array(CompiledRoute::class))); $this->path = $data['path']; $this->host = $data['host']; $this->defaults = $data['defaults']; diff --git a/src/Symfony/Component/Routing/Tests/Loader/AnnotationFileLoaderTest.php b/src/Symfony/Component/Routing/Tests/Loader/AnnotationFileLoaderTest.php index 5d54f9f99f665..2ec3cc6fc9956 100644 --- a/src/Symfony/Component/Routing/Tests/Loader/AnnotationFileLoaderTest.php +++ b/src/Symfony/Component/Routing/Tests/Loader/AnnotationFileLoaderTest.php @@ -35,9 +35,6 @@ public function testLoad() $this->loader->load(__DIR__.'/../Fixtures/AnnotatedClasses/FooClass.php'); } - /** - * @requires PHP 5.4 - */ public function testLoadTraitWithClassConstant() { $this->reader->expects($this->never())->method('getClassAnnotation'); @@ -54,9 +51,6 @@ public function testLoadFileWithoutStartTag() $this->loader->load(__DIR__.'/../Fixtures/OtherAnnotatedClasses/NoStartTagClass.php'); } - /** - * @requires PHP 5.6 - */ public function testLoadVariadic() { $route = new Route(array('path' => '/path/to/{id}')); diff --git a/src/Symfony/Component/Serializer/Encoder/JsonDecode.php b/src/Symfony/Component/Serializer/Encoder/JsonDecode.php index e9ca7ce570e59..46a1e006fbd4c 100644 --- a/src/Symfony/Component/Serializer/Encoder/JsonDecode.php +++ b/src/Symfony/Component/Serializer/Encoder/JsonDecode.php @@ -69,7 +69,7 @@ public function __construct($associative = false, $depth = 512) * If not specified, this method will use the default set in JsonDecode::__construct * * json_decode_options: integer - * Specifies additional options as per documentation for json_decode. Only supported with PHP 5.4.0 and higher + * Specifies additional options as per documentation for json_decode. * * @return mixed * diff --git a/src/Symfony/Component/Serializer/Tests/Normalizer/GetSetMethodNormalizerTest.php b/src/Symfony/Component/Serializer/Tests/Normalizer/GetSetMethodNormalizerTest.php index ee0a159f06f8a..8961e9fc99021 100644 --- a/src/Symfony/Component/Serializer/Tests/Normalizer/GetSetMethodNormalizerTest.php +++ b/src/Symfony/Component/Serializer/Tests/Normalizer/GetSetMethodNormalizerTest.php @@ -146,9 +146,6 @@ public function testConstructorDenormalizeWithOptionalDefaultArgument() $this->assertEquals('test', $obj->getBar()); } - /** - * @requires PHP 5.6 - */ public function testConstructorDenormalizeWithVariadicArgument() { $obj = $this->normalizer->denormalize( @@ -157,9 +154,6 @@ public function testConstructorDenormalizeWithVariadicArgument() $this->assertEquals(array(1, 2, 3), $obj->getFoo()); } - /** - * @requires PHP 5.6 - */ public function testConstructorDenormalizeWithMissingVariadicArgument() { $obj = $this->normalizer->denormalize( diff --git a/src/Symfony/Component/Translation/Dumper/JsonFileDumper.php b/src/Symfony/Component/Translation/Dumper/JsonFileDumper.php index 08b538e1fec83..32bdaf5181199 100644 --- a/src/Symfony/Component/Translation/Dumper/JsonFileDumper.php +++ b/src/Symfony/Component/Translation/Dumper/JsonFileDumper.php @@ -28,7 +28,7 @@ public function formatCatalogue(MessageCatalogue $messages, $domain, array $opti if (isset($options['json_encoding'])) { $flags = $options['json_encoding']; } else { - $flags = defined('JSON_PRETTY_PRINT') ? JSON_PRETTY_PRINT : 0; + $flags = JSON_PRETTY_PRINT; } return json_encode($messages->all($domain), $flags); diff --git a/src/Symfony/Component/VarDumper/Caster/ArgsStub.php b/src/Symfony/Component/VarDumper/Caster/ArgsStub.php index 6675caa0478b9..270e18961f746 100644 --- a/src/Symfony/Component/VarDumper/Caster/ArgsStub.php +++ b/src/Symfony/Component/VarDumper/Caster/ArgsStub.php @@ -68,7 +68,7 @@ private static function getParameters($function, $class) if ($v->isPassedByReference()) { $k = '&'.$k; } - if (method_exists($v, 'isVariadic') && $v->isVariadic()) { + if ($v->isVariadic()) { $variadic .= $k; } else { $params[] = $k; diff --git a/src/Symfony/Component/VarDumper/Caster/ReflectionCaster.php b/src/Symfony/Component/VarDumper/Caster/ReflectionCaster.php index 9811eab5e7e48..a436f3b1842fc 100644 --- a/src/Symfony/Component/VarDumper/Caster/ReflectionCaster.php +++ b/src/Symfony/Component/VarDumper/Caster/ReflectionCaster.php @@ -186,7 +186,7 @@ public static function castFunctionAbstract(\ReflectionFunctionAbstract $c, arra foreach ($c->getParameters() as $v) { $k = '$'.$v->name; - if (method_exists($v, 'isVariadic') && $v->isVariadic()) { + if ($v->isVariadic()) { $k = '...'.$k; } if ($v->isPassedByReference()) { @@ -241,12 +241,8 @@ public static function castParameter(\ReflectionParameter $c, array $a, Stub $st 'allowsNull' => 'allowsNull', )); - if (method_exists($c, 'getType')) { - if ($v = $c->getType()) { - $a[$prefix.'typeHint'] = $v instanceof \ReflectionNamedType ? $v->getName() : $v->__toString(); - } - } elseif (preg_match('/^(?:[^ ]++ ){4}([a-zA-Z_\x7F-\xFF][^ ]++)/', $c, $v)) { - $a[$prefix.'typeHint'] = $v[1]; + if ($v = $c->getType()) { + $a[$prefix.'typeHint'] = $v instanceof \ReflectionNamedType ? $v->getName() : $v->__toString(); } if (isset($a[$prefix.'typeHint'])) { @@ -258,17 +254,13 @@ public static function castParameter(\ReflectionParameter $c, array $a, Stub $st try { $a[$prefix.'default'] = $v = $c->getDefaultValue(); - if (method_exists($c, 'isDefaultValueConstant') && $c->isDefaultValueConstant()) { + if ($c->isDefaultValueConstant()) { $a[$prefix.'default'] = new ConstStub($c->getDefaultValueConstantName(), $v); } if (null === $v) { unset($a[$prefix.'allowsNull']); } } catch (\ReflectionException $e) { - if (isset($a[$prefix.'typeHint']) && $c->allowsNull() && !class_exists('ReflectionNamedType', false)) { - $a[$prefix.'default'] = null; - unset($a[$prefix.'allowsNull']); - } } return $a; diff --git a/src/Symfony/Component/VarDumper/Tests/Caster/CasterTest.php b/src/Symfony/Component/VarDumper/Tests/Caster/CasterTest.php index 105d5638ee1bc..1dacce59bc180 100644 --- a/src/Symfony/Component/VarDumper/Tests/Caster/CasterTest.php +++ b/src/Symfony/Component/VarDumper/Tests/Caster/CasterTest.php @@ -151,9 +151,6 @@ public function provideFilter() ); } - /** - * @requires PHP 7.0 - */ public function testAnonymousClass() { $c = eval('return new class extends stdClass { private $foo = "foo"; };'); diff --git a/src/Symfony/Component/VarDumper/Tests/Caster/ReflectionCasterTest.php b/src/Symfony/Component/VarDumper/Tests/Caster/ReflectionCasterTest.php index 5495a78e40f34..4eada28c01da4 100644 --- a/src/Symfony/Component/VarDumper/Tests/Caster/ReflectionCasterTest.php +++ b/src/Symfony/Component/VarDumper/Tests/Caster/ReflectionCasterTest.php @@ -101,9 +101,6 @@ public function testReflectionParameter() ); } - /** - * @requires PHP 7.0 - */ public function testReflectionParameterScalar() { $f = eval('return function (int $a) {};'); @@ -121,9 +118,6 @@ public function testReflectionParameterScalar() ); } - /** - * @requires PHP 7.0 - */ public function testReturnType() { $f = eval('return function ():int {};'); @@ -143,9 +137,6 @@ class: "Symfony\Component\VarDumper\Tests\Caster\ReflectionCasterTest" ); } - /** - * @requires PHP 7.0 - */ public function testGenerator() { if (extension_loaded('xdebug')) { diff --git a/src/Symfony/Component/VarDumper/Tests/Dumper/CliDumperTest.php b/src/Symfony/Component/VarDumper/Tests/Dumper/CliDumperTest.php index 41785d4b563c6..c2291c6949668 100644 --- a/src/Symfony/Component/VarDumper/Tests/Dumper/CliDumperTest.php +++ b/src/Symfony/Component/VarDumper/Tests/Dumper/CliDumperTest.php @@ -401,7 +401,6 @@ public function testRefsInProperties() /** * @runInSeparateProcess * @preserveGlobalState disabled - * @requires PHP 5.6 */ public function testSpecialVars56() { @@ -460,47 +459,6 @@ public function testGlobals() 2 => &1 array:1 [&1] ] -EOTXT - , - $out - ); - } - - /** - * @runInSeparateProcess - * @preserveGlobalState disabled - */ - public function testBuggyRefs() - { - if (PHP_VERSION_ID >= 50600) { - $this->markTestSkipped('PHP 5.6 fixed refs counting'); - } - - $var = $this->getSpecialVars(); - $var = $var[0]; - - $dumper = new CliDumper(); - $dumper->setColors(false); - $cloner = new VarCloner(); - - $data = $cloner->cloneVar($var)->withMaxDepth(3); - $out = ''; - $dumper->dump($data, function ($line, $depth) use (&$out) { - if ($depth >= 0) { - $out .= str_repeat(' ', $depth).$line."\n"; - } - }); - - $this->assertSame( - <<<'EOTXT' -array:1 [ - 0 => array:1 [ - 0 => array:1 [ - 0 => array:1 [ …1] - ] - ] -] - EOTXT , $out diff --git a/src/Symfony/Component/Yaml/Tests/InlineTest.php b/src/Symfony/Component/Yaml/Tests/InlineTest.php index a26ffbf9e44c6..5e46fb99bdae0 100644 --- a/src/Symfony/Component/Yaml/Tests/InlineTest.php +++ b/src/Symfony/Component/Yaml/Tests/InlineTest.php @@ -570,12 +570,7 @@ public function testParseTimestampAsDateTimeObject($yaml, $year, $month, $day, $ $expected = new \DateTime($yaml); $expected->setTimeZone(new \DateTimeZone('UTC')); $expected->setDate($year, $month, $day); - - if (PHP_VERSION_ID >= 70100) { - $expected->setTime($hour, $minute, $second, 1000000 * ($second - (int) $second)); - } else { - $expected->setTime($hour, $minute, $second); - } + $expected->setTime($hour, $minute, $second, 1000000 * ($second - (int) $second)); $date = Inline::parse($yaml, Yaml::PARSE_DATETIME); $this->assertEquals($expected, $date); From c1c525cdfe5cf3254f77c1262a6ad4da766b8dbf Mon Sep 17 00:00:00 2001 From: Roland Franssen Date: Thu, 18 May 2017 21:56:59 +0200 Subject: [PATCH 0050/1099] [DI] Remove deprecated dumping an uncompiled container --- .../DependencyInjection/CHANGELOG.md | 1 + .../DependencyInjection/Dumper/PhpDumper.php | 101 +++++------------- .../Tests/Dumper/PhpDumperTest.php | 7 +- 3 files changed, 30 insertions(+), 79 deletions(-) diff --git a/src/Symfony/Component/DependencyInjection/CHANGELOG.md b/src/Symfony/Component/DependencyInjection/CHANGELOG.md index b274283d2772d..0d923f0b6d2e5 100644 --- a/src/Symfony/Component/DependencyInjection/CHANGELOG.md +++ b/src/Symfony/Component/DependencyInjection/CHANGELOG.md @@ -5,6 +5,7 @@ CHANGELOG ----- * removed `Container::isFrozen` + * removed support for dumping an ucompiled container in `PhpDumper` 3.3.0 ----- diff --git a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php index 12e43ab635c5e..05f9a3d2e6464 100644 --- a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php +++ b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php @@ -25,6 +25,7 @@ use Symfony\Component\DependencyInjection\Parameter; use Symfony\Component\DependencyInjection\Exception\EnvParameterException; use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; +use Symfony\Component\DependencyInjection\Exception\LogicException; use Symfony\Component\DependencyInjection\Exception\RuntimeException; use Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException; use Symfony\Component\DependencyInjection\LazyProxy\ProxyHelper; @@ -80,7 +81,7 @@ class PhpDumper extends Dumper public function __construct(ContainerBuilder $container) { if (!$container->isCompiled()) { - @trigger_error('Dumping an uncompiled ContainerBuilder is deprecated since version 3.3 and will not be supported anymore in 4.0. Compile the container beforehand.', E_USER_DEPRECATED); + throw new LogicException('Cannot dump an uncompiled container.'); } parent::__construct($container); @@ -154,17 +155,11 @@ public function dump(array $options = array()) } } - $code = $this->startClass($options['class'], $options['base_class'], $options['namespace']); - - if ($this->container->isCompiled()) { - $code .= $this->addFrozenConstructor(); - $code .= $this->addFrozenCompile(); - $code .= $this->addFrozenIsCompiled(); - } else { - $code .= $this->addConstructor(); - } - - $code .= + $code = + $this->startClass($options['class'], $options['base_class'], $options['namespace']). + $this->addConstructor(). + $this->addCompile(). + $this->addIsCompiled(). $this->addServices(). $this->addDefaultParametersMethod(). $this->endClass(). @@ -783,7 +778,6 @@ private function addNewInstance(Definition $definition, $return, $instantiation, */ private function startClass($class, $baseClass, $namespace) { - $bagClass = $this->container->isCompiled() ? 'use Symfony\Component\DependencyInjection\ParameterBag\FrozenParameterBag;' : 'use Symfony\Component\DependencyInjection\ParameterBag\\ParameterBag;'; $namespaceLine = $namespace ? "\nnamespace $namespace;\n" : ''; return <<docStar} * $class. @@ -813,46 +807,12 @@ class $class extends $baseClass EOF; } - /** - * Adds the constructor. - * - * @return string - */ - private function addConstructor() - { - $targetDirs = $this->exportTargetDirs(); - $arguments = $this->container->getParameterBag()->all() ? 'new ParameterBag($this->getDefaultParameters())' : null; - - $code = <<docStar} - * Constructor. - */ - public function __construct() - {{$targetDirs} - parent::__construct($arguments); - -EOF; - - $code .= $this->addNormalizedIds(); - $code .= $this->addMethodMap(); - $code .= $this->addPrivateServices(); - $code .= $this->addAliases(); - - $code .= <<<'EOF' - } - -EOF; - - return $code; - } - /** * Adds the constructor for a compiled container. * * @return string */ - private function addFrozenConstructor() + private function addConstructor() { $targetDirs = $this->exportTargetDirs(); @@ -888,7 +848,7 @@ public function __construct() * * @return string */ - private function addFrozenCompile() + private function addCompile() { return <<container->getAliases()) { - return $this->container->isCompiled() ? "\n \$this->aliases = array();\n" : ''; + return "\n \$this->aliases = array();\n"; } $code = " \$this->aliases = array(\n"; @@ -1046,9 +1006,7 @@ private function addDefaultParametersMethod() } $parameters = sprintf("array(\n%s\n%s)", implode("\n", $php), str_repeat(' ', 8)); - $code = ''; - if ($this->container->isCompiled()) { - $code .= <<<'EOF' + $code = <<<'EOF' /** * {@inheritdoc} @@ -1102,13 +1060,13 @@ public function getParameterBag() } EOF; - if ('' === $this->docStar) { - $code = str_replace('/**', '/*', $code); - } + if ('' === $this->docStar) { + $code = str_replace('/**', '/*', $code); + } - if ($dynamicPhp) { - $loadedDynamicParameters = $this->exportParameters(array_combine(array_keys($dynamicPhp), array_fill(0, count($dynamicPhp), false)), '', 8); - $getDynamicParameter = <<<'EOF' + if ($dynamicPhp) { + $loadedDynamicParameters = $this->exportParameters(array_combine(array_keys($dynamicPhp), array_fill(0, count($dynamicPhp), false)), '', 8); + $getDynamicParameter = <<<'EOF' switch ($name) { %s default: throw new InvalidArgumentException(sprintf('The dynamic parameter "%%s" must be defined.', $name)); @@ -1117,13 +1075,13 @@ public function getParameterBag() return $this->dynamicParameters[$name] = $value; EOF; - $getDynamicParameter = sprintf($getDynamicParameter, implode("\n", $dynamicPhp)); - } else { - $loadedDynamicParameters = 'array()'; - $getDynamicParameter = str_repeat(' ', 8).'throw new InvalidArgumentException(sprintf(\'The dynamic parameter "%s" must be defined.\', $name));'; - } + $getDynamicParameter = sprintf($getDynamicParameter, implode("\n", $dynamicPhp)); + } else { + $loadedDynamicParameters = 'array()'; + $getDynamicParameter = str_repeat(' ', 8).'throw new InvalidArgumentException(sprintf(\'The dynamic parameter "%s" must be defined.\', $name));'; + } - $code .= <<docStar} * Gets the default parameters. * @@ -1595,7 +1546,7 @@ private function dumpLiteralClass($class) */ private function dumpParameter($name) { - if ($this->container->isCompiled() && $this->container->hasParameter($name)) { + if ($this->container->hasParameter($name)) { return $this->dumpValue($this->container->getParameter($name), false); } diff --git a/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php b/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php index aea09d916ac6b..a157c09f3ff95 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php @@ -130,14 +130,13 @@ public function testAddParameters() } /** - * @group legacy - * @expectedDeprecation Dumping an uncompiled ContainerBuilder is deprecated since version 3.3 and will not be supported anymore in 4.0. Compile the container beforehand. + * @expectedException \Symfony\Component\DependencyInjection\Exception\LogicException + * @expectedExceptionMessage Cannot dump an uncompiled container. */ public function testAddServiceWithoutCompilation() { $container = include self::$fixturesPath.'/containers/container9.php'; - $dumper = new PhpDumper($container); - $this->assertEquals(str_replace('%path%', str_replace('\\', '\\\\', self::$fixturesPath.DIRECTORY_SEPARATOR.'includes'.DIRECTORY_SEPARATOR), file_get_contents(self::$fixturesPath.'/php/services9.php')), $dumper->dump(), '->dump() dumps services'); + new PhpDumper($container); } public function testAddService() From d102fc08e48451aee932a8138d9cfaa726cee288 Mon Sep 17 00:00:00 2001 From: Maxime Steinhausser Date: Tue, 9 May 2017 09:19:29 +0200 Subject: [PATCH 0051/1099] [FrameworkBundle] KernelTestCase: deprecate not using KERNEL_CLASS --- UPGRADE-3.4.md | 13 +++++++++++++ UPGRADE-4.0.md | 9 +++++++++ src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md | 6 ++++++ .../Bundle/FrameworkBundle/Test/KernelTestCase.php | 10 ++++++++++ 4 files changed, 38 insertions(+) diff --git a/UPGRADE-3.4.md b/UPGRADE-3.4.md index 29a810c8703e5..9ce416f6d5259 100644 --- a/UPGRADE-3.4.md +++ b/UPGRADE-3.4.md @@ -8,6 +8,19 @@ Finder deprecated and will be removed in 4.0 as it used to fix a bug which existed before version 5.5.23/5.6.7 +FrameworkBundle +--------------- + + * Using the `KERNEL_DIR` environment variable or the automatic guessing based + on the `phpunit.xml` / `phpunit.xml.dist` file location is deprecated since 3.4. + Set the `KERNEL_CLASS` environment variable to the fully-qualified class name + of your Kernel instead. Not setting the `KERNEL_CLASS` environment variable + will throw an exception on 4.0 unless you override the `KernelTestCase::createKernel()` + or `KernelTestCase::getKernelClass()` method. + + * The `KernelTestCase::getPhpUnitXmlDir()` and `KernelTestCase::getPhpUnitCliConfigArgument()` + methods are deprecated since 3.4 and will be removed in 4.0. + Validator --------- diff --git a/UPGRADE-4.0.md b/UPGRADE-4.0.md index e4d9df88d675b..e4fe94c5f939e 100644 --- a/UPGRADE-4.0.md +++ b/UPGRADE-4.0.md @@ -333,6 +333,15 @@ FrameworkBundle * The `Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\ValidateWorkflowsPass` class has been removed. Use the `Symfony\Component\Workflow\DependencyInjection\ValidateWorkflowsPass` class instead. + + * Using the `KERNEL_DIR` environment variable and the automatic guessing based + on the `phpunit.xml` file location have been removed from the `KernelTestCase::getKernelClass()` + method implementation. Set the `KERNEL_CLASS` environment variable to the + fully-qualified class name of your Kernel or override the `KernelTestCase::createKernel()` + or `KernelTestCase::getKernelClass()` method instead. + + * The methods `KernelTestCase::getPhpUnitXmlDir()` and `KernelTestCase::getPhpUnitCliConfigArgument()` + have been removed. HttpFoundation -------------- diff --git a/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md b/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md index df80163243c1c..1a94fb6012462 100644 --- a/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md +++ b/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md @@ -1,6 +1,12 @@ CHANGELOG ========= +3.4.0 +----- + +* Deprecated using the `KERNEL_DIR` environment variable with `KernelTestCase::getKernelClass()`. +* Deprecated the `KernelTestCase::getPhpUnitXmlDir()` and `KernelTestCase::getPhpUnitCliConfigArgument()` methods. + 3.3.0 ----- diff --git a/src/Symfony/Bundle/FrameworkBundle/Test/KernelTestCase.php b/src/Symfony/Bundle/FrameworkBundle/Test/KernelTestCase.php index 26781cdf2285c..802259eedbfee 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Test/KernelTestCase.php +++ b/src/Symfony/Bundle/FrameworkBundle/Test/KernelTestCase.php @@ -39,9 +39,13 @@ abstract class KernelTestCase extends TestCase * @return string The directory where phpunit.xml(.dist) is stored * * @throws \RuntimeException + * + * @deprecated since 3.4 and will be removed in 4.0. */ protected static function getPhpUnitXmlDir() { + @trigger_error(sprintf('The %s() method is deprecated since 3.4 and will be removed in 4.0.', __METHOD__), E_USER_DEPRECATED); + if (!isset($_SERVER['argv']) || false === strpos($_SERVER['argv'][0], 'phpunit')) { throw new \RuntimeException('You must override the KernelTestCase::createKernel() method.'); } @@ -72,9 +76,13 @@ protected static function getPhpUnitXmlDir() * the last configuration argument. * * @return string The value of the PHPUnit CLI configuration option + * + * @deprecated since 3.4 and will be removed in 4.0. */ private static function getPhpUnitCliConfigArgument() { + @trigger_error(sprintf('The %s() method is deprecated since 3.4 and will be removed in 4.0.', __METHOD__), E_USER_DEPRECATED); + $dir = null; $reversedArgs = array_reverse($_SERVER['argv']); foreach ($reversedArgs as $argIndex => $testArg) { @@ -112,6 +120,8 @@ protected static function getKernelClass() } return $class; + } else { + @trigger_error(sprintf('Using the KERNEL_DIR environment variable or the automatic guessing based on the phpunit.xml / phpunit.xml.dist file location is deprecated since 3.4. Set the KERNEL_CLASS environment variable to the fully-qualified class name of your Kernel instead. Not setting the KERNEL_CLASS environment variable will throw an exception on 4.0 unless you override the %1$::createKernel() or %1$::getKernelClass() method.', static::class), E_USER_DEPRECATED); } if (isset($_SERVER['KERNEL_DIR'])) { From c10a780afb0ceb2cf0196fc83b37972c69d77e25 Mon Sep 17 00:00:00 2001 From: Maxime Steinhausser Date: Sat, 15 Apr 2017 13:48:33 +0200 Subject: [PATCH 0052/1099] [Serializer] DateTimeNormalizer: allow to provide timezone --- .../Normalizer/DateTimeNormalizer.php | 34 ++++++++- .../Normalizer/DateTimeNormalizerTest.php | 76 +++++++++++++++++++ 2 files changed, 106 insertions(+), 4 deletions(-) diff --git a/src/Symfony/Component/Serializer/Normalizer/DateTimeNormalizer.php b/src/Symfony/Component/Serializer/Normalizer/DateTimeNormalizer.php index 5958aab0679bd..960782bc465b4 100644 --- a/src/Symfony/Component/Serializer/Normalizer/DateTimeNormalizer.php +++ b/src/Symfony/Component/Serializer/Normalizer/DateTimeNormalizer.php @@ -23,18 +23,22 @@ class DateTimeNormalizer implements NormalizerInterface, DenormalizerInterface { const FORMAT_KEY = 'datetime_format'; + const TIMEZONE_KEY = 'datetime_timezone'; /** * @var string */ private $format; + private $timezone; /** - * @param string $format + * @param string $format + * @param \DateTimeZone|null $timezone */ - public function __construct($format = \DateTime::RFC3339) + public function __construct($format = \DateTime::RFC3339, \DateTimeZone $timezone = null) { $this->format = $format; + $this->timezone = $timezone; } /** @@ -49,6 +53,11 @@ public function normalize($object, $format = null, array $context = array()) } $format = isset($context[self::FORMAT_KEY]) ? $context[self::FORMAT_KEY] : $this->format; + $timezone = $this->getTimezone($context); + + if (null !== $timezone) { + $object = (new \DateTimeImmutable('@'.$object->getTimestamp()))->setTimezone($timezone); + } return $object->format($format); } @@ -69,9 +78,15 @@ public function supportsNormalization($data, $format = null) public function denormalize($data, $class, $format = null, array $context = array()) { $dateTimeFormat = isset($context[self::FORMAT_KEY]) ? $context[self::FORMAT_KEY] : null; + $timezone = $this->getTimezone($context); if (null !== $dateTimeFormat) { - $object = \DateTime::class === $class ? \DateTime::createFromFormat($dateTimeFormat, $data) : \DateTimeImmutable::createFromFormat($dateTimeFormat, $data); + if (null === $timezone && PHP_VERSION_ID < 50600) { + // https://bugs.php.net/bug.php?id=68669 + $object = \DateTime::class === $class ? \DateTime::createFromFormat($dateTimeFormat, $data) : \DateTimeImmutable::createFromFormat($dateTimeFormat, $data); + } else { + $object = \DateTime::class === $class ? \DateTime::createFromFormat($dateTimeFormat, $data, $timezone) : \DateTimeImmutable::createFromFormat($dateTimeFormat, $data, $timezone); + } if (false !== $object) { return $object; @@ -89,7 +104,7 @@ public function denormalize($data, $class, $format = null, array $context = arra } try { - return \DateTime::class === $class ? new \DateTime($data) : new \DateTimeImmutable($data); + return \DateTime::class === $class ? new \DateTime($data, $timezone) : new \DateTimeImmutable($data, $timezone); } catch (\Exception $e) { throw new UnexpectedValueException($e->getMessage(), $e->getCode(), $e); } @@ -126,4 +141,15 @@ private function formatDateTimeErrors(array $errors) return $formattedErrors; } + + private function getTimezone(array $context) + { + $dateTimeZone = array_key_exists(self::TIMEZONE_KEY, $context) ? $context[self::TIMEZONE_KEY] : $this->timezone; + + if (null === $dateTimeZone) { + return null; + } + + return $dateTimeZone instanceof \DateTimeZone ? $dateTimeZone : new \DateTimeZone($dateTimeZone); + } } diff --git a/src/Symfony/Component/Serializer/Tests/Normalizer/DateTimeNormalizerTest.php b/src/Symfony/Component/Serializer/Tests/Normalizer/DateTimeNormalizerTest.php index 6d622bbcc0e05..43cb67c968b13 100644 --- a/src/Symfony/Component/Serializer/Tests/Normalizer/DateTimeNormalizerTest.php +++ b/src/Symfony/Component/Serializer/Tests/Normalizer/DateTimeNormalizerTest.php @@ -52,6 +52,32 @@ public function testNormalizeUsingFormatPassedInConstructor() $this->assertEquals('16', (new DateTimeNormalizer('y'))->normalize(new \DateTime('2016/01/01', new \DateTimeZone('UTC')))); } + public function testNormalizeUsingTimeZonePassedInConstructor() + { + $normalizer = new DateTimeNormalizer(\DateTime::RFC3339, new \DateTimeZone('Japan')); + + $this->assertSame('2016-12-01T00:00:00+09:00', $normalizer->normalize(new \DateTime('2016/12/01', new \DateTimeZone('Japan')))); + $this->assertSame('2016-12-01T09:00:00+09:00', $normalizer->normalize(new \DateTime('2016/12/01', new \DateTimeZone('UTC')))); + } + + /** + * @dataProvider normalizeUsingTimeZonePassedInContextProvider + */ + public function testNormalizeUsingTimeZonePassedInContext($expected, $input, $timezone) + { + $this->assertSame($expected, $this->normalizer->normalize($input, null, array( + DateTimeNormalizer::TIMEZONE_KEY => $timezone, + ))); + } + + public function normalizeUsingTimeZonePassedInContextProvider() + { + yield array('2016-12-01T00:00:00+00:00', new \DateTime('2016/12/01', new \DateTimeZone('UTC')), null); + yield array('2016-12-01T00:00:00+09:00', new \DateTime('2016/12/01', new \DateTimeZone('Japan')), new \DateTimeZone('Japan')); + yield array('2016-12-01T09:00:00+09:00', new \DateTime('2016/12/01', new \DateTimeZone('UTC')), new \DateTimeZone('Japan')); + yield array('2016-12-01T09:00:00+09:00', new \DateTimeImmutable('2016/12/01', new \DateTimeZone('UTC')), new \DateTimeZone('Japan')); + } + /** * @expectedException \Symfony\Component\Serializer\Exception\InvalidArgumentException * @expectedExceptionMessage The object must implement the "\DateTimeInterface". @@ -76,6 +102,17 @@ public function testDenormalize() $this->assertEquals(new \DateTime('2016/01/01', new \DateTimeZone('UTC')), $this->normalizer->denormalize('2016-01-01T00:00:00+00:00', \DateTime::class)); } + public function testDenormalizeUsingTimezonePassedInConstructor() + { + $timezone = new \DateTimeZone('Japan'); + $expected = new \DateTime('2016/12/01 17:35:00', $timezone); + $normalizer = new DateTimeNormalizer(null, $timezone); + + $this->assertEquals($expected, $normalizer->denormalize('2016.12.01 17:35:00', \DateTime::class, null, array( + DateTimeNormalizer::FORMAT_KEY => 'Y.m.d H:i:s', + ))); + } + public function testDenormalizeUsingFormatPassedInContext() { $this->assertEquals(new \DateTimeImmutable('2016/01/01'), $this->normalizer->denormalize('2016.01.01', \DateTimeInterface::class, null, array(DateTimeNormalizer::FORMAT_KEY => 'Y.m.d|'))); @@ -83,6 +120,45 @@ public function testDenormalizeUsingFormatPassedInContext() $this->assertEquals(new \DateTime('2016/01/01'), $this->normalizer->denormalize('2016.01.01', \DateTime::class, null, array(DateTimeNormalizer::FORMAT_KEY => 'Y.m.d|'))); } + /** + * @dataProvider denormalizeUsingTimezonePassedInContextProvider + */ + public function testDenormalizeUsingTimezonePassedInContext($input, $expected, $timezone, $format = null) + { + $actual = $this->normalizer->denormalize($input, \DateTimeInterface::class, null, array( + DateTimeNormalizer::TIMEZONE_KEY => $timezone, + DateTimeNormalizer::FORMAT_KEY => $format, + )); + + $this->assertEquals($expected, $actual); + } + + public function denormalizeUsingTimezonePassedInContextProvider() + { + yield 'with timezone' => array( + '2016/12/01 17:35:00', + new \DateTimeImmutable('2016/12/01 17:35:00', new \DateTimeZone('Japan')), + new \DateTimeZone('Japan'), + ); + yield 'with timezone as string' => array( + '2016/12/01 17:35:00', + new \DateTimeImmutable('2016/12/01 17:35:00', new \DateTimeZone('Japan')), + 'Japan', + ); + yield 'with format without timezone information' => array( + '2016.12.01 17:35:00', + new \DateTimeImmutable('2016/12/01 17:35:00', new \DateTimeZone('Japan')), + new \DateTimeZone('Japan'), + 'Y.m.d H:i:s', + ); + yield 'ignored with format with timezone information' => array( + '2016-12-01T17:35:00Z', + new \DateTimeImmutable('2016/12/01 17:35:00', new \DateTimeZone('UTC')), + 'Europe/Paris', + \DateTime::RFC3339, + ); + } + /** * @expectedException \Symfony\Component\Serializer\Exception\UnexpectedValueException */ From fdb8c58e15b80f5314496d3a91008e98d8432617 Mon Sep 17 00:00:00 2001 From: Roland Franssen Date: Sat, 20 May 2017 21:52:06 +0200 Subject: [PATCH 0053/1099] [DI] Remove deprecated generating a dumped container without populating the method map --- .../DependencyInjection/CHANGELOG.md | 1 + .../DependencyInjection/Container.php | 30 +---- .../Tests/ContainerTest.php | 121 ------------------ 3 files changed, 2 insertions(+), 150 deletions(-) diff --git a/src/Symfony/Component/DependencyInjection/CHANGELOG.md b/src/Symfony/Component/DependencyInjection/CHANGELOG.md index 0d923f0b6d2e5..58ee70a884f3c 100644 --- a/src/Symfony/Component/DependencyInjection/CHANGELOG.md +++ b/src/Symfony/Component/DependencyInjection/CHANGELOG.md @@ -6,6 +6,7 @@ CHANGELOG * removed `Container::isFrozen` * removed support for dumping an ucompiled container in `PhpDumper` + * removed support for generating a dumped `Container` without populating the method map 3.3.0 ----- diff --git a/src/Symfony/Component/DependencyInjection/Container.php b/src/Symfony/Component/DependencyInjection/Container.php index 5a8c6eda3420e..13b464afb0ada 100644 --- a/src/Symfony/Component/DependencyInjection/Container.php +++ b/src/Symfony/Component/DependencyInjection/Container.php @@ -237,14 +237,6 @@ public function has($id) continue; } - // We only check the convention-based factory in a compiled container (i.e. a child class other than a ContainerBuilder, - // and only when the dumper has not generated the method map (otherwise the method map is considered to be fully populated by the dumper) - if (!$this->methodMap && !$this instanceof ContainerBuilder && __CLASS__ !== static::class && method_exists($this, 'get'.strtr($id, $this->underscoreMap).'Service')) { - @trigger_error('Generating a dumped container without populating the method map is deprecated since 3.2 and will be unsupported in 4.0. Update your dumper to generate the method map.', E_USER_DEPRECATED); - - return true; - } - return false; } } @@ -293,11 +285,6 @@ public function get($id, $invalidBehavior = self::EXCEPTION_ON_INVALID_REFERENCE } elseif (--$i && $id !== $normalizedId = $this->normalizeId($id)) { $id = $normalizedId; continue; - } elseif (!$this->methodMap && !$this instanceof ContainerBuilder && __CLASS__ !== static::class && method_exists($this, $method = 'get'.strtr($id, $this->underscoreMap).'Service')) { - // We only check the convention-based factory in a compiled container (i.e. a child class other than a ContainerBuilder, - // and only when the dumper has not generated the method map (otherwise the method map is considered to be fully populated by the dumper) - @trigger_error('Generating a dumped container without populating the method map is deprecated since 3.2 and will be unsupported in 4.0. Update your dumper to generate the method map.', E_USER_DEPRECATED); - // $method is set to the right value, proceed } else { if (self::EXCEPTION_ON_INVALID_REFERENCE === $invalidBehavior) { if (!$id) { @@ -374,22 +361,7 @@ public function reset() */ public function getServiceIds() { - $ids = array(); - - if (!$this->methodMap && !$this instanceof ContainerBuilder && __CLASS__ !== static::class) { - // We only check the convention-based factory in a compiled container (i.e. a child class other than a ContainerBuilder, - // and only when the dumper has not generated the method map (otherwise the method map is considered to be fully populated by the dumper) - @trigger_error('Generating a dumped container without populating the method map is deprecated since 3.2 and will be unsupported in 4.0. Update your dumper to generate the method map.', E_USER_DEPRECATED); - - foreach (get_class_methods($this) as $method) { - if (preg_match('/^get(.+)Service$/', $method, $match)) { - $ids[] = self::underscore($match[1]); - } - } - } - $ids[] = 'service_container'; - - return array_unique(array_merge($ids, array_keys($this->methodMap), array_keys($this->services))); + return array_unique(array_merge(array('service_container'), array_keys($this->methodMap), array_keys($this->services))); } /** diff --git a/src/Symfony/Component/DependencyInjection/Tests/ContainerTest.php b/src/Symfony/Component/DependencyInjection/Tests/ContainerTest.php index 1fc18126393af..b98be15d3ca44 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/ContainerTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/ContainerTest.php @@ -137,18 +137,6 @@ public function testGetServiceIds() $this->assertEquals(array('service_container', 'internal', 'bar', 'foo_bar', 'foo.baz', 'circular', 'throw_exception', 'throws_exception_on_service_configuration', 'foo'), $sc->getServiceIds(), '->getServiceIds() returns defined service ids by factory methods in the method map, followed by service ids defined by set()'); } - /** - * @group legacy - * @expectedDeprecation Generating a dumped container without populating the method map is deprecated since 3.2 and will be unsupported in 4.0. Update your dumper to generate the method map. - */ - public function testGetLegacyServiceIds() - { - $sc = new LegacyProjectServiceContainer(); - $sc->set('foo', $obj = new \stdClass()); - - $this->assertEquals(array('internal', 'bar', 'foo_bar', 'foo.baz', 'circular', 'throw_exception', 'throws_exception_on_service_configuration', 'service_container', 'foo'), $sc->getServiceIds(), '->getServiceIds() returns defined service ids by getXXXService() methods, followed by service ids defined by set()'); - } - public function testSet() { $sc = new Container(); @@ -227,38 +215,6 @@ public function testNormalizeIdKeepsCase() $this->assertSame('Foo', $sc->normalizeId('foo')); } - /** - * @group legacy - * @expectedDeprecation Service identifiers will be made case sensitive in Symfony 4.0. Using "Foo" instead of "foo" is deprecated since version 3.3. - * @expectedDeprecation Generating a dumped container without populating the method map is deprecated since 3.2 and will be unsupported in 4.0. Update your dumper to generate the method map. - * @expectedDeprecation Generating a dumped container without populating the method map is deprecated since 3.2 and will be unsupported in 4.0. Update your dumper to generate the method map. - * @expectedDeprecation Generating a dumped container without populating the method map is deprecated since 3.2 and will be unsupported in 4.0. Update your dumper to generate the method map. - * @expectedDeprecation Generating a dumped container without populating the method map is deprecated since 3.2 and will be unsupported in 4.0. Update your dumper to generate the method map. - */ - public function testLegacyGet() - { - $sc = new LegacyProjectServiceContainer(); - $sc->set('foo', $foo = new \stdClass()); - - $this->assertSame($foo, $sc->get('foo'), '->get() returns the service for the given id'); - $this->assertSame($foo, $sc->get('Foo'), '->get() returns the service for the given id, and converts id to lowercase'); - $this->assertSame($sc->__bar, $sc->get('bar'), '->get() returns the service for the given id'); - $this->assertSame($sc->__foo_bar, $sc->get('foo_bar'), '->get() returns the service if a get*Method() is defined'); - $this->assertSame($sc->__foo_baz, $sc->get('foo.baz'), '->get() returns the service if a get*Method() is defined'); - $this->assertSame($sc->__foo_baz, $sc->get('foo\\baz'), '->get() returns the service if a get*Method() is defined'); - - $sc->set('bar', $bar = new \stdClass()); - $this->assertSame($bar, $sc->get('bar'), '->get() prefers to return a service defined with set() than one defined with a getXXXMethod()'); - - try { - $sc->get(''); - $this->fail('->get() throws a \InvalidArgumentException exception if the service is empty'); - } catch (\Exception $e) { - $this->assertInstanceOf('Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException', $e, '->get() throws a ServiceNotFoundException exception if the service is empty'); - } - $this->assertNull($sc->get('', ContainerInterface::NULL_ON_INVALID_REFERENCE), '->get() returns null if the service is empty'); - } - public function testGetThrowServiceNotFoundException() { $sc = new ProjectServiceContainer(); @@ -317,26 +273,6 @@ public function testHas() $this->assertTrue($sc->has('foo.baz'), '->has() returns true if a get*Method() is defined'); } - /** - * @group legacy - * @expectedDeprecation Generating a dumped container without populating the method map is deprecated since 3.2 and will be unsupported in 4.0. Update your dumper to generate the method map. - * @expectedDeprecation Generating a dumped container without populating the method map is deprecated since 3.2 and will be unsupported in 4.0. Update your dumper to generate the method map. - * @expectedDeprecation Generating a dumped container without populating the method map is deprecated since 3.2 and will be unsupported in 4.0. Update your dumper to generate the method map. - * @expectedDeprecation Generating a dumped container without populating the method map is deprecated since 3.2 and will be unsupported in 4.0. Update your dumper to generate the method map. - */ - public function testLegacyHas() - { - $sc = new LegacyProjectServiceContainer(); - $sc->set('foo', new \stdClass()); - - $this->assertFalse($sc->has('foo1'), '->has() returns false if the service does not exist'); - $this->assertTrue($sc->has('foo'), '->has() returns true if the service exists'); - $this->assertTrue($sc->has('bar'), '->has() returns true if a get*Method() is defined'); - $this->assertTrue($sc->has('foo_bar'), '->has() returns true if a get*Method() is defined'); - $this->assertTrue($sc->has('foo.baz'), '->has() returns true if a get*Method() is defined'); - $this->assertTrue($sc->has('foo\\baz'), '->has() returns true if a get*Method() is defined'); - } - public function testInitialized() { $sc = new ProjectServiceContainer(); @@ -542,60 +478,3 @@ protected function getThrowsExceptionOnServiceConfigurationService() throw new \Exception('Something was terribly wrong while trying to configure the service!'); } } - -class LegacyProjectServiceContainer extends Container -{ - public $__bar; - public $__foo_bar; - public $__foo_baz; - public $__internal; - - public function __construct() - { - parent::__construct(); - - $this->__bar = new \stdClass(); - $this->__foo_bar = new \stdClass(); - $this->__foo_baz = new \stdClass(); - $this->__internal = new \stdClass(); - $this->privates = array('internal' => true); - $this->aliases = array('alias' => 'bar'); - } - - protected function getInternalService() - { - return $this->__internal; - } - - protected function getBarService() - { - return $this->__bar; - } - - protected function getFooBarService() - { - return $this->__foo_bar; - } - - protected function getFoo_BazService() - { - return $this->__foo_baz; - } - - protected function getCircularService() - { - return $this->get('circular'); - } - - protected function getThrowExceptionService() - { - throw new \Exception('Something went terribly wrong!'); - } - - protected function getThrowsExceptionOnServiceConfigurationService() - { - $this->services['throws_exception_on_service_configuration'] = $instance = new \stdClass(); - - throw new \Exception('Something was terribly wrong while trying to configure the service!'); - } -} From 21114f84e6e64855e95177bf48ff50ebef44fec3 Mon Sep 17 00:00:00 2001 From: Robin Chalas Date: Mon, 22 May 2017 09:27:42 +0200 Subject: [PATCH 0054/1099] CS Fixes --- .../Cache/Adapter/PhpArrayAdapter.php | 2 +- .../Component/Cache/Simple/PhpArrayCache.php | 2 +- src/Symfony/Component/Console/Application.php | 22 +++------- src/Symfony/Component/Debug/ErrorHandler.php | 4 -- .../Compiler/FactoryReturnTypePass.php | 2 +- .../LazyProxy/ProxyHelper.php | 2 +- .../ArgumentMetadataFactory.php | 40 +------------------ .../Extractor/ReflectionExtractor.php | 2 +- .../VarDumper/Caster/ReflectionCaster.php | 6 +-- src/Symfony/Component/Yaml/Parser.php | 26 +++++------- 10 files changed, 25 insertions(+), 83 deletions(-) diff --git a/src/Symfony/Component/Cache/Adapter/PhpArrayAdapter.php b/src/Symfony/Component/Cache/Adapter/PhpArrayAdapter.php index 08cd4731ba93c..8671258d72c52 100644 --- a/src/Symfony/Component/Cache/Adapter/PhpArrayAdapter.php +++ b/src/Symfony/Component/Cache/Adapter/PhpArrayAdapter.php @@ -53,7 +53,7 @@ function ($key, $value, $isHit) { } /** - * This adapter to take advantage of how PHP stores arrays in its latest versions. + * This adapter takes advantage of how PHP stores arrays in its latest versions. * * @param string $file The PHP file were values are cached * @param CacheItemPoolInterface $fallbackPool Fallback when opcache is disabled diff --git a/src/Symfony/Component/Cache/Simple/PhpArrayCache.php b/src/Symfony/Component/Cache/Simple/PhpArrayCache.php index 40d37051820f1..678d2ca8b3562 100644 --- a/src/Symfony/Component/Cache/Simple/PhpArrayCache.php +++ b/src/Symfony/Component/Cache/Simple/PhpArrayCache.php @@ -37,7 +37,7 @@ public function __construct($file, CacheInterface $fallbackPool) } /** - * This adapter to take advantage of how PHP stores arrays in its latest versions. + * This adapter takes advantage of how PHP stores arrays in its latest versions. * * @param string $file The PHP file were values are cached * diff --git a/src/Symfony/Component/Console/Application.php b/src/Symfony/Component/Console/Application.php index 14887c75e44c7..5a48a8d6764fc 100644 --- a/src/Symfony/Component/Console/Application.php +++ b/src/Symfony/Component/Console/Application.php @@ -194,13 +194,10 @@ public function doRun(InputInterface $input, OutputInterface $output) } try { - $e = $this->runningCommand = null; + $this->runningCommand = null; // the command name MUST be the first element of the input $command = $this->find($name); - } catch (\Exception $e) { } catch (\Throwable $e) { - } - if (null !== $e) { if (null !== $this->dispatcher) { $event = new ConsoleErrorEvent($input, $output, $e); $this->dispatcher->dispatch(ConsoleEvents::ERROR, $event); @@ -813,24 +810,17 @@ protected function doRunCommand(Command $command, InputInterface $input, OutputI } else { $exitCode = ConsoleCommandEvent::RETURN_CODE_DISABLED; } - } catch (\Exception $e) { } catch (\Throwable $e) { - } - if (null !== $e) { $event = new ConsoleErrorEvent($input, $output, $e, $command); $this->dispatcher->dispatch(ConsoleEvents::ERROR, $event); $e = $event->getError(); - if (0 === $exitCode = $event->getExitCode()) { - $e = null; + if (0 !== $exitCode = $event->getExitCode()) { + throw $e; } - } - - $event = new ConsoleTerminateEvent($command, $input, $output, $exitCode); - $this->dispatcher->dispatch(ConsoleEvents::TERMINATE, $event); - - if (null !== $e) { - throw $e; + } finally { + $event = new ConsoleTerminateEvent($command, $input, $output, $exitCode); + $this->dispatcher->dispatch(ConsoleEvents::TERMINATE, $event); } return $event->getExitCode(); diff --git a/src/Symfony/Component/Debug/ErrorHandler.php b/src/Symfony/Component/Debug/ErrorHandler.php index d6c4d10d2934a..744492a90527d 100644 --- a/src/Symfony/Component/Debug/ErrorHandler.php +++ b/src/Symfony/Component/Debug/ErrorHandler.php @@ -541,7 +541,6 @@ public function handleException($exception, array $error = null) if ($this->loggedErrors & $type) { try { $this->loggers[$type][0]->log($this->loggers[$type][1], $message, array('exception' => $exception)); - } catch (\Exception $handlerException) { } catch (\Throwable $handlerException) { } } @@ -558,7 +557,6 @@ public function handleException($exception, array $error = null) } try { call_user_func($this->exceptionHandler, $exception); - } catch (\Exception $handlerException) { } catch (\Throwable $handlerException) { } if (isset($handlerException)) { @@ -598,8 +596,6 @@ public static function handleFatalError(array $error = null) while (self::$stackedErrorLevels) { static::unstackErrors(); } - } catch (\Exception $exception) { - // Handled below } catch (\Throwable $exception) { // Handled below } diff --git a/src/Symfony/Component/DependencyInjection/Compiler/FactoryReturnTypePass.php b/src/Symfony/Component/DependencyInjection/Compiler/FactoryReturnTypePass.php index 84f9c6bc16e49..8834ff7e4f2b7 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/FactoryReturnTypePass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/FactoryReturnTypePass.php @@ -89,7 +89,7 @@ private function updateDefinition(ContainerBuilder $container, $id, Definition $ $returnType = $m->getReturnType(); if (null !== $returnType && !$returnType->isBuiltin()) { - $returnType = $returnType instanceof \ReflectionNamedType ? $returnType->getName() : $returnType->__toString(); + $returnType = $returnType->getName(); if (null !== $class) { $declaringClass = $m->getDeclaringClass()->getName(); if ('self' === strtolower($returnType)) { diff --git a/src/Symfony/Component/DependencyInjection/LazyProxy/ProxyHelper.php b/src/Symfony/Component/DependencyInjection/LazyProxy/ProxyHelper.php index 9a82937252904..5641167e90ea8 100644 --- a/src/Symfony/Component/DependencyInjection/LazyProxy/ProxyHelper.php +++ b/src/Symfony/Component/DependencyInjection/LazyProxy/ProxyHelper.php @@ -76,7 +76,7 @@ public static function getTypeHint(\ReflectionFunctionAbstract $r, \ReflectionPa return; } if (!is_string($type)) { - $name = $type instanceof \ReflectionNamedType ? $type->getName() : $type->__toString(); + $name = $type->getName(); if ($type->isBuiltin()) { return $noBuiltin ? null : $name; diff --git a/src/Symfony/Component/HttpKernel/ControllerMetadata/ArgumentMetadataFactory.php b/src/Symfony/Component/HttpKernel/ControllerMetadata/ArgumentMetadataFactory.php index a86a5675e3321..3208a2866727e 100644 --- a/src/Symfony/Component/HttpKernel/ControllerMetadata/ArgumentMetadataFactory.php +++ b/src/Symfony/Component/HttpKernel/ControllerMetadata/ArgumentMetadataFactory.php @@ -34,48 +34,12 @@ public function createArgumentMetadata($controller) } foreach ($reflection->getParameters() as $param) { - $arguments[] = new ArgumentMetadata($param->getName(), $this->getType($param), $this->isVariadic($param), $this->hasDefaultValue($param), $this->getDefaultValue($param), $param->allowsNull()); + $arguments[] = new ArgumentMetadata($param->getName(), $this->getType($param), $param->isVariadic(), $param->isDefaultValueAvailable(), $param->isDefaultValueAvailable() ? $param->getDefaultValue() : null, $param->allowsNull()); } return $arguments; } - /** - * Returns whether an argument is variadic. - * - * @param \ReflectionParameter $parameter - * - * @return bool - */ - private function isVariadic(\ReflectionParameter $parameter) - { - return $parameter->isVariadic(); - } - - /** - * Determines whether an argument has a default value. - * - * @param \ReflectionParameter $parameter - * - * @return bool - */ - private function hasDefaultValue(\ReflectionParameter $parameter) - { - return $parameter->isDefaultValueAvailable(); - } - - /** - * Returns a default value if available. - * - * @param \ReflectionParameter $parameter - * - * @return mixed|null - */ - private function getDefaultValue(\ReflectionParameter $parameter) - { - return $this->hasDefaultValue($parameter) ? $parameter->getDefaultValue() : null; - } - /** * Returns an associated type to the given parameter if available. * @@ -88,7 +52,7 @@ private function getType(\ReflectionParameter $parameter) if (!$type = $parameter->getType()) { return; } - $typeName = $type instanceof \ReflectionNamedType ? $type->getName() : $type->__toString(); + $typeName = $type->getName(); if ('array' === $typeName && !$type->isBuiltin()) { // Special case for HHVM with variadics return; diff --git a/src/Symfony/Component/PropertyInfo/Extractor/ReflectionExtractor.php b/src/Symfony/Component/PropertyInfo/Extractor/ReflectionExtractor.php index 0d67b07611401..87778caa6bccd 100644 --- a/src/Symfony/Component/PropertyInfo/Extractor/ReflectionExtractor.php +++ b/src/Symfony/Component/PropertyInfo/Extractor/ReflectionExtractor.php @@ -195,7 +195,7 @@ private function extractFromAccessor($class, $property) */ private function extractFromReflectionType(\ReflectionType $reflectionType) { - $phpTypeOrClass = $reflectionType instanceof \ReflectionNamedType ? $reflectionType->getName() : $reflectionType->__toString(); + $phpTypeOrClass = $reflectionType->getName(); $nullable = $reflectionType->allowsNull(); if (Type::BUILTIN_TYPE_ARRAY === $phpTypeOrClass) { diff --git a/src/Symfony/Component/VarDumper/Caster/ReflectionCaster.php b/src/Symfony/Component/VarDumper/Caster/ReflectionCaster.php index a436f3b1842fc..6b7bdf59f286f 100644 --- a/src/Symfony/Component/VarDumper/Caster/ReflectionCaster.php +++ b/src/Symfony/Component/VarDumper/Caster/ReflectionCaster.php @@ -87,7 +87,7 @@ public static function castType(\ReflectionType $c, array $a, Stub $stub, $isNes $prefix = Caster::PREFIX_VIRTUAL; $a += array( - $prefix.'name' => $c instanceof \ReflectionNamedType ? $c->getName() : $c->__toString(), + $prefix.'name' => $c->getName(), $prefix.'allowsNull' => $c->allowsNull(), $prefix.'isBuiltin' => $c->isBuiltin(), ); @@ -174,7 +174,7 @@ public static function castFunctionAbstract(\ReflectionFunctionAbstract $c, arra if (isset($a[$prefix.'returnType'])) { $v = $a[$prefix.'returnType']; - $v = $v instanceof \ReflectionNamedType ? $v->getName() : $v->__toString(); + $v = $v->getName(); $a[$prefix.'returnType'] = new ClassStub($a[$prefix.'returnType']->allowsNull() ? '?'.$v : $v, array(class_exists($v, false) || interface_exists($v, false) || trait_exists($v, false) ? $v : '', '')); } if (isset($a[$prefix.'class'])) { @@ -242,7 +242,7 @@ public static function castParameter(\ReflectionParameter $c, array $a, Stub $st )); if ($v = $c->getType()) { - $a[$prefix.'typeHint'] = $v instanceof \ReflectionNamedType ? $v->getName() : $v->__toString(); + $a[$prefix.'typeHint'] = $v->getName(); } if (isset($a[$prefix.'typeHint'])) { diff --git a/src/Symfony/Component/Yaml/Parser.php b/src/Symfony/Component/Yaml/Parser.php index dcedd899bc704..3134d907479a0 100644 --- a/src/Symfony/Component/Yaml/Parser.php +++ b/src/Symfony/Component/Yaml/Parser.php @@ -93,7 +93,6 @@ public function parse($value, $flags = 0) $this->refs = array(); $mbEncoding = null; - $e = null; $data = null; if (2 /* MB_OVERLOAD_STRING */ & (int) ini_get('mbstring.func_overload')) { @@ -103,22 +102,15 @@ public function parse($value, $flags = 0) try { $data = $this->doParse($value, $flags); - } catch (\Exception $e) { - } catch (\Throwable $e) { - } - - if (null !== $mbEncoding) { - mb_internal_encoding($mbEncoding); - } - - $this->lines = array(); - $this->currentLine = ''; - $this->refs = array(); - $this->skippedLineNumbers = array(); - $this->locallySkippedLineNumbers = array(); - - if (null !== $e) { - throw $e; + } finally { + if (null !== $mbEncoding) { + mb_internal_encoding($mbEncoding); + } + $this->lines = array(); + $this->currentLine = ''; + $this->refs = array(); + $this->skippedLineNumbers = array(); + $this->locallySkippedLineNumbers = array(); } return $data; From 6fdcb8496bd4b929d12e46ed227ef0ab48117f6d Mon Sep 17 00:00:00 2001 From: Hugo Hamon Date: Fri, 19 May 2017 11:18:49 +0200 Subject: [PATCH 0055/1099] [DependencyInjection] remove deprecated autowiring_types feature --- .../Console/Descriptor/JsonDescriptor.php | 7 -- .../Console/Descriptor/MarkdownDescriptor.php | 7 -- .../Console/Descriptor/TextDescriptor.php | 5 - .../DependencyInjection/CHANGELOG.md | 1 + .../Compiler/AutowirePass.php | 16 ---- .../Compiler/DecoratorServicePass.php | 6 -- .../ResolveDefinitionTemplatesPass.php | 8 -- .../DependencyInjection/Definition.php | 91 ------------------- .../DependencyInjection/Dumper/XmlDumper.php | 7 -- .../DependencyInjection/Dumper/YamlDumper.php | 8 -- .../Loader/XmlFileLoader.php | 4 - .../Loader/YamlFileLoader.php | 19 ---- .../schema/dic/services/services-1.0.xsd | 1 - .../Compiler/DecoratorServicePassTest.php | 24 ----- .../ResolveDefinitionTemplatesPassTest.php | 26 ------ .../Tests/DefinitionTest.php | 16 ---- .../Tests/Fixtures/xml/services22.xml | 9 -- .../Tests/Fixtures/yaml/bad_types1.yml | 5 - .../Tests/Fixtures/yaml/bad_types2.yml | 5 - .../Tests/Fixtures/yaml/services22.yml | 8 -- .../Tests/Loader/XmlFileLoaderTest.php | 12 --- .../Tests/Loader/YamlFileLoaderTest.php | 31 ------- 22 files changed, 1 insertion(+), 315 deletions(-) delete mode 100644 src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services22.xml delete mode 100644 src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/bad_types1.yml delete mode 100644 src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/bad_types2.yml delete mode 100644 src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services22.yml diff --git a/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/JsonDescriptor.php b/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/JsonDescriptor.php index 31ca3a9aafc05..892a5069d71c4 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/JsonDescriptor.php +++ b/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/JsonDescriptor.php @@ -231,13 +231,6 @@ private function getContainerDefinitionData(Definition $definition, $omitTags = 'autoconfigure' => $definition->isAutoconfigured(), ); - // forward compatibility with DependencyInjection component in version 4.0 - if (method_exists($definition, 'getAutowiringTypes')) { - foreach ($definition->getAutowiringTypes(false) as $autowiringType) { - $data['autowiring_types'][] = $autowiringType; - } - } - if ($showArguments) { $data['arguments'] = $this->describeValue($definition->getArguments(), $omitTags, $showArguments); } diff --git a/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/MarkdownDescriptor.php b/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/MarkdownDescriptor.php index 5703c108bccd3..ddd3328c8b2ad 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/MarkdownDescriptor.php +++ b/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/MarkdownDescriptor.php @@ -191,13 +191,6 @@ protected function describeContainerDefinition(Definition $definition, array $op ."\n".'- Autoconfigured: '.($definition->isAutoconfigured() ? 'yes' : 'no') ; - // forward compatibility with DependencyInjection component in version 4.0 - if (method_exists($definition, 'getAutowiringTypes')) { - foreach ($definition->getAutowiringTypes(false) as $autowiringType) { - $output .= "\n".'- Autowiring Type: `'.$autowiringType.'`'; - } - } - if (isset($options['show_arguments']) && $options['show_arguments']) { $output .= "\n".'- Arguments: '.($definition->getArguments() ? 'yes' : 'no'); } diff --git a/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/TextDescriptor.php b/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/TextDescriptor.php index 0abe5e8e398f8..badc022c2420e 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/TextDescriptor.php +++ b/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/TextDescriptor.php @@ -309,11 +309,6 @@ protected function describeContainerDefinition(Definition $definition, array $op $tableRows[] = array('Autowired', $definition->isAutowired() ? 'yes' : 'no'); $tableRows[] = array('Autoconfigured', $definition->isAutoconfigured() ? 'yes' : 'no'); - // forward compatibility with DependencyInjection component in version 4.0 - if (method_exists($definition, 'getAutowiringTypes') && $autowiringTypes = $definition->getAutowiringTypes(false)) { - $tableRows[] = array('Autowiring Types', implode(', ', $autowiringTypes)); - } - if ($definition->getFile()) { $tableRows[] = array('Required File', $definition->getFile() ? $definition->getFile() : '-'); } diff --git a/src/Symfony/Component/DependencyInjection/CHANGELOG.md b/src/Symfony/Component/DependencyInjection/CHANGELOG.md index 0d923f0b6d2e5..c5ab663eccab5 100644 --- a/src/Symfony/Component/DependencyInjection/CHANGELOG.md +++ b/src/Symfony/Component/DependencyInjection/CHANGELOG.md @@ -4,6 +4,7 @@ CHANGELOG 4.0.0 ----- + * removed support for autowiring types * removed `Container::isFrozen` * removed support for dumping an ucompiled container in `PhpDumper` diff --git a/src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php b/src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php index 07ecdcb340137..9811a868273ee 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php @@ -27,7 +27,6 @@ */ class AutowirePass extends AbstractRecursivePass { - private $definedTypes = array(); private $types; private $ambiguousServiceTypes = array(); private $autowired = array(); @@ -62,7 +61,6 @@ public function process(ContainerBuilder $container) try { parent::process($container); } finally { - $this->definedTypes = array(); $this->types = null; $this->ambiguousServiceTypes = array(); $this->autowired = array(); @@ -324,10 +322,6 @@ private function getAutowiredReference(TypedReference $reference) $this->populateAvailableTypes(); } - if (isset($this->definedTypes[$type])) { - return new TypedReference($this->types[$type], $type); - } - if (isset($this->types[$type])) { @trigger_error(sprintf('Autowiring services based on the types they implement is deprecated since Symfony 3.3 and won\'t be supported in version 4.0. You should %s the "%s" service to "%s" instead.', isset($this->types[$this->types[$type]]) ? 'alias' : 'rename (or alias)', $this->types[$type], $type), E_USER_DEPRECATED); @@ -370,12 +364,6 @@ private function populateAvailableType($id, Definition $definition) return; } - foreach ($definition->getAutowiringTypes(false) as $type) { - $this->definedTypes[$type] = true; - $this->types[$type] = $id; - unset($this->ambiguousServiceTypes[$type]); - } - if ($definition->isDeprecated() || !$reflectionClass = $this->container->getReflectionClass($definition->getClass(), true)) { return; } @@ -397,10 +385,6 @@ private function populateAvailableType($id, Definition $definition) */ private function set($type, $id) { - if (isset($this->definedTypes[$type])) { - return; - } - // is this already a type/class that is known to match multiple services? if (isset($this->ambiguousServiceTypes[$type])) { $this->ambiguousServiceTypes[$type][] = $id; diff --git a/src/Symfony/Component/DependencyInjection/Compiler/DecoratorServicePass.php b/src/Symfony/Component/DependencyInjection/Compiler/DecoratorServicePass.php index d1fe95a0bc7a5..7d00ce221e3e7 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/DecoratorServicePass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/DecoratorServicePass.php @@ -53,15 +53,9 @@ public function process(ContainerBuilder $container) } else { $decoratedDefinition = $container->getDefinition($inner); $definition->setTags(array_merge($decoratedDefinition->getTags(), $definition->getTags())); - if ($types = array_merge($decoratedDefinition->getAutowiringTypes(false), $definition->getAutowiringTypes(false))) { - $definition->setAutowiringTypes($types); - } $public = $decoratedDefinition->isPublic(); $decoratedDefinition->setPublic(false); $decoratedDefinition->setTags(array()); - if ($decoratedDefinition->getAutowiringTypes(false)) { - $decoratedDefinition->setAutowiringTypes(array()); - } $container->setDefinition($renamedId, $decoratedDefinition); } diff --git a/src/Symfony/Component/DependencyInjection/Compiler/ResolveDefinitionTemplatesPass.php b/src/Symfony/Component/DependencyInjection/Compiler/ResolveDefinitionTemplatesPass.php index dfceb6a920832..75e9ded601f25 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/ResolveDefinitionTemplatesPass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/ResolveDefinitionTemplatesPass.php @@ -89,9 +89,6 @@ private function doResolveDefinition(ChildDefinition $definition) $def->setArguments($parentDef->getArguments()); $def->setMethodCalls($parentDef->getMethodCalls()); $def->setProperties($parentDef->getProperties()); - if ($parentDef->getAutowiringTypes(false)) { - $def->setAutowiringTypes($parentDef->getAutowiringTypes(false)); - } if ($parentDef->isDeprecated()) { $def->setDeprecated(true, $parentDef->getDeprecationMessage('%service_id%')); } @@ -162,11 +159,6 @@ private function doResolveDefinition(ChildDefinition $definition) $def->setMethodCalls(array_merge($def->getMethodCalls(), $calls)); } - // merge autowiring types - foreach ($definition->getAutowiringTypes(false) as $autowiringType) { - $def->addAutowiringType($autowiringType); - } - // these attributes are always taken from the child $def->setAbstract($definition->isAbstract()); $def->setTags($definition->getTags()); diff --git a/src/Symfony/Component/DependencyInjection/Definition.php b/src/Symfony/Component/DependencyInjection/Definition.php index 68b3368da2ecc..ca4f630141918 100644 --- a/src/Symfony/Component/DependencyInjection/Definition.php +++ b/src/Symfony/Component/DependencyInjection/Definition.php @@ -39,7 +39,6 @@ class Definition private $lazy = false; private $decoratedService; private $autowired = false; - private $autowiringTypes = array(); private $changes = array(); protected $arguments = array(); @@ -745,28 +744,6 @@ public function getConfigurator() return $this->configurator; } - /** - * Sets types that will default to this definition. - * - * @param string[] $types - * - * @return $this - * - * @deprecated since version 3.3, to be removed in 4.0. - */ - public function setAutowiringTypes(array $types) - { - @trigger_error('Autowiring-types are deprecated since Symfony 3.3 and will be removed in 4.0. Use aliases instead.', E_USER_DEPRECATED); - - $this->autowiringTypes = array(); - - foreach ($types as $type) { - $this->autowiringTypes[$type] = true; - } - - return $this; - } - /** * Is the definition autowired? * @@ -792,72 +769,4 @@ public function setAutowired($autowired) return $this; } - - /** - * Gets autowiring types that will default to this definition. - * - * @return string[] - * - * @deprecated since version 3.3, to be removed in 4.0. - */ - public function getAutowiringTypes(/*$triggerDeprecation = true*/) - { - if (1 > func_num_args() || func_get_arg(0)) { - @trigger_error('Autowiring-types are deprecated since Symfony 3.3 and will be removed in 4.0. Use aliases instead.', E_USER_DEPRECATED); - } - - return array_keys($this->autowiringTypes); - } - - /** - * Adds a type that will default to this definition. - * - * @param string $type - * - * @return $this - * - * @deprecated since version 3.3, to be removed in 4.0. - */ - public function addAutowiringType($type) - { - @trigger_error(sprintf('Autowiring-types are deprecated since Symfony 3.3 and will be removed in 4.0. Use aliases instead for "%s".', $type), E_USER_DEPRECATED); - - $this->autowiringTypes[$type] = true; - - return $this; - } - - /** - * Removes a type. - * - * @param string $type - * - * @return $this - * - * @deprecated since version 3.3, to be removed in 4.0. - */ - public function removeAutowiringType($type) - { - @trigger_error(sprintf('Autowiring-types are deprecated since Symfony 3.3 and will be removed in 4.0. Use aliases instead for "%s".', $type), E_USER_DEPRECATED); - - unset($this->autowiringTypes[$type]); - - return $this; - } - - /** - * Will this definition default for the given type? - * - * @param string $type - * - * @return bool - * - * @deprecated since version 3.3, to be removed in 4.0. - */ - public function hasAutowiringType($type) - { - @trigger_error(sprintf('Autowiring-types are deprecated since Symfony 3.3 and will be removed in 4.0. Use aliases instead for "%s".', $type), E_USER_DEPRECATED); - - return isset($this->autowiringTypes[$type]); - } } diff --git a/src/Symfony/Component/DependencyInjection/Dumper/XmlDumper.php b/src/Symfony/Component/DependencyInjection/Dumper/XmlDumper.php index c00c2167e2bab..08308d375fd04 100644 --- a/src/Symfony/Component/DependencyInjection/Dumper/XmlDumper.php +++ b/src/Symfony/Component/DependencyInjection/Dumper/XmlDumper.php @@ -198,13 +198,6 @@ private function addService($definition, $id, \DOMElement $parent) $service->setAttribute('autowire', 'true'); } - foreach ($definition->getAutowiringTypes(false) as $autowiringTypeValue) { - $autowiringType = $this->document->createElement('autowiring-type'); - $autowiringType->appendChild($this->document->createTextNode($autowiringTypeValue)); - - $service->appendChild($autowiringType); - } - if ($definition->isAutoconfigured()) { $service->setAttribute('autoconfigure', 'true'); } diff --git a/src/Symfony/Component/DependencyInjection/Dumper/YamlDumper.php b/src/Symfony/Component/DependencyInjection/Dumper/YamlDumper.php index 81951fe536699..fdb1199f58a3c 100644 --- a/src/Symfony/Component/DependencyInjection/Dumper/YamlDumper.php +++ b/src/Symfony/Component/DependencyInjection/Dumper/YamlDumper.php @@ -109,14 +109,6 @@ private function addService($id, $definition) $code .= " autowire: true\n"; } - $autowiringTypesCode = ''; - foreach ($definition->getAutowiringTypes(false) as $autowiringType) { - $autowiringTypesCode .= sprintf(" - %s\n", $this->dumper->dump($autowiringType)); - } - if ($autowiringTypesCode) { - $code .= sprintf(" autowiring_types:\n%s", $autowiringTypesCode); - } - if ($definition->isLazy()) { $code .= " lazy: true\n"; } diff --git a/src/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php b/src/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php index 79c8fbf9677ab..1ba35a6e786e8 100644 --- a/src/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php +++ b/src/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php @@ -341,10 +341,6 @@ private function parseDefinition(\DOMElement $service, $file, array $defaults) $definition->addTag($tag->getAttribute('name'), $parameters); } - foreach ($this->getChildren($service, 'autowiring-type') as $type) { - $definition->addAutowiringType($type->textContent); - } - if ($value = $service->getAttribute('decorates')) { $renameId = $service->hasAttribute('decoration-inner-name') ? $service->getAttribute('decoration-inner-name') : null; $priority = $service->hasAttribute('decoration-priority') ? $service->getAttribute('decoration-priority') : 0; diff --git a/src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php b/src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php index 19d919f2eda0e..c6a1b821086e7 100644 --- a/src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php +++ b/src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php @@ -55,7 +55,6 @@ class YamlFileLoader extends FileLoader 'decoration_inner_name' => 'decoration_inner_name', 'decoration_priority' => 'decoration_priority', 'autowire' => 'autowire', - 'autowiring_types' => 'autowiring_types', 'autoconfigure' => 'autoconfigure', ); @@ -500,24 +499,6 @@ private function parseDefinition($id, $service, $file, array $defaults) $definition->setAutowired($service['autowire']); } - if (isset($service['autowiring_types'])) { - if (is_string($service['autowiring_types'])) { - $definition->addAutowiringType($service['autowiring_types']); - } else { - if (!is_array($service['autowiring_types'])) { - throw new InvalidArgumentException(sprintf('Parameter "autowiring_types" must be a string or an array for service "%s" in %s. Check your YAML syntax.', $id, $file)); - } - - foreach ($service['autowiring_types'] as $autowiringType) { - if (!is_string($autowiringType)) { - throw new InvalidArgumentException(sprintf('A "autowiring_types" attribute must be of type string for service "%s" in %s. Check your YAML syntax.', $id, $file)); - } - - $definition->addAutowiringType($autowiringType); - } - } - } - if (isset($service['autoconfigure'])) { if (!$definition instanceof ChildDefinition) { $definition->setAutoconfigured($service['autoconfigure']); diff --git a/src/Symfony/Component/DependencyInjection/Loader/schema/dic/services/services-1.0.xsd b/src/Symfony/Component/DependencyInjection/Loader/schema/dic/services/services-1.0.xsd index 2de786bdb7cba..1c5b2d9089cc6 100644 --- a/src/Symfony/Component/DependencyInjection/Loader/schema/dic/services/services-1.0.xsd +++ b/src/Symfony/Component/DependencyInjection/Loader/schema/dic/services/services-1.0.xsd @@ -116,7 +116,6 @@ - diff --git a/src/Symfony/Component/DependencyInjection/Tests/Compiler/DecoratorServicePassTest.php b/src/Symfony/Component/DependencyInjection/Tests/Compiler/DecoratorServicePassTest.php index 4430e83e983d2..8c51df86f6811 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Compiler/DecoratorServicePassTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Compiler/DecoratorServicePassTest.php @@ -144,30 +144,6 @@ public function testProcessMovesTagsFromDecoratedDefinitionToDecoratingDefinitio $this->assertEquals(array('bar' => array('attr' => 'baz'), 'foobar' => array('attr' => 'bar')), $container->getDefinition('baz')->getTags()); } - /** - * @group legacy - */ - public function testProcessMergesAutowiringTypesInDecoratingDefinitionAndRemoveThemFromDecoratedDefinition() - { - $container = new ContainerBuilder(); - - $container - ->register('parent') - ->addAutowiringType('Bar') - ; - - $container - ->register('child') - ->setDecoratedService('parent') - ->addAutowiringType('Foo') - ; - - $this->process($container); - - $this->assertEquals(array('Bar', 'Foo'), $container->getDefinition('child')->getAutowiringTypes()); - $this->assertEmpty($container->getDefinition('child.inner')->getAutowiringTypes()); - } - protected function process(ContainerBuilder $container) { $repeatedPass = new DecoratorServicePass(); diff --git a/src/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveDefinitionTemplatesPassTest.php b/src/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveDefinitionTemplatesPassTest.php index 9c64c502f659a..323aa003ef1c7 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveDefinitionTemplatesPassTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveDefinitionTemplatesPassTest.php @@ -324,32 +324,6 @@ public function testDecoratedServiceCanOverwriteDeprecatedParentStatus() $this->assertFalse($container->getDefinition('decorated_deprecated_parent')->isDeprecated()); } - /** - * @group legacy - */ - public function testProcessMergeAutowiringTypes() - { - $container = new ContainerBuilder(); - - $container - ->register('parent') - ->addAutowiringType('Foo') - ; - - $container - ->setDefinition('child', new ChildDefinition('parent')) - ->addAutowiringType('Bar') - ; - - $this->process($container); - - $childDef = $container->getDefinition('child'); - $this->assertEquals(array('Foo', 'Bar'), $childDef->getAutowiringTypes()); - - $parentDef = $container->getDefinition('parent'); - $this->assertSame(array('Foo'), $parentDef->getAutowiringTypes()); - } - public function testProcessResolvesAliases() { $container = new ContainerBuilder(); diff --git a/src/Symfony/Component/DependencyInjection/Tests/DefinitionTest.php b/src/Symfony/Component/DependencyInjection/Tests/DefinitionTest.php index 2821dc17c0dc2..283bb5cc75127 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/DefinitionTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/DefinitionTest.php @@ -364,22 +364,6 @@ public function testGetChangesWithChanges() $this->assertSame(array(), $def->getChanges()); } - /** - * @group legacy - */ - public function testTypes() - { - $def = new Definition('stdClass'); - - $this->assertEquals(array(), $def->getAutowiringTypes()); - $this->assertSame($def, $def->setAutowiringTypes(array('Foo'))); - $this->assertEquals(array('Foo'), $def->getAutowiringTypes()); - $this->assertSame($def, $def->addAutowiringType('Bar')); - $this->assertTrue($def->hasAutowiringType('Bar')); - $this->assertSame($def, $def->removeAutowiringType('Foo')); - $this->assertEquals(array('Bar'), $def->getAutowiringTypes()); - } - public function testShouldAutoconfigure() { $def = new Definition('stdClass'); diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services22.xml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services22.xml deleted file mode 100644 index fa79d389489fb..0000000000000 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services22.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - - Bar - Baz - - - diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/bad_types1.yml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/bad_types1.yml deleted file mode 100644 index 891e01497cadf..0000000000000 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/bad_types1.yml +++ /dev/null @@ -1,5 +0,0 @@ -services: - foo_service: - class: FooClass - # types is not an array - autowiring_types: 1 diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/bad_types2.yml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/bad_types2.yml deleted file mode 100644 index fb1d53e151014..0000000000000 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/bad_types2.yml +++ /dev/null @@ -1,5 +0,0 @@ -services: - foo_service: - class: FooClass - # autowiring_types is not a string - autowiring_types: [ 1 ] diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services22.yml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services22.yml deleted file mode 100644 index 55d015baea0fb..0000000000000 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services22.yml +++ /dev/null @@ -1,8 +0,0 @@ -services: - foo_service: - class: FooClass - autowiring_types: [ Foo, Bar ] - - baz_service: - class: Baz - autowiring_types: Foo diff --git a/src/Symfony/Component/DependencyInjection/Tests/Loader/XmlFileLoaderTest.php b/src/Symfony/Component/DependencyInjection/Tests/Loader/XmlFileLoaderTest.php index 41d1c48d54bcc..bcfeee0fdf5e5 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Loader/XmlFileLoaderTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Loader/XmlFileLoaderTest.php @@ -563,18 +563,6 @@ public function testLoadInlinedServices() $this->assertSame('configureBar', $barConfigurator[1]); } - /** - * @group legacy - */ - public function testType() - { - $container = new ContainerBuilder(); - $loader = new XmlFileLoader($container, new FileLocator(self::$fixturesPath.'/xml')); - $loader->load('services22.xml'); - - $this->assertEquals(array('Bar', 'Baz'), $container->getDefinition('foo')->getAutowiringTypes()); - } - public function testAutowire() { $container = new ContainerBuilder(); diff --git a/src/Symfony/Component/DependencyInjection/Tests/Loader/YamlFileLoaderTest.php b/src/Symfony/Component/DependencyInjection/Tests/Loader/YamlFileLoaderTest.php index 31194da917cb2..622bacf6944db 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Loader/YamlFileLoaderTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Loader/YamlFileLoaderTest.php @@ -307,37 +307,6 @@ public function testTagWithNonStringNameThrowsException() $loader->load('tag_name_no_string.yml'); } - /** - * @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException - */ - public function testTypesNotArray() - { - $loader = new YamlFileLoader(new ContainerBuilder(), new FileLocator(self::$fixturesPath.'/yaml')); - $loader->load('bad_types1.yml'); - } - - /** - * @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException - */ - public function testTypeNotString() - { - $loader = new YamlFileLoader(new ContainerBuilder(), new FileLocator(self::$fixturesPath.'/yaml')); - $loader->load('bad_types2.yml'); - } - - /** - * @group legacy - */ - public function testTypes() - { - $container = new ContainerBuilder(); - $loader = new YamlFileLoader($container, new FileLocator(self::$fixturesPath.'/yaml')); - $loader->load('services22.yml'); - - $this->assertEquals(array('Foo', 'Bar'), $container->getDefinition('foo_service')->getAutowiringTypes()); - $this->assertEquals(array('Foo'), $container->getDefinition('baz_service')->getAutowiringTypes()); - } - public function testParsesIteratorArgument() { $container = new ContainerBuilder(); From e0eb2472295c614ccb8f942cd3bc68d19b706de0 Mon Sep 17 00:00:00 2001 From: Roland Franssen Date: Sat, 20 May 2017 16:32:28 +0200 Subject: [PATCH 0056/1099] [DI] Deprecate Container::initialized() for privates --- .../DependencyInjection/CHANGELOG.md | 5 ++++ .../DependencyInjection/Container.php | 4 +++ .../Tests/ContainerTest.php | 25 +++++++++++++++++-- 3 files changed, 32 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/DependencyInjection/CHANGELOG.md b/src/Symfony/Component/DependencyInjection/CHANGELOG.md index a85de7dff882c..6ae0daa20efb7 100644 --- a/src/Symfony/Component/DependencyInjection/CHANGELOG.md +++ b/src/Symfony/Component/DependencyInjection/CHANGELOG.md @@ -1,6 +1,11 @@ CHANGELOG ========= +3.4.0 +----- + + * deprecated the ability to check for the initialization of a private service with the `Container::initialized()` method + 3.3.0 ----- diff --git a/src/Symfony/Component/DependencyInjection/Container.php b/src/Symfony/Component/DependencyInjection/Container.php index 05e038ac5cb63..08ceec494883f 100644 --- a/src/Symfony/Component/DependencyInjection/Container.php +++ b/src/Symfony/Component/DependencyInjection/Container.php @@ -370,6 +370,10 @@ public function initialized($id) $id = $this->aliases[$id]; } + if (isset($this->privates[$id])) { + @trigger_error(sprintf('Checking for the initialization of the "%s" private service is deprecated since Symfony 3.4 and won\'t be supported anymore in Symfony 4.0.', $id), E_USER_DEPRECATED); + } + return isset($this->services[$id]); } diff --git a/src/Symfony/Component/DependencyInjection/Tests/ContainerTest.php b/src/Symfony/Component/DependencyInjection/Tests/ContainerTest.php index 99419201c6389..9a49060fa5e68 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/ContainerTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/ContainerTest.php @@ -147,7 +147,7 @@ public function testGetServiceIds() $sc = new ProjectServiceContainer(); $sc->set('foo', $obj = new \stdClass()); - $this->assertEquals(array('service_container', 'internal', 'bar', 'foo_bar', 'foo.baz', 'circular', 'throw_exception', 'throws_exception_on_service_configuration', 'foo'), $sc->getServiceIds(), '->getServiceIds() returns defined service ids by factory methods in the method map, followed by service ids defined by set()'); + $this->assertEquals(array('service_container', 'internal', 'bar', 'foo_bar', 'foo.baz', 'circular', 'throw_exception', 'throws_exception_on_service_configuration', 'internal_dependency', 'foo'), $sc->getServiceIds(), '->getServiceIds() returns defined service ids by factory methods in the method map, followed by service ids defined by set()'); } /** @@ -363,6 +363,17 @@ public function testInitialized() $this->assertTrue($sc->initialized('alias'), '->initialized() returns true for alias if aliased service is initialized'); } + /** + * @group legacy + * @expectedDeprecation Checking for the initialization of the "internal" private service is deprecated since Symfony 3.4 and won't be supported anymore in Symfony 4.0. + */ + public function testInitializedWithPrivateService() + { + $sc = new ProjectServiceContainer(); + $sc->get('internal_dependency'); + $this->assertTrue($sc->initialized('internal')); + } + public function testReset() { $c = new Container(); @@ -504,6 +515,7 @@ class ProjectServiceContainer extends Container 'circular' => 'getCircularService', 'throw_exception' => 'getThrowExceptionService', 'throws_exception_on_service_configuration' => 'getThrowsExceptionOnServiceConfigurationService', + 'internal_dependency' => 'getInternalDependencyService', ); public function __construct() @@ -520,7 +532,7 @@ public function __construct() protected function getInternalService() { - return $this->__internal; + return $this->services['internal'] = $this->__internal; } protected function getBarService() @@ -554,6 +566,15 @@ protected function getThrowsExceptionOnServiceConfigurationService() throw new \Exception('Something was terribly wrong while trying to configure the service!'); } + + protected function getInternalDependencyService() + { + $this->services['internal_dependency'] = $instance = new \stdClass(); + + $instance->internal = isset($this->services['internal']) ? $this->services['internal'] : $this->getInternalService(); + + return $instance; + } } class LegacyProjectServiceContainer extends Container From 928da1ab57a9ee1839430466d7e77fd3dfebad3a Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Mon, 22 May 2017 21:41:19 +0200 Subject: [PATCH 0057/1099] [Form] remove deprecated features --- src/Symfony/Component/Form/CHANGELOG.md | 13 ++ .../Factory/PropertyAccessDecorator.php | 28 +--- .../Form/ChoiceList/LazyChoiceList.php | 101 +------------- .../Form/Extension/Core/Type/ChoiceType.php | 18 --- .../Form/Extension/Core/Type/CountryType.php | 11 +- .../Form/Extension/Core/Type/CurrencyType.php | 11 +- .../Form/Extension/Core/Type/LanguageType.php | 11 +- .../Form/Extension/Core/Type/LocaleType.php | 11 +- .../Form/Extension/Core/Type/TimezoneType.php | 11 +- .../Factory/PropertyAccessDecoratorTest.php | 130 ------------------ .../Tests/ChoiceList/LazyChoiceListTest.php | 61 +------- .../Core/Type/ExtendedChoiceTypeTest.php | 20 --- 12 files changed, 35 insertions(+), 391 deletions(-) diff --git a/src/Symfony/Component/Form/CHANGELOG.md b/src/Symfony/Component/Form/CHANGELOG.md index 1c8936995c226..9f5e6e23e7eba 100644 --- a/src/Symfony/Component/Form/CHANGELOG.md +++ b/src/Symfony/Component/Form/CHANGELOG.md @@ -1,6 +1,19 @@ CHANGELOG ========= +4.0.0 +----- + + * using the `choices` option in `CountryType`, `CurrencyType`, `LanguageType`, + `LocaleType`, and `TimezoneType` when the `choice_loader` option is not `null` + is not supported anymore and the configured choices will be ignored + * callable strings that are passed to the options of the `ChoiceType` are + treated as property paths + * the `choices_as_values` option of the `ChoiceType` has been removed + * removed the support for caching loaded choice lists in `LazyChoiceList`, + cache the choice list in the used `ChoiceLoaderInterface` implementation + instead + 3.3.0 ----- diff --git a/src/Symfony/Component/Form/ChoiceList/Factory/PropertyAccessDecorator.php b/src/Symfony/Component/Form/ChoiceList/Factory/PropertyAccessDecorator.php index 0e282f7083da5..5604e6910bc48 100644 --- a/src/Symfony/Component/Form/ChoiceList/Factory/PropertyAccessDecorator.php +++ b/src/Symfony/Component/Form/ChoiceList/Factory/PropertyAccessDecorator.php @@ -84,10 +84,8 @@ public function getDecoratedFactory() */ public function createListFromChoices($choices, $value = null) { - if (is_string($value) && !is_callable($value)) { + if (is_string($value)) { $value = new PropertyPath($value); - } elseif (is_string($value) && is_callable($value)) { - @trigger_error('Passing callable strings is deprecated since version 3.1 and PropertyAccessDecorator will treat them as property paths in 4.0. You should use a "\Closure" instead.', E_USER_DEPRECATED); } if ($value instanceof PropertyPath) { @@ -117,10 +115,8 @@ public function createListFromChoices($choices, $value = null) */ public function createListFromLoader(ChoiceLoaderInterface $loader, $value = null) { - if (is_string($value) && !is_callable($value)) { + if (is_string($value)) { $value = new PropertyPath($value); - } elseif (is_string($value) && is_callable($value)) { - @trigger_error('Passing callable strings is deprecated since version 3.1 and PropertyAccessDecorator will treat them as property paths in 4.0. You should use a "\Closure" instead.', E_USER_DEPRECATED); } if ($value instanceof PropertyPath) { @@ -155,10 +151,8 @@ public function createView(ChoiceListInterface $list, $preferredChoices = null, { $accessor = $this->propertyAccessor; - if (is_string($label) && !is_callable($label)) { + if (is_string($label)) { $label = new PropertyPath($label); - } elseif (is_string($label) && is_callable($label)) { - @trigger_error('Passing callable strings is deprecated since version 3.1 and PropertyAccessDecorator will treat them as property paths in 4.0. You should use a "\Closure" instead.', E_USER_DEPRECATED); } if ($label instanceof PropertyPath) { @@ -167,10 +161,8 @@ public function createView(ChoiceListInterface $list, $preferredChoices = null, }; } - if (is_string($preferredChoices) && !is_callable($preferredChoices)) { + if (is_string($preferredChoices)) { $preferredChoices = new PropertyPath($preferredChoices); - } elseif (is_string($preferredChoices) && is_callable($preferredChoices)) { - @trigger_error('Passing callable strings is deprecated since version 3.1 and PropertyAccessDecorator will treat them as property paths in 4.0. You should use a "\Closure" instead.', E_USER_DEPRECATED); } if ($preferredChoices instanceof PropertyPath) { @@ -184,10 +176,8 @@ public function createView(ChoiceListInterface $list, $preferredChoices = null, }; } - if (is_string($index) && !is_callable($index)) { + if (is_string($index)) { $index = new PropertyPath($index); - } elseif (is_string($index) && is_callable($index)) { - @trigger_error('Passing callable strings is deprecated since version 3.1 and PropertyAccessDecorator will treat them as property paths in 4.0. You should use a "\Closure" instead.', E_USER_DEPRECATED); } if ($index instanceof PropertyPath) { @@ -196,10 +186,8 @@ public function createView(ChoiceListInterface $list, $preferredChoices = null, }; } - if (is_string($groupBy) && !is_callable($groupBy)) { + if (is_string($groupBy)) { $groupBy = new PropertyPath($groupBy); - } elseif (is_string($groupBy) && is_callable($groupBy)) { - @trigger_error('Passing callable strings is deprecated since version 3.1 and PropertyAccessDecorator will treat them as property paths in 4.0. You should use a "\Closure" instead.', E_USER_DEPRECATED); } if ($groupBy instanceof PropertyPath) { @@ -212,10 +200,8 @@ public function createView(ChoiceListInterface $list, $preferredChoices = null, }; } - if (is_string($attr) && !is_callable($attr)) { + if (is_string($attr)) { $attr = new PropertyPath($attr); - } elseif (is_string($attr) && is_callable($attr)) { - @trigger_error('Passing callable strings is deprecated since version 3.1 and PropertyAccessDecorator will treat them as property paths in 4.0. You should use a "\Closure" instead.', E_USER_DEPRECATED); } if ($attr instanceof PropertyPath) { diff --git a/src/Symfony/Component/Form/ChoiceList/LazyChoiceList.php b/src/Symfony/Component/Form/ChoiceList/LazyChoiceList.php index e8e37b359566f..9e759afa6eb71 100644 --- a/src/Symfony/Component/Form/ChoiceList/LazyChoiceList.php +++ b/src/Symfony/Component/Form/ChoiceList/LazyChoiceList.php @@ -43,20 +43,6 @@ class LazyChoiceList implements ChoiceListInterface */ private $value; - /** - * @var ChoiceListInterface|null - * - * @deprecated Since 3.1, to be removed in 4.0. Cache the choice list in the {@link ChoiceLoaderInterface} instead. - */ - private $loadedList; - - /** - * @var bool - * - * @deprecated Flag used for BC layer since 3.1. To be removed in 4.0. - */ - private $loaded = false; - /** * Creates a lazily-loaded list using the given loader. * @@ -79,23 +65,7 @@ public function __construct(ChoiceLoaderInterface $loader, callable $value = nul */ public function getChoices() { - if ($this->loaded) { - // We can safely invoke the {@link ChoiceLoaderInterface} assuming it has the list - // in cache when the lazy list is already loaded - if ($this->loadedList !== $this->loader->loadChoiceList($this->value)) { - @trigger_error(sprintf('Caching the choice list in %s is deprecated since 3.1 and will not happen in 4.0. Cache the list in the %s instead.', __CLASS__, ChoiceLoaderInterface::class), E_USER_DEPRECATED); - } - - return $this->loadedList->getChoices(); - } - - // BC - $this->loadedList = $this->loader->loadChoiceList($this->value); - $this->loaded = true; - - return $this->loadedList->getChoices(); - // In 4.0 keep the following line only: - // return $this->loader->loadChoiceList($this->value)->getChoices() + return $this->loader->loadChoiceList($this->value)->getChoices(); } /** @@ -103,22 +73,7 @@ public function getChoices() */ public function getValues() { - if ($this->loaded) { - // Check whether the loader has the same cache - if ($this->loadedList !== $this->loader->loadChoiceList($this->value)) { - @trigger_error(sprintf('Caching the choice list in %s is deprecated since 3.1 and will not happen in 4.0. Cache the list in the %s instead.', __CLASS__, ChoiceLoaderInterface::class), E_USER_DEPRECATED); - } - - return $this->loadedList->getValues(); - } - - // BC - $this->loadedList = $this->loader->loadChoiceList($this->value); - $this->loaded = true; - - return $this->loadedList->getValues(); - // In 4.0 keep the following line only: - // return $this->loader->loadChoiceList($this->value)->getValues() + return $this->loader->loadChoiceList($this->value)->getValues(); } /** @@ -126,22 +81,7 @@ public function getValues() */ public function getStructuredValues() { - if ($this->loaded) { - // Check whether the loader has the same cache - if ($this->loadedList !== $this->loader->loadChoiceList($this->value)) { - @trigger_error(sprintf('Caching the choice list in %s is deprecated since 3.1 and will not happen in 4.0. Cache the list in the %s instead.', __CLASS__, ChoiceLoaderInterface::class), E_USER_DEPRECATED); - } - - return $this->loadedList->getStructuredValues(); - } - - // BC - $this->loadedList = $this->loader->loadChoiceList($this->value); - $this->loaded = true; - - return $this->loadedList->getStructuredValues(); - // In 4.0 keep the following line only: - // return $this->loader->loadChoiceList($this->value)->getStructuredValues(); + return $this->loader->loadChoiceList($this->value)->getStructuredValues(); } /** @@ -149,22 +89,7 @@ public function getStructuredValues() */ public function getOriginalKeys() { - if ($this->loaded) { - // Check whether the loader has the same cache - if ($this->loadedList !== $this->loader->loadChoiceList($this->value)) { - @trigger_error(sprintf('Caching the choice list in %s is deprecated since 3.1 and will not happen in 4.0. Cache the list in the %s instead.', __CLASS__, ChoiceLoaderInterface::class), E_USER_DEPRECATED); - } - - return $this->loadedList->getOriginalKeys(); - } - - // BC - $this->loadedList = $this->loader->loadChoiceList($this->value); - $this->loaded = true; - - return $this->loadedList->getOriginalKeys(); - // In 4.0 keep the following line only: - // return $this->loader->loadChoiceList($this->value)->getOriginalKeys(); + return $this->loader->loadChoiceList($this->value)->getOriginalKeys(); } /** @@ -172,15 +97,6 @@ public function getOriginalKeys() */ public function getChoicesForValues(array $values) { - if ($this->loaded) { - // Check whether the loader has the same cache - if ($this->loadedList !== $this->loader->loadChoiceList($this->value)) { - @trigger_error(sprintf('Caching the choice list in %s is deprecated since 3.1 and will not happen in 4.0. Cache the list in the %s instead.', __CLASS__, ChoiceLoaderInterface::class), E_USER_DEPRECATED); - } - - return $this->loadedList->getChoicesForValues($values); - } - return $this->loader->loadChoicesForValues($values, $this->value); } @@ -189,15 +105,6 @@ public function getChoicesForValues(array $values) */ public function getValuesForChoices(array $choices) { - if ($this->loaded) { - // Check whether the loader has the same cache - if ($this->loadedList !== $this->loader->loadChoiceList($this->value)) { - @trigger_error(sprintf('Caching the choice list in %s is deprecated since 3.1 and will not happen in 4.0. Cache the list in the %s instead.', __CLASS__, ChoiceLoaderInterface::class), E_USER_DEPRECATED); - } - - return $this->loadedList->getValuesForChoices($choices); - } - return $this->loader->loadValuesForChoices($choices, $this->value); } } diff --git a/src/Symfony/Component/Form/Extension/Core/Type/ChoiceType.php b/src/Symfony/Component/Form/Extension/Core/Type/ChoiceType.php index 25bb52f2903c6..1836c4a6c0ed3 100644 --- a/src/Symfony/Component/Form/Extension/Core/Type/ChoiceType.php +++ b/src/Symfony/Component/Form/Extension/Core/Type/ChoiceType.php @@ -273,22 +273,6 @@ public function configureOptions(OptionsResolver $resolver) return $options['required'] ? null : ''; }; - $choicesAsValuesNormalizer = function (Options $options, $choicesAsValues) { - // Not set by the user - if (null === $choicesAsValues) { - return true; - } - - // 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))); - } - - @trigger_error('The "choices_as_values" option is deprecated since version 3.1 and will be removed in 4.0. You should not use it anymore.', E_USER_DEPRECATED); - - return true; - }; - $placeholderNormalizer = function (Options $options, $placeholder) { if ($options['multiple']) { // never use an empty value for this case @@ -324,7 +308,6 @@ public function configureOptions(OptionsResolver $resolver) 'multiple' => false, 'expanded' => false, 'choices' => array(), - 'choices_as_values' => null, // deprecated since 3.1 'choice_loader' => null, 'choice_label' => null, 'choice_name' => null, @@ -345,7 +328,6 @@ public function configureOptions(OptionsResolver $resolver) $resolver->setNormalizer('placeholder', $placeholderNormalizer); $resolver->setNormalizer('choice_translation_domain', $choiceTranslationDomainNormalizer); - $resolver->setNormalizer('choices_as_values', $choicesAsValuesNormalizer); $resolver->setAllowedTypes('choices', array('null', 'array', '\Traversable')); $resolver->setAllowedTypes('choice_translation_domain', array('null', 'bool', 'string')); diff --git a/src/Symfony/Component/Form/Extension/Core/Type/CountryType.php b/src/Symfony/Component/Form/Extension/Core/Type/CountryType.php index 02e8e09cdc824..a96a42d3d6b67 100644 --- a/src/Symfony/Component/Form/Extension/Core/Type/CountryType.php +++ b/src/Symfony/Component/Form/Extension/Core/Type/CountryType.php @@ -15,7 +15,6 @@ use Symfony\Component\Form\ChoiceList\ArrayChoiceList; use Symfony\Component\Form\ChoiceList\Loader\ChoiceLoaderInterface; use Symfony\Component\Intl\Intl; -use Symfony\Component\OptionsResolver\Options; use Symfony\Component\OptionsResolver\OptionsResolver; class CountryType extends AbstractType implements ChoiceLoaderInterface @@ -37,15 +36,7 @@ class CountryType extends AbstractType implements ChoiceLoaderInterface public function configureOptions(OptionsResolver $resolver) { $resolver->setDefaults(array( - 'choice_loader' => function (Options $options) { - if ($options['choices']) { - @trigger_error(sprintf('Using the "choices" option in %s has been deprecated since version 3.3 and will be ignored in 4.0. Override the "choice_loader" option instead or set it to null.', __CLASS__), E_USER_DEPRECATED); - - return null; - } - - return $this; - }, + 'choice_loader' => $this, 'choice_translation_domain' => false, )); } diff --git a/src/Symfony/Component/Form/Extension/Core/Type/CurrencyType.php b/src/Symfony/Component/Form/Extension/Core/Type/CurrencyType.php index 990235c10a99a..9970d03ad7195 100644 --- a/src/Symfony/Component/Form/Extension/Core/Type/CurrencyType.php +++ b/src/Symfony/Component/Form/Extension/Core/Type/CurrencyType.php @@ -15,7 +15,6 @@ use Symfony\Component\Form\ChoiceList\ArrayChoiceList; use Symfony\Component\Form\ChoiceList\Loader\ChoiceLoaderInterface; use Symfony\Component\Intl\Intl; -use Symfony\Component\OptionsResolver\Options; use Symfony\Component\OptionsResolver\OptionsResolver; class CurrencyType extends AbstractType implements ChoiceLoaderInterface @@ -37,15 +36,7 @@ class CurrencyType extends AbstractType implements ChoiceLoaderInterface public function configureOptions(OptionsResolver $resolver) { $resolver->setDefaults(array( - 'choice_loader' => function (Options $options) { - if ($options['choices']) { - @trigger_error(sprintf('Using the "choices" option in %s has been deprecated since version 3.3 and will be ignored in 4.0. Override the "choice_loader" option instead or set it to null.', __CLASS__), E_USER_DEPRECATED); - - return null; - } - - return $this; - }, + 'choice_loader' => $this, 'choice_translation_domain' => false, )); } diff --git a/src/Symfony/Component/Form/Extension/Core/Type/LanguageType.php b/src/Symfony/Component/Form/Extension/Core/Type/LanguageType.php index 2137c65a9e440..279402a3e28e3 100644 --- a/src/Symfony/Component/Form/Extension/Core/Type/LanguageType.php +++ b/src/Symfony/Component/Form/Extension/Core/Type/LanguageType.php @@ -15,7 +15,6 @@ use Symfony\Component\Form\ChoiceList\ArrayChoiceList; use Symfony\Component\Form\ChoiceList\Loader\ChoiceLoaderInterface; use Symfony\Component\Intl\Intl; -use Symfony\Component\OptionsResolver\Options; use Symfony\Component\OptionsResolver\OptionsResolver; class LanguageType extends AbstractType implements ChoiceLoaderInterface @@ -37,15 +36,7 @@ class LanguageType extends AbstractType implements ChoiceLoaderInterface public function configureOptions(OptionsResolver $resolver) { $resolver->setDefaults(array( - 'choice_loader' => function (Options $options) { - if ($options['choices']) { - @trigger_error(sprintf('Using the "choices" option in %s has been deprecated since version 3.3 and will be ignored in 4.0. Override the "choice_loader" option instead or set it to null.', __CLASS__), E_USER_DEPRECATED); - - return null; - } - - return $this; - }, + 'choice_loader' => $this, 'choice_translation_domain' => false, )); } diff --git a/src/Symfony/Component/Form/Extension/Core/Type/LocaleType.php b/src/Symfony/Component/Form/Extension/Core/Type/LocaleType.php index 38e62af060d98..de795956b77a1 100644 --- a/src/Symfony/Component/Form/Extension/Core/Type/LocaleType.php +++ b/src/Symfony/Component/Form/Extension/Core/Type/LocaleType.php @@ -15,7 +15,6 @@ use Symfony\Component\Form\ChoiceList\ArrayChoiceList; use Symfony\Component\Form\ChoiceList\Loader\ChoiceLoaderInterface; use Symfony\Component\Intl\Intl; -use Symfony\Component\OptionsResolver\Options; use Symfony\Component\OptionsResolver\OptionsResolver; class LocaleType extends AbstractType implements ChoiceLoaderInterface @@ -37,15 +36,7 @@ class LocaleType extends AbstractType implements ChoiceLoaderInterface public function configureOptions(OptionsResolver $resolver) { $resolver->setDefaults(array( - 'choice_loader' => function (Options $options) { - if ($options['choices']) { - @trigger_error(sprintf('Using the "choices" option in %s has been deprecated since version 3.3 and will be ignored in 4.0. Override the "choice_loader" option instead or set it to null.', __CLASS__), E_USER_DEPRECATED); - - return null; - } - - return $this; - }, + 'choice_loader' => $this, 'choice_translation_domain' => false, )); } diff --git a/src/Symfony/Component/Form/Extension/Core/Type/TimezoneType.php b/src/Symfony/Component/Form/Extension/Core/Type/TimezoneType.php index ffa86cb9aa525..fbfce90ba50bb 100644 --- a/src/Symfony/Component/Form/Extension/Core/Type/TimezoneType.php +++ b/src/Symfony/Component/Form/Extension/Core/Type/TimezoneType.php @@ -14,7 +14,6 @@ use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\ChoiceList\ArrayChoiceList; use Symfony\Component\Form\ChoiceList\Loader\ChoiceLoaderInterface; -use Symfony\Component\OptionsResolver\Options; use Symfony\Component\OptionsResolver\OptionsResolver; class TimezoneType extends AbstractType implements ChoiceLoaderInterface @@ -34,15 +33,7 @@ class TimezoneType extends AbstractType implements ChoiceLoaderInterface public function configureOptions(OptionsResolver $resolver) { $resolver->setDefaults(array( - 'choice_loader' => function (Options $options) { - if ($options['choices']) { - @trigger_error(sprintf('Using the "choices" option in %s has been deprecated since version 3.3 and will be ignored in 4.0. Override the "choice_loader" option instead or set it to null.', __CLASS__), E_USER_DEPRECATED); - - return null; - } - - return $this; - }, + 'choice_loader' => $this, 'choice_translation_domain' => false, )); } diff --git a/src/Symfony/Component/Form/Tests/ChoiceList/Factory/PropertyAccessDecoratorTest.php b/src/Symfony/Component/Form/Tests/ChoiceList/Factory/PropertyAccessDecoratorTest.php index d100dcff4a5fd..43c91c363df88 100644 --- a/src/Symfony/Component/Form/Tests/ChoiceList/Factory/PropertyAccessDecoratorTest.php +++ b/src/Symfony/Component/Form/Tests/ChoiceList/Factory/PropertyAccessDecoratorTest.php @@ -64,21 +64,6 @@ public function testCreateFromChoicesPropertyPathInstance() $this->assertSame(array('value'), $this->factory->createListFromChoices($choices, new PropertyPath('property'))); } - /** - * @group legacy - */ - public function testCreateFromChoicesPropertyPathWithCallableString() - { - $choices = array('foo' => 'bar'); - - $this->decoratedFactory->expects($this->once()) - ->method('createListFromChoices') - ->with($choices, 'end') - ->willReturn('RESULT'); - - $this->assertSame('RESULT', $this->factory->createListFromChoices($choices, 'end')); - } - public function testCreateFromLoaderPropertyPath() { $loader = $this->getMockBuilder('Symfony\Component\Form\ChoiceList\Loader\ChoiceLoaderInterface')->getMock(); @@ -93,21 +78,6 @@ public function testCreateFromLoaderPropertyPath() $this->assertSame('value', $this->factory->createListFromLoader($loader, 'property')); } - /** - * @group legacy - */ - public function testCreateFromLoaderPropertyPathWithCallableString() - { - $loader = $this->getMockBuilder('Symfony\Component\Form\ChoiceList\Loader\ChoiceLoaderInterface')->getMock(); - - $this->decoratedFactory->expects($this->once()) - ->method('createListFromLoader') - ->with($loader, 'end') - ->willReturn('RESULT'); - - $this->assertSame('RESULT', $this->factory->createListFromLoader($loader, 'end')); - } - // https://github.com/symfony/symfony/issues/5494 public function testCreateFromChoicesAssumeNullIfValuePropertyPathUnreadable() { @@ -169,24 +139,6 @@ public function testCreateViewPreferredChoicesAsPropertyPath() )); } - /** - * @group legacy - */ - public function testCreateViewPreferredChoicesAsPropertyPathWithCallableString() - { - $list = $this->getMockBuilder('Symfony\Component\Form\ChoiceList\ChoiceListInterface')->getMock(); - - $this->decoratedFactory->expects($this->once()) - ->method('createView') - ->with($list, 'end') - ->willReturn('RESULT'); - - $this->assertSame('RESULT', $this->factory->createView( - $list, - 'end' - )); - } - public function testCreateViewPreferredChoicesAsPropertyPathInstance() { $list = $this->getMockBuilder('Symfony\Component\Form\ChoiceList\ChoiceListInterface')->getMock(); @@ -240,25 +192,6 @@ public function testCreateViewLabelsAsPropertyPath() )); } - /** - * @group legacy - */ - public function testCreateViewLabelsAsPropertyPathWithCallableString() - { - $list = $this->getMockBuilder('Symfony\Component\Form\ChoiceList\ChoiceListInterface')->getMock(); - - $this->decoratedFactory->expects($this->once()) - ->method('createView') - ->with($list, null, 'end') - ->willReturn('RESULT'); - - $this->assertSame('RESULT', $this->factory->createView( - $list, - null, // preferred choices - 'end' - )); - } - public function testCreateViewLabelsAsPropertyPathInstance() { $list = $this->getMockBuilder('Symfony\Component\Form\ChoiceList\ChoiceListInterface')->getMock(); @@ -296,26 +229,6 @@ public function testCreateViewIndicesAsPropertyPath() )); } - /** - * @group legacy - */ - public function testCreateViewIndicesAsPropertyPathWithCallableString() - { - $list = $this->getMockBuilder('Symfony\Component\Form\ChoiceList\ChoiceListInterface')->getMock(); - - $this->decoratedFactory->expects($this->once()) - ->method('createView') - ->with($list, null, null, 'end') - ->willReturn('RESULT'); - - $this->assertSame('RESULT', $this->factory->createView( - $list, - null, // preferred choices - null, // label - 'end' - )); - } - public function testCreateViewIndicesAsPropertyPathInstance() { $list = $this->getMockBuilder('Symfony\Component\Form\ChoiceList\ChoiceListInterface')->getMock(); @@ -355,27 +268,6 @@ public function testCreateViewGroupsAsPropertyPath() )); } - /** - * @group legacy - */ - public function testCreateViewGroupsAsPropertyPathWithCallableString() - { - $list = $this->getMockBuilder('Symfony\Component\Form\ChoiceList\ChoiceListInterface')->getMock(); - - $this->decoratedFactory->expects($this->once()) - ->method('createView') - ->with($list, null, null, null, 'end') - ->willReturn('RESULT'); - - $this->assertSame('RESULT', $this->factory->createView( - $list, - null, // preferred choices - null, // label - null, // index - 'end' - )); - } - public function testCreateViewGroupsAsPropertyPathInstance() { $list = $this->getMockBuilder('Symfony\Component\Form\ChoiceList\ChoiceListInterface')->getMock(); @@ -438,28 +330,6 @@ public function testCreateViewAttrAsPropertyPath() )); } - /** - * @group legacy - */ - public function testCreateViewAttrAsPropertyPathWithCallableString() - { - $list = $this->getMockBuilder('Symfony\Component\Form\ChoiceList\ChoiceListInterface')->getMock(); - - $this->decoratedFactory->expects($this->once()) - ->method('createView') - ->with($list, null, null, null, null, 'end') - ->willReturn('RESULT'); - - $this->assertSame('RESULT', $this->factory->createView( - $list, - null, // preferred choices - null, // label - null, // inde - null, // groups - 'end' - )); - } - public function testCreateViewAttrAsPropertyPathInstance() { $list = $this->getMockBuilder('Symfony\Component\Form\ChoiceList\ChoiceListInterface')->getMock(); diff --git a/src/Symfony/Component/Form/Tests/ChoiceList/LazyChoiceListTest.php b/src/Symfony/Component/Form/Tests/ChoiceList/LazyChoiceListTest.php index 61c8a5aa0b0e3..57b125925435f 100644 --- a/src/Symfony/Component/Form/Tests/ChoiceList/LazyChoiceListTest.php +++ b/src/Symfony/Component/Form/Tests/ChoiceList/LazyChoiceListTest.php @@ -12,7 +12,6 @@ namespace Symfony\Component\Form\Tests\ChoiceList; use PHPUnit\Framework\TestCase; -use Symfony\Component\Form\ChoiceList\ArrayChoiceList; use Symfony\Component\Form\ChoiceList\LazyChoiceList; /** @@ -61,30 +60,6 @@ public function testGetChoiceLoadersLoadsLoadedListOnFirstCall() $this->assertSame('RESULT', $this->list->getChoices()); } - /** - * @group legacy - */ - public function testGetChoicesUsesLoadedListWhenLoaderDoesNotCacheChoiceListOnFirstCall() - { - $this->loader->expects($this->at(0)) - ->method('loadChoiceList') - ->with($this->value) - ->willReturn($this->loadedList); - - $this->loader->expects($this->at(1)) - ->method('loadChoiceList') - ->with($this->value) - ->willReturn(new ArrayChoiceList(array('a', 'b'))); - - // The same list is returned by the lazy choice list - $this->loadedList->expects($this->exactly(2)) - ->method('getChoices') - ->will($this->returnValue('RESULT')); - - $this->assertSame('RESULT', $this->list->getChoices()); - $this->assertSame('RESULT', $this->list->getChoices()); - } - public function testGetValuesLoadsLoadedListOnFirstCall() { $this->loader->expects($this->exactly(2)) @@ -146,18 +121,13 @@ public function testGetChoicesForValuesForwardsCallIfListNotLoaded() public function testGetChoicesForValuesUsesLoadedList() { - $this->loader->expects($this->exactly(3)) + $this->loader->expects($this->exactly(1)) ->method('loadChoiceList') ->with($this->value) - // For BC, the same choice loaded list is returned 3 times - // It should only twice in 4.0 ->will($this->returnValue($this->loadedList)); - $this->loader->expects($this->never()) - ->method('loadChoicesForValues'); - - $this->loadedList->expects($this->exactly(2)) - ->method('getChoicesForValues') + $this->loader->expects($this->exactly(2)) + ->method('loadChoicesForValues') ->with(array('a', 'b')) ->will($this->returnValue('RESULT')); @@ -168,34 +138,15 @@ public function testGetChoicesForValuesUsesLoadedList() $this->assertSame('RESULT', $this->list->getChoicesForValues(array('a', 'b'))); } - /** - * @group legacy - */ - public function testGetValuesForChoicesForwardsCallIfListNotLoaded() - { - $this->loader->expects($this->exactly(2)) - ->method('loadValuesForChoices') - ->with(array('a', 'b')) - ->will($this->returnValue('RESULT')); - - $this->assertSame('RESULT', $this->list->getValuesForChoices(array('a', 'b'))); - $this->assertSame('RESULT', $this->list->getValuesForChoices(array('a', 'b'))); - } - public function testGetValuesForChoicesUsesLoadedList() { - $this->loader->expects($this->exactly(3)) + $this->loader->expects($this->exactly(1)) ->method('loadChoiceList') ->with($this->value) - // For BC, the same choice loaded list is returned 3 times - // It should only twice in 4.0 ->will($this->returnValue($this->loadedList)); - $this->loader->expects($this->never()) - ->method('loadValuesForChoices'); - - $this->loadedList->expects($this->exactly(2)) - ->method('getValuesForChoices') + $this->loader->expects($this->exactly(2)) + ->method('loadValuesForChoices') ->with(array('a', 'b')) ->will($this->returnValue('RESULT')); diff --git a/src/Symfony/Component/Form/Tests/Extension/Core/Type/ExtendedChoiceTypeTest.php b/src/Symfony/Component/Form/Tests/Extension/Core/Type/ExtendedChoiceTypeTest.php index 959ae488a1ee7..0475254d970a2 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Core/Type/ExtendedChoiceTypeTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Core/Type/ExtendedChoiceTypeTest.php @@ -18,26 +18,6 @@ class ExtendedChoiceTypeTest extends TestCase { - /** - * @group legacy - * @dataProvider provideTestedTypes - */ - public function testLegacyChoicesAreOverridden($type) - { - $factory = Forms::createFormFactoryBuilder() - ->addTypeExtension(new ChoiceTypeExtension($type)) - ->getFormFactory() - ; - - $choices = $factory->create($type)->createView()->vars['choices']; - - $this->assertCount(2, $choices); - $this->assertSame('A', $choices[0]->label); - $this->assertSame('a', $choices[0]->value); - $this->assertSame('B', $choices[1]->label); - $this->assertSame('b', $choices[1]->value); - } - /** * @dataProvider provideTestedTypes */ From 3a03de0787b07b0af046a65f19eb867ca5c53030 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Sun, 21 May 2017 11:15:41 +0200 Subject: [PATCH 0058/1099] [Translation] remove deprecated features --- .../Component/Translation/CHANGELOG.md | 5 ++++ .../Translation/Dumper/FileDumper.php | 23 ++++++------------- .../Tests/Dumper/FileDumperTest.php | 23 ------------------- .../Translation/Writer/TranslationWriter.php | 1 + 4 files changed, 13 insertions(+), 39 deletions(-) diff --git a/src/Symfony/Component/Translation/CHANGELOG.md b/src/Symfony/Component/Translation/CHANGELOG.md index 349faceb0c8f0..033b623e1b91e 100644 --- a/src/Symfony/Component/Translation/CHANGELOG.md +++ b/src/Symfony/Component/Translation/CHANGELOG.md @@ -1,6 +1,11 @@ CHANGELOG ========= +4.0.0 +----- + + * removed the backup feature of the `FileDumper` class + 3.2.0 ----- diff --git a/src/Symfony/Component/Translation/Dumper/FileDumper.php b/src/Symfony/Component/Translation/Dumper/FileDumper.php index b2b50cfc9470d..51b111821c8c1 100644 --- a/src/Symfony/Component/Translation/Dumper/FileDumper.php +++ b/src/Symfony/Component/Translation/Dumper/FileDumper.php @@ -17,7 +17,6 @@ /** * FileDumper is an implementation of DumperInterface that dump a message catalogue to file(s). - * Performs backup of already existing files. * * Options: * - path (mandatory): the directory where the files should be saved @@ -33,13 +32,6 @@ abstract class FileDumper implements DumperInterface */ protected $relativePathTemplate = '%domain%.%locale%.%extension%'; - /** - * Make file backup before the dump. - * - * @var bool - */ - private $backup = true; - /** * Sets the template for the relative paths to files. * @@ -57,7 +49,12 @@ public function setRelativePathTemplate($relativePathTemplate) */ public function setBackup($backup) { - $this->backup = $backup; + if (false !== $backup) { + throw new \LogicException('The backup feature is no longer supported.'); + } + + // the method is only present to not break BC + // to be deprecated in 4.1 } /** @@ -71,14 +68,8 @@ public function dump(MessageCatalogue $messages, $options = array()) // save a file for each domain foreach ($messages->getDomains() as $domain) { - // backup $fullpath = $options['path'].'/'.$this->getRelativePath($domain, $messages->getLocale()); - if (file_exists($fullpath)) { - if ($this->backup) { - @trigger_error('Creating a backup while dumping a message catalogue is deprecated since version 3.1 and will be removed in 4.0. Use TranslationWriter::disableBackup() to disable the backup.', E_USER_DEPRECATED); - copy($fullpath, $fullpath.'~'); - } - } else { + if (!file_exists($fullpath)) { $directory = dirname($fullpath); if (!file_exists($directory) && !@mkdir($directory, 0777, true)) { throw new RuntimeException(sprintf('Unable to create directory "%s".', $directory)); diff --git a/src/Symfony/Component/Translation/Tests/Dumper/FileDumperTest.php b/src/Symfony/Component/Translation/Tests/Dumper/FileDumperTest.php index 9ed4c91eca4cc..7c734fc169bc6 100644 --- a/src/Symfony/Component/Translation/Tests/Dumper/FileDumperTest.php +++ b/src/Symfony/Component/Translation/Tests/Dumper/FileDumperTest.php @@ -30,29 +30,6 @@ public function testDump() $this->assertFileExists($tempDir.'/messages.en.concrete'); } - /** - * @group legacy - */ - public function testDumpBackupsFileIfExisting() - { - $tempDir = sys_get_temp_dir(); - $file = $tempDir.'/messages.en.concrete'; - $backupFile = $file.'~'; - - @touch($file); - - $catalogue = new MessageCatalogue('en'); - $catalogue->add(array('foo' => 'bar')); - - $dumper = new ConcreteFileDumper(); - $dumper->dump($catalogue, array('path' => $tempDir)); - - $this->assertFileExists($backupFile); - - @unlink($file); - @unlink($backupFile); - } - public function testDumpCreatesNestedDirectoriesAndFile() { $tempDir = sys_get_temp_dir(); diff --git a/src/Symfony/Component/Translation/Writer/TranslationWriter.php b/src/Symfony/Component/Translation/Writer/TranslationWriter.php index 901a8894e1c4c..6c10fb2e82ca6 100644 --- a/src/Symfony/Component/Translation/Writer/TranslationWriter.php +++ b/src/Symfony/Component/Translation/Writer/TranslationWriter.php @@ -46,6 +46,7 @@ public function addDumper($format, DumperInterface $dumper) */ public function disableBackup() { + // to be deprecated in 4.1 foreach ($this->dumpers as $dumper) { if (method_exists($dumper, 'setBackup')) { $dumper->setBackup(false); From 3b6c495c89d2ca7fe62d6c8014d86eef31157dd3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9my=20Deruss=C3=A9?= Date: Mon, 1 May 2017 17:32:30 +0200 Subject: [PATCH 0059/1099] =?UTF-8?q?[Lock]=C2=A0Re-add=20the=20Lock=20com?= =?UTF-8?q?ponent=20in=203.4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- composer.json | 1 + src/Symfony/Component/Lock/.gitignore | 3 + src/Symfony/Component/Lock/CHANGELOG.md | 7 + .../Lock/Exception/ExceptionInterface.php | 21 ++ .../Exception/InvalidArgumentException.php | 19 + .../Lock/Exception/LockAcquiringException.php | 21 ++ .../Exception/LockConflictedException.php | 21 ++ .../Lock/Exception/LockReleasingException.php | 21 ++ .../Lock/Exception/LockStorageException.php | 21 ++ .../Lock/Exception/NotSupportedException.php | 21 ++ src/Symfony/Component/Lock/Factory.php | 51 +++ src/Symfony/Component/Lock/Key.php | 73 ++++ src/Symfony/Component/Lock/LICENSE | 19 + src/Symfony/Component/Lock/Lock.php | 123 ++++++ src/Symfony/Component/Lock/LockInterface.php | 59 +++ src/Symfony/Component/Lock/README.md | 11 + .../Component/Lock/Store/CombinedStore.php | 174 +++++++++ .../Component/Lock/Store/FlockStore.php | 138 +++++++ .../Component/Lock/Store/MemcachedStore.php | 179 +++++++++ .../Component/Lock/Store/RedisStore.php | 156 ++++++++ .../Lock/Store/RetryTillSaveStore.php | 102 +++++ .../Component/Lock/Store/SemaphoreStore.php | 112 ++++++ src/Symfony/Component/Lock/StoreInterface.php | 73 ++++ .../Lock/Strategy/ConsensusStrategy.php | 36 ++ .../Lock/Strategy/StrategyInterface.php | 43 +++ .../Lock/Strategy/UnanimousStrategy.php | 36 ++ .../Component/Lock/Tests/FactoryTest.php | 36 ++ src/Symfony/Component/Lock/Tests/LockTest.php | 156 ++++++++ .../Tests/Store/AbstractRedisStoreTest.php | 45 +++ .../Lock/Tests/Store/AbstractStoreTest.php | 112 ++++++ .../Tests/Store/BlockingStoreTestTrait.php | 81 ++++ .../Lock/Tests/Store/CombinedStoreTest.php | 356 ++++++++++++++++++ .../Tests/Store/ExpiringStoreTestTrait.php | 78 ++++ .../Lock/Tests/Store/FlockStoreTest.php | 77 ++++ .../Lock/Tests/Store/MemcachedStoreTest.php | 52 +++ .../Lock/Tests/Store/PredisStoreTest.php | 36 ++ .../Lock/Tests/Store/RedisArrayStoreTest.php | 38 ++ .../Lock/Tests/Store/RedisStoreTest.php | 36 ++ .../Tests/Store/RetryTillSaveStoreTest.php | 35 ++ .../Lock/Tests/Store/SemaphoreStoreTest.php | 36 ++ .../Tests/Strategy/ConsensusStrategyTest.php | 89 +++++ .../Tests/Strategy/UnanimousStrategyTest.php | 89 +++++ src/Symfony/Component/Lock/composer.json | 38 ++ src/Symfony/Component/Lock/phpunit.xml.dist | 32 ++ 44 files changed, 2963 insertions(+) create mode 100644 src/Symfony/Component/Lock/.gitignore create mode 100644 src/Symfony/Component/Lock/CHANGELOG.md create mode 100644 src/Symfony/Component/Lock/Exception/ExceptionInterface.php create mode 100644 src/Symfony/Component/Lock/Exception/InvalidArgumentException.php create mode 100644 src/Symfony/Component/Lock/Exception/LockAcquiringException.php create mode 100644 src/Symfony/Component/Lock/Exception/LockConflictedException.php create mode 100644 src/Symfony/Component/Lock/Exception/LockReleasingException.php create mode 100644 src/Symfony/Component/Lock/Exception/LockStorageException.php create mode 100644 src/Symfony/Component/Lock/Exception/NotSupportedException.php create mode 100644 src/Symfony/Component/Lock/Factory.php create mode 100644 src/Symfony/Component/Lock/Key.php create mode 100644 src/Symfony/Component/Lock/LICENSE create mode 100644 src/Symfony/Component/Lock/Lock.php create mode 100644 src/Symfony/Component/Lock/LockInterface.php create mode 100644 src/Symfony/Component/Lock/README.md create mode 100644 src/Symfony/Component/Lock/Store/CombinedStore.php create mode 100644 src/Symfony/Component/Lock/Store/FlockStore.php create mode 100644 src/Symfony/Component/Lock/Store/MemcachedStore.php create mode 100644 src/Symfony/Component/Lock/Store/RedisStore.php create mode 100644 src/Symfony/Component/Lock/Store/RetryTillSaveStore.php create mode 100644 src/Symfony/Component/Lock/Store/SemaphoreStore.php create mode 100644 src/Symfony/Component/Lock/StoreInterface.php create mode 100644 src/Symfony/Component/Lock/Strategy/ConsensusStrategy.php create mode 100644 src/Symfony/Component/Lock/Strategy/StrategyInterface.php create mode 100644 src/Symfony/Component/Lock/Strategy/UnanimousStrategy.php create mode 100644 src/Symfony/Component/Lock/Tests/FactoryTest.php create mode 100644 src/Symfony/Component/Lock/Tests/LockTest.php create mode 100644 src/Symfony/Component/Lock/Tests/Store/AbstractRedisStoreTest.php create mode 100644 src/Symfony/Component/Lock/Tests/Store/AbstractStoreTest.php create mode 100644 src/Symfony/Component/Lock/Tests/Store/BlockingStoreTestTrait.php create mode 100644 src/Symfony/Component/Lock/Tests/Store/CombinedStoreTest.php create mode 100644 src/Symfony/Component/Lock/Tests/Store/ExpiringStoreTestTrait.php create mode 100644 src/Symfony/Component/Lock/Tests/Store/FlockStoreTest.php create mode 100644 src/Symfony/Component/Lock/Tests/Store/MemcachedStoreTest.php create mode 100644 src/Symfony/Component/Lock/Tests/Store/PredisStoreTest.php create mode 100644 src/Symfony/Component/Lock/Tests/Store/RedisArrayStoreTest.php create mode 100644 src/Symfony/Component/Lock/Tests/Store/RedisStoreTest.php create mode 100644 src/Symfony/Component/Lock/Tests/Store/RetryTillSaveStoreTest.php create mode 100644 src/Symfony/Component/Lock/Tests/Store/SemaphoreStoreTest.php create mode 100644 src/Symfony/Component/Lock/Tests/Strategy/ConsensusStrategyTest.php create mode 100644 src/Symfony/Component/Lock/Tests/Strategy/UnanimousStrategyTest.php create mode 100644 src/Symfony/Component/Lock/composer.json create mode 100644 src/Symfony/Component/Lock/phpunit.xml.dist diff --git a/composer.json b/composer.json index 13ad97446582a..42be8e2b4ee41 100644 --- a/composer.json +++ b/composer.json @@ -56,6 +56,7 @@ "symfony/inflector": "self.version", "symfony/intl": "self.version", "symfony/ldap": "self.version", + "symfony/lock": "self.version", "symfony/monolog-bridge": "self.version", "symfony/options-resolver": "self.version", "symfony/process": "self.version", diff --git a/src/Symfony/Component/Lock/.gitignore b/src/Symfony/Component/Lock/.gitignore new file mode 100644 index 0000000000000..5414c2c655e72 --- /dev/null +++ b/src/Symfony/Component/Lock/.gitignore @@ -0,0 +1,3 @@ +composer.lock +phpunit.xml +vendor/ diff --git a/src/Symfony/Component/Lock/CHANGELOG.md b/src/Symfony/Component/Lock/CHANGELOG.md new file mode 100644 index 0000000000000..8e992b982a9b9 --- /dev/null +++ b/src/Symfony/Component/Lock/CHANGELOG.md @@ -0,0 +1,7 @@ +CHANGELOG +========= + +3.4.0 +----- + + * added the component diff --git a/src/Symfony/Component/Lock/Exception/ExceptionInterface.php b/src/Symfony/Component/Lock/Exception/ExceptionInterface.php new file mode 100644 index 0000000000000..0d41958474061 --- /dev/null +++ b/src/Symfony/Component/Lock/Exception/ExceptionInterface.php @@ -0,0 +1,21 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Lock\Exception; + +/** + * Base ExceptionInterface for the Lock Component. + * + * @author Jérémy Derussé + */ +interface ExceptionInterface +{ +} diff --git a/src/Symfony/Component/Lock/Exception/InvalidArgumentException.php b/src/Symfony/Component/Lock/Exception/InvalidArgumentException.php new file mode 100644 index 0000000000000..f2f74b37ce324 --- /dev/null +++ b/src/Symfony/Component/Lock/Exception/InvalidArgumentException.php @@ -0,0 +1,19 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Lock\Exception; + +/** + * @author Jérémy Derussé + */ +class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface +{ +} diff --git a/src/Symfony/Component/Lock/Exception/LockAcquiringException.php b/src/Symfony/Component/Lock/Exception/LockAcquiringException.php new file mode 100644 index 0000000000000..e6756aec14fcd --- /dev/null +++ b/src/Symfony/Component/Lock/Exception/LockAcquiringException.php @@ -0,0 +1,21 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Lock\Exception; + +/** + * LockAcquiringException is thrown when an issue happens during the acquisition of a lock. + * + * @author Jérémy Derussé + */ +class LockAcquiringException extends \RuntimeException implements ExceptionInterface +{ +} diff --git a/src/Symfony/Component/Lock/Exception/LockConflictedException.php b/src/Symfony/Component/Lock/Exception/LockConflictedException.php new file mode 100644 index 0000000000000..8fcd6a836d217 --- /dev/null +++ b/src/Symfony/Component/Lock/Exception/LockConflictedException.php @@ -0,0 +1,21 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Lock\Exception; + +/** + * LockConflictedException is thrown when a lock is acquired by someone else. + * + * @author Jérémy Derussé + */ +class LockConflictedException extends \RuntimeException implements ExceptionInterface +{ +} diff --git a/src/Symfony/Component/Lock/Exception/LockReleasingException.php b/src/Symfony/Component/Lock/Exception/LockReleasingException.php new file mode 100644 index 0000000000000..56eedde79eb43 --- /dev/null +++ b/src/Symfony/Component/Lock/Exception/LockReleasingException.php @@ -0,0 +1,21 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Lock\Exception; + +/** + * LockReleasingException is thrown when an issue happens during the release of a lock. + * + * @author Jérémy Derussé + */ +class LockReleasingException extends \RuntimeException implements ExceptionInterface +{ +} diff --git a/src/Symfony/Component/Lock/Exception/LockStorageException.php b/src/Symfony/Component/Lock/Exception/LockStorageException.php new file mode 100644 index 0000000000000..8c393fc1bd509 --- /dev/null +++ b/src/Symfony/Component/Lock/Exception/LockStorageException.php @@ -0,0 +1,21 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Lock\Exception; + +/** + * LockStorageException is thrown when an issue happens during the manipulation of a lock in a store. + * + * @author Jérémy Derussé + */ +class LockStorageException extends \RuntimeException implements ExceptionInterface +{ +} diff --git a/src/Symfony/Component/Lock/Exception/NotSupportedException.php b/src/Symfony/Component/Lock/Exception/NotSupportedException.php new file mode 100644 index 0000000000000..c9a7f013c11aa --- /dev/null +++ b/src/Symfony/Component/Lock/Exception/NotSupportedException.php @@ -0,0 +1,21 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Lock\Exception; + +/** + * NotSupportedException is thrown when an unsupported method is called. + * + * @author Jérémy Derussé + */ +class NotSupportedException extends \LogicException implements ExceptionInterface +{ +} diff --git a/src/Symfony/Component/Lock/Factory.php b/src/Symfony/Component/Lock/Factory.php new file mode 100644 index 0000000000000..c050145f90978 --- /dev/null +++ b/src/Symfony/Component/Lock/Factory.php @@ -0,0 +1,51 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Lock; + +use Psr\Log\LoggerAwareInterface; +use Psr\Log\LoggerAwareTrait; +use Psr\Log\NullLogger; + +/** + * Factory provides method to create locks. + * + * @author Jérémy Derussé + */ +class Factory implements LoggerAwareInterface +{ + use LoggerAwareTrait; + + private $store; + + public function __construct(StoreInterface $store) + { + $this->store = $store; + + $this->logger = new NullLogger(); + } + + /** + * Creates a lock for the given resource. + * + * @param string $resource The resource to lock + * @param float $ttl maximum expected lock duration + * + * @return Lock + */ + public function createLock($resource, $ttl = 300.0) + { + $lock = new Lock(new Key($resource), $this->store, $ttl); + $lock->setLogger($this->logger); + + return $lock; + } +} diff --git a/src/Symfony/Component/Lock/Key.php b/src/Symfony/Component/Lock/Key.php new file mode 100644 index 0000000000000..5b53ae9b6b078 --- /dev/null +++ b/src/Symfony/Component/Lock/Key.php @@ -0,0 +1,73 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Lock; + +/** + * Key is a container for the state of the locks in stores. + * + * @author Jérémy Derussé + */ +final class Key +{ + private $resource; + private $state = array(); + + /** + * @param string $resource + */ + public function __construct($resource) + { + $this->resource = (string) $resource; + } + + public function __toString() + { + return $this->resource; + } + + /** + * @param string $stateKey + * + * @return bool + */ + public function hasState($stateKey) + { + return isset($this->state[$stateKey]); + } + + /** + * @param string $stateKey + * @param mixed $state + */ + public function setState($stateKey, $state) + { + $this->state[$stateKey] = $state; + } + + /** + * @param string $stateKey + */ + public function removeState($stateKey) + { + unset($this->state[$stateKey]); + } + + /** + * @param $stateKey + * + * @return mixed + */ + public function getState($stateKey) + { + return $this->state[$stateKey]; + } +} diff --git a/src/Symfony/Component/Lock/LICENSE b/src/Symfony/Component/Lock/LICENSE new file mode 100644 index 0000000000000..ce39894f6a9a2 --- /dev/null +++ b/src/Symfony/Component/Lock/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2016-2017 Fabien Potencier + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/src/Symfony/Component/Lock/Lock.php b/src/Symfony/Component/Lock/Lock.php new file mode 100644 index 0000000000000..5d5342a528002 --- /dev/null +++ b/src/Symfony/Component/Lock/Lock.php @@ -0,0 +1,123 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Lock; + +use Psr\Log\LoggerAwareInterface; +use Psr\Log\LoggerAwareTrait; +use Psr\Log\NullLogger; +use Symfony\Component\Lock\Exception\InvalidArgumentException; +use Symfony\Component\Lock\Exception\LockAcquiringException; +use Symfony\Component\Lock\Exception\LockConflictedException; +use Symfony\Component\Lock\Exception\LockReleasingException; + +/** + * Lock is the default implementation of the LockInterface. + * + * @author Jérémy Derussé + */ +final class Lock implements LockInterface, LoggerAwareInterface +{ + use LoggerAwareTrait; + + private $store; + private $key; + private $ttl; + + /** + * @param Key $key + * @param StoreInterface $store + * @param float|null $ttl + */ + public function __construct(Key $key, StoreInterface $store, $ttl = null) + { + $this->store = $store; + $this->key = $key; + $this->ttl = $ttl; + + $this->logger = new NullLogger(); + } + + /** + * {@inheritdoc} + */ + public function acquire($blocking = false) + { + try { + if (!$blocking) { + $this->store->save($this->key); + } else { + $this->store->waitAndSave($this->key); + } + + $this->logger->info('Successfully acquired the "{resource}" lock.', array('resource' => $this->key)); + + if ($this->ttl) { + $this->refresh(); + } + + return true; + } catch (LockConflictedException $e) { + $this->logger->warning('Failed to acquire the "{resource}" lock. Someone else already acquired the lock.', array('resource' => $this->key)); + + if ($blocking) { + throw $e; + } + + return false; + } catch (\Exception $e) { + $this->logger->warning('Failed to acquire the "{resource}" lock.', array('resource' => $this->key, 'exception' => $e)); + throw new LockAcquiringException(sprintf('Failed to acquire the "%s" lock.', $this->key), 0, $e); + } + } + + /** + * {@inheritdoc} + */ + public function refresh() + { + if (!$this->ttl) { + throw new InvalidArgumentException('You have to define an expiration duration.'); + } + + try { + $this->store->putOffExpiration($this->key, $this->ttl); + $this->logger->info('Expiration defined for "{resource}" lock for "{ttl}" seconds.', array('resource' => $this->key, 'ttl' => $this->ttl)); + } catch (LockConflictedException $e) { + $this->logger->warning('Failed to define an expiration for the "{resource}" lock, someone else acquired the lock.', array('resource' => $this->key)); + throw $e; + } catch (\Exception $e) { + $this->logger->warning('Failed to define an expiration for the "{resource}" lock.', array('resource' => $this->key, 'exception' => $e)); + throw new LockAcquiringException(sprintf('Failed to define an expiration for the "%s" lock.', $this->key), 0, $e); + } + } + + /** + * {@inheritdoc} + */ + public function isAcquired() + { + return $this->store->exists($this->key); + } + + /** + * {@inheritdoc} + */ + public function release() + { + $this->store->delete($this->key); + + if ($this->store->exists($this->key)) { + $this->logger->warning('Failed to release the "{resource}" lock.', array('resource' => $this->key)); + throw new LockReleasingException(sprintf('Failed to release the "%s" lock.', $this->key)); + } + } +} diff --git a/src/Symfony/Component/Lock/LockInterface.php b/src/Symfony/Component/Lock/LockInterface.php new file mode 100644 index 0000000000000..ab05d7a8f4ab1 --- /dev/null +++ b/src/Symfony/Component/Lock/LockInterface.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\Lock; + +use Symfony\Component\Lock\Exception\LockAcquiringException; +use Symfony\Component\Lock\Exception\LockConflictedException; +use Symfony\Component\Lock\Exception\LockReleasingException; + +/** + * LockInterface defines an interface to manipulate the status of a lock. + * + * @author Jérémy Derussé + */ +interface LockInterface +{ + /** + * Acquires the lock. If the lock is acquired by someone else, the parameter `blocking` determines whether or not + * the the call should block until the release of the lock. + * + * @param bool $blocking Whether or not the Lock should wait for the release of someone else + * + * @return bool Whether or not the lock had been acquired. + * + * @throws LockConflictedException If the lock is acquired by someone else in blocking mode + * @throws LockAcquiringException If the lock can not be acquired + */ + public function acquire($blocking = false); + + /** + * Increase the duration of an acquired lock. + * + * @throws LockConflictedException If the lock is acquired by someone else + * @throws LockAcquiringException If the lock can not be refreshed + */ + public function refresh(); + + /** + * Returns whether or not the lock is acquired. + * + * @return bool + */ + public function isAcquired(); + + /** + * Release the lock. + * + * @throws LockReleasingException If the lock can not be released + */ + public function release(); +} diff --git a/src/Symfony/Component/Lock/README.md b/src/Symfony/Component/Lock/README.md new file mode 100644 index 0000000000000..0be0bfd49dfda --- /dev/null +++ b/src/Symfony/Component/Lock/README.md @@ -0,0 +1,11 @@ +Lock Component +============== + +Resources +--------- + + * [Documentation](https://symfony.com/doc/master/components/lock.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) + in the [main Symfony repository](https://github.com/symfony/symfony) diff --git a/src/Symfony/Component/Lock/Store/CombinedStore.php b/src/Symfony/Component/Lock/Store/CombinedStore.php new file mode 100644 index 0000000000000..0f5a78cef6455 --- /dev/null +++ b/src/Symfony/Component/Lock/Store/CombinedStore.php @@ -0,0 +1,174 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Lock\Store; + +use Psr\Log\LoggerAwareInterface; +use Psr\Log\LoggerAwareTrait; +use Psr\Log\NullLogger; +use Symfony\Component\Lock\Exception\InvalidArgumentException; +use Symfony\Component\Lock\Exception\LockConflictedException; +use Symfony\Component\Lock\Exception\NotSupportedException; +use Symfony\Component\Lock\Key; +use Symfony\Component\Lock\Strategy\StrategyInterface; +use Symfony\Component\Lock\StoreInterface; + +/** + * CombinedStore is a StoreInterface implementation able to manage and synchronize several StoreInterfaces. + * + * @author Jérémy Derussé + */ +class CombinedStore implements StoreInterface, LoggerAwareInterface +{ + use LoggerAwareTrait; + + /** @var StoreInterface[] */ + private $stores; + /** @var StrategyInterface */ + private $strategy; + + /** + * @param StoreInterface[] $stores The list of synchronized stores + * @param StrategyInterface $strategy + * + * @throws InvalidArgumentException + */ + public function __construct(array $stores, StrategyInterface $strategy) + { + foreach ($stores as $store) { + if (!$store instanceof StoreInterface) { + throw new InvalidArgumentException(sprintf('The store must implement "%s". Got "%s".', StoreInterface::class, get_class($store))); + } + } + + $this->stores = $stores; + $this->strategy = $strategy; + $this->logger = new NullLogger(); + } + + /** + * {@inheritdoc} + */ + public function save(Key $key) + { + $successCount = 0; + $failureCount = 0; + $storesCount = count($this->stores); + + foreach ($this->stores as $store) { + try { + $store->save($key); + ++$successCount; + } catch (\Exception $e) { + $this->logger->warning('One store failed to save the "{resource}" lock.', array('resource' => $key, 'store' => $store, 'exception' => $e)); + ++$failureCount; + } + + if (!$this->strategy->canBeMet($failureCount, $storesCount)) { + break; + } + } + + if ($this->strategy->isMet($successCount, $storesCount)) { + return; + } + + $this->logger->warning('Failed to store the "{resource}" lock. Quorum has not been met.', array('resource' => $key, 'success' => $successCount, 'failure' => $failureCount)); + + // clean up potential locks + $this->delete($key); + + throw new LockConflictedException(); + } + + public function waitAndSave(Key $key) + { + throw new NotSupportedException(sprintf('The store "%s" does not supports blocking locks.', get_class($this))); + } + + /** + * {@inheritdoc} + */ + public function putOffExpiration(Key $key, $ttl) + { + $successCount = 0; + $failureCount = 0; + $storesCount = count($this->stores); + + foreach ($this->stores as $store) { + try { + $store->putOffExpiration($key, $ttl); + ++$successCount; + } catch (\Exception $e) { + $this->logger->warning('One store failed to put off the expiration of the "{resource}" lock.', array('resource' => $key, 'store' => $store, 'exception' => $e)); + ++$failureCount; + } + + if (!$this->strategy->canBeMet($failureCount, $storesCount)) { + break; + } + } + + if ($this->strategy->isMet($successCount, $storesCount)) { + return; + } + + $this->logger->warning('Failed to define the expiration for the "{resource}" lock. Quorum has not been met.', array('resource' => $key, 'success' => $successCount, 'failure' => $failureCount)); + + // clean up potential locks + $this->delete($key); + + throw new LockConflictedException(); + } + + /** + * {@inheritdoc} + */ + public function delete(Key $key) + { + foreach ($this->stores as $store) { + try { + $store->delete($key); + } catch (\Exception $e) { + $this->logger->notice('One store failed to delete the "{resource}" lock.', array('resource' => $key, 'store' => $store, 'exception' => $e)); + } catch (\Throwable $e) { + $this->logger->notice('One store failed to delete the "{resource}" lock.', array('resource' => $key, 'store' => $store, 'exception' => $e)); + } + } + } + + /** + * {@inheritdoc} + */ + public function exists(Key $key) + { + $successCount = 0; + $failureCount = 0; + $storesCount = count($this->stores); + + foreach ($this->stores as $store) { + if ($store->exists($key)) { + ++$successCount; + } else { + ++$failureCount; + } + + if ($this->strategy->isMet($successCount, $storesCount)) { + return true; + } + if (!$this->strategy->canBeMet($failureCount, $storesCount)) { + return false; + } + } + + return false; + } +} diff --git a/src/Symfony/Component/Lock/Store/FlockStore.php b/src/Symfony/Component/Lock/Store/FlockStore.php new file mode 100644 index 0000000000000..6bd28c83a42e8 --- /dev/null +++ b/src/Symfony/Component/Lock/Store/FlockStore.php @@ -0,0 +1,138 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Lock\Store; + +use Symfony\Component\Lock\Exception\InvalidArgumentException; +use Symfony\Component\Lock\Exception\LockConflictedException; +use Symfony\Component\Lock\Exception\LockStorageException; +use Symfony\Component\Lock\Key; +use Symfony\Component\Lock\StoreInterface; + +/** + * FlockStore is a StoreInterface implementation using the FileSystem flock. + * + * Original implementation in \Symfony\Component\Filesystem\LockHandler. + * + * @author Jérémy Derussé + * @author Grégoire Pineau + * @author Romain Neutron + * @author Nicolas Grekas + */ +class FlockStore implements StoreInterface +{ + private $lockPath; + + /** + * @param string $lockPath the directory to store the lock + * + * @throws LockStorageException If the lock directory could not be created or is not writable + */ + public function __construct($lockPath) + { + if (!is_dir($lockPath) || !is_writable($lockPath)) { + throw new InvalidArgumentException(sprintf('The directory "%s" is not writable.', $lockPath)); + } + + $this->lockPath = $lockPath; + } + + /** + * {@inheritdoc} + */ + public function save(Key $key) + { + $this->lock($key, false); + } + + /** + * {@inheritdoc} + */ + public function waitAndSave(Key $key) + { + $this->lock($key, true); + } + + private function lock(Key $key, $blocking) + { + // The lock is maybe already acquired. + if ($key->hasState(__CLASS__)) { + return; + } + + $fileName = sprintf('%s/sf.%s.%s.lock', + $this->lockPath, + preg_replace('/[^a-z0-9\._-]+/i', '-', $key), + hash('sha256', $key) + ); + + // Silence error reporting + set_error_handler(function () { + }); + if (!$handle = fopen($fileName, 'r')) { + if ($handle = fopen($fileName, 'x')) { + chmod($fileName, 0444); + } elseif (!$handle = fopen($fileName, 'r')) { + usleep(100); // Give some time for chmod() to complete + $handle = fopen($fileName, 'r'); + } + } + restore_error_handler(); + + if (!$handle) { + $error = error_get_last(); + throw new LockStorageException($error['message'], 0, null); + } + + // On Windows, even if PHP doc says the contrary, LOCK_NB works, see + // https://bugs.php.net/54129 + if (!flock($handle, LOCK_EX | ($blocking ? 0 : LOCK_NB))) { + fclose($handle); + throw new LockConflictedException(); + } + + $key->setState(__CLASS__, $handle); + } + + /** + * {@inheritdoc} + */ + public function putOffExpiration(Key $key, $ttl) + { + // do nothing, the flock locks forever. + } + + /** + * {@inheritdoc} + */ + public function delete(Key $key) + { + // The lock is maybe not acquired. + if (!$key->hasState(__CLASS__)) { + return; + } + + $handle = $key->getState(__CLASS__); + + flock($handle, LOCK_UN | LOCK_NB); + fclose($handle); + + $key->removeState(__CLASS__); + } + + /** + * {@inheritdoc} + */ + public function exists(Key $key) + { + return $key->hasState(__CLASS__); + } +} diff --git a/src/Symfony/Component/Lock/Store/MemcachedStore.php b/src/Symfony/Component/Lock/Store/MemcachedStore.php new file mode 100644 index 0000000000000..a1e31ee63320f --- /dev/null +++ b/src/Symfony/Component/Lock/Store/MemcachedStore.php @@ -0,0 +1,179 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Lock\Store; + +use Symfony\Component\Lock\Exception\InvalidArgumentException; +use Symfony\Component\Lock\Exception\LockConflictedException; +use Symfony\Component\Lock\Key; +use Symfony\Component\Lock\StoreInterface; + +/** + * MemcachedStore is a StoreInterface implementation using Memcached as store engine. + * + * @author Jérémy Derussé + */ +class MemcachedStore implements StoreInterface +{ + private $memcached; + private $initialTtl; + /** @var bool */ + private $useExtendedReturn; + + public static function isSupported() + { + return extension_loaded('memcached'); + } + + /** + * @param \Memcached $memcached + * @param int $initialTtl the expiration delay of locks in seconds + */ + public function __construct(\Memcached $memcached, $initialTtl = 300) + { + if (!static::isSupported()) { + throw new InvalidArgumentException('Memcached extension is required'); + } + + if ($initialTtl < 1) { + throw new InvalidArgumentException(sprintf('%s() expects a strictly positive TTL. Got %d.', __METHOD__, $initialTtl)); + } + + $this->memcached = $memcached; + $this->initialTtl = $initialTtl; + } + + /** + * {@inheritdoc} + */ + public function save(Key $key) + { + $token = $this->getToken($key); + + if ($this->memcached->add((string) $key, $token, (int) ceil($this->initialTtl))) { + return; + } + + // the lock is already acquire. It could be us. Let's try to put off. + $this->putOffExpiration($key, $this->initialTtl); + } + + public function waitAndSave(Key $key) + { + throw new InvalidArgumentException(sprintf('The store "%s" does not supports blocking locks.', get_class($this))); + } + + /** + * {@inheritdoc} + */ + public function putOffExpiration(Key $key, $ttl) + { + if ($ttl < 1) { + throw new InvalidArgumentException(sprintf('%s() expects a TTL greater or equals to 1. Got %s.', __METHOD__, $ttl)); + } + + // Interface defines a float value but Store required an integer. + $ttl = (int) ceil($ttl); + + $token = $this->getToken($key); + + list($value, $cas) = $this->getValueAndCas($key); + + // Could happens when we ask a putOff after a timeout but in luck nobody steal the lock + if (\Memcached::RES_NOTFOUND === $this->memcached->getResultCode()) { + if ($this->memcached->add((string) $key, $token, $ttl)) { + return; + } + + // no luck, with concurrency, someone else acquire the lock + throw new LockConflictedException(); + } + + // Someone else steal the lock + if ($value !== $token) { + throw new LockConflictedException(); + } + + if (!$this->memcached->cas($cas, (string) $key, $token, $ttl)) { + throw new LockConflictedException(); + } + } + + /** + * {@inheritdoc} + */ + public function delete(Key $key) + { + $token = $this->getToken($key); + + list($value, $cas) = $this->getValueAndCas($key); + + if ($value !== $token) { + // we are not the owner of the lock. Nothing to do. + return; + } + + // To avoid concurrency in deletion, the trick is to extends the TTL then deleting the key + if (!$this->memcached->cas($cas, (string) $key, $token, 2)) { + // Someone steal our lock. It does not belongs to us anymore. Nothing to do. + return; + } + + // Now, we are the owner of the lock for 2 more seconds, we can delete it. + $this->memcached->delete((string) $key); + } + + /** + * {@inheritdoc} + */ + public function exists(Key $key) + { + return $this->memcached->get((string) $key) === $this->getToken($key); + } + + /** + * Retrieve an unique token for the given key. + * + * @param Key $key + * + * @return string + */ + private function getToken(Key $key) + { + if (!$key->hasState(__CLASS__)) { + $token = base64_encode(random_bytes(32)); + $key->setState(__CLASS__, $token); + } + + return $key->getState(__CLASS__); + } + + private function getValueAndCas(Key $key) + { + if (null === $this->useExtendedReturn) { + $this->useExtendedReturn = version_compare(phpversion('memcached'), '2.9.9', '>'); + } + + if ($this->useExtendedReturn) { + $extendedReturn = $this->memcached->get((string) $key, null, \Memcached::GET_EXTENDED); + if ($extendedReturn === \Memcached::GET_ERROR_RETURN_VALUE) { + return array($extendedReturn, 0.0); + } + + return array($extendedReturn['value'], $extendedReturn['cas']); + } + + $cas = 0.0; + $value = $this->memcached->get((string) $key, null, $cas); + + return array($value, $cas); + } +} diff --git a/src/Symfony/Component/Lock/Store/RedisStore.php b/src/Symfony/Component/Lock/Store/RedisStore.php new file mode 100644 index 0000000000000..b9ea2a5fb80e3 --- /dev/null +++ b/src/Symfony/Component/Lock/Store/RedisStore.php @@ -0,0 +1,156 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Lock\Store; + +use Symfony\Component\Lock\Exception\InvalidArgumentException; +use Symfony\Component\Lock\Exception\LockConflictedException; +use Symfony\Component\Lock\Key; +use Symfony\Component\Lock\StoreInterface; + +/** + * RedisStore is a StoreInterface implementation using Redis as store engine. + * + * @author Jérémy Derussé + */ +class RedisStore implements StoreInterface +{ + private $redis; + private $initialTtl; + + /** + * @param \Redis|\RedisArray|\RedisCluster|\Predis\Client $redisClient + * @param float $initialTtl the expiration delay of locks in seconds + */ + public function __construct($redisClient, $initialTtl = 300.0) + { + if (!$redisClient instanceof \Redis && !$redisClient instanceof \RedisArray && !$redisClient instanceof \RedisCluster && !$redisClient instanceof \Predis\Client) { + throw new InvalidArgumentException(sprintf('%s() expects parameter 1 to be Redis, RedisArray, RedisCluster or Predis\Client, %s given', __METHOD__, is_object($redisClient) ? get_class($redisClient) : gettype($redisClient))); + } + + if ($initialTtl <= 0) { + throw new InvalidArgumentException(sprintf('%s() expects a strictly positive TTL. Got %d.', __METHOD__, $initialTtl)); + } + + $this->redis = $redisClient; + $this->initialTtl = $initialTtl; + } + + /** + * {@inheritdoc} + */ + public function save(Key $key) + { + $script = ' + if redis.call("GET", KEYS[1]) == ARGV[1] then + return redis.call("PEXPIRE", KEYS[1], ARGV[2]) + else + return redis.call("set", KEYS[1], ARGV[1], "NX", "PX", ARGV[2]) + end + '; + + $expire = (int) ceil($this->initialTtl * 1000); + if (!$this->evaluate($script, (string) $key, array($this->getToken($key), $expire))) { + throw new LockConflictedException(); + } + } + + public function waitAndSave(Key $key) + { + throw new InvalidArgumentException(sprintf('The store "%s" does not supports blocking locks.', get_class($this))); + } + + /** + * {@inheritdoc} + */ + public function putOffExpiration(Key $key, $ttl) + { + $script = ' + if redis.call("GET", KEYS[1]) == ARGV[1] then + return redis.call("PEXPIRE", KEYS[1], ARGV[2]) + else + return 0 + end + '; + + $expire = (int) ceil($ttl * 1000); + if (!$this->evaluate($script, (string) $key, array($this->getToken($key), $expire))) { + throw new LockConflictedException(); + } + } + + /** + * {@inheritdoc} + */ + public function delete(Key $key) + { + $script = ' + if redis.call("GET", KEYS[1]) == ARGV[1] then + return redis.call("DEL", KEYS[1]) + else + return 0 + end + '; + + $this->evaluate($script, (string) $key, array($this->getToken($key))); + } + + /** + * {@inheritdoc} + */ + public function exists(Key $key) + { + return $this->redis->get((string) $key) === $this->getToken($key); + } + + /** + * Evaluates a script in the corresponding redis client. + * + * @param string $script + * @param string $resource + * @param array $args + * + * @return mixed + */ + private function evaluate($script, $resource, array $args) + { + if ($this->redis instanceof \Redis || $this->redis instanceof \RedisCluster) { + return $this->redis->eval($script, array_merge(array($resource), $args), 1); + } + + if ($this->redis instanceof \RedisArray) { + return $this->redis->_instance($this->redis->_target($resource))->eval($script, array_merge(array($resource), $args), 1); + } + + if ($this->redis instanceof \Predis\Client) { + return call_user_func_array(array($this->redis, 'eval'), array_merge(array($script, 1, $resource), $args)); + } + + throw new InvalidArgumentException(sprintf('%s() expects been initialized with a Redis, RedisArray, RedisCluster or Predis\Client, %s given', __METHOD__, is_object($this->redis) ? get_class($this->redis) : gettype($this->redis))); + } + + /** + * Retrieves an unique token for the given key. + * + * @param Key $key + * + * @return string + */ + private function getToken(Key $key) + { + if (!$key->hasState(__CLASS__)) { + $token = base64_encode(random_bytes(32)); + $key->setState(__CLASS__, $token); + } + + return $key->getState(__CLASS__); + } +} diff --git a/src/Symfony/Component/Lock/Store/RetryTillSaveStore.php b/src/Symfony/Component/Lock/Store/RetryTillSaveStore.php new file mode 100644 index 0000000000000..dfc3b266687d9 --- /dev/null +++ b/src/Symfony/Component/Lock/Store/RetryTillSaveStore.php @@ -0,0 +1,102 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Lock\Store; + +use Psr\Log\LoggerAwareInterface; +use Psr\Log\LoggerAwareTrait; +use Psr\Log\NullLogger; +use Symfony\Component\Lock\Exception\LockConflictedException; +use Symfony\Component\Lock\Key; +use Symfony\Component\Lock\StoreInterface; + +/** + * RetryTillSaveStore is a StoreInterface implementation which decorate a non blocking StoreInterface to provide a + * blocking storage. + * + * @author Jérémy Derussé + */ +class RetryTillSaveStore implements StoreInterface, LoggerAwareInterface +{ + use LoggerAwareTrait; + + private $decorated; + private $retrySleep; + private $retryCount; + + /** + * @param StoreInterface $decorated The decorated StoreInterface + * @param int $retrySleep Duration in ms between 2 retry + * @param int $retryCount Maximum amount of retry + */ + public function __construct(StoreInterface $decorated, $retrySleep = 100, $retryCount = PHP_INT_MAX) + { + $this->decorated = $decorated; + $this->retrySleep = $retrySleep; + $this->retryCount = $retryCount; + + $this->logger = new NullLogger(); + } + + /** + * {@inheritdoc} + */ + public function save(Key $key) + { + $this->decorated->save($key); + } + + /** + * {@inheritdoc} + */ + public function waitAndSave(Key $key) + { + $retry = 0; + $sleepRandomness = (int) ($this->retrySleep / 10); + do { + try { + $this->decorated->save($key); + + return; + } catch (LockConflictedException $e) { + usleep(($this->retrySleep + random_int(-$sleepRandomness, $sleepRandomness)) * 1000); + } + } while (++$retry < $this->retryCount); + + $this->logger->warning('Failed to store the "{resource}" lock. Abort after {retry} retry.', array('resource' => $key, 'retry' => $retry)); + + throw new LockConflictedException(); + } + + /** + * {@inheritdoc} + */ + public function putOffExpiration(Key $key, $ttl) + { + $this->decorated->putOffExpiration($key, $ttl); + } + + /** + * {@inheritdoc} + */ + public function delete(Key $key) + { + $this->decorated->delete($key); + } + + /** + * {@inheritdoc} + */ + public function exists(Key $key) + { + return $this->decorated->exists($key); + } +} diff --git a/src/Symfony/Component/Lock/Store/SemaphoreStore.php b/src/Symfony/Component/Lock/Store/SemaphoreStore.php new file mode 100644 index 0000000000000..986c33b6e9c56 --- /dev/null +++ b/src/Symfony/Component/Lock/Store/SemaphoreStore.php @@ -0,0 +1,112 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Lock\Store; + +use Symfony\Component\Lock\Exception\InvalidArgumentException; +use Symfony\Component\Lock\Exception\LockConflictedException; +use Symfony\Component\Lock\Exception\NotSupportedException; +use Symfony\Component\Lock\Key; +use Symfony\Component\Lock\StoreInterface; + +/** + * SemaphoreStore is a StoreInterface implementation using Semaphore as store engine. + * + * @author Jérémy Derussé + */ +class SemaphoreStore implements StoreInterface +{ + public static function isSupported() + { + return extension_loaded('sysvsem'); + } + + public function __construct() + { + if (!static::isSupported()) { + throw new InvalidArgumentException('Semaphore extension (sysvsem) is required'); + } + } + + /** + * {@inheritdoc} + */ + public function save(Key $key) + { + $this->lock($key, false); + } + + /** + * {@inheritdoc} + */ + public function waitAndSave(Key $key) + { + $this->lock($key, true); + } + + private function lock(Key $key, $blocking) + { + if ($key->hasState(__CLASS__)) { + return; + } + + $resource = sem_get(crc32($key)); + + if (PHP_VERSION_ID < 50601) { + if (!$blocking) { + throw new NotSupportedException(sprintf('The store "%s" does not supports non blocking locks.', get_class($this))); + } + + $acquired = sem_acquire($resource); + } else { + $acquired = sem_acquire($resource, !$blocking); + } + + if (!$acquired) { + throw new LockConflictedException(); + } + + $key->setState(__CLASS__, $resource); + } + + /** + * {@inheritdoc} + */ + public function delete(Key $key) + { + // The lock is maybe not acquired. + if (!$key->hasState(__CLASS__)) { + return; + } + + $resource = $key->getState(__CLASS__); + + sem_release($resource); + + $key->removeState(__CLASS__); + } + + /** + * {@inheritdoc} + */ + public function putOffExpiration(Key $key, $ttl) + { + // do nothing, the flock locks forever. + } + + /** + * {@inheritdoc} + */ + public function exists(Key $key) + { + return $key->hasState(__CLASS__); + } +} diff --git a/src/Symfony/Component/Lock/StoreInterface.php b/src/Symfony/Component/Lock/StoreInterface.php new file mode 100644 index 0000000000000..428786b4c8bf6 --- /dev/null +++ b/src/Symfony/Component/Lock/StoreInterface.php @@ -0,0 +1,73 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Lock; + +use Symfony\Component\Lock\Exception\LockConflictedException; +use Symfony\Component\Lock\Exception\NotSupportedException; + +/** + * StoreInterface defines an interface to manipulate a lock store. + * + * @author Jérémy Derussé + */ +interface StoreInterface +{ + /** + * Stores the resource if it's not locked by someone else. + * + * @param Key $key key to lock + * + * @throws LockConflictedException + */ + public function save(Key $key); + + /** + * Waits a key becomes free, then stores the resource. + * + * If the store does not support this feature it should throw a NotSupportedException. + * + * @param Key $key key to lock + * + * @throws LockConflictedException + * @throws NotSupportedException + */ + public function waitAndSave(Key $key); + + /** + * Extends the ttl of a resource. + * + * If the store does not support this feature it should throw a NotSupportedException. + * + * @param Key $key key to lock + * @param float $ttl amount of second to keep the lock in the store + * + * @throws LockConflictedException + * @throws NotSupportedException + */ + public function putOffExpiration(Key $key, $ttl); + + /** + * Removes a resource from the storage. + * + * @param Key $key key to remove + */ + public function delete(Key $key); + + /** + * Returns whether or not the resource exists in the storage. + * + * @param Key $key key to remove + * + * @return bool + */ + public function exists(Key $key); +} diff --git a/src/Symfony/Component/Lock/Strategy/ConsensusStrategy.php b/src/Symfony/Component/Lock/Strategy/ConsensusStrategy.php new file mode 100644 index 0000000000000..047820a409f1d --- /dev/null +++ b/src/Symfony/Component/Lock/Strategy/ConsensusStrategy.php @@ -0,0 +1,36 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Lock\Strategy; + +/** + * ConsensusStrategy is a StrategyInterface implementation where strictly more than 50% items should be successful. + * + * @author Jérémy Derussé + */ +class ConsensusStrategy implements StrategyInterface +{ + /** + * {@inheritdoc} + */ + public function isMet($numberOfSuccess, $numberOfItems) + { + return $numberOfSuccess > ($numberOfItems / 2); + } + + /** + * {@inheritdoc} + */ + public function canBeMet($numberOfFailure, $numberOfItems) + { + return $numberOfFailure < ($numberOfItems / 2); + } +} diff --git a/src/Symfony/Component/Lock/Strategy/StrategyInterface.php b/src/Symfony/Component/Lock/Strategy/StrategyInterface.php new file mode 100644 index 0000000000000..beaa7280a2d49 --- /dev/null +++ b/src/Symfony/Component/Lock/Strategy/StrategyInterface.php @@ -0,0 +1,43 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Lock\Strategy; + +/** + * StrategyInterface defines an interface to indicate when a quorum is met and can be met. + * + * @author Jérémy Derussé + */ +interface StrategyInterface +{ + /** + * Returns whether or not the quorum is met. + * + * @param int $numberOfSuccess + * @param int $numberOfItems + * + * @return bool + */ + public function isMet($numberOfSuccess, $numberOfItems); + + /** + * Returns whether or not the quorum *could* be met. + * + * This method does not mean the quorum *would* be met for sure, but can be useful to stop a process early when you + * known there is no chance to meet the quorum. + * + * @param int $numberOfFailure + * @param int $numberOfItems + * + * @return bool + */ + public function canBeMet($numberOfFailure, $numberOfItems); +} diff --git a/src/Symfony/Component/Lock/Strategy/UnanimousStrategy.php b/src/Symfony/Component/Lock/Strategy/UnanimousStrategy.php new file mode 100644 index 0000000000000..12d57e526ecf4 --- /dev/null +++ b/src/Symfony/Component/Lock/Strategy/UnanimousStrategy.php @@ -0,0 +1,36 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Lock\Strategy; + +/** + * UnanimousStrategy is a StrategyInterface implementation where 100% of elements should be successful. + * + * @author Jérémy Derussé + */ +class UnanimousStrategy implements StrategyInterface +{ + /** + * {@inheritdoc} + */ + public function isMet($numberOfSuccess, $numberOfItems) + { + return $numberOfSuccess === $numberOfItems; + } + + /** + * {@inheritdoc} + */ + public function canBeMet($numberOfFailure, $numberOfItems) + { + return $numberOfFailure === 0; + } +} diff --git a/src/Symfony/Component/Lock/Tests/FactoryTest.php b/src/Symfony/Component/Lock/Tests/FactoryTest.php new file mode 100644 index 0000000000000..d67949098c7a4 --- /dev/null +++ b/src/Symfony/Component/Lock/Tests/FactoryTest.php @@ -0,0 +1,36 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Lock\Tests; + +use PHPUnit\Framework\TestCase; +use Psr\Log\LoggerInterface; +use Symfony\Component\Lock\Factory; +use Symfony\Component\Lock\LockInterface; +use Symfony\Component\Lock\StoreInterface; + +/** + * @author Jérémy Derussé + */ +class FactoryTest extends TestCase +{ + public function testCreateLock() + { + $store = $this->getMockBuilder(StoreInterface::class)->getMock(); + $logger = $this->getMockBuilder(LoggerInterface::class)->getMock(); + $factory = new Factory($store); + $factory->setLogger($logger); + + $lock = $factory->createLock('foo'); + + $this->assertInstanceOf(LockInterface::class, $lock); + } +} diff --git a/src/Symfony/Component/Lock/Tests/LockTest.php b/src/Symfony/Component/Lock/Tests/LockTest.php new file mode 100644 index 0000000000000..58dbdc5820131 --- /dev/null +++ b/src/Symfony/Component/Lock/Tests/LockTest.php @@ -0,0 +1,156 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Lock\Tests; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\Lock\Exception\LockConflictedException; +use Symfony\Component\Lock\Key; +use Symfony\Component\Lock\Lock; +use Symfony\Component\Lock\StoreInterface; + +/** + * @author Jérémy Derussé + */ +class LockTest extends TestCase +{ + public function testAcquireNoBlocking() + { + $key = new Key(uniqid(__METHOD__, true)); + $store = $this->getMockBuilder(StoreInterface::class)->getMock(); + $lock = new Lock($key, $store); + + $store + ->expects($this->once()) + ->method('save'); + + $this->assertTrue($lock->acquire(false)); + } + + public function testAcquireReturnsFalse() + { + $key = new Key(uniqid(__METHOD__, true)); + $store = $this->getMockBuilder(StoreInterface::class)->getMock(); + $lock = new Lock($key, $store); + + $store + ->expects($this->once()) + ->method('save') + ->willThrowException(new LockConflictedException()); + + $this->assertFalse($lock->acquire(false)); + } + + public function testAcquireBlocking() + { + $key = new Key(uniqid(__METHOD__, true)); + $store = $this->getMockBuilder(StoreInterface::class)->getMock(); + $lock = new Lock($key, $store); + + $store + ->expects($this->never()) + ->method('save'); + $store + ->expects($this->once()) + ->method('waitAndSave'); + + $this->assertTrue($lock->acquire(true)); + } + + public function testAcquireSetsTtl() + { + $key = new Key(uniqid(__METHOD__, true)); + $store = $this->getMockBuilder(StoreInterface::class)->getMock(); + $lock = new Lock($key, $store, 10); + + $store + ->expects($this->once()) + ->method('save'); + $store + ->expects($this->once()) + ->method('putOffExpiration') + ->with($key, 10); + + $lock->acquire(); + } + + public function testRefresh() + { + $key = new Key(uniqid(__METHOD__, true)); + $store = $this->getMockBuilder(StoreInterface::class)->getMock(); + $lock = new Lock($key, $store, 10); + + $store + ->expects($this->once()) + ->method('putOffExpiration') + ->with($key, 10); + + $lock->refresh(); + } + + public function testIsAquired() + { + $key = new Key(uniqid(__METHOD__, true)); + $store = $this->getMockBuilder(StoreInterface::class)->getMock(); + $lock = new Lock($key, $store, 10); + + $store + ->expects($this->once()) + ->method('exists') + ->with($key) + ->willReturn(true); + + $this->assertTrue($lock->isAcquired()); + } + + public function testRelease() + { + $key = new Key(uniqid(__METHOD__, true)); + $store = $this->getMockBuilder(StoreInterface::class)->getMock(); + $lock = new Lock($key, $store, 10); + + $store + ->expects($this->once()) + ->method('delete') + ->with($key); + + $store + ->expects($this->once()) + ->method('exists') + ->with($key) + ->willReturn(false); + + $lock->release(); + } + + /** + * @expectedException \Symfony\Component\Lock\Exception\LockReleasingException + */ + public function testReleaseThrowsExceptionIfNotWellDeleted() + { + $key = new Key(uniqid(__METHOD__, true)); + $store = $this->getMockBuilder(StoreInterface::class)->getMock(); + $lock = new Lock($key, $store, 10); + + $store + ->expects($this->once()) + ->method('delete') + ->with($key); + + $store + ->expects($this->once()) + ->method('exists') + ->with($key) + ->willReturn(true); + + $lock->release(); + } +} diff --git a/src/Symfony/Component/Lock/Tests/Store/AbstractRedisStoreTest.php b/src/Symfony/Component/Lock/Tests/Store/AbstractRedisStoreTest.php new file mode 100644 index 0000000000000..4b9c81bd8e8c2 --- /dev/null +++ b/src/Symfony/Component/Lock/Tests/Store/AbstractRedisStoreTest.php @@ -0,0 +1,45 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Lock\Tests\Store; + +use Symfony\Component\Lock\Store\RedisStore; + +/** + * @author Jérémy Derussé + */ +abstract class AbstractRedisStoreTest extends AbstractStoreTest +{ + use ExpiringStoreTestTrait; + + /** + * {@inheritdoc} + */ + protected function getClockDelay() + { + return 250000; + } + + /** + * Return a RedisConnection. + * + * @return \Redis|\RedisArray|\RedisCluster|\Predis\Client + */ + abstract protected function getRedisConnection(); + + /** + * {@inheritdoc} + */ + public function getStore() + { + return new RedisStore($this->getRedisConnection()); + } +} diff --git a/src/Symfony/Component/Lock/Tests/Store/AbstractStoreTest.php b/src/Symfony/Component/Lock/Tests/Store/AbstractStoreTest.php new file mode 100644 index 0000000000000..c0d758744ce1a --- /dev/null +++ b/src/Symfony/Component/Lock/Tests/Store/AbstractStoreTest.php @@ -0,0 +1,112 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Lock\Tests\Store; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\Lock\Exception\LockConflictedException; +use Symfony\Component\Lock\Key; +use Symfony\Component\Lock\StoreInterface; + +/** + * @author Jérémy Derussé + */ +abstract class AbstractStoreTest extends TestCase +{ + /** + * @return StoreInterface; + */ + abstract protected function getStore(); + + public function testSave() + { + $store = $this->getStore(); + + $key = new Key(uniqid(__METHOD__, true)); + + $this->assertFalse($store->exists($key)); + $store->save($key); + $this->assertTrue($store->exists($key)); + $store->delete($key); + $this->assertFalse($store->exists($key)); + } + + public function testSaveWithDifferentResources() + { + $store = $this->getStore(); + + $key1 = new Key(uniqid(__METHOD__, true)); + $key2 = new Key(uniqid(__METHOD__, true)); + + $store->save($key1); + $this->assertTrue($store->exists($key1)); + $this->assertFalse($store->exists($key2)); + $store->save($key2); + + $this->assertTrue($store->exists($key1)); + $this->assertTrue($store->exists($key2)); + + $store->delete($key1); + $this->assertFalse($store->exists($key1)); + $store->delete($key2); + $this->assertFalse($store->exists($key2)); + } + + public function testSaveWithDifferentKeysOnSameResources() + { + $store = $this->getStore(); + + $resource = uniqid(__METHOD__, true); + $key1 = new Key($resource); + $key2 = new Key($resource); + + $store->save($key1); + $this->assertTrue($store->exists($key1)); + $this->assertFalse($store->exists($key2)); + + try { + $store->save($key2); + throw new \Exception('The store shouldn\'t save the second key'); + } catch (LockConflictedException $e) { + } + + // The failure of previous attempt should not impact the state of current locks + $this->assertTrue($store->exists($key1)); + $this->assertFalse($store->exists($key2)); + + $store->delete($key1); + $this->assertFalse($store->exists($key1)); + $this->assertFalse($store->exists($key2)); + + $store->save($key2); + $this->assertFalse($store->exists($key1)); + $this->assertTrue($store->exists($key2)); + + $store->delete($key2); + $this->assertFalse($store->exists($key1)); + $this->assertFalse($store->exists($key2)); + } + + public function testSaveTwice() + { + $store = $this->getStore(); + + $resource = uniqid(__METHOD__, true); + $key = new Key($resource); + + $store->save($key); + $store->save($key); + // just asserts it don't throw an exception + $this->addToAssertionCount(1); + + $store->delete($key); + } +} diff --git a/src/Symfony/Component/Lock/Tests/Store/BlockingStoreTestTrait.php b/src/Symfony/Component/Lock/Tests/Store/BlockingStoreTestTrait.php new file mode 100644 index 0000000000000..c34a82abafcb6 --- /dev/null +++ b/src/Symfony/Component/Lock/Tests/Store/BlockingStoreTestTrait.php @@ -0,0 +1,81 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Lock\Tests\Store; + +use Symfony\Component\Lock\Exception\LockConflictedException; +use Symfony\Component\Lock\Key; +use Symfony\Component\Lock\StoreInterface; + +/** + * @author Jérémy Derussé + */ +trait BlockingStoreTestTrait +{ + /** + * @see AbstractStoreTest::getStore() + */ + abstract protected function getStore(); + + /** + * Tests blocking locks thanks to pcntl. + * + * This test is time sensible: the $clockDelay could be adjust. + * + * @requires extension pcntl + */ + public function testBlockingLocks() + { + // Amount a microsecond used to order async actions + $clockDelay = 50000; + + if (PHP_VERSION_ID < 50600 || defined('HHVM_VERSION_ID')) { + $this->markTestSkipped('The PHP engine does not keep resource in child forks'); + + return; + } + + /** @var StoreInterface $store */ + $store = $this->getStore(); + $key = new Key(uniqid(__METHOD__, true)); + + if ($childPID1 = pcntl_fork()) { + // give time to fork to start + usleep(2 * $clockDelay); + + try { + // This call should failed given the lock should already by acquired by the child #1 + $store->save($key); + $this->fail('The store saves a locked key.'); + } catch (LockConflictedException $e) { + } + + // This call should be blocked by the child #1 + $store->waitAndSave($key); + $this->assertTrue($store->exists($key)); + $store->delete($key); + + // Now, assert the child process worked well + pcntl_waitpid($childPID1, $status1); + $this->assertSame(0, pcntl_wexitstatus($status1), 'The child process couldn\'t lock the resource'); + } else { + try { + $store->save($key); + // Wait 3 ClockDelay to let parent process to finish + usleep(3 * $clockDelay); + $store->delete($key); + exit(0); + } catch (\Exception $e) { + exit(1); + } + } + } +} diff --git a/src/Symfony/Component/Lock/Tests/Store/CombinedStoreTest.php b/src/Symfony/Component/Lock/Tests/Store/CombinedStoreTest.php new file mode 100644 index 0000000000000..debe06183dc35 --- /dev/null +++ b/src/Symfony/Component/Lock/Tests/Store/CombinedStoreTest.php @@ -0,0 +1,356 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Lock\Tests\Store; + +use Symfony\Component\Lock\Exception\LockConflictedException; +use Symfony\Component\Lock\Key; +use Symfony\Component\Lock\Strategy\UnanimousStrategy; +use Symfony\Component\Lock\Strategy\StrategyInterface; +use Symfony\Component\Lock\Store\CombinedStore; +use Symfony\Component\Lock\Store\RedisStore; +use Symfony\Component\Lock\StoreInterface; + +/** + * @author Jérémy Derussé + */ +class CombinedStoreTest extends AbstractStoreTest +{ + use ExpiringStoreTestTrait; + + /** + * {@inheritdoc} + */ + protected function getClockDelay() + { + return 250000; + } + + /** + * {@inheritdoc} + */ + public function getStore() + { + $redis = new \Predis\Client('tcp://'.getenv('REDIS_HOST').':6379'); + try { + $redis->connect(); + } catch (\Exception $e) { + self::markTestSkipped($e->getMessage()); + } + + return new CombinedStore(array(new RedisStore($redis)), new UnanimousStrategy()); + } + + /** @var \PHPUnit_Framework_MockObject_MockObject */ + private $strategy; + /** @var \PHPUnit_Framework_MockObject_MockObject */ + private $store1; + /** @var \PHPUnit_Framework_MockObject_MockObject */ + private $store2; + /** @var CombinedStore */ + private $store; + + public function setup() + { + $this->strategy = $this->getMockBuilder(StrategyInterface::class)->getMock(); + $this->store1 = $this->getMockBuilder(StoreInterface::class)->getMock(); + $this->store2 = $this->getMockBuilder(StoreInterface::class)->getMock(); + + $this->store = new CombinedStore(array($this->store1, $this->store2), $this->strategy); + } + + /** + * @expectedException \Symfony\Component\Lock\Exception\LockConflictedException + */ + public function testSaveThrowsExceptionOnFailure() + { + $key = new Key(uniqid(__METHOD__, true)); + + $this->store1 + ->expects($this->once()) + ->method('save') + ->with($key) + ->willThrowException(new LockConflictedException()); + $this->store2 + ->expects($this->once()) + ->method('save') + ->with($key) + ->willThrowException(new LockConflictedException()); + + $this->strategy + ->expects($this->any()) + ->method('canBeMet') + ->willReturn(true); + $this->strategy + ->expects($this->any()) + ->method('isMet') + ->willReturn(false); + + $this->store->save($key); + } + + public function testSaveCleanupOnFailure() + { + $key = new Key(uniqid(__METHOD__, true)); + + $this->store1 + ->expects($this->once()) + ->method('save') + ->with($key) + ->willThrowException(new LockConflictedException()); + $this->store2 + ->expects($this->once()) + ->method('save') + ->with($key) + ->willThrowException(new LockConflictedException()); + + $this->store1 + ->expects($this->once()) + ->method('delete'); + $this->store2 + ->expects($this->once()) + ->method('delete'); + + $this->strategy + ->expects($this->any()) + ->method('canBeMet') + ->willReturn(true); + $this->strategy + ->expects($this->any()) + ->method('isMet') + ->willReturn(false); + + try { + $this->store->save($key); + } catch (LockConflictedException $e) { + // Catch the exception given this is not what we want to assert in this tests + } + } + + public function testSaveAbortWhenStrategyCantBeMet() + { + $key = new Key(uniqid(__METHOD__, true)); + + $this->store1 + ->expects($this->once()) + ->method('save') + ->with($key) + ->willThrowException(new LockConflictedException()); + $this->store2 + ->expects($this->never()) + ->method('save'); + + $this->strategy + ->expects($this->once()) + ->method('canBeMet') + ->willReturn(false); + $this->strategy + ->expects($this->any()) + ->method('isMet') + ->willReturn(false); + + try { + $this->store->save($key); + } catch (LockConflictedException $e) { + // Catch the exception given this is not what we want to assert in this tests + } + } + + /** + * @expectedException \Symfony\Component\Lock\Exception\LockConflictedException + */ + public function testputOffExpirationThrowsExceptionOnFailure() + { + $key = new Key(uniqid(__METHOD__, true)); + $ttl = random_int(1, 10); + + $this->store1 + ->expects($this->once()) + ->method('putOffExpiration') + ->with($key, $ttl) + ->willThrowException(new LockConflictedException()); + $this->store2 + ->expects($this->once()) + ->method('putOffExpiration') + ->with($key, $ttl) + ->willThrowException(new LockConflictedException()); + + $this->strategy + ->expects($this->any()) + ->method('canBeMet') + ->willReturn(true); + $this->strategy + ->expects($this->any()) + ->method('isMet') + ->willReturn(false); + + $this->store->putOffExpiration($key, $ttl); + } + + public function testputOffExpirationCleanupOnFailure() + { + $key = new Key(uniqid(__METHOD__, true)); + $ttl = random_int(1, 10); + + $this->store1 + ->expects($this->once()) + ->method('putOffExpiration') + ->with($key, $ttl) + ->willThrowException(new LockConflictedException()); + $this->store2 + ->expects($this->once()) + ->method('putOffExpiration') + ->with($key, $ttl) + ->willThrowException(new LockConflictedException()); + + $this->store1 + ->expects($this->once()) + ->method('delete'); + $this->store2 + ->expects($this->once()) + ->method('delete'); + + $this->strategy + ->expects($this->any()) + ->method('canBeMet') + ->willReturn(true); + $this->strategy + ->expects($this->any()) + ->method('isMet') + ->willReturn(false); + + try { + $this->store->putOffExpiration($key, $ttl); + } catch (LockConflictedException $e) { + // Catch the exception given this is not what we want to assert in this tests + } + } + + public function testputOffExpirationAbortWhenStrategyCantBeMet() + { + $key = new Key(uniqid(__METHOD__, true)); + $ttl = random_int(1, 10); + + $this->store1 + ->expects($this->once()) + ->method('putOffExpiration') + ->with($key, $ttl) + ->willThrowException(new LockConflictedException()); + $this->store2 + ->expects($this->never()) + ->method('putOffExpiration'); + + $this->strategy + ->expects($this->once()) + ->method('canBeMet') + ->willReturn(false); + $this->strategy + ->expects($this->any()) + ->method('isMet') + ->willReturn(false); + + try { + $this->store->putOffExpiration($key, $ttl); + } catch (LockConflictedException $e) { + // Catch the exception given this is not what we want to assert in this tests + } + } + + public function testPutOffExpirationIgnoreNonExpiringStorage() + { + $store1 = $this->getMockBuilder(StoreInterface::class)->getMock(); + $store2 = $this->getMockBuilder(StoreInterface::class)->getMock(); + + $store = new CombinedStore(array($store1, $store2), $this->strategy); + + $key = new Key(uniqid(__METHOD__, true)); + $ttl = random_int(1, 10); + + $this->strategy + ->expects($this->any()) + ->method('canBeMet') + ->willReturn(true); + $this->strategy + ->expects($this->once()) + ->method('isMet') + ->with(2, 2) + ->willReturn(true); + + $store->putOffExpiration($key, $ttl); + } + + public function testExistsDontAskToEveryBody() + { + $key = new Key(uniqid(__METHOD__, true)); + + $this->store1 + ->expects($this->any()) + ->method('exists') + ->with($key) + ->willReturn(false); + $this->store2 + ->expects($this->never()) + ->method('exists'); + + $this->strategy + ->expects($this->any()) + ->method('canBeMet') + ->willReturn(true); + $this->strategy + ->expects($this->once()) + ->method('isMet') + ->willReturn(true); + + $this->assertTrue($this->store->exists($key)); + } + + public function testExistsAbortWhenStrategyCantBeMet() + { + $key = new Key(uniqid(__METHOD__, true)); + + $this->store1 + ->expects($this->any()) + ->method('exists') + ->with($key) + ->willReturn(false); + $this->store2 + ->expects($this->never()) + ->method('exists'); + + $this->strategy + ->expects($this->once()) + ->method('canBeMet') + ->willReturn(false); + $this->strategy + ->expects($this->once()) + ->method('isMet') + ->willReturn(false); + + $this->assertFalse($this->store->exists($key)); + } + + public function testDeleteDontStopOnFailure() + { + $key = new Key(uniqid(__METHOD__, true)); + + $this->store1 + ->expects($this->once()) + ->method('delete') + ->with($key) + ->willThrowException(new \Exception()); + $this->store2 + ->expects($this->once()) + ->method('delete') + ->with($key); + + $this->store->delete($key); + } +} diff --git a/src/Symfony/Component/Lock/Tests/Store/ExpiringStoreTestTrait.php b/src/Symfony/Component/Lock/Tests/Store/ExpiringStoreTestTrait.php new file mode 100644 index 0000000000000..0280aa61739ee --- /dev/null +++ b/src/Symfony/Component/Lock/Tests/Store/ExpiringStoreTestTrait.php @@ -0,0 +1,78 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Lock\Tests\Store; + +use Symfony\Component\Lock\Key; +use Symfony\Component\Lock\StoreInterface; + +/** + * @author Jérémy Derussé + */ +trait ExpiringStoreTestTrait +{ + /** + * Amount a microsecond used to order async actions. + * + * @return int + */ + abstract protected function getClockDelay(); + + /** + * @see AbstractStoreTest::getStore() + */ + abstract protected function getStore(); + + /** + * Tests the store automatically delete the key when it expire. + * + * This test is time sensible: the $clockDelay could be adjust. + */ + public function testExpiration() + { + $key = new Key(uniqid(__METHOD__, true)); + $clockDelay = $this->getClockDelay(); + + /** @var StoreInterface $store */ + $store = $this->getStore(); + + $store->save($key); + $store->putOffExpiration($key, $clockDelay / 1000000); + $this->assertTrue($store->exists($key)); + + usleep(2 * $clockDelay); + $this->assertFalse($store->exists($key)); + } + + /** + * Tests the refresh can push the limits to the expiration. + * + * This test is time sensible: the $clockDelay could be adjust. + */ + public function testRefreshLock() + { + // Amount a microsecond used to order async actions + $clockDelay = $this->getClockDelay(); + + // Amount a microsecond used to order async actions + $key = new Key(uniqid(__METHOD__, true)); + + /** @var StoreInterface $store */ + $store = $this->getStore(); + + $store->save($key); + $store->putOffExpiration($key, 1.0 * $clockDelay / 1000000); + $this->assertTrue($store->exists($key)); + + usleep(2.1 * $clockDelay); + $this->assertFalse($store->exists($key)); + } +} diff --git a/src/Symfony/Component/Lock/Tests/Store/FlockStoreTest.php b/src/Symfony/Component/Lock/Tests/Store/FlockStoreTest.php new file mode 100644 index 0000000000000..17c59c440a9cc --- /dev/null +++ b/src/Symfony/Component/Lock/Tests/Store/FlockStoreTest.php @@ -0,0 +1,77 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Lock\Tests\Store; + +use Symfony\Component\Lock\Key; +use Symfony\Component\Lock\Store\FlockStore; + +/** + * @author Jérémy Derussé + */ +class FlockStoreTest extends AbstractStoreTest +{ + use BlockingStoreTestTrait; + + /** + * {@inheritdoc} + */ + protected function getStore() + { + return new FlockStore(sys_get_temp_dir()); + } + + /** + * @expectedException \Symfony\Component\Lock\Exception\InvalidArgumentException + * @expectedExceptionMessage The directory "/a/b/c/d/e" is not writable. + */ + public function testConstructWhenRepositoryDoesNotExist() + { + if (!getenv('USER') || 'root' === getenv('USER')) { + $this->markTestSkipped('This test will fail if run under superuser'); + } + + new FlockStore('/a/b/c/d/e'); + } + + /** + * @expectedException \Symfony\Component\Lock\Exception\InvalidArgumentException + * @expectedExceptionMessage The directory "/" is not writable. + */ + public function testConstructWhenRepositoryIsNotWriteable() + { + if (!getenv('USER') || 'root' === getenv('USER')) { + $this->markTestSkipped('This test will fail if run under superuser'); + } + + new FlockStore('/'); + } + + public function testSaveSanitizeName() + { + $store = $this->getStore(); + + $key = new Key(''); + + $file = sprintf( + '%s/sf.-php-echo-hello-word-.4b3d9d0d27ddef3a78a64685dda3a963e478659a9e5240feaf7b4173a8f28d5f.lock', + sys_get_temp_dir() + ); + // ensure the file does not exist before the store + @unlink($file); + + $store->save($key); + + $this->assertFileExists($file); + + $store->delete($key); + } +} diff --git a/src/Symfony/Component/Lock/Tests/Store/MemcachedStoreTest.php b/src/Symfony/Component/Lock/Tests/Store/MemcachedStoreTest.php new file mode 100644 index 0000000000000..72615baae2ce8 --- /dev/null +++ b/src/Symfony/Component/Lock/Tests/Store/MemcachedStoreTest.php @@ -0,0 +1,52 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Lock\Tests\Store; + +use Symfony\Component\Lock\Store\MemcachedStore; + +/** + * @author Jérémy Derussé + * + * @requires extension memcached + */ +class MemcachedStoreTest extends AbstractStoreTest +{ + use ExpiringStoreTestTrait; + + public static function setupBeforeClass() + { + $memcached = new \Memcached(); + $memcached->addServer(getenv('MEMCACHED_HOST'), 11211); + if (false === $memcached->getStats()) { + self::markTestSkipped('Unable to connect to the memcache host'); + } + } + + /** + * {@inheritdoc} + */ + protected function getClockDelay() + { + return 1000000; + } + + /** + * {@inheritdoc} + */ + public function getStore() + { + $memcached = new \Memcached(); + $memcached->addServer(getenv('MEMCACHED_HOST'), 11211); + + return new MemcachedStore($memcached); + } +} diff --git a/src/Symfony/Component/Lock/Tests/Store/PredisStoreTest.php b/src/Symfony/Component/Lock/Tests/Store/PredisStoreTest.php new file mode 100644 index 0000000000000..621affecb5435 --- /dev/null +++ b/src/Symfony/Component/Lock/Tests/Store/PredisStoreTest.php @@ -0,0 +1,36 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Lock\Tests\Store; + +/** + * @author Jérémy Derussé + */ +class PredisStoreTest extends AbstractRedisStoreTest +{ + public static function setupBeforeClass() + { + $redis = new \Predis\Client('tcp://'.getenv('REDIS_HOST').':6379'); + try { + $redis->connect(); + } catch (\Exception $e) { + self::markTestSkipped($e->getMessage()); + } + } + + protected function getRedisConnection() + { + $redis = new \Predis\Client('tcp://'.getenv('REDIS_HOST').':6379'); + $redis->connect(); + + return $redis; + } +} diff --git a/src/Symfony/Component/Lock/Tests/Store/RedisArrayStoreTest.php b/src/Symfony/Component/Lock/Tests/Store/RedisArrayStoreTest.php new file mode 100644 index 0000000000000..180da4618da03 --- /dev/null +++ b/src/Symfony/Component/Lock/Tests/Store/RedisArrayStoreTest.php @@ -0,0 +1,38 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Lock\Tests\Store; + +/** + * @author Jérémy Derussé + * + * @requires extension redis + */ +class RedisArrayStoreTest extends AbstractRedisStoreTest +{ + public static function setupBeforeClass() + { + if (!class_exists('RedisArray')) { + self::markTestSkipped('The RedisArray class is required.'); + } + if (!@((new \Redis())->connect(getenv('REDIS_HOST')))) { + $e = error_get_last(); + self::markTestSkipped($e['message']); + } + } + + protected function getRedisConnection() + { + $redis = new \RedisArray(array(getenv('REDIS_HOST'))); + + return $redis; + } +} diff --git a/src/Symfony/Component/Lock/Tests/Store/RedisStoreTest.php b/src/Symfony/Component/Lock/Tests/Store/RedisStoreTest.php new file mode 100644 index 0000000000000..6c7d244107b6d --- /dev/null +++ b/src/Symfony/Component/Lock/Tests/Store/RedisStoreTest.php @@ -0,0 +1,36 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Lock\Tests\Store; + +/** + * @author Jérémy Derussé + * + * @requires extension redis + */ +class RedisStoreTest extends AbstractRedisStoreTest +{ + public static function setupBeforeClass() + { + if (!@((new \Redis())->connect(getenv('REDIS_HOST')))) { + $e = error_get_last(); + self::markTestSkipped($e['message']); + } + } + + protected function getRedisConnection() + { + $redis = new \Redis(); + $redis->connect(getenv('REDIS_HOST')); + + return $redis; + } +} diff --git a/src/Symfony/Component/Lock/Tests/Store/RetryTillSaveStoreTest.php b/src/Symfony/Component/Lock/Tests/Store/RetryTillSaveStoreTest.php new file mode 100644 index 0000000000000..febd48f279fc5 --- /dev/null +++ b/src/Symfony/Component/Lock/Tests/Store/RetryTillSaveStoreTest.php @@ -0,0 +1,35 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Lock\Tests\Store; + +use Symfony\Component\Lock\Store\RedisStore; +use Symfony\Component\Lock\Store\RetryTillSaveStore; + +/** + * @author Jérémy Derussé + */ +class RetryTillSaveStoreTest extends AbstractStoreTest +{ + use BlockingStoreTestTrait; + + public function getStore() + { + $redis = new \Predis\Client('tcp://'.getenv('REDIS_HOST').':6379'); + try { + $redis->connect(); + } catch (\Exception $e) { + self::markTestSkipped($e->getMessage()); + } + + return new RetryTillSaveStore(new RedisStore($redis), 100, 100); + } +} diff --git a/src/Symfony/Component/Lock/Tests/Store/SemaphoreStoreTest.php b/src/Symfony/Component/Lock/Tests/Store/SemaphoreStoreTest.php new file mode 100644 index 0000000000000..b989910507818 --- /dev/null +++ b/src/Symfony/Component/Lock/Tests/Store/SemaphoreStoreTest.php @@ -0,0 +1,36 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Lock\Tests\Store; + +use Symfony\Component\Lock\Store\SemaphoreStore; + +/** + * @author Jérémy Derussé + * + * @requires extension sysvsem + */ +class SemaphoreStoreTest extends AbstractStoreTest +{ + use BlockingStoreTestTrait; + + /** + * {@inheritdoc} + */ + protected function getStore() + { + if (PHP_VERSION_ID < 50601) { + $this->markTestSkipped('Non blocking semaphore are supported by PHP version greater or equals than 5.6.1'); + } + + return new SemaphoreStore(); + } +} diff --git a/src/Symfony/Component/Lock/Tests/Strategy/ConsensusStrategyTest.php b/src/Symfony/Component/Lock/Tests/Strategy/ConsensusStrategyTest.php new file mode 100644 index 0000000000000..09215f9a94d63 --- /dev/null +++ b/src/Symfony/Component/Lock/Tests/Strategy/ConsensusStrategyTest.php @@ -0,0 +1,89 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Lock\Tests\Strategy; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\Lock\Strategy\ConsensusStrategy; + +/** + * @author Jérémy Derussé + */ +class ConsensusStrategyTest extends TestCase +{ + /** @var ConsensusStrategy */ + private $strategy; + + public function setup() + { + $this->strategy = new ConsensusStrategy(); + } + + public function provideMetResults() + { + // success, failure, total, isMet + yield array(3, 0, 3, true); + yield array(2, 1, 3, true); + yield array(2, 0, 3, true); + yield array(1, 2, 3, false); + yield array(1, 1, 3, false); + yield array(1, 0, 3, false); + yield array(0, 3, 3, false); + yield array(0, 2, 3, false); + yield array(0, 1, 3, false); + yield array(0, 0, 3, false); + + yield array(2, 0, 2, true); + yield array(1, 1, 2, false); + yield array(1, 0, 2, false); + yield array(0, 2, 2, false); + yield array(0, 1, 2, false); + yield array(0, 0, 2, false); + } + + public function provideIndeterminate() + { + // success, failure, total, canBeMet + yield array(3, 0, 3, true); + yield array(2, 1, 3, true); + yield array(2, 0, 3, true); + yield array(1, 2, 3, false); + yield array(1, 1, 3, true); + yield array(1, 0, 3, true); + yield array(0, 3, 3, false); + yield array(0, 2, 3, false); + yield array(0, 1, 3, true); + yield array(0, 0, 3, true); + + yield array(2, 0, 2, true); + yield array(1, 1, 2, false); + yield array(1, 0, 2, true); + yield array(0, 2, 2, false); + yield array(0, 1, 2, false); + yield array(0, 0, 2, true); + } + + /** + * @dataProvider provideMetResults + */ + public function testMet($success, $failure, $total, $isMet) + { + $this->assertSame($isMet, $this->strategy->isMet($success, $total)); + } + + /** + * @dataProvider provideIndeterminate + */ + public function canBeMet($success, $failure, $total, $isMet) + { + $this->assertSame($isMet, $this->strategy->canBeMet($failure, $total)); + } +} diff --git a/src/Symfony/Component/Lock/Tests/Strategy/UnanimousStrategyTest.php b/src/Symfony/Component/Lock/Tests/Strategy/UnanimousStrategyTest.php new file mode 100644 index 0000000000000..76ea68a41e3b3 --- /dev/null +++ b/src/Symfony/Component/Lock/Tests/Strategy/UnanimousStrategyTest.php @@ -0,0 +1,89 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Lock\Tests\Strategy; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\Lock\Strategy\UnanimousStrategy; + +/** + * @author Jérémy Derussé + */ +class UnanimousStrategyTest extends TestCase +{ + /** @var UnanimousStrategy */ + private $strategy; + + public function setup() + { + $this->strategy = new UnanimousStrategy(); + } + + public function provideMetResults() + { + // success, failure, total, isMet + yield array(3, 0, 3, true); + yield array(2, 1, 3, false); + yield array(2, 0, 3, false); + yield array(1, 2, 3, false); + yield array(1, 1, 3, false); + yield array(1, 0, 3, false); + yield array(0, 3, 3, false); + yield array(0, 2, 3, false); + yield array(0, 1, 3, false); + yield array(0, 0, 3, false); + + yield array(2, 0, 2, true); + yield array(1, 1, 2, false); + yield array(1, 0, 2, false); + yield array(0, 2, 2, false); + yield array(0, 1, 2, false); + yield array(0, 0, 2, false); + } + + public function provideIndeterminate() + { + // success, failure, total, canBeMet + yield array(3, 0, 3, true); + yield array(2, 1, 3, false); + yield array(2, 0, 3, true); + yield array(1, 2, 3, false); + yield array(1, 1, 3, false); + yield array(1, 0, 3, true); + yield array(0, 3, 3, false); + yield array(0, 2, 3, false); + yield array(0, 1, 3, false); + yield array(0, 0, 3, true); + + yield array(2, 0, 2, true); + yield array(1, 1, 2, false); + yield array(1, 0, 2, true); + yield array(0, 2, 2, false); + yield array(0, 1, 2, false); + yield array(0, 0, 2, true); + } + + /** + * @dataProvider provideMetResults + */ + public function testMet($success, $failure, $total, $isMet) + { + $this->assertSame($isMet, $this->strategy->isMet($success, $total)); + } + + /** + * @dataProvider provideIndeterminate + */ + public function canBeMet($success, $failure, $total, $isMet) + { + $this->assertSame($isMet, $this->strategy->canBeMet($failure, $total)); + } +} diff --git a/src/Symfony/Component/Lock/composer.json b/src/Symfony/Component/Lock/composer.json new file mode 100644 index 0000000000000..ea25802233bc5 --- /dev/null +++ b/src/Symfony/Component/Lock/composer.json @@ -0,0 +1,38 @@ +{ + "name": "symfony/lock", + "type": "library", + "description": "Symfony Lock Component", + "keywords": ["locking", "redlock", "mutex", "semaphore", "flock", "cas"], + "homepage": "https://symfony.com", + "license": "MIT", + "authors": [ + { + "name": "Jérémy Derussé", + "email": "jeremy@derusse.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "require": { + "php": ">=5.5.9", + "symfony/polyfill-php70": "~1.0", + "psr/log": "~1.0" + }, + "require-dev": { + "predis/predis": "~1.0" + }, + "autoload": { + "psr-4": { "Symfony\\Component\\Lock\\": "" }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "minimum-stability": "dev", + "extra": { + "branch-alias": { + "dev-master": "3.4-dev" + } + } +} diff --git a/src/Symfony/Component/Lock/phpunit.xml.dist b/src/Symfony/Component/Lock/phpunit.xml.dist new file mode 100644 index 0000000000000..be3ca21576fdd --- /dev/null +++ b/src/Symfony/Component/Lock/phpunit.xml.dist @@ -0,0 +1,32 @@ + + + + + + + + + + + + ./Tests/ + + + + + + ./ + + ./Tests + ./vendor + + + + From 956003134590226789eede159c1d89f10ffd8281 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Tue, 23 May 2017 23:46:08 +0200 Subject: [PATCH 0060/1099] [Routing] remove deprecated features --- src/Symfony/Component/Routing/CHANGELOG.md | 6 ++++++ src/Symfony/Component/Routing/RouteCompiler.php | 6 ++---- src/Symfony/Component/Routing/Tests/RouteCompilerTest.php | 3 +-- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/src/Symfony/Component/Routing/CHANGELOG.md b/src/Symfony/Component/Routing/CHANGELOG.md index d04581f405069..206c1ccf612ff 100644 --- a/src/Symfony/Component/Routing/CHANGELOG.md +++ b/src/Symfony/Component/Routing/CHANGELOG.md @@ -1,6 +1,12 @@ CHANGELOG ========= +4.0.0 +----- + + * dropped support for using UTF-8 route patterns without using the `utf8` option + * dropped support for using UTF-8 route requirements without using the `utf8` option + 3.3.0 ----- diff --git a/src/Symfony/Component/Routing/RouteCompiler.php b/src/Symfony/Component/Routing/RouteCompiler.php index a64776a01ae2e..872203f3f5d6f 100644 --- a/src/Symfony/Component/Routing/RouteCompiler.php +++ b/src/Symfony/Component/Routing/RouteCompiler.php @@ -103,8 +103,7 @@ private static function compilePattern(Route $route, $pattern, $isHost) $needsUtf8 = $route->getOption('utf8'); if (!$needsUtf8 && $useUtf8 && preg_match('/[\x80-\xFF]/', $pattern)) { - $needsUtf8 = true; - @trigger_error(sprintf('Using UTF-8 route patterns without setting the "utf8" option is deprecated since Symfony 3.2 and will throw a LogicException in 4.0. Turn on the "utf8" route option for pattern "%s".', $pattern), E_USER_DEPRECATED); + throw new \LogicException(sprintf('Cannot use UTF-8 route patterns without setting the "utf8" option for route "%s".', $route->getPath())); } if (!$useUtf8 && $needsUtf8) { throw new \LogicException(sprintf('Cannot mix UTF-8 requirements with non-UTF-8 pattern "%s".', $pattern)); @@ -176,8 +175,7 @@ private static function compilePattern(Route $route, $pattern, $isHost) if (!preg_match('//u', $regexp)) { $useUtf8 = false; } elseif (!$needsUtf8 && preg_match('/[\x80-\xFF]|(? Date: Wed, 24 May 2017 11:02:43 +0200 Subject: [PATCH 0061/1099] [3.4] Allow 4.* deps --- src/Symfony/Bridge/Doctrine/composer.json | 22 +++---- src/Symfony/Bridge/Monolog/composer.json | 8 +-- src/Symfony/Bridge/ProxyManager/composer.json | 4 +- src/Symfony/Bridge/Twig/composer.json | 28 ++++----- src/Symfony/Bundle/DebugBundle/composer.json | 12 ++-- .../Bundle/FrameworkBundle/composer.json | 58 +++++++++---------- .../Bundle/SecurityBundle/composer.json | 38 ++++++------ src/Symfony/Bundle/TwigBundle/composer.json | 22 +++---- .../Bundle/WebProfilerBundle/composer.json | 16 ++--- .../Bundle/WebServerBundle/composer.json | 6 +- src/Symfony/Component/Asset/composer.json | 4 +- .../Component/BrowserKit/composer.json | 6 +- .../Component/ClassLoader/composer.json | 2 +- src/Symfony/Component/Config/composer.json | 6 +- src/Symfony/Component/Console/composer.json | 12 ++-- src/Symfony/Component/Debug/composer.json | 2 +- .../DependencyInjection/composer.json | 6 +- .../Component/DomCrawler/composer.json | 2 +- src/Symfony/Component/Dotenv/composer.json | 2 +- .../Component/EventDispatcher/composer.json | 8 +-- .../ExpressionLanguage/composer.json | 2 +- src/Symfony/Component/Form/composer.json | 24 ++++---- .../Component/HttpFoundation/composer.json | 2 +- .../Component/HttpKernel/composer.json | 34 +++++------ src/Symfony/Component/Intl/composer.json | 2 +- src/Symfony/Component/Ldap/composer.json | 2 +- .../Component/PropertyAccess/composer.json | 4 +- .../Component/PropertyInfo/composer.json | 8 +-- src/Symfony/Component/Routing/composer.json | 10 ++-- .../Component/Security/Core/composer.json | 10 ++-- .../Component/Security/Csrf/composer.json | 4 +- .../Component/Security/Guard/composer.json | 4 +- .../Component/Security/Http/composer.json | 14 ++--- src/Symfony/Component/Security/composer.json | 18 +++--- .../Component/Serializer/composer.json | 14 ++--- .../Component/Translation/composer.json | 6 +- src/Symfony/Component/Validator/composer.json | 16 ++--- src/Symfony/Component/WebLink/composer.json | 6 +- src/Symfony/Component/Workflow/composer.json | 10 ++-- src/Symfony/Component/Yaml/composer.json | 2 +- 40 files changed, 228 insertions(+), 228 deletions(-) diff --git a/src/Symfony/Bridge/Doctrine/composer.json b/src/Symfony/Bridge/Doctrine/composer.json index 28fb8491d49f0..6558860588e60 100644 --- a/src/Symfony/Bridge/Doctrine/composer.json +++ b/src/Symfony/Bridge/Doctrine/composer.json @@ -21,17 +21,17 @@ "symfony/polyfill-mbstring": "~1.0" }, "require-dev": { - "symfony/stopwatch": "~2.8|~3.0|~4.0.0", - "symfony/dependency-injection": "~3.3|~4.0.0", - "symfony/form": "^3.2.5|~4.0.0", - "symfony/http-kernel": "~2.8|~3.0|~4.0.0", - "symfony/property-access": "~2.8|~3.0|~4.0.0", - "symfony/property-info": "~2.8|3.0|~4.0.0", - "symfony/proxy-manager-bridge": "~2.8|~3.0|~4.0.0", - "symfony/security": "~2.8|~3.0|~4.0.0", - "symfony/expression-language": "~2.8|~3.0|~4.0.0", - "symfony/validator": "^3.2.5|~4.0.0", - "symfony/translation": "~2.8|~3.0|~4.0.0", + "symfony/stopwatch": "~2.8|~3.0|~4.0", + "symfony/dependency-injection": "~3.3|~4.0", + "symfony/form": "^3.2.5|~4.0", + "symfony/http-kernel": "~2.8|~3.0|~4.0", + "symfony/property-access": "~2.8|~3.0|~4.0", + "symfony/property-info": "~2.8|3.0|~4.0", + "symfony/proxy-manager-bridge": "~2.8|~3.0|~4.0", + "symfony/security": "~2.8|~3.0|~4.0", + "symfony/expression-language": "~2.8|~3.0|~4.0", + "symfony/validator": "^3.2.5|~4.0", + "symfony/translation": "~2.8|~3.0|~4.0", "doctrine/data-fixtures": "1.0.*", "doctrine/dbal": "~2.4", "doctrine/orm": "^2.4.5" diff --git a/src/Symfony/Bridge/Monolog/composer.json b/src/Symfony/Bridge/Monolog/composer.json index 5622ce1b88b09..b627abad0a79a 100644 --- a/src/Symfony/Bridge/Monolog/composer.json +++ b/src/Symfony/Bridge/Monolog/composer.json @@ -18,12 +18,12 @@ "require": { "php": ">=5.5.9", "monolog/monolog": "~1.19", - "symfony/http-kernel": "~2.8|~3.0|~4.0.0" + "symfony/http-kernel": "~2.8|~3.0|~4.0" }, "require-dev": { - "symfony/console": "~2.8|~3.0|~4.0.0", - "symfony/event-dispatcher": "~2.8|~3.0|~4.0.0", - "symfony/var-dumper": "~3.3|~4.0.0" + "symfony/console": "~2.8|~3.0|~4.0", + "symfony/event-dispatcher": "~2.8|~3.0|~4.0", + "symfony/var-dumper": "~3.3|~4.0" }, "conflict": { "symfony/http-foundation": "<3.3" diff --git a/src/Symfony/Bridge/ProxyManager/composer.json b/src/Symfony/Bridge/ProxyManager/composer.json index a13589816c652..510257552d797 100644 --- a/src/Symfony/Bridge/ProxyManager/composer.json +++ b/src/Symfony/Bridge/ProxyManager/composer.json @@ -17,11 +17,11 @@ ], "require": { "php": ">=5.5.9", - "symfony/dependency-injection": "~2.8|~3.0|~4.0.0", + "symfony/dependency-injection": "~2.8|~3.0|~4.0", "ocramius/proxy-manager": "~0.4|~1.0|~2.0" }, "require-dev": { - "symfony/config": "~2.8|~3.0|~4.0.0" + "symfony/config": "~2.8|~3.0|~4.0" }, "autoload": { "psr-4": { "Symfony\\Bridge\\ProxyManager\\": "" }, diff --git a/src/Symfony/Bridge/Twig/composer.json b/src/Symfony/Bridge/Twig/composer.json index bbeeb4df45ee5..fd86e83fb20c0 100644 --- a/src/Symfony/Bridge/Twig/composer.json +++ b/src/Symfony/Bridge/Twig/composer.json @@ -21,22 +21,22 @@ }, "require-dev": { "fig/link-util": "^1.0", - "symfony/asset": "~2.8|~3.0|~4.0.0", - "symfony/finder": "~2.8|~3.0|~4.0.0", - "symfony/form": "^3.2.7|~4.0.0", - "symfony/http-kernel": "~3.2|~4.0.0", + "symfony/asset": "~2.8|~3.0|~4.0", + "symfony/finder": "~2.8|~3.0|~4.0", + "symfony/form": "^3.2.7|~4.0", + "symfony/http-kernel": "~3.2|~4.0", "symfony/polyfill-intl-icu": "~1.0", - "symfony/routing": "~2.8|~3.0|~4.0.0", - "symfony/templating": "~2.8|~3.0|~4.0.0", - "symfony/translation": "~2.8|~3.0|~4.0.0", - "symfony/yaml": "~2.8|~3.0|~4.0.0", - "symfony/security": "~2.8|~3.0|~4.0.0", + "symfony/routing": "~2.8|~3.0|~4.0", + "symfony/templating": "~2.8|~3.0|~4.0", + "symfony/translation": "~2.8|~3.0|~4.0", + "symfony/yaml": "~2.8|~3.0|~4.0", + "symfony/security": "~2.8|~3.0|~4.0", "symfony/security-acl": "~2.8|~3.0", - "symfony/stopwatch": "~2.8|~3.0|~4.0.0", - "symfony/console": "~2.8|~3.0|~4.0.0", - "symfony/var-dumper": "~2.8.10|~3.1.4|~3.2|~4.0.0", - "symfony/expression-language": "~2.8|~3.0|~4.0.0", - "symfony/web-link": "~3.3|~4.0.0" + "symfony/stopwatch": "~2.8|~3.0|~4.0", + "symfony/console": "~2.8|~3.0|~4.0", + "symfony/var-dumper": "~2.8.10|~3.1.4|~3.2|~4.0", + "symfony/expression-language": "~2.8|~3.0|~4.0", + "symfony/web-link": "~3.3|~4.0" }, "suggest": { "symfony/finder": "", diff --git a/src/Symfony/Bundle/DebugBundle/composer.json b/src/Symfony/Bundle/DebugBundle/composer.json index e910d4d927e3c..89376a9b8b5a4 100644 --- a/src/Symfony/Bundle/DebugBundle/composer.json +++ b/src/Symfony/Bundle/DebugBundle/composer.json @@ -17,14 +17,14 @@ ], "require": { "php": ">=5.5.9", - "symfony/http-kernel": "~2.8|~3.0|~4.0.0", - "symfony/twig-bridge": "~2.8|~3.0|~4.0.0", - "symfony/var-dumper": "~2.8|~3.0|~4.0.0" + "symfony/http-kernel": "~2.8|~3.0|~4.0", + "symfony/twig-bridge": "~2.8|~3.0|~4.0", + "symfony/var-dumper": "~2.8|~3.0|~4.0" }, "require-dev": { - "symfony/config": "~3.3|~4.0.0", - "symfony/dependency-injection": "~3.3|~4.0.0", - "symfony/web-profiler-bundle": "~2.8|~3.0|~4.0.0" + "symfony/config": "~3.3|~4.0", + "symfony/dependency-injection": "~3.3|~4.0", + "symfony/web-profiler-bundle": "~2.8|~3.0|~4.0" }, "suggest": { "symfony/config": "For service container configuration", diff --git a/src/Symfony/Bundle/FrameworkBundle/composer.json b/src/Symfony/Bundle/FrameworkBundle/composer.json index 5355f61f31cc6..038ef7e4bc8b4 100644 --- a/src/Symfony/Bundle/FrameworkBundle/composer.json +++ b/src/Symfony/Bundle/FrameworkBundle/composer.json @@ -18,42 +18,42 @@ "require": { "php": ">=5.5.9", "ext-xml": "*", - "symfony/cache": "~3.3|~4.0.0", + "symfony/cache": "~3.3|~4.0", "symfony/class-loader": "~3.2", - "symfony/dependency-injection": "~3.3-beta2|~4.0.0", - "symfony/config": "~3.3|~4.0.0", - "symfony/event-dispatcher": "~3.3|~4.0.0", - "symfony/http-foundation": "~3.3|~4.0.0", - "symfony/http-kernel": "~3.3|~4.0.0", + "symfony/dependency-injection": "~3.3-beta2|~4.0", + "symfony/config": "~3.3|~4.0", + "symfony/event-dispatcher": "~3.3|~4.0", + "symfony/http-foundation": "~3.3|~4.0", + "symfony/http-kernel": "~3.3|~4.0", "symfony/polyfill-mbstring": "~1.0", - "symfony/filesystem": "~2.8|~3.0|~4.0.0", - "symfony/finder": "~2.8|~3.0|~4.0.0", - "symfony/routing": "~3.3|~4.0.0", - "symfony/stopwatch": "~2.8|~3.0|~4.0.0", + "symfony/filesystem": "~2.8|~3.0|~4.0", + "symfony/finder": "~2.8|~3.0|~4.0", + "symfony/routing": "~3.3|~4.0", + "symfony/stopwatch": "~2.8|~3.0|~4.0", "doctrine/cache": "~1.0" }, "require-dev": { "fig/link-util": "^1.0", - "symfony/asset": "~3.3|~4.0.0", - "symfony/browser-kit": "~2.8|~3.0|~4.0.0", - "symfony/console": "~3.3|~4.0.0", - "symfony/css-selector": "~2.8|~3.0|~4.0.0", - "symfony/dom-crawler": "~2.8|~3.0|~4.0.0", + "symfony/asset": "~3.3|~4.0", + "symfony/browser-kit": "~2.8|~3.0|~4.0", + "symfony/console": "~3.3|~4.0", + "symfony/css-selector": "~2.8|~3.0|~4.0", + "symfony/dom-crawler": "~2.8|~3.0|~4.0", "symfony/polyfill-intl-icu": "~1.0", - "symfony/security": "~2.8|~3.0|~4.0.0", - "symfony/form": "~3.3|~4.0.0", - "symfony/expression-language": "~2.8|~3.0|~4.0.0", - "symfony/process": "~2.8|~3.0|~4.0.0", - "symfony/security-core": "~3.2|~4.0.0", - "symfony/security-csrf": "~2.8|~3.0|~4.0.0", - "symfony/serializer": "~3.3|~4.0.0", - "symfony/translation": "~3.2|~4.0.0", - "symfony/templating": "~2.8|~3.0|~4.0.0", - "symfony/validator": "~3.3|~4.0.0", - "symfony/workflow": "~3.3|~4.0.0", - "symfony/yaml": "~3.2|~4.0.0", - "symfony/property-info": "~3.3|~4.0.0", - "symfony/web-link": "~3.3|~4.0.0", + "symfony/security": "~2.8|~3.0|~4.0", + "symfony/form": "~3.3|~4.0", + "symfony/expression-language": "~2.8|~3.0|~4.0", + "symfony/process": "~2.8|~3.0|~4.0", + "symfony/security-core": "~3.2|~4.0", + "symfony/security-csrf": "~2.8|~3.0|~4.0", + "symfony/serializer": "~3.3|~4.0", + "symfony/translation": "~3.2|~4.0", + "symfony/templating": "~2.8|~3.0|~4.0", + "symfony/validator": "~3.3|~4.0", + "symfony/workflow": "~3.3|~4.0", + "symfony/yaml": "~3.2|~4.0", + "symfony/property-info": "~3.3|~4.0", + "symfony/web-link": "~3.3|~4.0", "doctrine/annotations": "~1.0", "phpdocumentor/reflection-docblock": "^3.0", "twig/twig": "~1.26|~2.0", diff --git a/src/Symfony/Bundle/SecurityBundle/composer.json b/src/Symfony/Bundle/SecurityBundle/composer.json index 275c7bbfce0d2..30b8f474b4ecb 100644 --- a/src/Symfony/Bundle/SecurityBundle/composer.json +++ b/src/Symfony/Bundle/SecurityBundle/composer.json @@ -17,29 +17,29 @@ ], "require": { "php": ">=5.5.9", - "symfony/security": "~3.3|~4.0.0", - "symfony/dependency-injection": "~3.3-beta2|~4.0.0", - "symfony/http-kernel": "~3.3|~4.0.0", + "symfony/security": "~3.3|~4.0", + "symfony/dependency-injection": "~3.3-beta2|~4.0", + "symfony/http-kernel": "~3.3|~4.0", "symfony/polyfill-php70": "~1.0" }, "require-dev": { - "symfony/asset": "~2.8|~3.0|~4.0.0", - "symfony/browser-kit": "~2.8|~3.0|~4.0.0", - "symfony/console": "~3.2|~4.0.0", - "symfony/css-selector": "~2.8|~3.0|~4.0.0", - "symfony/dom-crawler": "~2.8|~3.0|~4.0.0", - "symfony/form": "^2.8.18|^3.2.5|~4.0.0", - "symfony/framework-bundle": "^3.2.8|~4.0.0", - "symfony/http-foundation": "~2.8|~3.0|~4.0.0", + "symfony/asset": "~2.8|~3.0|~4.0", + "symfony/browser-kit": "~2.8|~3.0|~4.0", + "symfony/console": "~3.2|~4.0", + "symfony/css-selector": "~2.8|~3.0|~4.0", + "symfony/dom-crawler": "~2.8|~3.0|~4.0", + "symfony/form": "^2.8.18|^3.2.5|~4.0", + "symfony/framework-bundle": "^3.2.8|~4.0", + "symfony/http-foundation": "~2.8|~3.0|~4.0", "symfony/security-acl": "~2.8|~3.0", - "symfony/translation": "~2.8|~3.0|~4.0.0", - "symfony/twig-bundle": "~2.8|~3.0|~4.0.0", - "symfony/twig-bridge": "~2.8|~3.0|~4.0.0", - "symfony/process": "~2.8|~3.0|~4.0.0", - "symfony/validator": "^3.2.5|~4.0.0", - "symfony/var-dumper": "~3.3|~4.0.0", - "symfony/yaml": "~2.8|~3.0|~4.0.0", - "symfony/expression-language": "~2.8|~3.0|~4.0.0", + "symfony/translation": "~2.8|~3.0|~4.0", + "symfony/twig-bundle": "~2.8|~3.0|~4.0", + "symfony/twig-bridge": "~2.8|~3.0|~4.0", + "symfony/process": "~2.8|~3.0|~4.0", + "symfony/validator": "^3.2.5|~4.0", + "symfony/var-dumper": "~3.3|~4.0", + "symfony/yaml": "~2.8|~3.0|~4.0", + "symfony/expression-language": "~2.8|~3.0|~4.0", "doctrine/doctrine-bundle": "~1.4", "twig/twig": "~1.28|~2.0" }, diff --git a/src/Symfony/Bundle/TwigBundle/composer.json b/src/Symfony/Bundle/TwigBundle/composer.json index ece1c9160212b..c16d1dc6bd68a 100644 --- a/src/Symfony/Bundle/TwigBundle/composer.json +++ b/src/Symfony/Bundle/TwigBundle/composer.json @@ -24,17 +24,17 @@ "twig/twig": "^1.32|^2.2" }, "require-dev": { - "symfony/asset": "~2.8|~3.0|~4.0.0", - "symfony/stopwatch": "~2.8|~3.0|~4.0.0", - "symfony/dependency-injection": "~3.3|~4.0.0", - "symfony/expression-language": "~2.8|~3.0|~4.0.0", - "symfony/finder": "~2.8|~3.0|~4.0.0", - "symfony/form": "~2.8|~3.0|~4.0.0", - "symfony/routing": "~2.8|~3.0|~4.0.0", - "symfony/templating": "~2.8|~3.0|~4.0.0", - "symfony/yaml": "~2.8|~3.0|~4.0.0", - "symfony/framework-bundle": "^3.2.8|~4.0.0", - "symfony/web-link": "~3.3|~4.0.0", + "symfony/asset": "~2.8|~3.0|~4.0", + "symfony/stopwatch": "~2.8|~3.0|~4.0", + "symfony/dependency-injection": "~3.3|~4.0", + "symfony/expression-language": "~2.8|~3.0|~4.0", + "symfony/finder": "~2.8|~3.0|~4.0", + "symfony/form": "~2.8|~3.0|~4.0", + "symfony/routing": "~2.8|~3.0|~4.0", + "symfony/templating": "~2.8|~3.0|~4.0", + "symfony/yaml": "~2.8|~3.0|~4.0", + "symfony/framework-bundle": "^3.2.8|~4.0", + "symfony/web-link": "~3.3|~4.0", "doctrine/annotations": "~1.0" }, "conflict": { diff --git a/src/Symfony/Bundle/WebProfilerBundle/composer.json b/src/Symfony/Bundle/WebProfilerBundle/composer.json index e1c148baf5912..2769fc3d11528 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/composer.json +++ b/src/Symfony/Bundle/WebProfilerBundle/composer.json @@ -17,18 +17,18 @@ ], "require": { "php": ">=5.5.9", - "symfony/http-kernel": "~3.2|~4.0.0", + "symfony/http-kernel": "~3.2|~4.0", "symfony/polyfill-php70": "~1.0", - "symfony/routing": "~2.8|~3.0|~4.0.0", - "symfony/twig-bridge": "~2.8|~3.0|~4.0.0", + "symfony/routing": "~2.8|~3.0|~4.0", + "symfony/twig-bridge": "~2.8|~3.0|~4.0", "twig/twig": "~1.28|~2.0", - "symfony/var-dumper": "~3.3|~4.0.0" + "symfony/var-dumper": "~3.3|~4.0" }, "require-dev": { - "symfony/config": "~2.8|~3.0|~4.0.0", - "symfony/console": "~2.8|~3.0|~4.0.0", - "symfony/dependency-injection": "~3.3|~4.0.0", - "symfony/stopwatch": "~2.8|~3.0|~4.0.0" + "symfony/config": "~2.8|~3.0|~4.0", + "symfony/console": "~2.8|~3.0|~4.0", + "symfony/dependency-injection": "~3.3|~4.0", + "symfony/stopwatch": "~2.8|~3.0|~4.0" }, "conflict": { "symfony/dependency-injection": "<3.3", diff --git a/src/Symfony/Bundle/WebServerBundle/composer.json b/src/Symfony/Bundle/WebServerBundle/composer.json index cf6222295c8a0..9583782bbf114 100644 --- a/src/Symfony/Bundle/WebServerBundle/composer.json +++ b/src/Symfony/Bundle/WebServerBundle/composer.json @@ -17,9 +17,9 @@ ], "require": { "php": ">=5.5.9", - "symfony/console": "~2.8.8|~3.0.8|~3.1.2|~3.2|~4.0.0", - "symfony/http-kernel": "~2.8|~3.0|~4.0.0", - "symfony/process": "~2.8|~3.0|~4.0.0" + "symfony/console": "~2.8.8|~3.0.8|~3.1.2|~3.2|~4.0", + "symfony/http-kernel": "~2.8|~3.0|~4.0", + "symfony/process": "~2.8|~3.0|~4.0" }, "autoload": { "psr-4": { "Symfony\\Bundle\\WebServerBundle\\": "" }, diff --git a/src/Symfony/Component/Asset/composer.json b/src/Symfony/Component/Asset/composer.json index ffdb80b0d45d3..5966220dcc5ae 100644 --- a/src/Symfony/Component/Asset/composer.json +++ b/src/Symfony/Component/Asset/composer.json @@ -22,8 +22,8 @@ "symfony/http-foundation": "" }, "require-dev": { - "symfony/http-foundation": "~2.8|~3.0|~4.0.0", - "symfony/http-kernel": "~2.8|~3.0|~4.0.0" + "symfony/http-foundation": "~2.8|~3.0|~4.0", + "symfony/http-kernel": "~2.8|~3.0|~4.0" }, "autoload": { "psr-4": { "Symfony\\Component\\Asset\\": "" }, diff --git a/src/Symfony/Component/BrowserKit/composer.json b/src/Symfony/Component/BrowserKit/composer.json index 6a78ee846b276..14fea2567b969 100644 --- a/src/Symfony/Component/BrowserKit/composer.json +++ b/src/Symfony/Component/BrowserKit/composer.json @@ -17,11 +17,11 @@ ], "require": { "php": ">=5.5.9", - "symfony/dom-crawler": "~2.8|~3.0|~4.0.0" + "symfony/dom-crawler": "~2.8|~3.0|~4.0" }, "require-dev": { - "symfony/process": "~2.8|~3.0|~4.0.0", - "symfony/css-selector": "~2.8|~3.0|~4.0.0" + "symfony/process": "~2.8|~3.0|~4.0", + "symfony/css-selector": "~2.8|~3.0|~4.0" }, "suggest": { "symfony/process": "" diff --git a/src/Symfony/Component/ClassLoader/composer.json b/src/Symfony/Component/ClassLoader/composer.json index 690032cbccc9b..b8eeecdfa5ba4 100644 --- a/src/Symfony/Component/ClassLoader/composer.json +++ b/src/Symfony/Component/ClassLoader/composer.json @@ -20,7 +20,7 @@ "php": ">=5.5.9" }, "require-dev": { - "symfony/finder": "~2.8|~3.0|~4.0.0", + "symfony/finder": "~2.8|~3.0|~4.0", "symfony/polyfill-apcu": "~1.1" }, "suggest": { diff --git a/src/Symfony/Component/Config/composer.json b/src/Symfony/Component/Config/composer.json index 5ba594cb34afc..0e14ef8d937ec 100644 --- a/src/Symfony/Component/Config/composer.json +++ b/src/Symfony/Component/Config/composer.json @@ -17,11 +17,11 @@ ], "require": { "php": ">=5.5.9", - "symfony/filesystem": "~2.8|~3.0|~4.0.0" + "symfony/filesystem": "~2.8|~3.0|~4.0" }, "require-dev": { - "symfony/yaml": "~3.0|~4.0.0", - "symfony/dependency-injection": "~3.3|~4.0.0" + "symfony/yaml": "~3.0|~4.0", + "symfony/dependency-injection": "~3.3|~4.0" }, "conflict": { "symfony/dependency-injection": "<3.3" diff --git a/src/Symfony/Component/Console/composer.json b/src/Symfony/Component/Console/composer.json index 97cf6ae90b015..db73b1f371a4b 100644 --- a/src/Symfony/Component/Console/composer.json +++ b/src/Symfony/Component/Console/composer.json @@ -18,14 +18,14 @@ "require": { "php": ">=5.5.9", "symfony/polyfill-mbstring": "~1.0", - "symfony/debug": "~2.8|~3.0|~4.0.0" + "symfony/debug": "~2.8|~3.0|~4.0" }, "require-dev": { - "symfony/http-kernel": "~2.8|~3.0|~4.0.0", - "symfony/event-dispatcher": "~2.8|~3.0|~4.0.0", - "symfony/dependency-injection": "~3.3|~4.0.0", - "symfony/filesystem": "~2.8|~3.0|~4.0.0", - "symfony/process": "~2.8|~3.0|~4.0.0", + "symfony/http-kernel": "~2.8|~3.0|~4.0", + "symfony/event-dispatcher": "~2.8|~3.0|~4.0", + "symfony/dependency-injection": "~3.3|~4.0", + "symfony/filesystem": "~2.8|~3.0|~4.0", + "symfony/process": "~2.8|~3.0|~4.0", "psr/log": "~1.0" }, "suggest": { diff --git a/src/Symfony/Component/Debug/composer.json b/src/Symfony/Component/Debug/composer.json index 3fb492be41821..310fbaf006539 100644 --- a/src/Symfony/Component/Debug/composer.json +++ b/src/Symfony/Component/Debug/composer.json @@ -23,7 +23,7 @@ "symfony/http-kernel": ">=2.3,<2.3.24|~2.4.0|>=2.5,<2.5.9|>=2.6,<2.6.2" }, "require-dev": { - "symfony/http-kernel": "~2.8|~3.0|~4.0.0" + "symfony/http-kernel": "~2.8|~3.0|~4.0" }, "autoload": { "psr-4": { "Symfony\\Component\\Debug\\": "" }, diff --git a/src/Symfony/Component/DependencyInjection/composer.json b/src/Symfony/Component/DependencyInjection/composer.json index a682bfd007015..4b3e63385ea40 100644 --- a/src/Symfony/Component/DependencyInjection/composer.json +++ b/src/Symfony/Component/DependencyInjection/composer.json @@ -20,9 +20,9 @@ "psr/container": "^1.0" }, "require-dev": { - "symfony/yaml": "~3.3|~4.0.0", - "symfony/config": "~3.3|~4.0.0", - "symfony/expression-language": "~2.8|~3.0|~4.0.0" + "symfony/yaml": "~3.3|~4.0", + "symfony/config": "~3.3|~4.0", + "symfony/expression-language": "~2.8|~3.0|~4.0" }, "suggest": { "symfony/yaml": "", diff --git a/src/Symfony/Component/DomCrawler/composer.json b/src/Symfony/Component/DomCrawler/composer.json index dce2585d70506..765a08c0efb85 100644 --- a/src/Symfony/Component/DomCrawler/composer.json +++ b/src/Symfony/Component/DomCrawler/composer.json @@ -20,7 +20,7 @@ "symfony/polyfill-mbstring": "~1.0" }, "require-dev": { - "symfony/css-selector": "~2.8|~3.0|~4.0.0" + "symfony/css-selector": "~2.8|~3.0|~4.0" }, "suggest": { "symfony/css-selector": "" diff --git a/src/Symfony/Component/Dotenv/composer.json b/src/Symfony/Component/Dotenv/composer.json index 48210c7bc3bca..90fc80cbf5a7e 100644 --- a/src/Symfony/Component/Dotenv/composer.json +++ b/src/Symfony/Component/Dotenv/composer.json @@ -19,7 +19,7 @@ "php": ">=5.5.9" }, "require-dev": { - "symfony/process": "~3.2|~4.0.0" + "symfony/process": "~3.2|~4.0" }, "autoload": { "psr-4": { "Symfony\\Component\\Dotenv\\": "" }, diff --git a/src/Symfony/Component/EventDispatcher/composer.json b/src/Symfony/Component/EventDispatcher/composer.json index c9fb559fb6ec8..cc79a3141d42d 100644 --- a/src/Symfony/Component/EventDispatcher/composer.json +++ b/src/Symfony/Component/EventDispatcher/composer.json @@ -19,10 +19,10 @@ "php": ">=5.5.9" }, "require-dev": { - "symfony/dependency-injection": "~3.3|~4.0.0", - "symfony/expression-language": "~2.8|~3.0|~4.0.0", - "symfony/config": "~2.8|~3.0|~4.0.0", - "symfony/stopwatch": "~2.8|~3.0|~4.0.0", + "symfony/dependency-injection": "~3.3|~4.0", + "symfony/expression-language": "~2.8|~3.0|~4.0", + "symfony/config": "~2.8|~3.0|~4.0", + "symfony/stopwatch": "~2.8|~3.0|~4.0", "psr/log": "~1.0" }, "conflict": { diff --git a/src/Symfony/Component/ExpressionLanguage/composer.json b/src/Symfony/Component/ExpressionLanguage/composer.json index ffa6c0bc21212..47f8eb4902280 100644 --- a/src/Symfony/Component/ExpressionLanguage/composer.json +++ b/src/Symfony/Component/ExpressionLanguage/composer.json @@ -17,7 +17,7 @@ ], "require": { "php": ">=5.5.9", - "symfony/cache": "~3.1|~4.0.0" + "symfony/cache": "~3.1|~4.0" }, "autoload": { "psr-4": { "Symfony\\Component\\ExpressionLanguage\\": "" }, diff --git a/src/Symfony/Component/Form/composer.json b/src/Symfony/Component/Form/composer.json index a1e42ca025620..c9e646c6b2dec 100644 --- a/src/Symfony/Component/Form/composer.json +++ b/src/Symfony/Component/Form/composer.json @@ -17,22 +17,22 @@ ], "require": { "php": ">=5.5.9", - "symfony/event-dispatcher": "~2.8|~3.0|~4.0.0", - "symfony/intl": "^2.8.18|^3.2.5|~4.0.0", - "symfony/options-resolver": "~2.8|~3.0|~4.0.0", + "symfony/event-dispatcher": "~2.8|~3.0|~4.0", + "symfony/intl": "^2.8.18|^3.2.5|~4.0", + "symfony/options-resolver": "~2.8|~3.0|~4.0", "symfony/polyfill-mbstring": "~1.0", - "symfony/property-access": "~2.8|~3.0|~4.0.0" + "symfony/property-access": "~2.8|~3.0|~4.0" }, "require-dev": { "doctrine/collections": "~1.0", - "symfony/validator": "^3.2.5|~4.0.0", - "symfony/dependency-injection": "~3.3|~4.0.0", - "symfony/config": "~2.7|~3.0|~4.0.0", - "symfony/http-foundation": "~2.8|~3.0|~4.0.0", - "symfony/http-kernel": "~2.8|~3.0|~4.0.0", - "symfony/security-csrf": "~2.8|~3.0|~4.0.0", - "symfony/translation": "~2.8|~3.0|~4.0.0", - "symfony/var-dumper": "~3.3|~4.0.0" + "symfony/validator": "^3.2.5|~4.0", + "symfony/dependency-injection": "~3.3|~4.0", + "symfony/config": "~2.7|~3.0|~4.0", + "symfony/http-foundation": "~2.8|~3.0|~4.0", + "symfony/http-kernel": "~2.8|~3.0|~4.0", + "symfony/security-csrf": "~2.8|~3.0|~4.0", + "symfony/translation": "~2.8|~3.0|~4.0", + "symfony/var-dumper": "~3.3|~4.0" }, "conflict": { "phpunit/phpunit": "<4.8.35|<5.4.3,>=5.0", diff --git a/src/Symfony/Component/HttpFoundation/composer.json b/src/Symfony/Component/HttpFoundation/composer.json index 7e0994993fe3c..44192dfe17d3c 100644 --- a/src/Symfony/Component/HttpFoundation/composer.json +++ b/src/Symfony/Component/HttpFoundation/composer.json @@ -20,7 +20,7 @@ "symfony/polyfill-mbstring": "~1.1" }, "require-dev": { - "symfony/expression-language": "~2.8|~3.0|~4.0.0" + "symfony/expression-language": "~2.8|~3.0|~4.0" }, "autoload": { "psr-4": { "Symfony\\Component\\HttpFoundation\\": "" }, diff --git a/src/Symfony/Component/HttpKernel/composer.json b/src/Symfony/Component/HttpKernel/composer.json index fd5938b3b361f..7983e8b3bc2e8 100644 --- a/src/Symfony/Component/HttpKernel/composer.json +++ b/src/Symfony/Component/HttpKernel/composer.json @@ -17,27 +17,27 @@ ], "require": { "php": ">=5.5.9", - "symfony/event-dispatcher": "~2.8|~3.0|~4.0.0", - "symfony/http-foundation": "~3.3|~4.0.0", - "symfony/debug": "~2.8|~3.0|~4.0.0", + "symfony/event-dispatcher": "~2.8|~3.0|~4.0", + "symfony/http-foundation": "~3.3|~4.0", + "symfony/debug": "~2.8|~3.0|~4.0", "psr/log": "~1.0" }, "require-dev": { - "symfony/browser-kit": "~2.8|~3.0|~4.0.0", + "symfony/browser-kit": "~2.8|~3.0|~4.0", "symfony/class-loader": "~2.8|~3.0", - "symfony/config": "~2.8|~3.0|~4.0.0", - "symfony/console": "~2.8|~3.0|~4.0.0", - "symfony/css-selector": "~2.8|~3.0|~4.0.0", - "symfony/dependency-injection": "~3.3|~4.0.0", - "symfony/dom-crawler": "~2.8|~3.0|~4.0.0", - "symfony/expression-language": "~2.8|~3.0|~4.0.0", - "symfony/finder": "~2.8|~3.0|~4.0.0", - "symfony/process": "~2.8|~3.0|~4.0.0", - "symfony/routing": "~2.8|~3.0|~4.0.0", - "symfony/stopwatch": "~2.8|~3.0|~4.0.0", - "symfony/templating": "~2.8|~3.0|~4.0.0", - "symfony/translation": "~2.8|~3.0|~4.0.0", - "symfony/var-dumper": "~3.3|~4.0.0", + "symfony/config": "~2.8|~3.0|~4.0", + "symfony/console": "~2.8|~3.0|~4.0", + "symfony/css-selector": "~2.8|~3.0|~4.0", + "symfony/dependency-injection": "~3.3|~4.0", + "symfony/dom-crawler": "~2.8|~3.0|~4.0", + "symfony/expression-language": "~2.8|~3.0|~4.0", + "symfony/finder": "~2.8|~3.0|~4.0", + "symfony/process": "~2.8|~3.0|~4.0", + "symfony/routing": "~2.8|~3.0|~4.0", + "symfony/stopwatch": "~2.8|~3.0|~4.0", + "symfony/templating": "~2.8|~3.0|~4.0", + "symfony/translation": "~2.8|~3.0|~4.0", + "symfony/var-dumper": "~3.3|~4.0", "psr/cache": "~1.0" }, "conflict": { diff --git a/src/Symfony/Component/Intl/composer.json b/src/Symfony/Component/Intl/composer.json index 9bc914765c240..477eea64bea84 100644 --- a/src/Symfony/Component/Intl/composer.json +++ b/src/Symfony/Component/Intl/composer.json @@ -28,7 +28,7 @@ "symfony/polyfill-intl-icu": "~1.0" }, "require-dev": { - "symfony/filesystem": "~2.8|~3.0|~4.0.0" + "symfony/filesystem": "~2.8|~3.0|~4.0" }, "suggest": { "ext-intl": "to use the component with locales other than \"en\"" diff --git a/src/Symfony/Component/Ldap/composer.json b/src/Symfony/Component/Ldap/composer.json index 886cb502a0dd6..b6fd70cafdcd5 100644 --- a/src/Symfony/Component/Ldap/composer.json +++ b/src/Symfony/Component/Ldap/composer.json @@ -18,7 +18,7 @@ "require": { "php": ">=5.5.9", "symfony/polyfill-php56": "~1.0", - "symfony/options-resolver": "~2.8|~3.0|~4.0.0", + "symfony/options-resolver": "~2.8|~3.0|~4.0", "ext-ldap": "*" }, "autoload": { diff --git a/src/Symfony/Component/PropertyAccess/composer.json b/src/Symfony/Component/PropertyAccess/composer.json index b2dbedb1af9ac..127bd19d8aa7c 100644 --- a/src/Symfony/Component/PropertyAccess/composer.json +++ b/src/Symfony/Component/PropertyAccess/composer.json @@ -18,10 +18,10 @@ "require": { "php": ">=5.5.9", "symfony/polyfill-php70": "~1.0", - "symfony/inflector": "~3.1|~4.0.0" + "symfony/inflector": "~3.1|~4.0" }, "require-dev": { - "symfony/cache": "~3.1|~4.0.0" + "symfony/cache": "~3.1|~4.0" }, "suggest": { "psr/cache-implementation": "To cache access methods." diff --git a/src/Symfony/Component/PropertyInfo/composer.json b/src/Symfony/Component/PropertyInfo/composer.json index 508b308daebf5..8a0eab08164a1 100644 --- a/src/Symfony/Component/PropertyInfo/composer.json +++ b/src/Symfony/Component/PropertyInfo/composer.json @@ -24,12 +24,12 @@ ], "require": { "php": ">=5.5.9", - "symfony/inflector": "~3.1|~4.0.0" + "symfony/inflector": "~3.1|~4.0" }, "require-dev": { - "symfony/serializer": "~2.8|~3.0|~4.0.0", - "symfony/cache": "~3.1|~4.0.0", - "symfony/dependency-injection": "~3.3|~4.0.0", + "symfony/serializer": "~2.8|~3.0|~4.0", + "symfony/cache": "~3.1|~4.0", + "symfony/dependency-injection": "~3.3|~4.0", "phpdocumentor/reflection-docblock": "^3.0", "doctrine/annotations": "~1.0" }, diff --git a/src/Symfony/Component/Routing/composer.json b/src/Symfony/Component/Routing/composer.json index a9f192cd120a0..d09aff593287b 100644 --- a/src/Symfony/Component/Routing/composer.json +++ b/src/Symfony/Component/Routing/composer.json @@ -19,11 +19,11 @@ "php": ">=5.5.9" }, "require-dev": { - "symfony/config": "~2.8|~3.0|~4.0.0", - "symfony/http-foundation": "~2.8|~3.0|~4.0.0", - "symfony/yaml": "~3.3|~4.0.0", - "symfony/expression-language": "~2.8|~3.0|~4.0.0", - "symfony/dependency-injection": "~3.3|~4.0.0", + "symfony/config": "~2.8|~3.0|~4.0", + "symfony/http-foundation": "~2.8|~3.0|~4.0", + "symfony/yaml": "~3.3|~4.0", + "symfony/expression-language": "~2.8|~3.0|~4.0", + "symfony/dependency-injection": "~3.3|~4.0", "doctrine/annotations": "~1.0", "doctrine/common": "~2.2", "psr/log": "~1.0" diff --git a/src/Symfony/Component/Security/Core/composer.json b/src/Symfony/Component/Security/Core/composer.json index 1fa423cd4479e..c9864c5b87d52 100644 --- a/src/Symfony/Component/Security/Core/composer.json +++ b/src/Symfony/Component/Security/Core/composer.json @@ -20,11 +20,11 @@ "symfony/polyfill-php56": "~1.0" }, "require-dev": { - "symfony/event-dispatcher": "~2.8|~3.0|~4.0.0", - "symfony/expression-language": "~2.8|~3.0|~4.0.0", - "symfony/http-foundation": "~2.8|~3.0|~4.0.0", - "symfony/ldap": "~3.1|~4.0.0", - "symfony/validator": "^3.2.5|~4.0.0", + "symfony/event-dispatcher": "~2.8|~3.0|~4.0", + "symfony/expression-language": "~2.8|~3.0|~4.0", + "symfony/http-foundation": "~2.8|~3.0|~4.0", + "symfony/ldap": "~3.1|~4.0", + "symfony/validator": "^3.2.5|~4.0", "psr/log": "~1.0" }, "suggest": { diff --git a/src/Symfony/Component/Security/Csrf/composer.json b/src/Symfony/Component/Security/Csrf/composer.json index f23354377dbd8..4cdf3181744b9 100644 --- a/src/Symfony/Component/Security/Csrf/composer.json +++ b/src/Symfony/Component/Security/Csrf/composer.json @@ -19,10 +19,10 @@ "php": ">=5.5.9", "symfony/polyfill-php56": "~1.0", "symfony/polyfill-php70": "~1.0", - "symfony/security-core": "~2.8|~3.0|~4.0.0" + "symfony/security-core": "~2.8|~3.0|~4.0" }, "require-dev": { - "symfony/http-foundation": "~2.8|~3.0|~4.0.0" + "symfony/http-foundation": "~2.8|~3.0|~4.0" }, "suggest": { "symfony/http-foundation": "For using the class SessionTokenStorage." diff --git a/src/Symfony/Component/Security/Guard/composer.json b/src/Symfony/Component/Security/Guard/composer.json index 07d29f4df50f5..a44bd86d6c008 100644 --- a/src/Symfony/Component/Security/Guard/composer.json +++ b/src/Symfony/Component/Security/Guard/composer.json @@ -17,8 +17,8 @@ ], "require": { "php": ">=5.5.9", - "symfony/security-core": "~2.8|~3.0|~4.0.0", - "symfony/security-http": "~3.1|~4.0.0" + "symfony/security-core": "~2.8|~3.0|~4.0", + "symfony/security-http": "~3.1|~4.0" }, "require-dev": { "psr/log": "~1.0" diff --git a/src/Symfony/Component/Security/Http/composer.json b/src/Symfony/Component/Security/Http/composer.json index fc9aeec1d4d62..357ccc00f4927 100644 --- a/src/Symfony/Component/Security/Http/composer.json +++ b/src/Symfony/Component/Security/Http/composer.json @@ -17,17 +17,17 @@ ], "require": { "php": ">=5.5.9", - "symfony/security-core": "~3.2|~4.0.0", - "symfony/event-dispatcher": "~2.8|~3.0|~4.0.0", - "symfony/http-foundation": "~2.8|~3.0|~4.0.0", - "symfony/http-kernel": "~3.3|~4.0.0", + "symfony/security-core": "~3.2|~4.0", + "symfony/event-dispatcher": "~2.8|~3.0|~4.0", + "symfony/http-foundation": "~2.8|~3.0|~4.0", + "symfony/http-kernel": "~3.3|~4.0", "symfony/polyfill-php56": "~1.0", "symfony/polyfill-php70": "~1.0", - "symfony/property-access": "~2.8|~3.0|~4.0.0" + "symfony/property-access": "~2.8|~3.0|~4.0" }, "require-dev": { - "symfony/routing": "~2.8|~3.0|~4.0.0", - "symfony/security-csrf": "~2.8|~3.0|~4.0.0", + "symfony/routing": "~2.8|~3.0|~4.0", + "symfony/security-csrf": "~2.8|~3.0|~4.0", "psr/log": "~1.0" }, "suggest": { diff --git a/src/Symfony/Component/Security/composer.json b/src/Symfony/Component/Security/composer.json index 2d7c69b985b86..65c731b678ec9 100644 --- a/src/Symfony/Component/Security/composer.json +++ b/src/Symfony/Component/Security/composer.json @@ -17,13 +17,13 @@ ], "require": { "php": ">=5.5.9", - "symfony/event-dispatcher": "~2.8|~3.0|~4.0.0", - "symfony/http-foundation": "~2.8|~3.0|~4.0.0", - "symfony/http-kernel": "~3.3|~4.0.0", + "symfony/event-dispatcher": "~2.8|~3.0|~4.0", + "symfony/http-foundation": "~2.8|~3.0|~4.0", + "symfony/http-kernel": "~3.3|~4.0", "symfony/polyfill-php56": "~1.0", "symfony/polyfill-php70": "~1.0", "symfony/polyfill-util": "~1.0", - "symfony/property-access": "~2.8|~3.0|~4.0.0" + "symfony/property-access": "~2.8|~3.0|~4.0" }, "replace": { "symfony/security-core": "self.version", @@ -32,12 +32,12 @@ "symfony/security-http": "self.version" }, "require-dev": { - "symfony/finder": "~2.8|~3.0|~4.0.0", + "symfony/finder": "~2.8|~3.0|~4.0", "symfony/polyfill-intl-icu": "~1.0", - "symfony/routing": "~2.8|~3.0|~4.0.0", - "symfony/validator": "^3.2.5|~4.0.0", - "symfony/expression-language": "~2.8|~3.0|~4.0.0", - "symfony/ldap": "~3.1|~4.0.0", + "symfony/routing": "~2.8|~3.0|~4.0", + "symfony/validator": "^3.2.5|~4.0", + "symfony/expression-language": "~2.8|~3.0|~4.0", + "symfony/ldap": "~3.1|~4.0", "psr/log": "~1.0" }, "suggest": { diff --git a/src/Symfony/Component/Serializer/composer.json b/src/Symfony/Component/Serializer/composer.json index fac63187e1344..3219ac0805483 100644 --- a/src/Symfony/Component/Serializer/composer.json +++ b/src/Symfony/Component/Serializer/composer.json @@ -19,14 +19,14 @@ "php": ">=5.5.9" }, "require-dev": { - "symfony/yaml": "~3.3|~4.0.0", - "symfony/config": "~2.8|~3.0|~4.0.0", - "symfony/property-access": "~2.8|~3.0|~4.0.0", - "symfony/http-foundation": "~2.8|~3.0|~4.0.0", - "symfony/cache": "~3.1|~4.0.0", - "symfony/property-info": "~3.1|~4.0.0", + "symfony/yaml": "~3.3|~4.0", + "symfony/config": "~2.8|~3.0|~4.0", + "symfony/property-access": "~2.8|~3.0|~4.0", + "symfony/http-foundation": "~2.8|~3.0|~4.0", + "symfony/cache": "~3.1|~4.0", + "symfony/property-info": "~3.1|~4.0", "doctrine/annotations": "~1.0", - "symfony/dependency-injection": "~3.2|~4.0.0", + "symfony/dependency-injection": "~3.2|~4.0", "doctrine/cache": "~1.0", "phpdocumentor/reflection-docblock": "~3.0" }, diff --git a/src/Symfony/Component/Translation/composer.json b/src/Symfony/Component/Translation/composer.json index 966c41f23af39..4b4897e8e340e 100644 --- a/src/Symfony/Component/Translation/composer.json +++ b/src/Symfony/Component/Translation/composer.json @@ -20,9 +20,9 @@ "symfony/polyfill-mbstring": "~1.0" }, "require-dev": { - "symfony/config": "~2.8|~3.0|~4.0.0", - "symfony/intl": "^2.8.18|^3.2.5|~4.0.0", - "symfony/yaml": "~3.3|~4.0.0", + "symfony/config": "~2.8|~3.0|~4.0", + "symfony/intl": "^2.8.18|^3.2.5|~4.0", + "symfony/yaml": "~3.3|~4.0", "psr/log": "~1.0" }, "conflict": { diff --git a/src/Symfony/Component/Validator/composer.json b/src/Symfony/Component/Validator/composer.json index ff44ba9126f60..21c0a8a7cd022 100644 --- a/src/Symfony/Component/Validator/composer.json +++ b/src/Symfony/Component/Validator/composer.json @@ -18,16 +18,16 @@ "require": { "php": ">=5.5.9", "symfony/polyfill-mbstring": "~1.0", - "symfony/translation": "~2.8|~3.0|~4.0.0" + "symfony/translation": "~2.8|~3.0|~4.0" }, "require-dev": { - "symfony/http-foundation": "~2.8|~3.0|~4.0.0", - "symfony/intl": "^2.8.18|^3.2.5|~4.0.0", - "symfony/yaml": "~3.3|~4.0.0", - "symfony/config": "~2.8|~3.0|~4.0.0", - "symfony/dependency-injection": "~3.3|~4.0.0", - "symfony/expression-language": "~2.8|~3.0|~4.0.0", - "symfony/cache": "~3.1|~4.0.0", + "symfony/http-foundation": "~2.8|~3.0|~4.0", + "symfony/intl": "^2.8.18|^3.2.5|~4.0", + "symfony/yaml": "~3.3|~4.0", + "symfony/config": "~2.8|~3.0|~4.0", + "symfony/dependency-injection": "~3.3|~4.0", + "symfony/expression-language": "~2.8|~3.0|~4.0", + "symfony/cache": "~3.1|~4.0", "doctrine/annotations": "~1.0", "doctrine/cache": "~1.0", "egulias/email-validator": "^1.2.8|~2.0" diff --git a/src/Symfony/Component/WebLink/composer.json b/src/Symfony/Component/WebLink/composer.json index 8db660c676e14..4940f3375155f 100644 --- a/src/Symfony/Component/WebLink/composer.json +++ b/src/Symfony/Component/WebLink/composer.json @@ -24,9 +24,9 @@ "symfony/http-kernel": "" }, "require-dev": { - "symfony/event-dispatcher": "^2.8|^3.0|~4.0.0", - "symfony/http-foundation": "^2.8|^3.0|~4.0.0", - "symfony/http-kernel": "^2.8|^3.0|~4.0.0" + "symfony/event-dispatcher": "^2.8|^3.0|~4.0", + "symfony/http-foundation": "^2.8|^3.0|~4.0", + "symfony/http-kernel": "^2.8|^3.0|~4.0" }, "autoload": { "psr-4": { "Symfony\\Component\\WebLink\\": "" }, diff --git a/src/Symfony/Component/Workflow/composer.json b/src/Symfony/Component/Workflow/composer.json index 918bda4b99801..8a111dbd674ea 100644 --- a/src/Symfony/Component/Workflow/composer.json +++ b/src/Symfony/Component/Workflow/composer.json @@ -21,14 +21,14 @@ ], "require": { "php": ">=5.5.9", - "symfony/property-access": "~2.3|~3.0|~4.0.0" + "symfony/property-access": "~2.3|~3.0|~4.0" }, "require-dev": { "psr/log": "~1.0", - "symfony/dependency-injection": "~2.8|~3.0|~4.0.0", - "symfony/event-dispatcher": "~2.1|~3.0|~4.0.0", - "symfony/expression-language": "~2.8|~3.0|~4.0.0", - "symfony/security-core": "~2.8|~3.0|~4.0.0" + "symfony/dependency-injection": "~2.8|~3.0|~4.0", + "symfony/event-dispatcher": "~2.1|~3.0|~4.0", + "symfony/expression-language": "~2.8|~3.0|~4.0", + "symfony/security-core": "~2.8|~3.0|~4.0" }, "autoload": { "psr-4": { "Symfony\\Component\\Workflow\\": "" } diff --git a/src/Symfony/Component/Yaml/composer.json b/src/Symfony/Component/Yaml/composer.json index 8c218ac9ac35c..d05cb7fb4dba8 100644 --- a/src/Symfony/Component/Yaml/composer.json +++ b/src/Symfony/Component/Yaml/composer.json @@ -19,7 +19,7 @@ "php": ">=5.5.9" }, "require-dev": { - "symfony/console": "~2.8|~3.0|~4.0.0" + "symfony/console": "~2.8|~3.0|~4.0" }, "suggest": { "symfony/console": "For validating YAML files using the lint command" From 4d522d338aa2fd8250208265fa644bd69b07fdca Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Tue, 23 May 2017 00:37:58 +0200 Subject: [PATCH 0062/1099] [HttpKernel] remove deprecated features --- src/Symfony/Component/HttpKernel/CHANGELOG.md | 10 +- .../DataCollector/DataCollector.php | 42 +------- .../DataCollector/Util/ValueExporter.php | 99 ------------------- .../AbstractSurrogateFragmentRenderer.php | 2 +- .../Component/HttpKernel/HttpKernel.php | 8 +- src/Symfony/Component/HttpKernel/Kernel.php | 53 +++------- .../DataCollector/Util/ValueExporterTest.php | 51 ---------- .../Fragment/EsiFragmentRendererTest.php | 12 --- .../Fragment/InlineFragmentRendererTest.php | 23 ----- .../HttpKernel/Tests/HttpKernelTest.php | 18 ---- .../Component/HttpKernel/Tests/KernelTest.php | 19 ---- 11 files changed, 27 insertions(+), 310 deletions(-) delete mode 100644 src/Symfony/Component/HttpKernel/DataCollector/Util/ValueExporter.php delete mode 100644 src/Symfony/Component/HttpKernel/Tests/DataCollector/Util/ValueExporterTest.php diff --git a/src/Symfony/Component/HttpKernel/CHANGELOG.md b/src/Symfony/Component/HttpKernel/CHANGELOG.md index 9419d84b18e08..0a8d37f45380b 100644 --- a/src/Symfony/Component/HttpKernel/CHANGELOG.md +++ b/src/Symfony/Component/HttpKernel/CHANGELOG.md @@ -4,6 +4,10 @@ CHANGELOG 4.0.0 ----- + * removed the `DataCollector::varToString()` method, use `DataCollector::cloneVar()` + instead + * using the `DataCollector::cloneVar()` method requires the VarDumper component + * removed the `ValueExporter` class * removed `ControllerResolverInterface::getArguments()` * removed `TraceableControllerResolver::getArguments()` * removed `ControllerResolver::getArguments()` and the ability to resolve arguments @@ -11,7 +15,11 @@ CHANGELOG * removed `LazyLoadingFragmentHandler::addRendererService()` * removed `Psr6CacheClearer::addPool()` * removed `Extension::addClassesToCompile()` and `Extension::getClassesToCompile()` - * removed `Kernel::loadClassCache()`, `Kernel::doLoadClassCache()` and `Kernel::setClassCache()` + * removed `Kernel::loadClassCache()`, `Kernel::doLoadClassCache()`, `Kernel::setClassCache()`, + and `Kernel::getEnvParameters()` + * support for the `X-Status-Code` when handling exceptions in the `HttpKernel` + has been dropped, use the `HttpKernel::allowCustomResponseCode()` method + instead 3.3.0 ----- diff --git a/src/Symfony/Component/HttpKernel/DataCollector/DataCollector.php b/src/Symfony/Component/HttpKernel/DataCollector/DataCollector.php index 0d574eae3b3af..77c72f9562e75 100644 --- a/src/Symfony/Component/HttpKernel/DataCollector/DataCollector.php +++ b/src/Symfony/Component/HttpKernel/DataCollector/DataCollector.php @@ -11,7 +11,6 @@ namespace Symfony\Component\HttpKernel\DataCollector; -use Symfony\Component\HttpKernel\DataCollector\Util\ValueExporter; use Symfony\Component\VarDumper\Caster\ClassStub; use Symfony\Component\VarDumper\Cloner\ClonerInterface; use Symfony\Component\VarDumper\Cloner\Data; @@ -29,11 +28,6 @@ abstract class DataCollector implements DataCollectorInterface, \Serializable { protected $data = array(); - /** - * @var ValueExporter - */ - private $valueExporter; - /** * @var ClonerInterface */ @@ -62,42 +56,14 @@ public function unserialize($data) protected function cloneVar($var) { if (null === self::$cloner) { - if (class_exists(ClassStub::class)) { - self::$cloner = new VarCloner(); - self::$cloner->setMaxItems(-1); - } else { - @trigger_error(sprintf('Using the %s() method without the VarDumper component is deprecated since version 3.2 and won\'t be supported in 4.0. Install symfony/var-dumper version 3.2 or above.', __METHOD__), E_USER_DEPRECATED); - self::$cloner = false; - } - } - if (false === self::$cloner) { - if (null === $this->valueExporter) { - $this->valueExporter = new ValueExporter(); + if (!class_exists(ClassStub::class)) { + throw new \LogicException(sprintf('The VarDumper component is needed for the %s() method. Install symfony/var-dumper version 3.2 or above.', __METHOD__)); } - return $this->valueExporter->exportValue($var); + self::$cloner = new VarCloner(); + self::$cloner->setMaxItems(-1); } return self::$cloner->cloneVar($var); } - - /** - * Converts a PHP variable to a string. - * - * @param mixed $var A PHP variable - * - * @return string The string representation of the variable - * - * @deprecated since version 3.2, to be removed in 4.0. Use cloneVar() instead. - */ - protected function varToString($var) - { - @trigger_error(sprintf('The %s() method is deprecated since version 3.2 and will be removed in 4.0. Use cloneVar() instead.', __METHOD__), E_USER_DEPRECATED); - - if (null === $this->valueExporter) { - $this->valueExporter = new ValueExporter(); - } - - return $this->valueExporter->exportValue($var); - } } diff --git a/src/Symfony/Component/HttpKernel/DataCollector/Util/ValueExporter.php b/src/Symfony/Component/HttpKernel/DataCollector/Util/ValueExporter.php deleted file mode 100644 index f1e48311c0429..0000000000000 --- a/src/Symfony/Component/HttpKernel/DataCollector/Util/ValueExporter.php +++ /dev/null @@ -1,99 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\DataCollector\Util; - -@trigger_error('The '.__NAMESPACE__.'\ValueExporter class is deprecated since version 3.2 and will be removed in 4.0. Use the VarDumper component instead.', E_USER_DEPRECATED); - -/** - * @author Bernhard Schussek - * - * @deprecated since version 3.2, to be removed in 4.0. Use the VarDumper component instead. - */ -class ValueExporter -{ - /** - * Converts a PHP value to a string. - * - * @param mixed $value The PHP value - * @param int $depth only for internal usage - * @param bool $deep only for internal usage - * - * @return string The string representation of the given value - */ - public function exportValue($value, $depth = 1, $deep = false) - { - if ($value instanceof \__PHP_Incomplete_Class) { - return sprintf('__PHP_Incomplete_Class(%s)', $this->getClassNameFromIncomplete($value)); - } - - if (is_object($value)) { - if ($value instanceof \DateTimeInterface) { - return sprintf('Object(%s) - %s', get_class($value), $value->format(\DateTime::ATOM)); - } - - return sprintf('Object(%s)', get_class($value)); - } - - if (is_array($value)) { - if (empty($value)) { - return '[]'; - } - - $indent = str_repeat(' ', $depth); - - $a = array(); - foreach ($value as $k => $v) { - if (is_array($v)) { - $deep = true; - } - $a[] = sprintf('%s => %s', $k, $this->exportValue($v, $depth + 1, $deep)); - } - - if ($deep) { - return sprintf("[\n%s%s\n%s]", $indent, implode(sprintf(", \n%s", $indent), $a), str_repeat(' ', $depth - 1)); - } - - $s = sprintf('[%s]', implode(', ', $a)); - - if (80 > strlen($s)) { - return $s; - } - - return sprintf("[\n%s%s\n]", $indent, implode(sprintf(",\n%s", $indent), $a)); - } - - if (is_resource($value)) { - return sprintf('Resource(%s#%d)', get_resource_type($value), $value); - } - - if (null === $value) { - return 'null'; - } - - if (false === $value) { - return 'false'; - } - - if (true === $value) { - return 'true'; - } - - return (string) $value; - } - - private function getClassNameFromIncomplete(\__PHP_Incomplete_Class $value) - { - $array = new \ArrayObject($value); - - return $array['__PHP_Incomplete_Class_Name']; - } -} diff --git a/src/Symfony/Component/HttpKernel/Fragment/AbstractSurrogateFragmentRenderer.php b/src/Symfony/Component/HttpKernel/Fragment/AbstractSurrogateFragmentRenderer.php index 0d4d26b6765c6..07ab304e93ef1 100644 --- a/src/Symfony/Component/HttpKernel/Fragment/AbstractSurrogateFragmentRenderer.php +++ b/src/Symfony/Component/HttpKernel/Fragment/AbstractSurrogateFragmentRenderer.php @@ -65,7 +65,7 @@ public function render($uri, Request $request, array $options = array()) { if (!$this->surrogate || !$this->surrogate->hasSurrogateCapability($request)) { if ($uri instanceof ControllerReference && $this->containsNonScalars($uri->attributes)) { - @trigger_error('Passing non-scalar values as part of URI attributes to the ESI and SSI rendering strategies is deprecated since version 3.1, and will be removed in 4.0. Use a different rendering strategy or pass scalar values.', E_USER_DEPRECATED); + throw new \InvalidArgumentException('Passing non-scalar values as part of URI attributes to the ESI and SSI rendering strategies is not supported. Use a different rendering strategy or pass scalar values.'); } return $this->inlineStrategy->render($uri, $request, $options); diff --git a/src/Symfony/Component/HttpKernel/HttpKernel.php b/src/Symfony/Component/HttpKernel/HttpKernel.php index 228ddb7fea795..4a35a9990b761 100644 --- a/src/Symfony/Component/HttpKernel/HttpKernel.php +++ b/src/Symfony/Component/HttpKernel/HttpKernel.php @@ -239,13 +239,7 @@ private function handleException(\Exception $e, $request, $type) $response = $event->getResponse(); // the developer asked for a specific status code - if ($response->headers->has('X-Status-Code')) { - @trigger_error(sprintf('Using the X-Status-Code header is deprecated since version 3.3 and will be removed in 4.0. Use %s::allowCustomResponseCode() instead.', GetResponseForExceptionEvent::class), E_USER_DEPRECATED); - - $response->setStatusCode($response->headers->get('X-Status-Code')); - - $response->headers->remove('X-Status-Code'); - } elseif (!$event->isAllowingCustomResponseCode() && !$response->isClientError() && !$response->isServerError() && !$response->isRedirect()) { + if (!$event->isAllowingCustomResponseCode() && !$response->isClientError() && !$response->isServerError() && !$response->isRedirect()) { // ensure that we actually have an error response if ($e instanceof HttpExceptionInterface) { // keep the HTTP status code and headers diff --git a/src/Symfony/Component/HttpKernel/Kernel.php b/src/Symfony/Component/HttpKernel/Kernel.php index 2c6e3250f7935..76c153363a177 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -544,50 +544,21 @@ protected function getKernelParameters() ); } - return array_merge( - array( - 'kernel.root_dir' => realpath($this->rootDir) ?: $this->rootDir, - 'kernel.project_dir' => realpath($this->projectDir) ?: $this->projectDir, - 'kernel.environment' => $this->environment, - 'kernel.debug' => $this->debug, - 'kernel.name' => $this->name, - 'kernel.cache_dir' => realpath($this->getCacheDir()) ?: $this->getCacheDir(), - 'kernel.logs_dir' => realpath($this->getLogDir()) ?: $this->getLogDir(), - 'kernel.bundles' => $bundles, - 'kernel.bundles_metadata' => $bundlesMetadata, - 'kernel.charset' => $this->getCharset(), - 'kernel.container_class' => $this->getContainerClass(), - ), - $this->getEnvParameters(false) + return array( + 'kernel.root_dir' => realpath($this->rootDir) ?: $this->rootDir, + 'kernel.project_dir' => realpath($this->projectDir) ?: $this->projectDir, + 'kernel.environment' => $this->environment, + 'kernel.debug' => $this->debug, + 'kernel.name' => $this->name, + 'kernel.cache_dir' => realpath($this->getCacheDir()) ?: $this->getCacheDir(), + 'kernel.logs_dir' => realpath($this->getLogDir()) ?: $this->getLogDir(), + 'kernel.bundles' => $bundles, + 'kernel.bundles_metadata' => $bundlesMetadata, + 'kernel.charset' => $this->getCharset(), + 'kernel.container_class' => $this->getContainerClass(), ); } - /** - * Gets the environment parameters. - * - * Only the parameters starting with "SYMFONY__" are considered. - * - * @return array An array of parameters - * - * @deprecated since version 3.3, to be removed in 4.0 - */ - protected function getEnvParameters() - { - if (0 === func_num_args() || func_get_arg(0)) { - @trigger_error(sprintf('The %s() method is deprecated as of 3.3 and will be removed in 4.0. Use the %%env()%% syntax to get the value of any environment variable from configuration files instead.', __METHOD__), E_USER_DEPRECATED); - } - - $parameters = array(); - foreach ($_SERVER as $key => $value) { - if (0 === strpos($key, 'SYMFONY__')) { - @trigger_error(sprintf('The support of special environment variables that start with SYMFONY__ (such as "%s") is deprecated as of 3.3 and will be removed in 4.0. Use the %%env()%% syntax instead to get the value of environment variables in configuration files.', $key), E_USER_DEPRECATED); - $parameters[strtolower(str_replace('__', '.', substr($key, 9)))] = $value; - } - } - - return $parameters; - } - /** * Builds the service container. * diff --git a/src/Symfony/Component/HttpKernel/Tests/DataCollector/Util/ValueExporterTest.php b/src/Symfony/Component/HttpKernel/Tests/DataCollector/Util/ValueExporterTest.php deleted file mode 100644 index 5fe92d60e0491..0000000000000 --- a/src/Symfony/Component/HttpKernel/Tests/DataCollector/Util/ValueExporterTest.php +++ /dev/null @@ -1,51 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\Tests\DataCollector\Util; - -use PHPUnit\Framework\TestCase; -use Symfony\Component\HttpKernel\DataCollector\Util\ValueExporter; - -/** - * @group legacy - */ -class ValueExporterTest extends TestCase -{ - /** - * @var ValueExporter - */ - private $valueExporter; - - protected function setUp() - { - $this->valueExporter = new ValueExporter(); - } - - public function testDateTime() - { - $dateTime = new \DateTime('2014-06-10 07:35:40', new \DateTimeZone('UTC')); - $this->assertSame('Object(DateTime) - 2014-06-10T07:35:40+00:00', $this->valueExporter->exportValue($dateTime)); - } - - public function testDateTimeImmutable() - { - $dateTime = new \DateTimeImmutable('2014-06-10 07:35:40', new \DateTimeZone('UTC')); - $this->assertSame('Object(DateTimeImmutable) - 2014-06-10T07:35:40+00:00', $this->valueExporter->exportValue($dateTime)); - } - - public function testIncompleteClass() - { - $foo = new \__PHP_Incomplete_Class(); - $array = new \ArrayObject($foo); - $array['__PHP_Incomplete_Class_Name'] = 'AppBundle/Foo'; - $this->assertSame('__PHP_Incomplete_Class(AppBundle/Foo)', $this->valueExporter->exportValue($foo)); - } -} diff --git a/src/Symfony/Component/HttpKernel/Tests/Fragment/EsiFragmentRendererTest.php b/src/Symfony/Component/HttpKernel/Tests/Fragment/EsiFragmentRendererTest.php index bfe922e22c76b..6cefea6b02f3b 100644 --- a/src/Symfony/Component/HttpKernel/Tests/Fragment/EsiFragmentRendererTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/Fragment/EsiFragmentRendererTest.php @@ -26,18 +26,6 @@ public function testRenderFallbackToInlineStrategyIfEsiNotSupported() $strategy->render('/', Request::create('/')); } - /** - * @group legacy - * @expectedDeprecation Passing non-scalar values as part of URI attributes to the ESI and SSI rendering strategies is deprecated %s. - */ - public function testRenderFallbackWithObjectAttributesIsDeprecated() - { - $strategy = new EsiFragmentRenderer(new Esi(), $this->getInlineStrategy(true), new UriSigner('foo')); - $request = Request::create('/'); - $reference = new ControllerReference('main_controller', array('foo' => array('a' => array(), 'b' => new \stdClass())), array()); - $strategy->render($reference, $request); - } - public function testRender() { $strategy = new EsiFragmentRenderer(new Esi(), $this->getInlineStrategy()); diff --git a/src/Symfony/Component/HttpKernel/Tests/Fragment/InlineFragmentRendererTest.php b/src/Symfony/Component/HttpKernel/Tests/Fragment/InlineFragmentRendererTest.php index ee556fa6e5ba6..844b53b9a1f06 100644 --- a/src/Symfony/Component/HttpKernel/Tests/Fragment/InlineFragmentRendererTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/Fragment/InlineFragmentRendererTest.php @@ -13,8 +13,6 @@ use PHPUnit\Framework\TestCase; use Symfony\Component\HttpFoundation\RequestStack; -use Symfony\Component\HttpKernel\Controller\ArgumentResolver; -use Symfony\Component\HttpKernel\Controller\ControllerResolverInterface; use Symfony\Component\HttpKernel\Controller\ControllerReference; use Symfony\Component\HttpKernel\HttpKernel; use Symfony\Component\HttpKernel\Fragment\InlineFragmentRenderer; @@ -53,27 +51,6 @@ public function testRenderWithObjectsAsAttributes() $this->assertSame('foo', $strategy->render(new ControllerReference('main_controller', array('object' => $object), array()), Request::create('/'))->getContent()); } - /** - * @group legacy - */ - public function testRenderWithObjectsAsAttributesPassedAsObjectsInTheController() - { - $resolver = $this->getMockBuilder(ControllerResolverInterface::class)->getMock(); - $resolver - ->expects($this->once()) - ->method('getController') - ->will($this->returnValue(function (\stdClass $object, Bar $object1) { - return new Response($object1->getBar()); - })) - ; - - $kernel = new HttpKernel(new EventDispatcher(), $resolver, new RequestStack(), new ArgumentResolver()); - $renderer = new InlineFragmentRenderer($kernel); - - $response = $renderer->render(new ControllerReference('main_controller', array('object' => new \stdClass(), 'object1' => new Bar()), array()), Request::create('/')); - $this->assertEquals('bar', $response->getContent()); - } - public function testRenderWithTrustedHeaderDisabled() { Request::setTrustedProxies(array(), 0); diff --git a/src/Symfony/Component/HttpKernel/Tests/HttpKernelTest.php b/src/Symfony/Component/HttpKernel/Tests/HttpKernelTest.php index 7aed26aa59c9c..0adef984c6f5c 100644 --- a/src/Symfony/Component/HttpKernel/Tests/HttpKernelTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/HttpKernelTest.php @@ -111,24 +111,6 @@ public function testHandleHttpException() $this->assertEquals('POST', $response->headers->get('Allow')); } - /** - * @group legacy - * @dataProvider getStatusCodes - */ - public function testLegacyHandleWhenAnExceptionIsHandledWithASpecificStatusCode($responseStatusCode, $expectedStatusCode) - { - $dispatcher = new EventDispatcher(); - $dispatcher->addListener(KernelEvents::EXCEPTION, function ($event) use ($responseStatusCode, $expectedStatusCode) { - $event->setResponse(new Response('', $responseStatusCode, array('X-Status-Code' => $expectedStatusCode))); - }); - - $kernel = $this->getHttpKernel($dispatcher, function () { throw new \RuntimeException(); }); - $response = $kernel->handle(new Request()); - - $this->assertEquals($expectedStatusCode, $response->getStatusCode()); - $this->assertFalse($response->headers->has('X-Status-Code')); - } - public function getStatusCodes() { return array( diff --git a/src/Symfony/Component/HttpKernel/Tests/KernelTest.php b/src/Symfony/Component/HttpKernel/Tests/KernelTest.php index 32166687ed2ea..94a483ff16e34 100644 --- a/src/Symfony/Component/HttpKernel/Tests/KernelTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/KernelTest.php @@ -717,25 +717,6 @@ public function testKernelRootDirNameStartingWithANumber() $this->assertEquals('_123', $kernel->getName()); } - /** - * @group legacy - * @expectedDeprecation The Symfony\Component\HttpKernel\Kernel::getEnvParameters() method is deprecated as of 3.3 and will be removed in 4.0. Use the %cenv()%c syntax to get the value of any environment variable from configuration files instead. - * @expectedDeprecation The support of special environment variables that start with SYMFONY__ (such as "SYMFONY__FOO__BAR") is deprecated as of 3.3 and will be removed in 4.0. Use the %cenv()%c syntax instead to get the value of environment variables in configuration files. - */ - public function testSymfonyEnvironmentVariables() - { - $_SERVER['SYMFONY__FOO__BAR'] = 'baz'; - - $kernel = $this->getKernel(); - $method = new \ReflectionMethod($kernel, 'getEnvParameters'); - $method->setAccessible(true); - - $envParameters = $method->invoke($kernel); - $this->assertSame('baz', $envParameters['foo.bar']); - - unset($_SERVER['SYMFONY__FOO__BAR']); - } - /** * Returns a mock for the BundleInterface. * From efe23371dce1157be6a24c6045543b3a23b708a4 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Fri, 19 May 2017 09:52:04 +0200 Subject: [PATCH 0063/1099] [Yaml] remove deprecated features --- src/Symfony/Component/Yaml/CHANGELOG.md | 21 +++ src/Symfony/Component/Yaml/Dumper.php | 30 ---- src/Symfony/Component/Yaml/Inline.php | 117 +++---------- src/Symfony/Component/Yaml/Parser.php | 53 +----- .../Component/Yaml/Tests/DumperTest.php | 66 ------- .../Fixtures/YtsSpecificationExamples.yml | 38 ---- .../Yaml/Tests/Fixtures/YtsTypeTransfers.yml | 42 ----- .../Fixtures/legacyBooleanMappingKeys.yml | 23 --- .../Tests/Fixtures/legacyNonStringKeys.yml | 2 - .../Tests/Fixtures/legacyNullMappingKey.yml | 9 - .../Component/Yaml/Tests/InlineTest.php | 65 ++----- .../Component/Yaml/Tests/ParserTest.php | 162 ++++-------------- src/Symfony/Component/Yaml/Yaml.php | 44 ----- 13 files changed, 89 insertions(+), 583 deletions(-) delete mode 100644 src/Symfony/Component/Yaml/Tests/Fixtures/legacyBooleanMappingKeys.yml delete mode 100644 src/Symfony/Component/Yaml/Tests/Fixtures/legacyNonStringKeys.yml delete mode 100644 src/Symfony/Component/Yaml/Tests/Fixtures/legacyNullMappingKey.yml diff --git a/src/Symfony/Component/Yaml/CHANGELOG.md b/src/Symfony/Component/Yaml/CHANGELOG.md index b44b93892af66..e1c04c1042ea1 100644 --- a/src/Symfony/Component/Yaml/CHANGELOG.md +++ b/src/Symfony/Component/Yaml/CHANGELOG.md @@ -1,6 +1,27 @@ CHANGELOG ========= +4.0.0 +----- + + * complex mappings will throw a `ParseException` + * support for the comma as a group separator for floats has been dropped, use + the underscore instead + * support for the `!!php/object` tag has been dropped, use the `!php/object` + tag instead + * duplicate mapping keys throw a `ParseException` + * non-string mapping keys throw a `ParseException`, use the `Yaml::PARSE_KEYS_AS_STRINGS` + flag to cast them to strings + * `%` at the beginning of an unquoted string throw a `ParseException` + * mappings with a colon (`:`) that is not followed by a whitespace throw a + `ParseException` + * the `Dumper::setIndentation()` method has been removed + * being able to pass boolean options to the `Yaml::parse()`, `Yaml::dump()`, + `Parser::parse()`, and `Dumper::dump()` methods to configure the behavior of + the parser and dumper is no longer supported, pass bitmask flags instead + * the constructor arguments of the `Parser` class have been removed + * the `Inline` class is internal and no longer part of the BC promise + 3.3.0 ----- diff --git a/src/Symfony/Component/Yaml/Dumper.php b/src/Symfony/Component/Yaml/Dumper.php index a38bce014279a..4a6df6a892b15 100644 --- a/src/Symfony/Component/Yaml/Dumper.php +++ b/src/Symfony/Component/Yaml/Dumper.php @@ -37,18 +37,6 @@ public function __construct($indentation = 4) $this->indentation = $indentation; } - /** - * Sets the indentation. - * - * @param int $num The amount of spaces to use for indentation of nested nodes - */ - public function setIndentation($num) - { - @trigger_error('The '.__METHOD__.' method is deprecated since version 3.1 and will be removed in 4.0. Pass the indentation to the constructor instead.', E_USER_DEPRECATED); - - $this->indentation = (int) $num; - } - /** * Dumps a PHP value to YAML. * @@ -61,24 +49,6 @@ public function setIndentation($num) */ public function dump($input, $inline = 0, $indent = 0, $flags = 0) { - if (is_bool($flags)) { - @trigger_error('Passing a boolean flag to toggle exception handling is deprecated since version 3.1 and will be removed in 4.0. Use the Yaml::DUMP_EXCEPTION_ON_INVALID_TYPE flag instead.', E_USER_DEPRECATED); - - if ($flags) { - $flags = Yaml::DUMP_EXCEPTION_ON_INVALID_TYPE; - } else { - $flags = 0; - } - } - - if (func_num_args() >= 5) { - @trigger_error('Passing a boolean flag to toggle object support is deprecated since version 3.1 and will be removed in 4.0. Use the Yaml::DUMP_OBJECT flag instead.', E_USER_DEPRECATED); - - if (func_get_arg(4)) { - $flags |= Yaml::DUMP_OBJECT; - } - } - $output = ''; $prefix = $indent ? str_repeat(' ', $indent) : ''; $dumpObjectAsInlineMap = true; diff --git a/src/Symfony/Component/Yaml/Inline.php b/src/Symfony/Component/Yaml/Inline.php index 1004034486c06..ee2608e6294a9 100644 --- a/src/Symfony/Component/Yaml/Inline.php +++ b/src/Symfony/Component/Yaml/Inline.php @@ -46,38 +46,6 @@ class Inline */ public static function parse($value, $flags = 0, $references = array()) { - if (is_bool($flags)) { - @trigger_error('Passing a boolean flag to toggle exception handling is deprecated since version 3.1 and will be removed in 4.0. Use the Yaml::PARSE_EXCEPTION_ON_INVALID_TYPE flag instead.', E_USER_DEPRECATED); - - if ($flags) { - $flags = Yaml::PARSE_EXCEPTION_ON_INVALID_TYPE; - } else { - $flags = 0; - } - } - - if (func_num_args() >= 3 && !is_array($references)) { - @trigger_error('Passing a boolean flag to toggle object support is deprecated since version 3.1 and will be removed in 4.0. Use the Yaml::PARSE_OBJECT flag instead.', E_USER_DEPRECATED); - - if ($references) { - $flags |= Yaml::PARSE_OBJECT; - } - - if (func_num_args() >= 4) { - @trigger_error('Passing a boolean flag to toggle object for map support is deprecated since version 3.1 and will be removed in 4.0. Use the Yaml::PARSE_OBJECT_FOR_MAP flag instead.', E_USER_DEPRECATED); - - if (func_get_arg(3)) { - $flags |= Yaml::PARSE_OBJECT_FOR_MAP; - } - } - - if (func_num_args() >= 5) { - $references = func_get_arg(4); - } else { - $references = array(); - } - } - self::$exceptionOnInvalidType = (bool) (Yaml::PARSE_EXCEPTION_ON_INVALID_TYPE & $flags); self::$objectSupport = (bool) (Yaml::PARSE_OBJECT & $flags); self::$objectForMap = (bool) (Yaml::PARSE_OBJECT_FOR_MAP & $flags); @@ -137,24 +105,6 @@ public static function parse($value, $flags = 0, $references = array()) */ public static function dump($value, $flags = 0) { - if (is_bool($flags)) { - @trigger_error('Passing a boolean flag to toggle exception handling is deprecated since version 3.1 and will be removed in 4.0. Use the Yaml::DUMP_EXCEPTION_ON_INVALID_TYPE flag instead.', E_USER_DEPRECATED); - - if ($flags) { - $flags = Yaml::DUMP_EXCEPTION_ON_INVALID_TYPE; - } else { - $flags = 0; - } - } - - if (func_num_args() >= 3) { - @trigger_error('Passing a boolean flag to toggle object support is deprecated since version 3.1 and will be removed in 4.0. Use the Yaml::DUMP_OBJECT flag instead.', E_USER_DEPRECATED); - - if (func_get_arg(2)) { - $flags |= Yaml::DUMP_OBJECT; - } - } - switch (true) { case is_resource($value): if (Yaml::DUMP_EXCEPTION_ON_INVALID_TYPE & $flags) { @@ -300,7 +250,7 @@ private static function dumpArray($value, $flags) * * @internal */ - public static function parseScalar($scalar, $flags = 0, $delimiters = null, &$i = 0, $evaluate = true, $references = array(), $legacyOmittedKeySupport = false) + public static function parseScalar($scalar, $flags = 0, $delimiters = null, &$i = 0, $evaluate = true, $references = array()) { if (in_array($scalar[$i], array('"', "'"))) { // quoted scalar @@ -322,7 +272,7 @@ public static function parseScalar($scalar, $flags = 0, $delimiters = null, &$i if (Parser::preg_match('/[ \t]+#/', $output, $match, PREG_OFFSET_CAPTURE)) { $output = substr($output, 0, $match[0][1]); } - } elseif (Parser::preg_match('/^(.'.($legacyOmittedKeySupport ? '+' : '*').'?)('.implode('|', $delimiters).')/', substr($scalar, $i), $match)) { + } elseif (Parser::preg_match('/^(.*?)('.implode('|', $delimiters).')/', substr($scalar, $i), $match)) { $output = $match[1]; $i += strlen($output); } else { @@ -330,14 +280,10 @@ public static function parseScalar($scalar, $flags = 0, $delimiters = null, &$i } // a non-quoted string cannot start with @ or ` (reserved) nor with a scalar indicator (| or >) - if ($output && ('@' === $output[0] || '`' === $output[0] || '|' === $output[0] || '>' === $output[0])) { + if ($output && ('@' === $output[0] || '`' === $output[0] || '|' === $output[0] || '>' === $output[0] || '%' === $output[0])) { throw new ParseException(sprintf('The reserved indicator "%s" cannot start a plain scalar; you need to quote the scalar.', $output[0])); } - if ($output && '%' === $output[0]) { - @trigger_error(sprintf('Not quoting the scalar "%s" starting with the "%%" indicator character is deprecated since Symfony 3.1 and will throw a ParseException in 4.0.', $output), E_USER_DEPRECATED); - } - if ($evaluate) { $output = self::evaluateScalar($output, $flags, $references); } @@ -479,26 +425,27 @@ private static function parseMapping($mapping, $flags, &$i = 0, $references = ar } // key - $key = self::parseScalar($mapping, $flags, array(':', ' '), $i, false, array(), true); + $offsetBeforeKeyParsing = $i; + $key = self::parseScalar($mapping, $flags, array(':', ' '), $i, false, array()); - if (':' !== $key && false === $i = strpos($mapping, ':', $i)) { - break; + if ($offsetBeforeKeyParsing === $i) { + throw new ParseException('Missing mapping key.', self::$parsedLineNumber + 1, $mapping); } - if (':' === $key) { - @trigger_error('Omitting the key of a mapping is deprecated and will throw a ParseException in 4.0.', E_USER_DEPRECATED); + if (false === $i = strpos($mapping, ':', $i)) { + break; } if (!(Yaml::PARSE_KEYS_AS_STRINGS & $flags)) { $evaluatedKey = self::evaluateScalar($key, $flags, $references); if ('' !== $key && $evaluatedKey !== $key && !is_string($evaluatedKey)) { - @trigger_error('Implicit casting of incompatible mapping keys to strings is deprecated since version 3.3 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0. Pass the PARSE_KEYS_AS_STRING flag to explicitly enable the type casts.', E_USER_DEPRECATED); + throw new ParseException('Non-string mapping keys are not supported. Pass the Yaml::PARSE_KEYS_AS_STRINGS flag to cast them to strings.', self::$parsedLineNumber + 1, $mapping); } } - if (':' !== $key && (!isset($mapping[$i + 1]) || !in_array($mapping[$i + 1], array(' ', ',', '[', ']', '{', '}'), true))) { - @trigger_error('Using a colon that is not followed by an indication character (i.e. " ", ",", "[", "]", "{", "}" is deprecated since version 3.2 and will throw a ParseException in 4.0.', E_USER_DEPRECATED); + if (!isset($mapping[$i + 1]) || !in_array($mapping[$i + 1], array(' ', ',', '[', ']', '{', '}'), true)) { + throw new ParseException('Colons must be followed by a space or an indication character (i.e. " ", ",", "[", "]", "{", "}").', self::$parsedLineNumber + 1, $mapping); } while ($i < $len) { @@ -509,7 +456,6 @@ private static function parseMapping($mapping, $flags, &$i = 0, $references = ar } $tag = self::parseTag($mapping, $i, $flags); - $duplicate = false; switch ($mapping[$i]) { case '[': // nested sequence @@ -518,8 +464,7 @@ private static function parseMapping($mapping, $flags, &$i = 0, $references = ar // Parser cannot abort this mapping earlier, since lines // are processed sequentially. if (isset($output[$key])) { - @trigger_error(sprintf('Duplicate key "%s" detected on line %d whilst parsing YAML. Silent handling of duplicate mapping keys in YAML is deprecated since version 3.2 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0.', $key, self::$parsedLineNumber + 1), E_USER_DEPRECATED); - $duplicate = true; + throw new ParseException(sprintf('Duplicate key "%s" detected.', $key), self::$parsedLineNumber + 1, $mapping); } break; case '{': @@ -529,8 +474,7 @@ private static function parseMapping($mapping, $flags, &$i = 0, $references = ar // Parser cannot abort this mapping earlier, since lines // are processed sequentially. if (isset($output[$key])) { - @trigger_error(sprintf('Duplicate key "%s" detected on line %d whilst parsing YAML. Silent handling of duplicate mapping keys in YAML is deprecated since version 3.2 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0.', $key, self::$parsedLineNumber + 1), E_USER_DEPRECATED); - $duplicate = true; + throw new ParseException(sprintf('Duplicate key "%s" detected.', $key), self::$parsedLineNumber + 1, $mapping); } break; default: @@ -539,19 +483,17 @@ private static function parseMapping($mapping, $flags, &$i = 0, $references = ar // Parser cannot abort this mapping earlier, since lines // are processed sequentially. if (isset($output[$key])) { - @trigger_error(sprintf('Duplicate key "%s" detected on line %d whilst parsing YAML. Silent handling of duplicate mapping keys in YAML is deprecated since version 3.2 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0.', $key, self::$parsedLineNumber + 1), E_USER_DEPRECATED); - $duplicate = true; + throw new ParseException(sprintf('Duplicate key "%s" detected.', $key), self::$parsedLineNumber + 1, $mapping); } --$i; } - if (!$duplicate) { - if (null !== $tag) { - $output[$key] = new TaggedValue($tag, $value); - } else { - $output[$key] = $value; - } + if (null !== $tag) { + $output[$key] = new TaggedValue($tag, $value); + } else { + $output[$key] = $value; } + ++$i; continue 2; @@ -620,18 +562,6 @@ private static function evaluateScalar($scalar, $flags, $references = array()) throw new ParseException('Object support when parsing a YAML file has been disabled.'); } - return; - case 0 === strpos($scalar, '!!php/object:'): - if (self::$objectSupport) { - @trigger_error('The !!php/object tag to indicate dumped PHP objects is deprecated since version 3.1 and will be removed in 4.0. Use the !php/object tag instead.', E_USER_DEPRECATED); - - return unserialize(substr($scalar, 13)); - } - - if (self::$exceptionOnInvalidType) { - throw new ParseException('Object support when parsing a YAML file has been disabled.'); - } - return; case 0 === strpos($scalar, '!php/const:'): if (self::$constantSupport) { @@ -680,13 +610,8 @@ private static function evaluateScalar($scalar, $flags, $references = array()) return -log(0); case '-.inf' === $scalarLower: return log(0); - case Parser::preg_match('/^(-|\+)?[0-9][0-9,]*(\.[0-9_]+)?$/', $scalar): case Parser::preg_match('/^(-|\+)?[0-9][0-9_]*(\.[0-9_]+)?$/', $scalar): - if (false !== strpos($scalar, ',')) { - @trigger_error('Using the comma as a group separator for floats is deprecated since version 3.2 and will be removed in 4.0.', E_USER_DEPRECATED); - } - - return (float) str_replace(array(',', '_'), '', $scalar); + return (float) str_replace('_', '', $scalar); case Parser::preg_match(self::getTimestampRegex(), $scalar): if (Yaml::PARSE_DATETIME & $flags) { // When no timezone is provided in the parsed date, YAML spec says we must assume UTC. diff --git a/src/Symfony/Component/Yaml/Parser.php b/src/Symfony/Component/Yaml/Parser.php index dcedd899bc704..d939facf233ea 100644 --- a/src/Symfony/Component/Yaml/Parser.php +++ b/src/Symfony/Component/Yaml/Parser.php @@ -33,21 +33,6 @@ class Parser private $skippedLineNumbers = array(); private $locallySkippedLineNumbers = array(); - public function __construct() - { - if (func_num_args() > 0) { - @trigger_error(sprintf('The constructor arguments $offset, $totalNumberOfLines, $skippedLineNumbers of %s are deprecated and will be removed in 4.0', self::class), E_USER_DEPRECATED); - - $this->offset = func_get_arg(0); - if (func_num_args() > 1) { - $this->totalNumberOfLines = func_get_arg(1); - } - if (func_num_args() > 2) { - $this->skippedLineNumbers = func_get_arg(2); - } - } - } - /** * Parses a YAML string to a PHP value. * @@ -60,32 +45,6 @@ public function __construct() */ public function parse($value, $flags = 0) { - if (is_bool($flags)) { - @trigger_error('Passing a boolean flag to toggle exception handling is deprecated since version 3.1 and will be removed in 4.0. Use the Yaml::PARSE_EXCEPTION_ON_INVALID_TYPE flag instead.', E_USER_DEPRECATED); - - if ($flags) { - $flags = Yaml::PARSE_EXCEPTION_ON_INVALID_TYPE; - } else { - $flags = 0; - } - } - - if (func_num_args() >= 3) { - @trigger_error('Passing a boolean flag to toggle object support is deprecated since version 3.1 and will be removed in 4.0. Use the Yaml::PARSE_OBJECT flag instead.', E_USER_DEPRECATED); - - if (func_get_arg(2)) { - $flags |= Yaml::PARSE_OBJECT; - } - } - - if (func_num_args() >= 4) { - @trigger_error('Passing a boolean flag to toggle object for map support is deprecated since version 3.1 and will be removed in 4.0. Use the Yaml::PARSE_OBJECT_FOR_MAP flag instead.', E_USER_DEPRECATED); - - if (func_get_arg(3)) { - $flags |= Yaml::PARSE_OBJECT_FOR_MAP; - } - } - if (false === preg_match('//u', $value)) { throw new ParseException('The YAML value does not appear to be valid UTF-8.'); } @@ -178,7 +137,7 @@ private function doParse($value, $flags) } if (isset($values['value'][1]) && '?' === $values['value'][0] && ' ' === $values['value'][1]) { - @trigger_error('Starting an unquoted string with a question mark followed by a space is deprecated since version 3.3 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0.', E_USER_DEPRECATED); + throw new ParseException('Complex mappings are not supported.', $this->getRealCurrentLineNb() + 1, $this->currentLine); } // array @@ -230,7 +189,7 @@ private function doParse($value, $flags) } if (!(Yaml::PARSE_KEYS_AS_STRINGS & $flags) && !is_string($key)) { - @trigger_error('Implicit casting of incompatible mapping keys to strings is deprecated since version 3.3 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0. Pass the PARSE_KEYS_AS_STRING flag to explicitly enable the type casts.', E_USER_DEPRECATED); + throw new ParseException('Non-string mapping keys are not supported. Pass the Yaml::PARSE_KEYS_AS_STRINGS flag to cast them to strings.', $this->getRealCurrentLineNb() + 1, $this->currentLine); } // Convert float keys to strings, to avoid being converted to integers by PHP @@ -304,7 +263,7 @@ private function doParse($value, $flags) $data[$key] = null; } } else { - @trigger_error(sprintf('Duplicate key "%s" detected on line %d whilst parsing YAML. Silent handling of duplicate mapping keys in YAML is deprecated since version 3.2 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0.', $key, $this->getRealCurrentLineNb() + 1), E_USER_DEPRECATED); + throw new ParseException(sprintf('Duplicate key "%s" detected.', $key), $this->getRealCurrentLineNb() + 1, $this->currentLine); } } else { // remember the parsed line number here in case we need it to provide some contexts in error messages below @@ -319,7 +278,7 @@ private function doParse($value, $flags) $data[$key] = $value; } } else { - @trigger_error(sprintf('Duplicate key "%s" detected on line %d whilst parsing YAML. Silent handling of duplicate mapping keys in YAML is deprecated since version 3.2 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0.', $key, $realCurrentLineNbKey + 1), E_USER_DEPRECATED); + throw new ParseException(sprintf('Duplicate key "%s" detected.', $key), $realCurrentLineNbKey + 1, $this->currentLine); } } } else { @@ -329,7 +288,7 @@ private function doParse($value, $flags) if ($allowOverwrite || !isset($data[$key])) { $data[$key] = $value; } else { - @trigger_error(sprintf('Duplicate key "%s" detected on line %d whilst parsing YAML. Silent handling of duplicate mapping keys in YAML is deprecated since version 3.2 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0.', $key, $this->getRealCurrentLineNb() + 1), E_USER_DEPRECATED); + throw new ParseException(sprintf('Duplicate key "%s" detected.', $key), $this->getRealCurrentLineNb() + 1, $this->currentLine); } } if ($isRef) { @@ -342,7 +301,7 @@ private function doParse($value, $flags) } if (isset($this->currentLine[1]) && '?' === $this->currentLine[0] && ' ' === $this->currentLine[1]) { - @trigger_error('Starting an unquoted string with a question mark followed by a space is deprecated since version 3.3 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0.', E_USER_DEPRECATED); + throw new ParseException('Complex mappings are not supported.', $this->getRealCurrentLineNb() + 1, $this->currentLine); } // 1-liner optionally followed by newline(s) diff --git a/src/Symfony/Component/Yaml/Tests/DumperTest.php b/src/Symfony/Component/Yaml/Tests/DumperTest.php index 1c80bec6506c2..b6648d8ce7eda 100644 --- a/src/Symfony/Component/Yaml/Tests/DumperTest.php +++ b/src/Symfony/Component/Yaml/Tests/DumperTest.php @@ -77,35 +77,6 @@ public function testIndentationInConstructor() $this->assertEquals($expected, $dumper->dump($this->array, 4, 0)); } - /** - * @group legacy - */ - public function testSetIndentation() - { - $this->dumper->setIndentation(7); - - $expected = <<<'EOF' -'': bar -foo: '#bar' -'foo''bar': { } -bar: - - 1 - - foo -foobar: - foo: bar - bar: - - 1 - - foo - foobar: - foo: bar - bar: - - 1 - - foo - -EOF; - $this->assertEquals($expected, $this->dumper->dump($this->array, 4, 0)); - } - public function testSpecifications() { $files = $this->parser->parse(file_get_contents($this->path.'/index.yml')); @@ -213,16 +184,6 @@ public function testObjectSupportEnabled() $this->assertEquals('{ foo: !php/object:O:30:"Symfony\Component\Yaml\Tests\A":1:{s:1:"a";s:3:"foo";}, bar: 1 }', $dump, '->dump() is able to dump objects'); } - /** - * @group legacy - */ - public function testObjectSupportEnabledPassingTrue() - { - $dump = $this->dumper->dump(array('foo' => new A(), 'bar' => 1), 0, 0, false, true); - - $this->assertEquals('{ foo: !php/object:O:30:"Symfony\Component\Yaml\Tests\A":1:{s:1:"a";s:3:"foo";}, bar: 1 }', $dump, '->dump() is able to dump objects'); - } - public function testObjectSupportDisabledButNoExceptions() { $dump = $this->dumper->dump(array('foo' => new A(), 'bar' => 1)); @@ -238,33 +199,6 @@ public function testObjectSupportDisabledWithExceptions() $this->dumper->dump(array('foo' => new A(), 'bar' => 1), 0, 0, Yaml::DUMP_EXCEPTION_ON_INVALID_TYPE); } - /** - * @group legacy - * @expectedException \Symfony\Component\Yaml\Exception\DumpException - */ - public function testObjectSupportDisabledWithExceptionsPassingTrue() - { - $this->dumper->dump(array('foo' => new A(), 'bar' => 1), 0, 0, true); - } - - public function testEmptyArray() - { - $dump = $this->dumper->dump(array()); - $this->assertEquals('{ }', $dump); - - $dump = $this->dumper->dump(array(), 0, 0, Yaml::DUMP_EMPTY_ARRAY_AS_SEQUENCE); - $this->assertEquals('[]', $dump); - - $dump = $this->dumper->dump(array(), 9, 0, Yaml::DUMP_EMPTY_ARRAY_AS_SEQUENCE); - $this->assertEquals('[]', $dump); - - $dump = $this->dumper->dump(new \ArrayObject(), 0, 0, Yaml::DUMP_EMPTY_ARRAY_AS_SEQUENCE | Yaml::DUMP_OBJECT_AS_MAP); - $this->assertEquals('{ }', $dump); - - $dump = $this->dumper->dump(new \stdClass(), 0, 0, Yaml::DUMP_EMPTY_ARRAY_AS_SEQUENCE | Yaml::DUMP_OBJECT_AS_MAP); - $this->assertEquals('{ }', $dump); - } - /** * @dataProvider getEscapeSequences */ diff --git a/src/Symfony/Component/Yaml/Tests/Fixtures/YtsSpecificationExamples.yml b/src/Symfony/Component/Yaml/Tests/Fixtures/YtsSpecificationExamples.yml index 45e27b7b7410e..6776d3e833aed 100644 --- a/src/Symfony/Component/Yaml/Tests/Fixtures/YtsSpecificationExamples.yml +++ b/src/Symfony/Component/Yaml/Tests/Fixtures/YtsSpecificationExamples.yml @@ -518,16 +518,6 @@ php: | 'hexadecimal' => 0xC ) --- -test: Decimal Integer -deprecated: true -spec: 2.19 -yaml: | - decimal: +12,345 -php: | - array( - 'decimal' => 12345.0, - ) ---- # FIX: spec shows parens around -inf and NaN test: Floating point spec: 2.20 @@ -546,16 +536,6 @@ php: | 'float as whole number' => (float) 1 ) --- -test: Fixed Floating point -deprecated: true -spec: 2.20 -yaml: | - fixed: 1,230.15 -php: | - array( - 'fixed' => 1230.15, - ) ---- test: Timestamps todo: true spec: 2.22 @@ -1530,24 +1510,6 @@ php: | 'hexadecimal' => 12 ) --- -test: Decimal -deprecated: true -yaml: | - decimal: +12,345 -php: | - array( - 'decimal' => 12345.0, - ) ---- -test: Fixed Float -deprecated: true -yaml: | - fixed: 1,230.15 -php: | - array( - 'fixed' => 1230.15, - ) ---- test: Float yaml: | canonical: 1.23015e+3 diff --git a/src/Symfony/Component/Yaml/Tests/Fixtures/YtsTypeTransfers.yml b/src/Symfony/Component/Yaml/Tests/Fixtures/YtsTypeTransfers.yml index 5b9df73be1572..185e4ef58c8e2 100644 --- a/src/Symfony/Component/Yaml/Tests/Fixtures/YtsTypeTransfers.yml +++ b/src/Symfony/Component/Yaml/Tests/Fixtures/YtsTypeTransfers.yml @@ -182,34 +182,6 @@ php: | 'simple' => 12, ) --- -test: Positive Big Integer -deprecated: true -dump_skip: true -brief: > - An integer is a series of numbers, optionally - starting with a positive or negative sign. Integers - may also contain commas for readability. -yaml: | - one-thousand: 1,000 -php: | - array( - 'one-thousand' => 1000.0, - ) ---- -test: Negative Big Integer -deprecated: true -dump_skip: true -brief: > - An integer is a series of numbers, optionally - starting with a positive or negative sign. Integers - may also contain commas for readability. -yaml: | - negative one-thousand: -1,000 -php: | - array( - 'negative one-thousand' => -1000.0 - ) ---- test: Floats dump_skip: true brief: > @@ -225,20 +197,6 @@ php: | 'scientific notation' => 1000.09 ) --- -test: Larger Float -dump_skip: true -deprecated: true -brief: > - Floats are represented by numbers with decimals, - allowing for scientific notation, as well as - positive and negative infinity and "not a number." -yaml: | - larger float: 1,000.09 -php: | - array( - 'larger float' => 1000.09, - ) ---- test: Time todo: true brief: > diff --git a/src/Symfony/Component/Yaml/Tests/Fixtures/legacyBooleanMappingKeys.yml b/src/Symfony/Component/Yaml/Tests/Fixtures/legacyBooleanMappingKeys.yml deleted file mode 100644 index 5e8d091707d51..0000000000000 --- a/src/Symfony/Component/Yaml/Tests/Fixtures/legacyBooleanMappingKeys.yml +++ /dev/null @@ -1,23 +0,0 @@ ---- %YAML:1.0 -test: Miscellaneous -spec: 2.21 -yaml: | - true: true - false: false -php: | - array( - 1 => true, - 0 => false, - ) ---- -test: Boolean -yaml: | - false: used as key - logical: true - answer: false -php: | - array( - false => 'used as key', - 'logical' => true, - 'answer' => false - ) diff --git a/src/Symfony/Component/Yaml/Tests/Fixtures/legacyNonStringKeys.yml b/src/Symfony/Component/Yaml/Tests/Fixtures/legacyNonStringKeys.yml deleted file mode 100644 index 4e28201856d2a..0000000000000 --- a/src/Symfony/Component/Yaml/Tests/Fixtures/legacyNonStringKeys.yml +++ /dev/null @@ -1,2 +0,0 @@ -- legacyBooleanMappingKeys -- legacyNullMappingKey diff --git a/src/Symfony/Component/Yaml/Tests/Fixtures/legacyNullMappingKey.yml b/src/Symfony/Component/Yaml/Tests/Fixtures/legacyNullMappingKey.yml deleted file mode 100644 index 551a6205e137d..0000000000000 --- a/src/Symfony/Component/Yaml/Tests/Fixtures/legacyNullMappingKey.yml +++ /dev/null @@ -1,9 +0,0 @@ ---- %YAML:1.0 -test: Miscellaneous -spec: 2.21 -yaml: | - null: ~ -php: | - array( - '' => null, - ) diff --git a/src/Symfony/Component/Yaml/Tests/InlineTest.php b/src/Symfony/Component/Yaml/Tests/InlineTest.php index a26ffbf9e44c6..56a38662327e1 100644 --- a/src/Symfony/Component/Yaml/Tests/InlineTest.php +++ b/src/Symfony/Component/Yaml/Tests/InlineTest.php @@ -74,17 +74,6 @@ public function testParsePhpConstantThrowsExceptionOnInvalidType() Inline::parse('!php/const:PHP_INT_MAX', Yaml::PARSE_EXCEPTION_ON_INVALID_TYPE); } - /** - * @group legacy - * @dataProvider getTestsForParseWithMapObjects - */ - public function testParseWithMapObjectsPassingTrue($yaml, $value) - { - $actual = Inline::parse($yaml, false, false, true); - - $this->assertSame(serialize($value), serialize($actual)); - } - /** * @dataProvider getTestsForDump */ @@ -167,13 +156,12 @@ public function testParseInvalidMappingKeyShouldThrowException() } /** - * @group legacy - * @expectedDeprecation Using a colon that is not followed by an indication character (i.e. " ", ",", "[", "]", "{", "}" is deprecated since version 3.2 and will throw a ParseException in 4.0. - * throws \Symfony\Component\Yaml\Exception\ParseException in 4.0 + * @expectedException \Symfony\Component\Yaml\Exception\ParseException + * @expectedExceptionMessage Colons must be followed by a space or an indication character (i.e. " ", ",", "[", "]", "{", "}") */ public function testParseMappingKeyWithColonNotFollowedBySpace() { - Inline::parse('{1:""}'); + Inline::parse('{foo:""}'); } /** @@ -208,15 +196,6 @@ public function testParseReferences($yaml, $expected) $this->assertSame($expected, Inline::parse($yaml, 0, array('var' => 'var-value'))); } - /** - * @group legacy - * @dataProvider getDataForParseReferences - */ - public function testParseReferencesAsFifthArgument($yaml, $expected) - { - $this->assertSame($expected, Inline::parse($yaml, false, false, false, array('var' => 'var-value'))); - } - public function getDataForParseReferences() { return array( @@ -241,19 +220,6 @@ public function testParseMapReferenceInSequence() $this->assertSame(array($foo), Inline::parse('[*foo]', 0, array('foo' => $foo))); } - /** - * @group legacy - */ - public function testParseMapReferenceInSequenceAsFifthArgument() - { - $foo = array( - 'a' => 'Steve', - 'b' => 'Clark', - 'c' => 'Brian', - ); - $this->assertSame(array($foo), Inline::parse('[*foo]', false, false, false, array('foo' => $foo))); - } - /** * @expectedException \Symfony\Component\Yaml\Exception\ParseException * @expectedExceptionMessage A reference must contain at least one character. @@ -299,17 +265,7 @@ public function testParseUnquotedScalarStartingWithScalarIndicator($indicator) public function getScalarIndicators() { - return array(array('|'), array('>')); - } - - /** - * @group legacy - * @expectedDeprecation Not quoting the scalar "%bar " starting with the "%" indicator character is deprecated since Symfony 3.1 and will throw a ParseException in 4.0. - * throws \Symfony\Component\Yaml\Exception\ParseException in 4.0 - */ - public function testParseUnquotedScalarStartingWithPercentCharacter() - { - Inline::parse('{ foo: %bar }'); + return array(array('|'), array('>'), array('%')); } /** @@ -695,12 +651,12 @@ public function testVeryLongQuotedStrings() } /** - * @group legacy - * @expectedDeprecation Omitting the key of a mapping is deprecated and will throw a ParseException in 4.0. + * @expectedException \Symfony\Component\Yaml\Exception\ParseException + * @expectedExceptionMessage Missing mapping key */ - public function testOmittedMappingKeyIsParsedAsColon() + public function testMappingKeysCannotBeOmitted() { - $this->assertSame(array(':' => 'foo'), Inline::parse('{: foo}')); + Inline::parse('{: foo}'); } /** @@ -725,8 +681,9 @@ public function testTheEmptyStringIsAValidMappingKey() } /** - * @group legacy - * @expectedDeprecation Implicit casting of incompatible mapping keys to strings is deprecated since version 3.3 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0. Pass the PARSE_KEYS_AS_STRING flag to explicitly enable the type casts. + * @expectedException \Symfony\Component\Yaml\Exception\ParseException + * @expectedExceptionMessage Non-string mapping keys are not supported. Pass the Yaml::PARSE_KEYS_AS_STRINGS flag to cast them to strings + * * @dataProvider getNotPhpCompatibleMappingKeyData */ public function testImplicitStringCastingOfMappingKeysIsDeprecated($yaml, $expected) diff --git a/src/Symfony/Component/Yaml/Tests/ParserTest.php b/src/Symfony/Component/Yaml/Tests/ParserTest.php index f64d7589d8d88..f52921d986d9e 100644 --- a/src/Symfony/Component/Yaml/Tests/ParserTest.php +++ b/src/Symfony/Component/Yaml/Tests/ParserTest.php @@ -35,34 +35,9 @@ protected function tearDown() /** * @dataProvider getDataFormSpecifications */ - public function testSpecifications($expected, $yaml, $comment, $deprecated) + public function testSpecifications($expected, $yaml, $comment) { - $deprecations = array(); - - if ($deprecated) { - set_error_handler(function ($type, $msg) use (&$deprecations) { - if (E_USER_DEPRECATED !== $type) { - restore_error_handler(); - - if (class_exists('PHPUnit_Util_ErrorHandler')) { - return call_user_func_array('PHPUnit_Util_ErrorHandler::handleError', func_get_args()); - } - - return call_user_func_array('PHPUnit\Util\ErrorHandler::handleError', func_get_args()); - } - - $deprecations[] = $msg; - }); - } - $this->assertEquals($expected, var_export($this->parser->parse($yaml), true), $comment); - - if ($deprecated) { - restore_error_handler(); - - $this->assertCount(1, $deprecations); - $this->assertContains('Using the comma as a group separator for floats is deprecated since version 3.2 and will be removed in 4.0.', $deprecations[0]); - } } public function getDataFormSpecifications() @@ -83,20 +58,6 @@ public function getNonStringMappingKeysData() return $this->loadTestsFromFixtureFiles('nonStringKeys.yml'); } - /** - * @group legacy - * @dataProvider getLegacyNonStringMappingKeysData - */ - public function testLegacyNonStringMappingKeys($expected, $yaml, $comment) - { - $this->assertSame($expected, var_export($this->parser->parse($yaml), true), $comment); - } - - public function getLegacyNonStringMappingKeysData() - { - return $this->loadTestsFromFixtureFiles('legacyNonStringKeys.yml'); - } - public function testTabsInYaml() { // test tabs in YAML @@ -475,35 +436,13 @@ public function testObjectSupportEnabled() $this->assertEquals(array('foo' => new B(), 'bar' => 1), $this->parser->parse($input, Yaml::PARSE_OBJECT), '->parse() is able to parse objects'); } - /** - * @group legacy - */ - public function testObjectSupportEnabledPassingTrue() - { - $input = <<<'EOF' -foo: !php/object:O:30:"Symfony\Component\Yaml\Tests\B":1:{s:1:"b";s:3:"foo";} -bar: 1 -EOF; - $this->assertEquals(array('foo' => new B(), 'bar' => 1), $this->parser->parse($input, false, true), '->parse() is able to parse objects'); - } - - /** - * @group legacy - */ - public function testObjectSupportEnabledWithDeprecatedTag() + public function testObjectSupportDisabledButNoExceptions() { $input = <<<'EOF' -foo: !!php/object:O:30:"Symfony\Component\Yaml\Tests\B":1:{s:1:"b";s:3:"foo";} +foo: !php/object:O:30:"Symfony\Tests\Component\Yaml\B":1:{s:1:"b";s:3:"foo";} bar: 1 EOF; - $this->assertEquals(array('foo' => new B(), 'bar' => 1), $this->parser->parse($input, Yaml::PARSE_OBJECT), '->parse() is able to parse objects'); - } - /** - * @dataProvider invalidDumpedObjectProvider - */ - public function testObjectSupportDisabledButNoExceptions($input) - { $this->assertEquals(array('foo' => null, 'bar' => 1), $this->parser->parse($input), '->parse() does not parse objects'); } @@ -521,15 +460,6 @@ public function testObjectForMap($yaml, $expected, $explicitlyParseKeysAsStrings $this->assertEquals($expected, $this->parser->parse($yaml, $flags)); } - /** - * @group legacy - * @dataProvider getObjectForMapTests - */ - public function testObjectForMapEnabledWithMappingUsingBooleanToggles($yaml, $expected) - { - $this->assertEquals($expected, $this->parser->parse($yaml, false, false, true)); - } - public function getObjectForMapTests() { $tests = array(); @@ -594,11 +524,15 @@ public function getObjectForMapTests() } /** - * @dataProvider invalidDumpedObjectProvider * @expectedException \Symfony\Component\Yaml\Exception\ParseException */ - public function testObjectsSupportDisabledWithExceptions($yaml) + public function testObjectsSupportDisabledWithExceptions() { + $yaml = <<<'EOF' +foo: !php/object:O:30:"Symfony\Tests\Component\Yaml\B":1:{s:1:"b";s:3:"foo";} +bar: 1 +EOF; + $this->parser->parse($yaml, Yaml::PARSE_EXCEPTION_ON_INVALID_TYPE); } @@ -613,33 +547,6 @@ public function testCanParseContentWithTrailingSpaces() $this->assertSame($expected, $this->parser->parse($yaml)); } - /** - * @group legacy - * @dataProvider invalidDumpedObjectProvider - * @expectedException \Symfony\Component\Yaml\Exception\ParseException - */ - public function testObjectsSupportDisabledWithExceptionsUsingBooleanToggles($yaml) - { - $this->parser->parse($yaml, true); - } - - public function invalidDumpedObjectProvider() - { - $yamlTag = <<<'EOF' -foo: !!php/object:O:30:"Symfony\Tests\Component\Yaml\B":1:{s:1:"b";s:3:"foo";} -bar: 1 -EOF; - $localTag = <<<'EOF' -foo: !php/object:O:30:"Symfony\Tests\Component\Yaml\B":1:{s:1:"b";s:3:"foo";} -bar: 1 -EOF; - - return array( - 'yaml-tag' => array($yamlTag), - 'local-tag' => array($localTag), - ); - } - /** * @requires extension iconv */ @@ -805,6 +712,9 @@ public function testScalarInSequence() } /** + * @expectedException \Symfony\Component\Yaml\Exception\ParseException + * @expectedExceptionMessage Duplicate key "child" detected + * * > It is an error for two equal keys to appear in the same mapping node. * > In such a case the YAML processor may continue, ignoring the second * > `key: value` pair and issuing an appropriate warning. This strategy @@ -813,7 +723,6 @@ public function testScalarInSequence() * * @see http://yaml.org/spec/1.2/spec.html#id2759572 * @see http://yaml.org/spec/1.1/#id932806 - * @group legacy */ public function testMappingDuplicateKeyBlock() { @@ -834,7 +743,8 @@ public function testMappingDuplicateKeyBlock() } /** - * @group legacy + * @expectedException \Symfony\Component\Yaml\Exception\ParseException + * @expectedExceptionMessage Duplicate key "child" detected */ public function testMappingDuplicateKeyFlow() { @@ -851,13 +761,13 @@ public function testMappingDuplicateKeyFlow() } /** - * @group legacy + * @expectedException \Symfony\Component\Yaml\Exception\ParseException * @dataProvider getParseExceptionOnDuplicateData - * @expectedDeprecation Duplicate key "%s" detected on line %d whilst parsing YAML. Silent handling of duplicate mapping keys in YAML is deprecated %s. - * throws \Symfony\Component\Yaml\Exception\ParseException in 4.0 */ public function testParseExceptionOnDuplicate($input, $duplicateKey, $lineNumber) { + $this->expectExceptionMessage(sprintf('Duplicate key "%s" detected at line %d', $duplicateKey, $lineNumber)); + Yaml::parse($input); } @@ -1080,8 +990,8 @@ public function testYamlDirective() } /** - * @group legacy - * @expectedDeprecation Implicit casting of incompatible mapping keys to strings is deprecated since version 3.3 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0. Pass the PARSE_KEYS_AS_STRING flag to explicitly enable the type casts. + * @expectedException \Symfony\Component\Yaml\Exception\ParseException + * @expectedExceptionMessage Non-string mapping keys are not supported. Pass the Yaml::PARSE_KEYS_AS_STRINGS flag to cast them to strings */ public function testFloatKeys() { @@ -1091,19 +1001,12 @@ public function testFloatKeys() 1.3: "baz" EOF; - $expected = array( - 'foo' => array( - '1.2' => 'bar', - '1.3' => 'baz', - ), - ); - - $this->assertEquals($expected, $this->parser->parse($yaml)); + $this->parser->parse($yaml); } /** - * @group legacy - * @expectedDeprecation Implicit casting of incompatible mapping keys to strings is deprecated since version 3.3 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0. Pass the PARSE_KEYS_AS_STRING flag to explicitly enable the type casts. + * @expectedException \Symfony\Component\Yaml\Exception\ParseException + * @expectedExceptionMessage Non-string mapping keys are not supported. Pass the Yaml::PARSE_KEYS_AS_STRINGS flag to cast them to strings */ public function testBooleanKeys() { @@ -1112,12 +1015,7 @@ public function testBooleanKeys() false: bar EOF; - $expected = array( - 1 => 'foo', - 0 => 'bar', - ); - - $this->assertEquals($expected, $this->parser->parse($yaml)); + $this->parser->parse($yaml); } public function testExplicitStringCastingOfFloatKeys() @@ -1653,8 +1551,8 @@ public function testExceptionWhenUsingUnsuportedBuiltInTags() } /** - * @group legacy - * @expectedDeprecation Starting an unquoted string with a question mark followed by a space is deprecated since version 3.3 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0. + * @expectedException \Symfony\Component\Yaml\Exception\ParseException + * @expectedExceptionMessage Complex mappings are not supported at line 1 (near "? "1""). */ public function testComplexMappingThrowsParseException() { @@ -1668,8 +1566,8 @@ public function testComplexMappingThrowsParseException() } /** - * @group legacy - * @expectedDeprecation Starting an unquoted string with a question mark followed by a space is deprecated since version 3.3 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0. + * @expectedException \Symfony\Component\Yaml\Exception\ParseException + * @expectedExceptionMessage Complex mappings are not supported at line 2 (near "? "1""). */ public function testComplexMappingNestedInMappingThrowsParseException() { @@ -1684,8 +1582,8 @@ public function testComplexMappingNestedInMappingThrowsParseException() } /** - * @group legacy - * @expectedDeprecation Starting an unquoted string with a question mark followed by a space is deprecated since version 3.3 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0. + * @expectedException \Symfony\Component\Yaml\Exception\ParseException + * @expectedExceptionMessage Complex mappings are not supported at line 1 (near "- ? "1""). */ public function testComplexMappingNestedInSequenceThrowsParseException() { @@ -1734,7 +1632,7 @@ private function loadTestsFromFixtureFiles($testsFile) } else { eval('$expected = '.trim($test['php']).';'); - $tests[] = array(var_export($expected, true), $test['yaml'], $test['test'], isset($test['deprecated']) ? $test['deprecated'] : false); + $tests[] = array(var_export($expected, true), $test['yaml'], $test['test']); } } } diff --git a/src/Symfony/Component/Yaml/Yaml.php b/src/Symfony/Component/Yaml/Yaml.php index 84f749b560dbf..168d0b75523a5 100644 --- a/src/Symfony/Component/Yaml/Yaml.php +++ b/src/Symfony/Component/Yaml/Yaml.php @@ -51,32 +51,6 @@ class Yaml */ public static function parse($input, $flags = 0) { - if (is_bool($flags)) { - @trigger_error('Passing a boolean flag to toggle exception handling is deprecated since version 3.1 and will be removed in 4.0. Use the PARSE_EXCEPTION_ON_INVALID_TYPE flag instead.', E_USER_DEPRECATED); - - if ($flags) { - $flags = self::PARSE_EXCEPTION_ON_INVALID_TYPE; - } else { - $flags = 0; - } - } - - if (func_num_args() >= 3) { - @trigger_error('Passing a boolean flag to toggle object support is deprecated since version 3.1 and will be removed in 4.0. Use the PARSE_OBJECT flag instead.', E_USER_DEPRECATED); - - if (func_get_arg(2)) { - $flags |= self::PARSE_OBJECT; - } - } - - if (func_num_args() >= 4) { - @trigger_error('Passing a boolean flag to toggle object for map support is deprecated since version 3.1 and will be removed in 4.0. Use the Yaml::PARSE_OBJECT_FOR_MAP flag instead.', E_USER_DEPRECATED); - - if (func_get_arg(3)) { - $flags |= self::PARSE_OBJECT_FOR_MAP; - } - } - $yaml = new Parser(); return $yaml->parse($input, $flags); @@ -97,24 +71,6 @@ public static function parse($input, $flags = 0) */ public static function dump($input, $inline = 2, $indent = 4, $flags = 0) { - if (is_bool($flags)) { - @trigger_error('Passing a boolean flag to toggle exception handling is deprecated since version 3.1 and will be removed in 4.0. Use the DUMP_EXCEPTION_ON_INVALID_TYPE flag instead.', E_USER_DEPRECATED); - - if ($flags) { - $flags = self::DUMP_EXCEPTION_ON_INVALID_TYPE; - } else { - $flags = 0; - } - } - - if (func_num_args() >= 5) { - @trigger_error('Passing a boolean flag to toggle object support is deprecated since version 3.1 and will be removed in 4.0. Use the DUMP_OBJECT flag instead.', E_USER_DEPRECATED); - - if (func_get_arg(4)) { - $flags |= self::DUMP_OBJECT; - } - } - $yaml = new Dumper($indent); return $yaml->dump($input, $inline, 0, $flags); From 3a129494b1816ca272a98624719709fc5a8b4b3e Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Fri, 19 May 2017 19:36:56 +0200 Subject: [PATCH 0064/1099] [ProxyManagerBridge] remove deprecated features --- .../LazyProxy/PhpDumper/ProxyDumper.php | 11 ++++------- .../LazyProxy/PhpDumper/ProxyDumperTest.php | 18 ++++-------------- .../Component/DependencyInjection/CHANGELOG.md | 2 ++ .../LazyProxy/PhpDumper/DumperInterface.php | 4 ++-- .../LazyProxy/PhpDumper/NullDumperTest.php | 2 +- 5 files changed, 13 insertions(+), 24 deletions(-) diff --git a/src/Symfony/Bridge/ProxyManager/LazyProxy/PhpDumper/ProxyDumper.php b/src/Symfony/Bridge/ProxyManager/LazyProxy/PhpDumper/ProxyDumper.php index 447549b970442..cf9161440178d 100644 --- a/src/Symfony/Bridge/ProxyManager/LazyProxy/PhpDumper/ProxyDumper.php +++ b/src/Symfony/Bridge/ProxyManager/LazyProxy/PhpDumper/ProxyDumper.php @@ -14,7 +14,6 @@ use ProxyManager\Generator\ClassGenerator; use ProxyManager\GeneratorStrategy\BaseGeneratorStrategy; use ProxyManager\ProxyGenerator\LazyLoadingValueHolderGenerator; -use Symfony\Component\DependencyInjection\Container; use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\DependencyInjection\LazyProxy\PhpDumper\DumperInterface; @@ -63,7 +62,7 @@ public function isProxyCandidate(Definition $definition) /** * {@inheritdoc} */ - public function getProxyFactoryCode(Definition $definition, $id) + public function getProxyFactoryCode(Definition $definition, $id, $methodName = null) { $instantiation = 'return'; @@ -71,12 +70,10 @@ public function getProxyFactoryCode(Definition $definition, $id) $instantiation .= " \$this->services['$id'] ="; } - if (func_num_args() >= 3) { - $methodName = func_get_arg(2); - } else { - @trigger_error(sprintf('You must use the third argument of %s to define the method to call to construct your service since version 3.1, not using it won\'t be supported in 4.0.', __METHOD__), E_USER_DEPRECATED); - $methodName = 'get'.Container::camelize($id).'Service'; + if (null === $methodName) { + throw new \InvalidArgumentException(sprintf('Missing name of method to call to construct the service "%s".', $id)); } + $proxyClass = $this->getProxyClassName($definition); $generatedClass = $this->generateProxyClass($definition); diff --git a/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/PhpDumper/ProxyDumperTest.php b/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/PhpDumper/ProxyDumperTest.php index 64082c8f7f3f1..d4d143a56f7dc 100644 --- a/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/PhpDumper/ProxyDumperTest.php +++ b/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/PhpDumper/ProxyDumperTest.php @@ -80,24 +80,14 @@ public function testGetProxyFactoryCodeWithCustomMethod() } /** - * @group legacy + * @expectedException \InvalidArgumentException + * @expectedExceptionMessage Missing name of method to call to construct the service "foo". */ - public function testGetProxyFactoryCode() + public function testGetProxyFactoryCodeWithoutCustomMethod() { $definition = new Definition(__CLASS__); - $definition->setLazy(true); - - $code = $this->dumper->getProxyFactoryCode($definition, 'foo'); - - $this->assertStringMatchesFormat( - '%wif ($lazyLoad) {%wreturn $this->services[\'foo\'] =%s' - .'SymfonyBridgeProxyManagerTestsLazyProxyPhpDumperProxyDumperTest_%s(%wfunction ' - .'(&$wrappedInstance, \ProxyManager\Proxy\LazyLoadingInterface $proxy) {' - .'%w$wrappedInstance = $this->getFooService(false);%w$proxy->setProxyInitializer(null);' - .'%wreturn true;%w}%w);%w}%w', - $code - ); + $this->dumper->getProxyFactoryCode($definition, 'foo'); } /** diff --git a/src/Symfony/Component/DependencyInjection/CHANGELOG.md b/src/Symfony/Component/DependencyInjection/CHANGELOG.md index e95f82b945e72..e7d8baeb4a8cc 100644 --- a/src/Symfony/Component/DependencyInjection/CHANGELOG.md +++ b/src/Symfony/Component/DependencyInjection/CHANGELOG.md @@ -4,6 +4,8 @@ CHANGELOG 4.0.0 ----- + * added a third `$methodName` argument to the `getProxyFactoryCode()` method + of the `DumperInterface` * removed support for autowiring types * removed `Container::isFrozen` * removed support for dumping an ucompiled container in `PhpDumper` diff --git a/src/Symfony/Component/DependencyInjection/LazyProxy/PhpDumper/DumperInterface.php b/src/Symfony/Component/DependencyInjection/LazyProxy/PhpDumper/DumperInterface.php index ce88eba9742fd..9697be53a76d9 100644 --- a/src/Symfony/Component/DependencyInjection/LazyProxy/PhpDumper/DumperInterface.php +++ b/src/Symfony/Component/DependencyInjection/LazyProxy/PhpDumper/DumperInterface.php @@ -34,11 +34,11 @@ public function isProxyCandidate(Definition $definition); * * @param Definition $definition * @param string $id service identifier - * @param string $methodName the method name to get the service, will be added to the interface in 4.0 + * @param string $methodName the method name to get the service * * @return string */ - public function getProxyFactoryCode(Definition $definition, $id/**, $methodName = null */); + public function getProxyFactoryCode(Definition $definition, $id, $methodName); /** * Generates the code for the lazy proxy. diff --git a/src/Symfony/Component/DependencyInjection/Tests/LazyProxy/PhpDumper/NullDumperTest.php b/src/Symfony/Component/DependencyInjection/Tests/LazyProxy/PhpDumper/NullDumperTest.php index cde2c147e752c..1cd8d1a279c00 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/LazyProxy/PhpDumper/NullDumperTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/LazyProxy/PhpDumper/NullDumperTest.php @@ -28,7 +28,7 @@ public function testNullDumper() $definition = new Definition('stdClass'); $this->assertFalse($dumper->isProxyCandidate($definition)); - $this->assertSame('', $dumper->getProxyFactoryCode($definition, 'foo')); + $this->assertSame('', $dumper->getProxyFactoryCode($definition, 'foo', 'getFooService')); $this->assertSame('', $dumper->getProxyCode($definition)); } } From 6311be71579a01a08a784ab77e62703ca95acdbb Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Wed, 24 May 2017 17:30:25 +0200 Subject: [PATCH 0065/1099] [travis] Fix 3/4 cross tests --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 4e9aad6b4669b..87d8e6e5ef17a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -26,9 +26,9 @@ matrix: group: edge - php: 5.5 - php: 5.6 - - php: 7.0 - env: deps=high - php: 7.1 + env: deps=high + - php: 7.0 env: deps=low fast_finish: true From f0147dac802fbb9052249263e2a8260b1ea3b13c Mon Sep 17 00:00:00 2001 From: Robin Chalas Date: Wed, 24 May 2017 18:36:02 +0200 Subject: [PATCH 0066/1099] Remove PHP < 7.1 leftovers --- .../Compiler/FactoryReturnTypePassTest.php | 1 - src/Symfony/Component/HttpKernel/Kernel.php | 6 +----- .../PropertyAccess/PropertyAccessor.php | 19 ------------------- .../Tests/Encoder/JsonDecodeTest.php | 1 - .../Tests/Encoder/JsonEncodeTest.php | 3 +-- 5 files changed, 2 insertions(+), 28 deletions(-) diff --git a/src/Symfony/Component/DependencyInjection/Tests/Compiler/FactoryReturnTypePassTest.php b/src/Symfony/Component/DependencyInjection/Tests/Compiler/FactoryReturnTypePassTest.php index 5d5f5339be22d..f37248a717d77 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Compiler/FactoryReturnTypePassTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Compiler/FactoryReturnTypePassTest.php @@ -98,7 +98,6 @@ public function testCircularReference() } /** - * @requires function ReflectionMethod::getReturnType * @expectedDeprecation Relying on its factory's return-type to define the class of service "factory" is deprecated since Symfony 3.3 and won't work in 4.0. Set the "class" attribute to "Symfony\Component\DependencyInjection\Tests\Fixtures\FactoryDummy" on the service definition instead. */ public function testCompile() diff --git a/src/Symfony/Component/HttpKernel/Kernel.php b/src/Symfony/Component/HttpKernel/Kernel.php index 2c6e3250f7935..9985fc25b4b99 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -780,11 +780,7 @@ public function serialize() public function unserialize($data) { - if (PHP_VERSION_ID >= 70000) { - list($environment, $debug) = unserialize($data, array('allowed_classes' => false)); - } else { - list($environment, $debug) = unserialize($data); - } + list($environment, $debug) = unserialize($data, array('allowed_classes' => false)); $this->__construct($environment, $debug); } diff --git a/src/Symfony/Component/PropertyAccess/PropertyAccessor.php b/src/Symfony/Component/PropertyAccess/PropertyAccessor.php index 975824b5057e0..e4d0bb669c9d8 100644 --- a/src/Symfony/Component/PropertyAccess/PropertyAccessor.php +++ b/src/Symfony/Component/PropertyAccess/PropertyAccessor.php @@ -141,8 +141,6 @@ class PropertyAccessor implements PropertyAccessorInterface * @var array */ private $writePropertyCache = array(); - private static $previousErrorHandler = false; - private static $errorHandler = array(__CLASS__, 'handleError'); private static $resultProto = array(self::VALUE => null); /** @@ -240,26 +238,9 @@ public function setValue(&$objectOrArray, $propertyPath, $value) } } catch (\TypeError $e) { self::throwInvalidArgumentException($e->getMessage(), $e->getTrace(), 0); - } finally { - if (PHP_VERSION_ID < 70000 && false !== self::$previousErrorHandler) { - restore_error_handler(); - self::$previousErrorHandler = false; - } } } - /** - * @internal - */ - public static function handleError($type, $message, $file, $line, $context) - { - if (E_RECOVERABLE_ERROR === $type) { - self::throwInvalidArgumentException($message, debug_backtrace(false), 1); - } - - return null !== self::$previousErrorHandler && false !== call_user_func(self::$previousErrorHandler, $type, $message, $file, $line, $context); - } - private static function throwInvalidArgumentException($message, $trace, $i) { if (isset($trace[$i]['file']) && __FILE__ === $trace[$i]['file']) { diff --git a/src/Symfony/Component/Serializer/Tests/Encoder/JsonDecodeTest.php b/src/Symfony/Component/Serializer/Tests/Encoder/JsonDecodeTest.php index 774064d43a853..f4208f1256820 100644 --- a/src/Symfony/Component/Serializer/Tests/Encoder/JsonDecodeTest.php +++ b/src/Symfony/Component/Serializer/Tests/Encoder/JsonDecodeTest.php @@ -56,7 +56,6 @@ public function decodeProvider() } /** - * @requires function json_last_error_msg * @dataProvider decodeProviderException * @expectedException \Symfony\Component\Serializer\Exception\UnexpectedValueException */ diff --git a/src/Symfony/Component/Serializer/Tests/Encoder/JsonEncodeTest.php b/src/Symfony/Component/Serializer/Tests/Encoder/JsonEncodeTest.php index ed33233fb47ea..f4cbf76afc16b 100644 --- a/src/Symfony/Component/Serializer/Tests/Encoder/JsonEncodeTest.php +++ b/src/Symfony/Component/Serializer/Tests/Encoder/JsonEncodeTest.php @@ -17,7 +17,7 @@ class JsonEncodeTest extends TestCase { - private $encoder; + private $encode; protected function setUp() { @@ -50,7 +50,6 @@ public function encodeProvider() } /** - * @requires function json_last_error_msg * @expectedException \Symfony\Component\Serializer\Exception\UnexpectedValueException */ public function testEncodeWithError() From 367b055816f702d1151afaf2c7d8160fdf610e71 Mon Sep 17 00:00:00 2001 From: Robin Chalas Date: Wed, 24 May 2017 19:37:23 +0200 Subject: [PATCH 0067/1099] Make internal constants private --- .../PropertyAccess/PropertyAccessor.php | 101 +++--------------- 1 file changed, 17 insertions(+), 84 deletions(-) diff --git a/src/Symfony/Component/PropertyAccess/PropertyAccessor.php b/src/Symfony/Component/PropertyAccess/PropertyAccessor.php index 975824b5057e0..515475e9479fc 100644 --- a/src/Symfony/Component/PropertyAccess/PropertyAccessor.php +++ b/src/Symfony/Component/PropertyAccess/PropertyAccessor.php @@ -32,90 +32,23 @@ */ class PropertyAccessor implements PropertyAccessorInterface { - /** - * @internal - */ - const VALUE = 0; - - /** - * @internal - */ - const REF = 1; - - /** - * @internal - */ - const IS_REF_CHAINED = 2; - - /** - * @internal - */ - const ACCESS_HAS_PROPERTY = 0; - - /** - * @internal - */ - const ACCESS_TYPE = 1; - - /** - * @internal - */ - const ACCESS_NAME = 2; - - /** - * @internal - */ - const ACCESS_REF = 3; - - /** - * @internal - */ - const ACCESS_ADDER = 4; - - /** - * @internal - */ - const ACCESS_REMOVER = 5; - - /** - * @internal - */ - const ACCESS_TYPE_METHOD = 0; - - /** - * @internal - */ - const ACCESS_TYPE_PROPERTY = 1; - - /** - * @internal - */ - const ACCESS_TYPE_MAGIC = 2; - - /** - * @internal - */ - const ACCESS_TYPE_ADDER_AND_REMOVER = 3; - - /** - * @internal - */ - const ACCESS_TYPE_NOT_FOUND = 4; - - /** - * @internal - */ - const CACHE_PREFIX_READ = 'r'; - - /** - * @internal - */ - const CACHE_PREFIX_WRITE = 'w'; - - /** - * @internal - */ - const CACHE_PREFIX_PROPERTY_PATH = 'p'; + private const VALUE = 0; + private const REF = 1; + private const IS_REF_CHAINED = 2; + private const ACCESS_HAS_PROPERTY = 0; + private const ACCESS_TYPE = 1; + private const ACCESS_NAME = 2; + private const ACCESS_REF = 3; + private const ACCESS_ADDER = 4; + private const ACCESS_REMOVER = 5; + private const ACCESS_TYPE_METHOD = 0; + private const ACCESS_TYPE_PROPERTY = 1; + private const ACCESS_TYPE_MAGIC = 2; + private const ACCESS_TYPE_ADDER_AND_REMOVER = 3; + private const ACCESS_TYPE_NOT_FOUND = 4; + private const CACHE_PREFIX_READ = 'r'; + private const CACHE_PREFIX_WRITE = 'w'; + private const CACHE_PREFIX_PROPERTY_PATH = 'p'; /** * @var bool From 4bae9aa3dacca2f3aabf5860d28e26d907f24736 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Thu, 25 May 2017 10:45:41 +0200 Subject: [PATCH 0068/1099] [Console] remove remaining deprecated features --- src/Symfony/Component/Console/CHANGELOG.md | 1 + .../Component/Console/Formatter/OutputFormatter.php | 8 +------- .../Console/Tests/Formatter/OutputFormatterTest.php | 11 ----------- 3 files changed, 2 insertions(+), 18 deletions(-) diff --git a/src/Symfony/Component/Console/CHANGELOG.md b/src/Symfony/Component/Console/CHANGELOG.md index 3952997e64ee0..fdf77cb8a57e7 100644 --- a/src/Symfony/Component/Console/CHANGELOG.md +++ b/src/Symfony/Component/Console/CHANGELOG.md @@ -4,6 +4,7 @@ CHANGELOG 4.0.0 ----- + * `OutputFormatter` throws an exception when unknown options are used * removed `QuestionHelper::setInputStream()/getInputStream()` * removed `Application::getTerminalWidth()/getTerminalHeight()` and `Application::setTerminalDimensions()/getTerminalDimensions()` diff --git a/src/Symfony/Component/Console/Formatter/OutputFormatter.php b/src/Symfony/Component/Console/Formatter/OutputFormatter.php index d32f0915de010..2befd74ea7f8c 100644 --- a/src/Symfony/Component/Console/Formatter/OutputFormatter.php +++ b/src/Symfony/Component/Console/Formatter/OutputFormatter.php @@ -211,13 +211,7 @@ private function createStyleFromString($string) preg_match_all('([^,;]+)', $match[1], $options); $options = array_shift($options); foreach ($options as $option) { - try { - $style->setOption($option); - } catch (\InvalidArgumentException $e) { - @trigger_error(sprintf('Unknown style options are deprecated since version 3.2 and will be removed in 4.0. Exception "%s".', $e->getMessage()), E_USER_DEPRECATED); - - return false; - } + $style->setOption($option); } } else { return false; diff --git a/src/Symfony/Component/Console/Tests/Formatter/OutputFormatterTest.php b/src/Symfony/Component/Console/Tests/Formatter/OutputFormatterTest.php index 4b11028be5e35..05647cd258a72 100644 --- a/src/Symfony/Component/Console/Tests/Formatter/OutputFormatterTest.php +++ b/src/Symfony/Component/Console/Tests/Formatter/OutputFormatterTest.php @@ -193,17 +193,6 @@ public function provideInlineStyleOptionsCases() ); } - /** - * @group legacy - * @dataProvider provideInlineStyleTagsWithUnknownOptions - * @expectedDeprecation Unknown style options are deprecated since version 3.2 and will be removed in 4.0. Exception "Invalid option specified: "%s". Expected one of (bold, underscore, blink, reverse, conceal)". - */ - public function testInlineStyleOptionsUnknownAreDeprecated($tag, $option) - { - $formatter = new OutputFormatter(true); - $formatter->format($tag); - } - public function provideInlineStyleTagsWithUnknownOptions() { return array( From b8c68da0107a4f433dd414a355ea5589da0da0e8 Mon Sep 17 00:00:00 2001 From: Roland Franssen Date: Thu, 25 May 2017 08:46:02 +0200 Subject: [PATCH 0069/1099] [DI] Deprecate XML services without ID --- UPGRADE-3.4.md | 11 +++++--- UPGRADE-4.0.md | 2 ++ .../Resources/config/services.xml | 4 +-- .../DependencyInjection/CHANGELOG.md | 1 + .../Loader/XmlFileLoader.php | 2 ++ .../xml/nested_service_without_id.xml | 10 ++++++++ .../Tests/Fixtures/xml/services28.xml | 2 +- .../Tests/Fixtures/xml/services5.xml | 2 +- .../Fixtures/xml/services_without_id.xml | 11 ++++++++ .../Tests/Loader/XmlFileLoaderTest.php | 25 +++++++++++++++++-- 10 files changed, 61 insertions(+), 9 deletions(-) create mode 100644 src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/nested_service_without_id.xml create mode 100644 src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services_without_id.xml diff --git a/UPGRADE-3.4.md b/UPGRADE-3.4.md index 29a810c8703e5..21db4d1ed6194 100644 --- a/UPGRADE-3.4.md +++ b/UPGRADE-3.4.md @@ -1,15 +1,20 @@ UPGRADE FROM 3.3 to 3.4 ======================= +DependencyInjection +------------------- + + * Top-level anonymous services in XML are deprecated and will throw an exception in Symfony 4.0. + Finder ------ * The `Symfony\Component\Finder\Iterator\FilterIterator` class has been deprecated and will be removed in 4.0 as it used to fix a bug which existed - before version 5.5.23/5.6.7 + before version 5.5.23/5.6.7. Validator --------- - * not setting the `strict` option of the `Choice` constraint to `true` is - deprecated and will throw an exception in Symfony 4.0 + * Not setting the `strict` option of the `Choice` constraint to `true` is + deprecated and will throw an exception in Symfony 4.0. diff --git a/UPGRADE-4.0.md b/UPGRADE-4.0.md index 70c6f8e7e6413..448e7b235a6f5 100644 --- a/UPGRADE-4.0.md +++ b/UPGRADE-4.0.md @@ -128,6 +128,8 @@ DependencyInjection * The ``strict`` attribute in service arguments has been removed. The attribute is ignored since 3.0, so you can simply remove it. + * Top-level anonymous services in XML are no longer supported. + EventDispatcher --------------- diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/services.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/services.xml index 7c935a6bd0198..cecbdf8d85f2a 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/services.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/services.xml @@ -66,12 +66,12 @@ - + - + diff --git a/src/Symfony/Component/DependencyInjection/CHANGELOG.md b/src/Symfony/Component/DependencyInjection/CHANGELOG.md index 6ae0daa20efb7..594d62c0c7336 100644 --- a/src/Symfony/Component/DependencyInjection/CHANGELOG.md +++ b/src/Symfony/Component/DependencyInjection/CHANGELOG.md @@ -5,6 +5,7 @@ CHANGELOG ----- * deprecated the ability to check for the initialization of a private service with the `Container::initialized()` method + * deprecated support for top-level anonymous services in XML 3.3.0 ----- diff --git a/src/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php b/src/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php index 79c8fbf9677ab..78dd38c673754 100644 --- a/src/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php +++ b/src/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php @@ -413,6 +413,8 @@ private function processAnonymousServices(\DOMDocument $xml, $file, $defaults) // anonymous services "in the wild" if (false !== $nodes = $xpath->query('//container:services/container:service[not(@id)]')) { foreach ($nodes as $node) { + @trigger_error(sprintf('Top-level anonymous services are deprecated since Symfony 3.4, the "id" attribute will be required in version 4.0 in %s at line %d.', $file, $node->getLineNo()), E_USER_DEPRECATED); + // give it a unique name $id = sprintf('%d_%s', ++$count, hash('sha256', $file)); $node->setAttribute('id', $id); diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/nested_service_without_id.xml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/nested_service_without_id.xml new file mode 100644 index 0000000000000..f8eb009949943 --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/nested_service_without_id.xml @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services28.xml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services28.xml index 9c3ba9bbb5064..0076cc31ebbf1 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services28.xml +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services28.xml @@ -5,7 +5,7 @@ - + diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services5.xml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services5.xml index 347df977dd26b..721f028287750 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services5.xml +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services5.xml @@ -18,7 +18,7 @@ - + diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services_without_id.xml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services_without_id.xml new file mode 100644 index 0000000000000..afabf3d891d39 --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services_without_id.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/src/Symfony/Component/DependencyInjection/Tests/Loader/XmlFileLoaderTest.php b/src/Symfony/Component/DependencyInjection/Tests/Loader/XmlFileLoaderTest.php index 41d1c48d54bcc..9ffe5793e4764 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Loader/XmlFileLoaderTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Loader/XmlFileLoaderTest.php @@ -230,6 +230,28 @@ public function testLoadAnonymousServices() $this->assertSame($fooArgs[0], $barArgs[0]); } + /** + * @group legacy + * @expectedDeprecation Top-level anonymous services are deprecated since Symfony 3.4, the "id" attribute will be required in version 4.0 in %sservices_without_id.xml at line 4. + */ + public function testLoadAnonymousServicesWithoutId() + { + $container = new ContainerBuilder(); + $loader = new XmlFileLoader($container, new FileLocator(self::$fixturesPath.'/xml')); + $loader->load('services_without_id.xml'); + } + + public function testLoadAnonymousNestedServices() + { + $container = new ContainerBuilder(); + $loader = new XmlFileLoader($container, new FileLocator(self::$fixturesPath.'/xml')); + $loader->load('nested_service_without_id.xml'); + + $this->assertTrue($container->hasDefinition('FooClass')); + $arguments = $container->getDefinition('FooClass')->getArguments(); + $this->assertInstanceOf(Reference::class, array_shift($arguments)); + } + public function testLoadServices() { $container = new ContainerBuilder(); @@ -667,9 +689,8 @@ public function testDefaults() $this->assertSame('service_container', key($definitions)); array_shift($definitions); - $this->assertStringStartsWith('1_', key($definitions)); - $anonymous = current($definitions); + $this->assertSame('bar', key($definitions)); $this->assertTrue($anonymous->isPublic()); $this->assertTrue($anonymous->isAutowired()); $this->assertSame(array('foo' => array(array())), $anonymous->getTags()); From 8425f1b7484c343fd2f332b882aca6132497350f Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Thu, 25 May 2017 10:56:57 +0200 Subject: [PATCH 0070/1099] [Serializer] remove remaining deprecated features --- src/Symfony/Component/Serializer/CHANGELOG.md | 8 ++++++ .../Encoder/SerializerAwareEncoder.php | 27 ------------------- .../Serializer/Encoder/XmlEncoder.php | 6 ++++- .../Normalizer/AbstractNormalizer.php | 5 +++- .../Normalizer/SerializerAwareNormalizer.php | 27 ------------------- .../Component/Serializer/Serializer.php | 14 ---------- 6 files changed, 17 insertions(+), 70 deletions(-) delete mode 100644 src/Symfony/Component/Serializer/Encoder/SerializerAwareEncoder.php delete mode 100644 src/Symfony/Component/Serializer/Normalizer/SerializerAwareNormalizer.php diff --git a/src/Symfony/Component/Serializer/CHANGELOG.md b/src/Symfony/Component/Serializer/CHANGELOG.md index 01c16d00cf2d9..250525d8528f3 100644 --- a/src/Symfony/Component/Serializer/CHANGELOG.md +++ b/src/Symfony/Component/Serializer/CHANGELOG.md @@ -1,6 +1,14 @@ CHANGELOG ========= +4.0.0 +----- + + * removed the `SerializerAwareEncoder` and `SerializerAwareNormalizer` classes, + use the `SerializerAwareTrait` instead + * removed the `Serializer::$normalizerCache` and `Serializer::$denormalizerCache` + properties + 3.3.0 ----- diff --git a/src/Symfony/Component/Serializer/Encoder/SerializerAwareEncoder.php b/src/Symfony/Component/Serializer/Encoder/SerializerAwareEncoder.php deleted file mode 100644 index 873af922ef204..0000000000000 --- a/src/Symfony/Component/Serializer/Encoder/SerializerAwareEncoder.php +++ /dev/null @@ -1,27 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Serializer\Encoder; - -use Symfony\Component\Serializer\SerializerAwareInterface; -use Symfony\Component\Serializer\SerializerAwareTrait; - -/** - * SerializerAware Encoder implementation. - * - * @author Jordi Boggiano - * - * @deprecated since version 3.2, to be removed in 4.0. Use the SerializerAwareTrait instead. - */ -abstract class SerializerAwareEncoder implements SerializerAwareInterface -{ - use SerializerAwareTrait; -} diff --git a/src/Symfony/Component/Serializer/Encoder/XmlEncoder.php b/src/Symfony/Component/Serializer/Encoder/XmlEncoder.php index f52c609d7e77b..9e61c4335dcf0 100644 --- a/src/Symfony/Component/Serializer/Encoder/XmlEncoder.php +++ b/src/Symfony/Component/Serializer/Encoder/XmlEncoder.php @@ -12,6 +12,8 @@ namespace Symfony\Component\Serializer\Encoder; use Symfony\Component\Serializer\Exception\UnexpectedValueException; +use Symfony\Component\Serializer\SerializerAwareInterface; +use Symfony\Component\Serializer\SerializerAwareTrait; /** * Encodes XML data. @@ -21,8 +23,10 @@ * @author Fabian Vogler * @author Kévin Dunglas */ -class XmlEncoder extends SerializerAwareEncoder implements EncoderInterface, DecoderInterface, NormalizationAwareInterface +class XmlEncoder implements EncoderInterface, DecoderInterface, NormalizationAwareInterface, SerializerAwareInterface { + use SerializerAwareTrait; + const FORMAT = 'xml'; /** diff --git a/src/Symfony/Component/Serializer/Normalizer/AbstractNormalizer.php b/src/Symfony/Component/Serializer/Normalizer/AbstractNormalizer.php index e283cbe61f169..a6d4fed210068 100644 --- a/src/Symfony/Component/Serializer/Normalizer/AbstractNormalizer.php +++ b/src/Symfony/Component/Serializer/Normalizer/AbstractNormalizer.php @@ -19,14 +19,17 @@ use Symfony\Component\Serializer\Mapping\AttributeMetadataInterface; use Symfony\Component\Serializer\NameConverter\NameConverterInterface; use Symfony\Component\Serializer\SerializerAwareInterface; +use Symfony\Component\Serializer\SerializerAwareTrait; /** * Normalizer implementation. * * @author Kévin Dunglas */ -abstract class AbstractNormalizer extends SerializerAwareNormalizer implements NormalizerInterface, DenormalizerInterface, SerializerAwareInterface +abstract class AbstractNormalizer implements NormalizerInterface, DenormalizerInterface, SerializerAwareInterface { + use SerializerAwareTrait; + const CIRCULAR_REFERENCE_LIMIT = 'circular_reference_limit'; const OBJECT_TO_POPULATE = 'object_to_populate'; const GROUPS = 'groups'; diff --git a/src/Symfony/Component/Serializer/Normalizer/SerializerAwareNormalizer.php b/src/Symfony/Component/Serializer/Normalizer/SerializerAwareNormalizer.php deleted file mode 100644 index 0480d9ffba98b..0000000000000 --- a/src/Symfony/Component/Serializer/Normalizer/SerializerAwareNormalizer.php +++ /dev/null @@ -1,27 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Serializer\Normalizer; - -use Symfony\Component\Serializer\SerializerAwareTrait; -use Symfony\Component\Serializer\SerializerAwareInterface; - -/** - * SerializerAware Normalizer implementation. - * - * @author Jordi Boggiano - * - * @deprecated since version 3.1, to be removed in 4.0. Use the SerializerAwareTrait instead. - */ -abstract class SerializerAwareNormalizer implements SerializerAwareInterface -{ - use SerializerAwareTrait; -} diff --git a/src/Symfony/Component/Serializer/Serializer.php b/src/Symfony/Component/Serializer/Serializer.php index 36752465ac149..cf6663d7195fd 100644 --- a/src/Symfony/Component/Serializer/Serializer.php +++ b/src/Symfony/Component/Serializer/Serializer.php @@ -54,20 +54,6 @@ class Serializer implements SerializerInterface, NormalizerInterface, Denormaliz */ protected $normalizers = array(); - /** - * @var array - * - * @deprecated since 3.1 will be removed in 4.0 - */ - protected $normalizerCache = array(); - - /** - * @var array - * - * @deprecated since 3.1 will be removed in 4.0 - */ - protected $denormalizerCache = array(); - public function __construct(array $normalizers = array(), array $encoders = array()) { foreach ($normalizers as $normalizer) { From ff77cde0fd2ae06c1bbc25e36def453bdd0b29a3 Mon Sep 17 00:00:00 2001 From: Maxime Steinhausser Date: Thu, 25 May 2017 12:50:57 +0200 Subject: [PATCH 0071/1099] Remove some more PHP < 7.1.3 code --- src/Symfony/Component/HttpFoundation/Request.php | 15 +-------------- src/Symfony/Component/Yaml/Tests/InlineTest.php | 6 +----- 2 files changed, 2 insertions(+), 19 deletions(-) diff --git a/src/Symfony/Component/HttpFoundation/Request.php b/src/Symfony/Component/HttpFoundation/Request.php index 536e110788946..cc489ebdffa36 100644 --- a/src/Symfony/Component/HttpFoundation/Request.php +++ b/src/Symfony/Component/HttpFoundation/Request.php @@ -300,20 +300,7 @@ public function initialize(array $query = array(), array $request = array(), arr */ public static function createFromGlobals() { - // With the php's bug #66606, the php's built-in web server - // stores the Content-Type and Content-Length header values in - // HTTP_CONTENT_TYPE and HTTP_CONTENT_LENGTH fields. - $server = $_SERVER; - if ('cli-server' === PHP_SAPI) { - if (array_key_exists('HTTP_CONTENT_LENGTH', $_SERVER)) { - $server['CONTENT_LENGTH'] = $_SERVER['HTTP_CONTENT_LENGTH']; - } - if (array_key_exists('HTTP_CONTENT_TYPE', $_SERVER)) { - $server['CONTENT_TYPE'] = $_SERVER['HTTP_CONTENT_TYPE']; - } - } - - $request = self::createRequestFromFactory($_GET, $_POST, array(), $_COOKIE, $_FILES, $server); + $request = self::createRequestFromFactory($_GET, $_POST, array(), $_COOKIE, $_FILES, $_SERVER); if (0 === strpos($request->headers->get('CONTENT_TYPE'), 'application/x-www-form-urlencoded') && in_array(strtoupper($request->server->get('REQUEST_METHOD', 'GET')), array('PUT', 'DELETE', 'PATCH')) diff --git a/src/Symfony/Component/Yaml/Tests/InlineTest.php b/src/Symfony/Component/Yaml/Tests/InlineTest.php index b3cfb8075dde3..ed70338644e3e 100644 --- a/src/Symfony/Component/Yaml/Tests/InlineTest.php +++ b/src/Symfony/Component/Yaml/Tests/InlineTest.php @@ -551,11 +551,7 @@ public function testParseNestedTimestampListAsDateTimeObject($yaml, $year, $mont $expected = new \DateTime($yaml); $expected->setTimeZone(new \DateTimeZone('UTC')); $expected->setDate($year, $month, $day); - if (PHP_VERSION_ID >= 70100) { - $expected->setTime($hour, $minute, $second, 1000000 * ($second - (int) $second)); - } else { - $expected->setTime($hour, $minute, $second); - } + $expected->setTime($hour, $minute, $second, 1000000 * ($second - (int) $second)); $expectedNested = array('nested' => array($expected)); $yamlNested = "{nested: [$yaml]}"; From e92232f97dd8230784f24a7efb84db9ae57af556 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Sat, 27 May 2017 12:38:52 +0200 Subject: [PATCH 0072/1099] Add missing var-dumper dep to framework-bundle --- src/Symfony/Bundle/FrameworkBundle/composer.json | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Symfony/Bundle/FrameworkBundle/composer.json b/src/Symfony/Bundle/FrameworkBundle/composer.json index f628c1c6ba0d4..c3005b6f35bba 100644 --- a/src/Symfony/Bundle/FrameworkBundle/composer.json +++ b/src/Symfony/Bundle/FrameworkBundle/composer.json @@ -50,6 +50,7 @@ "symfony/translation": "~3.2|~4.0", "symfony/templating": "~2.8|~3.0|~4.0", "symfony/validator": "~3.3|~4.0", + "symfony/var-dumper": "~3.3|~4.0", "symfony/workflow": "~3.3|~4.0", "symfony/yaml": "~3.2|~4.0", "symfony/property-info": "~3.3|~4.0", From 9045fd9c3cb91818af9e7f812635ecdcdfb08b3d Mon Sep 17 00:00:00 2001 From: Maxime Steinhausser Date: Sat, 27 May 2017 16:22:29 +0200 Subject: [PATCH 0073/1099] [FrameworkBundle] Fix changelog --- src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md b/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md index d59ec4fa63d73..65a97e13d8514 100644 --- a/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md +++ b/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md @@ -14,7 +14,7 @@ CHANGELOG * Removed `cache:clear` warmup part along with the `--no-optional-warmers` option * Removed core form types services registration when unnecessary * Removed `framework.serializer.cache` option and `serializer.mapping.cache.apc`, `serializer.mapping.cache.doctrine.apc` services - * Removed `ConstraintValidatorFactory::$validators` and `ConstraintValidatorFactory::$container` protected properties + * Removed `ConstraintValidatorFactory` * Removed class parameters related to routing * Removed absolute template paths support in the template name parser From 58e733b49eccb98e3286c0e1c0c2ebe3499c0031 Mon Sep 17 00:00:00 2001 From: Tom Panier Date: Mon, 15 May 2017 12:42:47 +0200 Subject: [PATCH 0074/1099] [PropertyInfo] Made ReflectionExtractor's prefix lists instance variables This allows for easier, instance-specific overriding of said values. --- .../Extractor/PhpDocExtractor.php | 30 ++++++- .../Extractor/ReflectionExtractor.php | 48 +++++++--- .../Tests/Extractors/PhpDocExtractorTest.php | 90 +++++++++++++++++++ .../Extractors/ReflectionExtractorTest.php | 50 +++++++++++ 4 files changed, 204 insertions(+), 14 deletions(-) diff --git a/src/Symfony/Component/PropertyInfo/Extractor/PhpDocExtractor.php b/src/Symfony/Component/PropertyInfo/Extractor/PhpDocExtractor.php index e90579efbb570..f9fb721fb8298 100644 --- a/src/Symfony/Component/PropertyInfo/Extractor/PhpDocExtractor.php +++ b/src/Symfony/Component/PropertyInfo/Extractor/PhpDocExtractor.php @@ -53,11 +53,35 @@ class PhpDocExtractor implements PropertyDescriptionExtractorInterface, Property */ private $phpDocTypeHelper; - public function __construct(DocBlockFactoryInterface $docBlockFactory = null) + /** + * @var string[] + */ + private $mutatorPrefixes; + + /** + * @var string[] + */ + private $accessorPrefixes; + + /** + * @var string[] + */ + private $arrayMutatorPrefixes; + + /** + * @param DocBlockFactoryInterface $docBlockFactory + * @param string[]|null $mutatorPrefixes + * @param string[]|null $accessorPrefixes + * @param string[]|null $arrayMutatorPrefixes + */ + public function __construct(DocBlockFactoryInterface $docBlockFactory = null, array $mutatorPrefixes = null, array $accessorPrefixes = null, array $arrayMutatorPrefixes = null) { $this->docBlockFactory = $docBlockFactory ?: DocBlockFactory::createInstance(); $this->contextFactory = new ContextFactory(); $this->phpDocTypeHelper = new PhpDocTypeHelper(); + $this->mutatorPrefixes = null !== $mutatorPrefixes ? $mutatorPrefixes : ReflectionExtractor::$defaultMutatorPrefixes; + $this->accessorPrefixes = null !== $accessorPrefixes ? $accessorPrefixes : ReflectionExtractor::$defaultAccessorPrefixes; + $this->arrayMutatorPrefixes = null !== $arrayMutatorPrefixes ? $arrayMutatorPrefixes : ReflectionExtractor::$defaultArrayMutatorPrefixes; } /** @@ -137,7 +161,7 @@ public function getTypes($class, $property, array $context = array()) return; } - if (!in_array($prefix, ReflectionExtractor::$arrayMutatorPrefixes)) { + if (!in_array($prefix, $this->arrayMutatorPrefixes)) { return $types; } @@ -217,7 +241,7 @@ private function getDocBlockFromProperty($class, $property) */ private function getDocBlockFromMethod($class, $ucFirstProperty, $type) { - $prefixes = $type === self::ACCESSOR ? ReflectionExtractor::$accessorPrefixes : ReflectionExtractor::$mutatorPrefixes; + $prefixes = $type === self::ACCESSOR ? $this->accessorPrefixes : $this->mutatorPrefixes; $prefix = null; foreach ($prefixes as $prefix) { diff --git a/src/Symfony/Component/PropertyInfo/Extractor/ReflectionExtractor.php b/src/Symfony/Component/PropertyInfo/Extractor/ReflectionExtractor.php index 228aa583e8feb..772f975a89114 100644 --- a/src/Symfony/Component/PropertyInfo/Extractor/ReflectionExtractor.php +++ b/src/Symfony/Component/PropertyInfo/Extractor/ReflectionExtractor.php @@ -31,27 +31,53 @@ class ReflectionExtractor implements PropertyListExtractorInterface, PropertyTyp * * @var string[] */ - public static $mutatorPrefixes = array('add', 'remove', 'set'); + public static $defaultMutatorPrefixes = array('add', 'remove', 'set'); /** * @internal * * @var string[] */ - public static $accessorPrefixes = array('is', 'can', 'get'); + public static $defaultAccessorPrefixes = array('is', 'can', 'get'); /** * @internal * * @var string[] */ - public static $arrayMutatorPrefixes = array('add', 'remove'); + public static $defaultArrayMutatorPrefixes = array('add', 'remove'); + /** + * @var bool + */ private $supportsParameterType; - public function __construct() + /** + * @var string[] + */ + private $mutatorPrefixes; + + /** + * @var string[] + */ + private $accessorPrefixes; + + /** + * @var string[] + */ + private $arrayMutatorPrefixes; + + /** + * @param string[]|null $mutatorPrefixes + * @param string[]|null $accessorPrefixes + * @param string[]|null $arrayMutatorPrefixes + */ + public function __construct(array $mutatorPrefixes = null, array $accessorPrefixes = null, array $arrayMutatorPrefixes = null) { $this->supportsParameterType = method_exists('ReflectionParameter', 'getType'); + $this->mutatorPrefixes = null !== $mutatorPrefixes ? $mutatorPrefixes : self::$defaultMutatorPrefixes; + $this->accessorPrefixes = null !== $accessorPrefixes ? $accessorPrefixes : self::$defaultAccessorPrefixes; + $this->arrayMutatorPrefixes = null !== $arrayMutatorPrefixes ? $arrayMutatorPrefixes : self::$defaultArrayMutatorPrefixes; } /** @@ -174,7 +200,7 @@ private function extractFromMutator($class, $property) return; } - if (in_array($prefix, self::$arrayMutatorPrefixes)) { + if (in_array($prefix, $this->arrayMutatorPrefixes)) { $type = new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, new Type(Type::BUILTIN_TYPE_INT), $type); } @@ -266,7 +292,7 @@ private function getAccessorMethod($class, $property) { $ucProperty = ucfirst($property); - foreach (self::$accessorPrefixes as $prefix) { + foreach ($this->accessorPrefixes as $prefix) { try { $reflectionMethod = new \ReflectionMethod($class, $prefix.$ucProperty); if ($reflectionMethod->isStatic()) { @@ -298,9 +324,9 @@ private function getMutatorMethod($class, $property) $ucProperty = ucfirst($property); $ucSingulars = (array) Inflector::singularize($ucProperty); - foreach (self::$mutatorPrefixes as $prefix) { + foreach ($this->mutatorPrefixes as $prefix) { $names = array($ucProperty); - if (in_array($prefix, self::$arrayMutatorPrefixes)) { + if (in_array($prefix, $this->arrayMutatorPrefixes)) { $names = array_merge($names, $ucSingulars); } @@ -332,10 +358,10 @@ private function getMutatorMethod($class, $property) */ private function getPropertyName($methodName, array $reflectionProperties) { - $pattern = implode('|', array_merge(self::$accessorPrefixes, self::$mutatorPrefixes)); + $pattern = implode('|', array_merge($this->accessorPrefixes, $this->mutatorPrefixes)); - if (preg_match('/^('.$pattern.')(.+)$/i', $methodName, $matches)) { - if (!in_array($matches[1], self::$arrayMutatorPrefixes)) { + if ('' !== $pattern && preg_match('/^('.$pattern.')(.+)$/i', $methodName, $matches)) { + if (!in_array($matches[1], $this->arrayMutatorPrefixes)) { return $matches[2]; } diff --git a/src/Symfony/Component/PropertyInfo/Tests/Extractors/PhpDocExtractorTest.php b/src/Symfony/Component/PropertyInfo/Tests/Extractors/PhpDocExtractorTest.php index d0eb3eed06c49..8d1d9ab0ca160 100644 --- a/src/Symfony/Component/PropertyInfo/Tests/Extractors/PhpDocExtractorTest.php +++ b/src/Symfony/Component/PropertyInfo/Tests/Extractors/PhpDocExtractorTest.php @@ -40,6 +40,26 @@ public function testExtract($property, array $type = null, $shortDescription, $l $this->assertSame($longDescription, $this->extractor->getLongDescription('Symfony\Component\PropertyInfo\Tests\Fixtures\Dummy', $property)); } + /** + * @dataProvider typesWithCustomPrefixesProvider + */ + public function testExtractTypesWithCustomPrefixes($property, array $type = null) + { + $customExtractor = new PhpDocExtractor(null, array('add', 'remove'), array('is', 'can')); + + $this->assertEquals($type, $customExtractor->getTypes('Symfony\Component\PropertyInfo\Tests\Fixtures\Dummy', $property)); + } + + /** + * @dataProvider typesWithNoPrefixesProvider + */ + public function testExtractTypesWithNoPrefixes($property, array $type = null) + { + $noPrefixExtractor = new PhpDocExtractor(null, array(), array(), array()); + + $this->assertEquals($type, $noPrefixExtractor->getTypes('Symfony\Component\PropertyInfo\Tests\Fixtures\Dummy', $property)); + } + public function typesProvider() { return array( @@ -75,6 +95,76 @@ public function typesProvider() ); } + public function typesWithCustomPrefixesProvider() + { + return array( + array('foo', null, 'Short description.', 'Long description.'), + array('bar', array(new Type(Type::BUILTIN_TYPE_STRING)), 'This is bar', null), + array('baz', array(new Type(Type::BUILTIN_TYPE_INT)), 'Should be used.', null), + array('foo2', array(new Type(Type::BUILTIN_TYPE_FLOAT)), null, null), + array('foo3', array(new Type(Type::BUILTIN_TYPE_CALLABLE)), null, null), + array('foo4', array(new Type(Type::BUILTIN_TYPE_NULL)), null, null), + array('foo5', null, null, null), + array( + 'files', + array( + new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, new Type(Type::BUILTIN_TYPE_INT), new Type(Type::BUILTIN_TYPE_OBJECT, false, 'SplFileInfo')), + new Type(Type::BUILTIN_TYPE_RESOURCE), + ), + null, + null, + ), + array('bal', array(new Type(Type::BUILTIN_TYPE_OBJECT, false, 'DateTime')), null, null), + array('parent', array(new Type(Type::BUILTIN_TYPE_OBJECT, false, 'Symfony\Component\PropertyInfo\Tests\Fixtures\ParentDummy')), null, null), + array('collection', array(new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, new Type(Type::BUILTIN_TYPE_INT), new Type(Type::BUILTIN_TYPE_OBJECT, false, 'DateTime'))), null, null), + array('a', null, 'A.', null), + array('b', null, 'B.', null), + array('c', array(new Type(Type::BUILTIN_TYPE_BOOL, true)), null, null), + array('d', array(new Type(Type::BUILTIN_TYPE_BOOL)), null, null), + array('e', array(new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, new Type(Type::BUILTIN_TYPE_INT), new Type(Type::BUILTIN_TYPE_RESOURCE))), null, null), + array('f', array(new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, new Type(Type::BUILTIN_TYPE_INT), new Type(Type::BUILTIN_TYPE_OBJECT, false, 'DateTime'))), null, null), + array('g', array(new Type(Type::BUILTIN_TYPE_ARRAY, true, null, true)), 'Nullable array.', null), + array('donotexist', null, null, null), + array('staticGetter', null, null, null), + array('staticSetter', null, null, null), + ); + } + + public function typesWithNoPrefixesProvider() + { + return array( + array('foo', null, 'Short description.', 'Long description.'), + array('bar', array(new Type(Type::BUILTIN_TYPE_STRING)), 'This is bar', null), + array('baz', array(new Type(Type::BUILTIN_TYPE_INT)), 'Should be used.', null), + array('foo2', array(new Type(Type::BUILTIN_TYPE_FLOAT)), null, null), + array('foo3', array(new Type(Type::BUILTIN_TYPE_CALLABLE)), null, null), + array('foo4', array(new Type(Type::BUILTIN_TYPE_NULL)), null, null), + array('foo5', null, null, null), + array( + 'files', + array( + new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, new Type(Type::BUILTIN_TYPE_INT), new Type(Type::BUILTIN_TYPE_OBJECT, false, 'SplFileInfo')), + new Type(Type::BUILTIN_TYPE_RESOURCE), + ), + null, + null, + ), + array('bal', array(new Type(Type::BUILTIN_TYPE_OBJECT, false, 'DateTime')), null, null), + array('parent', array(new Type(Type::BUILTIN_TYPE_OBJECT, false, 'Symfony\Component\PropertyInfo\Tests\Fixtures\ParentDummy')), null, null), + array('collection', array(new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, new Type(Type::BUILTIN_TYPE_INT), new Type(Type::BUILTIN_TYPE_OBJECT, false, 'DateTime'))), null, null), + array('a', null, 'A.', null), + array('b', null, 'B.', null), + array('c', null, null, null), + array('d', null, null, null), + array('e', null, null, null), + array('f', null, null, null), + array('g', array(new Type(Type::BUILTIN_TYPE_ARRAY, true, null, true)), 'Nullable array.', null), + array('donotexist', null, null, null), + array('staticGetter', null, null, null), + array('staticSetter', null, null, null), + ); + } + public function testReturnNullOnEmptyDocBlock() { $this->assertNull($this->extractor->getShortDescription(EmptyDocBlock::class, 'foo')); diff --git a/src/Symfony/Component/PropertyInfo/Tests/Extractors/ReflectionExtractorTest.php b/src/Symfony/Component/PropertyInfo/Tests/Extractors/ReflectionExtractorTest.php index 573528c012f55..5bf5d2e69ab8e 100644 --- a/src/Symfony/Component/PropertyInfo/Tests/Extractors/ReflectionExtractorTest.php +++ b/src/Symfony/Component/PropertyInfo/Tests/Extractors/ReflectionExtractorTest.php @@ -60,6 +60,56 @@ public function testGetProperties() ); } + public function testGetPropertiesWithCustomPrefixes() + { + $customExtractor = new ReflectionExtractor(array('add', 'remove'), array('is', 'can')); + + $this->assertSame( + array( + 'bal', + 'parent', + 'collection', + 'B', + 'Guid', + 'g', + 'foo', + 'foo2', + 'foo3', + 'foo4', + 'foo5', + 'files', + 'c', + 'd', + 'e', + 'f', + ), + $customExtractor->getProperties('Symfony\Component\PropertyInfo\Tests\Fixtures\Dummy') + ); + } + + public function testGetPropertiesWithNoPrefixes() + { + $noPrefixExtractor = new ReflectionExtractor(array(), array(), array()); + + $this->assertSame( + array( + 'bal', + 'parent', + 'collection', + 'B', + 'Guid', + 'g', + 'foo', + 'foo2', + 'foo3', + 'foo4', + 'foo5', + 'files', + ), + $noPrefixExtractor->getProperties('Symfony\Component\PropertyInfo\Tests\Fixtures\Dummy') + ); + } + /** * @dataProvider typesProvider */ From 894f99bfe59fc4d0938f5b42b55f68502c1546d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Thu, 18 May 2017 08:41:42 +0200 Subject: [PATCH 0075/1099] [Serializer] Remove support for deprecated signatures --- src/Symfony/Component/Serializer/CHANGELOG.md | 3 + .../Normalizer/AbstractNormalizer.php | 15 +---- .../Component/Serializer/Serializer.php | 60 ++----------------- .../AbstractObjectNormalizerTest.php | 2 +- 4 files changed, 9 insertions(+), 71 deletions(-) diff --git a/src/Symfony/Component/Serializer/CHANGELOG.md b/src/Symfony/Component/Serializer/CHANGELOG.md index 250525d8528f3..f6b0c892df7e9 100644 --- a/src/Symfony/Component/Serializer/CHANGELOG.md +++ b/src/Symfony/Component/Serializer/CHANGELOG.md @@ -8,6 +8,9 @@ CHANGELOG use the `SerializerAwareTrait` instead * removed the `Serializer::$normalizerCache` and `Serializer::$denormalizerCache` properties + * added an optional `string $format = null` argument to `AbstractNormalizer::instantiateObject` + * added an optional `array $context = array()` to `Serializer::supportsNormalization`, `Serializer::supportsDenormalization`, + `Serializer::supportsEncoding` and `Serializer::supportsDecoding` 3.3.0 ----- diff --git a/src/Symfony/Component/Serializer/Normalizer/AbstractNormalizer.php b/src/Symfony/Component/Serializer/Normalizer/AbstractNormalizer.php index a6d4fed210068..065ea7d720950 100644 --- a/src/Symfony/Component/Serializer/Normalizer/AbstractNormalizer.php +++ b/src/Symfony/Component/Serializer/Normalizer/AbstractNormalizer.php @@ -305,21 +305,8 @@ protected function getConstructor(array &$data, $class, array &$context, \Reflec * * @throws RuntimeException */ - protected function instantiateObject(array &$data, $class, array &$context, \ReflectionClass $reflectionClass, $allowedAttributes/*, string $format = null*/) + protected function instantiateObject(array &$data, $class, array &$context, \ReflectionClass $reflectionClass, $allowedAttributes, string $format = null) { - if (func_num_args() >= 6) { - $format = func_get_arg(5); - } else { - if (__CLASS__ !== get_class($this)) { - $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 3.2.', get_class($this), __FUNCTION__), E_USER_DEPRECATED); - } - } - - $format = null; - } - if ( isset($context[static::OBJECT_TO_POPULATE]) && is_object($context[static::OBJECT_TO_POPULATE]) && diff --git a/src/Symfony/Component/Serializer/Serializer.php b/src/Symfony/Component/Serializer/Serializer.php index cf6663d7195fd..f63c7d5c88e62 100644 --- a/src/Symfony/Component/Serializer/Serializer.php +++ b/src/Symfony/Component/Serializer/Serializer.php @@ -163,42 +163,16 @@ public function denormalize($data, $type, $format = null, array $context = array /** * {@inheritdoc} */ - public function supportsNormalization($data, $format = null/*, array $context = array()*/) + public function supportsNormalization($data, $format = null, array $context = array()) { - if (func_num_args() > 2) { - $context = func_get_arg(2); - } else { - if (__CLASS__ !== get_class($this)) { - $r = new \ReflectionMethod($this, __FUNCTION__); - if (__CLASS__ !== $r->getDeclaringClass()->getName()) { - @trigger_error(sprintf('Method %s() will have a third `$context = array()` argument in version 4.0. Not defining it is deprecated since 3.3.', __METHOD__), E_USER_DEPRECATED); - } - } - - $context = array(); - } - return null !== $this->getNormalizer($data, $format, $context); } /** * {@inheritdoc} */ - public function supportsDenormalization($data, $type, $format = null/*, array $context = array()*/) + public function supportsDenormalization($data, $type, $format = null, array $context = array()) { - if (func_num_args() > 3) { - $context = func_get_arg(3); - } else { - if (__CLASS__ !== get_class($this)) { - $r = new \ReflectionMethod($this, __FUNCTION__); - if (__CLASS__ !== $r->getDeclaringClass()->getName()) { - @trigger_error(sprintf('Method %s() will have a fourth `$context = array()` argument in version 4.0. Not defining it is deprecated since 3.3.', __METHOD__), E_USER_DEPRECATED); - } - } - - $context = array(); - } - return null !== $this->getDenormalizer($data, $type, $format, $context); } @@ -284,42 +258,16 @@ private function denormalizeObject($data, $class, $format, array $context = arra /** * {@inheritdoc} */ - public function supportsEncoding($format/*, array $context = array()*/) + public function supportsEncoding($format, array $context = array()) { - if (func_num_args() > 1) { - $context = func_get_arg(1); - } else { - if (__CLASS__ !== get_class($this)) { - $r = new \ReflectionMethod($this, __FUNCTION__); - if (__CLASS__ !== $r->getDeclaringClass()->getName()) { - @trigger_error(sprintf('Method %s() will have a second `$context = array()` argument in version 4.0. Not defining it is deprecated since 3.3.', __METHOD__), E_USER_DEPRECATED); - } - } - - $context = array(); - } - return $this->encoder->supportsEncoding($format, $context); } /** * {@inheritdoc} */ - public function supportsDecoding($format/*, array $context = array()*/) + public function supportsDecoding($format, array $context = array()) { - if (func_num_args() > 1) { - $context = func_get_arg(1); - } else { - if (__CLASS__ !== get_class($this)) { - $r = new \ReflectionMethod($this, __FUNCTION__); - if (__CLASS__ !== $r->getDeclaringClass()->getName()) { - @trigger_error(sprintf('Method %s() will have a second `$context = array()` argument in version 4.0. Not defining it is deprecated since 3.3.', __METHOD__), E_USER_DEPRECATED); - } - } - - $context = array(); - } - return $this->decoder->supportsDecoding($format, $context); } } diff --git a/src/Symfony/Component/Serializer/Tests/Normalizer/AbstractObjectNormalizerTest.php b/src/Symfony/Component/Serializer/Tests/Normalizer/AbstractObjectNormalizerTest.php index 1040111cfe620..d58d1843cb0d0 100644 --- a/src/Symfony/Component/Serializer/Tests/Normalizer/AbstractObjectNormalizerTest.php +++ b/src/Symfony/Component/Serializer/Tests/Normalizer/AbstractObjectNormalizerTest.php @@ -73,7 +73,7 @@ protected function isAllowedAttribute($classOrObject, $attribute, $format = null return in_array($attribute, array('foo', 'baz')); } - public function instantiateObject(array &$data, $class, array &$context, \ReflectionClass $reflectionClass, $allowedAttributes, $format = null) + public function instantiateObject(array &$data, $class, array &$context, \ReflectionClass $reflectionClass, $allowedAttributes, string $format = null) { return parent::instantiateObject($data, $class, $context, $reflectionClass, $allowedAttributes, $format); } From 84f5de902d0dedfa94f70a1e65124f2bbdd6400c Mon Sep 17 00:00:00 2001 From: Yonel Ceruto Date: Sun, 28 May 2017 19:55:48 -0400 Subject: [PATCH 0076/1099] mix attr options between type-guess options and user options --- src/Symfony/Component/Form/FormFactory.php | 8 +++++++- src/Symfony/Component/Form/Tests/FormFactoryTest.php | 4 ++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Component/Form/FormFactory.php b/src/Symfony/Component/Form/FormFactory.php index ca228ba31db79..34e3666dbd563 100644 --- a/src/Symfony/Component/Form/FormFactory.php +++ b/src/Symfony/Component/Form/FormFactory.php @@ -126,7 +126,13 @@ public function createBuilderForProperty($class, $property, $data = null, array // user options may override guessed options if ($typeGuess) { - $options = array_merge($typeGuess->getOptions(), $options); + $attrs = array(); + $typeGuessOptions = $typeGuess->getOptions(); + if (isset($typeGuessOptions['attr']) && isset($options['attr'])) { + $attrs = array('attr' => array_merge($typeGuessOptions['attr'], $options['attr'])); + } + + $options = array_merge($typeGuessOptions, $options, $attrs); } return $this->createNamedBuilder($property, $type, $data, $options); diff --git a/src/Symfony/Component/Form/Tests/FormFactoryTest.php b/src/Symfony/Component/Form/Tests/FormFactoryTest.php index 4185a4a0025d2..2fcb33bc3ecdb 100644 --- a/src/Symfony/Component/Form/Tests/FormFactoryTest.php +++ b/src/Symfony/Component/Form/Tests/FormFactoryTest.php @@ -450,7 +450,7 @@ public function testOptionsCanBeOverridden() ->with('Application\Author', 'firstName') ->will($this->returnValue(new TypeGuess( 'text', - array('attr' => array('maxlength' => 10)), + array('attr' => array('class' => 'foo', 'maxlength' => 10)), Guess::MEDIUM_CONFIDENCE ))); @@ -458,7 +458,7 @@ public function testOptionsCanBeOverridden() $factory->expects($this->once()) ->method('createNamedBuilder') - ->with('firstName', 'text', null, array('attr' => array('maxlength' => 11))) + ->with('firstName', 'text', null, array('attr' => array('class' => 'foo', 'maxlength' => 11))) ->will($this->returnValue('builderInstance')); $this->builder = $factory->createBuilderForProperty( From e7436af7a6f8915b6a1562255c3ca1516beeebfa Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Mon, 29 May 2017 12:04:03 -0700 Subject: [PATCH 0077/1099] updated CHANGELOG for 2.7.28 --- CHANGELOG-2.7.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/CHANGELOG-2.7.md b/CHANGELOG-2.7.md index 1d1f0984f1988..fb402c9aaf2ca 100644 --- a/CHANGELOG-2.7.md +++ b/CHANGELOG-2.7.md @@ -7,6 +7,20 @@ in 2.7 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/v2.7.0...v2.7.1 +* 2.7.28 (2017-05-29) + + * bug #22847 [Console] ChoiceQuestion must have choices (ro0NL) + * bug #22900 [FrameworkBundle][Console] Fix the override of a command registered by the kernel (aaa2000) + * bug #22910 [Filesystem] improve error handling in lock() (xabbuh) + * bug #22718 [Console] Fixed different behaviour of key and value user inputs in multiple choice question (borNfreee) + * bug #22901 Fix missing abstract key in XmlDumper (weaverryan) + * bug #22817 [PhpUnitBridge] optional error handler arguments (xabbuh) + * bug #22647 [VarDumper] Fix dumping of non-nested stubs (nicolas-grekas) + * bug #22584 [Security] Avoid unnecessary route lookup for empty logout path (ro0NL) + * bug #22690 [Console] Fix errors not rethrown even if not handled by console.error listeners (chalasr) + * bug #22669 [FrameworkBundle] AbstractConfigCommand: do not try registering bundles twice (ogizanagi) + * bug #22676 [FrameworkBundle] Adding the extension XML (flug) + * 2.7.27 (2017-05-01) * bug #22528 [Asset] Starting slash should indicate no basePath wanted (weaverryan) From 1d51bbd3849b9bd645016f6bde37c50da263bfe5 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Mon, 29 May 2017 12:04:10 -0700 Subject: [PATCH 0078/1099] update CONTRIBUTORS for 2.7.28 --- CONTRIBUTORS.md | 51 ++++++++++++++++++++++++++++++++----------------- 1 file changed, 33 insertions(+), 18 deletions(-) diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index 9fe1d4c7e9d50..66212cf3bf4c4 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -24,20 +24,20 @@ Symfony is the result of the work of many people who made the code better - Wouter De Jong (wouterj) - Romain Neutron (romain) - Grégoire Pineau (lyrixx) + - Robin Chalas (chalas_r) - Joseph Bielawski (stloyd) + - Maxime Steinhausser (ogizanagi) - Karma Dordrak (drak) - - Robin Chalas (chalas_r) - Lukas Kahwe Smith (lsmith) - Martin Hasoň (hason) - - Maxime Steinhausser (ogizanagi) - Jeremy Mikola (jmikola) - Jean-François Simon (jfsimon) - Benjamin Eberlei (beberlei) - Igor Wiedler (igorw) - Eriksen Costa (eriksencosta) - Jules Pietri (heah) - - Sarah Khalil (saro0h) - Roland Franssen (ro0) + - Sarah Khalil (saro0h) - Jonathan Wage (jwage) - Guilhem Niot (energetick) - Diego Saint Esteben (dosten) @@ -49,10 +49,10 @@ Symfony is the result of the work of many people who made the code better - Alexander Mols (asm89) - Bulat Shakirzyanov (avalanche123) - Peter Rehm (rpet) + - Iltar van der Berg (kjarli) - Saša Stamenković (umpirsky) - Henrik Bjørnskov (henrikbjorn) - Miha Vrhovnik - - Iltar van der Berg (kjarli) - Diego Saint Esteben (dii3g0) - Konstantin Kudryashov (everzet) - Bilal Amarni (bamarni) @@ -64,8 +64,8 @@ Symfony is the result of the work of many people who made the code better - Michel Weimerskirch (mweimerskirch) - Eric Clemmons (ericclemmons) - Charles Sarrazin (csarrazi) - - Pierre du Plessis (pierredup) - Christian Raue + - Pierre du Plessis (pierredup) - Arnout Boks (aboks) - Deni - Henrik Westphal (snc) @@ -77,12 +77,12 @@ Symfony is the result of the work of many people who made the code better - Lee McDermott - Brandon Turner - Luis Cordova (cordoval) + - Jérémy DERUSSÉ (jderusse) - Graham Campbell (graham) - Daniel Holmes (dholmes) - Toni Uebernickel (havvg) - Bart van den Burg (burgov) - Jordan Alliot (jalliot) - - Jérémy DERUSSÉ (jderusse) - John Wards (johnwards) - Dariusz Ruminski - Fran Moreno (franmomu) @@ -92,8 +92,8 @@ Symfony is the result of the work of many people who made the code better - Arnaud Le Blanc (arnaud-lb) - Maxime STEINHAUSSER - Michal Piotrowski (eventhorizon) - - Tim Nagel (merk) - Issei Murasawa (issei_m) + - Tim Nagel (merk) - Brice BERNARD (brikou) - Alexander M. Turek (derrabus) - Baptiste Clavié (talus) @@ -115,6 +115,7 @@ Symfony is the result of the work of many people who made the code better - Fabien Pennequin (fabienpennequin) - Gordon Franke (gimler) - Eric GELOEN (gelo) + - Yonel Ceruto González (yonelceruto) - Daniel Wehner (dawehner) - Tugdual Saunier (tucksaun) - Théo FIDRY (theofidry) @@ -122,7 +123,6 @@ Symfony is the result of the work of many people who made the code better - Florian Lonqueu-Brochard (florianlb) - Sebastiaan Stok (sstok) - Stefano Sala (stefano.sala) - - Yonel Ceruto González (yonelceruto) - Evgeniy (ewgraf) - Juti Noppornpitak (shiroyuki) - Tigran Azatyan (tigranazatyan) @@ -157,6 +157,7 @@ Symfony is the result of the work of many people who made the code better - Amal Raghav (kertz) - Jonathan Ingram (jonathaningram) - Artur Kotyrba + - David Maicher (dmaicher) - jeremyFreeAgent (Jérémy Romey) (jeremyfreeagent) - James Halsall (jaitsu) - Warnar Boekkooi (boekkooi) @@ -166,6 +167,7 @@ Symfony is the result of the work of many people who made the code better - Possum - Dorian Villet (gnutix) - Richard Miller (mr_r_miller) + - Julien Falque (julienfalque) - Mario A. Alvarez Garcia (nomack84) - Dennis Benkert (denderello) - Benjamin Dulau (dbenjamin) @@ -179,7 +181,6 @@ Symfony is the result of the work of many people who made the code better - Daniel Espendiller - sun (sun) - Larry Garfield (crell) - - Julien Falque (julienfalque) - Martin Schuhfuß (usefulthink) - apetitpa - Matthieu Bontemps (mbontemps) @@ -202,6 +203,7 @@ Symfony is the result of the work of many people who made the code better - Tom Van Looy (tvlooy) - Sven Paulus (subsven) - Rui Marinho (ruimarinho) + - Marek Štípek (maryo) - SpacePossum - Eugene Wissner - Julien Brochet (mewt) @@ -215,7 +217,6 @@ Symfony is the result of the work of many people who made the code better - julien pauli (jpauli) - Lorenz Schori - Sébastien Lavoie (lavoiesl) - - David Maicher (dmaicher) - Francois Zaninotto - Alexander Kotynia (olden) - Daniel Tschinder @@ -252,6 +253,7 @@ Symfony is the result of the work of many people who made the code better - Albert Casademont (acasademont) - Jhonny Lidfors (jhonne) - Diego Agulló (aeoris) + - Andreas Schempp (aschempp) - jdhoek - Pavel Batanov (scaytrase) - Nikita Konstantinov @@ -270,8 +272,8 @@ Symfony is the result of the work of many people who made the code better - Michael Holm (hollo) - Marc Weistroff (futurecat) - Christian Schmidt - - Marek Štípek (maryo) - Hidde Wieringa (hiddewie) + - Chad Sikorra (chadsikorra) - Jordan Samouh (jordansamouh) - Chris Smith (cs278) - Florian Klein (docteurklein) @@ -301,10 +303,10 @@ Symfony is the result of the work of many people who made the code better - Francesc Rosàs (frosas) - Massimiliano Arione (garak) - Julien Galenski (ruian) - - Andreas Schempp (aschempp) - Bongiraud Dominique - janschoenherr - Thomas Schulz (king2500) + - Dariusz Rumiński - Berny Cantos (xphere81) - Ricard Clau (ricardclau) - Mark Challoner (markchalloner) @@ -383,7 +385,6 @@ Symfony is the result of the work of many people who made the code better - Christophe L. (christophelau) - Anthon Pang (robocoder) - Emanuele Gaspari (inmarelibero) - - Dariusz Rumiński - Sébastien Santoro (dereckson) - Brian King - Michel Salib (michelsalib) @@ -400,6 +401,7 @@ Symfony is the result of the work of many people who made the code better - Jan Rosier (rosier) - Thomas Royer (cydonia7) - Josip Kruslin + - Asmir Mustafic (goetas) - vagrant - EdgarPE - Florian Pfitzer (marmelatze) @@ -418,7 +420,6 @@ Symfony is the result of the work of many people who made the code better - Marcin Sikoń (marphi) - Dominik Zogg (dominik.zogg) - Marek Pietrzak - - Chad Sikorra (chadsikorra) - franek (franek) - Christian Wahler - Gintautas Miselis @@ -542,7 +543,6 @@ Symfony is the result of the work of many people who made the code better - Andre Rømcke (andrerom) - Nahuel Cuesta (ncuesta) - Chris Boden (cboden) - - Asmir Mustafic (goetas) - Stefan Gehrig (sgehrig) - Hany el-Kerdany - Wang Jingyu @@ -580,6 +580,7 @@ Symfony is the result of the work of many people who made the code better - Sergey Kolodyazhnyy (skolodyazhnyy) - umpirski - Denis Brumann (dbrumann) + - Michael Babker (mbabker) - Quentin de Longraye (quentinus95) - Chris Heng (gigablah) - Richard Bradley @@ -627,6 +628,7 @@ Symfony is the result of the work of many people who made the code better - twifty - Indra Gunawan (guind) - Peter Ward + - insekticid - Julien DIDIER (juliendidier) - Dominik Ritter (dritter) - Sebastian Grodzicki (sgrodzicki) @@ -743,6 +745,7 @@ Symfony is the result of the work of many people who made the code better - Jan Kramer (jankramer) - abdul malik ikhsan (samsonasik) - Henry Snoek (snoek09) + - Jérémy M (th3mouk) - Simone Di Maulo (toretto460) - Christian Morgan - Alexander Miehe (engerim) @@ -759,6 +762,7 @@ Symfony is the result of the work of many people who made the code better - Douglas Reith (douglas_reith) - Harry Walter (haswalt) - Johnson Page (jwpage) + - Ruben Gonzalez (rubenruateltek) - Michael Roterman (wtfzdotnet) - Arno Geurts - Adán Lobato (adanlobato) @@ -884,6 +888,7 @@ Symfony is the result of the work of many people who made the code better - Eddie Jaoude - Antanas Arvasevicius - Haritz Iturbe (hizai) + - Baptiste Meyer (meyerbaptiste) - Nerijus Arlauskas (nercury) - SPolischook - Diego Sapriza @@ -912,6 +917,7 @@ Symfony is the result of the work of many people who made the code better - Jeremy Bush - wizhippo - Viacheslav Sychov + - Tyson Andre - Carlos Ortega Huetos - rpg600 - Péter Buri (burci) @@ -1012,6 +1018,7 @@ Symfony is the result of the work of many people who made the code better - Conrad Kleinespel - Sebastian Utz - Adrien Gallou (agallou) + - Maks Rafalko (bornfree) - Karol Sójko (karolsojko) - Grzegorz Zdanowski (kiler129) - sl_toto (sl_toto) @@ -1046,7 +1053,6 @@ Symfony is the result of the work of many people who made the code better - Kim Laï Trinh - Jason Desrosiers - m.chwedziak - - insekticid - Philip Frank - Lance McNearney - Giorgio Premi @@ -1056,6 +1062,7 @@ Symfony is the result of the work of many people who made the code better - Alberto Pirovano (geezmo) - Pete Mitchell (peterjmit) - Tom Corrigan (tomcorrigan) + - adev - Luis Galeas - Martin Pärtel - George Mponos (gmponos) @@ -1224,6 +1231,7 @@ Symfony is the result of the work of many people who made the code better - Romain Dorgueil - Grayson Koonce (breerly) - Fabien LUCAS (flucas2) + - Indra Gunawan (indragunawan) - Karim Cassam Chenaï (ka) - Nicolas Bastien (nicolas_bastien) - Denis (yethee) @@ -1271,6 +1279,7 @@ Symfony is the result of the work of many people who made the code better - Daan van Renterghem - Nicole Cordes - Bram Van der Sype (brammm) + - Christopher Hertel (chertel) - Guile (guile) - Julien Moulin (lizjulien) - Mauro Foti (skler) @@ -1289,6 +1298,7 @@ Symfony is the result of the work of many people who made the code better - Johann Pardanaud - Trevor Suarez - gedrox + - Alan Bondarchuk - dropfen - Andrey Chernykh - Edvinas Klovas @@ -1301,6 +1311,7 @@ Symfony is the result of the work of many people who made the code better - bertillon - Bertalan Attila - Yannick Bensacq (cibou) + - Gawain Lynch (gawain) - Luca Genuzio (genuzio) - Hans Nilsson (hansnilsson) - Andrew Marcinkevičius (ifdattic) @@ -1310,7 +1321,6 @@ Symfony is the result of the work of many people who made the code better - Dan Patrick (mdpatrick) - Rares Vlaseanu (raresvla) - tante kinast (tante) - - Jérémy M (th3mouk) - Vincent LEFORT (vlefort) - Sadicov Vladimir (xtech) - Kevin EMO (zarcox) @@ -1334,7 +1344,6 @@ Symfony is the result of the work of many people who made the code better - Jonny Schmid (schmidjon) - Götz Gottwald - Veres Lajos - - Michael Babker - grifx - Robert Campbell - Matt Lehner @@ -1413,9 +1422,11 @@ Symfony is the result of the work of many people who made the code better - Yanick Witschi - Ondrej Mirtes - akimsko + - Ben Scott - Youpie - srsbiz - Taylan Kasap + - Michael Orlitzky - Nicolas A. Bérard-Nault - Saem Ghani - Stefan Oderbolz @@ -1428,6 +1439,7 @@ Symfony is the result of the work of many people who made the code better - Ben - Evgeniy Tetenchuk - dasmfm + - Mathias Geat - Arnaud Buathier (arnapou) - chesteroni (chesteroni) - Mauricio Lopez (diaspar) @@ -1514,6 +1526,7 @@ Symfony is the result of the work of many people who made the code better - Abdulkadir N. A. - Yevgen Kovalienia - Lebnik + - Ondřej Führer - Sema - Elan Ruusamäe - Thorsten Hallwas @@ -1566,6 +1579,7 @@ Symfony is the result of the work of many people who made the code better - Bill Hance (billhance) - Bernd Matzner (bmatzner) - Bram Tweedegolf (bram_tweedegolf) + - Brandon Kelly (brandonkelly) - Choong Wei Tjeng (choonge) - Kousuke Ebihara (co3k) - Loïc Vernet (coil) @@ -1673,6 +1687,7 @@ Symfony is the result of the work of many people who made the code better - Andrew Carter (andrewcarteruk) - Adam Elsodaney (archfizz) - Daniel Kolvik (dkvk) + - Marc Lemay (flug) - Jeroen De Dauw (jeroendedauw) - Maxime COLIN (maximecolin) - Muharrem Demirci (mdemirci) From a13a17ad0444bab920122c2cb2e54b12173f2227 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Mon, 29 May 2017 12:04:18 -0700 Subject: [PATCH 0079/1099] updated VERSION for 2.7.28 --- 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 1c1928825025c..05f6dc29223ce 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -58,12 +58,12 @@ abstract class Kernel implements KernelInterface, TerminableInterface protected $startTime; protected $loadClassCache; - const VERSION = '2.7.28-DEV'; + const VERSION = '2.7.28'; const VERSION_ID = 20728; const MAJOR_VERSION = 2; const MINOR_VERSION = 7; const RELEASE_VERSION = 28; - const EXTRA_VERSION = 'DEV'; + const EXTRA_VERSION = ''; const END_OF_MAINTENANCE = '05/2018'; const END_OF_LIFE = '05/2019'; From aa04f35092de3ebecbf75963adf2dfd9aeead80a Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Mon, 29 May 2017 12:14:01 -0700 Subject: [PATCH 0080/1099] bumped Symfony version to 2.7.29 --- 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 05f6dc29223ce..4bbd67b1e5ef3 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -58,12 +58,12 @@ abstract class Kernel implements KernelInterface, TerminableInterface protected $startTime; protected $loadClassCache; - const VERSION = '2.7.28'; - const VERSION_ID = 20728; + const VERSION = '2.7.29-DEV'; + const VERSION_ID = 20729; const MAJOR_VERSION = 2; const MINOR_VERSION = 7; - const RELEASE_VERSION = 28; - const EXTRA_VERSION = ''; + const RELEASE_VERSION = 29; + const EXTRA_VERSION = 'DEV'; const END_OF_MAINTENANCE = '05/2018'; const END_OF_LIFE = '05/2019'; From 1140ae19308c87610e1686db8dbe5384860328d6 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Mon, 29 May 2017 12:14:50 -0700 Subject: [PATCH 0081/1099] updated CHANGELOG for 2.8.21 --- CHANGELOG-2.8.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/CHANGELOG-2.8.md b/CHANGELOG-2.8.md index 52328ef28f5c3..b73a0f1a2b18b 100644 --- a/CHANGELOG-2.8.md +++ b/CHANGELOG-2.8.md @@ -7,6 +7,21 @@ in 2.8 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/v2.8.0...v2.8.1 +* 2.8.21 (2017-05-29) + + * bug #22847 [Console] ChoiceQuestion must have choices (ro0NL) + * bug #22900 [FrameworkBundle][Console] Fix the override of a command registered by the kernel (aaa2000) + * bug #22910 [Filesystem] improve error handling in lock() (xabbuh) + * bug #22718 [Console] Fixed different behaviour of key and value user inputs in multiple choice question (borNfreee) + * bug #22901 Fix missing abstract key in XmlDumper (weaverryan) + * bug #22817 [PhpUnitBridge] optional error handler arguments (xabbuh) + * bug #22752 Improved how profiler errors are displayed on small screens (javiereguiluz) + * bug #22647 [VarDumper] Fix dumping of non-nested stubs (nicolas-grekas) + * bug #22584 [Security] Avoid unnecessary route lookup for empty logout path (ro0NL) + * bug #22690 [Console] Fix errors not rethrown even if not handled by console.error listeners (chalasr) + * bug #22669 [FrameworkBundle] AbstractConfigCommand: do not try registering bundles twice (ogizanagi) + * bug #22676 [FrameworkBundle] Adding the extension XML (flug) + * 2.8.20 (2017-05-01) * bug #22550 Allow Upper Case property names in ObjectNormalizer (insekticid) From ecf57807c8110681f4a599bc2e3b028d38a6b336 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Mon, 29 May 2017 12:14:58 -0700 Subject: [PATCH 0082/1099] updated VERSION for 2.8.21 --- 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 51417f5dcbf32..86be16e14e70e 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -59,12 +59,12 @@ abstract class Kernel implements KernelInterface, TerminableInterface protected $startTime; protected $loadClassCache; - const VERSION = '2.8.21-DEV'; + const VERSION = '2.8.21'; const VERSION_ID = 20821; const MAJOR_VERSION = 2; const MINOR_VERSION = 8; const RELEASE_VERSION = 21; - const EXTRA_VERSION = 'DEV'; + const EXTRA_VERSION = ''; const END_OF_MAINTENANCE = '11/2018'; const END_OF_LIFE = '11/2019'; From af6b25b28c0b6d9cd528503ae3f8d845b3028052 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Mon, 29 May 2017 12:30:05 -0700 Subject: [PATCH 0083/1099] bumped Symfony version to 2.8.22 --- 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 86be16e14e70e..545c27b0366dc 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -59,12 +59,12 @@ abstract class Kernel implements KernelInterface, TerminableInterface protected $startTime; protected $loadClassCache; - const VERSION = '2.8.21'; - const VERSION_ID = 20821; + const VERSION = '2.8.22-DEV'; + const VERSION_ID = 20822; const MAJOR_VERSION = 2; const MINOR_VERSION = 8; - const RELEASE_VERSION = 21; - const EXTRA_VERSION = ''; + const RELEASE_VERSION = 22; + const EXTRA_VERSION = 'DEV'; const END_OF_MAINTENANCE = '11/2018'; const END_OF_LIFE = '11/2019'; From 17fd48cdfe73e83b499ad82c9cb13422074d1e30 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Mon, 29 May 2017 12:31:58 -0700 Subject: [PATCH 0084/1099] updated CHANGELOG for 3.2.9 --- CHANGELOG-3.2.md | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/CHANGELOG-3.2.md b/CHANGELOG-3.2.md index c76c8add66003..de1e0fd980928 100644 --- a/CHANGELOG-3.2.md +++ b/CHANGELOG-3.2.md @@ -7,6 +7,29 @@ in 3.2 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.2.0...v3.2.1 +* 3.2.9 (2017-05-29) + + * bug #22847 [Console] ChoiceQuestion must have choices (ro0NL) + * bug #22900 [FrameworkBundle][Console] Fix the override of a command registered by the kernel (aaa2000) + * bug #22910 [Filesystem] improve error handling in lock() (xabbuh) + * bug #22924 [Cache] Dont use pipelining with RedisCluster (nicolas-grekas) + * bug #22718 [Console] Fixed different behaviour of key and value user inputs in multiple choice question (borNfreee) + * bug #22829 [Yaml] fix colon without space deprecation (xabbuh) + * bug #22901 Fix missing abstract key in XmlDumper (weaverryan) + * bug #22912 [DI] Avoid private call to Container::has() (ro0NL) + * bug #22866 [DI] Check for privates before shared services (ro0NL) + * bug #22874 [WebProfilerBundle] Fix sub-requests display in time profiler panel (nicolas-grekas) + * bug #22817 [PhpUnitBridge] optional error handler arguments (xabbuh) + * bug #22752 Improved how profiler errors are displayed on small screens (javiereguiluz) + * bug #22715 [FrameworkBundle] remove Security deps from the require section (xabbuh) + * bug #22647 [VarDumper] Fix dumping of non-nested stubs (nicolas-grekas) + * bug #22409 [Yaml] respect inline level when dumping objects as maps (goetas, xabbuh) + * bug #22584 [Security] Avoid unnecessary route lookup for empty logout path (ro0NL) + * bug #22690 [Console] Fix errors not rethrown even if not handled by console.error listeners (chalasr) + * bug #22669 [FrameworkBundle] AbstractConfigCommand: do not try registering bundles twice (ogizanagi) + * bug #22676 [FrameworkBundle] Adding the extension XML (flug) + * bug #22652 [Workflow] Move twig extension registration to twig bundle (ogizanagi) + * 3.2.8 (2017-05-01) * bug #22550 Allow Upper Case property names in ObjectNormalizer (insekticid) From a948880ecbd2660a73bb17c7ec0e7374ffca5df9 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Mon, 29 May 2017 12:32:04 -0700 Subject: [PATCH 0085/1099] updated VERSION for 3.2.9 --- 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 ddfe322cc2853..af4fcaa4f30eb 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -58,12 +58,12 @@ abstract class Kernel implements KernelInterface, TerminableInterface protected $startTime; protected $loadClassCache; - const VERSION = '3.2.9-DEV'; + const VERSION = '3.2.9'; const VERSION_ID = 30209; const MAJOR_VERSION = 3; const MINOR_VERSION = 2; const RELEASE_VERSION = 9; - const EXTRA_VERSION = 'DEV'; + const EXTRA_VERSION = ''; const END_OF_MAINTENANCE = '07/2017'; const END_OF_LIFE = '01/2018'; From 17deeaf42e9809a563947d7a1c709b8e10035d6c Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Mon, 29 May 2017 13:10:37 -0700 Subject: [PATCH 0086/1099] bumped Symfony version to 3.2.10 --- 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 af4fcaa4f30eb..4b849b8133062 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -58,12 +58,12 @@ abstract class Kernel implements KernelInterface, TerminableInterface protected $startTime; protected $loadClassCache; - const VERSION = '3.2.9'; - const VERSION_ID = 30209; + const VERSION = '3.2.10-DEV'; + const VERSION_ID = 30210; const MAJOR_VERSION = 3; const MINOR_VERSION = 2; - const RELEASE_VERSION = 9; - const EXTRA_VERSION = ''; + const RELEASE_VERSION = 10; + const EXTRA_VERSION = 'DEV'; const END_OF_MAINTENANCE = '07/2017'; const END_OF_LIFE = '01/2018'; From adc39a2f57fcfd85ed46b8938c6ea2a4f4c1f129 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Mon, 29 May 2017 14:23:02 -0700 Subject: [PATCH 0087/1099] bumped Symfony version to 3.3.1 --- src/Symfony/Component/HttpKernel/Kernel.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Symfony/Component/HttpKernel/Kernel.php b/src/Symfony/Component/HttpKernel/Kernel.php index e2f1df0351ad0..c9724c61f9ab9 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -61,12 +61,12 @@ abstract class Kernel implements KernelInterface, TerminableInterface private $projectDir; - const VERSION = '3.3.0'; - const VERSION_ID = 30300; + const VERSION = '3.3.1-DEV'; + const VERSION_ID = 30301; const MAJOR_VERSION = 3; const MINOR_VERSION = 3; - const RELEASE_VERSION = 0; - const EXTRA_VERSION = ''; + const RELEASE_VERSION = 1; + const EXTRA_VERSION = 'DEV'; const END_OF_MAINTENANCE = '01/2018'; const END_OF_LIFE = '07/2018'; From 65297de3aa44953ca39243fd3b713d4a83a20900 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Kurzeja?= Date: Tue, 30 May 2017 10:18:53 +0200 Subject: [PATCH 0088/1099] #22839 - changed debug toolbar dump section to relative and use full window width --- .../Resources/views/Profiler/toolbar.css.twig | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/toolbar.css.twig b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/toolbar.css.twig index 22a11b03a4361..7a2d92e134a5f 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/toolbar.css.twig +++ b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/toolbar.css.twig @@ -350,6 +350,15 @@ 100% { background: #222; } } +.sf-toolbar-block.sf-toolbar-block-dump { + position: static; +} + +.sf-toolbar-block.sf-toolbar-block-dump .sf-toolbar-info { + max-width: none; + right: 0; +} + .sf-toolbar-block-dump pre.sf-dump { background-color: #222; border-color: #777; From ff6151b15f69b5b519cf10d675a9cc6b085af97b Mon Sep 17 00:00:00 2001 From: Maxime Steinhausser Date: Tue, 30 May 2017 18:27:31 +0200 Subject: [PATCH 0089/1099] [Profiler] Fix text selection on exception pages --- .../Bundle/TwigBundle/Resources/views/base_js.html.twig | 5 +++++ .../Bundle/TwigBundle/Resources/views/exception.css.twig | 1 - .../Resources/views/Profiler/base_js.html.twig | 5 +++++ src/Symfony/Component/Debug/ExceptionHandler.php | 1 - 4 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Bundle/TwigBundle/Resources/views/base_js.html.twig b/src/Symfony/Bundle/TwigBundle/Resources/views/base_js.html.twig index d85d2e0ea32ae..337c40898697f 100644 --- a/src/Symfony/Bundle/TwigBundle/Resources/views/base_js.html.twig +++ b/src/Symfony/Bundle/TwigBundle/Resources/views/base_js.html.twig @@ -478,6 +478,11 @@ addEventListener(toggles[i], 'click', function(e) { e.preventDefault(); + if ('' !== window.getSelection().toString()) { + /* Don't do anything on text selection */ + return; + } + var toggle = e.target || e.srcElement; /* needed because when the toggle contains HTML contents, user can click */ diff --git a/src/Symfony/Bundle/TwigBundle/Resources/views/exception.css.twig b/src/Symfony/Bundle/TwigBundle/Resources/views/exception.css.twig index 4f553f20df5e9..1c8c76e78db4a 100644 --- a/src/Symfony/Bundle/TwigBundle/Resources/views/exception.css.twig +++ b/src/Symfony/Bundle/TwigBundle/Resources/views/exception.css.twig @@ -89,7 +89,6 @@ header .container { display: flex; justify-content: space-between; } .exception-illustration { flex-basis: 111px; flex-shrink: 0; height: 66px; margin-left: 15px; opacity: .7; } .trace + .trace { margin-top: 30px; } -.trace-head { -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; } .trace-head .trace-class { color: #222; font-size: 18px; font-weight: bold; line-height: 1.3; margin: 0; position: relative; } .trace-head .trace-namespace { color: #999; display: block; font-size: 13px; } .trace-head .icon { position: absolute; right: 0; top: 0; } diff --git a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/base_js.html.twig b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/base_js.html.twig index 79da38a230f01..abdf19d0fa5f6 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/base_js.html.twig +++ b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/base_js.html.twig @@ -478,6 +478,11 @@ addEventListener(toggles[i], 'click', function(e) { e.preventDefault(); + if ('' !== window.getSelection().toString()) { + /* Don't do anything on text selection */ + return; + } + var toggle = e.target || e.srcElement; /* needed because when the toggle contains HTML contents, user can click */ diff --git a/src/Symfony/Component/Debug/ExceptionHandler.php b/src/Symfony/Component/Debug/ExceptionHandler.php index 1fe60d9f31e69..5c399ef089e3b 100644 --- a/src/Symfony/Component/Debug/ExceptionHandler.php +++ b/src/Symfony/Component/Debug/ExceptionHandler.php @@ -316,7 +316,6 @@ public function getStylesheet(FlattenException $exception) .exception-illustration { flex-basis: 111px; flex-shrink: 0; height: 66px; margin-left: 15px; opacity: .7; } .trace + .trace { margin-top: 30px; } - .trace-head { -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; } .trace-head .trace-class { color: #222; font-size: 18px; font-weight: bold; line-height: 1.3; margin: 0; position: relative; } .trace-message { font-size: 14px; font-weight: normal; margin: .5em 0 0; } From 8618399e4264d810aecb33e33edbf628a71cf913 Mon Sep 17 00:00:00 2001 From: Maxime Steinhausser Date: Wed, 31 May 2017 01:27:40 +0200 Subject: [PATCH 0090/1099] [Profiler] Fix clicking on links inside toggle --- .../Bundle/TwigBundle/Resources/views/base_js.html.twig | 8 ++++++++ .../Resources/views/Profiler/base_js.html.twig | 8 ++++++++ 2 files changed, 16 insertions(+) diff --git a/src/Symfony/Bundle/TwigBundle/Resources/views/base_js.html.twig b/src/Symfony/Bundle/TwigBundle/Resources/views/base_js.html.twig index 337c40898697f..4ce8013c4463a 100644 --- a/src/Symfony/Bundle/TwigBundle/Resources/views/base_js.html.twig +++ b/src/Symfony/Bundle/TwigBundle/Resources/views/base_js.html.twig @@ -512,6 +512,14 @@ var altContent = toggle.getAttribute('data-toggle-alt-content'); toggle.innerHTML = currentContent !== altContent ? altContent : originalContent; }); + + /* Prevents from disallowing clicks on links inside toggles */ + var toggleLinks = document.querySelectorAll('.sf-toggle a'); + for (var i = 0; i < toggleLinks.length; i++) { + addEventListener(toggleLinks[i], 'click', function(e) { + e.stopPropagation(); + }); + } } } }; diff --git a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/base_js.html.twig b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/base_js.html.twig index abdf19d0fa5f6..b5f08f869168d 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/base_js.html.twig +++ b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/base_js.html.twig @@ -513,6 +513,14 @@ toggle.innerHTML = currentContent !== altContent ? altContent : originalContent; }); } + + /* Prevents from disallowing clicks on links inside toggles */ + var toggleLinks = document.querySelectorAll('.sf-toggle a'); + for (var i = 0; i < toggleLinks.length; i++) { + addEventListener(toggleLinks[i], 'click', function(e) { + e.stopPropagation(); + }); + } } }; })(); From c9a86511af55bdf15f3f0060c0bd91c77e5c2794 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Wed, 31 May 2017 08:30:26 +0200 Subject: [PATCH 0091/1099] [Lock] Remove useless dependency to symfony/polyfill-php70 --- src/Symfony/Component/Lock/composer.json | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Symfony/Component/Lock/composer.json b/src/Symfony/Component/Lock/composer.json index a4f947de4d1ca..e9ba36de5f95f 100644 --- a/src/Symfony/Component/Lock/composer.json +++ b/src/Symfony/Component/Lock/composer.json @@ -17,7 +17,6 @@ ], "require": { "php": "^7.1.3", - "symfony/polyfill-php70": "~1.0", "psr/log": "~1.0" }, "require-dev": { From 28e615a656548cbedcdd3760423d7948e6fe656e Mon Sep 17 00:00:00 2001 From: Robin Chalas Date: Tue, 30 May 2017 14:30:58 +0200 Subject: [PATCH 0092/1099] Fix decorating TagAware adapters in dev --- .../Compiler/CacheCollectorPass.php | 7 ++-- .../Cache/Adapter/TraceableAdapter.php | 4 +-- .../Adapter/TraceableTagAwareAdapter.php | 36 +++++++++++++++++++ .../Adapter/TraceableTagAwareAdapterTest.php | 34 ++++++++++++++++++ 4 files changed, 77 insertions(+), 4 deletions(-) create mode 100644 src/Symfony/Component/Cache/Adapter/TraceableTagAwareAdapter.php create mode 100644 src/Symfony/Component/Cache/Tests/Adapter/TraceableTagAwareAdapterTest.php diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/CacheCollectorPass.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/CacheCollectorPass.php index 3d1908bf9bc92..a4b89144ef717 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/CacheCollectorPass.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/CacheCollectorPass.php @@ -11,7 +11,9 @@ namespace Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler; +use Symfony\Component\Cache\Adapter\TagAwareAdapterInterface; use Symfony\Component\Cache\Adapter\TraceableAdapter; +use Symfony\Component\Cache\Adapter\TraceableTagAwareAdapter; use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Reference; @@ -34,11 +36,12 @@ public function process(ContainerBuilder $container) $collectorDefinition = $container->getDefinition('data_collector.cache'); foreach ($container->findTaggedServiceIds('cache.pool') as $id => $attributes) { - if ($container->getDefinition($id)->isAbstract()) { + $definition = $container->getDefinition($id); + if ($definition->isAbstract()) { continue; } - $container->register($id.'.recorder', TraceableAdapter::class) + $container->register($id.'.recorder', is_subclass_of($definition->getClass(), TagAwareAdapterInterface::class) ? TraceableTagAwareAdapter::class : TraceableAdapter::class) ->setDecoratedService($id) ->addArgument(new Reference($id.'.recorder.inner')) ->setPublic(false); diff --git a/src/Symfony/Component/Cache/Adapter/TraceableAdapter.php b/src/Symfony/Component/Cache/Adapter/TraceableAdapter.php index d813c61ad9038..1ddf65b3015e2 100644 --- a/src/Symfony/Component/Cache/Adapter/TraceableAdapter.php +++ b/src/Symfony/Component/Cache/Adapter/TraceableAdapter.php @@ -22,7 +22,7 @@ */ class TraceableAdapter implements AdapterInterface { - private $pool; + protected $pool; private $calls = array(); public function __construct(AdapterInterface $pool) @@ -177,7 +177,7 @@ public function getCalls() } } - private function start($name) + protected function start($name) { $this->calls[] = $event = new TraceableAdapterEvent(); $event->name = $name; diff --git a/src/Symfony/Component/Cache/Adapter/TraceableTagAwareAdapter.php b/src/Symfony/Component/Cache/Adapter/TraceableTagAwareAdapter.php new file mode 100644 index 0000000000000..de68955d8e56d --- /dev/null +++ b/src/Symfony/Component/Cache/Adapter/TraceableTagAwareAdapter.php @@ -0,0 +1,36 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache\Adapter; + +/** + * @author Robin Chalas + */ +class TraceableTagAwareAdapter extends TraceableAdapter implements TagAwareAdapterInterface +{ + public function __construct(TagAwareAdapterInterface $pool) + { + parent::__construct($pool); + } + + /** + * {@inheritdoc} + */ + public function invalidateTags(array $tags) + { + $event = $this->start(__FUNCTION__); + try { + return $event->result = $this->pool->invalidateTags($tags); + } finally { + $event->end = microtime(true); + } + } +} diff --git a/src/Symfony/Component/Cache/Tests/Adapter/TraceableTagAwareAdapterTest.php b/src/Symfony/Component/Cache/Tests/Adapter/TraceableTagAwareAdapterTest.php new file mode 100644 index 0000000000000..38f3c6c087dfc --- /dev/null +++ b/src/Symfony/Component/Cache/Tests/Adapter/TraceableTagAwareAdapterTest.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\Component\Cache\Tests\Adapter; + +use Symfony\Component\Cache\Adapter\FilesystemAdapter; +use Symfony\Component\Cache\Adapter\TagAwareAdapter; +use Symfony\Component\Cache\Adapter\TraceableTagAwareAdapter; + +class TraceableTagAwareAdapterTest extends TraceableAdapterTest +{ + public function testInvalidateTags() + { + $pool = new TraceableTagAwareAdapter(new TagAwareAdapter(new FilesystemAdapter())); + $pool->invalidateTags(array('foo')); + $calls = $pool->getCalls(); + $this->assertCount(1, $calls); + + $call = $calls[0]; + $this->assertSame('invalidateTags', $call->name); + $this->assertSame(0, $call->hits); + $this->assertSame(0, $call->misses); + $this->assertNotEmpty($call->start); + $this->assertNotEmpty($call->end); + } +} From c5b9c1a8c81d36bffec8a957de9aa58bcb2f52c0 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Wed, 31 May 2017 10:22:24 +0200 Subject: [PATCH 0093/1099] [Config] Allow empty globs --- .../Component/Config/Loader/FileLoader.php | 17 +++++++++++------ .../Config/Tests/Loader/FileLoaderTest.php | 16 ++++++++++++++++ 2 files changed, 27 insertions(+), 6 deletions(-) diff --git a/src/Symfony/Component/Config/Loader/FileLoader.php b/src/Symfony/Component/Config/Loader/FileLoader.php index d3fe0eacfc0d9..02aa811fc5497 100644 --- a/src/Symfony/Component/Config/Loader/FileLoader.php +++ b/src/Symfony/Component/Config/Loader/FileLoader.php @@ -83,13 +83,18 @@ public function getLocator() */ public function import($resource, $type = null, $ignoreErrors = false, $sourceResource = null) { - if (is_string($resource) && false !== strpbrk($resource, '*?{[')) { + if (is_string($resource) && strlen($resource) !== $i = strcspn($resource, '*?{[')) { $ret = array(); - foreach ($this->glob($resource, false, $_, true) as $path => $info) { - $ret[] = $this->doImport($path, $type, $ignoreErrors, $sourceResource); + $isSubpath = 0 !== $i && false !== strpos(substr($resource, 0, $i), '/'); + foreach ($this->glob($resource, false, $_, $ignoreErrors || !$isSubpath) as $path => $info) { + if (null !== $res = $this->doImport($path, $type, $ignoreErrors, $sourceResource)) { + $ret[] = $res; + } + $isSubpath = true; } - if ($ret) { - return count($ret) > 1 ? $ret : $ret[0]; + + if ($isSubpath) { + return isset($ret[1]) ? $ret : (isset($ret[0]) ? $ret[0] : null); } } @@ -104,7 +109,7 @@ protected function glob($pattern, $recursive, &$resource = null, $ignoreErrors = if (strlen($pattern) === $i = strcspn($pattern, '*?{[')) { $prefix = $pattern; $pattern = ''; - } elseif (0 === $i) { + } elseif (0 === $i || false === strpos(substr($pattern, 0, $i), '/')) { $prefix = '.'; $pattern = '/'.$pattern; } else { diff --git a/src/Symfony/Component/Config/Tests/Loader/FileLoaderTest.php b/src/Symfony/Component/Config/Tests/Loader/FileLoaderTest.php index 59b625525bff1..c6e283c74919b 100644 --- a/src/Symfony/Component/Config/Tests/Loader/FileLoaderTest.php +++ b/src/Symfony/Component/Config/Tests/Loader/FileLoaderTest.php @@ -12,6 +12,7 @@ namespace Symfony\Component\Config\Tests\Loader; use PHPUnit\Framework\TestCase; +use Symfony\Component\Config\FileLocator; use Symfony\Component\Config\Loader\FileLoader; use Symfony\Component\Config\Loader\LoaderResolver; @@ -74,6 +75,21 @@ public function testImportWithGlobLikeResource() $this->assertSame('[foo]', $loader->import('[foo]')); } + + public function testImportWithNoGlobMatch() + { + $locatorMock = $this->getMockBuilder('Symfony\Component\Config\FileLocatorInterface')->getMock(); + $loader = new TestFileLoader($locatorMock); + + $this->assertNull($loader->import('./*.abc')); + } + + public function testImportWithSimpleGlob() + { + $loader = new TestFileLoader(new FileLocator(__DIR__)); + + $this->assertSame(__FILE__, strtr($loader->import('FileLoaderTest.*'), '/', DIRECTORY_SEPARATOR)); + } } class TestFileLoader extends FileLoader From 8c3c0fe65e3d61379e14f2dd1f63f6a951d528b6 Mon Sep 17 00:00:00 2001 From: Dariusz Date: Wed, 31 May 2017 11:30:46 +0200 Subject: [PATCH 0094/1099] CS: adjust chaining indentation --- .../DoctrineDataCollectorTest.php | 12 ++--- .../Constraints/UniqueEntityValidatorTest.php | 12 ++--- .../Tests/Command/RouterDebugCommandTest.php | 4 +- .../Tests/Command/RouterMatchCommandTest.php | 4 +- .../Console/Tests/ApplicationTest.php | 8 ++-- .../Compiler/AutoAliasServicePassTest.php | 10 ++-- .../Form/Tests/AbstractDivLayoutTest.php | 4 +- .../DataTransformerChainTest.php | 24 +++++----- .../Extension/Core/Type/FormTypeTest.php | 12 ++--- .../LegacySessionCsrfProviderTest.php | 12 ++--- .../Component/Form/Tests/FormFactoryTest.php | 48 +++++++++---------- .../EventListener/RouterListenerTest.php | 16 +++---- .../Acl/Tests/Domain/AuditLoggerTest.php | 10 ++-- .../SecurityIdentityRetrievalStrategyTest.php | 8 ++-- .../Tests/Domain/UserSecurityIdentityTest.php | 4 +- .../Validator/Constraints/UrlValidator.php | 8 ++-- .../Tests/Mapping/Loader/LoaderChainTest.php | 24 +++++----- 17 files changed, 110 insertions(+), 110 deletions(-) diff --git a/src/Symfony/Bridge/Doctrine/Tests/DataCollector/DoctrineDataCollectorTest.php b/src/Symfony/Bridge/Doctrine/Tests/DataCollector/DoctrineDataCollectorTest.php index 3059f8aba00a3..7557390bc6ab6 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/DataCollector/DoctrineDataCollectorTest.php +++ b/src/Symfony/Bridge/Doctrine/Tests/DataCollector/DoctrineDataCollectorTest.php @@ -142,13 +142,13 @@ private function createCollector($queries) $registry = $this->getMockBuilder('Doctrine\Common\Persistence\ManagerRegistry')->getMock(); $registry - ->expects($this->any()) - ->method('getConnectionNames') - ->will($this->returnValue(array('default' => 'doctrine.dbal.default_connection'))); + ->expects($this->any()) + ->method('getConnectionNames') + ->will($this->returnValue(array('default' => 'doctrine.dbal.default_connection'))); $registry - ->expects($this->any()) - ->method('getManagerNames') - ->will($this->returnValue(array('default' => 'doctrine.orm.default_entity_manager'))); + ->expects($this->any()) + ->method('getManagerNames') + ->will($this->returnValue(array('default' => 'doctrine.orm.default_entity_manager'))); $registry->expects($this->any()) ->method('getConnection') ->will($this->returnValue($connection)); diff --git a/src/Symfony/Bridge/Doctrine/Tests/Validator/Constraints/UniqueEntityValidatorTest.php b/src/Symfony/Bridge/Doctrine/Tests/Validator/Constraints/UniqueEntityValidatorTest.php index 115da8cba0008..61131e47045aa 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/Validator/Constraints/UniqueEntityValidatorTest.php +++ b/src/Symfony/Bridge/Doctrine/Tests/Validator/Constraints/UniqueEntityValidatorTest.php @@ -89,8 +89,8 @@ protected function createEntityManagerMock($repositoryMock) ->getMock() ; $em->expects($this->any()) - ->method('getRepository') - ->will($this->returnValue($repositoryMock)) + ->method('getRepository') + ->will($this->returnValue($repositoryMock)) ; $classMetadata = $this->getMockBuilder('Doctrine\Common\Persistence\Mapping\ClassMetadata')->getMock(); @@ -115,8 +115,8 @@ protected function createEntityManagerMock($repositoryMock) ; $classMetadata->reflFields = array('name' => $refl); $em->expects($this->any()) - ->method('getClassMetadata') - ->will($this->returnValue($classMetadata)) + ->method('getClassMetadata') + ->will($this->returnValue($classMetadata)) ; return $em; @@ -333,8 +333,8 @@ public function testValidateUniquenessUsingCustomRepositoryMethod() $repository = $this->createRepositoryMock(); $repository->expects($this->once()) - ->method('findByCustom') - ->will($this->returnValue(array())) + ->method('findByCustom') + ->will($this->returnValue(array())) ; $this->em = $this->createEntityManagerMock($repository); $this->registry = $this->createRegistryMock($this->em); diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/RouterDebugCommandTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/RouterDebugCommandTest.php index 9060af4d8260e..1a9e87e1ceeb8 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/RouterDebugCommandTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/RouterDebugCommandTest.php @@ -72,8 +72,8 @@ private function getContainer() ; $loader = $this->getMockBuilder('Symfony\Bundle\FrameworkBundle\Routing\DelegatingLoader') - ->disableOriginalConstructor() - ->getMock(); + ->disableOriginalConstructor() + ->getMock(); $container = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerInterface')->getMock(); $container diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/RouterMatchCommandTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/RouterMatchCommandTest.php index 6e9b5debe2f59..82a33b46d56da 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/RouterMatchCommandTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/RouterMatchCommandTest.php @@ -76,8 +76,8 @@ private function getContainer() ; $loader = $this->getMockBuilder('Symfony\Bundle\FrameworkBundle\Routing\DelegatingLoader') - ->disableOriginalConstructor() - ->getMock(); + ->disableOriginalConstructor() + ->getMock(); $container = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerInterface')->getMock(); $container diff --git a/src/Symfony/Component/Console/Tests/ApplicationTest.php b/src/Symfony/Component/Console/Tests/ApplicationTest.php index a955ee44c9fb4..c521cfd29148f 100644 --- a/src/Symfony/Component/Console/Tests/ApplicationTest.php +++ b/src/Symfony/Component/Console/Tests/ApplicationTest.php @@ -735,8 +735,8 @@ public function testRunReturnsIntegerExitCode() $application = $this->getMockBuilder('Symfony\Component\Console\Application')->setMethods(array('doRun'))->getMock(); $application->setAutoExit(false); $application->expects($this->once()) - ->method('doRun') - ->will($this->throwException($exception)); + ->method('doRun') + ->will($this->throwException($exception)); $exitCode = $application->run(new ArrayInput(array()), new NullOutput()); @@ -750,8 +750,8 @@ public function testRunReturnsExitCodeOneForExceptionCodeZero() $application = $this->getMockBuilder('Symfony\Component\Console\Application')->setMethods(array('doRun'))->getMock(); $application->setAutoExit(false); $application->expects($this->once()) - ->method('doRun') - ->will($this->throwException($exception)); + ->method('doRun') + ->will($this->throwException($exception)); $exitCode = $application->run(new ArrayInput(array()), new NullOutput()); diff --git a/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutoAliasServicePassTest.php b/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutoAliasServicePassTest.php index f8199b8c9f791..281634225acaa 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutoAliasServicePassTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutoAliasServicePassTest.php @@ -25,7 +25,7 @@ public function testProcessWithMissingParameter() $container = new ContainerBuilder(); $container->register('example') - ->addTag('auto_alias', array('format' => '%non_existing%.example')); + ->addTag('auto_alias', array('format' => '%non_existing%.example')); $pass = new AutoAliasServicePass(); $pass->process($container); @@ -39,7 +39,7 @@ public function testProcessWithMissingFormat() $container = new ContainerBuilder(); $container->register('example') - ->addTag('auto_alias', array()); + ->addTag('auto_alias', array()); $container->setParameter('existing', 'mysql'); $pass = new AutoAliasServicePass(); @@ -51,7 +51,7 @@ public function testProcessWithNonExistingAlias() $container = new ContainerBuilder(); $container->register('example', 'Symfony\Component\DependencyInjection\Tests\Compiler\ServiceClassDefault') - ->addTag('auto_alias', array('format' => '%existing%.example')); + ->addTag('auto_alias', array('format' => '%existing%.example')); $container->setParameter('existing', 'mysql'); $pass = new AutoAliasServicePass(); @@ -66,7 +66,7 @@ public function testProcessWithExistingAlias() $container = new ContainerBuilder(); $container->register('example', 'Symfony\Component\DependencyInjection\Tests\Compiler\ServiceClassDefault') - ->addTag('auto_alias', array('format' => '%existing%.example')); + ->addTag('auto_alias', array('format' => '%existing%.example')); $container->register('mysql.example', 'Symfony\Component\DependencyInjection\Tests\Compiler\ServiceClassMysql'); $container->setParameter('existing', 'mysql'); @@ -84,7 +84,7 @@ public function testProcessWithManualAlias() $container = new ContainerBuilder(); $container->register('example', 'Symfony\Component\DependencyInjection\Tests\Compiler\ServiceClassDefault') - ->addTag('auto_alias', array('format' => '%existing%.example')); + ->addTag('auto_alias', array('format' => '%existing%.example')); $container->register('mysql.example', 'Symfony\Component\DependencyInjection\Tests\Compiler\ServiceClassMysql'); $container->register('mariadb.example', 'Symfony\Component\DependencyInjection\Tests\Compiler\ServiceClassMariadb'); diff --git a/src/Symfony/Component/Form/Tests/AbstractDivLayoutTest.php b/src/Symfony/Component/Form/Tests/AbstractDivLayoutTest.php index 511c7f138cc7f..bd4121c5b64c3 100644 --- a/src/Symfony/Component/Form/Tests/AbstractDivLayoutTest.php +++ b/src/Symfony/Component/Form/Tests/AbstractDivLayoutTest.php @@ -346,8 +346,8 @@ public function testCollectionRow() ); $form = $this->factory->createNamedBuilder('form', 'form') - ->add($collection) - ->getForm(); + ->add($collection) + ->getForm(); $this->assertWidgetMatchesXpath($form->createView(), array(), '/div diff --git a/src/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/DataTransformerChainTest.php b/src/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/DataTransformerChainTest.php index fc9f85e3c752e..16302b3483692 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/DataTransformerChainTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/DataTransformerChainTest.php @@ -20,14 +20,14 @@ public function testTransform() { $transformer1 = $this->getMockBuilder('Symfony\Component\Form\DataTransformerInterface')->getMock(); $transformer1->expects($this->once()) - ->method('transform') - ->with($this->identicalTo('foo')) - ->will($this->returnValue('bar')); + ->method('transform') + ->with($this->identicalTo('foo')) + ->will($this->returnValue('bar')); $transformer2 = $this->getMockBuilder('Symfony\Component\Form\DataTransformerInterface')->getMock(); $transformer2->expects($this->once()) - ->method('transform') - ->with($this->identicalTo('bar')) - ->will($this->returnValue('baz')); + ->method('transform') + ->with($this->identicalTo('bar')) + ->will($this->returnValue('baz')); $chain = new DataTransformerChain(array($transformer1, $transformer2)); @@ -38,14 +38,14 @@ public function testReverseTransform() { $transformer2 = $this->getMockBuilder('Symfony\Component\Form\DataTransformerInterface')->getMock(); $transformer2->expects($this->once()) - ->method('reverseTransform') - ->with($this->identicalTo('foo')) - ->will($this->returnValue('bar')); + ->method('reverseTransform') + ->with($this->identicalTo('foo')) + ->will($this->returnValue('bar')); $transformer1 = $this->getMockBuilder('Symfony\Component\Form\DataTransformerInterface')->getMock(); $transformer1->expects($this->once()) - ->method('reverseTransform') - ->with($this->identicalTo('bar')) - ->will($this->returnValue('baz')); + ->method('reverseTransform') + ->with($this->identicalTo('bar')) + ->will($this->returnValue('baz')); $chain = new DataTransformerChain(array($transformer1, $transformer2)); diff --git a/src/Symfony/Component/Form/Tests/Extension/Core/Type/FormTypeTest.php b/src/Symfony/Component/Form/Tests/Extension/Core/Type/FormTypeTest.php index 1ff4057d5f373..bd772a4e59fd9 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Core/Type/FormTypeTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Core/Type/FormTypeTest.php @@ -124,9 +124,9 @@ public function testReadOnlyFormWithNonReadOnlyParentIsReadOnly() public function testNonReadOnlyFormWithNonReadOnlyParentIsNotReadOnly() { $view = $this->factory->createNamedBuilder('parent', static::TESTED_TYPE) - ->add('child', static::TESTED_TYPE) - ->getForm() - ->createView(); + ->add('child', static::TESTED_TYPE) + ->getForm() + ->createView(); $this->assertFalse($view['child']->vars['read_only']); } @@ -478,9 +478,9 @@ public function testPassMultipartTrueIfAnyChildIsMultipartToView() public function testViewIsNotRenderedByDefault() { $view = $this->factory->createBuilder(static::TESTED_TYPE) - ->add('foo', static::TESTED_TYPE) - ->getForm() - ->createView(); + ->add('foo', static::TESTED_TYPE) + ->getForm() + ->createView(); $this->assertFalse($view->isRendered()); } diff --git a/src/Symfony/Component/Form/Tests/Extension/Csrf/CsrfProvider/LegacySessionCsrfProviderTest.php b/src/Symfony/Component/Form/Tests/Extension/Csrf/CsrfProvider/LegacySessionCsrfProviderTest.php index bd87d9cc8c577..8bf4183d61e84 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Csrf/CsrfProvider/LegacySessionCsrfProviderTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Csrf/CsrfProvider/LegacySessionCsrfProviderTest.php @@ -37,8 +37,8 @@ protected function tearDown() public function testGenerateCsrfToken() { $this->session->expects($this->once()) - ->method('getId') - ->will($this->returnValue('ABCDEF')); + ->method('getId') + ->will($this->returnValue('ABCDEF')); $token = $this->provider->generateCsrfToken('foo'); @@ -48,8 +48,8 @@ public function testGenerateCsrfToken() public function testIsCsrfTokenValidSucceeds() { $this->session->expects($this->once()) - ->method('getId') - ->will($this->returnValue('ABCDEF')); + ->method('getId') + ->will($this->returnValue('ABCDEF')); $token = sha1('SECRET'.'foo'.'ABCDEF'); @@ -59,8 +59,8 @@ public function testIsCsrfTokenValidSucceeds() public function testIsCsrfTokenValidFails() { $this->session->expects($this->once()) - ->method('getId') - ->will($this->returnValue('ABCDEF')); + ->method('getId') + ->will($this->returnValue('ABCDEF')); $token = sha1('SECRET'.'bar'.'ABCDEF'); diff --git a/src/Symfony/Component/Form/Tests/FormFactoryTest.php b/src/Symfony/Component/Form/Tests/FormFactoryTest.php index 4185a4a0025d2..29d5be7d55991 100644 --- a/src/Symfony/Component/Form/Tests/FormFactoryTest.php +++ b/src/Symfony/Component/Form/Tests/FormFactoryTest.php @@ -427,9 +427,9 @@ public function testCreateBuilderForPropertyCreatesFormWithHighestConfidence() public function testCreateBuilderCreatesTextFormIfNoGuess() { $this->guesser1->expects($this->once()) - ->method('guessType') - ->with('Application\Author', 'firstName') - ->will($this->returnValue(null)); + ->method('guessType') + ->with('Application\Author', 'firstName') + ->will($this->returnValue(null)); $factory = $this->getMockFactory(array('createNamedBuilder')); @@ -446,9 +446,9 @@ public function testCreateBuilderCreatesTextFormIfNoGuess() public function testOptionsCanBeOverridden() { $this->guesser1->expects($this->once()) - ->method('guessType') - ->with('Application\Author', 'firstName') - ->will($this->returnValue(new TypeGuess( + ->method('guessType') + ->with('Application\Author', 'firstName') + ->will($this->returnValue(new TypeGuess( 'text', array('attr' => array('maxlength' => 10)), Guess::MEDIUM_CONFIDENCE @@ -474,17 +474,17 @@ public function testOptionsCanBeOverridden() public function testCreateBuilderUsesMaxLengthIfFound() { $this->guesser1->expects($this->once()) - ->method('guessMaxLength') - ->with('Application\Author', 'firstName') - ->will($this->returnValue(new ValueGuess( + ->method('guessMaxLength') + ->with('Application\Author', 'firstName') + ->will($this->returnValue(new ValueGuess( 15, Guess::MEDIUM_CONFIDENCE ))); $this->guesser2->expects($this->once()) - ->method('guessMaxLength') - ->with('Application\Author', 'firstName') - ->will($this->returnValue(new ValueGuess( + ->method('guessMaxLength') + ->with('Application\Author', 'firstName') + ->will($this->returnValue(new ValueGuess( 20, Guess::HIGH_CONFIDENCE ))); @@ -542,17 +542,17 @@ public function testCreateBuilderUsesMaxLengthAndPattern() public function testCreateBuilderUsesRequiredSettingWithHighestConfidence() { $this->guesser1->expects($this->once()) - ->method('guessRequired') - ->with('Application\Author', 'firstName') - ->will($this->returnValue(new ValueGuess( + ->method('guessRequired') + ->with('Application\Author', 'firstName') + ->will($this->returnValue(new ValueGuess( true, Guess::MEDIUM_CONFIDENCE ))); $this->guesser2->expects($this->once()) - ->method('guessRequired') - ->with('Application\Author', 'firstName') - ->will($this->returnValue(new ValueGuess( + ->method('guessRequired') + ->with('Application\Author', 'firstName') + ->will($this->returnValue(new ValueGuess( false, Guess::HIGH_CONFIDENCE ))); @@ -575,17 +575,17 @@ public function testCreateBuilderUsesRequiredSettingWithHighestConfidence() public function testCreateBuilderUsesPatternIfFound() { $this->guesser1->expects($this->once()) - ->method('guessPattern') - ->with('Application\Author', 'firstName') - ->will($this->returnValue(new ValueGuess( + ->method('guessPattern') + ->with('Application\Author', 'firstName') + ->will($this->returnValue(new ValueGuess( '[a-z]', Guess::MEDIUM_CONFIDENCE ))); $this->guesser2->expects($this->once()) - ->method('guessPattern') - ->with('Application\Author', 'firstName') - ->will($this->returnValue(new ValueGuess( + ->method('guessPattern') + ->with('Application\Author', 'firstName') + ->will($this->returnValue(new ValueGuess( '[a-zA-Z]', Guess::HIGH_CONFIDENCE ))); diff --git a/src/Symfony/Component/HttpKernel/Tests/EventListener/RouterListenerTest.php b/src/Symfony/Component/HttpKernel/Tests/EventListener/RouterListenerTest.php index 40636fa684d5c..8376ba8f6fd18 100644 --- a/src/Symfony/Component/HttpKernel/Tests/EventListener/RouterListenerTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/EventListener/RouterListenerTest.php @@ -33,14 +33,14 @@ protected function setUp() public function testPort($defaultHttpPort, $defaultHttpsPort, $uri, $expectedHttpPort, $expectedHttpsPort) { $urlMatcher = $this->getMockBuilder('Symfony\Component\Routing\Matcher\UrlMatcherInterface') - ->disableOriginalConstructor() - ->getMock(); + ->disableOriginalConstructor() + ->getMock(); $context = new RequestContext(); $context->setHttpPort($defaultHttpPort); $context->setHttpsPort($defaultHttpsPort); $urlMatcher->expects($this->any()) - ->method('getContext') - ->will($this->returnValue($context)); + ->method('getContext') + ->will($this->returnValue($context)); $listener = new RouterListener($urlMatcher, null, null, $this->requestStack); $event = $this->createGetResponseEventForUri($uri); @@ -133,13 +133,13 @@ public function testLoggingParameter($parameter, $log) { $requestMatcher = $this->getMockBuilder('Symfony\Component\Routing\Matcher\RequestMatcherInterface')->getMock(); $requestMatcher->expects($this->once()) - ->method('matchRequest') - ->will($this->returnValue($parameter)); + ->method('matchRequest') + ->will($this->returnValue($parameter)); $logger = $this->getMockBuilder('Psr\Log\LoggerInterface')->getMock(); $logger->expects($this->once()) - ->method('info') - ->with($this->equalTo($log)); + ->method('info') + ->with($this->equalTo($log)); $kernel = $this->getMockBuilder('Symfony\Component\HttpKernel\HttpKernelInterface')->getMock(); $request = Request::create('http://localhost/'); diff --git a/src/Symfony/Component/Security/Acl/Tests/Domain/AuditLoggerTest.php b/src/Symfony/Component/Security/Acl/Tests/Domain/AuditLoggerTest.php index 630d217558ac7..d7d1f6b1ad090 100644 --- a/src/Symfony/Component/Security/Acl/Tests/Domain/AuditLoggerTest.php +++ b/src/Symfony/Component/Security/Acl/Tests/Domain/AuditLoggerTest.php @@ -31,8 +31,8 @@ public function testLogIfNeeded($granting, $audit) ; $ace - ->expects($this->never()) - ->method('isAuditFailure') + ->expects($this->never()) + ->method('isAuditFailure') ; } else { $ace @@ -49,9 +49,9 @@ public function testLogIfNeeded($granting, $audit) if (true === $audit) { $logger - ->expects($this->once()) - ->method('doLog') - ->with($this->equalTo($granting), $this->equalTo($ace)) + ->expects($this->once()) + ->method('doLog') + ->with($this->equalTo($granting), $this->equalTo($ace)) ; } else { $logger diff --git a/src/Symfony/Component/Security/Acl/Tests/Domain/SecurityIdentityRetrievalStrategyTest.php b/src/Symfony/Component/Security/Acl/Tests/Domain/SecurityIdentityRetrievalStrategyTest.php index 2b5e35ecb7c3b..3bc0bde13dae9 100644 --- a/src/Symfony/Component/Security/Acl/Tests/Domain/SecurityIdentityRetrievalStrategyTest.php +++ b/src/Symfony/Component/Security/Acl/Tests/Domain/SecurityIdentityRetrievalStrategyTest.php @@ -27,8 +27,8 @@ public function testGetSecurityIdentities($user, array $roles, $authenticationSt if ('anonymous' === $authenticationStatus) { $token = $this->getMockBuilder('Symfony\Component\Security\Core\Authentication\Token\AnonymousToken') - ->disableOriginalConstructor() - ->getMock(); + ->disableOriginalConstructor() + ->getMock(); } else { $class = ''; if (is_string($user)) { @@ -36,8 +36,8 @@ public function testGetSecurityIdentities($user, array $roles, $authenticationSt } $token = $this->getMockBuilder('Symfony\Component\Security\Core\Authentication\Token\TokenInterface') - ->setMockClassName($class) - ->getMock(); + ->setMockClassName($class) + ->getMock(); } $token ->expects($this->once()) diff --git a/src/Symfony/Component/Security/Acl/Tests/Domain/UserSecurityIdentityTest.php b/src/Symfony/Component/Security/Acl/Tests/Domain/UserSecurityIdentityTest.php index 613de22ada017..672b5788e4581 100644 --- a/src/Symfony/Component/Security/Acl/Tests/Domain/UserSecurityIdentityTest.php +++ b/src/Symfony/Component/Security/Acl/Tests/Domain/UserSecurityIdentityTest.php @@ -45,8 +45,8 @@ public function testEquals($id1, $id2, $equal) public function getCompareData() { $account = $this->getMockBuilder('Symfony\Component\Security\Core\User\UserInterface') - ->setMockClassName('USI_AccountImpl') - ->getMock(); + ->setMockClassName('USI_AccountImpl') + ->getMock(); $account ->expects($this->any()) ->method('getUsername') diff --git a/src/Symfony/Component/Validator/Constraints/UrlValidator.php b/src/Symfony/Component/Validator/Constraints/UrlValidator.php index a12dc14979b47..5cb126d8fe2fe 100644 --- a/src/Symfony/Component/Validator/Constraints/UrlValidator.php +++ b/src/Symfony/Component/Validator/Constraints/UrlValidator.php @@ -83,12 +83,12 @@ public function validate($value, Constraint $constraint) if (!is_string($host) || !checkdnsrr($host, 'ANY')) { if ($this->context instanceof ExecutionContextInterface) { $this->context->buildViolation($constraint->dnsMessage) - ->setParameter('{{ value }}', $this->formatValue($host)) - ->addViolation(); + ->setParameter('{{ value }}', $this->formatValue($host)) + ->addViolation(); } else { $this->buildViolation($constraint->dnsMessage) - ->setParameter('{{ value }}', $this->formatValue($host)) - ->addViolation(); + ->setParameter('{{ value }}', $this->formatValue($host)) + ->addViolation(); } } } diff --git a/src/Symfony/Component/Validator/Tests/Mapping/Loader/LoaderChainTest.php b/src/Symfony/Component/Validator/Tests/Mapping/Loader/LoaderChainTest.php index 49a8b5256d0b6..0d28b0a399e48 100644 --- a/src/Symfony/Component/Validator/Tests/Mapping/Loader/LoaderChainTest.php +++ b/src/Symfony/Component/Validator/Tests/Mapping/Loader/LoaderChainTest.php @@ -23,13 +23,13 @@ public function testAllLoadersAreCalled() $loader1 = $this->getMockBuilder('Symfony\Component\Validator\Mapping\Loader\LoaderInterface')->getMock(); $loader1->expects($this->once()) - ->method('loadClassMetadata') - ->with($this->equalTo($metadata)); + ->method('loadClassMetadata') + ->with($this->equalTo($metadata)); $loader2 = $this->getMockBuilder('Symfony\Component\Validator\Mapping\Loader\LoaderInterface')->getMock(); $loader2->expects($this->once()) - ->method('loadClassMetadata') - ->with($this->equalTo($metadata)); + ->method('loadClassMetadata') + ->with($this->equalTo($metadata)); $chain = new LoaderChain(array( $loader1, @@ -45,13 +45,13 @@ public function testReturnsTrueIfAnyLoaderReturnedTrue() $loader1 = $this->getMockBuilder('Symfony\Component\Validator\Mapping\Loader\LoaderInterface')->getMock(); $loader1->expects($this->any()) - ->method('loadClassMetadata') - ->will($this->returnValue(true)); + ->method('loadClassMetadata') + ->will($this->returnValue(true)); $loader2 = $this->getMockBuilder('Symfony\Component\Validator\Mapping\Loader\LoaderInterface')->getMock(); $loader2->expects($this->any()) - ->method('loadClassMetadata') - ->will($this->returnValue(false)); + ->method('loadClassMetadata') + ->will($this->returnValue(false)); $chain = new LoaderChain(array( $loader1, @@ -67,13 +67,13 @@ public function testReturnsFalseIfNoLoaderReturnedTrue() $loader1 = $this->getMockBuilder('Symfony\Component\Validator\Mapping\Loader\LoaderInterface')->getMock(); $loader1->expects($this->any()) - ->method('loadClassMetadata') - ->will($this->returnValue(false)); + ->method('loadClassMetadata') + ->will($this->returnValue(false)); $loader2 = $this->getMockBuilder('Symfony\Component\Validator\Mapping\Loader\LoaderInterface')->getMock(); $loader2->expects($this->any()) - ->method('loadClassMetadata') - ->will($this->returnValue(false)); + ->method('loadClassMetadata') + ->will($this->returnValue(false)); $chain = new LoaderChain(array( $loader1, From a8dfbb11807539fd0f49baccfb088787e82a0d4a Mon Sep 17 00:00:00 2001 From: Iltar van der Berg Date: Tue, 30 May 2017 15:00:50 +0200 Subject: [PATCH 0095/1099] Support unknown compiler log format --- .../DataCollector/LoggerDataCollector.php | 3 +++ .../Tests/DataCollector/Compiler.log | 4 ++++ .../DataCollector/LoggerDataCollectorTest.php | 21 +++++++++++++++++++ 3 files changed, 28 insertions(+) create mode 100644 src/Symfony/Component/HttpKernel/Tests/DataCollector/Compiler.log diff --git a/src/Symfony/Component/HttpKernel/DataCollector/LoggerDataCollector.php b/src/Symfony/Component/HttpKernel/DataCollector/LoggerDataCollector.php index d32c581cb6b28..7ae1fbbd61537 100644 --- a/src/Symfony/Component/HttpKernel/DataCollector/LoggerDataCollector.php +++ b/src/Symfony/Component/HttpKernel/DataCollector/LoggerDataCollector.php @@ -138,6 +138,9 @@ private function getContainerCompilerLogs() $logs = array(); foreach (file($file, FILE_IGNORE_NEW_LINES) as $log) { $log = explode(': ', $log, 2); + if (!isset($log[1]) || !preg_match('/^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*+(?:\\\\[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*+)++$/', $log[0])) { + $log = array('Unknown Compiler Pass', implode(': ', $log)); + } $logs[$log[0]][] = array('message' => $log[1]); } diff --git a/src/Symfony/Component/HttpKernel/Tests/DataCollector/Compiler.log b/src/Symfony/Component/HttpKernel/Tests/DataCollector/Compiler.log new file mode 100644 index 0000000000000..88b6840eae8e9 --- /dev/null +++ b/src/Symfony/Component/HttpKernel/Tests/DataCollector/Compiler.log @@ -0,0 +1,4 @@ +Symfony\Component\DependencyInjection\Compiler\RemovePrivateAliasesPass: Removed service "Psr\Container\ContainerInterface"; reason: private alias. +Symfony\Component\DependencyInjection\Compiler\RemovePrivateAliasesPass: Removed service "Symfony\Component\DependencyInjection\ContainerInterface"; reason: private alias. +Some custom logging message +With ending : diff --git a/src/Symfony/Component/HttpKernel/Tests/DataCollector/LoggerDataCollectorTest.php b/src/Symfony/Component/HttpKernel/Tests/DataCollector/LoggerDataCollectorTest.php index 5a01ee88161e9..62bf2c00c7586 100644 --- a/src/Symfony/Component/HttpKernel/Tests/DataCollector/LoggerDataCollectorTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/DataCollector/LoggerDataCollectorTest.php @@ -17,6 +17,27 @@ class LoggerDataCollectorTest extends TestCase { + public function testCollectWithUnexpectedFormat() + { + $logger = $this->getMockBuilder('Symfony\Component\HttpKernel\Log\DebugLoggerInterface')->getMock(); + $logger->expects($this->once())->method('countErrors')->will($this->returnValue('foo')); + $logger->expects($this->exactly(2))->method('getLogs')->will($this->returnValue(array())); + + $c = new LoggerDataCollector($logger, __DIR__.'/'); + $c->lateCollect(); + $compilerLogs = $c->getCompilerLogs()->getValue('message'); + + $this->assertSame(array( + array('message' => 'Removed service "Psr\Container\ContainerInterface"; reason: private alias.'), + array('message' => 'Removed service "Symfony\Component\DependencyInjection\ContainerInterface"; reason: private alias.'), + ), $compilerLogs['Symfony\Component\DependencyInjection\Compiler\RemovePrivateAliasesPass']); + + $this->assertSame(array( + array('message' => 'Some custom logging message'), + array('message' => 'With ending :'), + ), $compilerLogs['Unknown Compiler Pass']); + } + /** * @dataProvider getCollectTestData */ From 47d5e6b82c91a4f6093f70e6a01255e66d4cd172 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Wed, 31 May 2017 12:58:03 +0200 Subject: [PATCH 0096/1099] [PropertyInfo][DoctrineBridge] The bigint Doctrine's type must be converted to string --- .../Bridge/Doctrine/PropertyInfo/DoctrineExtractor.php | 5 +---- .../Doctrine/Tests/PropertyInfo/DoctrineExtractorTest.php | 2 ++ .../Doctrine/Tests/PropertyInfo/Fixtures/DoctrineDummy.php | 6 ++++++ 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/Symfony/Bridge/Doctrine/PropertyInfo/DoctrineExtractor.php b/src/Symfony/Bridge/Doctrine/PropertyInfo/DoctrineExtractor.php index aba31792f99ee..e07c7b0bc2cba 100644 --- a/src/Symfony/Bridge/Doctrine/PropertyInfo/DoctrineExtractor.php +++ b/src/Symfony/Bridge/Doctrine/PropertyInfo/DoctrineExtractor.php @@ -174,13 +174,13 @@ private function getPhpType($doctrineType) { switch ($doctrineType) { case DBALType::SMALLINT: - case DBALType::BIGINT: case DBALType::INTEGER: return Type::BUILTIN_TYPE_INT; case DBALType::FLOAT: return Type::BUILTIN_TYPE_FLOAT; + case DBALType::BIGINT: case DBALType::STRING: case DBALType::TEXT: case DBALType::GUID: @@ -196,9 +196,6 @@ private function getPhpType($doctrineType) case DBALType::OBJECT: return Type::BUILTIN_TYPE_OBJECT; - - default: - return; } } } diff --git a/src/Symfony/Bridge/Doctrine/Tests/PropertyInfo/DoctrineExtractorTest.php b/src/Symfony/Bridge/Doctrine/Tests/PropertyInfo/DoctrineExtractorTest.php index 277922daefd51..48822d5888fbc 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/PropertyInfo/DoctrineExtractorTest.php +++ b/src/Symfony/Bridge/Doctrine/Tests/PropertyInfo/DoctrineExtractorTest.php @@ -55,6 +55,7 @@ public function testGetProperties() 'bool', 'binary', 'customFoo', + 'bigint', 'foo', 'bar', 'indexedBar', @@ -76,6 +77,7 @@ public function typesProvider() return array( array('id', array(new Type(Type::BUILTIN_TYPE_INT))), array('guid', array(new Type(Type::BUILTIN_TYPE_STRING))), + array('bigint', array(new Type(Type::BUILTIN_TYPE_STRING))), array('float', array(new Type(Type::BUILTIN_TYPE_FLOAT))), array('decimal', array(new Type(Type::BUILTIN_TYPE_STRING))), array('bool', array(new Type(Type::BUILTIN_TYPE_BOOL))), diff --git a/src/Symfony/Bridge/Doctrine/Tests/PropertyInfo/Fixtures/DoctrineDummy.php b/src/Symfony/Bridge/Doctrine/Tests/PropertyInfo/Fixtures/DoctrineDummy.php index ad3b7b9227652..9ceae5150c7ab 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/PropertyInfo/Fixtures/DoctrineDummy.php +++ b/src/Symfony/Bridge/Doctrine/Tests/PropertyInfo/Fixtures/DoctrineDummy.php @@ -11,6 +11,7 @@ namespace Symfony\Bridge\Doctrine\Tests\PropertyInfo\Fixtures; +use Doctrine\ORM\Mapping as ORM; use Doctrine\ORM\Mapping\Column; use Doctrine\ORM\Mapping\Entity; use Doctrine\ORM\Mapping\Id; @@ -90,5 +91,10 @@ class DoctrineDummy */ private $customFoo; + /** + * @Column(type="bigint") + */ + private $bigint; + public $notMapped; } From a3793198fa33c410489627a03fbb1ac8c7ecafe8 Mon Sep 17 00:00:00 2001 From: Robin Chalas Date: Wed, 31 May 2017 13:48:12 +0200 Subject: [PATCH 0097/1099] Remove extra arg in call to TraceableAdapter::start() --- src/Symfony/Component/Cache/Adapter/TraceableAdapter.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/Cache/Adapter/TraceableAdapter.php b/src/Symfony/Component/Cache/Adapter/TraceableAdapter.php index 1ddf65b3015e2..9959199f67ccc 100644 --- a/src/Symfony/Component/Cache/Adapter/TraceableAdapter.php +++ b/src/Symfony/Component/Cache/Adapter/TraceableAdapter.php @@ -107,7 +107,7 @@ public function saveDeferred(CacheItemInterface $item) */ public function getItems(array $keys = array()) { - $event = $this->start(__FUNCTION__, $keys); + $event = $this->start(__FUNCTION__); try { $result = $this->pool->getItems($keys); } finally { From 2d3e44e11ea053d2506408e49191e9b1797a9c14 Mon Sep 17 00:00:00 2001 From: Ryan Weaver Date: Wed, 31 May 2017 09:45:25 -0400 Subject: [PATCH 0098/1099] Fixing a bug where an autowiring exception was thrown even when that service was removed The specific report was for a service with a private constructor. This also clarifies that the AutowirePass throws AutowiringFailedException for all situations. And a bug was fixed in the constructor of AutowiringFailedException --- .../Compiler/AutowirePass.php | 10 +++- .../Exception/AutowiringFailedException.php | 2 +- .../Tests/Compiler/AutowirePassTest.php | 49 +++++++++++++------ 3 files changed, 44 insertions(+), 17 deletions(-) diff --git a/src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php b/src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php index b79a656aa8eaf..bf7fc844c732b 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php @@ -133,7 +133,13 @@ private function doProcessValue($value, $isRoot = false) $autowiredMethods = $this->getMethodsToAutowire($reflectionClass); $methodCalls = $value->getMethodCalls(); - if ($constructor = $this->getConstructor($value, false)) { + try { + $constructor = $this->getConstructor($value, false); + } catch (RuntimeException $e) { + throw new AutowiringFailedException($this->currentId, $e->getMessage(), 0, $e); + } + + if ($constructor) { array_unshift($methodCalls, array($constructor, $value->getArguments())); } @@ -242,7 +248,7 @@ private function autowireCalls(\ReflectionClass $reflectionClass, array $methodC * * @return array The autowired arguments * - * @throws RuntimeException + * @throws AutowiringFailedException */ private function autowireMethod(\ReflectionFunctionAbstract $reflectionMethod, array $arguments) { diff --git a/src/Symfony/Component/DependencyInjection/Exception/AutowiringFailedException.php b/src/Symfony/Component/DependencyInjection/Exception/AutowiringFailedException.php index f5c50d4dee336..145cd8cbdcf24 100644 --- a/src/Symfony/Component/DependencyInjection/Exception/AutowiringFailedException.php +++ b/src/Symfony/Component/DependencyInjection/Exception/AutowiringFailedException.php @@ -18,7 +18,7 @@ class AutowiringFailedException extends RuntimeException { private $serviceId; - public function __construct($serviceId, $message = '', $code = 0, Exception $previous = null) + public function __construct($serviceId, $message = '', $code = 0, \Exception $previous = null) { $this->serviceId = $serviceId; diff --git a/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowirePassTest.php b/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowirePassTest.php index e2ba9ec4e4b97..ca297f217495d 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowirePassTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowirePassTest.php @@ -151,7 +151,21 @@ public function testExceptionsAreStored() } /** - * @expectedException \Symfony\Component\DependencyInjection\Exception\RuntimeException + * @expectedException \Symfony\Component\DependencyInjection\Exception\AutowiringFailedException + * @expectedExceptionMessage Unable to resolve service "private_service": constructor of class "Symfony\Component\DependencyInjection\Tests\Compiler\PrivateConstructor" must be public. + */ + public function testPrivateConstructorThrowsAutowireException() + { + $container = new ContainerBuilder(); + + $container->autowire('private_service', __NAMESPACE__.'\PrivateConstructor'); + + $pass = new AutowirePass(true); + $pass->process($container); + } + + /** + * @expectedException \Symfony\Component\DependencyInjection\Exception\AutowiringFailedException * @expectedExceptionMessage Cannot autowire service "a": argument "$collision" of method "Symfony\Component\DependencyInjection\Tests\Compiler\CannotBeAutowired::__construct()" references interface "Symfony\Component\DependencyInjection\Tests\Compiler\CollisionInterface" but no such service exists. You should maybe alias this interface to one of these existing services: "c1", "c2", "c3". */ public function testTypeCollision() @@ -169,7 +183,7 @@ public function testTypeCollision() } /** - * @expectedException \Symfony\Component\DependencyInjection\Exception\RuntimeException + * @expectedException \Symfony\Component\DependencyInjection\Exception\AutowiringFailedException * @expectedExceptionMessage Cannot autowire service "a": argument "$k" of method "Symfony\Component\DependencyInjection\Tests\Compiler\NotGuessableArgument::__construct()" references class "Symfony\Component\DependencyInjection\Tests\Compiler\Foo" but no such service exists. You should maybe alias this class to one of these existing services: "a1", "a2". */ public function testTypeNotGuessable() @@ -186,7 +200,7 @@ public function testTypeNotGuessable() } /** - * @expectedException \Symfony\Component\DependencyInjection\Exception\RuntimeException + * @expectedException \Symfony\Component\DependencyInjection\Exception\AutowiringFailedException * @expectedExceptionMessage Cannot autowire service "a": argument "$k" of method "Symfony\Component\DependencyInjection\Tests\Compiler\NotGuessableArgumentForSubclass::__construct()" references class "Symfony\Component\DependencyInjection\Tests\Compiler\A" but no such service exists. You should maybe alias this class to one of these existing services: "a1", "a2". */ public function testTypeNotGuessableWithSubclass() @@ -203,7 +217,7 @@ public function testTypeNotGuessableWithSubclass() } /** - * @expectedException \Symfony\Component\DependencyInjection\Exception\RuntimeException + * @expectedException \Symfony\Component\DependencyInjection\Exception\AutowiringFailedException * @expectedExceptionMessage Cannot autowire service "a": argument "$collision" of method "Symfony\Component\DependencyInjection\Tests\Compiler\CannotBeAutowired::__construct()" references interface "Symfony\Component\DependencyInjection\Tests\Compiler\CollisionInterface" but no such service exists. */ public function testTypeNotGuessableNoServicesFound() @@ -322,7 +336,7 @@ public function testDontTriggerAutowiring() } /** - * @expectedException \Symfony\Component\DependencyInjection\Exception\RuntimeException + * @expectedException \Symfony\Component\DependencyInjection\Exception\AutowiringFailedException * @expectedExceptionMessage Cannot autowire service "a": argument "$r" of method "Symfony\Component\DependencyInjection\Tests\Compiler\BadTypeHintedArgument::__construct()" has type "Symfony\Component\DependencyInjection\Tests\Compiler\NotARealClass" but this class does not exist. */ public function testClassNotFoundThrowsException() @@ -337,7 +351,7 @@ public function testClassNotFoundThrowsException() } /** - * @expectedException \Symfony\Component\DependencyInjection\Exception\RuntimeException + * @expectedException \Symfony\Component\DependencyInjection\Exception\AutowiringFailedException * @expectedExceptionMessage Cannot autowire service "a": argument "$r" of method "Symfony\Component\DependencyInjection\Tests\Compiler\BadParentTypeHintedArgument::__construct()" has type "Symfony\Component\DependencyInjection\Tests\Compiler\OptionalServiceClass" but this class does not exist. */ public function testParentClassNotFoundThrowsException() @@ -354,7 +368,7 @@ public function testParentClassNotFoundThrowsException() /** * @group legacy * @expectedDeprecation Autowiring services based on the types they implement is deprecated since Symfony 3.3 and won't be supported in version 4.0. You should rename (or alias) the "foo" service to "Symfony\Component\DependencyInjection\Tests\Compiler\Foo" instead. - * @expectedExceptionInSymfony4 \Symfony\Component\DependencyInjection\Exception\RuntimeException + * @expectedExceptionInSymfony4 \Symfony\Component\DependencyInjection\Exception\AutowiringFailedException * @expectedExceptionMessageInSymfony4 Cannot autowire service "bar": argument "$foo" of method "Symfony\Component\DependencyInjection\Tests\Compiler\Bar::__construct()" references class "Symfony\Component\DependencyInjection\Tests\Compiler\Foo" but this service is abstract. You should maybe alias this class to the existing "foo" service. */ public function testDontUseAbstractServices() @@ -399,7 +413,7 @@ public function testSomeSpecificArgumentsAreSet() } /** - * @expectedException \Symfony\Component\DependencyInjection\Exception\RuntimeException + * @expectedException \Symfony\Component\DependencyInjection\Exception\AutowiringFailedException * @expectedExceptionMessage Cannot autowire service "arg_no_type_hint": argument "$foo" of method "Symfony\Component\DependencyInjection\Tests\Compiler\MultipleArguments::__construct()" must have a type-hint or be given a value explicitly. */ public function testScalarArgsCannotBeAutowired() @@ -607,7 +621,7 @@ public function testIgnoreServiceWithClassNotExisting() } /** - * @expectedException \Symfony\Component\DependencyInjection\Exception\RuntimeException + * @expectedException \Symfony\Component\DependencyInjection\Exception\AutowiringFailedException * @expectedExceptionMessage Cannot autowire service "setter_injection_collision": argument "$collision" of method "Symfony\Component\DependencyInjection\Tests\Compiler\SetterInjectionCollision::setMultipleInstancesForOneArg()" references interface "Symfony\Component\DependencyInjection\Tests\Compiler\CollisionInterface" but no such service exists. You should maybe alias this interface to one of these existing services: "c1", "c2". */ public function testSetterInjectionCollisionThrowsException() @@ -626,7 +640,7 @@ public function testSetterInjectionCollisionThrowsException() /** * @group legacy * @expectedDeprecation Autowiring services based on the types they implement is deprecated since Symfony 3.3 and won't be supported in version 4.0. You should rename (or alias) the "foo" service to "Symfony\Component\DependencyInjection\Tests\Compiler\Foo" instead. - * @expectedExceptionInSymfony4 \Symfony\Component\DependencyInjection\Exception\RuntimeException + * @expectedExceptionInSymfony4 \Symfony\Component\DependencyInjection\Exception\AutowiringFailedException * @expectedExceptionMessageInSymfony4 Cannot autowire service "bar": argument "$foo" of method "Symfony\Component\DependencyInjection\Tests\Compiler\Bar::__construct()" references class "Symfony\Component\DependencyInjection\Tests\Compiler\Foo" but no such service exists. You should maybe alias this class to the existing "foo" service. */ public function testProcessDoesNotTriggerDeprecations() @@ -677,7 +691,7 @@ public function testWithFactory() /** * @dataProvider provideNotWireableCalls - * @expectedException \Symfony\Component\DependencyInjection\Exception\RuntimeException + * @expectedException \Symfony\Component\DependencyInjection\Exception\AutowiringFailedException */ public function testNotWireableCalls($method, $expectedMsg) { @@ -717,7 +731,7 @@ public function provideNotWireableCalls() /** * @group legacy * @expectedDeprecation Autowiring services based on the types they implement is deprecated since Symfony 3.3 and won't be supported in version 4.0. You should rename (or alias) the "i" service to "Symfony\Component\DependencyInjection\Tests\Compiler\I" instead. - * @expectedExceptionInSymfony4 \Symfony\Component\DependencyInjection\Exception\RuntimeException + * @expectedExceptionInSymfony4 \Symfony\Component\DependencyInjection\Exception\AutowiringFailedException * @expectedExceptionMessageInSymfony4 Cannot autowire service "j": argument "$i" of method "Symfony\Component\DependencyInjection\Tests\Compiler\J::__construct()" references class "Symfony\Component\DependencyInjection\Tests\Compiler\I" but no such service exists. Try changing the type-hint to "Symfony\Component\DependencyInjection\Tests\Compiler\IInterface" instead. */ public function testByIdAlternative() @@ -734,7 +748,7 @@ public function testByIdAlternative() } /** - * @expectedException \Symfony\Component\DependencyInjection\Exception\RuntimeException + * @expectedException \Symfony\Component\DependencyInjection\Exception\AutowiringFailedException * @expectedExceptionMessage Cannot autowire service "j": argument "$i" of method "Symfony\Component\DependencyInjection\Tests\Compiler\J::__construct()" references class "Symfony\Component\DependencyInjection\Tests\Compiler\I" but no such service exists. Try changing the type-hint to "Symfony\Component\DependencyInjection\Tests\Compiler\IInterface" instead. */ public function testExceptionWhenAliasExists() @@ -754,7 +768,7 @@ public function testExceptionWhenAliasExists() } /** - * @expectedException \Symfony\Component\DependencyInjection\Exception\RuntimeException + * @expectedException \Symfony\Component\DependencyInjection\Exception\AutowiringFailedException * @expectedExceptionMessage Cannot autowire service "j": argument "$i" of method "Symfony\Component\DependencyInjection\Tests\Compiler\J::__construct()" references class "Symfony\Component\DependencyInjection\Tests\Compiler\I" but no such service exists. You should maybe alias this class to one of these existing services: "i", "i2". */ public function testExceptionWhenAliasDoesNotExist() @@ -1091,3 +1105,10 @@ protected function setProtectedMethod(A $a) { } } + +class PrivateConstructor +{ + private function __construct() + { + } +} From 63a8aff2c887a4358529ebe7adb851725515e4eb Mon Sep 17 00:00:00 2001 From: Christophe Coevoet Date: Wed, 31 May 2017 17:20:46 +0200 Subject: [PATCH 0099/1099] Harden the debugging of Twig filters and functions Removing the environment and context arguments is now based on Twig metadata rather than on some wild guessing which might go wrong. --- .../Bridge/Twig/Command/DebugCommand.php | 23 ++++++++++--------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/src/Symfony/Bridge/Twig/Command/DebugCommand.php b/src/Symfony/Bridge/Twig/Command/DebugCommand.php index 349a8b81b83c1..7473221277c81 100644 --- a/src/Symfony/Bridge/Twig/Command/DebugCommand.php +++ b/src/Symfony/Bridge/Twig/Command/DebugCommand.php @@ -159,14 +159,20 @@ private function getMetadata($type, $entity) throw new \UnexpectedValueException('Unsupported callback type'); } + $args = $refl->getParameters(); + // filter out context/environment args - $args = array_filter($refl->getParameters(), function ($param) use ($entity) { - if ($entity->needsContext() && $param->getName() === 'context') { - return false; - } + if ($entity->needsEnvironment()) { + array_shift($args); + } + if ($entity->needsContext()) { + array_shift($args); + } - return !$param->getClass() || $param->getClass()->getName() !== 'Twig_Environment'; - }); + if ($type === 'filters') { + // remove the value the filter is applied on + array_shift($args); + } // format args $args = array_map(function ($param) { @@ -177,11 +183,6 @@ private function getMetadata($type, $entity) return $param->getName(); }, $args); - if ($type === 'filters') { - // remove the value the filter is applied on - array_shift($args); - } - return $args; } } From a990d5c558f195235b5390b27cb06ad4c00ba052 Mon Sep 17 00:00:00 2001 From: Ryan Weaver Date: Fri, 5 May 2017 07:31:04 -0400 Subject: [PATCH 0100/1099] Improving deprecation message when hitting the "deprecated type" lookup, but an alias is available --- .../Compiler/AutowirePass.php | 62 ++++++++++++------- .../Tests/Compiler/AutowirePassTest.php | 49 ++++++++++++++- 2 files changed, 86 insertions(+), 25 deletions(-) diff --git a/src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php b/src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php index bf7fc844c732b..49138f91bea34 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php @@ -114,7 +114,7 @@ protected function processValue($value, $isRoot = false) private function doProcessValue($value, $isRoot = false) { if ($value instanceof TypedReference) { - if ($ref = $this->getAutowiredReference($value)) { + if ($ref = $this->getAutowiredReference($value, $value->getRequiringClass() ? sprintf('for "%s" in "%s"', $value->getType(), $value->getRequiringClass()) : '')) { return $ref; } $this->container->log($this, $this->createTypeNotFoundMessage($value, 'it')); @@ -282,7 +282,7 @@ private function autowireMethod(\ReflectionFunctionAbstract $reflectionMethod, a continue; } - if (!$value = $this->getAutowiredReference($ref = new TypedReference($type, $type, !$parameter->isOptional() ? $class : ''))) { + if (!$value = $this->getAutowiredReference($ref = new TypedReference($type, $type, !$parameter->isOptional() ? $class : ''), 'for '.sprintf('argument "$%s" of method "%s()"', $parameter->name, $class.'::'.$method))) { $failureMessage = $this->createTypeNotFoundMessage($ref, sprintf('argument "$%s" of method "%s()"', $parameter->name, $class !== $this->currentId ? $class.'::'.$method : $method)); if ($parameter->isDefaultValueAvailable()) { @@ -316,7 +316,7 @@ private function autowireMethod(\ReflectionFunctionAbstract $reflectionMethod, a /** * @return TypedReference|null A reference to the service matching the given type, if any */ - private function getAutowiredReference(TypedReference $reference) + private function getAutowiredReference(TypedReference $reference, $deprecationMessage) { $this->lastFailure = null; $type = $reference->getType(); @@ -334,7 +334,14 @@ private function getAutowiredReference(TypedReference $reference) } if (isset($this->types[$type])) { - @trigger_error(sprintf('Autowiring services based on the types they implement is deprecated since Symfony 3.3 and won\'t be supported in version 4.0. You should %s the "%s" service to "%s" instead.', isset($this->types[$this->types[$type]]) ? 'alias' : 'rename (or alias)', $this->types[$type], $type), E_USER_DEPRECATED); + $message = 'Autowiring services based on the types they implement is deprecated since Symfony 3.3 and won\'t be supported in version 4.0.'; + if ($aliasSuggestion = $this->getAliasesSuggestionForType($type = $reference->getType(), $deprecationMessage)) { + $message .= ' '.$aliasSuggestion; + } else { + $message .= sprintf(' You should %s the "%s" service to "%s" instead.', isset($this->types[$this->types[$type]]) ? 'alias' : 'rename (or alias)', $this->types[$type], $type); + } + + @trigger_error($message, E_USER_DEPRECATED); return new TypedReference($this->types[$type], $type); } @@ -490,25 +497,9 @@ private function createTypeNotFoundMessage(TypedReference $reference, $label) private function createTypeAlternatives(TypedReference $reference) { - $type = $reference->getType(); - $aliases = array(); - foreach (class_parents($type) + class_implements($type) as $parent) { - if ($this->container->has($parent) && !$this->container->findDefinition($parent)->isAbstract()) { - $aliases[] = $parent; - } - } - - if (1 < $len = count($aliases)) { - $message = ' Try changing the type-hint to one of its parents: '; - for ($i = 0, --$len; $i < $len; ++$i) { - $message .= sprintf('%s "%s", ', class_exists($aliases[$i], false) ? 'class' : 'interface', $aliases[$i]); - } - $message .= sprintf('or %s "%s".', class_exists($aliases[$i], false) ? 'class' : 'interface', $aliases[$i]); - - return $message; - } - if ($aliases) { - return sprintf(' Try changing the type-hint to "%s" instead.', $aliases[0]); + // try suggesting available aliases first + if ($message = $this->getAliasesSuggestionForType($type = $reference->getType())) { + return ' '.$message; } if (isset($this->ambiguousServiceTypes[$type])) { @@ -548,4 +539,29 @@ private static function getResourceMetadataForMethod(\ReflectionMethod $method) return $methodArgumentsMetadata; } + + private function getAliasesSuggestionForType($type, $extraContext = null) + { + $aliases = array(); + foreach (class_parents($type) + class_implements($type) as $parent) { + if ($this->container->has($parent) && !$this->container->findDefinition($parent)->isAbstract()) { + $aliases[] = $parent; + } + } + + $extraContext = $extraContext ? ' '.$extraContext : ''; + if (1 < $len = count($aliases)) { + $message = sprintf('Try changing the type-hint%s to one of its parents: ', $extraContext); + for ($i = 0, --$len; $i < $len; ++$i) { + $message .= sprintf('%s "%s", ', class_exists($aliases[$i], false) ? 'class' : 'interface', $aliases[$i]); + } + $message .= sprintf('or %s "%s".', class_exists($aliases[$i], false) ? 'class' : 'interface', $aliases[$i]); + + return $message; + } + + if ($aliases) { + return sprintf('Try changing the type-hint%s to "%s" instead.', $extraContext, $aliases[0]); + } + } } diff --git a/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowirePassTest.php b/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowirePassTest.php index ca297f217495d..41ad5634132c0 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowirePassTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowirePassTest.php @@ -78,6 +78,28 @@ public function testProcessAutowireParent() $this->assertEquals(B::class, (string) $container->getDefinition('c')->getArgument(0)); } + /** + * @group legacy + * @expectedDeprecation Autowiring services based on the types they implement is deprecated since Symfony 3.3 and won't be supported in version 4.0. Try changing the type-hint for argument "$a" of method "Symfony\Component\DependencyInjection\Tests\Compiler\C::__construct()" to "Symfony\Component\DependencyInjection\Tests\Compiler\AInterface" instead. + * @expectedExceptionInSymfony4 \Symfony\Component\DependencyInjection\Exception\RuntimeException + * @expectedExceptionMessageInSymfony4 Cannot autowire service "c": argument "$a" of method "Symfony\Component\DependencyInjection\Tests\Compiler\C::__construct()" references class "Symfony\Component\DependencyInjection\Tests\Compiler\A" but no such service exists. You should maybe alias this class to the existing "Symfony\Component\DependencyInjection\Tests\Compiler\B" service. + */ + public function testProcessLegacyAutowireWithAvailableInterface() + { + $container = new ContainerBuilder(); + + $container->setAlias(AInterface::class, B::class); + $container->register(B::class); + $cDefinition = $container->register('c', __NAMESPACE__.'\C'); + $cDefinition->setAutowired(true); + + (new ResolveClassPass())->process($container); + (new AutowirePass())->process($container); + + $this->assertCount(1, $container->getDefinition('c')->getArguments()); + $this->assertEquals(B::class, (string) $container->getDefinition('c')->getArgument(0)); + } + /** * @group legacy * @expectedDeprecation Autowiring services based on the types they implement is deprecated since Symfony 3.3 and won't be supported in version 4.0. You should alias the "Symfony\Component\DependencyInjection\Tests\Compiler\F" service to "Symfony\Component\DependencyInjection\Tests\Compiler\DInterface" instead. @@ -730,7 +752,7 @@ public function provideNotWireableCalls() /** * @group legacy - * @expectedDeprecation Autowiring services based on the types they implement is deprecated since Symfony 3.3 and won't be supported in version 4.0. You should rename (or alias) the "i" service to "Symfony\Component\DependencyInjection\Tests\Compiler\I" instead. + * @expectedDeprecation Autowiring services based on the types they implement is deprecated since Symfony 3.3 and won't be supported in version 4.0. Try changing the type-hint for argument "$i" of method "Symfony\Component\DependencyInjection\Tests\Compiler\J::__construct()" to "Symfony\Component\DependencyInjection\Tests\Compiler\IInterface" instead. * @expectedExceptionInSymfony4 \Symfony\Component\DependencyInjection\Exception\AutowiringFailedException * @expectedExceptionMessageInSymfony4 Cannot autowire service "j": argument "$i" of method "Symfony\Component\DependencyInjection\Tests\Compiler\J::__construct()" references class "Symfony\Component\DependencyInjection\Tests\Compiler\I" but no such service exists. Try changing the type-hint to "Symfony\Component\DependencyInjection\Tests\Compiler\IInterface" instead. */ @@ -747,6 +769,25 @@ public function testByIdAlternative() $pass->process($container); } + /** + * @group legacy + * @expectedDeprecation Autowiring services based on the types they implement is deprecated since Symfony 3.3 and won't be supported in version 4.0. Try changing the type-hint for "Symfony\Component\DependencyInjection\Tests\Compiler\A" in "Symfony\Component\DependencyInjection\Tests\Compiler\Bar" to "Symfony\Component\DependencyInjection\Tests\Compiler\AInterface" instead. + */ + public function testTypedReferenceDeprecationNotice() + { + $container = new ContainerBuilder(); + + $container->register('aClass', A::class); + $container->setAlias(AInterface::class, 'aClass'); + $container + ->register('bar', Bar::class) + ->setProperty('a', array(new TypedReference(A::class, A::class, Bar::class))) + ; + + $pass = new AutowirePass(); + $pass->process($container); + } + /** * @expectedException \Symfony\Component\DependencyInjection\Exception\AutowiringFailedException * @expectedExceptionMessage Cannot autowire service "j": argument "$i" of method "Symfony\Component\DependencyInjection\Tests\Compiler\J::__construct()" references class "Symfony\Component\DependencyInjection\Tests\Compiler\I" but no such service exists. Try changing the type-hint to "Symfony\Component\DependencyInjection\Tests\Compiler\IInterface" instead. @@ -798,7 +839,11 @@ public function __construct(Foo $foo) } } -class A +interface AInterface +{ +} + +class A implements AInterface { public static function create(Foo $foo) { From 793b9a001f5fa09a501322aa4dcb8a3506fb6da2 Mon Sep 17 00:00:00 2001 From: Ryan Weaver Date: Wed, 31 May 2017 10:32:39 -0400 Subject: [PATCH 0101/1099] [DI] Autowiring exception thrown when inlined service is removed --- .../Compiler/AutowireExceptionPass.php | 16 ++++++- .../Compiler/InlineServiceDefinitionsPass.php | 6 ++- .../Compiler/AutowireExceptionPassTest.php | 43 +++++++++++++++++-- .../InlineServiceDefinitionsPassTest.php | 6 +-- 4 files changed, 62 insertions(+), 9 deletions(-) diff --git a/src/Symfony/Component/DependencyInjection/Compiler/AutowireExceptionPass.php b/src/Symfony/Component/DependencyInjection/Compiler/AutowireExceptionPass.php index 2ee9427a15098..a1ed422f7336d 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/AutowireExceptionPass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/AutowireExceptionPass.php @@ -44,9 +44,23 @@ public function process(ContainerBuilder $container) $this->inlineServicePass = null; foreach ($exceptions as $exception) { - if ($container->hasDefinition($exception->getServiceId()) || in_array($exception->getServiceId(), $inlinedIds)) { + if ($this->doesServiceExistInTheContainer($exception->getServiceId(), $container, $inlinedIds)) { throw $exception; } } } + + private function doesServiceExistInTheContainer($serviceId, ContainerBuilder $container, array $inlinedIds) + { + if ($container->hasDefinition($serviceId)) { + return true; + } + + // was the service inlined? Of so, does its parent service exist? + if (isset($inlinedIds[$serviceId])) { + return $this->doesServiceExistInTheContainer($inlinedIds[$serviceId], $container, $inlinedIds); + } + + return false; + } } diff --git a/src/Symfony/Component/DependencyInjection/Compiler/InlineServiceDefinitionsPass.php b/src/Symfony/Component/DependencyInjection/Compiler/InlineServiceDefinitionsPass.php index b084d7e4dce28..a2eb511c643d7 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/InlineServiceDefinitionsPass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/InlineServiceDefinitionsPass.php @@ -36,7 +36,9 @@ public function setRepeatedPass(RepeatedPass $repeatedPass) /** * Returns an array of all services inlined by this pass. * - * @return array Service id strings + * The key is the inlined service id and its value is the service it was inlined into. + * + * @return array */ public function getInlinedServiceIds() { @@ -57,7 +59,7 @@ protected function processValue($value, $isRoot = false) if ($this->isInlineableDefinition($id, $definition, $this->container->getCompiler()->getServiceReferenceGraph())) { $this->container->log($this, sprintf('Inlined service "%s" to "%s".', $id, $this->currentId)); - $this->inlinedServiceIds[] = $id; + $this->inlinedServiceIds[$id] = $this->currentId; if ($definition->isShared()) { return $definition; diff --git a/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowireExceptionPassTest.php b/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowireExceptionPassTest.php index 092b6401c48ef..8cd03f578ac02 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowireExceptionPassTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowireExceptionPassTest.php @@ -54,7 +54,7 @@ public function testThrowExceptionIfServiceInlined() $autowirePass = $this->getMockBuilder(AutowirePass::class) ->getMock(); - $autowireException = new AutowiringFailedException('foo_service_id', 'An autowiring exception message'); + $autowireException = new AutowiringFailedException('a_service', 'An autowiring exception message'); $autowirePass->expects($this->any()) ->method('getAutowiringExceptions') ->will($this->returnValue(array($autowireException))); @@ -63,10 +63,16 @@ public function testThrowExceptionIfServiceInlined() ->getMock(); $inlinePass->expects($this->any()) ->method('getInlinedServiceIds') - ->will($this->returnValue(array('foo_service_id'))); + ->will($this->returnValue(array( + // a_service inlined into b_service + 'a_service' => 'b_service', + // b_service inlined into c_service + 'b_service' => 'c_service', + ))); - // don't register the foo_service_id service $container = new ContainerBuilder(); + // ONLY register c_service in the final container + $container->register('c_service', 'stdClass'); $pass = new AutowireExceptionPass($autowirePass, $inlinePass); @@ -78,6 +84,37 @@ public function testThrowExceptionIfServiceInlined() } } + public function testDoNotThrowExceptionIfServiceInlinedButRemoved() + { + $autowirePass = $this->getMockBuilder(AutowirePass::class) + ->getMock(); + + $autowireException = new AutowiringFailedException('a_service', 'An autowiring exception message'); + $autowirePass->expects($this->any()) + ->method('getAutowiringExceptions') + ->will($this->returnValue(array($autowireException))); + + $inlinePass = $this->getMockBuilder(InlineServiceDefinitionsPass::class) + ->getMock(); + $inlinePass->expects($this->any()) + ->method('getInlinedServiceIds') + ->will($this->returnValue(array( + // a_service inlined into b_service + 'a_service' => 'b_service', + // b_service inlined into c_service + 'b_service' => 'c_service', + ))); + + // do NOT register c_service in the container + $container = new ContainerBuilder(); + + $pass = new AutowireExceptionPass($autowirePass, $inlinePass); + + $pass->process($container); + // mark the test as passed + $this->assertTrue(true); + } + public function testNoExceptionIfServiceRemoved() { $autowirePass = $this->getMockBuilder(AutowirePass::class) diff --git a/src/Symfony/Component/DependencyInjection/Tests/Compiler/InlineServiceDefinitionsPassTest.php b/src/Symfony/Component/DependencyInjection/Tests/Compiler/InlineServiceDefinitionsPassTest.php index d241758b04425..0eaea411f114f 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Compiler/InlineServiceDefinitionsPassTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Compiler/InlineServiceDefinitionsPassTest.php @@ -252,7 +252,7 @@ public function testProcessDoesNotSetLazyArgumentValuesAfterInlining() $this->assertSame('inline', (string) $values[0]); } - public function testGetInlinedServiceIds() + public function testGetInlinedServiceIdData() { $container = new ContainerBuilder(); $container @@ -265,7 +265,7 @@ public function testGetInlinedServiceIds() ; $container - ->register('service') + ->register('other_service') ->setArguments(array(new Reference('inlinable.service'))) ; @@ -273,7 +273,7 @@ public function testGetInlinedServiceIds() $repeatedPass = new RepeatedPass(array(new AnalyzeServiceReferencesPass(), $inlinePass)); $repeatedPass->process($container); - $this->assertEquals(array('inlinable.service'), $inlinePass->getInlinedServiceIds()); + $this->assertEquals(array('inlinable.service' => 'other_service'), $inlinePass->getInlinedServiceIds()); } protected function process(ContainerBuilder $container) From e8f70c75b98fe709b2890829b5bc12d47b90fec6 Mon Sep 17 00:00:00 2001 From: Roland Franssen Date: Tue, 30 May 2017 16:55:30 +0200 Subject: [PATCH 0102/1099] [Cache] Ignore missing annotations.php --- src/Symfony/Component/Cache/Traits/PhpArrayTrait.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/Cache/Traits/PhpArrayTrait.php b/src/Symfony/Component/Cache/Traits/PhpArrayTrait.php index 2b0ae50f6a1ac..2d2c7db3d014f 100644 --- a/src/Symfony/Component/Cache/Traits/PhpArrayTrait.php +++ b/src/Symfony/Component/Cache/Traits/PhpArrayTrait.php @@ -126,6 +126,6 @@ public function clear() */ private function initialize() { - $this->values = @(include $this->file) ?: array(); + $this->values = file_exists($this->file) ? (include $this->file ?: array()) : array(); } } From 996698d996801f64cb6241cec1e1b3d5d77eacf3 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Thu, 1 Jun 2017 08:27:51 +0200 Subject: [PATCH 0103/1099] [DI] Deal with inlined non-shared services --- .../Compiler/AutowireExceptionPass.php | 6 +++++- .../Compiler/InlineServiceDefinitionsPass.php | 4 ++-- .../Tests/Compiler/AutowireExceptionPassTest.php | 8 ++++---- .../Tests/Compiler/InlineServiceDefinitionsPassTest.php | 2 +- 4 files changed, 12 insertions(+), 8 deletions(-) diff --git a/src/Symfony/Component/DependencyInjection/Compiler/AutowireExceptionPass.php b/src/Symfony/Component/DependencyInjection/Compiler/AutowireExceptionPass.php index a1ed422f7336d..12be3d915fd10 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/AutowireExceptionPass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/AutowireExceptionPass.php @@ -58,7 +58,11 @@ private function doesServiceExistInTheContainer($serviceId, ContainerBuilder $co // was the service inlined? Of so, does its parent service exist? if (isset($inlinedIds[$serviceId])) { - return $this->doesServiceExistInTheContainer($inlinedIds[$serviceId], $container, $inlinedIds); + foreach ($inlinedIds[$serviceId] as $parentId) { + if ($this->doesServiceExistInTheContainer($parentId, $container, $inlinedIds)) { + return true; + } + } } return false; diff --git a/src/Symfony/Component/DependencyInjection/Compiler/InlineServiceDefinitionsPass.php b/src/Symfony/Component/DependencyInjection/Compiler/InlineServiceDefinitionsPass.php index a2eb511c643d7..7a5da70d09567 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/InlineServiceDefinitionsPass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/InlineServiceDefinitionsPass.php @@ -36,7 +36,7 @@ public function setRepeatedPass(RepeatedPass $repeatedPass) /** * Returns an array of all services inlined by this pass. * - * The key is the inlined service id and its value is the service it was inlined into. + * The key is the inlined service id and its value is the list of services it was inlined into. * * @return array */ @@ -59,7 +59,7 @@ protected function processValue($value, $isRoot = false) if ($this->isInlineableDefinition($id, $definition, $this->container->getCompiler()->getServiceReferenceGraph())) { $this->container->log($this, sprintf('Inlined service "%s" to "%s".', $id, $this->currentId)); - $this->inlinedServiceIds[$id] = $this->currentId; + $this->inlinedServiceIds[$id][] = $this->currentId; if ($definition->isShared()) { return $definition; diff --git a/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowireExceptionPassTest.php b/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowireExceptionPassTest.php index 8cd03f578ac02..4f0b3d6c2566c 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowireExceptionPassTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowireExceptionPassTest.php @@ -65,9 +65,9 @@ public function testThrowExceptionIfServiceInlined() ->method('getInlinedServiceIds') ->will($this->returnValue(array( // a_service inlined into b_service - 'a_service' => 'b_service', + 'a_service' => array('b_service'), // b_service inlined into c_service - 'b_service' => 'c_service', + 'b_service' => array('c_service'), ))); $container = new ContainerBuilder(); @@ -100,9 +100,9 @@ public function testDoNotThrowExceptionIfServiceInlinedButRemoved() ->method('getInlinedServiceIds') ->will($this->returnValue(array( // a_service inlined into b_service - 'a_service' => 'b_service', + 'a_service' => array('b_service'), // b_service inlined into c_service - 'b_service' => 'c_service', + 'b_service' => array('c_service'), ))); // do NOT register c_service in the container diff --git a/src/Symfony/Component/DependencyInjection/Tests/Compiler/InlineServiceDefinitionsPassTest.php b/src/Symfony/Component/DependencyInjection/Tests/Compiler/InlineServiceDefinitionsPassTest.php index 0eaea411f114f..f0dd7fe74dc4c 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Compiler/InlineServiceDefinitionsPassTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Compiler/InlineServiceDefinitionsPassTest.php @@ -273,7 +273,7 @@ public function testGetInlinedServiceIdData() $repeatedPass = new RepeatedPass(array(new AnalyzeServiceReferencesPass(), $inlinePass)); $repeatedPass->process($container); - $this->assertEquals(array('inlinable.service' => 'other_service'), $inlinePass->getInlinedServiceIds()); + $this->assertEquals(array('inlinable.service' => array('other_service')), $inlinePass->getInlinedServiceIds()); } protected function process(ContainerBuilder $container) From 71d4e366a9bcea717fc418b41e5fe5821d677635 Mon Sep 17 00:00:00 2001 From: Frank de Jonge Date: Thu, 1 Jun 2017 11:46:06 +0200 Subject: [PATCH 0104/1099] [Routing] Allow GET requests to be redirected. Fixes #23004 --- .../Matcher/Dumper/PhpMatcherDumper.php | 2 +- .../Tests/Fixtures/dumper/url_matcher6.php | 204 ++++++++++++++++ .../Tests/Fixtures/dumper/url_matcher7.php | 228 ++++++++++++++++++ .../Matcher/Dumper/PhpMatcherDumperTest.php | 21 ++ 4 files changed, 454 insertions(+), 1 deletion(-) create mode 100644 src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher6.php create mode 100644 src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher7.php diff --git a/src/Symfony/Component/Routing/Matcher/Dumper/PhpMatcherDumper.php b/src/Symfony/Component/Routing/Matcher/Dumper/PhpMatcherDumper.php index 7f0d0520b938f..8eae68c4c280e 100644 --- a/src/Symfony/Component/Routing/Matcher/Dumper/PhpMatcherDumper.php +++ b/src/Symfony/Component/Routing/Matcher/Dumper/PhpMatcherDumper.php @@ -238,7 +238,7 @@ private function compileRoute(Route $route, $name, $supportsRedirections, $paren $hostMatches = false; $methods = $route->getMethods(); - $supportsTrailingSlash = $supportsRedirections && (!$methods || in_array('HEAD', $methods)); + $supportsTrailingSlash = $supportsRedirections && (!$methods || in_array('HEAD', $methods) || in_array('GET', $methods)); $regex = $compiledRoute->getRegex(); if (!count($compiledRoute->getPathVariables()) && false !== preg_match('#^(.)\^(?P.*?)\$\1#'.(substr($regex, -1) === 'u' ? 'u' : ''), $regex, $m)) { diff --git a/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher6.php b/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher6.php new file mode 100644 index 0000000000000..c7645521f5a6e --- /dev/null +++ b/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher6.php @@ -0,0 +1,204 @@ +context = $context; + } + + public function match($pathinfo) + { + $allow = array(); + $pathinfo = rawurldecode($pathinfo); + $trimmedPathinfo = rtrim($pathinfo, '/'); + $context = $this->context; + $request = $this->request; + $requestMethod = $canonicalMethod = $context->getMethod(); + $scheme = $context->getScheme(); + + if ('HEAD' === $requestMethod) { + $canonicalMethod = 'GET'; + } + + + if (0 === strpos($pathinfo, '/trailing/simple')) { + // simple_trailing_slash_no_methods + if ('/trailing/simple/no-methods/' === $pathinfo) { + return array('_route' => 'simple_trailing_slash_no_methods'); + } + + // simple_trailing_slash_GET_method + if ('/trailing/simple/get-method/' === $pathinfo) { + if ('GET' !== $canonicalMethod) { + $allow[] = 'GET'; + goto not_simple_trailing_slash_GET_method; + } + + return array('_route' => 'simple_trailing_slash_GET_method'); + } + not_simple_trailing_slash_GET_method: + + // simple_trailing_slash_HEAD_method + if ('/trailing/simple/head-method/' === $pathinfo) { + if ('HEAD' !== $requestMethod) { + $allow[] = 'HEAD'; + goto not_simple_trailing_slash_HEAD_method; + } + + return array('_route' => 'simple_trailing_slash_HEAD_method'); + } + not_simple_trailing_slash_HEAD_method: + + // simple_trailing_slash_POST_method + if ('/trailing/simple/post-method/' === $pathinfo) { + if ('POST' !== $canonicalMethod) { + $allow[] = 'POST'; + goto not_simple_trailing_slash_POST_method; + } + + return array('_route' => 'simple_trailing_slash_POST_method'); + } + not_simple_trailing_slash_POST_method: + + } + + elseif (0 === strpos($pathinfo, '/trailing/regex')) { + // regex_trailing_slash_no_methods + if (0 === strpos($pathinfo, '/trailing/regex/no-methods') && preg_match('#^/trailing/regex/no\\-methods/(?P[^/]++)/$#s', $pathinfo, $matches)) { + return $this->mergeDefaults(array_replace($matches, array('_route' => 'regex_trailing_slash_no_methods')), array ()); + } + + // regex_trailing_slash_GET_method + if (0 === strpos($pathinfo, '/trailing/regex/get-method') && preg_match('#^/trailing/regex/get\\-method/(?P[^/]++)/$#s', $pathinfo, $matches)) { + if ('GET' !== $canonicalMethod) { + $allow[] = 'GET'; + goto not_regex_trailing_slash_GET_method; + } + + return $this->mergeDefaults(array_replace($matches, array('_route' => 'regex_trailing_slash_GET_method')), array ()); + } + not_regex_trailing_slash_GET_method: + + // regex_trailing_slash_HEAD_method + if (0 === strpos($pathinfo, '/trailing/regex/head-method') && preg_match('#^/trailing/regex/head\\-method/(?P[^/]++)/$#s', $pathinfo, $matches)) { + if ('HEAD' !== $requestMethod) { + $allow[] = 'HEAD'; + goto not_regex_trailing_slash_HEAD_method; + } + + return $this->mergeDefaults(array_replace($matches, array('_route' => 'regex_trailing_slash_HEAD_method')), array ()); + } + not_regex_trailing_slash_HEAD_method: + + // regex_trailing_slash_POST_method + if (0 === strpos($pathinfo, '/trailing/regex/post-method') && preg_match('#^/trailing/regex/post\\-method/(?P[^/]++)/$#s', $pathinfo, $matches)) { + if ('POST' !== $canonicalMethod) { + $allow[] = 'POST'; + goto not_regex_trailing_slash_POST_method; + } + + return $this->mergeDefaults(array_replace($matches, array('_route' => 'regex_trailing_slash_POST_method')), array ()); + } + not_regex_trailing_slash_POST_method: + + } + + elseif (0 === strpos($pathinfo, '/not-trailing/simple')) { + // simple_not_trailing_slash_no_methods + if ('/not-trailing/simple/no-methods' === $pathinfo) { + return array('_route' => 'simple_not_trailing_slash_no_methods'); + } + + // simple_not_trailing_slash_GET_method + if ('/not-trailing/simple/get-method' === $pathinfo) { + if ('GET' !== $canonicalMethod) { + $allow[] = 'GET'; + goto not_simple_not_trailing_slash_GET_method; + } + + return array('_route' => 'simple_not_trailing_slash_GET_method'); + } + not_simple_not_trailing_slash_GET_method: + + // simple_not_trailing_slash_HEAD_method + if ('/not-trailing/simple/head-method' === $pathinfo) { + if ('HEAD' !== $requestMethod) { + $allow[] = 'HEAD'; + goto not_simple_not_trailing_slash_HEAD_method; + } + + return array('_route' => 'simple_not_trailing_slash_HEAD_method'); + } + not_simple_not_trailing_slash_HEAD_method: + + // simple_not_trailing_slash_POST_method + if ('/not-trailing/simple/post-method' === $pathinfo) { + if ('POST' !== $canonicalMethod) { + $allow[] = 'POST'; + goto not_simple_not_trailing_slash_POST_method; + } + + return array('_route' => 'simple_not_trailing_slash_POST_method'); + } + not_simple_not_trailing_slash_POST_method: + + } + + elseif (0 === strpos($pathinfo, '/not-trailing/regex')) { + // regex_not_trailing_slash_no_methods + if (0 === strpos($pathinfo, '/not-trailing/regex/no-methods') && preg_match('#^/not\\-trailing/regex/no\\-methods/(?P[^/]++)$#s', $pathinfo, $matches)) { + return $this->mergeDefaults(array_replace($matches, array('_route' => 'regex_not_trailing_slash_no_methods')), array ()); + } + + // regex_not_trailing_slash_GET_method + if (0 === strpos($pathinfo, '/not-trailing/regex/get-method') && preg_match('#^/not\\-trailing/regex/get\\-method/(?P[^/]++)$#s', $pathinfo, $matches)) { + if ('GET' !== $canonicalMethod) { + $allow[] = 'GET'; + goto not_regex_not_trailing_slash_GET_method; + } + + return $this->mergeDefaults(array_replace($matches, array('_route' => 'regex_not_trailing_slash_GET_method')), array ()); + } + not_regex_not_trailing_slash_GET_method: + + // regex_not_trailing_slash_HEAD_method + if (0 === strpos($pathinfo, '/not-trailing/regex/head-method') && preg_match('#^/not\\-trailing/regex/head\\-method/(?P[^/]++)$#s', $pathinfo, $matches)) { + if ('HEAD' !== $requestMethod) { + $allow[] = 'HEAD'; + goto not_regex_not_trailing_slash_HEAD_method; + } + + return $this->mergeDefaults(array_replace($matches, array('_route' => 'regex_not_trailing_slash_HEAD_method')), array ()); + } + not_regex_not_trailing_slash_HEAD_method: + + // regex_not_trailing_slash_POST_method + if (0 === strpos($pathinfo, '/not-trailing/regex/post-method') && preg_match('#^/not\\-trailing/regex/post\\-method/(?P[^/]++)$#s', $pathinfo, $matches)) { + if ('POST' !== $canonicalMethod) { + $allow[] = 'POST'; + goto not_regex_not_trailing_slash_POST_method; + } + + return $this->mergeDefaults(array_replace($matches, array('_route' => 'regex_not_trailing_slash_POST_method')), array ()); + } + not_regex_not_trailing_slash_POST_method: + + } + + throw 0 < count($allow) ? new MethodNotAllowedException(array_unique($allow)) : new ResourceNotFoundException(); + } +} diff --git a/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher7.php b/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher7.php new file mode 100644 index 0000000000000..876a90f2da468 --- /dev/null +++ b/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher7.php @@ -0,0 +1,228 @@ +context = $context; + } + + public function match($pathinfo) + { + $allow = array(); + $pathinfo = rawurldecode($pathinfo); + $trimmedPathinfo = rtrim($pathinfo, '/'); + $context = $this->context; + $request = $this->request; + $requestMethod = $canonicalMethod = $context->getMethod(); + $scheme = $context->getScheme(); + + if ('HEAD' === $requestMethod) { + $canonicalMethod = 'GET'; + } + + + if (0 === strpos($pathinfo, '/trailing/simple')) { + // simple_trailing_slash_no_methods + if ('/trailing/simple/no-methods' === $trimmedPathinfo) { + if (substr($pathinfo, -1) !== '/') { + return $this->redirect($pathinfo.'/', 'simple_trailing_slash_no_methods'); + } + + return array('_route' => 'simple_trailing_slash_no_methods'); + } + + // simple_trailing_slash_GET_method + if ('/trailing/simple/get-method' === $trimmedPathinfo) { + if ('GET' !== $canonicalMethod) { + $allow[] = 'GET'; + goto not_simple_trailing_slash_GET_method; + } + + if (substr($pathinfo, -1) !== '/') { + return $this->redirect($pathinfo.'/', 'simple_trailing_slash_GET_method'); + } + + return array('_route' => 'simple_trailing_slash_GET_method'); + } + not_simple_trailing_slash_GET_method: + + // simple_trailing_slash_HEAD_method + if ('/trailing/simple/head-method' === $trimmedPathinfo) { + if ('HEAD' !== $requestMethod) { + $allow[] = 'HEAD'; + goto not_simple_trailing_slash_HEAD_method; + } + + if (substr($pathinfo, -1) !== '/') { + return $this->redirect($pathinfo.'/', 'simple_trailing_slash_HEAD_method'); + } + + return array('_route' => 'simple_trailing_slash_HEAD_method'); + } + not_simple_trailing_slash_HEAD_method: + + // simple_trailing_slash_POST_method + if ('/trailing/simple/post-method/' === $pathinfo) { + if ('POST' !== $canonicalMethod) { + $allow[] = 'POST'; + goto not_simple_trailing_slash_POST_method; + } + + return array('_route' => 'simple_trailing_slash_POST_method'); + } + not_simple_trailing_slash_POST_method: + + } + + elseif (0 === strpos($pathinfo, '/trailing/regex')) { + // regex_trailing_slash_no_methods + if (0 === strpos($pathinfo, '/trailing/regex/no-methods') && preg_match('#^/trailing/regex/no\\-methods/(?P[^/]++)/?$#s', $pathinfo, $matches)) { + if (substr($pathinfo, -1) !== '/') { + return $this->redirect($pathinfo.'/', 'regex_trailing_slash_no_methods'); + } + + return $this->mergeDefaults(array_replace($matches, array('_route' => 'regex_trailing_slash_no_methods')), array ()); + } + + // regex_trailing_slash_GET_method + if (0 === strpos($pathinfo, '/trailing/regex/get-method') && preg_match('#^/trailing/regex/get\\-method/(?P[^/]++)/?$#s', $pathinfo, $matches)) { + if ('GET' !== $canonicalMethod) { + $allow[] = 'GET'; + goto not_regex_trailing_slash_GET_method; + } + + if (substr($pathinfo, -1) !== '/') { + return $this->redirect($pathinfo.'/', 'regex_trailing_slash_GET_method'); + } + + return $this->mergeDefaults(array_replace($matches, array('_route' => 'regex_trailing_slash_GET_method')), array ()); + } + not_regex_trailing_slash_GET_method: + + // regex_trailing_slash_HEAD_method + if (0 === strpos($pathinfo, '/trailing/regex/head-method') && preg_match('#^/trailing/regex/head\\-method/(?P[^/]++)/?$#s', $pathinfo, $matches)) { + if ('HEAD' !== $requestMethod) { + $allow[] = 'HEAD'; + goto not_regex_trailing_slash_HEAD_method; + } + + if (substr($pathinfo, -1) !== '/') { + return $this->redirect($pathinfo.'/', 'regex_trailing_slash_HEAD_method'); + } + + return $this->mergeDefaults(array_replace($matches, array('_route' => 'regex_trailing_slash_HEAD_method')), array ()); + } + not_regex_trailing_slash_HEAD_method: + + // regex_trailing_slash_POST_method + if (0 === strpos($pathinfo, '/trailing/regex/post-method') && preg_match('#^/trailing/regex/post\\-method/(?P[^/]++)/$#s', $pathinfo, $matches)) { + if ('POST' !== $canonicalMethod) { + $allow[] = 'POST'; + goto not_regex_trailing_slash_POST_method; + } + + return $this->mergeDefaults(array_replace($matches, array('_route' => 'regex_trailing_slash_POST_method')), array ()); + } + not_regex_trailing_slash_POST_method: + + } + + elseif (0 === strpos($pathinfo, '/not-trailing/simple')) { + // simple_not_trailing_slash_no_methods + if ('/not-trailing/simple/no-methods' === $pathinfo) { + return array('_route' => 'simple_not_trailing_slash_no_methods'); + } + + // simple_not_trailing_slash_GET_method + if ('/not-trailing/simple/get-method' === $pathinfo) { + if ('GET' !== $canonicalMethod) { + $allow[] = 'GET'; + goto not_simple_not_trailing_slash_GET_method; + } + + return array('_route' => 'simple_not_trailing_slash_GET_method'); + } + not_simple_not_trailing_slash_GET_method: + + // simple_not_trailing_slash_HEAD_method + if ('/not-trailing/simple/head-method' === $pathinfo) { + if ('HEAD' !== $requestMethod) { + $allow[] = 'HEAD'; + goto not_simple_not_trailing_slash_HEAD_method; + } + + return array('_route' => 'simple_not_trailing_slash_HEAD_method'); + } + not_simple_not_trailing_slash_HEAD_method: + + // simple_not_trailing_slash_POST_method + if ('/not-trailing/simple/post-method' === $pathinfo) { + if ('POST' !== $canonicalMethod) { + $allow[] = 'POST'; + goto not_simple_not_trailing_slash_POST_method; + } + + return array('_route' => 'simple_not_trailing_slash_POST_method'); + } + not_simple_not_trailing_slash_POST_method: + + } + + elseif (0 === strpos($pathinfo, '/not-trailing/regex')) { + // regex_not_trailing_slash_no_methods + if (0 === strpos($pathinfo, '/not-trailing/regex/no-methods') && preg_match('#^/not\\-trailing/regex/no\\-methods/(?P[^/]++)$#s', $pathinfo, $matches)) { + return $this->mergeDefaults(array_replace($matches, array('_route' => 'regex_not_trailing_slash_no_methods')), array ()); + } + + // regex_not_trailing_slash_GET_method + if (0 === strpos($pathinfo, '/not-trailing/regex/get-method') && preg_match('#^/not\\-trailing/regex/get\\-method/(?P[^/]++)$#s', $pathinfo, $matches)) { + if ('GET' !== $canonicalMethod) { + $allow[] = 'GET'; + goto not_regex_not_trailing_slash_GET_method; + } + + return $this->mergeDefaults(array_replace($matches, array('_route' => 'regex_not_trailing_slash_GET_method')), array ()); + } + not_regex_not_trailing_slash_GET_method: + + // regex_not_trailing_slash_HEAD_method + if (0 === strpos($pathinfo, '/not-trailing/regex/head-method') && preg_match('#^/not\\-trailing/regex/head\\-method/(?P[^/]++)$#s', $pathinfo, $matches)) { + if ('HEAD' !== $requestMethod) { + $allow[] = 'HEAD'; + goto not_regex_not_trailing_slash_HEAD_method; + } + + return $this->mergeDefaults(array_replace($matches, array('_route' => 'regex_not_trailing_slash_HEAD_method')), array ()); + } + not_regex_not_trailing_slash_HEAD_method: + + // regex_not_trailing_slash_POST_method + if (0 === strpos($pathinfo, '/not-trailing/regex/post-method') && preg_match('#^/not\\-trailing/regex/post\\-method/(?P[^/]++)$#s', $pathinfo, $matches)) { + if ('POST' !== $canonicalMethod) { + $allow[] = 'POST'; + goto not_regex_not_trailing_slash_POST_method; + } + + return $this->mergeDefaults(array_replace($matches, array('_route' => 'regex_not_trailing_slash_POST_method')), array ()); + } + not_regex_not_trailing_slash_POST_method: + + } + + throw 0 < count($allow) ? new MethodNotAllowedException(array_unique($allow)) : new ResourceNotFoundException(); + } +} diff --git a/src/Symfony/Component/Routing/Tests/Matcher/Dumper/PhpMatcherDumperTest.php b/src/Symfony/Component/Routing/Tests/Matcher/Dumper/PhpMatcherDumperTest.php index e26b48e78d1f5..9d4f086be7702 100644 --- a/src/Symfony/Component/Routing/Tests/Matcher/Dumper/PhpMatcherDumperTest.php +++ b/src/Symfony/Component/Routing/Tests/Matcher/Dumper/PhpMatcherDumperTest.php @@ -345,12 +345,33 @@ public function getRouteCollections() $groupOptimisedCollection->add('slashed_b', new Route('/slashed/group/b/')); $groupOptimisedCollection->add('slashed_c', new Route('/slashed/group/c/')); + $trailingSlashCollection = new RouteCollection(); + $trailingSlashCollection->add('simple_trailing_slash_no_methods', new Route('/trailing/simple/no-methods/', array(), array(), array(), '', array(), array())); + $trailingSlashCollection->add('simple_trailing_slash_GET_method', new Route('/trailing/simple/get-method/', array(), array(), array(), '', array(), array('GET'))); + $trailingSlashCollection->add('simple_trailing_slash_HEAD_method', new Route('/trailing/simple/head-method/', array(), array(), array(), '', array(), array('HEAD'))); + $trailingSlashCollection->add('simple_trailing_slash_POST_method', new Route('/trailing/simple/post-method/', array(), array(), array(), '', array(), array('POST'))); + $trailingSlashCollection->add('regex_trailing_slash_no_methods', new Route('/trailing/regex/no-methods/{param}/', array(), array(), array(), '', array(), array())); + $trailingSlashCollection->add('regex_trailing_slash_GET_method', new Route('/trailing/regex/get-method/{param}/', array(), array(), array(), '', array(), array('GET'))); + $trailingSlashCollection->add('regex_trailing_slash_HEAD_method', new Route('/trailing/regex/head-method/{param}/', array(), array(), array(), '', array(), array('HEAD'))); + $trailingSlashCollection->add('regex_trailing_slash_POST_method', new Route('/trailing/regex/post-method/{param}/', array(), array(), array(), '', array(), array('POST'))); + + $trailingSlashCollection->add('simple_not_trailing_slash_no_methods', new Route('/not-trailing/simple/no-methods', array(), array(), array(), '', array(), array())); + $trailingSlashCollection->add('simple_not_trailing_slash_GET_method', new Route('/not-trailing/simple/get-method', array(), array(), array(), '', array(), array('GET'))); + $trailingSlashCollection->add('simple_not_trailing_slash_HEAD_method', new Route('/not-trailing/simple/head-method', array(), array(), array(), '', array(), array('HEAD'))); + $trailingSlashCollection->add('simple_not_trailing_slash_POST_method', new Route('/not-trailing/simple/post-method', array(), array(), array(), '', array(), array('POST'))); + $trailingSlashCollection->add('regex_not_trailing_slash_no_methods', new Route('/not-trailing/regex/no-methods/{param}', array(), array(), array(), '', array(), array())); + $trailingSlashCollection->add('regex_not_trailing_slash_GET_method', new Route('/not-trailing/regex/get-method/{param}', array(), array(), array(), '', array(), array('GET'))); + $trailingSlashCollection->add('regex_not_trailing_slash_HEAD_method', new Route('/not-trailing/regex/head-method/{param}', array(), array(), array(), '', array(), array('HEAD'))); + $trailingSlashCollection->add('regex_not_trailing_slash_POST_method', new Route('/not-trailing/regex/post-method/{param}', array(), array(), array(), '', array(), array('POST'))); + return array( array($collection, 'url_matcher1.php', array()), array($redirectCollection, 'url_matcher2.php', array('base_class' => 'Symfony\Component\Routing\Tests\Fixtures\RedirectableUrlMatcher')), array($rootprefixCollection, 'url_matcher3.php', array()), array($headMatchCasesCollection, 'url_matcher4.php', array()), array($groupOptimisedCollection, 'url_matcher5.php', array('base_class' => 'Symfony\Component\Routing\Tests\Fixtures\RedirectableUrlMatcher')), + array($trailingSlashCollection, 'url_matcher6.php', array()), + array($trailingSlashCollection, 'url_matcher7.php', array('base_class' => 'Symfony\Component\Routing\Tests\Fixtures\RedirectableUrlMatcher')), ); } } From f42c73f213b85ce173401dd416691a275a06f860 Mon Sep 17 00:00:00 2001 From: Romain Neutron Date: Wed, 31 May 2017 17:48:21 +0200 Subject: [PATCH 0105/1099] [Form] Fix \IntlDateFormatter timezone parameter usage to bypass PHP bug #66323 --- .../DataTransformer/DateTimeToLocalizedStringTransformer.php | 4 ++++ src/Symfony/Component/Form/Extension/Core/Type/DateType.php | 3 ++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/Form/Extension/Core/DataTransformer/DateTimeToLocalizedStringTransformer.php b/src/Symfony/Component/Form/Extension/Core/DataTransformer/DateTimeToLocalizedStringTransformer.php index 9411de82b4393..e1db36bda663d 100644 --- a/src/Symfony/Component/Form/Extension/Core/DataTransformer/DateTimeToLocalizedStringTransformer.php +++ b/src/Symfony/Component/Form/Extension/Core/DataTransformer/DateTimeToLocalizedStringTransformer.php @@ -163,6 +163,10 @@ protected function getIntlDateFormatter($ignoreTimezone = false) $dateFormat = $this->dateFormat; $timeFormat = $this->timeFormat; $timezone = $ignoreTimezone ? 'UTC' : $this->outputTimezone; + if (class_exists('IntlTimeZone', false)) { + // see https://bugs.php.net/bug.php?id=66323 + $timezone = \IntlTimeZone::createTimeZone($timezone); + } $calendar = $this->calendar; $pattern = $this->pattern; diff --git a/src/Symfony/Component/Form/Extension/Core/Type/DateType.php b/src/Symfony/Component/Form/Extension/Core/Type/DateType.php index 2bc433f8414f2..fdb7ff59e7022 100644 --- a/src/Symfony/Component/Form/Extension/Core/Type/DateType.php +++ b/src/Symfony/Component/Form/Extension/Core/Type/DateType.php @@ -77,7 +77,8 @@ public function buildForm(FormBuilderInterface $builder, array $options) \Locale::getDefault(), $dateFormat, $timeFormat, - null, + // see https://bugs.php.net/bug.php?id=66323 + class_exists('IntlTimeZone', false) ? \IntlTimeZone::createDefault() : null, $calendar, $pattern ); From 9578fd3eb6c3e9ab8cccd5a64cb12275f53c9b38 Mon Sep 17 00:00:00 2001 From: Ryan Weaver Date: Thu, 1 Jun 2017 06:36:44 -0400 Subject: [PATCH 0106/1099] Adding a new event subscriber that "parses" the _controller attribute in the FW --- .../ResolveControllerNameSubscriber.php | 48 +++++++++++++++++ .../FrameworkBundle/Resources/config/web.xml | 5 ++ .../ResolveControllerNameSubscriberTest.php | 54 +++++++++++++++++++ .../SubRequestServiceResolutionController.php | 38 +++++++++++++ .../Tests/Functional/SubRequestsTest.php | 8 +++ .../ControllerServiceResolution/bundles.php | 18 +++++++ .../ControllerServiceResolution/config.yml | 10 ++++ .../ControllerServiceResolution/routing.yml | 4 ++ 8 files changed, 185 insertions(+) create mode 100644 src/Symfony/Bundle/FrameworkBundle/EventListener/ResolveControllerNameSubscriber.php create mode 100644 src/Symfony/Bundle/FrameworkBundle/Tests/EventListener/ResolveControllerNameSubscriberTest.php create mode 100644 src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/TestBundle/Controller/SubRequestServiceResolutionController.php create mode 100644 src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/ControllerServiceResolution/bundles.php create mode 100644 src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/ControllerServiceResolution/config.yml create mode 100644 src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/ControllerServiceResolution/routing.yml diff --git a/src/Symfony/Bundle/FrameworkBundle/EventListener/ResolveControllerNameSubscriber.php b/src/Symfony/Bundle/FrameworkBundle/EventListener/ResolveControllerNameSubscriber.php new file mode 100644 index 0000000000000..b083bb7ba8723 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/EventListener/ResolveControllerNameSubscriber.php @@ -0,0 +1,48 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\FrameworkBundle\EventListener; + +use Symfony\Bundle\FrameworkBundle\Controller\ControllerNameParser; +use Symfony\Component\EventDispatcher\EventSubscriberInterface; +use Symfony\Component\HttpKernel\Event\GetResponseEvent; +use Symfony\Component\HttpKernel\KernelEvents; + +/** + * Guarantees that the _controller key is parsed into its final format. + * + * @author Ryan Weaver + */ +class ResolveControllerNameSubscriber implements EventSubscriberInterface +{ + private $parser; + + public function __construct(ControllerNameParser $parser) + { + $this->parser = $parser; + } + + public function onKernelRequest(GetResponseEvent $event) + { + $controller = $event->getRequest()->attributes->get('_controller'); + if ($controller && false === strpos($controller, '::') && 2 === substr_count($controller, ':')) { + // controller in the a:b:c notation then + $event->getRequest()->attributes->set('_controller', $this->parser->parse($controller)); + } + } + + public static function getSubscribedEvents() + { + return array( + KernelEvents::REQUEST => array('onKernelRequest', 24), + ); + } +} diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/web.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/web.xml index 0203bf048bc2f..1eed0e92f6c21 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/web.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/web.xml @@ -70,5 +70,10 @@ + + + + + diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/EventListener/ResolveControllerNameSubscriberTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/EventListener/ResolveControllerNameSubscriberTest.php new file mode 100644 index 0000000000000..e5cc6d28a4e9d --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/EventListener/ResolveControllerNameSubscriberTest.php @@ -0,0 +1,54 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\FrameworkBundle\Tests\EventListener; + +use Symfony\Bundle\FrameworkBundle\Controller\ControllerNameParser; +use Symfony\Bundle\FrameworkBundle\EventListener\ResolveControllerNameSubscriber; +use Symfony\Bundle\FrameworkBundle\Tests\TestCase; +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpKernel\Event\GetResponseEvent; +use Symfony\Component\HttpKernel\HttpKernelInterface; + +class ResolveControllerNameSubscriberTest extends TestCase +{ + public function testReplacesControllerAttribute() + { + $parser = $this->getMockBuilder(ControllerNameParser::class)->disableOriginalConstructor()->getMock(); + $parser->expects($this->any()) + ->method('parse') + ->with('AppBundle:Starting:format') + ->willReturn('App\\Final\\Format::methodName'); + $httpKernel = $this->getMockBuilder(HttpKernelInterface::class)->getMock(); + + $request = new Request(); + $request->attributes->set('_controller', 'AppBundle:Starting:format'); + + $subscriber = new ResolveControllerNameSubscriber($parser); + $subscriber->onKernelRequest(new GetResponseEvent($httpKernel, $request, HttpKernelInterface::MASTER_REQUEST)); + $this->assertEquals('App\\Final\\Format::methodName', $request->attributes->get('_controller')); + } + + public function testSkipsOtherControllerFormats() + { + $parser = $this->getMockBuilder(ControllerNameParser::class)->disableOriginalConstructor()->getMock(); + $parser->expects($this->never()) + ->method('parse'); + $httpKernel = $this->getMockBuilder(HttpKernelInterface::class)->getMock(); + + $request = new Request(); + $request->attributes->set('_controller', 'Other:format'); + + $subscriber = new ResolveControllerNameSubscriber($parser); + $subscriber->onKernelRequest(new GetResponseEvent($httpKernel, $request, HttpKernelInterface::MASTER_REQUEST)); + $this->assertEquals('Other:format', $request->attributes->get('_controller')); + } +} diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/TestBundle/Controller/SubRequestServiceResolutionController.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/TestBundle/Controller/SubRequestServiceResolutionController.php new file mode 100644 index 0000000000000..ae17f605a40f1 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/TestBundle/Controller/SubRequestServiceResolutionController.php @@ -0,0 +1,38 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\FrameworkBundle\Tests\Functional\Bundle\TestBundle\Controller; + +use Psr\Log\LoggerInterface; +use Symfony\Component\DependencyInjection\ContainerAwareInterface; +use Symfony\Component\DependencyInjection\ContainerAwareTrait; +use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\HttpKernel\HttpKernelInterface; + +class SubRequestServiceResolutionController implements ContainerAwareInterface +{ + use ContainerAwareTrait; + + public function indexAction() + { + $request = $this->container->get('request_stack')->getCurrentRequest(); + $path['_forwarded'] = $request->attributes; + $path['_controller'] = 'TestBundle:SubRequestServiceResolution:fragment'; + $subRequest = $request->duplicate(array(), null, $path); + + return $this->container->get('http_kernel')->handle($subRequest, HttpKernelInterface::SUB_REQUEST); + } + + public function fragmentAction(LoggerInterface $logger) + { + return new Response('---'); + } +} diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/SubRequestsTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/SubRequestsTest.php index 2aaeb220f7189..1a87ff928a6e4 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/SubRequestsTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/SubRequestsTest.php @@ -20,4 +20,12 @@ public function testStateAfterSubRequest() $this->assertEquals('--fr/json--en/html--fr/json--http://localhost/subrequest/fragment/en', $client->getResponse()->getContent()); } + + public function testSubRequestControllerServicesAreResolved() + { + $client = $this->createClient(array('test_case' => 'ControllerServiceResolution', 'root_config' => 'config.yml')); + $client->request('GET', 'https://localhost/subrequest'); + + $this->assertEquals('---', $client->getResponse()->getContent()); + } } diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/ControllerServiceResolution/bundles.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/ControllerServiceResolution/bundles.php new file mode 100644 index 0000000000000..a73987bcc986a --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/ControllerServiceResolution/bundles.php @@ -0,0 +1,18 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +use Symfony\Bundle\FrameworkBundle\Tests\Functional\Bundle\TestBundle\TestBundle; +use Symfony\Bundle\FrameworkBundle\FrameworkBundle; + +return array( + new FrameworkBundle(), + new TestBundle(), +); diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/ControllerServiceResolution/config.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/ControllerServiceResolution/config.yml new file mode 100644 index 0000000000000..d196ce950921a --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/ControllerServiceResolution/config.yml @@ -0,0 +1,10 @@ +imports: + - { resource: ../config/default.yml } + +services: + Symfony\Bundle\FrameworkBundle\Tests\Functional\Bundle\TestBundle\Controller\SubRequestServiceResolutionController: + public: true + tags: [controller.service_arguments] + + logger: { class: Psr\Log\NullLogger } + Psr\Log\LoggerInterface: '@logger' diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/ControllerServiceResolution/routing.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/ControllerServiceResolution/routing.yml new file mode 100644 index 0000000000000..ffd9471525a6c --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/ControllerServiceResolution/routing.yml @@ -0,0 +1,4 @@ +sub_request_page: + path: /subrequest + defaults: + _controller: 'TestBundle:SubRequestServiceResolution:index' From dfb5549f63ec274c8ebfec1ff4e94c5b5dd4f1a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A1chym=20Tou=C5=A1ek?= Date: Thu, 1 Jun 2017 15:50:35 +0200 Subject: [PATCH 0107/1099] [PhpUnitBridge] Fix detection of PHPUnit 5 --- src/Symfony/Bridge/PhpUnit/SymfonyTestsListener.php | 2 +- src/Symfony/Bridge/PhpUnit/TextUI/Command.php | 2 +- src/Symfony/Bridge/PhpUnit/TextUI/TestRunner.php | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Bridge/PhpUnit/SymfonyTestsListener.php b/src/Symfony/Bridge/PhpUnit/SymfonyTestsListener.php index f85dbb367ca9c..2dad6ef0095bc 100644 --- a/src/Symfony/Bridge/PhpUnit/SymfonyTestsListener.php +++ b/src/Symfony/Bridge/PhpUnit/SymfonyTestsListener.php @@ -16,7 +16,7 @@ use PHPUnit\Framework\TestSuite; use PHPUnit\Framework\Warning; -if (class_exists('PHPUnit_Framework_BaseTestListener')) { +if (class_exists('PHPUnit_Runner_Version') && version_compare(\PHPUnit_Runner_Version::id(), '6.0.0', '<')) { class_alias('Symfony\Bridge\PhpUnit\Legacy\SymfonyTestsListener', 'Symfony\Bridge\PhpUnit\SymfonyTestsListener'); return; diff --git a/src/Symfony/Bridge/PhpUnit/TextUI/Command.php b/src/Symfony/Bridge/PhpUnit/TextUI/Command.php index 77b617fdcc269..408533292a656 100644 --- a/src/Symfony/Bridge/PhpUnit/TextUI/Command.php +++ b/src/Symfony/Bridge/PhpUnit/TextUI/Command.php @@ -13,7 +13,7 @@ use PHPUnit\TextUI\Command as BaseCommand; -if (class_exists('PHPUnit_TextUI_Command')) { +if (class_exists('PHPUnit_Runner_Version') && version_compare(\PHPUnit_Runner_Version::id(), '6.0.0', '<')) { class_alias('Symfony\Bridge\PhpUnit\Legacy\Command', 'Symfony\Bridge\PhpUnit\TextUI\Command'); return; diff --git a/src/Symfony/Bridge/PhpUnit/TextUI/TestRunner.php b/src/Symfony/Bridge/PhpUnit/TextUI/TestRunner.php index 2d18b4f9afa2b..07fe2d165b627 100644 --- a/src/Symfony/Bridge/PhpUnit/TextUI/TestRunner.php +++ b/src/Symfony/Bridge/PhpUnit/TextUI/TestRunner.php @@ -14,7 +14,7 @@ use PHPUnit\TextUI\TestRunner as BaseRunner; use Symfony\Bridge\PhpUnit\SymfonyTestsListener; -if (class_exists('PHPUnit_TextUI_Command')) { +if (class_exists('PHPUnit_Runner_Version') && version_compare(\PHPUnit_Runner_Version::id(), '6.0.0', '<')) { class_alias('Symfony\Bridge\PhpUnit\Legacy\TestRunner', 'Symfony\Bridge\PhpUnit\TextUI\TestRunner'); return; From 28b253ab40620dbf74df16f4ee8705d557fdd5d2 Mon Sep 17 00:00:00 2001 From: Robin Chalas Date: Thu, 1 Jun 2017 17:20:33 +0200 Subject: [PATCH 0108/1099] Fix CacheCollectorPass priority --- .../Compiler/CacheCollectorPass.php | 21 ++++++-- .../FrameworkBundle/FrameworkBundle.php | 2 +- .../Resources/config/cache_debug.xml | 4 +- .../Compiler/CacheCollectorPassTest.php | 49 +++++++++++++++++++ 4 files changed, 69 insertions(+), 7 deletions(-) create mode 100644 src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/CacheCollectorPassTest.php diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/CacheCollectorPass.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/CacheCollectorPass.php index a4b89144ef717..05e8a00a7925a 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/CacheCollectorPass.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/CacheCollectorPass.php @@ -16,6 +16,7 @@ use Symfony\Component\Cache\Adapter\TraceableTagAwareAdapter; use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\DependencyInjection\Reference; /** @@ -41,13 +42,25 @@ public function process(ContainerBuilder $container) continue; } - $container->register($id.'.recorder', is_subclass_of($definition->getClass(), TagAwareAdapterInterface::class) ? TraceableTagAwareAdapter::class : TraceableAdapter::class) - ->setDecoratedService($id) - ->addArgument(new Reference($id.'.recorder.inner')) - ->setPublic(false); + $recorder = new Definition(is_subclass_of($definition->getClass(), TagAwareAdapterInterface::class) ? TraceableTagAwareAdapter::class : TraceableAdapter::class); + $recorder->setTags($definition->getTags()); + $recorder->setPublic($definition->isPublic()); + $recorder->setArguments(array(new Reference($innerId = $id.'.recorder_inner'))); + + $definition->setTags(array()); + $definition->setPublic(false); + + if ($types = $definition->getAutowiringTypes(false)) { + $recorder->setAutowiringTypes($types); + $definition->setAutowiringTypes(array()); + } + + $container->setDefinition($innerId, $definition); + $container->setDefinition($id, $recorder); // Tell the collector to add the new instance $collectorDefinition->addMethodCall('addInstance', array($id, new Reference($id))); + $collectorDefinition->setPublic(false); } } } diff --git a/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php b/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php index 1844f9b4a4391..99ab06b337772 100644 --- a/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php +++ b/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php @@ -115,7 +115,7 @@ public function build(ContainerBuilder $container) $container->addCompilerPass(new UnusedTagsPass(), PassConfig::TYPE_AFTER_REMOVING); $container->addCompilerPass(new ContainerBuilderDebugDumpPass(), PassConfig::TYPE_BEFORE_REMOVING, -255); $this->addCompilerPassIfExists($container, ConfigCachePass::class); - $container->addCompilerPass(new CacheCollectorPass()); + $container->addCompilerPass(new CacheCollectorPass(), PassConfig::TYPE_BEFORE_REMOVING); } } diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/cache_debug.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/cache_debug.xml index 9356d66769c1e..1b9b4077c0dd8 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/cache_debug.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/cache_debug.xml @@ -7,8 +7,8 @@ - - + + diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/CacheCollectorPassTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/CacheCollectorPassTest.php new file mode 100644 index 0000000000000..6a9438ecbd7c8 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/CacheCollectorPassTest.php @@ -0,0 +1,49 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\Compiler; + +use PHPUnit\Framework\TestCase; +use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\CacheCollectorPass; +use Symfony\Component\Cache\Adapter\FilesystemAdapter; +use Symfony\Component\Cache\Adapter\TagAwareAdapter; +use Symfony\Component\Cache\Adapter\TraceableAdapter; +use Symfony\Component\Cache\Adapter\TraceableTagAwareAdapter; +use Symfony\Component\Cache\DataCollector\CacheDataCollector; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Reference; + +class CacheCollectorPassTest extends TestCase +{ + public function testProcess() + { + $container = new ContainerBuilder(); + $container + ->register('fs', FilesystemAdapter::class) + ->addTag('cache.pool'); + $container + ->register('tagged_fs', TagAwareAdapter::class) + ->addArgument(new Reference('fs')) + ->addTag('cache.pool'); + + $collector = $container->register('data_collector.cache', CacheDataCollector::class); + (new CacheCollectorPass())->process($container); + + $this->assertEquals(array( + array('addInstance', array('fs', new Reference('fs'))), + array('addInstance', array('tagged_fs', new Reference('tagged_fs'))), + ), $collector->getMethodCalls()); + + $this->assertSame(TraceableAdapter::class, $container->findDefinition('fs')->getClass()); + $this->assertSame(TraceableTagAwareAdapter::class, $container->getDefinition('tagged_fs')->getClass()); + $this->assertFalse($collector->isPublic(), 'The "data_collector.cache" should be private after processing'); + } +} From c17a009d666007150b9fdeba61521d0760cf4ab6 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Thu, 1 Jun 2017 11:24:09 +0200 Subject: [PATCH 0109/1099] [EventDispatcher] Handle laziness internally instead of relying on ClosureProxyArgument --- .../ContainerAwareEventDispatcher.php | 2 +- .../RegisterListenersPass.php | 7 +- .../EventDispatcher/EventDispatcher.php | 66 +++++++++++++++--- .../Tests/AbstractEventDispatcherTest.php | 67 +++++++++++++++++++ .../RegisterListenersPassTest.php | 9 +-- 5 files changed, 134 insertions(+), 17 deletions(-) diff --git a/src/Symfony/Component/EventDispatcher/ContainerAwareEventDispatcher.php b/src/Symfony/Component/EventDispatcher/ContainerAwareEventDispatcher.php index 195acf2e0b6e6..72eca3deb0490 100644 --- a/src/Symfony/Component/EventDispatcher/ContainerAwareEventDispatcher.php +++ b/src/Symfony/Component/EventDispatcher/ContainerAwareEventDispatcher.php @@ -116,7 +116,7 @@ public function removeListener($eventName, $listener) public function hasListeners($eventName = null) { if (null === $eventName) { - return (bool) count($this->listenerIds) || (bool) count($this->listeners); + return count($this->listenerIds) || count($this->listeners) || parent::hasListeners(); } if (isset($this->listenerIds[$eventName])) { diff --git a/src/Symfony/Component/EventDispatcher/DependencyInjection/RegisterListenersPass.php b/src/Symfony/Component/EventDispatcher/DependencyInjection/RegisterListenersPass.php index 8b2df3ea0f639..50e466a3983c6 100644 --- a/src/Symfony/Component/EventDispatcher/DependencyInjection/RegisterListenersPass.php +++ b/src/Symfony/Component/EventDispatcher/DependencyInjection/RegisterListenersPass.php @@ -11,10 +11,11 @@ namespace Symfony\Component\EventDispatcher\DependencyInjection; -use Symfony\Component\DependencyInjection\Argument\ClosureProxyArgument; +use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; +use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\EventDispatcher\EventDispatcher; use Symfony\Component\EventDispatcher\EventSubscriberInterface; @@ -78,7 +79,7 @@ public function process(ContainerBuilder $container) $event['method'] = preg_replace('/[^a-z0-9]/i', '', $event['method']); } - $definition->addMethodCall('addListener', array($event['event'], new ClosureProxyArgument($id, $event['method']), $priority)); + $definition->addMethodCall('addListener', array($event['event'], array(new ServiceClosureArgument(new Reference($id)), $event['method']), $priority)); } } @@ -103,7 +104,7 @@ public function process(ContainerBuilder $container) ExtractingEventDispatcher::$subscriber = $class; $extractingDispatcher->addSubscriber($extractingDispatcher); foreach ($extractingDispatcher->listeners as $args) { - $args[1] = new ClosureProxyArgument($id, $args[1]); + $args[1] = array(new ServiceClosureArgument(new Reference($id)), $args[1]); $definition->addMethodCall('addListener', $args); } $extractingDispatcher->listeners = array(); diff --git a/src/Symfony/Component/EventDispatcher/EventDispatcher.php b/src/Symfony/Component/EventDispatcher/EventDispatcher.php index 01bfc0066ea25..4630b01cd8644 100644 --- a/src/Symfony/Component/EventDispatcher/EventDispatcher.php +++ b/src/Symfony/Component/EventDispatcher/EventDispatcher.php @@ -24,6 +24,7 @@ * @author Fabien Potencier * @author Jordi Boggiano * @author Jordan Alliot + * @author Nicolas Grekas */ class EventDispatcher implements EventDispatcherInterface { @@ -52,7 +53,7 @@ public function dispatch($eventName, Event $event = null) public function getListeners($eventName = null) { if (null !== $eventName) { - if (!isset($this->listeners[$eventName])) { + if (empty($this->listeners[$eventName])) { return array(); } @@ -77,13 +78,23 @@ public function getListeners($eventName = null) */ public function getListenerPriority($eventName, $listener) { - if (!isset($this->listeners[$eventName])) { + if (empty($this->listeners[$eventName])) { return; } + if (is_array($listener) && isset($listener[0]) && $listener[0] instanceof \Closure) { + $listener[0] = $listener[0](); + } + foreach ($this->listeners[$eventName] as $priority => $listeners) { - if (false !== in_array($listener, $listeners, true)) { - return $priority; + foreach ($listeners as $k => $v) { + if ($v !== $listener && is_array($v) && isset($v[0]) && $v[0] instanceof \Closure) { + $v[0] = $v[0](); + $this->listeners[$eventName][$priority][$k] = $v; + } + if ($v === $listener) { + return $priority; + } } } } @@ -93,7 +104,17 @@ public function getListenerPriority($eventName, $listener) */ public function hasListeners($eventName = null) { - return (bool) $this->getListeners($eventName); + if (null !== $eventName) { + return !empty($this->listeners[$eventName]); + } + + foreach ($this->listeners as $eventListeners) { + if ($eventListeners) { + return true; + } + } + + return false; } /** @@ -110,13 +131,30 @@ public function addListener($eventName, $listener, $priority = 0) */ public function removeListener($eventName, $listener) { - if (!isset($this->listeners[$eventName])) { + if (empty($this->listeners[$eventName])) { return; } + if (is_array($listener) && isset($listener[0]) && $listener[0] instanceof \Closure) { + $listener[0] = $listener[0](); + } + foreach ($this->listeners[$eventName] as $priority => $listeners) { - if (false !== ($key = array_search($listener, $listeners, true))) { - unset($this->listeners[$eventName][$priority][$key], $this->sorted[$eventName]); + foreach ($listeners as $k => $v) { + if ($v !== $listener && is_array($v) && isset($v[0]) && $v[0] instanceof \Closure) { + $v[0] = $v[0](); + } + if ($v === $listener) { + unset($listeners[$k], $this->sorted[$eventName]); + } else { + $listeners[$k] = $v; + } + } + + if ($listeners) { + $this->listeners[$eventName][$priority] = $listeners; + } else { + unset($this->listeners[$eventName][$priority]); } } } @@ -183,6 +221,16 @@ protected function doDispatch($listeners, $eventName, Event $event) private function sortListeners($eventName) { krsort($this->listeners[$eventName]); - $this->sorted[$eventName] = call_user_func_array('array_merge', $this->listeners[$eventName]); + $this->sorted[$eventName] = array(); + + foreach ($this->listeners[$eventName] as $priority => $listeners) { + foreach ($listeners as $k => $listener) { + if (is_array($listener) && isset($listener[0]) && $listener[0] instanceof \Closure) { + $listener[0] = $listener[0](); + $this->listeners[$eventName][$priority][$k] = $listener; + } + $this->sorted[$eventName][] = $listener; + } + } } } diff --git a/src/Symfony/Component/EventDispatcher/Tests/AbstractEventDispatcherTest.php b/src/Symfony/Component/EventDispatcher/Tests/AbstractEventDispatcherTest.php index 5943039c9e6de..b3fd66927f2b5 100644 --- a/src/Symfony/Component/EventDispatcher/Tests/AbstractEventDispatcherTest.php +++ b/src/Symfony/Component/EventDispatcher/Tests/AbstractEventDispatcherTest.php @@ -302,6 +302,73 @@ public function testHasListenersWithoutEventsReturnsFalseAfterHasListenersWithEv $this->assertFalse($this->dispatcher->hasListeners('foo')); $this->assertFalse($this->dispatcher->hasListeners()); } + + public function testHasListenersIsLazy() + { + $called = 0; + $listener = array(function () use (&$called) { ++$called; }, 'onFoo'); + $this->dispatcher->addListener('foo', $listener); + $this->assertTrue($this->dispatcher->hasListeners()); + $this->assertTrue($this->dispatcher->hasListeners('foo')); + $this->assertSame(0, $called); + } + + public function testDispatchLazyListener() + { + $called = 0; + $factory = function () use (&$called) { + ++$called; + + return new TestWithDispatcher(); + }; + $this->dispatcher->addListener('foo', array($factory, 'foo')); + $this->assertSame(0, $called); + $this->dispatcher->dispatch('foo', new Event()); + $this->dispatcher->dispatch('foo', new Event()); + $this->assertSame(1, $called); + } + + public function testRemoveFindsLazyListeners() + { + $test = new TestWithDispatcher(); + $factory = function () use ($test) { return $test; }; + + $this->dispatcher->addListener('foo', array($factory, 'foo')); + $this->assertTrue($this->dispatcher->hasListeners('foo')); + $this->dispatcher->removeListener('foo', array($test, 'foo')); + $this->assertFalse($this->dispatcher->hasListeners('foo')); + + $this->dispatcher->addListener('foo', array($test, 'foo')); + $this->assertTrue($this->dispatcher->hasListeners('foo')); + $this->dispatcher->removeListener('foo', array($factory, 'foo')); + $this->assertFalse($this->dispatcher->hasListeners('foo')); + } + + public function testPriorityFindsLazyListeners() + { + $test = new TestWithDispatcher(); + $factory = function () use ($test) { return $test; }; + + $this->dispatcher->addListener('foo', array($factory, 'foo'), 3); + $this->assertSame(3, $this->dispatcher->getListenerPriority('foo', array($test, 'foo'))); + $this->dispatcher->removeListener('foo', array($factory, 'foo')); + + $this->dispatcher->addListener('foo', array($test, 'foo'), 5); + $this->assertSame(5, $this->dispatcher->getListenerPriority('foo', array($factory, 'foo'))); + } + + public function testGetLazyListeners() + { + $test = new TestWithDispatcher(); + $factory = function () use ($test) { return $test; }; + + $this->dispatcher->addListener('foo', array($factory, 'foo'), 3); + $this->assertSame(array(array($test, 'foo')), $this->dispatcher->getListeners('foo')); + + $this->dispatcher->removeListener('foo', array($test, 'foo')); + $this->dispatcher->addListener('bar', array($factory, 'foo'), 3); + $this->assertSame(array('bar' => array(array($test, 'foo'))), $this->dispatcher->getListeners()); + } } class CallableClass diff --git a/src/Symfony/Component/EventDispatcher/Tests/DependencyInjection/RegisterListenersPassTest.php b/src/Symfony/Component/EventDispatcher/Tests/DependencyInjection/RegisterListenersPassTest.php index f583cd04cf9a7..d46d8c591195f 100644 --- a/src/Symfony/Component/EventDispatcher/Tests/DependencyInjection/RegisterListenersPassTest.php +++ b/src/Symfony/Component/EventDispatcher/Tests/DependencyInjection/RegisterListenersPassTest.php @@ -12,8 +12,9 @@ namespace Symfony\Component\EventDispatcher\Tests\DependencyInjection; use PHPUnit\Framework\TestCase; -use Symfony\Component\DependencyInjection\Argument\ClosureProxyArgument; +use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument; use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\EventDispatcher\DependencyInjection\RegisterListenersPass; class RegisterListenersPassTest extends TestCase @@ -127,17 +128,17 @@ public function testEventSubscriberResolvableClassName() $registerListenersPass->process($container); $definition = $container->getDefinition('event_dispatcher'); - $expected_calls = array( + $expectedCalls = array( array( 'addListener', array( 'event', - new ClosureProxyArgument('foo', 'onEvent'), + array(new ServiceClosureArgument(new Reference('foo')), 'onEvent'), 0, ), ), ); - $this->assertEquals($expected_calls, $definition->getMethodCalls()); + $this->assertEquals($expectedCalls, $definition->getMethodCalls()); } /** From f91a020b842ed05f26656f4957e2dbc87e8fe1c8 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Thu, 1 Jun 2017 10:56:34 -0700 Subject: [PATCH 0110/1099] Using FQ name for PHP_VERSION_ID --- .github/build-packages.php | 2 +- phpunit | 2 +- .../Bridge/Twig/Extension/CodeExtension.php | 2 +- .../Bridge/Twig/Tests/Node/DumpNodeTest.php | 8 +++---- .../Bridge/Twig/Tests/Node/FormThemeTest.php | 4 ++-- .../Node/SearchAndRenderBlockNodeTest.php | 4 ++-- .../Bridge/Twig/Tests/Node/TransNodeTest.php | 8 +++---- .../FrameworkBundle/Command/ServerCommand.php | 2 +- .../Templating/Helper/CodeHelper.php | 2 +- .../Translation/PhpExtractor.php | 2 +- .../ClassLoader/ClassCollectionLoader.php | 2 +- .../ClassLoader/ClassMapGenerator.php | 4 ++-- .../Tests/ClassMapGeneratorTest.php | 4 ++-- .../Console/Descriptor/TextDescriptor.php | 2 +- src/Symfony/Component/Debug/ErrorHandler.php | 2 +- .../Component/Debug/ExceptionHandler.php | 4 ++-- .../Debug/Tests/DebugClassLoaderTest.php | 6 ++--- .../Component/ExpressionLanguage/Parser.php | 2 +- .../Finder/Iterator/FilterIterator.php | 2 +- .../Iterator/RecursiveDirectoryIterator.php | 2 +- .../Form/Extension/Core/Type/DateType.php | 2 +- .../Csrf/CsrfProvider/DefaultCsrfProvider.php | 2 +- .../Validator/ValidatorTypeGuesserTest.php | 2 +- .../Component/HttpFoundation/JsonResponse.php | 10 ++++---- .../Component/HttpFoundation/Request.php | 2 +- .../Storage/Handler/NativeSessionHandler.php | 2 +- .../Session/Storage/NativeSessionStorage.php | 14 +++++------ .../Session/Storage/Proxy/AbstractProxy.php | 4 ++-- .../HttpFoundation/Tests/RequestTest.php | 2 +- .../Handler/NativeFileSessionHandlerTest.php | 2 +- .../Handler/NativeSessionHandlerTest.php | 2 +- .../Storage/NativeSessionStorageTest.php | 4 ++-- .../Storage/PhpBridgeSessionStorageTest.php | 2 +- .../Storage/Proxy/AbstractProxyTest.php | 8 +++---- .../Storage/Proxy/SessionHandlerProxyTest.php | 2 +- .../DataCollector/DumpDataCollector.php | 4 ++-- .../Fragment/HIncludeFragmentRenderer.php | 2 +- src/Symfony/Component/HttpKernel/Kernel.php | 2 +- .../Controller/ControllerResolverTest.php | 2 +- .../DataCollector/DumpDataCollectorTest.php | 6 ++--- .../Data/Bundle/Writer/JsonBundleWriter.php | 2 +- .../Intl/DateFormatter/IntlDateFormatter.php | 8 +++---- .../Intl/NumberFormatter/NumberFormatter.php | 4 ++-- .../Bundle/Reader/IntlBundleReaderTest.php | 4 ++-- .../Bundle/Writer/JsonBundleWriterTest.php | 2 +- .../Bundle/Writer/PhpBundleWriterTest.php | 2 +- .../AbstractIntlDateFormatterTest.php | 24 +++++++++---------- .../AbstractNumberFormatterTest.php | 6 ++--- .../PropertyAccess/PropertyAccessor.php | 4 ++-- .../Routing/Loader/AnnotationFileLoader.php | 2 +- .../NativeSessionTokenStorage.php | 2 +- .../Session/SessionAuthenticationStrategy.php | 2 +- .../SessionAuthenticationStrategyTest.php | 4 ++-- .../Serializer/Encoder/JsonDecode.php | 2 +- .../Component/Templating/PhpEngine.php | 2 +- .../Tests/Dumper/JsonFileDumperTest.php | 2 +- .../AbstractComparisonValidatorTestCase.php | 4 ++-- .../Constraints/IdenticalToValidatorTest.php | 2 +- .../Tests/Constraints/RangeValidatorTest.php | 6 ++--- .../Component/VarDumper/Cloner/VarCloner.php | 2 +- .../VarDumper/Tests/CliDumperTest.php | 4 ++-- .../VarDumper/Tests/HtmlDumperTest.php | 2 +- .../Tests/Test/VarDumperTestTraitTest.php | 2 +- .../Yaml/Exception/ParseException.php | 2 +- .../Yaml/Tests/ParseExceptionTest.php | 4 ++-- 65 files changed, 121 insertions(+), 121 deletions(-) diff --git a/.github/build-packages.php b/.github/build-packages.php index 02a2239732be2..56112b753ad32 100644 --- a/.github/build-packages.php +++ b/.github/build-packages.php @@ -11,7 +11,7 @@ $mergeBase = trim(shell_exec(sprintf('git merge-base %s HEAD', array_shift($dirs)))); $packages = array(); -$flags = PHP_VERSION_ID >= 50400 ? JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE : 0; +$flags = \PHP_VERSION_ID >= 50400 ? JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE : 0; foreach ($dirs as $k => $dir) { if (!system("git diff --name-only $mergeBase -- $dir", $exitStatus)) { diff --git a/phpunit b/phpunit index 559660b1df25f..53e1a8dc31dbf 100755 --- a/phpunit +++ b/phpunit @@ -7,7 +7,7 @@ if (!file_exists(__DIR__.'/vendor/symfony/phpunit-bridge/bin/simple-phpunit')) { echo "Unable to find the `simple-phpunit` script in `vendor/symfony/phpunit-bridge/bin/`.\nPlease run `composer update` before running this command.\n"; exit(1); } -if (PHP_VERSION_ID >= 70000 && !getenv('SYMFONY_PHPUNIT_VERSION')) { +if (\PHP_VERSION_ID >= 70000 && !getenv('SYMFONY_PHPUNIT_VERSION')) { putenv('SYMFONY_PHPUNIT_VERSION=6.0'); } putenv('SYMFONY_PHPUNIT_DIR='.__DIR__.'/.phpunit'); diff --git a/src/Symfony/Bridge/Twig/Extension/CodeExtension.php b/src/Symfony/Bridge/Twig/Extension/CodeExtension.php index 59dbeec7e995b..4b25d62198341 100644 --- a/src/Symfony/Bridge/Twig/Extension/CodeExtension.php +++ b/src/Symfony/Bridge/Twig/Extension/CodeExtension.php @@ -174,7 +174,7 @@ public function formatFile($file, $line, $text = null) $text = "$text at line $line"; if (false !== $link = $this->getFileLink($file, $line)) { - if (PHP_VERSION_ID >= 50400) { + if (\PHP_VERSION_ID >= 50400) { $flags = ENT_QUOTES | ENT_SUBSTITUTE; } else { $flags = ENT_QUOTES; diff --git a/src/Symfony/Bridge/Twig/Tests/Node/DumpNodeTest.php b/src/Symfony/Bridge/Twig/Tests/Node/DumpNodeTest.php index 93c8433c2894e..e38d9c728283b 100644 --- a/src/Symfony/Bridge/Twig/Tests/Node/DumpNodeTest.php +++ b/src/Symfony/Bridge/Twig/Tests/Node/DumpNodeTest.php @@ -81,9 +81,9 @@ public function testOneVar() } EOTXT; - if (PHP_VERSION_ID >= 70000) { + if (\PHP_VERSION_ID >= 70000) { $expected = preg_replace('/%(.*?)%/', '($context["$1"] ?? null)', $expected); - } elseif (PHP_VERSION_ID >= 50400) { + } elseif (\PHP_VERSION_ID >= 50400) { $expected = preg_replace('/%(.*?)%/', '(isset($context["$1"]) ? $context["$1"] : null)', $expected); } else { $expected = preg_replace('/%(.*?)%/', '$this->getContext($context, "$1")', $expected); @@ -114,9 +114,9 @@ public function testMultiVars() EOTXT; - if (PHP_VERSION_ID >= 70000) { + if (\PHP_VERSION_ID >= 70000) { $expected = preg_replace('/%(.*?)%/', '($context["$1"] ?? null)', $expected); - } elseif (PHP_VERSION_ID >= 50400) { + } elseif (\PHP_VERSION_ID >= 50400) { $expected = preg_replace('/%(.*?)%/', '(isset($context["$1"]) ? $context["$1"] : null)', $expected); } else { $expected = preg_replace('/%(.*?)%/', '$this->getContext($context, "$1")', $expected); diff --git a/src/Symfony/Bridge/Twig/Tests/Node/FormThemeTest.php b/src/Symfony/Bridge/Twig/Tests/Node/FormThemeTest.php index 4202355594745..923c20ff35d5f 100644 --- a/src/Symfony/Bridge/Twig/Tests/Node/FormThemeTest.php +++ b/src/Symfony/Bridge/Twig/Tests/Node/FormThemeTest.php @@ -67,11 +67,11 @@ public function testCompile() protected function getVariableGetter($name) { - if (PHP_VERSION_ID >= 70000) { + if (\PHP_VERSION_ID >= 70000) { return sprintf('($context["%s"] ?? null)', $name, $name); } - if (PHP_VERSION_ID >= 50400) { + if (\PHP_VERSION_ID >= 50400) { return sprintf('(isset($context["%s"]) ? $context["%s"] : null)', $name, $name); } diff --git a/src/Symfony/Bridge/Twig/Tests/Node/SearchAndRenderBlockNodeTest.php b/src/Symfony/Bridge/Twig/Tests/Node/SearchAndRenderBlockNodeTest.php index 69b987e83297f..e29f66ea3c56b 100644 --- a/src/Symfony/Bridge/Twig/Tests/Node/SearchAndRenderBlockNodeTest.php +++ b/src/Symfony/Bridge/Twig/Tests/Node/SearchAndRenderBlockNodeTest.php @@ -264,11 +264,11 @@ public function testCompileLabelWithLabelThatEvaluatesToNullAndAttributes() protected function getVariableGetter($name) { - if (PHP_VERSION_ID >= 70000) { + if (\PHP_VERSION_ID >= 70000) { return sprintf('($context["%s"] ?? null)', $name, $name); } - if (PHP_VERSION_ID >= 50400) { + if (\PHP_VERSION_ID >= 50400) { return sprintf('(isset($context["%s"]) ? $context["%s"] : null)', $name, $name); } diff --git a/src/Symfony/Bridge/Twig/Tests/Node/TransNodeTest.php b/src/Symfony/Bridge/Twig/Tests/Node/TransNodeTest.php index 683d47af27aea..aabd813e5c5ac 100644 --- a/src/Symfony/Bridge/Twig/Tests/Node/TransNodeTest.php +++ b/src/Symfony/Bridge/Twig/Tests/Node/TransNodeTest.php @@ -40,11 +40,11 @@ public function testCompileStrict() protected function getVariableGetterWithoutStrictCheck($name) { - if (PHP_VERSION_ID >= 70000) { + if (\PHP_VERSION_ID >= 70000) { return sprintf('($context["%s"] ?? null)', $name, $name); } - if (PHP_VERSION_ID >= 50400) { + if (\PHP_VERSION_ID >= 50400) { return sprintf('(isset($context["%s"]) ? $context["%s"] : null)', $name, $name); } @@ -57,11 +57,11 @@ protected function getVariableGetterWithStrictCheck($name) return sprintf('(isset($context["%s"]) || array_key_exists("%s", $context) ? $context["%s"] : (function () { throw new Twig_Error_Runtime(\'Variable "%s" does not exist.\', 0, $this->getSourceContext()); })())', $name, $name, $name, $name); } - if (PHP_VERSION_ID >= 70000) { + if (\PHP_VERSION_ID >= 70000) { return sprintf('($context["%s"] ?? $this->getContext($context, "%s"))', $name, $name, $name); } - if (PHP_VERSION_ID >= 50400) { + if (\PHP_VERSION_ID >= 50400) { return sprintf('(isset($context["%s"]) ? $context["%s"] : $this->getContext($context, "%s"))', $name, $name, $name); } diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/ServerCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/ServerCommand.php index 3e1c324f00203..c5f9ee0ecd21d 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/ServerCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/ServerCommand.php @@ -23,7 +23,7 @@ abstract class ServerCommand extends ContainerAwareCommand */ public function isEnabled() { - if (PHP_VERSION_ID < 50400 || defined('HHVM_VERSION')) { + if (\PHP_VERSION_ID < 50400 || defined('HHVM_VERSION')) { return false; } diff --git a/src/Symfony/Bundle/FrameworkBundle/Templating/Helper/CodeHelper.php b/src/Symfony/Bundle/FrameworkBundle/Templating/Helper/CodeHelper.php index cdf19e3ada807..06071e51b276c 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Templating/Helper/CodeHelper.php +++ b/src/Symfony/Bundle/FrameworkBundle/Templating/Helper/CodeHelper.php @@ -154,7 +154,7 @@ public function fileExcerpt($file, $line) */ public function formatFile($file, $line, $text = null) { - if (PHP_VERSION_ID >= 50400) { + if (\PHP_VERSION_ID >= 50400) { $flags = ENT_QUOTES | ENT_SUBSTITUTE; } else { $flags = ENT_QUOTES; diff --git a/src/Symfony/Bundle/FrameworkBundle/Translation/PhpExtractor.php b/src/Symfony/Bundle/FrameworkBundle/Translation/PhpExtractor.php index 97c94fdd14bf9..70658f67232d3 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Translation/PhpExtractor.php +++ b/src/Symfony/Bundle/FrameworkBundle/Translation/PhpExtractor.php @@ -85,7 +85,7 @@ public function extract($resource, MessageCatalogue $catalog) foreach ($files as $file) { $this->parseTokens(token_get_all(file_get_contents($file)), $catalog); - if (PHP_VERSION_ID >= 70000) { + if (\PHP_VERSION_ID >= 70000) { // PHP 7 memory manager will not release after token_get_all(), see https://bugs.php.net/70098 gc_mem_caches(); } diff --git a/src/Symfony/Component/ClassLoader/ClassCollectionLoader.php b/src/Symfony/Component/ClassLoader/ClassCollectionLoader.php index 6f88286de0ff5..cd3c433ed200a 100644 --- a/src/Symfony/Component/ClassLoader/ClassCollectionLoader.php +++ b/src/Symfony/Component/ClassLoader/ClassCollectionLoader.php @@ -232,7 +232,7 @@ public static function fixNamespaceDeclarations($source) $output .= self::compressCode($rawChunk); - if (PHP_VERSION_ID >= 70000) { + if (\PHP_VERSION_ID >= 70000) { // PHP 7 memory manager will not release after token_get_all(), see https://bugs.php.net/70098 unset($tokens, $rawChunk); gc_mem_caches(); diff --git a/src/Symfony/Component/ClassLoader/ClassMapGenerator.php b/src/Symfony/Component/ClassLoader/ClassMapGenerator.php index 2976eb81c09cf..a35c90ca10d8b 100644 --- a/src/Symfony/Component/ClassLoader/ClassMapGenerator.php +++ b/src/Symfony/Component/ClassLoader/ClassMapGenerator.php @@ -12,7 +12,7 @@ namespace Symfony\Component\ClassLoader; if (!defined('SYMFONY_TRAIT')) { - if (PHP_VERSION_ID >= 50400) { + if (\PHP_VERSION_ID >= 50400) { define('SYMFONY_TRAIT', T_TRAIT); } else { define('SYMFONY_TRAIT', 0); @@ -72,7 +72,7 @@ public static function createMap($dir) $classes = self::findClasses($path); - if (PHP_VERSION_ID >= 70000) { + if (\PHP_VERSION_ID >= 70000) { // PHP 7 memory manager will not release after token_get_all(), see https://bugs.php.net/70098 gc_mem_caches(); } diff --git a/src/Symfony/Component/ClassLoader/Tests/ClassMapGeneratorTest.php b/src/Symfony/Component/ClassLoader/Tests/ClassMapGeneratorTest.php index db7fb962cedde..c12182497a01b 100644 --- a/src/Symfony/Component/ClassLoader/Tests/ClassMapGeneratorTest.php +++ b/src/Symfony/Component/ClassLoader/Tests/ClassMapGeneratorTest.php @@ -108,7 +108,7 @@ public function getTestCreateMapTests() )), ); - if (PHP_VERSION_ID >= 50400) { + if (\PHP_VERSION_ID >= 50400) { $data[] = array(__DIR__.'/Fixtures/php5.4', array( 'TFoo' => __DIR__.'/Fixtures/php5.4/traits.php', 'CFoo' => __DIR__.'/Fixtures/php5.4/traits.php', @@ -119,7 +119,7 @@ public function getTestCreateMapTests() )); } - if (PHP_VERSION_ID >= 50500) { + if (\PHP_VERSION_ID >= 50500) { $data[] = array(__DIR__.'/Fixtures/php5.5', array( 'ClassCons\\Foo' => __DIR__.'/Fixtures/php5.5/class_cons.php', )); diff --git a/src/Symfony/Component/Console/Descriptor/TextDescriptor.php b/src/Symfony/Component/Console/Descriptor/TextDescriptor.php index b49b64d5acfa8..c0dd4830c3d2d 100644 --- a/src/Symfony/Component/Console/Descriptor/TextDescriptor.php +++ b/src/Symfony/Component/Console/Descriptor/TextDescriptor.php @@ -247,7 +247,7 @@ private function formatDefaultValue($default) } } - if (PHP_VERSION_ID < 50400) { + if (\PHP_VERSION_ID < 50400) { return str_replace(array('\/', '\\\\'), array('/', '\\'), json_encode($default)); } diff --git a/src/Symfony/Component/Debug/ErrorHandler.php b/src/Symfony/Component/Debug/ErrorHandler.php index 46bcc33f67f57..7624d1213f711 100644 --- a/src/Symfony/Component/Debug/ErrorHandler.php +++ b/src/Symfony/Component/Debug/ErrorHandler.php @@ -404,7 +404,7 @@ public function handleError($type, $message, $file, $line) $throw = new \ErrorException($this->levels[$type].': '.$message, 0, $type, $file, $line); } - if (PHP_VERSION_ID <= 50407 && (PHP_VERSION_ID >= 50400 || PHP_VERSION_ID <= 50317)) { + if (\PHP_VERSION_ID <= 50407 && (\PHP_VERSION_ID >= 50400 || \PHP_VERSION_ID <= 50317)) { // Exceptions thrown from error handlers are sometimes not caught by the exception // handler and shutdown handlers are bypassed before 5.4.8/5.3.18. // We temporarily re-enable display_errors to prevent any blank page related to this bug. diff --git a/src/Symfony/Component/Debug/ExceptionHandler.php b/src/Symfony/Component/Debug/ExceptionHandler.php index 23929b3946c0f..e0d7a0580cb70 100644 --- a/src/Symfony/Component/Debug/ExceptionHandler.php +++ b/src/Symfony/Component/Debug/ExceptionHandler.php @@ -434,7 +434,7 @@ protected static function utf8Htmlize($str) { @trigger_error('The '.__METHOD__.' method is deprecated since version 2.7 and will be removed in 3.0.', E_USER_DEPRECATED); - return htmlspecialchars($str, ENT_QUOTES | (PHP_VERSION_ID >= 50400 ? ENT_SUBSTITUTE : 0), 'UTF-8'); + return htmlspecialchars($str, ENT_QUOTES | (\PHP_VERSION_ID >= 50400 ? ENT_SUBSTITUTE : 0), 'UTF-8'); } /** @@ -442,7 +442,7 @@ protected static function utf8Htmlize($str) */ private function escapeHtml($str) { - return htmlspecialchars($str, ENT_QUOTES | (PHP_VERSION_ID >= 50400 ? ENT_SUBSTITUTE : 0), $this->charset); + return htmlspecialchars($str, ENT_QUOTES | (\PHP_VERSION_ID >= 50400 ? ENT_SUBSTITUTE : 0), $this->charset); } /** diff --git a/src/Symfony/Component/Debug/Tests/DebugClassLoaderTest.php b/src/Symfony/Component/Debug/Tests/DebugClassLoaderTest.php index 8d0a027346b38..133ca28e546b7 100644 --- a/src/Symfony/Component/Debug/Tests/DebugClassLoaderTest.php +++ b/src/Symfony/Component/Debug/Tests/DebugClassLoaderTest.php @@ -61,7 +61,7 @@ public function testIdempotence() public function testUnsilencing() { - if (PHP_VERSION_ID >= 70000) { + if (\PHP_VERSION_ID >= 70000) { $this->markTestSkipped('PHP7 throws exceptions, unsilencing is not required anymore.'); } if (defined('HHVM_VERSION')) { @@ -111,7 +111,7 @@ class ChildTestingStacking extends TestingStacking { function foo($bar) {} } restore_error_handler(); restore_exception_handler(); $this->assertStringStartsWith(__FILE__, $exception->getFile()); - if (PHP_VERSION_ID < 70000) { + if (\PHP_VERSION_ID < 70000) { $this->assertRegExp('/^Runtime Notice: Declaration/', $exception->getMessage()); $this->assertEquals(E_STRICT, $exception->getSeverity()); } else { @@ -227,7 +227,7 @@ class_exists('Symfony\Bridge\Debug\Tests\Fixtures\ExtendsDeprecatedParent', true public function testReservedForPhp7() { - if (PHP_VERSION_ID >= 70000) { + if (\PHP_VERSION_ID >= 70000) { $this->markTestSkipped('PHP7 already prevents using reserved names.'); } diff --git a/src/Symfony/Component/ExpressionLanguage/Parser.php b/src/Symfony/Component/ExpressionLanguage/Parser.php index 6f90451522290..d847dfa4b03bc 100644 --- a/src/Symfony/Component/ExpressionLanguage/Parser.php +++ b/src/Symfony/Component/ExpressionLanguage/Parser.php @@ -344,7 +344,7 @@ public function parsePostfixExpression($node) $node = new Node\GetAttrNode($node, $arg, $arguments, $type); } elseif ('[' === $token->value) { - if ($node instanceof Node\GetAttrNode && Node\GetAttrNode::METHOD_CALL === $node->attributes['type'] && PHP_VERSION_ID < 50400) { + if ($node instanceof Node\GetAttrNode && Node\GetAttrNode::METHOD_CALL === $node->attributes['type'] && \PHP_VERSION_ID < 50400) { throw new SyntaxError('Array calls on a method call is only supported on PHP 5.4+', $token->cursor, $this->stream->getExpression()); } diff --git a/src/Symfony/Component/Finder/Iterator/FilterIterator.php b/src/Symfony/Component/Finder/Iterator/FilterIterator.php index 3c3c3fbec0218..acb98361c9643 100644 --- a/src/Symfony/Component/Finder/Iterator/FilterIterator.php +++ b/src/Symfony/Component/Finder/Iterator/FilterIterator.php @@ -29,7 +29,7 @@ abstract class FilterIterator extends \FilterIterator */ public function rewind() { - if (PHP_VERSION_ID > 50607 || (PHP_VERSION_ID > 50523 && PHP_VERSION_ID < 50600)) { + if (\PHP_VERSION_ID > 50607 || (\PHP_VERSION_ID > 50523 && \PHP_VERSION_ID < 50600)) { parent::rewind(); return; diff --git a/src/Symfony/Component/Finder/Iterator/RecursiveDirectoryIterator.php b/src/Symfony/Component/Finder/Iterator/RecursiveDirectoryIterator.php index 1df2f5014f622..c87096fc87e23 100644 --- a/src/Symfony/Component/Finder/Iterator/RecursiveDirectoryIterator.php +++ b/src/Symfony/Component/Finder/Iterator/RecursiveDirectoryIterator.php @@ -119,7 +119,7 @@ public function rewind() } // @see https://bugs.php.net/68557 - if (PHP_VERSION_ID < 50523 || PHP_VERSION_ID >= 50600 && PHP_VERSION_ID < 50607) { + if (\PHP_VERSION_ID < 50523 || \PHP_VERSION_ID >= 50600 && \PHP_VERSION_ID < 50607) { parent::next(); } diff --git a/src/Symfony/Component/Form/Extension/Core/Type/DateType.php b/src/Symfony/Component/Form/Extension/Core/Type/DateType.php index fdb7ff59e7022..d77cdc8e70335 100644 --- a/src/Symfony/Component/Form/Extension/Core/Type/DateType.php +++ b/src/Symfony/Component/Form/Extension/Core/Type/DateType.php @@ -272,7 +272,7 @@ private function formatTimestamps(\IntlDateFormatter $formatter, $regex, array $ $timezone = $formatter->getTimezoneId(); $formattedTimestamps = array(); - if ($setTimeZone = PHP_VERSION_ID >= 50500 || method_exists($formatter, 'setTimeZone')) { + if ($setTimeZone = \PHP_VERSION_ID >= 50500 || method_exists($formatter, 'setTimeZone')) { $formatter->setTimeZone('UTC'); } else { $formatter->setTimeZoneId('UTC'); diff --git a/src/Symfony/Component/Form/Extension/Csrf/CsrfProvider/DefaultCsrfProvider.php b/src/Symfony/Component/Form/Extension/Csrf/CsrfProvider/DefaultCsrfProvider.php index 7e25a122c6f74..387f4ccf355cb 100644 --- a/src/Symfony/Component/Form/Extension/Csrf/CsrfProvider/DefaultCsrfProvider.php +++ b/src/Symfony/Component/Form/Extension/Csrf/CsrfProvider/DefaultCsrfProvider.php @@ -85,7 +85,7 @@ public function isCsrfTokenValid($intention, $token) */ protected function getSessionId() { - if (PHP_VERSION_ID >= 50400) { + if (\PHP_VERSION_ID >= 50400) { if (PHP_SESSION_NONE === session_status()) { session_start(); } diff --git a/src/Symfony/Component/Form/Tests/Extension/Validator/ValidatorTypeGuesserTest.php b/src/Symfony/Component/Form/Tests/Extension/Validator/ValidatorTypeGuesserTest.php index 6ddac337afea0..2f2d5676a9bd7 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Validator/ValidatorTypeGuesserTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Validator/ValidatorTypeGuesserTest.php @@ -90,7 +90,7 @@ public function testGuessRequired($constraint, $guess) */ public function testLegacyGuessRequired() { - if (PHP_VERSION_ID >= 70000) { + if (\PHP_VERSION_ID >= 70000) { $this->markTestSkipped('Cannot use a class called True on PHP 7 or higher.'); } $true = 'Symfony\Component\Validator\Constraints\True'; diff --git a/src/Symfony/Component/HttpFoundation/JsonResponse.php b/src/Symfony/Component/HttpFoundation/JsonResponse.php index b20e2e28ba3c1..c6e0ba6541061 100644 --- a/src/Symfony/Component/HttpFoundation/JsonResponse.php +++ b/src/Symfony/Component/HttpFoundation/JsonResponse.php @@ -121,7 +121,7 @@ public function setData($data = array()) $data = json_encode($data, $this->encodingOptions); } else { try { - if (PHP_VERSION_ID < 50400) { + if (\PHP_VERSION_ID < 50400) { // PHP 5.3 triggers annoying warnings for some // types that can't be serialized as JSON (INF, resources, etc.) // but doesn't provide the JsonSerializable interface. @@ -131,7 +131,7 @@ public function setData($data = array()) // PHP 5.4 and up wrap exceptions thrown by JsonSerializable // objects in a new exception that needs to be removed. // Fortunately, PHP 5.5 and up do not trigger any warning anymore. - if (PHP_VERSION_ID < 50500) { + if (\PHP_VERSION_ID < 50500) { // Clear json_last_error() json_encode(null); $errorHandler = set_error_handler('var_dump'); @@ -146,14 +146,14 @@ public function setData($data = array()) $data = json_encode($data, $this->encodingOptions); } - if (PHP_VERSION_ID < 50500) { + if (\PHP_VERSION_ID < 50500) { restore_error_handler(); } } catch (\Exception $e) { - if (PHP_VERSION_ID < 50500) { + if (\PHP_VERSION_ID < 50500) { restore_error_handler(); } - if (PHP_VERSION_ID >= 50400 && 'Exception' === get_class($e) && 0 === strpos($e->getMessage(), 'Failed calling ')) { + if (\PHP_VERSION_ID >= 50400 && 'Exception' === get_class($e) && 0 === strpos($e->getMessage(), 'Failed calling ')) { throw $e->getPrevious() ?: $e; } throw $e; diff --git a/src/Symfony/Component/HttpFoundation/Request.php b/src/Symfony/Component/HttpFoundation/Request.php index 0291f9f671aaa..0c11adab6a92e 100644 --- a/src/Symfony/Component/HttpFoundation/Request.php +++ b/src/Symfony/Component/HttpFoundation/Request.php @@ -1502,7 +1502,7 @@ public function isMethodCacheable() public function getContent($asResource = false) { $currentContentIsResource = is_resource($this->content); - if (PHP_VERSION_ID < 50600 && false === $this->content) { + if (\PHP_VERSION_ID < 50600 && false === $this->content) { throw new \LogicException('getContent() can only be called once when using the resource return type and PHP below 5.6.'); } diff --git a/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/NativeSessionHandler.php b/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/NativeSessionHandler.php index 95d5cdbf56310..03acbd94ee343 100644 --- a/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/NativeSessionHandler.php +++ b/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/NativeSessionHandler.php @@ -13,7 +13,7 @@ // Adds SessionHandler functionality if available. // @see http://php.net/sessionhandler -if (PHP_VERSION_ID >= 50400) { +if (\PHP_VERSION_ID >= 50400) { class NativeSessionHandler extends \SessionHandler { } diff --git a/src/Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.php b/src/Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.php index 4deb58eca2ede..36a20550b07cf 100644 --- a/src/Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.php +++ b/src/Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.php @@ -102,7 +102,7 @@ public function __construct(array $options = array(), $handler = null, MetadataB session_cache_limiter(''); // disable by default because it's managed by HeaderBag (if used) ini_set('session.use_cookies', 1); - if (PHP_VERSION_ID >= 50400) { + if (\PHP_VERSION_ID >= 50400) { session_register_shutdown(); } else { register_shutdown_function('session_write_close'); @@ -132,11 +132,11 @@ public function start() return true; } - if (PHP_VERSION_ID >= 50400 && \PHP_SESSION_ACTIVE === session_status()) { + if (\PHP_VERSION_ID >= 50400 && \PHP_SESSION_ACTIVE === session_status()) { throw new \RuntimeException('Failed to start the session: already started by PHP.'); } - if (PHP_VERSION_ID < 50400 && !$this->closed && isset($_SESSION) && session_id()) { + if (\PHP_VERSION_ID < 50400 && !$this->closed && isset($_SESSION) && session_id()) { // not 100% fool-proof, but is the most reliable way to determine if a session is active in PHP 5.3 throw new \RuntimeException('Failed to start the session: already started by PHP ($_SESSION is set).'); } @@ -197,12 +197,12 @@ public function setName($name) public function regenerate($destroy = false, $lifetime = null) { // Cannot regenerate the session ID for non-active sessions. - if (PHP_VERSION_ID >= 50400 && \PHP_SESSION_ACTIVE !== session_status()) { + if (\PHP_VERSION_ID >= 50400 && \PHP_SESSION_ACTIVE !== session_status()) { return false; } // Check if session ID exists in PHP 5.3 - if (PHP_VERSION_ID < 50400 && '' === session_id()) { + if (\PHP_VERSION_ID < 50400 && '' === session_id()) { return false; } @@ -384,13 +384,13 @@ public function setSaveHandler($saveHandler = null) if (!$saveHandler instanceof AbstractProxy && $saveHandler instanceof \SessionHandlerInterface) { $saveHandler = new SessionHandlerProxy($saveHandler); } elseif (!$saveHandler instanceof AbstractProxy) { - $saveHandler = PHP_VERSION_ID >= 50400 ? + $saveHandler = \PHP_VERSION_ID >= 50400 ? new SessionHandlerProxy(new \SessionHandler()) : new NativeProxy(); } $this->saveHandler = $saveHandler; if ($this->saveHandler instanceof \SessionHandlerInterface) { - if (PHP_VERSION_ID >= 50400) { + if (\PHP_VERSION_ID >= 50400) { session_set_save_handler($this->saveHandler, false); } else { session_set_save_handler( diff --git a/src/Symfony/Component/HttpFoundation/Session/Storage/Proxy/AbstractProxy.php b/src/Symfony/Component/HttpFoundation/Session/Storage/Proxy/AbstractProxy.php index 463677b55acfe..405e60b2fdfb3 100644 --- a/src/Symfony/Component/HttpFoundation/Session/Storage/Proxy/AbstractProxy.php +++ b/src/Symfony/Component/HttpFoundation/Session/Storage/Proxy/AbstractProxy.php @@ -72,7 +72,7 @@ public function isWrapper() */ public function isActive() { - if (PHP_VERSION_ID >= 50400) { + if (\PHP_VERSION_ID >= 50400) { return $this->active = \PHP_SESSION_ACTIVE === session_status(); } @@ -93,7 +93,7 @@ public function isActive() */ public function setActive($flag) { - if (PHP_VERSION_ID >= 50400) { + if (\PHP_VERSION_ID >= 50400) { throw new \LogicException('This method is disabled in PHP 5.4.0+'); } diff --git a/src/Symfony/Component/HttpFoundation/Tests/RequestTest.php b/src/Symfony/Component/HttpFoundation/Tests/RequestTest.php index 6f9d76b4835e0..bb7a3f4800cd6 100644 --- a/src/Symfony/Component/HttpFoundation/Tests/RequestTest.php +++ b/src/Symfony/Component/HttpFoundation/Tests/RequestTest.php @@ -1029,7 +1029,7 @@ public function testContentAsResource() */ public function testGetContentCantBeCalledTwiceWithResources($first, $second) { - if (PHP_VERSION_ID >= 50600) { + if (\PHP_VERSION_ID >= 50600) { $this->markTestSkipped('PHP >= 5.6 allows to open php://input several times.'); } diff --git a/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/NativeFileSessionHandlerTest.php b/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/NativeFileSessionHandlerTest.php index 947502f7b1660..67336f68dc45a 100644 --- a/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/NativeFileSessionHandlerTest.php +++ b/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/NativeFileSessionHandlerTest.php @@ -29,7 +29,7 @@ public function testConstruct() { $storage = new NativeSessionStorage(array('name' => 'TESTING'), new NativeFileSessionHandler(sys_get_temp_dir())); - if (PHP_VERSION_ID < 50400) { + if (\PHP_VERSION_ID < 50400) { $this->assertEquals('files', $storage->getSaveHandler()->getSaveHandlerName()); $this->assertEquals('files', ini_get('session.save_handler')); } else { diff --git a/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/NativeSessionHandlerTest.php b/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/NativeSessionHandlerTest.php index bd335b3b4cf71..021d8c0f9e3a0 100644 --- a/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/NativeSessionHandlerTest.php +++ b/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/NativeSessionHandlerTest.php @@ -30,7 +30,7 @@ public function testConstruct() // note for PHPUnit optimisers - the use of assertTrue/False // here is deliberate since the tests do not require the classes to exist - drak - if (PHP_VERSION_ID < 50400) { + if (\PHP_VERSION_ID < 50400) { $this->assertFalse($handler instanceof \SessionHandler); $this->assertTrue($handler instanceof NativeSessionHandler); } else { diff --git a/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/NativeSessionStorageTest.php b/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/NativeSessionStorageTest.php index 4da9a1bc515cb..20f9ca060bc3c 100644 --- a/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/NativeSessionStorageTest.php +++ b/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/NativeSessionStorageTest.php @@ -196,7 +196,7 @@ public function testSetSaveHandlerException() public function testSetSaveHandler53() { - if (PHP_VERSION_ID >= 50400) { + if (\PHP_VERSION_ID >= 50400) { $this->markTestSkipped('Test skipped, for PHP 5.3 only.'); } @@ -249,7 +249,7 @@ public function testStartedOutside() session_start(); $this->assertTrue(isset($_SESSION)); - if (PHP_VERSION_ID >= 50400) { + if (\PHP_VERSION_ID >= 50400) { // this only works in PHP >= 5.4 where session_status is available $this->assertTrue($storage->getSaveHandler()->isActive()); } diff --git a/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/PhpBridgeSessionStorageTest.php b/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/PhpBridgeSessionStorageTest.php index 99491ce86ac25..5cfb328d3095c 100644 --- a/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/PhpBridgeSessionStorageTest.php +++ b/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/PhpBridgeSessionStorageTest.php @@ -62,7 +62,7 @@ protected function getStorage() public function testPhpSession53() { - if (PHP_VERSION_ID >= 50400) { + if (\PHP_VERSION_ID >= 50400) { $this->markTestSkipped('Test skipped, for PHP 5.3 only.'); } diff --git a/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Proxy/AbstractProxyTest.php b/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Proxy/AbstractProxyTest.php index efd8d80d35c57..f21bcc9632be2 100644 --- a/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Proxy/AbstractProxyTest.php +++ b/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Proxy/AbstractProxyTest.php @@ -88,7 +88,7 @@ public function testIsWrapper() public function testIsActivePhp53() { - if (PHP_VERSION_ID >= 50400) { + if (\PHP_VERSION_ID >= 50400) { $this->markTestSkipped('Test skipped, for PHP 5.3 only.'); } @@ -109,7 +109,7 @@ public function testIsActivePhp54() public function testSetActivePhp53() { - if (PHP_VERSION_ID >= 50400) { + if (\PHP_VERSION_ID >= 50400) { $this->markTestSkipped('Test skipped, for PHP 5.3 only.'); } @@ -147,7 +147,7 @@ public function testName() */ public function testNameExceptionPhp53() { - if (PHP_VERSION_ID >= 50400) { + if (\PHP_VERSION_ID >= 50400) { $this->markTestSkipped('Test skipped, for PHP 5.3 only.'); } @@ -184,7 +184,7 @@ public function testId() */ public function testIdExceptionPhp53() { - if (PHP_VERSION_ID >= 50400) { + if (\PHP_VERSION_ID >= 50400) { $this->markTestSkipped('Test skipped, for PHP 5.3 only.'); } diff --git a/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Proxy/SessionHandlerProxyTest.php b/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Proxy/SessionHandlerProxyTest.php index 243f850b5ebdf..df277ac5a8def 100644 --- a/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Proxy/SessionHandlerProxyTest.php +++ b/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Proxy/SessionHandlerProxyTest.php @@ -54,7 +54,7 @@ public function testOpen() $this->assertFalse($this->proxy->isActive()); $this->proxy->open('name', 'id'); - if (PHP_VERSION_ID < 50400) { + if (\PHP_VERSION_ID < 50400) { $this->assertTrue($this->proxy->isActive()); } else { $this->assertFalse($this->proxy->isActive()); diff --git a/src/Symfony/Component/HttpKernel/DataCollector/DumpDataCollector.php b/src/Symfony/Component/HttpKernel/DataCollector/DumpDataCollector.php index 78fc74f2d3f4a..9448ad180b4f3 100644 --- a/src/Symfony/Component/HttpKernel/DataCollector/DumpDataCollector.php +++ b/src/Symfony/Component/HttpKernel/DataCollector/DumpDataCollector.php @@ -71,7 +71,7 @@ public function dump(Data $data) } $trace = DEBUG_BACKTRACE_PROVIDE_OBJECT | DEBUG_BACKTRACE_IGNORE_ARGS; - if (PHP_VERSION_ID >= 50400) { + if (\PHP_VERSION_ID >= 50400) { $trace = debug_backtrace($trace, 7); } else { $trace = debug_backtrace($trace); @@ -263,7 +263,7 @@ public function __destruct() private function doDump($data, $name, $file, $line) { - if (PHP_VERSION_ID >= 50400 && $this->dumper instanceof CliDumper) { + if (\PHP_VERSION_ID >= 50400 && $this->dumper instanceof CliDumper) { $contextDumper = function ($name, $file, $line, $fileLinkFormat) { if ($this instanceof HtmlDumper) { if ('' !== $file) { diff --git a/src/Symfony/Component/HttpKernel/Fragment/HIncludeFragmentRenderer.php b/src/Symfony/Component/HttpKernel/Fragment/HIncludeFragmentRenderer.php index 27051cfb772ee..09f84ec3b8e01 100644 --- a/src/Symfony/Component/HttpKernel/Fragment/HIncludeFragmentRenderer.php +++ b/src/Symfony/Component/HttpKernel/Fragment/HIncludeFragmentRenderer.php @@ -107,7 +107,7 @@ public function render($uri, Request $request, array $options = array()) } $renderedAttributes = ''; if (count($attributes) > 0) { - if (PHP_VERSION_ID >= 50400) { + if (\PHP_VERSION_ID >= 50400) { $flags = ENT_QUOTES | ENT_SUBSTITUTE; } else { $flags = ENT_QUOTES; diff --git a/src/Symfony/Component/HttpKernel/Kernel.php b/src/Symfony/Component/HttpKernel/Kernel.php index 4bbd67b1e5ef3..d20b6e2a16aed 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -753,7 +753,7 @@ public static function stripComments($source) $output .= $rawChunk; - if (PHP_VERSION_ID >= 70000) { + if (\PHP_VERSION_ID >= 70000) { // PHP 7 memory manager will not release after token_get_all(), see https://bugs.php.net/70098 unset($tokens, $rawChunk); gc_mem_caches(); diff --git a/src/Symfony/Component/HttpKernel/Tests/Controller/ControllerResolverTest.php b/src/Symfony/Component/HttpKernel/Tests/Controller/ControllerResolverTest.php index 046b71ac01170..58ca07fc5361b 100644 --- a/src/Symfony/Component/HttpKernel/Tests/Controller/ControllerResolverTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/Controller/ControllerResolverTest.php @@ -184,7 +184,7 @@ public function testGetArguments() $request->attributes->set('foobar', 'foobar'); $controller = array(new self(), 'controllerMethod3'); - if (PHP_VERSION_ID === 50316) { + if (\PHP_VERSION_ID === 50316) { $this->markTestSkipped('PHP 5.3.16 has a major bug in the Reflection sub-system'); } else { try { diff --git a/src/Symfony/Component/HttpKernel/Tests/DataCollector/DumpDataCollectorTest.php b/src/Symfony/Component/HttpKernel/Tests/DataCollector/DumpDataCollectorTest.php index 48b46efad0551..91f4b2e6f25e0 100644 --- a/src/Symfony/Component/HttpKernel/Tests/DataCollector/DumpDataCollectorTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/DataCollector/DumpDataCollectorTest.php @@ -68,7 +68,7 @@ public function testCollectDefault() $collector->collect(new Request(), new Response()); $output = ob_get_clean(); - if (PHP_VERSION_ID >= 50400) { + if (\PHP_VERSION_ID >= 50400) { $this->assertSame("DumpDataCollectorTest.php on line {$line}:\n123\n", $output); } else { $this->assertSame("\"DumpDataCollectorTest.php on line {$line}:\"\n123\n", $output); @@ -86,7 +86,7 @@ public function testCollectHtml() $collector->dump($data); $line = __LINE__ - 1; $file = __FILE__; - if (PHP_VERSION_ID >= 50400) { + if (\PHP_VERSION_ID >= 50400) { $xOutput = <<DumpDataCollectorTest.php on line {$line}: 123 @@ -124,7 +124,7 @@ public function testFlush() ob_start(); $collector->__destruct(); - if (PHP_VERSION_ID >= 50400) { + if (\PHP_VERSION_ID >= 50400) { $this->assertSame("DumpDataCollectorTest.php on line {$line}:\n456\n", ob_get_clean()); } else { $this->assertSame("\"DumpDataCollectorTest.php on line {$line}:\"\n456\n", ob_get_clean()); diff --git a/src/Symfony/Component/Intl/Data/Bundle/Writer/JsonBundleWriter.php b/src/Symfony/Component/Intl/Data/Bundle/Writer/JsonBundleWriter.php index 6a79340c695e4..1a5f07f0a1b31 100644 --- a/src/Symfony/Component/Intl/Data/Bundle/Writer/JsonBundleWriter.php +++ b/src/Symfony/Component/Intl/Data/Bundle/Writer/JsonBundleWriter.php @@ -35,7 +35,7 @@ public function write($path, $locale, $data) } }); - if (PHP_VERSION_ID >= 50400) { + if (\PHP_VERSION_ID >= 50400) { // Use JSON_PRETTY_PRINT so that we can see what changed in Git diffs file_put_contents( $path.'/'.$locale.'.json', diff --git a/src/Symfony/Component/Intl/DateFormatter/IntlDateFormatter.php b/src/Symfony/Component/Intl/DateFormatter/IntlDateFormatter.php index 908afc8acec01..438b4d73e943b 100644 --- a/src/Symfony/Component/Intl/DateFormatter/IntlDateFormatter.php +++ b/src/Symfony/Component/Intl/DateFormatter/IntlDateFormatter.php @@ -209,7 +209,7 @@ public function format($timestamp) $argumentError = null; if (!is_int($timestamp) && !$timestamp instanceof \DateTime) { $argumentError = 'datefmt_format: takes either an array or an integer timestamp value or a DateTime object'; - if (PHP_VERSION_ID >= 50500 || (extension_loaded('intl') && method_exists('IntlDateFormatter', 'setTimeZone'))) { + if (\PHP_VERSION_ID >= 50500 || (extension_loaded('intl') && method_exists('IntlDateFormatter', 'setTimeZone'))) { $argumentError = sprintf('datefmt_format: string \'%s\' is not numeric, which would be required for it to be a valid date', $timestamp); } } @@ -371,7 +371,7 @@ public function getTimeZoneId() } // In PHP 5.5 default timezone depends on `date_default_timezone_get()` method - if (PHP_VERSION_ID >= 50500 || (extension_loaded('intl') && method_exists('IntlDateFormatter', 'setTimeZone'))) { + if (\PHP_VERSION_ID >= 50500 || (extension_loaded('intl') && method_exists('IntlDateFormatter', 'setTimeZone'))) { return date_default_timezone_get(); } } @@ -536,7 +536,7 @@ public function setTimeZoneId($timeZoneId) { if (null === $timeZoneId) { // In PHP 5.5 if $timeZoneId is null it fallbacks to `date_default_timezone_get()` method - if (PHP_VERSION_ID >= 50500 || (extension_loaded('intl') && method_exists('IntlDateFormatter', 'setTimeZone'))) { + if (\PHP_VERSION_ID >= 50500 || (extension_loaded('intl') && method_exists('IntlDateFormatter', 'setTimeZone'))) { $timeZoneId = date_default_timezone_get(); } else { // TODO: changes were made to ext/intl in PHP 5.4.4 release that need to be investigated since it will @@ -567,7 +567,7 @@ public function setTimeZoneId($timeZoneId) $timeZone = $this->getTimeZoneId(); } } catch (\Exception $e) { - if (PHP_VERSION_ID >= 50500 || (extension_loaded('intl') && method_exists('IntlDateFormatter', 'setTimeZone'))) { + if (\PHP_VERSION_ID >= 50500 || (extension_loaded('intl') && method_exists('IntlDateFormatter', 'setTimeZone'))) { $timeZoneId = $timeZone = $this->getTimeZoneId(); } else { $timeZoneId = 'UTC'; diff --git a/src/Symfony/Component/Intl/NumberFormatter/NumberFormatter.php b/src/Symfony/Component/Intl/NumberFormatter/NumberFormatter.php index f93147c593ba2..50ee30a217da1 100644 --- a/src/Symfony/Component/Intl/NumberFormatter/NumberFormatter.php +++ b/src/Symfony/Component/Intl/NumberFormatter/NumberFormatter.php @@ -854,7 +854,7 @@ private function getInt64Value($value) // The negative PHP_INT_MAX was being converted to float if ( $value == -self::$int32Max - 1 && - ((PHP_VERSION_ID < 50400 && PHP_VERSION_ID >= 50314) || PHP_VERSION_ID >= 50404 || (extension_loaded('intl') && method_exists('IntlDateFormatter', 'setTimeZone'))) + ((\PHP_VERSION_ID < 50400 && \PHP_VERSION_ID >= 50314) || \PHP_VERSION_ID >= 50404 || (extension_loaded('intl') && method_exists('IntlDateFormatter', 'setTimeZone'))) ) { return (int) $value; } @@ -867,7 +867,7 @@ private function getInt64Value($value) // A 32 bit integer was being generated instead of a 64 bit integer if ( ($value > self::$int32Max || $value < -self::$int32Max - 1) && - (PHP_VERSION_ID < 50314 || (PHP_VERSION_ID >= 50400 && PHP_VERSION_ID < 50404)) && + (\PHP_VERSION_ID < 50314 || (\PHP_VERSION_ID >= 50400 && \PHP_VERSION_ID < 50404)) && !(extension_loaded('intl') && method_exists('IntlDateFormatter', 'setTimeZone')) ) { $value = (-2147483648 - ($value % -2147483648)) * ($value / abs($value)); diff --git a/src/Symfony/Component/Intl/Tests/Data/Bundle/Reader/IntlBundleReaderTest.php b/src/Symfony/Component/Intl/Tests/Data/Bundle/Reader/IntlBundleReaderTest.php index 88e6974bf2954..76543d3f0aa99 100644 --- a/src/Symfony/Component/Intl/Tests/Data/Bundle/Reader/IntlBundleReaderTest.php +++ b/src/Symfony/Component/Intl/Tests/Data/Bundle/Reader/IntlBundleReaderTest.php @@ -51,7 +51,7 @@ public function testReadFollowsAlias() public function testReadDoesNotFollowFallback() { - if (PHP_VERSION_ID < 50307 || PHP_VERSION_ID === 50400) { + if (\PHP_VERSION_ID < 50307 || \PHP_VERSION_ID === 50400) { $this->markTestSkipped('ResourceBundle handles disabling fallback properly only as of PHP 5.3.7 and 5.4.1.'); } @@ -71,7 +71,7 @@ public function testReadDoesNotFollowFallback() public function testReadDoesNotFollowFallbackAlias() { - if (PHP_VERSION_ID < 50307 || PHP_VERSION_ID === 50400) { + if (\PHP_VERSION_ID < 50307 || \PHP_VERSION_ID === 50400) { $this->markTestSkipped('ResourceBundle handles disabling fallback properly only as of PHP 5.3.7 and 5.4.1.'); } diff --git a/src/Symfony/Component/Intl/Tests/Data/Bundle/Writer/JsonBundleWriterTest.php b/src/Symfony/Component/Intl/Tests/Data/Bundle/Writer/JsonBundleWriterTest.php index b8610334d5a7a..d18968c9c95f2 100644 --- a/src/Symfony/Component/Intl/Tests/Data/Bundle/Writer/JsonBundleWriterTest.php +++ b/src/Symfony/Component/Intl/Tests/Data/Bundle/Writer/JsonBundleWriterTest.php @@ -44,7 +44,7 @@ protected function setUp() protected function tearDown() { - if (PHP_VERSION_ID < 50400) { + if (\PHP_VERSION_ID < 50400) { return; } diff --git a/src/Symfony/Component/Intl/Tests/Data/Bundle/Writer/PhpBundleWriterTest.php b/src/Symfony/Component/Intl/Tests/Data/Bundle/Writer/PhpBundleWriterTest.php index a4c0330e0d5e9..05bb9aad4f238 100644 --- a/src/Symfony/Component/Intl/Tests/Data/Bundle/Writer/PhpBundleWriterTest.php +++ b/src/Symfony/Component/Intl/Tests/Data/Bundle/Writer/PhpBundleWriterTest.php @@ -69,7 +69,7 @@ public function testWrite() */ public function testWriteResourceBundle() { - if (PHP_VERSION_ID < 50315 || (PHP_VERSION_ID >= 50400 && PHP_VERSION_ID < 50404)) { + if (\PHP_VERSION_ID < 50315 || (\PHP_VERSION_ID >= 50400 && \PHP_VERSION_ID < 50404)) { $this->markTestSkipped('ResourceBundle implements Traversable only as of PHP 5.3.15 and 5.4.4'); } diff --git a/src/Symfony/Component/Intl/Tests/DateFormatter/AbstractIntlDateFormatterTest.php b/src/Symfony/Component/Intl/Tests/DateFormatter/AbstractIntlDateFormatterTest.php index 43001a74fc6cb..669365c567b0a 100644 --- a/src/Symfony/Component/Intl/Tests/DateFormatter/AbstractIntlDateFormatterTest.php +++ b/src/Symfony/Component/Intl/Tests/DateFormatter/AbstractIntlDateFormatterTest.php @@ -37,7 +37,7 @@ public function testConstructorDefaultTimeZone() $formatter = $this->getDateFormatter('en', IntlDateFormatter::MEDIUM, IntlDateFormatter::SHORT); // In PHP 5.5 default timezone depends on `date_default_timezone_get()` method - if (PHP_VERSION_ID >= 50500 || (extension_loaded('intl') && method_exists('IntlDateFormatter', 'setTimeZone'))) { + if (\PHP_VERSION_ID >= 50500 || (extension_loaded('intl') && method_exists('IntlDateFormatter', 'setTimeZone'))) { $this->assertEquals(date_default_timezone_get(), $formatter->getTimeZoneId()); } else { $this->assertNull($formatter->getTimeZoneId()); @@ -277,7 +277,7 @@ public function testFormatIllegalArgumentError($pattern, $timestamp, $errorMessa public function formatErrorProvider() { // With PHP 5.5 IntlDateFormatter accepts empty values ('0') - if (PHP_VERSION_ID >= 50500 || (extension_loaded('intl') && method_exists('IntlDateFormatter', 'setTimeZone'))) { + if (\PHP_VERSION_ID >= 50500 || (extension_loaded('intl') && method_exists('IntlDateFormatter', 'setTimeZone'))) { return array( array('y-M-d', 'foobar', 'datefmt_format: string \'foobar\' is not numeric, which would be required for it to be a valid date: U_ILLEGAL_ARGUMENT_ERROR'), ); @@ -330,7 +330,7 @@ public function formatWithTimezoneProvider() ); // As of PHP 5.5, intl ext no longer fallbacks invalid time zones to UTC - if (PHP_VERSION_ID < 50500 && !(extension_loaded('intl') && method_exists('IntlDateFormatter', 'setTimeZone'))) { + if (\PHP_VERSION_ID < 50500 && !(extension_loaded('intl') && method_exists('IntlDateFormatter', 'setTimeZone'))) { // When time zone not exists, uses UTC by default $data[] = array(0, 'Foo/Bar', '1970-01-01 00:00:00'); $data[] = array(0, 'UTC+04:30', '1970-01-01 00:00:00'); @@ -413,7 +413,7 @@ public function testFormatWithGmtTimezone() { $formatter = $this->getDefaultDateFormatter('zzzz'); - if (PHP_VERSION_ID >= 50500 || (extension_loaded('intl') && method_exists('IntlDateFormatter', 'setTimeZone'))) { + if (\PHP_VERSION_ID >= 50500 || (extension_loaded('intl') && method_exists('IntlDateFormatter', 'setTimeZone'))) { $formatter->setTimeZone('GMT+03:00'); } else { $formatter->setTimeZoneId('GMT+03:00'); @@ -426,7 +426,7 @@ public function testFormatWithGmtTimeZoneAndMinutesOffset() { $formatter = $this->getDefaultDateFormatter('zzzz'); - if (PHP_VERSION_ID >= 50500 || (extension_loaded('intl') && method_exists('IntlDateFormatter', 'setTimeZone'))) { + if (\PHP_VERSION_ID >= 50500 || (extension_loaded('intl') && method_exists('IntlDateFormatter', 'setTimeZone'))) { $formatter->setTimeZone('GMT+00:30'); } else { $formatter->setTimeZoneId('GMT+00:30'); @@ -439,7 +439,7 @@ public function testFormatWithNonStandardTimezone() { $formatter = $this->getDefaultDateFormatter('zzzz'); - if (PHP_VERSION_ID >= 50500 || (extension_loaded('intl') && method_exists('IntlDateFormatter', 'setTimeZone'))) { + if (\PHP_VERSION_ID >= 50500 || (extension_loaded('intl') && method_exists('IntlDateFormatter', 'setTimeZone'))) { $formatter->setTimeZone('Pacific/Fiji'); } else { $formatter->setTimeZoneId('Pacific/Fiji'); @@ -471,7 +471,7 @@ public function testFormatWithDateTimeZoneGmt() public function testFormatWithDateTimeZoneGmtOffset() { - if (defined('HHVM_VERSION_ID') || PHP_VERSION_ID <= 50509) { + if (defined('HHVM_VERSION_ID') || \PHP_VERSION_ID <= 50509) { $this->markTestSkipped('DateTimeZone GMT offsets are supported since 5.5.10. See https://github.com/facebook/hhvm/issues/5875 for HHVM.'); } @@ -485,7 +485,7 @@ public function testFormatWithIntlTimeZone() if (!extension_loaded('intl')) { $this->markTestSkipped('Extension intl is required.'); } - if (PHP_VERSION_ID < 50500 && !method_exists('IntlDateFormatter', 'setTimeZone')) { + if (\PHP_VERSION_ID < 50500 && !method_exists('IntlDateFormatter', 'setTimeZone')) { $this->markTestSkipped('Only in PHP 5.5+ IntlDateFormatter allows to use DateTimeZone objects.'); } @@ -496,7 +496,7 @@ public function testFormatWithIntlTimeZone() public function testFormatWithTimezoneFromEnvironmentVariable() { - if (PHP_VERSION_ID >= 50500 || (extension_loaded('intl') && method_exists('IntlDateFormatter', 'setTimeZone'))) { + if (\PHP_VERSION_ID >= 50500 || (extension_loaded('intl') && method_exists('IntlDateFormatter', 'setTimeZone'))) { $this->markTestSkipped('IntlDateFormatter in PHP 5.5 no longer depends on TZ environment.'); } @@ -519,7 +519,7 @@ public function testFormatWithTimezoneFromEnvironmentVariable() public function testFormatWithTimezoneFromPhp() { - if (PHP_VERSION_ID < 50500 && !(extension_loaded('intl') && method_exists('IntlDateFormatter', 'setTimeZone'))) { + if (\PHP_VERSION_ID < 50500 && !(extension_loaded('intl') && method_exists('IntlDateFormatter', 'setTimeZone'))) { $this->markTestSkipped('Only in PHP 5.5 IntlDateFormatter depends on default timezone (`date_default_timezone_get()`).'); } @@ -949,7 +949,7 @@ public function testSetTimeZoneId($timeZoneId, $expectedTimeZoneId) { $formatter = $this->getDefaultDateFormatter(); - if (PHP_VERSION_ID >= 50500 || (extension_loaded('intl') && method_exists('IntlDateFormatter', 'setTimeZone'))) { + if (\PHP_VERSION_ID >= 50500 || (extension_loaded('intl') && method_exists('IntlDateFormatter', 'setTimeZone'))) { $formatter->setTimeZone($timeZoneId); } else { $formatter->setTimeZoneId($timeZoneId); @@ -960,7 +960,7 @@ public function testSetTimeZoneId($timeZoneId, $expectedTimeZoneId) public function setTimeZoneIdProvider() { - $isPhp55 = PHP_VERSION_ID >= 50500 || (extension_loaded('intl') && method_exists('IntlDateFormatter', 'setTimeZone')); + $isPhp55 = \PHP_VERSION_ID >= 50500 || (extension_loaded('intl') && method_exists('IntlDateFormatter', 'setTimeZone')); return array( array('UTC', 'UTC'), diff --git a/src/Symfony/Component/Intl/Tests/NumberFormatter/AbstractNumberFormatterTest.php b/src/Symfony/Component/Intl/Tests/NumberFormatter/AbstractNumberFormatterTest.php index d91f9a292afce..a3f86e2b5144a 100644 --- a/src/Symfony/Component/Intl/Tests/NumberFormatter/AbstractNumberFormatterTest.php +++ b/src/Symfony/Component/Intl/Tests/NumberFormatter/AbstractNumberFormatterTest.php @@ -701,7 +701,7 @@ public function testParseTypeInt64With32BitIntegerInPhp32Bit() // Bug #59597 was fixed on PHP 5.3.14 and 5.4.4 // The negative PHP_INT_MAX was being converted to float - if ((PHP_VERSION_ID < 50400 && PHP_VERSION_ID >= 50314) || PHP_VERSION_ID >= 50404 || (extension_loaded('intl') && method_exists('IntlDateFormatter', 'setTimeZone'))) { + if ((\PHP_VERSION_ID < 50400 && \PHP_VERSION_ID >= 50314) || \PHP_VERSION_ID >= 50404 || (extension_loaded('intl') && method_exists('IntlDateFormatter', 'setTimeZone'))) { $this->assertInternalType('int', $parsedValue); } else { $this->assertInternalType('float', $parsedValue); @@ -758,7 +758,7 @@ public function testParseTypeInt64With64BitIntegerInPhp64Bit() // Bug #59597 was fixed on PHP 5.3.14 and 5.4.4 // A 32 bit integer was being generated instead of a 64 bit integer - if (PHP_VERSION_ID < 50314 || (PHP_VERSION_ID >= 50400 && PHP_VERSION_ID < 50404)) { + if (\PHP_VERSION_ID < 50314 || (\PHP_VERSION_ID >= 50400 && \PHP_VERSION_ID < 50404)) { $this->assertEquals(-2147483648, $parsedValue, '->parse() TYPE_INT64 does not use true 64 bit integers, using only the 32 bit range (PHP < 5.3.14 and PHP < 5.4.4).'); } else { $this->assertEquals(2147483648, $parsedValue, '->parse() TYPE_INT64 uses true 64 bit integers (PHP >= 5.3.14 and PHP >= 5.4.4).'); @@ -769,7 +769,7 @@ public function testParseTypeInt64With64BitIntegerInPhp64Bit() // Bug #59597 was fixed on PHP 5.3.14 and 5.4.4 // A 32 bit integer was being generated instead of a 64 bit integer - if (PHP_VERSION_ID < 50314 || (PHP_VERSION_ID >= 50400 && PHP_VERSION_ID < 50404)) { + if (\PHP_VERSION_ID < 50314 || (\PHP_VERSION_ID >= 50400 && \PHP_VERSION_ID < 50404)) { $this->assertEquals(2147483647, $parsedValue, '->parse() TYPE_INT64 does not use true 64 bit integers, using only the 32 bit range (PHP < 5.3.14 and PHP < 5.4.4).'); } else { $this->assertEquals(-2147483649, $parsedValue, '->parse() TYPE_INT64 uses true 64 bit integers (PHP >= 5.3.14 and PHP >= 5.4.4).'); diff --git a/src/Symfony/Component/PropertyAccess/PropertyAccessor.php b/src/Symfony/Component/PropertyAccess/PropertyAccessor.php index d7ccc46438675..cdb075c84621f 100644 --- a/src/Symfony/Component/PropertyAccess/PropertyAccessor.php +++ b/src/Symfony/Component/PropertyAccess/PropertyAccessor.php @@ -166,7 +166,7 @@ public function setValue(&$objectOrArray, $propertyPath, $value) $overwrite = true; try { - if (PHP_VERSION_ID < 70000 && false === self::$previousErrorHandler) { + if (\PHP_VERSION_ID < 70000 && false === self::$previousErrorHandler) { self::$previousErrorHandler = set_error_handler(self::$errorHandler); } @@ -222,7 +222,7 @@ public function setValue(&$objectOrArray, $propertyPath, $value) } catch (\Throwable $e) { } - if (PHP_VERSION_ID < 70000 && false !== self::$previousErrorHandler) { + if (\PHP_VERSION_ID < 70000 && false !== self::$previousErrorHandler) { restore_error_handler(); self::$previousErrorHandler = false; } diff --git a/src/Symfony/Component/Routing/Loader/AnnotationFileLoader.php b/src/Symfony/Component/Routing/Loader/AnnotationFileLoader.php index b8fc03615f968..d98e024640366 100644 --- a/src/Symfony/Component/Routing/Loader/AnnotationFileLoader.php +++ b/src/Symfony/Component/Routing/Loader/AnnotationFileLoader.php @@ -64,7 +64,7 @@ public function load($file, $type = null) $collection->addResource(new FileResource($path)); $collection->addCollection($this->loader->load($class, $type)); } - if (PHP_VERSION_ID >= 70000) { + if (\PHP_VERSION_ID >= 70000) { // PHP 7 memory manager will not release after token_get_all(), see https://bugs.php.net/70098 gc_mem_caches(); } diff --git a/src/Symfony/Component/Security/Csrf/TokenStorage/NativeSessionTokenStorage.php b/src/Symfony/Component/Security/Csrf/TokenStorage/NativeSessionTokenStorage.php index 71151fa831813..4923576e7c9b7 100644 --- a/src/Symfony/Component/Security/Csrf/TokenStorage/NativeSessionTokenStorage.php +++ b/src/Symfony/Component/Security/Csrf/TokenStorage/NativeSessionTokenStorage.php @@ -108,7 +108,7 @@ public function removeToken($tokenId) private function startSession() { - if (PHP_VERSION_ID >= 50400) { + if (\PHP_VERSION_ID >= 50400) { if (PHP_SESSION_NONE === session_status()) { session_start(); } diff --git a/src/Symfony/Component/Security/Http/Session/SessionAuthenticationStrategy.php b/src/Symfony/Component/Security/Http/Session/SessionAuthenticationStrategy.php index ccfa6ba67a492..b431289392561 100644 --- a/src/Symfony/Component/Security/Http/Session/SessionAuthenticationStrategy.php +++ b/src/Symfony/Component/Security/Http/Session/SessionAuthenticationStrategy.php @@ -49,7 +49,7 @@ public function onAuthentication(Request $request, TokenInterface $token) case self::MIGRATE: // Destroying the old session is broken in php 5.4.0 - 5.4.10 // See php bug #63379 - $destroy = PHP_VERSION_ID < 50400 || PHP_VERSION_ID >= 50411; + $destroy = \PHP_VERSION_ID < 50400 || \PHP_VERSION_ID >= 50411; $request->getSession()->migrate($destroy); return; diff --git a/src/Symfony/Component/Security/Http/Tests/Session/SessionAuthenticationStrategyTest.php b/src/Symfony/Component/Security/Http/Tests/Session/SessionAuthenticationStrategyTest.php index 601c3375887cf..d18c1c3ee7075 100644 --- a/src/Symfony/Component/Security/Http/Tests/Session/SessionAuthenticationStrategyTest.php +++ b/src/Symfony/Component/Security/Http/Tests/Session/SessionAuthenticationStrategyTest.php @@ -40,7 +40,7 @@ public function testUnsupportedStrategy() public function testSessionIsMigrated() { - if (PHP_VERSION_ID >= 50400 && PHP_VERSION_ID < 50411) { + if (\PHP_VERSION_ID >= 50400 && \PHP_VERSION_ID < 50411) { $this->markTestSkipped('We cannot destroy the old session on PHP 5.4.0 - 5.4.10.'); } @@ -53,7 +53,7 @@ public function testSessionIsMigrated() public function testSessionIsMigratedWithPhp54Workaround() { - if (PHP_VERSION_ID < 50400 || PHP_VERSION_ID >= 50411) { + if (\PHP_VERSION_ID < 50400 || \PHP_VERSION_ID >= 50411) { $this->markTestSkipped('This PHP version is not affected.'); } diff --git a/src/Symfony/Component/Serializer/Encoder/JsonDecode.php b/src/Symfony/Component/Serializer/Encoder/JsonDecode.php index 5f5f2899f5fff..a7a11caf2e7f0 100644 --- a/src/Symfony/Component/Serializer/Encoder/JsonDecode.php +++ b/src/Symfony/Component/Serializer/Encoder/JsonDecode.php @@ -101,7 +101,7 @@ public function decode($data, $format, array $context = array()) $recursionDepth = $context['json_decode_recursion_depth']; $options = $context['json_decode_options']; - if (PHP_VERSION_ID >= 50400) { + if (\PHP_VERSION_ID >= 50400) { $decodedData = json_decode($data, $associative, $recursionDepth, $options); } else { $decodedData = json_decode($data, $associative, $recursionDepth); diff --git a/src/Symfony/Component/Templating/PhpEngine.php b/src/Symfony/Component/Templating/PhpEngine.php index 75846455b9ee4..de243d35e09bf 100644 --- a/src/Symfony/Component/Templating/PhpEngine.php +++ b/src/Symfony/Component/Templating/PhpEngine.php @@ -417,7 +417,7 @@ public function getGlobals() protected function initializeEscapers() { $that = $this; - if (PHP_VERSION_ID >= 50400) { + if (\PHP_VERSION_ID >= 50400) { $flags = ENT_QUOTES | ENT_SUBSTITUTE; } else { $flags = ENT_QUOTES; diff --git a/src/Symfony/Component/Translation/Tests/Dumper/JsonFileDumperTest.php b/src/Symfony/Component/Translation/Tests/Dumper/JsonFileDumperTest.php index f54768418ca68..74d1c27b6407f 100644 --- a/src/Symfony/Component/Translation/Tests/Dumper/JsonFileDumperTest.php +++ b/src/Symfony/Component/Translation/Tests/Dumper/JsonFileDumperTest.php @@ -19,7 +19,7 @@ class JsonFileDumperTest extends TestCase { public function testDump() { - if (PHP_VERSION_ID < 50400) { + if (\PHP_VERSION_ID < 50400) { $this->markTestIncomplete('PHP below 5.4 doesn\'t support JSON pretty printing'); } diff --git a/src/Symfony/Component/Validator/Tests/Constraints/AbstractComparisonValidatorTestCase.php b/src/Symfony/Component/Validator/Tests/Constraints/AbstractComparisonValidatorTestCase.php index 856e49d6c56a1..9c8ce50fc3dd1 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/AbstractComparisonValidatorTestCase.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/AbstractComparisonValidatorTestCase.php @@ -36,7 +36,7 @@ abstract class AbstractComparisonValidatorTestCase extends AbstractConstraintVal { protected static function addPhp5Dot5Comparisons(array $comparisons) { - if (PHP_VERSION_ID < 50500) { + if (\PHP_VERSION_ID < 50500) { return $comparisons; } @@ -130,7 +130,7 @@ public function testInvalidComparisonToValue($dirtyValue, $dirtyValueAsString, $ if ($dirtyValue instanceof \DateTime || $dirtyValue instanceof \DateTimeInterface) { IntlTestHelper::requireIntl($this, '57.1'); - if (PHP_VERSION_ID < 50304 && !(extension_loaded('intl') && method_exists('IntlDateFormatter', 'setTimeZone'))) { + if (\PHP_VERSION_ID < 50304 && !(extension_loaded('intl') && method_exists('IntlDateFormatter', 'setTimeZone'))) { $this->markTestSkipped('Intl supports formatting DateTime objects since 5.3.4'); } } diff --git a/src/Symfony/Component/Validator/Tests/Constraints/IdenticalToValidatorTest.php b/src/Symfony/Component/Validator/Tests/Constraints/IdenticalToValidatorTest.php index 1acb41a66ccd7..0b6a4e411af9f 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/IdenticalToValidatorTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/IdenticalToValidatorTest.php @@ -64,7 +64,7 @@ public function provideValidComparisons() array(null, 1), ); - if (PHP_VERSION_ID >= 50500) { + if (\PHP_VERSION_ID >= 50500) { $immutableDate = new \DateTimeImmutable('2000-01-01'); $comparisons[] = array($immutableDate, $immutableDate); } diff --git a/src/Symfony/Component/Validator/Tests/Constraints/RangeValidatorTest.php b/src/Symfony/Component/Validator/Tests/Constraints/RangeValidatorTest.php index ecee65cd81e27..b977a7e19c95b 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/RangeValidatorTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/RangeValidatorTest.php @@ -194,7 +194,7 @@ public function getTenthToTwentiethMarch2014() array(new \DateTime('March 20, 2014')), ); - if (PHP_VERSION_ID >= 50500) { + if (\PHP_VERSION_ID >= 50500) { $tests[] = array(new \DateTimeImmutable('March 10, 2014')); $tests[] = array(new \DateTimeImmutable('March 15, 2014')); $tests[] = array(new \DateTimeImmutable('March 20, 2014')); @@ -216,7 +216,7 @@ public function getSoonerThanTenthMarch2014() array(new \DateTime('March 9, 2014'), 'Mar 9, 2014, 12:00 AM'), ); - if (PHP_VERSION_ID >= 50500) { + if (\PHP_VERSION_ID >= 50500) { $tests[] = array(new \DateTimeImmutable('March 20, 2013'), 'Mar 20, 2013, 12:00 AM'); $tests[] = array(new \DateTimeImmutable('March 9, 2014'), 'Mar 9, 2014, 12:00 AM'); } @@ -237,7 +237,7 @@ public function getLaterThanTwentiethMarch2014() array(new \DateTime('March 9, 2015'), 'Mar 9, 2015, 12:00 AM'), ); - if (PHP_VERSION_ID >= 50500) { + if (\PHP_VERSION_ID >= 50500) { $tests[] = array(new \DateTimeImmutable('March 21, 2014'), 'Mar 21, 2014, 12:00 AM'); $tests[] = array(new \DateTimeImmutable('March 9, 2015'), 'Mar 9, 2015, 12:00 AM'); } diff --git a/src/Symfony/Component/VarDumper/Cloner/VarCloner.php b/src/Symfony/Component/VarDumper/Cloner/VarCloner.php index af467056a5d97..6c9ede3ed55da 100644 --- a/src/Symfony/Component/VarDumper/Cloner/VarCloner.php +++ b/src/Symfony/Component/VarDumper/Cloner/VarCloner.php @@ -308,7 +308,7 @@ private static function initHashMask() } else { // check if we are nested in an output buffering handler to prevent a fatal error with ob_start() below $obFuncs = array('ob_clean', 'ob_end_clean', 'ob_flush', 'ob_end_flush', 'ob_get_contents', 'ob_get_flush'); - foreach (debug_backtrace(PHP_VERSION_ID >= 50400 ? DEBUG_BACKTRACE_IGNORE_ARGS : false) as $frame) { + foreach (debug_backtrace(\PHP_VERSION_ID >= 50400 ? DEBUG_BACKTRACE_IGNORE_ARGS : false) as $frame) { if (isset($frame['function'][0]) && !isset($frame['class']) && 'o' === $frame['function'][0] && in_array($frame['function'], $obFuncs)) { $frame['line'] = 0; break; diff --git a/src/Symfony/Component/VarDumper/Tests/CliDumperTest.php b/src/Symfony/Component/VarDumper/Tests/CliDumperTest.php index 519e6a126b7dc..f8acf0d562438 100644 --- a/src/Symfony/Component/VarDumper/Tests/CliDumperTest.php +++ b/src/Symfony/Component/VarDumper/Tests/CliDumperTest.php @@ -45,7 +45,7 @@ public function testGet() $closure54 = ''; $r = defined('HHVM_VERSION') ? '' : '#%d'; - if (PHP_VERSION_ID >= 50400) { + if (\PHP_VERSION_ID >= 50400) { $closure54 = <<= 50600) { + if (\PHP_VERSION_ID >= 50600) { $this->markTestSkipped('PHP 5.6 fixed refs counting'); } diff --git a/src/Symfony/Component/VarDumper/Tests/HtmlDumperTest.php b/src/Symfony/Component/VarDumper/Tests/HtmlDumperTest.php index c3a8e1a6c948c..6ba68c5c80c0e 100644 --- a/src/Symfony/Component/VarDumper/Tests/HtmlDumperTest.php +++ b/src/Symfony/Component/VarDumper/Tests/HtmlDumperTest.php @@ -49,7 +49,7 @@ public function testGet() $closure54 = ''; $r = defined('HHVM_VERSION') ? '' : '#%d'; - if (PHP_VERSION_ID >= 50400) { + if (\PHP_VERSION_ID >= 50400) { $closure54 = <<class: "Symfony\Component\VarDumper\Tests\HtmlDumperTest" diff --git a/src/Symfony/Component/VarDumper/Tests/Test/VarDumperTestTraitTest.php b/src/Symfony/Component/VarDumper/Tests/Test/VarDumperTestTraitTest.php index a87476be75217..81d1a0cf1b592 100644 --- a/src/Symfony/Component/VarDumper/Tests/Test/VarDumperTestTraitTest.php +++ b/src/Symfony/Component/VarDumper/Tests/Test/VarDumperTestTraitTest.php @@ -10,6 +10,6 @@ */ // Skipping trait tests for PHP < 5.4 -if (PHP_VERSION_ID >= 50400) { +if (\PHP_VERSION_ID >= 50400) { require __DIR__.'/VarDumperTestTraitRequire54.php'; } diff --git a/src/Symfony/Component/Yaml/Exception/ParseException.php b/src/Symfony/Component/Yaml/Exception/ParseException.php index 74548df1f85e1..ef36cfbadd35c 100644 --- a/src/Symfony/Component/Yaml/Exception/ParseException.php +++ b/src/Symfony/Component/Yaml/Exception/ParseException.php @@ -123,7 +123,7 @@ private function updateRepr() } if (null !== $this->parsedFile) { - if (PHP_VERSION_ID >= 50400) { + if (\PHP_VERSION_ID >= 50400) { $jsonOptions = JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE; } else { $jsonOptions = 0; diff --git a/src/Symfony/Component/Yaml/Tests/ParseExceptionTest.php b/src/Symfony/Component/Yaml/Tests/ParseExceptionTest.php index 4f01ab938e504..b7797fb7f32b1 100644 --- a/src/Symfony/Component/Yaml/Tests/ParseExceptionTest.php +++ b/src/Symfony/Component/Yaml/Tests/ParseExceptionTest.php @@ -19,7 +19,7 @@ class ParseExceptionTest extends TestCase public function testGetMessage() { $exception = new ParseException('Error message', 42, 'foo: bar', '/var/www/app/config.yml'); - if (PHP_VERSION_ID >= 50400) { + if (\PHP_VERSION_ID >= 50400) { $message = 'Error message in "/var/www/app/config.yml" at line 42 (near "foo: bar")'; } else { $message = 'Error message in "\\/var\\/www\\/app\\/config.yml" at line 42 (near "foo: bar")'; @@ -31,7 +31,7 @@ public function testGetMessage() public function testGetMessageWithUnicodeInFilename() { $exception = new ParseException('Error message', 42, 'foo: bar', 'äöü.yml'); - if (PHP_VERSION_ID >= 50400) { + if (\PHP_VERSION_ID >= 50400) { $message = 'Error message in "äöü.yml" at line 42 (near "foo: bar")'; } else { $message = 'Error message in "\u00e4\u00f6\u00fc.yml" at line 42 (near "foo: bar")'; From 57daadbf67f3090f8bcd32e6cf70e9266dad9d3e Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Thu, 1 Jun 2017 22:30:09 +0200 Subject: [PATCH 0111/1099] [Di] Remove closure-proxy arguments --- UPGRADE-3.3.md | 2 +- UPGRADE-4.0.md | 2 +- .../Console/Descriptor/Descriptor.php | 4 - .../Console/Descriptor/TextDescriptor.php | 4 - .../Console/Descriptor/XmlDescriptor.php | 6 -- .../Console/Descriptor/ObjectsProvider.php | 2 - .../Descriptor/builder_1_arguments.json | 7 -- .../Descriptor/builder_1_arguments.xml | 1 - .../Descriptor/definition_arguments_1.json | 7 -- .../Descriptor/definition_arguments_1.txt | 43 ++++---- .../Descriptor/definition_arguments_1.xml | 1 - .../Argument/ClosureProxyArgument.php | 50 ---------- .../DependencyInjection/CHANGELOG.md | 1 - .../DependencyInjection/ContainerBuilder.php | 26 ----- .../DependencyInjection/Dumper/PhpDumper.php | 32 ------ .../DependencyInjection/Dumper/XmlDumper.php | 6 -- .../DependencyInjection/Dumper/YamlDumper.php | 3 - .../LazyProxy/ProxyHelper.php | 48 --------- .../Loader/XmlFileLoader.php | 10 -- .../Loader/YamlFileLoader.php | 16 --- .../schema/dic/services/services-1.0.xsd | 2 - .../InlineServiceDefinitionsPassTest.php | 8 +- .../Tests/ContainerBuilderTest.php | 62 ------------ .../Tests/Dumper/PhpDumperTest.php | 40 -------- .../Tests/Fixtures/containers/container31.php | 37 ------- .../Tests/Fixtures/containers/container32.php | 37 ------- .../Tests/Fixtures/containers/container33.php | 1 - .../Tests/Fixtures/containers/container9.php | 5 - ...ainer_dump_proxy_with_void_return_type.php | 27 ----- .../Tests/Fixtures/graphviz/services9.dot | 2 - .../Tests/Fixtures/php/services31.php | 23 ----- .../Tests/Fixtures/php/services32.php | 99 ------------------- .../Tests/Fixtures/php/services9.php | 16 --- .../Tests/Fixtures/php/services9_compiled.php | 16 --- ...vices_dump_proxy_with_void_return_type.php | 95 ------------------ .../Tests/Fixtures/xml/services9.xml | 3 - .../Tests/Fixtures/yaml/services9.yml | 3 - .../Component/EventDispatcher/CHANGELOG.md | 2 +- .../ContainerAwareEventDispatcher.php | 2 +- .../EventDispatcher/Debug/WrappedListener.php | 8 +- .../Component/VarDumper/Caster/ClassStub.php | 4 - 41 files changed, 30 insertions(+), 733 deletions(-) delete mode 100644 src/Symfony/Component/DependencyInjection/Argument/ClosureProxyArgument.php delete mode 100644 src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container31.php delete mode 100644 src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container32.php delete mode 100644 src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container_dump_proxy_with_void_return_type.php delete mode 100644 src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services32.php delete mode 100644 src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_dump_proxy_with_void_return_type.php diff --git a/UPGRADE-3.3.md b/UPGRADE-3.3.md index 05f44e549e11b..b8d2524654386 100644 --- a/UPGRADE-3.3.md +++ b/UPGRADE-3.3.md @@ -127,7 +127,7 @@ EventDispatcher --------------- * The `ContainerAwareEventDispatcher` class has been deprecated. - Use `EventDispatcher` with closure-proxy injection instead. + Use `EventDispatcher` with closure factories instead. Finder ------ diff --git a/UPGRADE-4.0.md b/UPGRADE-4.0.md index 6c10190c7c502..b06145202e7cd 100644 --- a/UPGRADE-4.0.md +++ b/UPGRADE-4.0.md @@ -132,7 +132,7 @@ EventDispatcher --------------- * The `ContainerAwareEventDispatcher` class has been removed. - Use `EventDispatcher` with closure-proxy injection instead. + Use `EventDispatcher` with closure factories instead. ExpressionLanguage ------------------ diff --git a/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/Descriptor.php b/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/Descriptor.php index 268a7818979cb..acaec0bf5dbab 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/Descriptor.php +++ b/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/Descriptor.php @@ -312,10 +312,6 @@ protected function formatClosure(\Closure $closure) { $r = new \ReflectionFunction($closure); - if (preg_match('#^/\*\* @closure-proxy ([^: ]++)::([^: ]++) \*/$#', $r->getDocComment(), $m)) { - return sprintf('%s::%s', $m[1], $m[2]); - } - return 'closure'; } } diff --git a/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/TextDescriptor.php b/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/TextDescriptor.php index 64c38cdff759f..06a404080d32d 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/TextDescriptor.php +++ b/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/TextDescriptor.php @@ -14,7 +14,6 @@ use Symfony\Component\Console\Helper\Table; use Symfony\Component\Console\Style\SymfonyStyle; use Symfony\Component\DependencyInjection\Alias; -use Symfony\Component\DependencyInjection\Argument\ClosureProxyArgument; use Symfony\Component\DependencyInjection\Argument\IteratorArgument; use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument; use Symfony\Component\DependencyInjection\ContainerBuilder; @@ -343,9 +342,6 @@ protected function describeContainerDefinition(Definition $definition, array $op $argumentsInformation[] = sprintf('Service(%s)', (string) $argument); } elseif ($argument instanceof IteratorArgument) { $argumentsInformation[] = sprintf('Iterator (%d element(s))', count($argument->getValues())); - } elseif ($argument instanceof ClosureProxyArgument) { - list($reference, $method) = $argument->getValues(); - $argumentsInformation[] = sprintf('ClosureProxy(Service(%s)::%s())', $reference, $method); } elseif ($argument instanceof Definition) { $argumentsInformation[] = 'Inlined Service'; } else { diff --git a/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/XmlDescriptor.php b/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/XmlDescriptor.php index c1e586cf927f5..f1770d8c3c453 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/XmlDescriptor.php +++ b/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/XmlDescriptor.php @@ -12,7 +12,6 @@ namespace Symfony\Bundle\FrameworkBundle\Console\Descriptor; use Symfony\Component\DependencyInjection\Alias; -use Symfony\Component\DependencyInjection\Argument\ClosureProxyArgument; use Symfony\Component\DependencyInjection\Argument\IteratorArgument; use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument; use Symfony\Component\DependencyInjection\ContainerBuilder; @@ -444,11 +443,6 @@ private function getArgumentNodes(array $arguments, \DOMDocument $dom) foreach ($this->getArgumentNodes($argument->getValues(), $dom) as $childArgumentXML) { $argumentXML->appendChild($childArgumentXML); } - } elseif ($argument instanceof ClosureProxyArgument) { - list($reference, $method) = $argument->getValues(); - $argumentXML->setAttribute('type', 'closure-proxy'); - $argumentXML->setAttribute('id', (string) $reference); - $argumentXML->setAttribute('method', $method); } elseif ($argument instanceof Definition) { $argumentXML->appendChild($dom->importNode($this->getContainerDefinitionDocument($argument, null, false, true)->childNodes->item(0), true)); } elseif (is_array($argument)) { diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Console/Descriptor/ObjectsProvider.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Console/Descriptor/ObjectsProvider.php index 0c0363c482bab..9eb2e874d63d5 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Console/Descriptor/ObjectsProvider.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Console/Descriptor/ObjectsProvider.php @@ -12,7 +12,6 @@ namespace Symfony\Bundle\FrameworkBundle\Tests\Console\Descriptor; use Symfony\Component\DependencyInjection\Alias; -use Symfony\Component\DependencyInjection\Argument\ClosureProxyArgument; use Symfony\Component\DependencyInjection\Argument\IteratorArgument; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Definition; @@ -119,7 +118,6 @@ public static function getContainerDefinitions() new Reference('definition_1'), new Reference('definition_2'), ))) - ->addArgument(new ClosureProxyArgument('definition1', 'get')) ->setFactory(array('Full\\Qualified\\FactoryClass', 'get')), 'definition_2' => $definition2 ->setPublic(false) diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_arguments.json b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_arguments.json index dd3f81f1768e4..e2ab628937760 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_arguments.json +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_arguments.json @@ -60,13 +60,6 @@ "type": "service", "id": "definition_2" } - ], - [ - { - "type": "service", - "id": "definition1" - }, - "get" ] ], "file": null, diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_arguments.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_arguments.xml index 91b292da50248..b016ae382a908 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_arguments.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/builder_1_arguments.xml @@ -22,7 +22,6 @@ - diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_arguments_1.json b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_arguments_1.json index 0590d3f76a611..5074d4fba6170 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_arguments_1.json +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_arguments_1.json @@ -58,13 +58,6 @@ "type": "service", "id": "definition_2" } - ], - [ - { - "type": "service", - "id": "definition1" - }, - "get" ] ], "file": null, diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_arguments_1.txt b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_arguments_1.txt index 0bb95302f8315..989f96ee1369f 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_arguments_1.txt +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_arguments_1.txt @@ -1,23 +1,22 @@ - ---------------- ------------------------------------------- -  Option   Value  - ---------------- ------------------------------------------- - Service ID - - Class Full\Qualified\Class1 - Tags - - Public yes - Synthetic no - Lazy yes - Shared yes - Abstract yes - Autowired no - Autoconfigured no - Factory Class Full\Qualified\FactoryClass - Factory Method get - Arguments Service(definition2)  - %parameter%  - Inlined Service  - Array (3 element(s))  - Iterator (2 element(s))  - ClosureProxy(Service(definition1)::get()) - ---------------- ------------------------------------------- + ---------------- ----------------------------- +  Option   Value  + ---------------- ----------------------------- + Service ID - + Class Full\Qualified\Class1 + Tags - + Public yes + Synthetic no + Lazy yes + Shared yes + Abstract yes + Autowired no + Autoconfigured no + Factory Class Full\Qualified\FactoryClass + Factory Method get + Arguments Service(definition2)  + %parameter%  + Inlined Service  + Array (3 element(s))  + Iterator (2 element(s)) + ---------------- ----------------------------- diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_arguments_1.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_arguments_1.xml index 6d3cb8eea40be..732f99f7839a1 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_arguments_1.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Descriptor/definition_arguments_1.xml @@ -20,5 +20,4 @@ - diff --git a/src/Symfony/Component/DependencyInjection/Argument/ClosureProxyArgument.php b/src/Symfony/Component/DependencyInjection/Argument/ClosureProxyArgument.php deleted file mode 100644 index 94ba13241a108..0000000000000 --- a/src/Symfony/Component/DependencyInjection/Argument/ClosureProxyArgument.php +++ /dev/null @@ -1,50 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Argument; - -use Symfony\Component\DependencyInjection\ContainerInterface; -use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; -use Symfony\Component\DependencyInjection\Reference; - -/** - * @author Nicolas Grekas - */ -class ClosureProxyArgument implements ArgumentInterface -{ - private $reference; - private $method; - - public function __construct($id, $method, $invalidBehavior = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE) - { - $this->reference = new Reference($id, $invalidBehavior); - $this->method = $method; - } - - /** - * {@inheritdoc} - */ - public function getValues() - { - return array($this->reference, $this->method); - } - - /** - * {@inheritdoc} - */ - public function setValues(array $values) - { - if (!$values[0] instanceof Reference) { - throw new InvalidArgumentException(sprintf('A ClosureProxyArgument must hold a Reference, "%s" given.', is_object($values[0]) ? get_class($values[0]) : gettype($values[0]))); - } - list($this->reference, $this->method) = $values; - } -} diff --git a/src/Symfony/Component/DependencyInjection/CHANGELOG.md b/src/Symfony/Component/DependencyInjection/CHANGELOG.md index b591c5958dae7..457e22413ea5f 100644 --- a/src/Symfony/Component/DependencyInjection/CHANGELOG.md +++ b/src/Symfony/Component/DependencyInjection/CHANGELOG.md @@ -20,7 +20,6 @@ CHANGELOG * added support for omitting the factory class name in a service definition if the definition class is set * deprecated case insensitivity of service identifiers * added "iterator" argument type for lazy iteration over a set of values and services - * added "closure-proxy" argument type for turning services' methods into lazy callables * added file-wide configurable defaults for service attributes "public", "tags", "autowire" and "autoconfigure" * made the "class" attribute optional, using the "id" as fallback diff --git a/src/Symfony/Component/DependencyInjection/ContainerBuilder.php b/src/Symfony/Component/DependencyInjection/ContainerBuilder.php index 0675dd6f58071..3887e56fc244a 100644 --- a/src/Symfony/Component/DependencyInjection/ContainerBuilder.php +++ b/src/Symfony/Component/DependencyInjection/ContainerBuilder.php @@ -12,7 +12,6 @@ namespace Symfony\Component\DependencyInjection; use Psr\Container\ContainerInterface as PsrContainerInterface; -use Symfony\Component\DependencyInjection\Argument\ClosureProxyArgument; use Symfony\Component\DependencyInjection\Argument\IteratorArgument; use Symfony\Component\DependencyInjection\Argument\RewindableGenerator; use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument; @@ -1161,31 +1160,6 @@ public function resolveServices($value) return $count; }); - } elseif ($value instanceof ClosureProxyArgument) { - $parameterBag = $this->getParameterBag(); - list($reference, $method) = $value->getValues(); - if ('service_container' === $id = (string) $reference) { - $class = parent::class; - } elseif (!$this->hasDefinition($id) && ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE !== $reference->getInvalidBehavior()) { - return; - } else { - $class = $parameterBag->resolveValue($this->findDefinition($id)->getClass()); - } - if (!method_exists($class, $method = $parameterBag->resolveValue($method))) { - throw new InvalidArgumentException(sprintf('Cannot create closure-proxy for service "%s": method "%s::%s" does not exist.', $id, $class, $method)); - } - $r = new \ReflectionMethod($class, $method); - if (!$r->isPublic()) { - throw new RuntimeException(sprintf('Cannot create closure-proxy for service "%s": method "%s::%s" must be public.', $id, $class, $method)); - } - foreach ($r->getParameters() as $p) { - if ($p->isPassedByReference()) { - throw new RuntimeException(sprintf('Cannot create closure-proxy for service "%s": parameter "$%s" of method "%s::%s" must not be passed by reference.', $id, $p->name, $class, $method)); - } - } - $value = function () use ($id, $method) { - return call_user_func_array(array($this->get($id), $method), func_get_args()); - }; } elseif ($value instanceof Reference) { $value = $this->get((string) $value, $value->getInvalidBehavior()); } elseif ($value instanceof Definition) { diff --git a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php index a1fb8950e0871..840b670f165f5 100644 --- a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php +++ b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php @@ -12,7 +12,6 @@ namespace Symfony\Component\DependencyInjection\Dumper; use Symfony\Component\DependencyInjection\Argument\ArgumentInterface; -use Symfony\Component\DependencyInjection\Argument\ClosureProxyArgument; use Symfony\Component\DependencyInjection\Argument\IteratorArgument; use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument; use Symfony\Component\DependencyInjection\Variable; @@ -27,7 +26,6 @@ use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; use Symfony\Component\DependencyInjection\Exception\RuntimeException; use Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException; -use Symfony\Component\DependencyInjection\LazyProxy\ProxyHelper; use Symfony\Component\DependencyInjection\LazyProxy\PhpDumper\DumperInterface as ProxyDumper; use Symfony\Component\DependencyInjection\LazyProxy\PhpDumper\NullDumper; use Symfony\Component\DependencyInjection\ExpressionLanguage; @@ -67,7 +65,6 @@ class PhpDumper extends Dumper private $docStar; private $serviceIdToMethodNameMap; private $usedMethodNames; - private $baseClass; /** * @var \Symfony\Component\DependencyInjection\LazyProxy\PhpDumper\DumperInterface @@ -125,7 +122,6 @@ public function dump(array $options = array()) $this->classResources = array(); $this->initializeMethodNamesMap($options['base_class']); - $this->baseClass = $options['base_class']; $this->docStar = $options['debug'] ? '*' : ''; @@ -1465,34 +1461,6 @@ private function dumpValue($value, $interpolate = true) return implode("\n", $code); } - - if ($value instanceof ClosureProxyArgument) { - list($reference, $method) = $value->getValues(); - $method = substr($this->dumpLiteralClass($this->dumpValue($method)), 1); - - if ('service_container' === (string) $reference) { - $class = $this->baseClass; - } elseif (!$this->container->hasDefinition((string) $reference) && ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE !== $reference->getInvalidBehavior()) { - return 'null'; - } else { - $class = substr($this->dumpLiteralClass($this->dumpValue($this->container->findDefinition((string) $reference)->getClass())), 1); - } - if (false !== strpos($class, '$') || false !== strpos($method, '$')) { - throw new RuntimeException(sprintf('Cannot dump definition for service "%s": dynamic class names or methods, and closure-proxies are incompatible with each other.', $reference)); - } - if (!method_exists($class, $method)) { - throw new InvalidArgumentException(sprintf('Cannot create closure-proxy for service "%s": method "%s::%s" does not exist.', $reference, $class, $method)); - } - $r = $this->container->getReflectionClass($class)->getMethod($method); - if (!$r->isPublic()) { - throw new InvalidArgumentException(sprintf('Cannot create closure-proxy for service "%s": method "%s::%s" must be public.', $reference, $class, $method)); - } - $signature = preg_replace('/^(&?)[^(]*/', '$1', ProxyHelper::getSignature($r, $call)); - - $return = 'void' !== ProxyHelper::getTypeHint($r); - - return sprintf("/** @closure-proxy %s::%s */ function %s {\n %s%s->%s;\n }", $class, $method, $signature, $return ? 'return ' : '', $this->dumpValue($reference), $call); - } } finally { list($this->definitionVariables, $this->referenceVariables, $this->variableCount) = $scope; } diff --git a/src/Symfony/Component/DependencyInjection/Dumper/XmlDumper.php b/src/Symfony/Component/DependencyInjection/Dumper/XmlDumper.php index 61978dcd28971..c6b3be06a1402 100644 --- a/src/Symfony/Component/DependencyInjection/Dumper/XmlDumper.php +++ b/src/Symfony/Component/DependencyInjection/Dumper/XmlDumper.php @@ -11,7 +11,6 @@ namespace Symfony\Component\DependencyInjection\Dumper; -use Symfony\Component\DependencyInjection\Argument\ClosureProxyArgument; use Symfony\Component\DependencyInjection\Argument\IteratorArgument; use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument; use Symfony\Component\DependencyInjection\ContainerInterface; @@ -302,11 +301,6 @@ private function convertParameters(array $parameters, $type, \DOMElement $parent } elseif ($value instanceof IteratorArgument) { $element->setAttribute('type', 'iterator'); $this->convertParameters($value->getValues(), $type, $element, 'key'); - } elseif ($value instanceof ClosureProxyArgument) { - list($reference, $method) = $value->getValues(); - $element->setAttribute('type', 'closure-proxy'); - $element->setAttribute('id', (string) $reference); - $element->setAttribute('method', $method); } elseif ($value instanceof Reference) { $element->setAttribute('type', 'service'); $element->setAttribute('id', (string) $value); diff --git a/src/Symfony/Component/DependencyInjection/Dumper/YamlDumper.php b/src/Symfony/Component/DependencyInjection/Dumper/YamlDumper.php index 81951fe536699..e71df2af24c14 100644 --- a/src/Symfony/Component/DependencyInjection/Dumper/YamlDumper.php +++ b/src/Symfony/Component/DependencyInjection/Dumper/YamlDumper.php @@ -15,7 +15,6 @@ use Symfony\Component\Yaml\Tag\TaggedValue; use Symfony\Component\DependencyInjection\Alias; use Symfony\Component\DependencyInjection\Argument\ArgumentInterface; -use Symfony\Component\DependencyInjection\Argument\ClosureProxyArgument; use Symfony\Component\DependencyInjection\Argument\IteratorArgument; use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument; use Symfony\Component\DependencyInjection\ContainerInterface; @@ -256,8 +255,6 @@ private function dumpValue($value) if ($value instanceof ArgumentInterface) { if ($value instanceof IteratorArgument) { $tag = 'iterator'; - } elseif ($value instanceof ClosureProxyArgument) { - $tag = 'closure_proxy'; } else { throw new RuntimeException(sprintf('Unspecified Yaml tag for type "%s".', get_class($value))); } diff --git a/src/Symfony/Component/DependencyInjection/LazyProxy/ProxyHelper.php b/src/Symfony/Component/DependencyInjection/LazyProxy/ProxyHelper.php index 5f0c8772fef43..84686efff5d6a 100644 --- a/src/Symfony/Component/DependencyInjection/LazyProxy/ProxyHelper.php +++ b/src/Symfony/Component/DependencyInjection/LazyProxy/ProxyHelper.php @@ -18,54 +18,6 @@ */ class ProxyHelper { - /** - * @return string The signature of the passed function, return type and function/method name included if any - */ - public static function getSignature(\ReflectionFunctionAbstract $r, &$call = null) - { - $signature = array(); - $call = array(); - - foreach ($r->getParameters() as $i => $p) { - $k = '$'.$p->name; - if (method_exists($p, 'isVariadic') && $p->isVariadic()) { - $k = '...'.$k; - } - $call[] = $k; - - if ($p->isPassedByReference()) { - $k = '&'.$k; - } - if ($type = self::getTypeHint($r, $p)) { - $k = $type.' '.$k; - } - if ($type && $p->allowsNull()) { - $k = '?'.$k; - } - - try { - $k .= ' = '.self::export($p->getDefaultValue()); - if ($type && $p->allowsNull() && null === $p->getDefaultValue()) { - $k = substr($k, 1); - } - } catch (\ReflectionException $e) { - if ($type && $p->allowsNull() && !class_exists('ReflectionNamedType', false)) { - $k .= ' = null'; - $k = substr($k, 1); - } - } - - $signature[] = $k; - } - $call = ($r->isClosure() ? '' : $r->name).'('.implode(', ', $call).')'; - - if ($type = self::getTypeHint($r)) { - $type = ': '.($r->getReturnType()->allowsNull() ? '?' : '').$type; - } - - return ($r->returnsReference() ? '&' : '').($r->isClosure() ? '' : $r->name).'('.implode(', ', $signature).')'.$type; - } - /** * @return string|null The FQCN or builtin name of the type hint, or null when the type hint references an invalid self|parent context */ diff --git a/src/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php b/src/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php index 79c8fbf9677ab..4b07e5c58581e 100644 --- a/src/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php +++ b/src/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php @@ -14,7 +14,6 @@ use Symfony\Component\Config\Util\XmlUtils; use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\DependencyInjection\Alias; -use Symfony\Component\DependencyInjection\Argument\ClosureProxyArgument; use Symfony\Component\DependencyInjection\Argument\IteratorArgument; use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\DependencyInjection\ChildDefinition; @@ -493,15 +492,6 @@ private function getArgumentsAsPhp(\DOMElement $node, $name, $file, $lowercase = case 'expression': $arguments[$key] = new Expression($arg->nodeValue); break; - case 'closure-proxy': - if (!$arg->getAttribute('id')) { - throw new InvalidArgumentException(sprintf('Tag "<%s>" with type="closure-proxy" has no or empty "id" attribute in "%s".', $name, $file)); - } - if (!$arg->getAttribute('method')) { - throw new InvalidArgumentException(sprintf('Tag "<%s>" with type="closure-proxy" has no or empty "method" attribute in "%s".', $name, $file)); - } - $arguments[$key] = new ClosureProxyArgument($arg->getAttribute('id'), $arg->getAttribute('method'), $invalidBehavior); - break; case 'collection': $arguments[$key] = $this->getArgumentsAsPhp($arg, $name, $file, false); break; diff --git a/src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php b/src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php index c3e697c1b5207..7a0123ba21bf5 100644 --- a/src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php +++ b/src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php @@ -13,7 +13,6 @@ use Symfony\Component\DependencyInjection\Alias; use Symfony\Component\DependencyInjection\Argument\ArgumentInterface; -use Symfony\Component\DependencyInjection\Argument\ClosureProxyArgument; use Symfony\Component\DependencyInjection\Argument\IteratorArgument; use Symfony\Component\DependencyInjection\ChildDefinition; use Symfony\Component\DependencyInjection\ContainerInterface; @@ -679,21 +678,6 @@ private function resolveServices($value, $file, $isParameter = false) throw new InvalidArgumentException(sprintf('"!iterator" tag only accepts arrays of "@service" references in "%s".', $file)); } } - if ('closure_proxy' === $value->getTag()) { - if (!is_array($argument) || array(0, 1) !== array_keys($argument) || !is_string($argument[0]) || !is_string($argument[1]) || 0 !== strpos($argument[0], '@') || 0 === strpos($argument[0], '@@')) { - throw new InvalidArgumentException(sprintf('"!closure_proxy" tagged values must be arrays of [@service, method] in "%s".', $file)); - } - - if (0 === strpos($argument[0], '@?')) { - $argument[0] = substr($argument[0], 2); - $invalidBehavior = ContainerInterface::IGNORE_ON_INVALID_REFERENCE; - } else { - $argument[0] = substr($argument[0], 1); - $invalidBehavior = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE; - } - - return new ClosureProxyArgument($argument[0], $argument[1], $invalidBehavior); - } if ('service' === $value->getTag()) { if ($isParameter) { throw new InvalidArgumentException(sprintf('Using an anonymous service in a parameter is not allowed in "%s".', $file)); diff --git a/src/Symfony/Component/DependencyInjection/Loader/schema/dic/services/services-1.0.xsd b/src/Symfony/Component/DependencyInjection/Loader/schema/dic/services/services-1.0.xsd index 2de786bdb7cba..6f5c8ccc543d3 100644 --- a/src/Symfony/Component/DependencyInjection/Loader/schema/dic/services/services-1.0.xsd +++ b/src/Symfony/Component/DependencyInjection/Loader/schema/dic/services/services-1.0.xsd @@ -218,7 +218,6 @@ - @@ -244,7 +243,6 @@ - diff --git a/src/Symfony/Component/DependencyInjection/Tests/Compiler/InlineServiceDefinitionsPassTest.php b/src/Symfony/Component/DependencyInjection/Tests/Compiler/InlineServiceDefinitionsPassTest.php index f0dd7fe74dc4c..26b24fa713242 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Compiler/InlineServiceDefinitionsPassTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Compiler/InlineServiceDefinitionsPassTest.php @@ -18,7 +18,7 @@ use Symfony\Component\DependencyInjection\Compiler\InlineServiceDefinitionsPass; use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Argument\ClosureProxyArgument; +use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument; use Symfony\Component\DependencyInjection\Argument\IteratorArgument; class InlineServiceDefinitionsPassTest extends TestCase @@ -233,8 +233,8 @@ public function testProcessDoesNotSetLazyArgumentValuesAfterInlining() ->setShared(false) ; $container - ->register('closure-proxy') - ->setArguments(array(new ClosureProxyArgument('inline', 'method'))) + ->register('service-closure') + ->setArguments(array(new ServiceClosureArgument(new Reference('inline')))) ; $container ->register('iterator') @@ -243,7 +243,7 @@ public function testProcessDoesNotSetLazyArgumentValuesAfterInlining() $this->process($container); - $values = $container->getDefinition('closure-proxy')->getArgument(0)->getValues(); + $values = $container->getDefinition('service-closure')->getArgument(0)->getValues(); $this->assertInstanceOf(Reference::class, $values[0]); $this->assertSame('inline', (string) $values[0]); diff --git a/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php b/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php index 3558c7bd226e1..51f7001491a19 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php @@ -20,7 +20,6 @@ use Symfony\Component\Config\Resource\ResourceInterface; use Symfony\Component\Config\Resource\DirectoryResource; use Symfony\Component\DependencyInjection\Alias; -use Symfony\Component\DependencyInjection\Argument\ClosureProxyArgument; use Symfony\Component\DependencyInjection\Argument\IteratorArgument; use Symfony\Component\DependencyInjection\Argument\RewindableGenerator; use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument; @@ -1008,63 +1007,6 @@ public function testAutowiring() $this->assertEquals(A::class, (string) $container->getDefinition('b')->getArgument(0)); } - public function testClosureProxy() - { - $container = new ContainerBuilder(); - - $container->register('foo', 'stdClass') - ->setProperty('foo', new ClosureProxyArgument('bar', 'c')) - ; - $container->register('bar', A::class); - - $foo = $container->get('foo'); - - $this->assertInstanceOf('Closure', $foo->foo); - $this->assertSame(123, call_user_func($foo->foo)); - } - - public function testClosureProxyContainer() - { - $container = new ContainerBuilder(); - - $container->register('foo', 'stdClass') - ->setProperty('foo', new ClosureProxyArgument('service_container', 'get')) - ; - - $foo = $container->get('foo'); - - $this->assertInstanceOf('Closure', $foo->foo); - $this->assertSame($foo, call_user_func($foo->foo, 'foo')); - } - - public function testClosureProxyOnInvalidNull() - { - $container = new ContainerBuilder(); - - $container->register('foo', 'stdClass') - ->setProperty('foo', new ClosureProxyArgument('bar', 'c', ContainerInterface::NULL_ON_INVALID_REFERENCE)) - ; - - $foo = $container->get('foo'); - - $this->assertNull($foo->foo); - } - - /** - * @expectedException \Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException - * @expectedExceptionMessage You have requested a non-existent service "bar". - */ - public function testClosureProxyOnInvalidException() - { - $container = new ContainerBuilder(); - - $container->register('foo', 'stdClass') - ->setProperty('foo', new ClosureProxyArgument('bar', 'c')) - ; - - $container->get('foo'); - } - public function testClassFromId() { $container = new ContainerBuilder(); @@ -1148,10 +1090,6 @@ class FooClass class A { - public function c() - { - return 123; - } } class B diff --git a/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php b/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php index b11201111c1f5..fe53b941006de 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php @@ -472,46 +472,6 @@ public function testLazyArgumentProvideGenerator() $this->assertEmpty(iterator_to_array($lazyContext->lazyEmptyValues)); } - public function testClosureProxy() - { - $container = include self::$fixturesPath.'/containers/container31.php'; - $container->compile(); - $dumper = new PhpDumper($container); - - $this->assertStringEqualsFile(self::$fixturesPath.'/php/services31.php', $dumper->dump()); - $res = $container->getResources(); - $this->assertSame('reflection.Symfony\Component\DependencyInjection\Tests\Fixtures\Container31\Foo', (string) array_pop($res)); - } - - /** - * @requires PHP 7.1 - */ - public function testClosureProxyWithVoidReturnType() - { - $container = include self::$fixturesPath.'/containers/container_dump_proxy_with_void_return_type.php'; - - $container->compile(); - $dumper = new PhpDumper($container); - - $this->assertStringEqualsFile(self::$fixturesPath.'/php/services_dump_proxy_with_void_return_type.php', $dumper->dump()); - $res = $container->getResources(); - $this->assertSame('reflection.Symfony\Component\DependencyInjection\Tests\Fixtures\ContainerVoid\Foo', (string) array_pop($res)); - } - - /** - * @requires PHP 7.1 - */ - public function testClosureProxyPhp71() - { - $container = include self::$fixturesPath.'/containers/container32.php'; - $container->compile(); - $dumper = new PhpDumper($container); - - $this->assertStringEqualsFile(self::$fixturesPath.'/php/services32.php', $dumper->dump()); - $res = $container->getResources(); - $this->assertSame('reflection.Symfony\Component\DependencyInjection\Tests\Fixtures\Container32\Foo', (string) array_pop($res)); - } - public function testNormalizedId() { $container = include self::$fixturesPath.'/containers/container33.php'; diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container31.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container31.php deleted file mode 100644 index e8493ad02cdf6..0000000000000 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container31.php +++ /dev/null @@ -1,37 +0,0 @@ -register('foo', Foo::class); - -$container->register('bar', 'stdClass') - ->setProperty('foo', array( - new ClosureProxyArgument('foo', 'withNoArgs'), - new ClosureProxyArgument('foo', 'withArgs'), - new ClosureProxyArgument('foo', 'withRefs'), - )) -; - -return $container; diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container32.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container32.php deleted file mode 100644 index 00d5654a5b464..0000000000000 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container32.php +++ /dev/null @@ -1,37 +0,0 @@ -register('foo', Foo::class); - -$container->register('bar', 'stdClass') - ->setProperty('foo', array( - new ClosureProxyArgument('foo', 'withVariadic'), - new ClosureProxyArgument('foo', 'withNullable'), - new ClosureProxyArgument('foo', 'withReturnType'), - )) -; - -return $container; diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container33.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container33.php index 482558cb0d352..6deb52d170af8 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container33.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container33.php @@ -2,7 +2,6 @@ namespace Symfony\Component\DependencyInjection\Tests\Fixtures\Container33; -use Symfony\Component\DependencyInjection\Argument\ClosureProxyArgument; use Symfony\Component\DependencyInjection\ContainerBuilder; if (!class_exists(Foo::class, false)) { diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container9.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container9.php index 2a31ec6d76e47..13b45fda07a70 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container9.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container9.php @@ -3,7 +3,6 @@ require_once __DIR__.'/../includes/classes.php'; require_once __DIR__.'/../includes/foo.php'; -use Symfony\Component\DependencyInjection\Argument\ClosureProxyArgument; use Symfony\Component\DependencyInjection\Argument\IteratorArgument; use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\DependencyInjection\ContainerBuilder; @@ -140,9 +139,5 @@ ->register('lazy_context_ignore_invalid_ref', 'LazyContext') ->setArguments(array(new IteratorArgument(array(new Reference('foo.baz'), new Reference('invalid', ContainerInterface::IGNORE_ON_INVALID_REFERENCE))), new IteratorArgument(array()))) ; -$container - ->register('closure_proxy', 'BarClass') - ->setArguments(array(new ClosureProxyArgument('closure_proxy', 'getBaz'))) -; return $container; diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container_dump_proxy_with_void_return_type.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container_dump_proxy_with_void_return_type.php deleted file mode 100644 index ef9cb92a6c141..0000000000000 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container_dump_proxy_with_void_return_type.php +++ /dev/null @@ -1,27 +0,0 @@ -register('foo', Foo::class); - -$container->register('bar', 'stdClass') - ->setProperty('foo', array( - new ClosureProxyArgument('foo', 'withVoid'), - )) -; - -return $container; diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/graphviz/services9.dot b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/graphviz/services9.dot index ac6a9c38d1d51..b316b93c1576b 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/graphviz/services9.dot +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/graphviz/services9.dot @@ -29,7 +29,6 @@ digraph sc { node_factory_service_simple [label="factory_service_simple\nBar\n", shape=record, fillcolor="#eeeeee", style="filled"]; node_lazy_context [label="lazy_context\nLazyContext\n", shape=record, fillcolor="#eeeeee", style="filled"]; node_lazy_context_ignore_invalid_ref [label="lazy_context_ignore_invalid_ref\nLazyContext\n", shape=record, fillcolor="#eeeeee", style="filled"]; - node_closure_proxy [label="closure_proxy\nBarClass\n", shape=record, fillcolor="#eeeeee", style="filled"]; node_foo2 [label="foo2\n\n", shape=record, fillcolor="#ff9999", style="filled"]; node_foo3 [label="foo3\n\n", shape=record, fillcolor="#ff9999", style="filled"]; node_foobaz [label="foobaz\n\n", shape=record, fillcolor="#ff9999", style="filled"]; @@ -51,5 +50,4 @@ digraph sc { node_lazy_context -> node_service_container [label="" style="filled" color="#9999ff"]; node_lazy_context_ignore_invalid_ref -> node_foo_baz [label="" style="filled" color="#9999ff"]; node_lazy_context_ignore_invalid_ref -> node_invalid [label="" style="filled" color="#9999ff"]; - node_closure_proxy -> node_closure_proxy [label="" style="filled" color="#9999ff"]; } diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services31.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services31.php index d22a130cd0514..daf0ed5d60a19 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services31.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services31.php @@ -61,29 +61,6 @@ public function isFrozen() return true; } - /** - * Gets the 'bar' service. - * - * This service is shared. - * This method always returns the same instance of the service. - * - * @return \stdClass A stdClass instance - */ - protected function getBarService() - { - $this->services['bar'] = $instance = new \stdClass(); - - $instance->foo = array(0 => /** @closure-proxy Symfony\Component\DependencyInjection\Tests\Fixtures\Container31\Foo::withNoArgs */ function () { - return ${($_ = isset($this->services['foo']) ? $this->services['foo'] : $this->get('foo')) && false ?: '_'}->withNoArgs(); - }, 1 => /** @closure-proxy Symfony\Component\DependencyInjection\Tests\Fixtures\Container31\Foo::withArgs */ function ($a, \Symfony\Component\DependencyInjection\Tests\Fixtures\Container31\Foo $b = NULL, $c = array(0 => 123)) { - return ${($_ = isset($this->services['foo']) ? $this->services['foo'] : $this->get('foo')) && false ?: '_'}->withArgs($a, $b, $c); - }, 2 => /** @closure-proxy Symfony\Component\DependencyInjection\Tests\Fixtures\Container31\Foo::withRefs */ function &(&$a = NULL, &$b) { - return ${($_ = isset($this->services['foo']) ? $this->services['foo'] : $this->get('foo')) && false ?: '_'}->withRefs($a, $b); - }); - - return $instance; - } - /** * Gets the 'foo' service. * diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services32.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services32.php deleted file mode 100644 index 08ca63092a6a6..0000000000000 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services32.php +++ /dev/null @@ -1,99 +0,0 @@ -services = array(); - $this->methodMap = array( - 'bar' => 'getBarService', - 'foo' => 'getFooService', - ); - - $this->aliases = array(); - } - - /** - * {@inheritdoc} - */ - public function compile() - { - throw new LogicException('You cannot compile a dumped container that was already compiled.'); - } - - /** - * {@inheritdoc} - */ - public function isCompiled() - { - return true; - } - - /** - * {@inheritdoc} - */ - public function isFrozen() - { - @trigger_error(sprintf('The %s() method is deprecated since version 3.3 and will be removed in 4.0. Use the isCompiled() method instead.', __METHOD__), E_USER_DEPRECATED); - - return true; - } - - /** - * Gets the 'bar' service. - * - * This service is shared. - * This method always returns the same instance of the service. - * - * @return \stdClass A stdClass instance - */ - protected function getBarService() - { - $this->services['bar'] = $instance = new \stdClass(); - - $instance->foo = array(0 => /** @closure-proxy Symfony\Component\DependencyInjection\Tests\Fixtures\Container32\Foo::withVariadic */ function ($a, &...$c) { - return ${($_ = isset($this->services['foo']) ? $this->services['foo'] : $this->get('foo')) && false ?: '_'}->withVariadic($a, ...$c); - }, 1 => /** @closure-proxy Symfony\Component\DependencyInjection\Tests\Fixtures\Container32\Foo::withNullable */ function (?int $a) { - return ${($_ = isset($this->services['foo']) ? $this->services['foo'] : $this->get('foo')) && false ?: '_'}->withNullable($a); - }, 2 => /** @closure-proxy Symfony\Component\DependencyInjection\Tests\Fixtures\Container32\Foo::withReturnType */ function (): \Bar { - return ${($_ = isset($this->services['foo']) ? $this->services['foo'] : $this->get('foo')) && false ?: '_'}->withReturnType(); - }); - - return $instance; - } - - /** - * Gets the 'foo' service. - * - * This service is shared. - * This method always returns the same instance of the service. - * - * @return \Symfony\Component\DependencyInjection\Tests\Fixtures\Container32\Foo A Symfony\Component\DependencyInjection\Tests\Fixtures\Container32\Foo instance - */ - protected function getFooService() - { - return $this->services['foo'] = new \Symfony\Component\DependencyInjection\Tests\Fixtures\Container32\Foo(); - } -} diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9.php index b8d5aeafacf24..2f8de5c8c0eb1 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9.php @@ -34,7 +34,6 @@ public function __construct() $this->methodMap = array( 'bar' => 'getBarService', 'baz' => 'getBazService', - 'closure_proxy' => 'getClosureProxyService', 'configurator_service' => 'getConfiguratorServiceService', 'configurator_service_simple' => 'getConfiguratorServiceSimpleService', 'configured_service' => 'getConfiguredServiceService', @@ -109,21 +108,6 @@ protected function getBazService() return $instance; } - /** - * Gets the 'closure_proxy' service. - * - * This service is shared. - * This method always returns the same instance of the service. - * - * @return \BarClass A BarClass instance - */ - protected function getClosureProxyService() - { - return $this->services['closure_proxy'] = new \BarClass(/** @closure-proxy BarClass::getBaz */ function () { - return ${($_ = isset($this->services['closure_proxy']) ? $this->services['closure_proxy'] : $this->get('closure_proxy')) && false ?: '_'}->getBaz(); - }); - } - /** * Gets the 'configured_service' service. * diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_compiled.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_compiled.php index a519cece6e297..08707b3b692c1 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_compiled.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_compiled.php @@ -32,7 +32,6 @@ public function __construct() $this->methodMap = array( 'bar' => 'getBarService', 'baz' => 'getBazService', - 'closure_proxy' => 'getClosureProxyService', 'configured_service' => 'getConfiguredServiceService', 'configured_service_simple' => 'getConfiguredServiceSimpleService', 'decorator_service' => 'getDecoratorServiceService', @@ -119,21 +118,6 @@ protected function getBazService() return $instance; } - /** - * Gets the 'closure_proxy' service. - * - * This service is shared. - * This method always returns the same instance of the service. - * - * @return \BarClass A BarClass instance - */ - protected function getClosureProxyService() - { - return $this->services['closure_proxy'] = new \BarClass(/** @closure-proxy BarClass::getBaz */ function () { - return ${($_ = isset($this->services['closure_proxy']) ? $this->services['closure_proxy'] : $this->get('closure_proxy')) && false ?: '_'}->getBaz(); - }); - } - /** * Gets the 'configured_service' service. * diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_dump_proxy_with_void_return_type.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_dump_proxy_with_void_return_type.php deleted file mode 100644 index ec6af7fc2c8c5..0000000000000 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_dump_proxy_with_void_return_type.php +++ /dev/null @@ -1,95 +0,0 @@ -services = array(); - $this->methodMap = array( - 'bar' => 'getBarService', - 'foo' => 'getFooService', - ); - - $this->aliases = array(); - } - - /** - * {@inheritdoc} - */ - public function compile() - { - throw new LogicException('You cannot compile a dumped container that was already compiled.'); - } - - /** - * {@inheritdoc} - */ - public function isCompiled() - { - return true; - } - - /** - * {@inheritdoc} - */ - public function isFrozen() - { - @trigger_error(sprintf('The %s() method is deprecated since version 3.3 and will be removed in 4.0. Use the isCompiled() method instead.', __METHOD__), E_USER_DEPRECATED); - - return true; - } - - /** - * Gets the 'bar' service. - * - * This service is shared. - * This method always returns the same instance of the service. - * - * @return \stdClass A stdClass instance - */ - protected function getBarService() - { - $this->services['bar'] = $instance = new \stdClass(); - - $instance->foo = array(0 => /** @closure-proxy Symfony\Component\DependencyInjection\Tests\Fixtures\ContainerVoid\Foo::withVoid */ function (): void { - ${($_ = isset($this->services['foo']) ? $this->services['foo'] : $this->get('foo')) && false ?: '_'}->withVoid(); - }); - - return $instance; - } - - /** - * Gets the 'foo' service. - * - * This service is shared. - * This method always returns the same instance of the service. - * - * @return \Symfony\Component\DependencyInjection\Tests\Fixtures\ContainerVoid\Foo A Symfony\Component\DependencyInjection\Tests\Fixtures\ContainerVoid\Foo instance - */ - protected function getFooService() - { - return $this->services['foo'] = new \Symfony\Component\DependencyInjection\Tests\Fixtures\ContainerVoid\Foo(); - } -} diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services9.xml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services9.xml index 79fdff4c4e2d0..100a23a9c5b7e 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services9.xml +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services9.xml @@ -130,9 +130,6 @@ - - - diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services9.yml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services9.yml index bfee29fb605e5..a7a9cc28fd61b 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services9.yml +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services9.yml @@ -116,9 +116,6 @@ services: lazy_context_ignore_invalid_ref: class: LazyContext arguments: [!iterator ['@foo.baz', '@?invalid'], !iterator []] - closure_proxy: - class: BarClass - arguments: [!closure_proxy ['@closure_proxy', getBaz]] alias_for_foo: '@foo' alias_for_alias: '@foo' Psr\Container\ContainerInterface: diff --git a/src/Symfony/Component/EventDispatcher/CHANGELOG.md b/src/Symfony/Component/EventDispatcher/CHANGELOG.md index 51c1d919bb4df..736bd84903b4b 100644 --- a/src/Symfony/Component/EventDispatcher/CHANGELOG.md +++ b/src/Symfony/Component/EventDispatcher/CHANGELOG.md @@ -4,7 +4,7 @@ CHANGELOG 3.3.0 ----- - * The ContainerAwareEventDispatcher class has been deprecated. Use EventDispatcher with closure-proxy injection instead. + * The ContainerAwareEventDispatcher class has been deprecated. Use EventDispatcher with closure factories instead. 3.0.0 ----- diff --git a/src/Symfony/Component/EventDispatcher/ContainerAwareEventDispatcher.php b/src/Symfony/Component/EventDispatcher/ContainerAwareEventDispatcher.php index 72eca3deb0490..f9e51b1a8b864 100644 --- a/src/Symfony/Component/EventDispatcher/ContainerAwareEventDispatcher.php +++ b/src/Symfony/Component/EventDispatcher/ContainerAwareEventDispatcher.php @@ -160,7 +160,7 @@ public function getListenerPriority($eventName, $listener) */ public function addSubscriberService($serviceId, $class) { - @trigger_error(sprintf('The %s class is deprecated since version 3.3 and will be removed in 4.0. Use EventDispatcher with closure-proxy injection instead.', __CLASS__), E_USER_DEPRECATED); + @trigger_error(sprintf('The %s class is deprecated since version 3.3 and will be removed in 4.0. Use EventDispatcher with closure factories instead.', __CLASS__), E_USER_DEPRECATED); foreach ($class::getSubscribedEvents() as $eventName => $params) { if (is_string($params)) { diff --git a/src/Symfony/Component/EventDispatcher/Debug/WrappedListener.php b/src/Symfony/Component/EventDispatcher/Debug/WrappedListener.php index 130cc54d343bd..4029883dd98c7 100644 --- a/src/Symfony/Component/EventDispatcher/Debug/WrappedListener.php +++ b/src/Symfony/Component/EventDispatcher/Debug/WrappedListener.php @@ -46,13 +46,7 @@ public function __construct($listener, $name, Stopwatch $stopwatch, EventDispatc $this->name = is_object($listener[0]) ? get_class($listener[0]) : $listener[0]; $this->pretty = $this->name.'::'.$listener[1]; } elseif ($listener instanceof \Closure) { - $r = new \ReflectionFunction($listener); - if (preg_match('#^/\*\* @closure-proxy ([^: ]++)::([^: ]++) \*/$#', $r->getDocComment(), $m)) { - $this->name = $m[1]; - $this->pretty = $m[1].'::'.$m[2]; - } else { - $this->pretty = $this->name = 'closure'; - } + $this->pretty = $this->name = 'closure'; } elseif (is_string($listener)) { $this->pretty = $this->name = $listener; } else { diff --git a/src/Symfony/Component/VarDumper/Caster/ClassStub.php b/src/Symfony/Component/VarDumper/Caster/ClassStub.php index 51990bc356c0d..4765174d08670 100644 --- a/src/Symfony/Component/VarDumper/Caster/ClassStub.php +++ b/src/Symfony/Component/VarDumper/Caster/ClassStub.php @@ -38,10 +38,6 @@ public function __construct($identifier, $callable = null) if (null !== $callable) { if ($callable instanceof \Closure) { $r = new \ReflectionFunction($callable); - - if (preg_match('#^/\*\* @closure-proxy ([^: ]++)::([^: ]++) \*/$#', $r->getDocComment(), $m)) { - $r = array($m[1], $m[2]); - } } elseif (is_object($callable)) { $r = array($callable, '__invoke'); } elseif (is_array($callable)) { From c3d1262208783fa103e7bb9fe5b3cddb1096dcfd Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Tue, 30 May 2017 12:15:38 +0200 Subject: [PATCH 0112/1099] Use namespaced Twig --- composer.json | 2 +- .../Bridge/Twig/Command/DebugCommand.php | 10 +- .../Bridge/Twig/Command/LintCommand.php | 25 ++-- .../Twig/DataCollector/TwigDataCollector.php | 11 +- .../Bridge/Twig/Extension/AssetExtension.php | 10 +- .../Bridge/Twig/Extension/CodeExtension.php | 21 +-- .../Bridge/Twig/Extension/DumpExtension.php | 12 +- .../Twig/Extension/ExpressionExtension.php | 6 +- .../Bridge/Twig/Extension/FormExtension.php | 34 +++-- .../Extension/HttpFoundationExtension.php | 8 +- .../Twig/Extension/HttpKernelExtension.php | 10 +- .../Twig/Extension/LogoutUrlExtension.php | 8 +- .../Twig/Extension/ProfilerExtension.php | 10 +- .../Twig/Extension/RoutingExtension.php | 19 ++- .../Twig/Extension/SecurityExtension.php | 6 +- .../Twig/Extension/StopwatchExtension.php | 3 +- .../Twig/Extension/TranslationExtension.php | 14 +- .../Bridge/Twig/Extension/YamlExtension.php | 8 +- src/Symfony/Bridge/Twig/Form/TwigRenderer.php | 3 +- .../Bridge/Twig/Form/TwigRendererEngine.php | 14 +- .../Twig/Form/TwigRendererEngineInterface.php | 11 +- .../Twig/Form/TwigRendererInterface.php | 11 +- src/Symfony/Bridge/Twig/Node/DumpNode.php | 11 +- .../Bridge/Twig/Node/FormThemeNode.php | 14 +- .../Bridge/Twig/Node/RenderBlockNode.php | 7 +- .../Twig/Node/SearchAndRenderBlockNode.php | 15 ++- .../Bridge/Twig/Node/StopwatchNode.php | 10 +- .../Twig/Node/TransDefaultDomainNode.php | 15 +-- src/Symfony/Bridge/Twig/Node/TransNode.php | 38 +++--- .../TranslationDefaultDomainNodeVisitor.php | 31 +++-- .../NodeVisitor/TranslationNodeVisitor.php | 31 +++-- .../Twig/Tests/Command/LintCommandTest.php | 4 +- .../Tests/Extension/DumpExtensionTest.php | 6 +- .../Extension/ExpressionExtensionTest.php | 4 +- .../Fixtures/StubFilesystemLoader.php | 4 +- ...xtensionBootstrap3HorizontalLayoutTest.php | 3 +- .../FormExtensionBootstrap3LayoutTest.php | 3 +- .../Extension/FormExtensionDivLayoutTest.php | 3 +- .../FormExtensionTableLayoutTest.php | 3 +- .../Extension/HttpKernelExtensionTest.php | 8 +- .../Tests/Extension/RoutingExtensionTest.php | 9 +- .../Extension/StopwatchExtensionTest.php | 9 +- .../Extension/TranslationExtensionTest.php | 18 +-- .../Bridge/Twig/Tests/Node/DumpNodeTest.php | 34 ++--- .../Bridge/Twig/Tests/Node/FormThemeTest.php | 30 +++-- .../Node/SearchAndRenderBlockNodeTest.php | 125 +++++++++--------- .../Bridge/Twig/Tests/Node/TransNodeTest.php | 14 +- ...ranslationDefaultDomainNodeVisitorTest.php | 15 ++- .../TranslationNodeVisitorTest.php | 22 +-- .../Tests/NodeVisitor/TwigNodeProvider.php | 51 ++++--- .../TokenParser/FormThemeTokenParserTest.php | 56 ++++---- .../Tests/Translation/TwigExtractorTest.php | 17 ++- .../Bridge/Twig/Tests/TwigEngineTest.php | 8 +- .../Twig/TokenParser/DumpTokenParser.php | 10 +- .../Twig/TokenParser/FormThemeTokenParser.php | 20 +-- .../Twig/TokenParser/StopwatchTokenParser.php | 15 ++- .../TokenParser/TransChoiceTokenParser.php | 24 ++-- .../TransDefaultDomainTokenParser.php | 13 +- .../Twig/TokenParser/TransTokenParser.php | 33 +++-- .../Bridge/Twig/Translation/TwigExtractor.php | 13 +- src/Symfony/Bridge/Twig/TwigEngine.php | 45 +++---- src/Symfony/Bridge/Twig/composer.json | 2 +- ...ainerAwareHIncludeFragmentRendererTest.php | 2 +- .../Bundle/FrameworkBundle/composer.json | 2 +- .../Twig/Extension/LogoutUrlExtension.php | 8 +- .../Bundle/SecurityBundle/composer.json | 2 +- .../CacheWarmer/TemplateCacheCacheWarmer.php | 3 +- .../Controller/ExceptionController.php | 9 +- .../TwigBundle/Debug/TimedTwigEngine.php | 11 +- .../DependencyInjection/Configuration.php | 2 +- .../Configurator/EnvironmentConfigurator.php | 13 +- .../TwigBundle/Extension/ActionsExtension.php | 6 +- .../TwigBundle/Extension/AssetsExtension.php | 12 +- .../TwigBundle/Loader/FilesystemLoader.php | 10 +- .../Bundle/TwigBundle/Node/RenderNode.php | 15 +-- .../TwigBundle/Resources/config/twig.xml | 10 +- .../Controller/ExceptionControllerTest.php | 10 +- .../Compiler/ExtensionPassTest.php | 2 +- .../DependencyInjection/TwigExtensionTest.php | 4 +- .../Tests/Loader/FilesystemLoaderTest.php | 6 +- .../LegacyRenderTokenParserTest.php | 23 ++-- .../TokenParser/RenderTokenParser.php | 18 ++- src/Symfony/Bundle/TwigBundle/TwigEngine.php | 26 ++-- src/Symfony/Bundle/TwigBundle/composer.json | 2 +- .../Controller/ExceptionController.php | 9 +- .../Controller/ProfilerController.php | 5 +- .../Controller/RouterController.php | 3 +- .../EventListener/WebDebugToolbarListener.php | 3 +- .../Profiler/TemplateManager.php | 22 ++- .../Controller/ProfilerControllerTest.php | 6 +- .../WebProfilerExtensionTest.php | 6 +- .../WebDebugToolbarListenerTest.php | 2 +- .../Tests/Profiler/TemplateManagerTest.php | 13 +- .../Twig/WebProfilerExtension.php | 6 +- .../Bundle/WebProfilerBundle/composer.json | 2 +- .../DataCollector/DumpDataCollector.php | 3 +- .../Fragment/HIncludeFragmentRenderer.php | 21 +-- .../Component/HttpKernel/composer.json | 3 +- 98 files changed, 773 insertions(+), 576 deletions(-) diff --git a/composer.json b/composer.json index ecad4326d517c..1770bc4f305af 100644 --- a/composer.json +++ b/composer.json @@ -21,7 +21,7 @@ "paragonie/random_compat": "~1.0", "symfony/polyfill-apcu": "~1.1", "symfony/polyfill-mbstring": "~1.1", - "twig/twig": "~1.28|~2.0", + "twig/twig": "~1.34|~2.4", "psr/log": "~1.0" }, "replace": { diff --git a/src/Symfony/Bridge/Twig/Command/DebugCommand.php b/src/Symfony/Bridge/Twig/Command/DebugCommand.php index 7473221277c81..d62aef0f2c32a 100644 --- a/src/Symfony/Bridge/Twig/Command/DebugCommand.php +++ b/src/Symfony/Bridge/Twig/Command/DebugCommand.php @@ -16,6 +16,7 @@ use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; +use Twig\Environment; /** * Lists twig functions, filters, globals and tests present in the current project. @@ -34,18 +35,13 @@ public function __construct($name = 'debug:twig') parent::__construct($name); } - /** - * Sets the twig environment. - * - * @param \Twig_Environment $twig - */ - public function setTwigEnvironment(\Twig_Environment $twig) + public function setTwigEnvironment(Environment $twig) { $this->twig = $twig; } /** - * @return \Twig_Environment $twig + * @return Environment $twig */ protected function getTwigEnvironment() { diff --git a/src/Symfony/Bridge/Twig/Command/LintCommand.php b/src/Symfony/Bridge/Twig/Command/LintCommand.php index 83f4e1948c4c5..a731242ce5403 100644 --- a/src/Symfony/Bridge/Twig/Command/LintCommand.php +++ b/src/Symfony/Bridge/Twig/Command/LintCommand.php @@ -17,6 +17,10 @@ use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Finder\Finder; +use Twig\Environment; +use Twig\Error\Error; +use Twig\Loader\ArrayLoader; +use Twig\Source; /** * Command that will validate your template syntax and output encountered errors. @@ -36,18 +40,13 @@ public function __construct($name = 'lint:twig') parent::__construct($name); } - /** - * Sets the twig environment. - * - * @param \Twig_Environment $twig - */ - public function setTwigEnvironment(\Twig_Environment $twig) + public function setTwigEnvironment(Environment $twig) { $this->twig = $twig; } /** - * @return \Twig_Environment $twig + * @return Environment $twig */ protected function getTwigEnvironment() { @@ -117,7 +116,7 @@ protected function execute(InputInterface $input, OutputInterface $output) return $this->display($input, $output, $filesInfo); } - private function getFilesInfo(\Twig_Environment $twig, array $filenames) + private function getFilesInfo(Environment $twig, array $filenames) { $filesInfo = array(); foreach ($filenames as $filename) { @@ -140,16 +139,16 @@ protected function findFiles($filename) throw new \RuntimeException(sprintf('File or directory "%s" is not readable', $filename)); } - private function validate(\Twig_Environment $twig, $template, $file) + private function validate(Environment $twig, $template, $file) { $realLoader = $twig->getLoader(); try { - $temporaryLoader = new \Twig_Loader_Array(array((string) $file => $template)); + $temporaryLoader = new ArrayLoader(array((string) $file => $template)); $twig->setLoader($temporaryLoader); - $nodeTree = $twig->parse($twig->tokenize(new \Twig_Source($template, (string) $file))); + $nodeTree = $twig->parse($twig->tokenize(new Source($template, (string) $file))); $twig->compile($nodeTree); $twig->setLoader($realLoader); - } catch (\Twig_Error $e) { + } catch (Error $e) { $twig->setLoader($realLoader); return array('template' => $template, 'file' => $file, 'valid' => false, 'exception' => $e); @@ -207,7 +206,7 @@ private function displayJson(OutputInterface $output, $filesInfo) return min($errors, 1); } - private function renderException(OutputInterface $output, $template, \Twig_Error $exception, $file = null) + private function renderException(OutputInterface $output, $template, Error $exception, $file = null) { $line = $exception->getTemplateLine(); diff --git a/src/Symfony/Bridge/Twig/DataCollector/TwigDataCollector.php b/src/Symfony/Bridge/Twig/DataCollector/TwigDataCollector.php index 763a5ec4b31ee..fc2583bc7b234 100644 --- a/src/Symfony/Bridge/Twig/DataCollector/TwigDataCollector.php +++ b/src/Symfony/Bridge/Twig/DataCollector/TwigDataCollector.php @@ -15,6 +15,9 @@ use Symfony\Component\HttpKernel\DataCollector\LateDataCollectorInterface; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; +use Twig\Markup; +use Twig\Profiler\Dumper\HtmlDumper; +use Twig\Profiler\Profile; /** * TwigDataCollector. @@ -26,7 +29,7 @@ class TwigDataCollector extends DataCollector implements LateDataCollectorInterf private $profile; private $computed; - public function __construct(\Twig_Profiler_Profile $profile) + public function __construct(Profile $profile) { $this->profile = $profile; } @@ -73,9 +76,9 @@ public function getMacroCount() public function getHtmlCallGraph() { - $dumper = new \Twig_Profiler_Dumper_Html(); + $dumper = new HtmlDumper(); - return new \Twig_Markup($dumper->dump($this->getProfile()), 'UTF-8'); + return new Markup($dumper->dump($this->getProfile()), 'UTF-8'); } public function getProfile() @@ -96,7 +99,7 @@ private function getComputedData($index) return $this->computed[$index]; } - private function computeData(\Twig_Profiler_Profile $profile) + private function computeData(Profile $profile) { $data = array( 'template_count' => 0, diff --git a/src/Symfony/Bridge/Twig/Extension/AssetExtension.php b/src/Symfony/Bridge/Twig/Extension/AssetExtension.php index a72f4503dd869..40974686adda4 100644 --- a/src/Symfony/Bridge/Twig/Extension/AssetExtension.php +++ b/src/Symfony/Bridge/Twig/Extension/AssetExtension.php @@ -13,13 +13,15 @@ use Symfony\Component\Asset\Packages; use Symfony\Component\Asset\VersionStrategy\StaticVersionStrategy; +use Twig\Extension\AbstractExtension; +use Twig\TwigFunction; /** * Twig extension for the Symfony Asset component. * * @author Fabien Potencier */ -class AssetExtension extends \Twig_Extension +class AssetExtension extends AbstractExtension { private $packages; private $foundationExtension; @@ -40,9 +42,9 @@ public function __construct(Packages $packages, HttpFoundationExtension $foundat public function getFunctions() { return array( - new \Twig_SimpleFunction('asset', array($this, 'getAssetUrl')), - new \Twig_SimpleFunction('asset_version', array($this, 'getAssetVersion')), - new \Twig_SimpleFunction('assets_version', array($this, 'getAssetsVersion'), array('deprecated' => true, 'alternative' => 'asset_version')), + new TwigFunction('asset', array($this, 'getAssetUrl')), + new TwigFunction('asset_version', array($this, 'getAssetVersion')), + new TwigFunction('assets_version', array($this, 'getAssetsVersion'), array('deprecated' => true, 'alternative' => 'asset_version')), ); } diff --git a/src/Symfony/Bridge/Twig/Extension/CodeExtension.php b/src/Symfony/Bridge/Twig/Extension/CodeExtension.php index 4b25d62198341..eca1e52d77a70 100644 --- a/src/Symfony/Bridge/Twig/Extension/CodeExtension.php +++ b/src/Symfony/Bridge/Twig/Extension/CodeExtension.php @@ -11,12 +11,15 @@ namespace Symfony\Bridge\Twig\Extension; +use Twig\Extension\AbstractExtension; +use Twig\TwigFilter; + /** * Twig extension relate to PHP code and used by the profiler and the default exception templates. * * @author Fabien Potencier */ -class CodeExtension extends \Twig_Extension +class CodeExtension extends AbstractExtension { private $fileLinkFormat; private $rootDir; @@ -42,14 +45,14 @@ public function __construct($fileLinkFormat, $rootDir, $charset) public function getFilters() { return array( - new \Twig_SimpleFilter('abbr_class', array($this, 'abbrClass'), array('is_safe' => array('html'))), - new \Twig_SimpleFilter('abbr_method', array($this, 'abbrMethod'), array('is_safe' => array('html'))), - new \Twig_SimpleFilter('format_args', array($this, 'formatArgs'), array('is_safe' => array('html'))), - new \Twig_SimpleFilter('format_args_as_text', array($this, 'formatArgsAsText')), - new \Twig_SimpleFilter('file_excerpt', array($this, 'fileExcerpt'), array('is_safe' => array('html'))), - new \Twig_SimpleFilter('format_file', array($this, 'formatFile'), array('is_safe' => array('html'))), - new \Twig_SimpleFilter('format_file_from_text', array($this, 'formatFileFromText'), array('is_safe' => array('html'))), - new \Twig_SimpleFilter('file_link', array($this, 'getFileLink')), + new TwigFilter('abbr_class', array($this, 'abbrClass'), array('is_safe' => array('html'))), + new TwigFilter('abbr_method', array($this, 'abbrMethod'), array('is_safe' => array('html'))), + new TwigFilter('format_args', array($this, 'formatArgs'), array('is_safe' => array('html'))), + new TwigFilter('format_args_as_text', array($this, 'formatArgsAsText')), + new TwigFilter('file_excerpt', array($this, 'fileExcerpt'), array('is_safe' => array('html'))), + new TwigFilter('format_file', array($this, 'formatFile'), array('is_safe' => array('html'))), + new TwigFilter('format_file_from_text', array($this, 'formatFileFromText'), array('is_safe' => array('html'))), + new TwigFilter('file_link', array($this, 'getFileLink')), ); } diff --git a/src/Symfony/Bridge/Twig/Extension/DumpExtension.php b/src/Symfony/Bridge/Twig/Extension/DumpExtension.php index 5e43547ff1f40..eddd4d7f2afa0 100644 --- a/src/Symfony/Bridge/Twig/Extension/DumpExtension.php +++ b/src/Symfony/Bridge/Twig/Extension/DumpExtension.php @@ -14,13 +14,17 @@ use Symfony\Bridge\Twig\TokenParser\DumpTokenParser; use Symfony\Component\VarDumper\Cloner\ClonerInterface; use Symfony\Component\VarDumper\Dumper\HtmlDumper; +use Twig\Environment; +use Twig\Extension\AbstractExtension; +use Twig\Template; +use Twig\TwigFunction; /** * Provides integration of the dump() function with Twig. * * @author Nicolas Grekas */ -class DumpExtension extends \Twig_Extension +class DumpExtension extends AbstractExtension { private $cloner; @@ -32,7 +36,7 @@ public function __construct(ClonerInterface $cloner) public function getFunctions() { return array( - new \Twig_SimpleFunction('dump', array($this, 'dump'), array('is_safe' => array('html'), 'needs_context' => true, 'needs_environment' => true)), + new TwigFunction('dump', array($this, 'dump'), array('is_safe' => array('html'), 'needs_context' => true, 'needs_environment' => true)), ); } @@ -46,7 +50,7 @@ public function getName() return 'dump'; } - public function dump(\Twig_Environment $env, $context) + public function dump(Environment $env, $context) { if (!$env->isDebug()) { return; @@ -55,7 +59,7 @@ public function dump(\Twig_Environment $env, $context) if (2 === func_num_args()) { $vars = array(); foreach ($context as $key => $value) { - if (!$value instanceof \Twig_Template) { + if (!$value instanceof Template) { $vars[$key] = $value; } } diff --git a/src/Symfony/Bridge/Twig/Extension/ExpressionExtension.php b/src/Symfony/Bridge/Twig/Extension/ExpressionExtension.php index 6b30a279419b7..fc64fa3e3775d 100644 --- a/src/Symfony/Bridge/Twig/Extension/ExpressionExtension.php +++ b/src/Symfony/Bridge/Twig/Extension/ExpressionExtension.php @@ -12,13 +12,15 @@ namespace Symfony\Bridge\Twig\Extension; use Symfony\Component\ExpressionLanguage\Expression; +use Twig\Extension\AbstractExtension; +use Twig\TwigFunction; /** * ExpressionExtension gives a way to create Expressions from a template. * * @author Fabien Potencier */ -class ExpressionExtension extends \Twig_Extension +class ExpressionExtension extends AbstractExtension { /** * {@inheritdoc} @@ -26,7 +28,7 @@ class ExpressionExtension extends \Twig_Extension public function getFunctions() { return array( - new \Twig_SimpleFunction('expression', array($this, 'createExpression')), + new TwigFunction('expression', array($this, 'createExpression')), ); } diff --git a/src/Symfony/Bridge/Twig/Extension/FormExtension.php b/src/Symfony/Bridge/Twig/Extension/FormExtension.php index e833e3de2d228..053b1d4a6b336 100644 --- a/src/Symfony/Bridge/Twig/Extension/FormExtension.php +++ b/src/Symfony/Bridge/Twig/Extension/FormExtension.php @@ -14,6 +14,12 @@ use Symfony\Bridge\Twig\TokenParser\FormThemeTokenParser; use Symfony\Bridge\Twig\Form\TwigRendererInterface; use Symfony\Component\Form\Extension\Core\View\ChoiceView; +use Twig\Environment; +use Twig\Extension\AbstractExtension; +use Twig\Extension\InitRuntimeInterface; +use Twig\TwigFilter; +use Twig\TwigFunction; +use Twig\TwigTest; /** * FormExtension extends Twig with form capabilities. @@ -21,7 +27,7 @@ * @author Fabien Potencier * @author Bernhard Schussek */ -class FormExtension extends \Twig_Extension implements \Twig_Extension_InitRuntimeInterface +class FormExtension extends AbstractExtension implements InitRuntimeInterface { /** * This property is public so that it can be accessed directly from compiled @@ -39,7 +45,7 @@ public function __construct(TwigRendererInterface $renderer) /** * {@inheritdoc} */ - public function initRuntime(\Twig_Environment $environment) + public function initRuntime(Environment $environment) { $this->renderer->setEnvironment($environment); } @@ -61,16 +67,16 @@ public function getTokenParsers() public function getFunctions() { return array( - new \Twig_SimpleFunction('form_enctype', null, array('node_class' => 'Symfony\Bridge\Twig\Node\FormEnctypeNode', 'is_safe' => array('html'), 'deprecated' => true, 'alternative' => 'form_start')), - new \Twig_SimpleFunction('form_widget', null, array('node_class' => 'Symfony\Bridge\Twig\Node\SearchAndRenderBlockNode', 'is_safe' => array('html'))), - new \Twig_SimpleFunction('form_errors', null, array('node_class' => 'Symfony\Bridge\Twig\Node\SearchAndRenderBlockNode', 'is_safe' => array('html'))), - new \Twig_SimpleFunction('form_label', null, array('node_class' => 'Symfony\Bridge\Twig\Node\SearchAndRenderBlockNode', 'is_safe' => array('html'))), - new \Twig_SimpleFunction('form_row', null, array('node_class' => 'Symfony\Bridge\Twig\Node\SearchAndRenderBlockNode', 'is_safe' => array('html'))), - new \Twig_SimpleFunction('form_rest', null, array('node_class' => 'Symfony\Bridge\Twig\Node\SearchAndRenderBlockNode', 'is_safe' => array('html'))), - new \Twig_SimpleFunction('form', null, array('node_class' => 'Symfony\Bridge\Twig\Node\RenderBlockNode', 'is_safe' => array('html'))), - new \Twig_SimpleFunction('form_start', null, array('node_class' => 'Symfony\Bridge\Twig\Node\RenderBlockNode', 'is_safe' => array('html'))), - new \Twig_SimpleFunction('form_end', null, array('node_class' => 'Symfony\Bridge\Twig\Node\RenderBlockNode', 'is_safe' => array('html'))), - new \Twig_SimpleFunction('csrf_token', array($this, 'renderCsrfToken')), + new TwigFunction('form_enctype', null, array('node_class' => 'Symfony\Bridge\Twig\Node\FormEnctypeNode', 'is_safe' => array('html'), 'deprecated' => true, 'alternative' => 'form_start')), + new TwigFunction('form_widget', null, array('node_class' => 'Symfony\Bridge\Twig\Node\SearchAndRenderBlockNode', 'is_safe' => array('html'))), + new TwigFunction('form_errors', null, array('node_class' => 'Symfony\Bridge\Twig\Node\SearchAndRenderBlockNode', 'is_safe' => array('html'))), + new TwigFunction('form_label', null, array('node_class' => 'Symfony\Bridge\Twig\Node\SearchAndRenderBlockNode', 'is_safe' => array('html'))), + new TwigFunction('form_row', null, array('node_class' => 'Symfony\Bridge\Twig\Node\SearchAndRenderBlockNode', 'is_safe' => array('html'))), + new TwigFunction('form_rest', null, array('node_class' => 'Symfony\Bridge\Twig\Node\SearchAndRenderBlockNode', 'is_safe' => array('html'))), + new TwigFunction('form', null, array('node_class' => 'Symfony\Bridge\Twig\Node\RenderBlockNode', 'is_safe' => array('html'))), + new TwigFunction('form_start', null, array('node_class' => 'Symfony\Bridge\Twig\Node\RenderBlockNode', 'is_safe' => array('html'))), + new TwigFunction('form_end', null, array('node_class' => 'Symfony\Bridge\Twig\Node\RenderBlockNode', 'is_safe' => array('html'))), + new TwigFunction('csrf_token', array($this, 'renderCsrfToken')), ); } @@ -80,7 +86,7 @@ public function getFunctions() public function getFilters() { return array( - new \Twig_SimpleFilter('humanize', array($this, 'humanize')), + new TwigFilter('humanize', array($this, 'humanize')), ); } @@ -90,7 +96,7 @@ public function getFilters() public function getTests() { return array( - new \Twig_SimpleTest('selectedchoice', array($this, 'isSelectedChoice')), + new TwigTest('selectedchoice', array($this, 'isSelectedChoice')), ); } diff --git a/src/Symfony/Bridge/Twig/Extension/HttpFoundationExtension.php b/src/Symfony/Bridge/Twig/Extension/HttpFoundationExtension.php index 69d6d326f4d08..90b515ee320ba 100644 --- a/src/Symfony/Bridge/Twig/Extension/HttpFoundationExtension.php +++ b/src/Symfony/Bridge/Twig/Extension/HttpFoundationExtension.php @@ -14,13 +14,15 @@ use Symfony\Component\HttpFoundation\RequestStack; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\Routing\RequestContext; +use Twig\Extension\AbstractExtension; +use Twig\TwigFunction; /** * Twig extension for the Symfony HttpFoundation component. * * @author Fabien Potencier */ -class HttpFoundationExtension extends \Twig_Extension +class HttpFoundationExtension extends AbstractExtension { private $requestStack; private $requestContext; @@ -37,8 +39,8 @@ public function __construct(RequestStack $requestStack, RequestContext $requestC public function getFunctions() { return array( - new \Twig_SimpleFunction('absolute_url', array($this, 'generateAbsoluteUrl')), - new \Twig_SimpleFunction('relative_path', array($this, 'generateRelativePath')), + new TwigFunction('absolute_url', array($this, 'generateAbsoluteUrl')), + new TwigFunction('relative_path', array($this, 'generateRelativePath')), ); } diff --git a/src/Symfony/Bridge/Twig/Extension/HttpKernelExtension.php b/src/Symfony/Bridge/Twig/Extension/HttpKernelExtension.php index 1da12aaf5eb10..07e913059754c 100644 --- a/src/Symfony/Bridge/Twig/Extension/HttpKernelExtension.php +++ b/src/Symfony/Bridge/Twig/Extension/HttpKernelExtension.php @@ -13,13 +13,15 @@ use Symfony\Component\HttpKernel\Fragment\FragmentHandler; use Symfony\Component\HttpKernel\Controller\ControllerReference; +use Twig\Extension\AbstractExtension; +use Twig\TwigFunction; /** * Provides integration with the HttpKernel component. * * @author Fabien Potencier */ -class HttpKernelExtension extends \Twig_Extension +class HttpKernelExtension extends AbstractExtension { private $handler; @@ -36,9 +38,9 @@ public function __construct(FragmentHandler $handler) public function getFunctions() { return array( - new \Twig_SimpleFunction('render', array($this, 'renderFragment'), array('is_safe' => array('html'))), - new \Twig_SimpleFunction('render_*', array($this, 'renderFragmentStrategy'), array('is_safe' => array('html'))), - new \Twig_SimpleFunction('controller', array($this, 'controller')), + new TwigFunction('render', array($this, 'renderFragment'), array('is_safe' => array('html'))), + new TwigFunction('render_*', array($this, 'renderFragmentStrategy'), array('is_safe' => array('html'))), + new TwigFunction('controller', array($this, 'controller')), ); } diff --git a/src/Symfony/Bridge/Twig/Extension/LogoutUrlExtension.php b/src/Symfony/Bridge/Twig/Extension/LogoutUrlExtension.php index ea105e8d955e4..17abb779899ac 100644 --- a/src/Symfony/Bridge/Twig/Extension/LogoutUrlExtension.php +++ b/src/Symfony/Bridge/Twig/Extension/LogoutUrlExtension.php @@ -12,13 +12,15 @@ namespace Symfony\Bridge\Twig\Extension; use Symfony\Component\Security\Http\Logout\LogoutUrlGenerator; +use Twig\Extension\AbstractExtension; +use Twig\TwigFunction; /** * LogoutUrlHelper provides generator functions for the logout URL to Twig. * * @author Jeremy Mikola */ -class LogoutUrlExtension extends \Twig_Extension +class LogoutUrlExtension extends AbstractExtension { private $generator; @@ -33,8 +35,8 @@ public function __construct(LogoutUrlGenerator $generator) public function getFunctions() { return array( - new \Twig_SimpleFunction('logout_url', array($this, 'getLogoutUrl')), - new \Twig_SimpleFunction('logout_path', array($this, 'getLogoutPath')), + new TwigFunction('logout_url', array($this, 'getLogoutUrl')), + new TwigFunction('logout_path', array($this, 'getLogoutPath')), ); } diff --git a/src/Symfony/Bridge/Twig/Extension/ProfilerExtension.php b/src/Symfony/Bridge/Twig/Extension/ProfilerExtension.php index 648a6c8036d75..21214f81196ad 100644 --- a/src/Symfony/Bridge/Twig/Extension/ProfilerExtension.php +++ b/src/Symfony/Bridge/Twig/Extension/ProfilerExtension.php @@ -12,16 +12,18 @@ namespace Symfony\Bridge\Twig\Extension; use Symfony\Component\Stopwatch\Stopwatch; +use Twig\Extension\ProfilerExtension as BaseProfilerExtension; +use Twig\Profiler\Profile; /** * @author Fabien Potencier */ -class ProfilerExtension extends \Twig_Extension_Profiler +class ProfilerExtension extends BaseProfilerExtension { private $stopwatch; private $events; - public function __construct(\Twig_Profiler_Profile $profile, Stopwatch $stopwatch = null) + public function __construct(Profile $profile, Stopwatch $stopwatch = null) { parent::__construct($profile); @@ -29,7 +31,7 @@ public function __construct(\Twig_Profiler_Profile $profile, Stopwatch $stopwatc $this->events = new \SplObjectStorage(); } - public function enter(\Twig_Profiler_Profile $profile) + public function enter(Profile $profile) { if ($this->stopwatch && $profile->isTemplate()) { $this->events[$profile] = $this->stopwatch->start($profile->getName(), 'template'); @@ -38,7 +40,7 @@ public function enter(\Twig_Profiler_Profile $profile) parent::enter($profile); } - public function leave(\Twig_Profiler_Profile $profile) + public function leave(Profile $profile) { parent::leave($profile); diff --git a/src/Symfony/Bridge/Twig/Extension/RoutingExtension.php b/src/Symfony/Bridge/Twig/Extension/RoutingExtension.php index 81cef949c7408..97b1ea31360ce 100644 --- a/src/Symfony/Bridge/Twig/Extension/RoutingExtension.php +++ b/src/Symfony/Bridge/Twig/Extension/RoutingExtension.php @@ -12,13 +12,18 @@ namespace Symfony\Bridge\Twig\Extension; use Symfony\Component\Routing\Generator\UrlGeneratorInterface; +use Twig\Extension\AbstractExtension; +use Twig\Node\Expression\ArrayExpression; +use Twig\Node\Expression\ConstantExpression; +use Twig\Node\Node; +use Twig\TwigFunction; /** * Provides integration of the Routing component with Twig. * * @author Fabien Potencier */ -class RoutingExtension extends \Twig_Extension +class RoutingExtension extends AbstractExtension { private $generator; @@ -35,8 +40,8 @@ public function __construct(UrlGeneratorInterface $generator) public function getFunctions() { return array( - new \Twig_SimpleFunction('url', array($this, 'getUrl'), array('is_safe_callback' => array($this, 'isUrlGenerationSafe'))), - new \Twig_SimpleFunction('path', array($this, 'getPath'), array('is_safe_callback' => array($this, 'isUrlGenerationSafe'))), + new TwigFunction('url', array($this, 'getUrl'), array('is_safe_callback' => array($this, 'isUrlGenerationSafe'))), + new TwigFunction('path', array($this, 'getPath'), array('is_safe_callback' => array($this, 'isUrlGenerationSafe'))), ); } @@ -82,9 +87,11 @@ public function getUrl($name, $parameters = array(), $schemeRelative = false) * - path('route', {'param1': 'value1', 'param2': 'value2'}) * If param1 and param2 reference placeholder in the route, it would still be safe. But we don't know. * - * @param \Twig_Node $argsNode The arguments of the path/url function + * @param Node $argsNode The arguments of the path/url function * * @return array An array with the contexts the URL is safe + * + * To be made @final in 3.4, and the type-hint be changed to "\Twig\Node\Node" in 4.0. */ public function isUrlGenerationSafe(\Twig_Node $argsNode) { @@ -93,8 +100,8 @@ public function isUrlGenerationSafe(\Twig_Node $argsNode) $argsNode->hasNode(1) ? $argsNode->getNode(1) : null ); - if (null === $paramsNode || $paramsNode instanceof \Twig_Node_Expression_Array && count($paramsNode) <= 2 && - (!$paramsNode->hasNode(1) || $paramsNode->getNode(1) instanceof \Twig_Node_Expression_Constant) + if (null === $paramsNode || $paramsNode instanceof ArrayExpression && count($paramsNode) <= 2 && + (!$paramsNode->hasNode(1) || $paramsNode->getNode(1) instanceof ConstantExpression) ) { return array('html'); } diff --git a/src/Symfony/Bridge/Twig/Extension/SecurityExtension.php b/src/Symfony/Bridge/Twig/Extension/SecurityExtension.php index b13d7c0f85338..ffa8293eec2b0 100644 --- a/src/Symfony/Bridge/Twig/Extension/SecurityExtension.php +++ b/src/Symfony/Bridge/Twig/Extension/SecurityExtension.php @@ -13,13 +13,15 @@ use Symfony\Component\Security\Acl\Voter\FieldVote; use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface; +use Twig\Extension\AbstractExtension; +use Twig\TwigFunction; /** * SecurityExtension exposes security context features. * * @author Fabien Potencier */ -class SecurityExtension extends \Twig_Extension +class SecurityExtension extends AbstractExtension { private $securityChecker; @@ -47,7 +49,7 @@ public function isGranted($role, $object = null, $field = null) public function getFunctions() { return array( - new \Twig_SimpleFunction('is_granted', array($this, 'isGranted')), + new TwigFunction('is_granted', array($this, 'isGranted')), ); } diff --git a/src/Symfony/Bridge/Twig/Extension/StopwatchExtension.php b/src/Symfony/Bridge/Twig/Extension/StopwatchExtension.php index 52af92324c228..635188b7389e4 100644 --- a/src/Symfony/Bridge/Twig/Extension/StopwatchExtension.php +++ b/src/Symfony/Bridge/Twig/Extension/StopwatchExtension.php @@ -13,13 +13,14 @@ use Symfony\Component\Stopwatch\Stopwatch; use Symfony\Bridge\Twig\TokenParser\StopwatchTokenParser; +use Twig\Extension\AbstractExtension; /** * Twig extension for the stopwatch helper. * * @author Wouter J */ -class StopwatchExtension extends \Twig_Extension +class StopwatchExtension extends AbstractExtension { private $stopwatch; diff --git a/src/Symfony/Bridge/Twig/Extension/TranslationExtension.php b/src/Symfony/Bridge/Twig/Extension/TranslationExtension.php index f1f2fbd20b82e..5155169a8173d 100644 --- a/src/Symfony/Bridge/Twig/Extension/TranslationExtension.php +++ b/src/Symfony/Bridge/Twig/Extension/TranslationExtension.php @@ -17,18 +17,22 @@ use Symfony\Component\Translation\TranslatorInterface; use Symfony\Bridge\Twig\NodeVisitor\TranslationNodeVisitor; use Symfony\Bridge\Twig\NodeVisitor\TranslationDefaultDomainNodeVisitor; +use Twig\Extension\AbstractExtension; +use Twig\NodeVisitor\NodeVisitorInterface; +use Twig\TokenParser\AbstractTokenParser; +use Twig\TwigFilter; /** * Provides integration of the Translation component with Twig. * * @author Fabien Potencier */ -class TranslationExtension extends \Twig_Extension +class TranslationExtension extends AbstractExtension { private $translator; private $translationNodeVisitor; - public function __construct(TranslatorInterface $translator, \Twig_NodeVisitorInterface $translationNodeVisitor = null) + public function __construct(TranslatorInterface $translator, NodeVisitorInterface $translationNodeVisitor = null) { if (!$translationNodeVisitor) { $translationNodeVisitor = new TranslationNodeVisitor(); @@ -49,15 +53,15 @@ public function getTranslator() public function getFilters() { return array( - new \Twig_SimpleFilter('trans', array($this, 'trans')), - new \Twig_SimpleFilter('transchoice', array($this, 'transchoice')), + new TwigFilter('trans', array($this, 'trans')), + new TwigFilter('transchoice', array($this, 'transchoice')), ); } /** * Returns the token parser instance to add to the existing list. * - * @return array An array of Twig_TokenParser instances + * @return AbstractTokenParser[] */ public function getTokenParsers() { diff --git a/src/Symfony/Bridge/Twig/Extension/YamlExtension.php b/src/Symfony/Bridge/Twig/Extension/YamlExtension.php index 2d46795b4a81e..894a2fd189014 100644 --- a/src/Symfony/Bridge/Twig/Extension/YamlExtension.php +++ b/src/Symfony/Bridge/Twig/Extension/YamlExtension.php @@ -13,13 +13,15 @@ use Symfony\Component\Yaml\Dumper as YamlDumper; use Symfony\Component\Yaml\Yaml; +use Twig\Extension\AbstractExtension; +use Twig\TwigFilter; /** * Provides integration of the Yaml component with Twig. * * @author Fabien Potencier */ -class YamlExtension extends \Twig_Extension +class YamlExtension extends AbstractExtension { /** * {@inheritdoc} @@ -27,8 +29,8 @@ class YamlExtension extends \Twig_Extension public function getFilters() { return array( - new \Twig_SimpleFilter('yaml_encode', array($this, 'encode')), - new \Twig_SimpleFilter('yaml_dump', array($this, 'dump')), + new TwigFilter('yaml_encode', array($this, 'encode')), + new TwigFilter('yaml_dump', array($this, 'dump')), ); } diff --git a/src/Symfony/Bridge/Twig/Form/TwigRenderer.php b/src/Symfony/Bridge/Twig/Form/TwigRenderer.php index ac139e44a1331..2485c0a88c530 100644 --- a/src/Symfony/Bridge/Twig/Form/TwigRenderer.php +++ b/src/Symfony/Bridge/Twig/Form/TwigRenderer.php @@ -12,6 +12,7 @@ namespace Symfony\Bridge\Twig\Form; use Symfony\Component\Form\FormRenderer; +use Twig\Environment; /** * @author Bernhard Schussek @@ -33,7 +34,7 @@ public function __construct(TwigRendererEngineInterface $engine, $csrfTokenManag /** * {@inheritdoc} */ - public function setEnvironment(\Twig_Environment $environment) + public function setEnvironment(Environment $environment) { $this->engine->setEnvironment($environment); } diff --git a/src/Symfony/Bridge/Twig/Form/TwigRendererEngine.php b/src/Symfony/Bridge/Twig/Form/TwigRendererEngine.php index 5248d5fd370ea..d83124e721366 100644 --- a/src/Symfony/Bridge/Twig/Form/TwigRendererEngine.php +++ b/src/Symfony/Bridge/Twig/Form/TwigRendererEngine.php @@ -13,6 +13,8 @@ use Symfony\Component\Form\AbstractRendererEngine; use Symfony\Component\Form\FormView; +use Twig\Environment; +use Twig\Template; /** * @author Bernhard Schussek @@ -20,19 +22,19 @@ class TwigRendererEngine extends AbstractRendererEngine implements TwigRendererEngineInterface { /** - * @var \Twig_Environment + * @var Environment */ private $environment; /** - * @var \Twig_Template + * @var Template */ private $template; /** * {@inheritdoc} */ - public function setEnvironment(\Twig_Environment $environment) + public function setEnvironment(Environment $environment) { $this->environment = $environment; } @@ -150,13 +152,13 @@ protected function loadResourceForBlockName($cacheKey, FormView $view, $blockNam */ protected function loadResourcesFromTheme($cacheKey, &$theme) { - if (!$theme instanceof \Twig_Template) { - /* @var \Twig_Template $theme */ + if (!$theme instanceof Template) { + /* @var Template $theme */ $theme = $this->environment->loadTemplate($theme); } if (null === $this->template) { - // Store the first \Twig_Template instance that we find so that + // Store the first Template instance that we find so that // we can call displayBlock() later on. It doesn't matter *which* // template we use for that, since we pass the used blocks manually // anyway. diff --git a/src/Symfony/Bridge/Twig/Form/TwigRendererEngineInterface.php b/src/Symfony/Bridge/Twig/Form/TwigRendererEngineInterface.php index ef764a248f339..3e8a8e1f4678d 100644 --- a/src/Symfony/Bridge/Twig/Form/TwigRendererEngineInterface.php +++ b/src/Symfony/Bridge/Twig/Form/TwigRendererEngineInterface.php @@ -12,16 +12,15 @@ namespace Symfony\Bridge\Twig\Form; use Symfony\Component\Form\FormRendererEngineInterface; +use Twig\Environment; + +// BC/FC with namespaced Twig +class_exists('Twig\Environment'); /** * @author Bernhard Schussek */ interface TwigRendererEngineInterface extends FormRendererEngineInterface { - /** - * Sets Twig's environment. - * - * @param \Twig_Environment $environment - */ - public function setEnvironment(\Twig_Environment $environment); + public function setEnvironment(Environment $environment); } diff --git a/src/Symfony/Bridge/Twig/Form/TwigRendererInterface.php b/src/Symfony/Bridge/Twig/Form/TwigRendererInterface.php index 4682f520008ac..cb45c17e1afc2 100644 --- a/src/Symfony/Bridge/Twig/Form/TwigRendererInterface.php +++ b/src/Symfony/Bridge/Twig/Form/TwigRendererInterface.php @@ -12,16 +12,15 @@ namespace Symfony\Bridge\Twig\Form; use Symfony\Component\Form\FormRendererInterface; +use Twig\Environment; + +// BC/FC with namespaced Twig +class_exists('Twig\Environment'); /** * @author Bernhard Schussek */ interface TwigRendererInterface extends FormRendererInterface { - /** - * Sets Twig's environment. - * - * @param \Twig_Environment $environment - */ - public function setEnvironment(\Twig_Environment $environment); + public function setEnvironment(Environment $environment); } diff --git a/src/Symfony/Bridge/Twig/Node/DumpNode.php b/src/Symfony/Bridge/Twig/Node/DumpNode.php index a66781e36550a..d820d75cc7db9 100644 --- a/src/Symfony/Bridge/Twig/Node/DumpNode.php +++ b/src/Symfony/Bridge/Twig/Node/DumpNode.php @@ -11,14 +11,17 @@ namespace Symfony\Bridge\Twig\Node; +use Twig\Compiler; +use Twig\Node\Node; + /** * @author Julien Galenski */ -class DumpNode extends \Twig_Node +class DumpNode extends Node { private $varPrefix; - public function __construct($varPrefix, \Twig_Node $values = null, $lineno, $tag = null) + public function __construct($varPrefix, Node $values = null, $lineno, $tag = null) { $nodes = array(); if (null !== $values) { @@ -32,7 +35,7 @@ public function __construct($varPrefix, \Twig_Node $values = null, $lineno, $tag /** * {@inheritdoc} */ - public function compile(\Twig_Compiler $compiler) + public function compile(Compiler $compiler) { $compiler ->write("if (\$this->env->isDebug()) {\n") @@ -44,7 +47,7 @@ public function compile(\Twig_Compiler $compiler) ->write(sprintf('$%svars = array();'."\n", $this->varPrefix)) ->write(sprintf('foreach ($context as $%1$skey => $%1$sval) {'."\n", $this->varPrefix)) ->indent() - ->write(sprintf('if (!$%sval instanceof \Twig_Template) {'."\n", $this->varPrefix)) + ->write(sprintf('if (!$%sval instanceof \Twig\Template) {'."\n", $this->varPrefix)) ->indent() ->write(sprintf('$%1$svars[$%1$skey] = $%1$sval;'."\n", $this->varPrefix)) ->outdent() diff --git a/src/Symfony/Bridge/Twig/Node/FormThemeNode.php b/src/Symfony/Bridge/Twig/Node/FormThemeNode.php index 91793771393d8..b2eb100d5bfdc 100644 --- a/src/Symfony/Bridge/Twig/Node/FormThemeNode.php +++ b/src/Symfony/Bridge/Twig/Node/FormThemeNode.php @@ -11,22 +11,20 @@ namespace Symfony\Bridge\Twig\Node; +use Twig\Compiler; +use Twig\Node\Node; + /** * @author Fabien Potencier */ -class FormThemeNode extends \Twig_Node +class FormThemeNode extends Node { - public function __construct(\Twig_Node $form, \Twig_Node $resources, $lineno, $tag = null) + public function __construct(Node $form, Node $resources, $lineno, $tag = null) { parent::__construct(array('form' => $form, 'resources' => $resources), array(), $lineno, $tag); } - /** - * Compiles the node to PHP. - * - * @param \Twig_Compiler $compiler A Twig_Compiler instance - */ - public function compile(\Twig_Compiler $compiler) + public function compile(Compiler $compiler) { $compiler ->addDebugInfo($this) diff --git a/src/Symfony/Bridge/Twig/Node/RenderBlockNode.php b/src/Symfony/Bridge/Twig/Node/RenderBlockNode.php index 33865e2f1cb78..4a06907b0b43a 100644 --- a/src/Symfony/Bridge/Twig/Node/RenderBlockNode.php +++ b/src/Symfony/Bridge/Twig/Node/RenderBlockNode.php @@ -11,6 +11,9 @@ namespace Symfony\Bridge\Twig\Node; +use Twig\Compiler; +use Twig\Node\Expression\FunctionExpression; + /** * Compiles a call to {@link \Symfony\Component\Form\FormRendererInterface::renderBlock()}. * @@ -19,9 +22,9 @@ * * @author Bernhard Schussek */ -class RenderBlockNode extends \Twig_Node_Expression_Function +class RenderBlockNode extends FunctionExpression { - public function compile(\Twig_Compiler $compiler) + public function compile(Compiler $compiler) { $compiler->addDebugInfo($this); $arguments = iterator_to_array($this->getNode('arguments')); diff --git a/src/Symfony/Bridge/Twig/Node/SearchAndRenderBlockNode.php b/src/Symfony/Bridge/Twig/Node/SearchAndRenderBlockNode.php index 9cb964865ea19..7c95199953b2f 100644 --- a/src/Symfony/Bridge/Twig/Node/SearchAndRenderBlockNode.php +++ b/src/Symfony/Bridge/Twig/Node/SearchAndRenderBlockNode.php @@ -11,12 +11,17 @@ namespace Symfony\Bridge\Twig\Node; +use Twig\Compiler; +use Twig\Node\Expression\ArrayExpression; +use Twig\Node\Expression\ConstantExpression; +use Twig\Node\Expression\FunctionExpression; + /** * @author Bernhard Schussek */ -class SearchAndRenderBlockNode extends \Twig_Node_Expression_Function +class SearchAndRenderBlockNode extends FunctionExpression { - public function compile(\Twig_Compiler $compiler) + public function compile(Compiler $compiler) { $compiler->addDebugInfo($this); $compiler->raw('$this->env->getExtension(\'Symfony\Bridge\Twig\Extension\FormExtension\')->renderer->searchAndRenderBlock('); @@ -39,7 +44,7 @@ public function compile(\Twig_Compiler $compiler) $variables = isset($arguments[2]) ? $arguments[2] : null; $lineno = $label->getTemplateLine(); - if ($label instanceof \Twig_Node_Expression_Constant) { + if ($label instanceof ConstantExpression) { // If the label argument is given as a constant, we can either // strip it away if it is empty, or integrate it into the array // of variables at compile time. @@ -48,8 +53,8 @@ public function compile(\Twig_Compiler $compiler) // Only insert the label into the array if it is not empty if (!twig_test_empty($label->getAttribute('value'))) { $originalVariables = $variables; - $variables = new \Twig_Node_Expression_Array(array(), $lineno); - $labelKey = new \Twig_Node_Expression_Constant('label', $lineno); + $variables = new ArrayExpression(array(), $lineno); + $labelKey = new ConstantExpression('label', $lineno); if (null !== $originalVariables) { foreach ($originalVariables->getKeyValuePairs() as $pair) { diff --git a/src/Symfony/Bridge/Twig/Node/StopwatchNode.php b/src/Symfony/Bridge/Twig/Node/StopwatchNode.php index 95d755a78cdb0..fac770c2499ba 100644 --- a/src/Symfony/Bridge/Twig/Node/StopwatchNode.php +++ b/src/Symfony/Bridge/Twig/Node/StopwatchNode.php @@ -11,19 +11,23 @@ namespace Symfony\Bridge\Twig\Node; +use Twig\Compiler; +use Twig\Node\Expression\AssignNameExpression; +use Twig\Node\Node; + /** * Represents a stopwatch node. * * @author Wouter J */ -class StopwatchNode extends \Twig_Node +class StopwatchNode extends Node { - public function __construct(\Twig_Node $name, \Twig_Node $body, \Twig_Node_Expression_AssignName $var, $lineno = 0, $tag = null) + public function __construct(Node $name, Node $body, AssignNameExpression $var, $lineno = 0, $tag = null) { parent::__construct(array('body' => $body, 'name' => $name, 'var' => $var), array(), $lineno, $tag); } - public function compile(\Twig_Compiler $compiler) + public function compile(Compiler $compiler) { $compiler ->addDebugInfo($this) diff --git a/src/Symfony/Bridge/Twig/Node/TransDefaultDomainNode.php b/src/Symfony/Bridge/Twig/Node/TransDefaultDomainNode.php index adee71ffc5dc4..c9c82b33e541c 100644 --- a/src/Symfony/Bridge/Twig/Node/TransDefaultDomainNode.php +++ b/src/Symfony/Bridge/Twig/Node/TransDefaultDomainNode.php @@ -11,22 +11,21 @@ namespace Symfony\Bridge\Twig\Node; +use Twig\Compiler; +use Twig\Node\Expression\AbstractExpression; +use Twig\Node\Node; + /** * @author Fabien Potencier */ -class TransDefaultDomainNode extends \Twig_Node +class TransDefaultDomainNode extends Node { - public function __construct(\Twig_Node_Expression $expr, $lineno = 0, $tag = null) + public function __construct(AbstractExpression $expr, $lineno = 0, $tag = null) { parent::__construct(array('expr' => $expr), array(), $lineno, $tag); } - /** - * Compiles the node to PHP. - * - * @param \Twig_Compiler $compiler A Twig_Compiler instance - */ - public function compile(\Twig_Compiler $compiler) + public function compile(Compiler $compiler) { // noop as this node is just a marker for TranslationDefaultDomainNodeVisitor } diff --git a/src/Symfony/Bridge/Twig/Node/TransNode.php b/src/Symfony/Bridge/Twig/Node/TransNode.php index 7b2f9c090405f..020810f7b7c55 100644 --- a/src/Symfony/Bridge/Twig/Node/TransNode.php +++ b/src/Symfony/Bridge/Twig/Node/TransNode.php @@ -11,12 +11,23 @@ namespace Symfony\Bridge\Twig\Node; +use Twig\Compiler; +use Twig\Node\Expression\AbstractExpression; +use Twig\Node\Expression\ArrayExpression; +use Twig\Node\Expression\ConstantExpression; +use Twig\Node\Expression\NameExpression; +use Twig\Node\Node; +use Twig\Node\TextNode; + +// BC/FC with namespaced Twig +class_exists('Twig\Node\Expression\ArrayExpression'); + /** * @author Fabien Potencier */ -class TransNode extends \Twig_Node +class TransNode extends Node { - public function __construct(\Twig_Node $body, \Twig_Node $domain = null, \Twig_Node_Expression $count = null, \Twig_Node_Expression $vars = null, \Twig_Node_Expression $locale = null, $lineno = 0, $tag = null) + public function __construct(Node $body, Node $domain = null, AbstractExpression $count = null, AbstractExpression $vars = null, AbstractExpression $locale = null, $lineno = 0, $tag = null) { $nodes = array('body' => $body); if (null !== $domain) { @@ -35,17 +46,12 @@ public function __construct(\Twig_Node $body, \Twig_Node $domain = null, \Twig_N parent::__construct($nodes, array(), $lineno, $tag); } - /** - * Compiles the node to PHP. - * - * @param \Twig_Compiler $compiler A Twig_Compiler instance - */ - public function compile(\Twig_Compiler $compiler) + public function compile(Compiler $compiler) { $compiler->addDebugInfo($this); - $defaults = new \Twig_Node_Expression_Array(array(), -1); - if ($this->hasNode('vars') && ($vars = $this->getNode('vars')) instanceof \Twig_Node_Expression_Array) { + $defaults = new ArrayExpression(array(), -1); + if ($this->hasNode('vars') && ($vars = $this->getNode('vars')) instanceof ArrayExpression) { $defaults = $this->getNode('vars'); $vars = null; } @@ -96,11 +102,11 @@ public function compile(\Twig_Compiler $compiler) $compiler->raw(");\n"); } - protected function compileString(\Twig_Node $body, \Twig_Node_Expression_Array $vars, $ignoreStrictCheck = false) + protected function compileString(Node $body, ArrayExpression $vars, $ignoreStrictCheck = false) { - if ($body instanceof \Twig_Node_Expression_Constant) { + if ($body instanceof ConstantExpression) { $msg = $body->getAttribute('value'); - } elseif ($body instanceof \Twig_Node_Text) { + } elseif ($body instanceof TextNode) { $msg = $body->getAttribute('data'); } else { return array($body, $vars); @@ -109,18 +115,18 @@ protected function compileString(\Twig_Node $body, \Twig_Node_Expression_Array $ preg_match_all('/(?getTemplateLine()); + $key = new ConstantExpression('%'.$var.'%', $body->getTemplateLine()); if (!$vars->hasElement($key)) { if ('count' === $var && $this->hasNode('count')) { $vars->addElement($this->getNode('count'), $key); } else { - $varExpr = new \Twig_Node_Expression_Name($var, $body->getTemplateLine()); + $varExpr = new NameExpression($var, $body->getTemplateLine()); $varExpr->setAttribute('ignore_strict_check', $ignoreStrictCheck); $vars->addElement($varExpr, $key); } } } - return array(new \Twig_Node_Expression_Constant(str_replace('%%', '%', trim($msg)), $body->getTemplateLine()), $vars); + return array(new ConstantExpression(str_replace('%%', '%', trim($msg)), $body->getTemplateLine()), $vars); } } diff --git a/src/Symfony/Bridge/Twig/NodeVisitor/TranslationDefaultDomainNodeVisitor.php b/src/Symfony/Bridge/Twig/NodeVisitor/TranslationDefaultDomainNodeVisitor.php index e64d6eae2347d..c69ca843e83ea 100644 --- a/src/Symfony/Bridge/Twig/NodeVisitor/TranslationDefaultDomainNodeVisitor.php +++ b/src/Symfony/Bridge/Twig/NodeVisitor/TranslationDefaultDomainNodeVisitor.php @@ -13,13 +13,22 @@ use Symfony\Bridge\Twig\Node\TransNode; use Symfony\Bridge\Twig\Node\TransDefaultDomainNode; +use Twig\Environment; +use Twig\Node\Expression\ArrayExpression; +use Twig\Node\Expression\AssignNameExpression; +use Twig\Node\Expression\ConstantExpression; +use Twig\Node\Expression\FilterExpression; +use Twig\Node\Expression\NameExpression; +use Twig\Node\ModuleNode; +use Twig\Node\Node; +use Twig\NodeVisitor\AbstractNodeVisitor; /** * TranslationDefaultDomainNodeVisitor. * * @author Fabien Potencier */ -class TranslationDefaultDomainNodeVisitor extends \Twig_BaseNodeVisitor +class TranslationDefaultDomainNodeVisitor extends AbstractNodeVisitor { /** * @var Scope @@ -37,23 +46,23 @@ public function __construct() /** * {@inheritdoc} */ - protected function doEnterNode(\Twig_Node $node, \Twig_Environment $env) + protected function doEnterNode(Node $node, Environment $env) { - if ($node instanceof \Twig_Node_Block || $node instanceof \Twig_Node_Module) { + if ($node instanceof Node_Block || $node instanceof ModuleNode) { $this->scope = $this->scope->enter(); } if ($node instanceof TransDefaultDomainNode) { - if ($node->getNode('expr') instanceof \Twig_Node_Expression_Constant) { + if ($node->getNode('expr') instanceof ConstantExpression) { $this->scope->set('domain', $node->getNode('expr')); return $node; } else { $var = $this->getVarName(); - $name = new \Twig_Node_Expression_AssignName($var, $node->getTemplateLine()); - $this->scope->set('domain', new \Twig_Node_Expression_Name($var, $node->getTemplateLine())); + $name = new AssignNameExpression($var, $node->getTemplateLine()); + $this->scope->set('domain', new NameExpression($var, $node->getTemplateLine())); - return new \Twig_Node_Set(false, new \Twig_Node(array($name)), new \Twig_Node(array($node->getNode('expr'))), $node->getTemplateLine()); + return new Node_Set(false, new Node(array($name)), new Node(array($node->getNode('expr'))), $node->getTemplateLine()); } } @@ -61,7 +70,7 @@ protected function doEnterNode(\Twig_Node $node, \Twig_Environment $env) return $node; } - if ($node instanceof \Twig_Node_Expression_Filter && in_array($node->getNode('filter')->getAttribute('value'), array('trans', 'transchoice'))) { + if ($node instanceof FilterExpression && in_array($node->getNode('filter')->getAttribute('value'), array('trans', 'transchoice'))) { $arguments = $node->getNode('arguments'); $ind = 'trans' === $node->getNode('filter')->getAttribute('value') ? 1 : 2; if ($this->isNamedArguments($arguments)) { @@ -71,7 +80,7 @@ protected function doEnterNode(\Twig_Node $node, \Twig_Environment $env) } else { if (!$arguments->hasNode($ind)) { if (!$arguments->hasNode($ind - 1)) { - $arguments->setNode($ind - 1, new \Twig_Node_Expression_Array(array(), $node->getTemplateLine())); + $arguments->setNode($ind - 1, new ArrayExpression(array(), $node->getTemplateLine())); } $arguments->setNode($ind, $this->scope->get('domain')); @@ -89,13 +98,13 @@ protected function doEnterNode(\Twig_Node $node, \Twig_Environment $env) /** * {@inheritdoc} */ - protected function doLeaveNode(\Twig_Node $node, \Twig_Environment $env) + protected function doLeaveNode(Node $node, Environment $env) { if ($node instanceof TransDefaultDomainNode) { return false; } - if ($node instanceof \Twig_Node_Block || $node instanceof \Twig_Node_Module) { + if ($node instanceof Node_Block || $node instanceof ModuleNode) { $this->scope = $this->scope->leave(); } diff --git a/src/Symfony/Bridge/Twig/NodeVisitor/TranslationNodeVisitor.php b/src/Symfony/Bridge/Twig/NodeVisitor/TranslationNodeVisitor.php index 6e3880d09ed98..01f230b9efdff 100644 --- a/src/Symfony/Bridge/Twig/NodeVisitor/TranslationNodeVisitor.php +++ b/src/Symfony/Bridge/Twig/NodeVisitor/TranslationNodeVisitor.php @@ -12,13 +12,18 @@ namespace Symfony\Bridge\Twig\NodeVisitor; use Symfony\Bridge\Twig\Node\TransNode; +use Twig\Environment; +use Twig\Node\Expression\ConstantExpression; +use Twig\Node\Expression\FilterExpression; +use Twig\Node\Node; +use Twig\NodeVisitor\AbstractNodeVisitor; /** * TranslationNodeVisitor extracts translation messages. * * @author Fabien Potencier */ -class TranslationNodeVisitor extends \Twig_BaseNodeVisitor +class TranslationNodeVisitor extends AbstractNodeVisitor { const UNDEFINED_DOMAIN = '_undefined'; @@ -45,16 +50,16 @@ public function getMessages() /** * {@inheritdoc} */ - protected function doEnterNode(\Twig_Node $node, \Twig_Environment $env) + protected function doEnterNode(Node $node, Environment $env) { if (!$this->enabled) { return $node; } if ( - $node instanceof \Twig_Node_Expression_Filter && + $node instanceof FilterExpression && 'trans' === $node->getNode('filter')->getAttribute('value') && - $node->getNode('node') instanceof \Twig_Node_Expression_Constant + $node->getNode('node') instanceof ConstantExpression ) { // extract constant nodes with a trans filter $this->messages[] = array( @@ -62,9 +67,9 @@ protected function doEnterNode(\Twig_Node $node, \Twig_Environment $env) $this->getReadDomainFromArguments($node->getNode('arguments'), 1), ); } elseif ( - $node instanceof \Twig_Node_Expression_Filter && + $node instanceof FilterExpression && 'transchoice' === $node->getNode('filter')->getAttribute('value') && - $node->getNode('node') instanceof \Twig_Node_Expression_Constant + $node->getNode('node') instanceof ConstantExpression ) { // extract constant nodes with a trans filter $this->messages[] = array( @@ -85,7 +90,7 @@ protected function doEnterNode(\Twig_Node $node, \Twig_Environment $env) /** * {@inheritdoc} */ - protected function doLeaveNode(\Twig_Node $node, \Twig_Environment $env) + protected function doLeaveNode(Node $node, Environment $env) { return $node; } @@ -99,12 +104,12 @@ public function getPriority() } /** - * @param \Twig_Node $arguments - * @param int $index + * @param Node $arguments + * @param int $index * * @return string|null */ - private function getReadDomainFromArguments(\Twig_Node $arguments, $index) + private function getReadDomainFromArguments(Node $arguments, $index) { if ($arguments->hasNode('domain')) { $argument = $arguments->getNode('domain'); @@ -118,13 +123,13 @@ private function getReadDomainFromArguments(\Twig_Node $arguments, $index) } /** - * @param \Twig_Node $node + * @param Node $node * * @return string|null */ - private function getReadDomainFromNode(\Twig_Node $node) + private function getReadDomainFromNode(Node $node) { - if ($node instanceof \Twig_Node_Expression_Constant) { + if ($node instanceof ConstantExpression) { return $node->getAttribute('value'); } diff --git a/src/Symfony/Bridge/Twig/Tests/Command/LintCommandTest.php b/src/Symfony/Bridge/Twig/Tests/Command/LintCommandTest.php index 9a5c33a528a37..3349e38531cad 100644 --- a/src/Symfony/Bridge/Twig/Tests/Command/LintCommandTest.php +++ b/src/Symfony/Bridge/Twig/Tests/Command/LintCommandTest.php @@ -16,6 +16,8 @@ use Symfony\Component\Console\Application; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Tester\CommandTester; +use Twig\Loader\FilesystemLoader; +use Twig\Environment; class LintCommandTest extends TestCase { @@ -71,7 +73,7 @@ public function testLintFileCompileTimeException() */ private function createCommandTester() { - $twig = new \Twig_Environment(new \Twig_Loader_Filesystem()); + $twig = new Environment(new FilesystemLoader()); $command = new LintCommand(); $command->setTwigEnvironment($twig); diff --git a/src/Symfony/Bridge/Twig/Tests/Extension/DumpExtensionTest.php b/src/Symfony/Bridge/Twig/Tests/Extension/DumpExtensionTest.php index 312fda1d7106a..36e0e6a08d99e 100644 --- a/src/Symfony/Bridge/Twig/Tests/Extension/DumpExtensionTest.php +++ b/src/Symfony/Bridge/Twig/Tests/Extension/DumpExtensionTest.php @@ -15,6 +15,8 @@ use Symfony\Bridge\Twig\Extension\DumpExtension; use Symfony\Component\VarDumper\VarDumper; use Symfony\Component\VarDumper\Cloner\VarCloner; +use Twig\Environment; +use Twig\Loader\ArrayLoader; class DumpExtensionTest extends TestCase { @@ -24,7 +26,7 @@ class DumpExtensionTest extends TestCase public function testDumpTag($template, $debug, $expectedOutput, $expectedDumped) { $extension = new DumpExtension(new VarCloner()); - $twig = new \Twig_Environment(new \Twig_Loader_Array(array('template' => $template)), array( + $twig = new Environment(new ArrayLoader(array('template' => $template)), array( 'debug' => $debug, 'cache' => false, 'optimizations' => 0, @@ -64,7 +66,7 @@ public function getDumpTags() public function testDump($context, $args, $expectedOutput, $debug = true) { $extension = new DumpExtension(new VarCloner()); - $twig = new \Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock(), array( + $twig = new Environment($this->getMockBuilder('Twig\Loader\LoaderInterface')->getMock(), array( 'debug' => $debug, 'cache' => false, 'optimizations' => 0, diff --git a/src/Symfony/Bridge/Twig/Tests/Extension/ExpressionExtensionTest.php b/src/Symfony/Bridge/Twig/Tests/Extension/ExpressionExtensionTest.php index 597dfc75f4165..ab3b44ccce0c1 100644 --- a/src/Symfony/Bridge/Twig/Tests/Extension/ExpressionExtensionTest.php +++ b/src/Symfony/Bridge/Twig/Tests/Extension/ExpressionExtensionTest.php @@ -13,6 +13,8 @@ use PHPUnit\Framework\TestCase; use Symfony\Bridge\Twig\Extension\ExpressionExtension; +use Twig\Environment; +use Twig\Loader\ArrayLoader; class ExpressionExtensionTest extends TestCase { @@ -21,7 +23,7 @@ class ExpressionExtensionTest extends TestCase public function testExpressionCreation() { $template = "{{ expression('1 == 1') }}"; - $twig = new \Twig_Environment(new \Twig_Loader_Array(array('template' => $template)), array('debug' => true, 'cache' => false, 'autoescape' => 'html', 'optimizations' => 0)); + $twig = new Environment(new ArrayLoader(array('template' => $template)), array('debug' => true, 'cache' => false, 'autoescape' => 'html', 'optimizations' => 0)); $twig->addExtension(new ExpressionExtension()); $output = $twig->render('template'); diff --git a/src/Symfony/Bridge/Twig/Tests/Extension/Fixtures/StubFilesystemLoader.php b/src/Symfony/Bridge/Twig/Tests/Extension/Fixtures/StubFilesystemLoader.php index 1c8e5dcd490f7..4cbc55b46a66c 100644 --- a/src/Symfony/Bridge/Twig/Tests/Extension/Fixtures/StubFilesystemLoader.php +++ b/src/Symfony/Bridge/Twig/Tests/Extension/Fixtures/StubFilesystemLoader.php @@ -11,7 +11,9 @@ namespace Symfony\Bridge\Twig\Tests\Extension\Fixtures; -class StubFilesystemLoader extends \Twig_Loader_Filesystem +use Twig\Loader\FilesystemLoader; + +class StubFilesystemLoader extends FilesystemLoader { protected function findTemplate($name, $throw = true) { diff --git a/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionBootstrap3HorizontalLayoutTest.php b/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionBootstrap3HorizontalLayoutTest.php index 8abcc8cd5677b..9d84946177af2 100644 --- a/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionBootstrap3HorizontalLayoutTest.php +++ b/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionBootstrap3HorizontalLayoutTest.php @@ -19,6 +19,7 @@ use Symfony\Bridge\Twig\Tests\Extension\Fixtures\StubFilesystemLoader; use Symfony\Component\Form\FormView; use Symfony\Component\Form\Tests\AbstractBootstrap3HorizontalLayoutTest; +use Twig\Environment; class FormExtensionBootstrap3HorizontalLayoutTest extends AbstractBootstrap3HorizontalLayoutTest { @@ -48,7 +49,7 @@ protected function setUp() __DIR__.'/Fixtures/templates/form', )); - $environment = new \Twig_Environment($loader, array('strict_variables' => true)); + $environment = new Environment($loader, array('strict_variables' => true)); $environment->addExtension(new TranslationExtension(new StubTranslator())); $environment->addExtension($this->extension); diff --git a/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionBootstrap3LayoutTest.php b/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionBootstrap3LayoutTest.php index 0236dd76e1e46..10161cbd4e1a7 100644 --- a/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionBootstrap3LayoutTest.php +++ b/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionBootstrap3LayoutTest.php @@ -19,6 +19,7 @@ use Symfony\Bridge\Twig\Tests\Extension\Fixtures\StubFilesystemLoader; use Symfony\Component\Form\FormView; use Symfony\Component\Form\Tests\AbstractBootstrap3LayoutTest; +use Twig\Environment; class FormExtensionBootstrap3LayoutTest extends AbstractBootstrap3LayoutTest { @@ -48,7 +49,7 @@ protected function setUp() __DIR__.'/Fixtures/templates/form', )); - $environment = new \Twig_Environment($loader, array('strict_variables' => true)); + $environment = new Environment($loader, array('strict_variables' => true)); $environment->addExtension(new TranslationExtension(new StubTranslator())); $environment->addExtension($this->extension); diff --git a/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionDivLayoutTest.php b/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionDivLayoutTest.php index d07e585a89234..2d7339b369d30 100644 --- a/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionDivLayoutTest.php +++ b/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionDivLayoutTest.php @@ -20,6 +20,7 @@ use Symfony\Component\Form\ChoiceList\View\ChoiceView; use Symfony\Component\Form\FormView; use Symfony\Component\Form\Tests\AbstractDivLayoutTest; +use Twig\Environment; class FormExtensionDivLayoutTest extends AbstractDivLayoutTest { @@ -49,7 +50,7 @@ protected function setUp() __DIR__.'/Fixtures/templates/form', )); - $environment = new \Twig_Environment($loader, array('strict_variables' => true)); + $environment = new Environment($loader, array('strict_variables' => true)); $environment->addExtension(new TranslationExtension(new StubTranslator())); $environment->addGlobal('global', ''); // the value can be any template that exists diff --git a/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionTableLayoutTest.php b/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionTableLayoutTest.php index 9c95db6d5fd9d..1d526d5138fa5 100644 --- a/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionTableLayoutTest.php +++ b/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionTableLayoutTest.php @@ -19,6 +19,7 @@ use Symfony\Component\Form\Tests\AbstractTableLayoutTest; use Symfony\Bridge\Twig\Tests\Extension\Fixtures\StubTranslator; use Symfony\Bridge\Twig\Tests\Extension\Fixtures\StubFilesystemLoader; +use Twig\Environment; class FormExtensionTableLayoutTest extends AbstractTableLayoutTest { @@ -48,7 +49,7 @@ protected function setUp() __DIR__.'/Fixtures/templates/form', )); - $environment = new \Twig_Environment($loader, array('strict_variables' => true)); + $environment = new Environment($loader, array('strict_variables' => true)); $environment->addExtension(new TranslationExtension(new StubTranslator())); $environment->addGlobal('global', ''); $environment->addExtension($this->extension); diff --git a/src/Symfony/Bridge/Twig/Tests/Extension/HttpKernelExtensionTest.php b/src/Symfony/Bridge/Twig/Tests/Extension/HttpKernelExtensionTest.php index 61e041d4d4c14..564ffc0432fe9 100644 --- a/src/Symfony/Bridge/Twig/Tests/Extension/HttpKernelExtensionTest.php +++ b/src/Symfony/Bridge/Twig/Tests/Extension/HttpKernelExtensionTest.php @@ -16,11 +16,13 @@ use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\Fragment\FragmentHandler; +use Twig\Environment; +use Twig\Loader\ArrayLoader; class HttpKernelExtensionTest extends TestCase { /** - * @expectedException \Twig_Error_Runtime + * @expectedException \Twig\Error\RuntimeError */ public function testFragmentWithError() { @@ -74,8 +76,8 @@ protected function getFragmentHandler($return) protected function renderTemplate(FragmentHandler $renderer, $template = '{{ render("foo") }}') { - $loader = new \Twig_Loader_Array(array('index' => $template)); - $twig = new \Twig_Environment($loader, array('debug' => true, 'cache' => false)); + $loader = new ArrayLoader(array('index' => $template)); + $twig = new Environment($loader, array('debug' => true, 'cache' => false)); $twig->addExtension(new HttpKernelExtension($renderer)); return $twig->render('index'); diff --git a/src/Symfony/Bridge/Twig/Tests/Extension/RoutingExtensionTest.php b/src/Symfony/Bridge/Twig/Tests/Extension/RoutingExtensionTest.php index 5fa4e9cd36b1c..fdff039851228 100644 --- a/src/Symfony/Bridge/Twig/Tests/Extension/RoutingExtensionTest.php +++ b/src/Symfony/Bridge/Twig/Tests/Extension/RoutingExtensionTest.php @@ -13,6 +13,9 @@ use PHPUnit\Framework\TestCase; use Symfony\Bridge\Twig\Extension\RoutingExtension; +use Twig\Environment; +use Twig\Node\Expression\FilterExpression; +use Twig\Source; class RoutingExtensionTest extends TestCase { @@ -21,12 +24,12 @@ class RoutingExtensionTest extends TestCase */ public function testEscaping($template, $mustBeEscaped) { - $twig = new \Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock(), array('debug' => true, 'cache' => false, 'autoescape' => 'html', 'optimizations' => 0)); + $twig = new Environment($this->getMockBuilder('Twig\Loader\LoaderInterface')->getMock(), array('debug' => true, 'cache' => false, 'autoescape' => 'html', 'optimizations' => 0)); $twig->addExtension(new RoutingExtension($this->getMockBuilder('Symfony\Component\Routing\Generator\UrlGeneratorInterface')->getMock())); - $nodes = $twig->parse($twig->tokenize(new \Twig_Source($template, ''))); + $nodes = $twig->parse($twig->tokenize(new Source($template, ''))); - $this->assertSame($mustBeEscaped, $nodes->getNode('body')->getNode(0)->getNode('expr') instanceof \Twig_Node_Expression_Filter); + $this->assertSame($mustBeEscaped, $nodes->getNode('body')->getNode(0)->getNode('expr') instanceof FilterExpression); } public function getEscapingTemplates() diff --git a/src/Symfony/Bridge/Twig/Tests/Extension/StopwatchExtensionTest.php b/src/Symfony/Bridge/Twig/Tests/Extension/StopwatchExtensionTest.php index 86a4fcbe32269..7bc4eed6ab3e1 100644 --- a/src/Symfony/Bridge/Twig/Tests/Extension/StopwatchExtensionTest.php +++ b/src/Symfony/Bridge/Twig/Tests/Extension/StopwatchExtensionTest.php @@ -13,11 +13,14 @@ use PHPUnit\Framework\TestCase; use Symfony\Bridge\Twig\Extension\StopwatchExtension; +use Twig\Environment; +use Twig\Error\RuntimeError; +use Twig\Loader\ArrayLoader; class StopwatchExtensionTest extends TestCase { /** - * @expectedException \Twig_Error_Syntax + * @expectedException \Twig\Error\SyntaxError */ public function testFailIfStoppingWrongEvent() { @@ -29,12 +32,12 @@ public function testFailIfStoppingWrongEvent() */ public function testTiming($template, $events) { - $twig = new \Twig_Environment(new \Twig_Loader_Array(array('template' => $template)), array('debug' => true, 'cache' => false, 'autoescape' => 'html', 'optimizations' => 0)); + $twig = new Environment(new ArrayLoader(array('template' => $template)), array('debug' => true, 'cache' => false, 'autoescape' => 'html', 'optimizations' => 0)); $twig->addExtension(new StopwatchExtension($this->getStopwatch($events))); try { $nodes = $twig->render('template'); - } catch (\Twig_Error_Runtime $e) { + } catch (RuntimeError $e) { throw $e->getPrevious(); } } diff --git a/src/Symfony/Bridge/Twig/Tests/Extension/TranslationExtensionTest.php b/src/Symfony/Bridge/Twig/Tests/Extension/TranslationExtensionTest.php index 446697d3dd8b2..36016d7f49bca 100644 --- a/src/Symfony/Bridge/Twig/Tests/Extension/TranslationExtensionTest.php +++ b/src/Symfony/Bridge/Twig/Tests/Extension/TranslationExtensionTest.php @@ -16,6 +16,8 @@ use Symfony\Component\Translation\Translator; use Symfony\Component\Translation\MessageSelector; use Symfony\Component\Translation\Loader\ArrayLoader; +use Twig\Environment; +use Twig\Loader\ArrayLoader as TwigArrayLoader; class TranslationExtensionTest extends TestCase { @@ -33,8 +35,8 @@ public function testTrans($template, $expected, array $variables = array()) { if ($expected != $this->getTemplate($template)->render($variables)) { echo $template."\n"; - $loader = new \Twig_Loader_Array(array('index' => $template)); - $twig = new \Twig_Environment($loader, array('debug' => true, 'cache' => false)); + $loader = new TwigArrayLoader(array('index' => $template)); + $twig = new Environment($loader, array('debug' => true, 'cache' => false)); $twig->addExtension(new TranslationExtension(new Translator('en', new MessageSelector()))); echo $twig->compile($twig->parse($twig->tokenize($twig->getLoader()->getSourceContext('index'))))."\n\n"; @@ -45,7 +47,7 @@ public function testTrans($template, $expected, array $variables = array()) } /** - * @expectedException \Twig_Error_Syntax + * @expectedException \Twig\Error\SyntaxError * @expectedExceptionMessage Unexpected token. Twig was looking for the "with", "from", or "into" keyword in "index" at line 3. */ public function testTransUnknownKeyword() @@ -54,7 +56,7 @@ public function testTransUnknownKeyword() } /** - * @expectedException \Twig_Error_Syntax + * @expectedException \Twig\Error\SyntaxError * @expectedExceptionMessage A message inside a trans tag must be a simple text in "index" at line 2. */ public function testTransComplexBody() @@ -63,7 +65,7 @@ public function testTransComplexBody() } /** - * @expectedException \Twig_Error_Syntax + * @expectedException \Twig\Error\SyntaxError * @expectedExceptionMessage A message inside a transchoice tag must be a simple text in "index" at line 2. */ public function testTransChoiceComplexBody() @@ -189,11 +191,11 @@ protected function getTemplate($template, $translator = null) } if (is_array($template)) { - $loader = new \Twig_Loader_Array($template); + $loader = new TwigArrayLoader($template); } else { - $loader = new \Twig_Loader_Array(array('index' => $template)); + $loader = new TwigArrayLoader(array('index' => $template)); } - $twig = new \Twig_Environment($loader, array('debug' => true, 'cache' => false)); + $twig = new Environment($loader, array('debug' => true, 'cache' => false)); $twig->addExtension(new TranslationExtension($translator)); return $twig->loadTemplate('index'); diff --git a/src/Symfony/Bridge/Twig/Tests/Node/DumpNodeTest.php b/src/Symfony/Bridge/Twig/Tests/Node/DumpNodeTest.php index e38d9c728283b..087596e242281 100644 --- a/src/Symfony/Bridge/Twig/Tests/Node/DumpNodeTest.php +++ b/src/Symfony/Bridge/Twig/Tests/Node/DumpNodeTest.php @@ -13,6 +13,10 @@ use PHPUnit\Framework\TestCase; use Symfony\Bridge\Twig\Node\DumpNode; +use Twig\Compiler; +use Twig\Environment; +use Twig\Node\Expression\NameExpression; +use Twig\Node\Node; class DumpNodeTest extends TestCase { @@ -20,14 +24,14 @@ public function testNoVar() { $node = new DumpNode('bar', null, 7); - $env = new \Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock()); - $compiler = new \Twig_Compiler($env); + $env = new Environment($this->getMockBuilder('Twig\Loader\LoaderInterface')->getMock()); + $compiler = new Compiler($env); $expected = <<<'EOTXT' if ($this->env->isDebug()) { $barvars = array(); foreach ($context as $barkey => $barval) { - if (!$barval instanceof \Twig_Template) { + if (!$barval instanceof \Twig\Template) { $barvars[$barkey] = $barval; } } @@ -44,14 +48,14 @@ public function testIndented() { $node = new DumpNode('bar', null, 7); - $env = new \Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock()); - $compiler = new \Twig_Compiler($env); + $env = new Environment($this->getMockBuilder('Twig\Loader\LoaderInterface')->getMock()); + $compiler = new Compiler($env); $expected = <<<'EOTXT' if ($this->env->isDebug()) { $barvars = array(); foreach ($context as $barkey => $barval) { - if (!$barval instanceof \Twig_Template) { + if (!$barval instanceof \Twig\Template) { $barvars[$barkey] = $barval; } } @@ -66,13 +70,13 @@ public function testIndented() public function testOneVar() { - $vars = new \Twig_Node(array( - new \Twig_Node_Expression_Name('foo', 7), + $vars = new Node(array( + new NameExpression('foo', 7), )); $node = new DumpNode('bar', $vars, 7); - $env = new \Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock()); - $compiler = new \Twig_Compiler($env); + $env = new Environment($this->getMockBuilder('Twig\Loader\LoaderInterface')->getMock()); + $compiler = new Compiler($env); $expected = <<<'EOTXT' if ($this->env->isDebug()) { @@ -94,14 +98,14 @@ public function testOneVar() public function testMultiVars() { - $vars = new \Twig_Node(array( - new \Twig_Node_Expression_Name('foo', 7), - new \Twig_Node_Expression_Name('bar', 7), + $vars = new Node(array( + new NameExpression('foo', 7), + new NameExpression('bar', 7), )); $node = new DumpNode('bar', $vars, 7); - $env = new \Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock()); - $compiler = new \Twig_Compiler($env); + $env = new Environment($this->getMockBuilder('Twig\Loader\LoaderInterface')->getMock()); + $compiler = new Compiler($env); $expected = <<<'EOTXT' if ($this->env->isDebug()) { diff --git a/src/Symfony/Bridge/Twig/Tests/Node/FormThemeTest.php b/src/Symfony/Bridge/Twig/Tests/Node/FormThemeTest.php index 923c20ff35d5f..48bbdab98cf1b 100644 --- a/src/Symfony/Bridge/Twig/Tests/Node/FormThemeTest.php +++ b/src/Symfony/Bridge/Twig/Tests/Node/FormThemeTest.php @@ -13,15 +13,21 @@ use PHPUnit\Framework\TestCase; use Symfony\Bridge\Twig\Node\FormThemeNode; +use Twig\Compiler; +use Twig\Environment; +use Twig\Node\Expression\ArrayExpression; +use Twig\Node\Expression\ConstantExpression; +use Twig\Node\Expression\NameExpression; +use Twig\Node\Node; class FormThemeTest extends TestCase { public function testConstructor() { - $form = new \Twig_Node_Expression_Name('form', 0); - $resources = new \Twig_Node(array( - new \Twig_Node_Expression_Constant('tpl1', 0), - new \Twig_Node_Expression_Constant('tpl2', 0), + $form = new NameExpression('form', 0); + $resources = new Node(array( + new ConstantExpression('tpl1', 0), + new ConstantExpression('tpl2', 0), )); $node = new FormThemeNode($form, $resources, 0); @@ -32,17 +38,17 @@ public function testConstructor() public function testCompile() { - $form = new \Twig_Node_Expression_Name('form', 0); - $resources = new \Twig_Node_Expression_Array(array( - new \Twig_Node_Expression_Constant(0, 0), - new \Twig_Node_Expression_Constant('tpl1', 0), - new \Twig_Node_Expression_Constant(1, 0), - new \Twig_Node_Expression_Constant('tpl2', 0), + $form = new NameExpression('form', 0); + $resources = new ArrayExpression(array( + new ConstantExpression(0, 0), + new ConstantExpression('tpl1', 0), + new ConstantExpression(1, 0), + new ConstantExpression('tpl2', 0), ), 0); $node = new FormThemeNode($form, $resources, 0); - $compiler = new \Twig_Compiler(new \Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock())); + $compiler = new Compiler(new Environment($this->getMockBuilder('Twig\Loader\LoaderInterface')->getMock())); $this->assertEquals( sprintf( @@ -52,7 +58,7 @@ public function testCompile() trim($compiler->compile($node)->getSource()) ); - $resources = new \Twig_Node_Expression_Constant('tpl1', 0); + $resources = new ConstantExpression('tpl1', 0); $node = new FormThemeNode($form, $resources, 0); diff --git a/src/Symfony/Bridge/Twig/Tests/Node/SearchAndRenderBlockNodeTest.php b/src/Symfony/Bridge/Twig/Tests/Node/SearchAndRenderBlockNodeTest.php index e29f66ea3c56b..a603576f30274 100644 --- a/src/Symfony/Bridge/Twig/Tests/Node/SearchAndRenderBlockNodeTest.php +++ b/src/Symfony/Bridge/Twig/Tests/Node/SearchAndRenderBlockNodeTest.php @@ -13,18 +13,25 @@ use PHPUnit\Framework\TestCase; use Symfony\Bridge\Twig\Node\SearchAndRenderBlockNode; +use Twig\Compiler; +use Twig\Environment; +use Twig\Node\Expression\ArrayExpression; +use Twig\Node\Expression\ConditionalExpression; +use Twig\Node\Expression\ConstantExpression; +use Twig\Node\Expression\NameExpression; +use Twig\Node\Node; class SearchAndRenderBlockNodeTest extends TestCase { public function testCompileWidget() { - $arguments = new \Twig_Node(array( - new \Twig_Node_Expression_Name('form', 0), + $arguments = new Node(array( + new NameExpression('form', 0), )); $node = new SearchAndRenderBlockNode('form_widget', $arguments, 0); - $compiler = new \Twig_Compiler(new \Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock())); + $compiler = new Compiler(new Environment($this->getMockBuilder('Twig\Loader\LoaderInterface')->getMock())); $this->assertEquals( sprintf( @@ -37,17 +44,17 @@ public function testCompileWidget() public function testCompileWidgetWithVariables() { - $arguments = new \Twig_Node(array( - new \Twig_Node_Expression_Name('form', 0), - new \Twig_Node_Expression_Array(array( - new \Twig_Node_Expression_Constant('foo', 0), - new \Twig_Node_Expression_Constant('bar', 0), + $arguments = new Node(array( + new NameExpression('form', 0), + new ArrayExpression(array( + new ConstantExpression('foo', 0), + new ConstantExpression('bar', 0), ), 0), )); $node = new SearchAndRenderBlockNode('form_widget', $arguments, 0); - $compiler = new \Twig_Compiler(new \Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock())); + $compiler = new Compiler(new Environment($this->getMockBuilder('Twig\Loader\LoaderInterface')->getMock())); $this->assertEquals( sprintf( @@ -60,14 +67,14 @@ public function testCompileWidgetWithVariables() public function testCompileLabelWithLabel() { - $arguments = new \Twig_Node(array( - new \Twig_Node_Expression_Name('form', 0), - new \Twig_Node_Expression_Constant('my label', 0), + $arguments = new Node(array( + new NameExpression('form', 0), + new ConstantExpression('my label', 0), )); $node = new SearchAndRenderBlockNode('form_label', $arguments, 0); - $compiler = new \Twig_Compiler(new \Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock())); + $compiler = new Compiler(new Environment($this->getMockBuilder('Twig\Loader\LoaderInterface')->getMock())); $this->assertEquals( sprintf( @@ -80,14 +87,14 @@ public function testCompileLabelWithLabel() public function testCompileLabelWithNullLabel() { - $arguments = new \Twig_Node(array( - new \Twig_Node_Expression_Name('form', 0), - new \Twig_Node_Expression_Constant(null, 0), + $arguments = new Node(array( + new NameExpression('form', 0), + new ConstantExpression(null, 0), )); $node = new SearchAndRenderBlockNode('form_label', $arguments, 0); - $compiler = new \Twig_Compiler(new \Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock())); + $compiler = new Compiler(new Environment($this->getMockBuilder('Twig\Loader\LoaderInterface')->getMock())); // "label" => null must not be included in the output! // Otherwise the default label is overwritten with null. @@ -102,14 +109,14 @@ public function testCompileLabelWithNullLabel() public function testCompileLabelWithEmptyStringLabel() { - $arguments = new \Twig_Node(array( - new \Twig_Node_Expression_Name('form', 0), - new \Twig_Node_Expression_Constant('', 0), + $arguments = new Node(array( + new NameExpression('form', 0), + new ConstantExpression('', 0), )); $node = new SearchAndRenderBlockNode('form_label', $arguments, 0); - $compiler = new \Twig_Compiler(new \Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock())); + $compiler = new Compiler(new Environment($this->getMockBuilder('Twig\Loader\LoaderInterface')->getMock())); // "label" => null must not be included in the output! // Otherwise the default label is overwritten with null. @@ -124,13 +131,13 @@ public function testCompileLabelWithEmptyStringLabel() public function testCompileLabelWithDefaultLabel() { - $arguments = new \Twig_Node(array( - new \Twig_Node_Expression_Name('form', 0), + $arguments = new Node(array( + new NameExpression('form', 0), )); $node = new SearchAndRenderBlockNode('form_label', $arguments, 0); - $compiler = new \Twig_Compiler(new \Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock())); + $compiler = new Compiler(new Environment($this->getMockBuilder('Twig\Loader\LoaderInterface')->getMock())); $this->assertEquals( sprintf( @@ -143,18 +150,18 @@ public function testCompileLabelWithDefaultLabel() public function testCompileLabelWithAttributes() { - $arguments = new \Twig_Node(array( - new \Twig_Node_Expression_Name('form', 0), - new \Twig_Node_Expression_Constant(null, 0), - new \Twig_Node_Expression_Array(array( - new \Twig_Node_Expression_Constant('foo', 0), - new \Twig_Node_Expression_Constant('bar', 0), + $arguments = new Node(array( + new NameExpression('form', 0), + new ConstantExpression(null, 0), + new ArrayExpression(array( + new ConstantExpression('foo', 0), + new ConstantExpression('bar', 0), ), 0), )); $node = new SearchAndRenderBlockNode('form_label', $arguments, 0); - $compiler = new \Twig_Compiler(new \Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock())); + $compiler = new Compiler(new Environment($this->getMockBuilder('Twig\Loader\LoaderInterface')->getMock())); // "label" => null must not be included in the output! // Otherwise the default label is overwritten with null. @@ -170,20 +177,20 @@ public function testCompileLabelWithAttributes() public function testCompileLabelWithLabelAndAttributes() { - $arguments = new \Twig_Node(array( - new \Twig_Node_Expression_Name('form', 0), - new \Twig_Node_Expression_Constant('value in argument', 0), - new \Twig_Node_Expression_Array(array( - new \Twig_Node_Expression_Constant('foo', 0), - new \Twig_Node_Expression_Constant('bar', 0), - new \Twig_Node_Expression_Constant('label', 0), - new \Twig_Node_Expression_Constant('value in attributes', 0), + $arguments = new Node(array( + new NameExpression('form', 0), + new ConstantExpression('value in argument', 0), + new ArrayExpression(array( + new ConstantExpression('foo', 0), + new ConstantExpression('bar', 0), + new ConstantExpression('label', 0), + new ConstantExpression('value in attributes', 0), ), 0), )); $node = new SearchAndRenderBlockNode('form_label', $arguments, 0); - $compiler = new \Twig_Compiler(new \Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock())); + $compiler = new Compiler(new Environment($this->getMockBuilder('Twig\Loader\LoaderInterface')->getMock())); $this->assertEquals( sprintf( @@ -196,22 +203,22 @@ public function testCompileLabelWithLabelAndAttributes() public function testCompileLabelWithLabelThatEvaluatesToNull() { - $arguments = new \Twig_Node(array( - new \Twig_Node_Expression_Name('form', 0), - new \Twig_Node_Expression_Conditional( + $arguments = new Node(array( + new NameExpression('form', 0), + new ConditionalExpression( // if - new \Twig_Node_Expression_Constant(true, 0), + new ConstantExpression(true, 0), // then - new \Twig_Node_Expression_Constant(null, 0), + new ConstantExpression(null, 0), // else - new \Twig_Node_Expression_Constant(null, 0), + new ConstantExpression(null, 0), 0 ), )); $node = new SearchAndRenderBlockNode('form_label', $arguments, 0); - $compiler = new \Twig_Compiler(new \Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock())); + $compiler = new Compiler(new Environment($this->getMockBuilder('Twig\Loader\LoaderInterface')->getMock())); // "label" => null must not be included in the output! // Otherwise the default label is overwritten with null. @@ -227,28 +234,28 @@ public function testCompileLabelWithLabelThatEvaluatesToNull() public function testCompileLabelWithLabelThatEvaluatesToNullAndAttributes() { - $arguments = new \Twig_Node(array( - new \Twig_Node_Expression_Name('form', 0), - new \Twig_Node_Expression_Conditional( + $arguments = new Node(array( + new NameExpression('form', 0), + new ConditionalExpression( // if - new \Twig_Node_Expression_Constant(true, 0), + new ConstantExpression(true, 0), // then - new \Twig_Node_Expression_Constant(null, 0), + new ConstantExpression(null, 0), // else - new \Twig_Node_Expression_Constant(null, 0), + new ConstantExpression(null, 0), 0 ), - new \Twig_Node_Expression_Array(array( - new \Twig_Node_Expression_Constant('foo', 0), - new \Twig_Node_Expression_Constant('bar', 0), - new \Twig_Node_Expression_Constant('label', 0), - new \Twig_Node_Expression_Constant('value in attributes', 0), + new ArrayExpression(array( + new ConstantExpression('foo', 0), + new ConstantExpression('bar', 0), + new ConstantExpression('label', 0), + new ConstantExpression('value in attributes', 0), ), 0), )); $node = new SearchAndRenderBlockNode('form_label', $arguments, 0); - $compiler = new \Twig_Compiler(new \Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock())); + $compiler = new Compiler(new Environment($this->getMockBuilder('Twig\Loader\LoaderInterface')->getMock())); // "label" => null must not be included in the output! // Otherwise the default label is overwritten with null. diff --git a/src/Symfony/Bridge/Twig/Tests/Node/TransNodeTest.php b/src/Symfony/Bridge/Twig/Tests/Node/TransNodeTest.php index aabd813e5c5ac..c4d67fc962666 100644 --- a/src/Symfony/Bridge/Twig/Tests/Node/TransNodeTest.php +++ b/src/Symfony/Bridge/Twig/Tests/Node/TransNodeTest.php @@ -13,6 +13,10 @@ use PHPUnit\Framework\TestCase; use Symfony\Bridge\Twig\Node\TransNode; +use Twig\Compiler; +use Twig\Environment; +use Twig\Node\Expression\NameExpression; +use Twig\Node\TextNode; /** * @author Asmir Mustafic @@ -21,12 +25,12 @@ class TransNodeTest extends TestCase { public function testCompileStrict() { - $body = new \Twig_Node_Text('trans %var%', 0); - $vars = new \Twig_Node_Expression_Name('foo', 0); + $body = new TextNode('trans %var%', 0); + $vars = new NameExpression('foo', 0); $node = new TransNode($body, null, null, $vars); - $env = new \Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock(), array('strict_variables' => true)); - $compiler = new \Twig_Compiler($env); + $env = new Environment($this->getMockBuilder('Twig\Loader\LoaderInterface')->getMock(), array('strict_variables' => true)); + $compiler = new Compiler($env); $this->assertEquals( sprintf( @@ -53,7 +57,7 @@ protected function getVariableGetterWithoutStrictCheck($name) protected function getVariableGetterWithStrictCheck($name) { - if (\Twig_Environment::MAJOR_VERSION >= 2) { + if (Environment::MAJOR_VERSION >= 2) { return sprintf('(isset($context["%s"]) || array_key_exists("%s", $context) ? $context["%s"] : (function () { throw new Twig_Error_Runtime(\'Variable "%s" does not exist.\', 0, $this->getSourceContext()); })())', $name, $name, $name, $name); } diff --git a/src/Symfony/Bridge/Twig/Tests/NodeVisitor/TranslationDefaultDomainNodeVisitorTest.php b/src/Symfony/Bridge/Twig/Tests/NodeVisitor/TranslationDefaultDomainNodeVisitorTest.php index da9f43a6c4e0e..eb4c9a83e86d7 100644 --- a/src/Symfony/Bridge/Twig/Tests/NodeVisitor/TranslationDefaultDomainNodeVisitorTest.php +++ b/src/Symfony/Bridge/Twig/Tests/NodeVisitor/TranslationDefaultDomainNodeVisitorTest.php @@ -14,6 +14,9 @@ use PHPUnit\Framework\TestCase; use Symfony\Bridge\Twig\NodeVisitor\TranslationDefaultDomainNodeVisitor; use Symfony\Bridge\Twig\NodeVisitor\TranslationNodeVisitor; +use Twig\Environment; +use Twig\Node\Expression\ArrayExpression; +use Twig\Node\Node; class TranslationDefaultDomainNodeVisitorTest extends TestCase { @@ -21,9 +24,9 @@ class TranslationDefaultDomainNodeVisitorTest extends TestCase private static $domain = 'domain'; /** @dataProvider getDefaultDomainAssignmentTestData */ - public function testDefaultDomainAssignment(\Twig_Node $node) + public function testDefaultDomainAssignment(Node $node) { - $env = new \Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock(), array('cache' => false, 'autoescape' => false, 'optimizations' => 0)); + $env = new Environment($this->getMockBuilder('Twig\Loader\LoaderInterface')->getMock(), array('cache' => false, 'autoescape' => false, 'optimizations' => 0)); $visitor = new TranslationDefaultDomainNodeVisitor(); // visit trans_default_domain tag @@ -47,9 +50,9 @@ public function testDefaultDomainAssignment(\Twig_Node $node) } /** @dataProvider getDefaultDomainAssignmentTestData */ - public function testNewModuleWithoutDefaultDomainTag(\Twig_Node $node) + public function testNewModuleWithoutDefaultDomainTag(Node $node) { - $env = new \Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock(), array('cache' => false, 'autoescape' => false, 'optimizations' => 0)); + $env = new Environment($this->getMockBuilder('Twig\Loader\LoaderInterface')->getMock(), array('cache' => false, 'autoescape' => false, 'optimizations' => 0)); $visitor = new TranslationDefaultDomainNodeVisitor(); // visit trans_default_domain tag @@ -80,10 +83,10 @@ public function getDefaultDomainAssignmentTestData() array(TwigNodeProvider::getTransTag(self::$message)), // with named arguments array(TwigNodeProvider::getTransFilter(self::$message, null, array( - 'arguments' => new \Twig_Node_Expression_Array(array(), 0), + 'arguments' => new ArrayExpression(array(), 0), ))), array(TwigNodeProvider::getTransChoiceFilter(self::$message), null, array( - 'arguments' => new \Twig_Node_Expression_Array(array(), 0), + 'arguments' => new ArrayExpression(array(), 0), )), ); } diff --git a/src/Symfony/Bridge/Twig/Tests/NodeVisitor/TranslationNodeVisitorTest.php b/src/Symfony/Bridge/Twig/Tests/NodeVisitor/TranslationNodeVisitorTest.php index d12fff532aaa1..9c2d0ab9e40e5 100644 --- a/src/Symfony/Bridge/Twig/Tests/NodeVisitor/TranslationNodeVisitorTest.php +++ b/src/Symfony/Bridge/Twig/Tests/NodeVisitor/TranslationNodeVisitorTest.php @@ -13,13 +13,19 @@ use PHPUnit\Framework\TestCase; use Symfony\Bridge\Twig\NodeVisitor\TranslationNodeVisitor; +use Twig\Environment; +use Twig\Node\Expression\ArrayExpression; +use Twig\Node\Expression\ConstantExpression; +use Twig\Node\Expression\FilterExpression; +use Twig\Node\Expression\NameExpression; +use Twig\Node\Node; class TranslationNodeVisitorTest extends TestCase { /** @dataProvider getMessagesExtractionTestData */ - public function testMessagesExtraction(\Twig_Node $node, array $expectedMessages) + public function testMessagesExtraction(Node $node, array $expectedMessages) { - $env = new \Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock(), array('cache' => false, 'autoescape' => false, 'optimizations' => 0)); + $env = new Environment($this->getMockBuilder('Twig\Loader\LoaderInterface')->getMock(), array('cache' => false, 'autoescape' => false, 'optimizations' => 0)); $visitor = new TranslationNodeVisitor(); $visitor->enable(); $visitor->enterNode($node, $env); @@ -31,12 +37,12 @@ public function testMessageExtractionWithInvalidDomainNode() { $message = 'new key'; - $node = new \Twig_Node_Expression_Filter( - new \Twig_Node_Expression_Constant($message, 0), - new \Twig_Node_Expression_Constant('trans', 0), - new \Twig_Node(array( - new \Twig_Node_Expression_Array(array(), 0), - new \Twig_Node_Expression_Name('variable', 0), + $node = new FilterExpression( + new ConstantExpression($message, 0), + new ConstantExpression('trans', 0), + new Node(array( + new ArrayExpression(array(), 0), + new NameExpression('variable', 0), )), 0 ); diff --git a/src/Symfony/Bridge/Twig/Tests/NodeVisitor/TwigNodeProvider.php b/src/Symfony/Bridge/Twig/Tests/NodeVisitor/TwigNodeProvider.php index 502cad38dec0b..49eac23e8aeda 100644 --- a/src/Symfony/Bridge/Twig/Tests/NodeVisitor/TwigNodeProvider.php +++ b/src/Symfony/Bridge/Twig/Tests/NodeVisitor/TwigNodeProvider.php @@ -13,19 +13,26 @@ use Symfony\Bridge\Twig\Node\TransDefaultDomainNode; use Symfony\Bridge\Twig\Node\TransNode; +use Twig\Node\BodyNode; +use Twig\Node\Expression\ArrayExpression; +use Twig\Node\Expression\ConstantExpression; +use Twig\Node\Expression\FilterExpression; +use Twig\Node\ModuleNode; +use Twig\Node\Node; +use Twig\Source; class TwigNodeProvider { public static function getModule($content) { - return new \Twig_Node_Module( - new \Twig_Node_Expression_Constant($content, 0), + return new ModuleNode( + new ConstantExpression($content, 0), null, - new \Twig_Node_Expression_Array(array(), 0), - new \Twig_Node_Expression_Array(array(), 0), - new \Twig_Node_Expression_Array(array(), 0), + new ArrayExpression(array(), 0), + new ArrayExpression(array(), 0), + new ArrayExpression(array(), 0), null, - new \Twig_Source('', '') + new Source('', '') ); } @@ -33,15 +40,15 @@ public static function getTransFilter($message, $domain = null, $arguments = nul { if (!$arguments) { $arguments = $domain ? array( - new \Twig_Node_Expression_Array(array(), 0), - new \Twig_Node_Expression_Constant($domain, 0), + new ArrayExpression(array(), 0), + new ConstantExpression($domain, 0), ) : array(); } - return new \Twig_Node_Expression_Filter( - new \Twig_Node_Expression_Constant($message, 0), - new \Twig_Node_Expression_Constant('trans', 0), - new \Twig_Node($arguments), + return new FilterExpression( + new ConstantExpression($message, 0), + new ConstantExpression('trans', 0), + new Node($arguments), 0 ); } @@ -50,16 +57,16 @@ public static function getTransChoiceFilter($message, $domain = null, $arguments { if (!$arguments) { $arguments = $domain ? array( - new \Twig_Node_Expression_Constant(0, 0), - new \Twig_Node_Expression_Array(array(), 0), - new \Twig_Node_Expression_Constant($domain, 0), + new ConstantExpression(0, 0), + new ArrayExpression(array(), 0), + new ConstantExpression($domain, 0), ) : array(); } - return new \Twig_Node_Expression_Filter( - new \Twig_Node_Expression_Constant($message, 0), - new \Twig_Node_Expression_Constant('transchoice', 0), - new \Twig_Node($arguments), + return new FilterExpression( + new ConstantExpression($message, 0), + new ConstantExpression('transchoice', 0), + new Node($arguments), 0 ); } @@ -67,15 +74,15 @@ public static function getTransChoiceFilter($message, $domain = null, $arguments public static function getTransTag($message, $domain = null) { return new TransNode( - new \Twig_Node_Body(array(), array('data' => $message)), - $domain ? new \Twig_Node_Expression_Constant($domain, 0) : null + new BodyNode(array(), array('data' => $message)), + $domain ? new ConstantExpression($domain, 0) : null ); } public static function getTransDefaultDomainTag($domain) { return new TransDefaultDomainNode( - new \Twig_Node_Expression_Constant($domain, 0) + new ConstantExpression($domain, 0) ); } } diff --git a/src/Symfony/Bridge/Twig/Tests/TokenParser/FormThemeTokenParserTest.php b/src/Symfony/Bridge/Twig/Tests/TokenParser/FormThemeTokenParserTest.php index 8931be061f9d2..0972b15e23fdc 100644 --- a/src/Symfony/Bridge/Twig/Tests/TokenParser/FormThemeTokenParserTest.php +++ b/src/Symfony/Bridge/Twig/Tests/TokenParser/FormThemeTokenParserTest.php @@ -14,6 +14,12 @@ use PHPUnit\Framework\TestCase; use Symfony\Bridge\Twig\TokenParser\FormThemeTokenParser; use Symfony\Bridge\Twig\Node\FormThemeNode; +use Twig\Environment; +use Twig\Node\Expression\ArrayExpression; +use Twig\Node\Expression\ConstantExpression; +use Twig\Node\Expression\NameExpression; +use Twig\Parser; +use Twig\Source; class FormThemeTokenParserTest extends TestCase { @@ -22,10 +28,10 @@ class FormThemeTokenParserTest extends TestCase */ public function testCompile($source, $expected) { - $env = new \Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock(), array('cache' => false, 'autoescape' => false, 'optimizations' => 0)); + $env = new Environment($this->getMockBuilder('Twig\Loader\LoaderInterface')->getMock(), array('cache' => false, 'autoescape' => false, 'optimizations' => 0)); $env->addTokenParser(new FormThemeTokenParser()); - $stream = $env->tokenize(new \Twig_Source($source, '')); - $parser = new \Twig_Parser($env); + $stream = $env->tokenize(new Source($source, '')); + $parser = new Parser($env); $this->assertEquals($expected, $parser->parse($stream)->getNode('body')->getNode(0)); } @@ -36,10 +42,10 @@ public function getTestsForFormTheme() array( '{% form_theme form "tpl1" %}', new FormThemeNode( - new \Twig_Node_Expression_Name('form', 1), - new \Twig_Node_Expression_Array(array( - new \Twig_Node_Expression_Constant(0, 1), - new \Twig_Node_Expression_Constant('tpl1', 1), + new NameExpression('form', 1), + new ArrayExpression(array( + new ConstantExpression(0, 1), + new ConstantExpression('tpl1', 1), ), 1), 1, 'form_theme' @@ -48,12 +54,12 @@ public function getTestsForFormTheme() array( '{% form_theme form "tpl1" "tpl2" %}', new FormThemeNode( - new \Twig_Node_Expression_Name('form', 1), - new \Twig_Node_Expression_Array(array( - new \Twig_Node_Expression_Constant(0, 1), - new \Twig_Node_Expression_Constant('tpl1', 1), - new \Twig_Node_Expression_Constant(1, 1), - new \Twig_Node_Expression_Constant('tpl2', 1), + new NameExpression('form', 1), + new ArrayExpression(array( + new ConstantExpression(0, 1), + new ConstantExpression('tpl1', 1), + new ConstantExpression(1, 1), + new ConstantExpression('tpl2', 1), ), 1), 1, 'form_theme' @@ -62,8 +68,8 @@ public function getTestsForFormTheme() array( '{% form_theme form with "tpl1" %}', new FormThemeNode( - new \Twig_Node_Expression_Name('form', 1), - new \Twig_Node_Expression_Constant('tpl1', 1), + new NameExpression('form', 1), + new ConstantExpression('tpl1', 1), 1, 'form_theme' ), @@ -71,10 +77,10 @@ public function getTestsForFormTheme() array( '{% form_theme form with ["tpl1"] %}', new FormThemeNode( - new \Twig_Node_Expression_Name('form', 1), - new \Twig_Node_Expression_Array(array( - new \Twig_Node_Expression_Constant(0, 1), - new \Twig_Node_Expression_Constant('tpl1', 1), + new NameExpression('form', 1), + new ArrayExpression(array( + new ConstantExpression(0, 1), + new ConstantExpression('tpl1', 1), ), 1), 1, 'form_theme' @@ -83,12 +89,12 @@ public function getTestsForFormTheme() array( '{% form_theme form with ["tpl1", "tpl2"] %}', new FormThemeNode( - new \Twig_Node_Expression_Name('form', 1), - new \Twig_Node_Expression_Array(array( - new \Twig_Node_Expression_Constant(0, 1), - new \Twig_Node_Expression_Constant('tpl1', 1), - new \Twig_Node_Expression_Constant(1, 1), - new \Twig_Node_Expression_Constant('tpl2', 1), + new NameExpression('form', 1), + new ArrayExpression(array( + new ConstantExpression(0, 1), + new ConstantExpression('tpl1', 1), + new ConstantExpression(1, 1), + new ConstantExpression('tpl2', 1), ), 1), 1, 'form_theme' diff --git a/src/Symfony/Bridge/Twig/Tests/Translation/TwigExtractorTest.php b/src/Symfony/Bridge/Twig/Tests/Translation/TwigExtractorTest.php index 0b1fb28b0e10c..013598a40b17f 100644 --- a/src/Symfony/Bridge/Twig/Tests/Translation/TwigExtractorTest.php +++ b/src/Symfony/Bridge/Twig/Tests/Translation/TwigExtractorTest.php @@ -15,6 +15,9 @@ use Symfony\Bridge\Twig\Extension\TranslationExtension; use Symfony\Bridge\Twig\Translation\TwigExtractor; use Symfony\Component\Translation\MessageCatalogue; +use Twig\Environment; +use Twig\Error\Error; +use Twig\Loader\ArrayLoader; class TwigExtractorTest extends TestCase { @@ -23,8 +26,8 @@ class TwigExtractorTest extends TestCase */ public function testExtract($template, $messages) { - $loader = $this->getMockBuilder('Twig_LoaderInterface')->getMock(); - $twig = new \Twig_Environment($loader, array( + $loader = $this->getMockBuilder('Twig\Loader\LoaderInterface')->getMock(); + $twig = new Environment($loader, array( 'strict_variables' => true, 'debug' => true, 'cache' => false, @@ -73,19 +76,19 @@ public function getExtractData() } /** - * @expectedException \Twig_Error + * @expectedException \Twig\Error\Error * @dataProvider resourcesWithSyntaxErrorsProvider */ public function testExtractSyntaxError($resources) { - $twig = new \Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock()); + $twig = new Environment($this->getMockBuilder('Twig\Loader\LoaderInterface')->getMock()); $twig->addExtension(new TranslationExtension($this->getMockBuilder('Symfony\Component\Translation\TranslatorInterface')->getMock())); $extractor = new TwigExtractor($twig); try { $extractor->extract($resources, new MessageCatalogue('en')); - } catch (\Twig_Error $e) { + } catch (Error $e) { if (method_exists($e, 'getSourceContext')) { $this->assertSame(dirname(__DIR__).strtr('/Fixtures/extractor/syntax_error.twig', '/', DIRECTORY_SEPARATOR), $e->getFile()); $this->assertSame(1, $e->getLine()); @@ -114,8 +117,8 @@ public function resourcesWithSyntaxErrorsProvider() */ public function testExtractWithFiles($resource) { - $loader = new \Twig_Loader_Array(array()); - $twig = new \Twig_Environment($loader, array( + $loader = new ArrayLoader(array()); + $twig = new Environment($loader, array( 'strict_variables' => true, 'debug' => true, 'cache' => false, diff --git a/src/Symfony/Bridge/Twig/Tests/TwigEngineTest.php b/src/Symfony/Bridge/Twig/Tests/TwigEngineTest.php index e2082df3dd75b..a74c59e8d28c9 100644 --- a/src/Symfony/Bridge/Twig/Tests/TwigEngineTest.php +++ b/src/Symfony/Bridge/Twig/Tests/TwigEngineTest.php @@ -14,6 +14,8 @@ use PHPUnit\Framework\TestCase; use Symfony\Bridge\Twig\TwigEngine; use Symfony\Component\Templating\TemplateReference; +use Twig\Environment; +use Twig\Loader\ArrayLoader; class TwigEngineTest extends TestCase { @@ -21,7 +23,7 @@ public function testExistsWithTemplateInstances() { $engine = $this->getTwig(); - $this->assertTrue($engine->exists($this->getMockForAbstractClass('Twig_Template', array(), '', false))); + $this->assertTrue($engine->exists($this->getMockForAbstractClass('Twig\Template', array(), '', false))); } public function testExistsWithNonExistentTemplates() @@ -57,7 +59,7 @@ public function testRender() } /** - * @expectedException \Twig_Error_Syntax + * @expectedException \Twig\Error\SyntaxError */ public function testRenderWithError() { @@ -68,7 +70,7 @@ public function testRenderWithError() protected function getTwig() { - $twig = new \Twig_Environment(new \Twig_Loader_Array(array( + $twig = new Environment(new ArrayLoader(array( 'index' => 'foo', 'error' => '{{ foo }', ))); diff --git a/src/Symfony/Bridge/Twig/TokenParser/DumpTokenParser.php b/src/Symfony/Bridge/Twig/TokenParser/DumpTokenParser.php index 269ead64f5d40..7cdbb77b4349b 100644 --- a/src/Symfony/Bridge/Twig/TokenParser/DumpTokenParser.php +++ b/src/Symfony/Bridge/Twig/TokenParser/DumpTokenParser.php @@ -12,6 +12,8 @@ namespace Symfony\Bridge\Twig\TokenParser; use Symfony\Bridge\Twig\Node\DumpNode; +use Twig\Token; +use Twig\TokenParser\AbstractTokenParser; /** * Token Parser for the 'dump' tag. @@ -25,18 +27,18 @@ * * @author Julien Galenski */ -class DumpTokenParser extends \Twig_TokenParser +class DumpTokenParser extends AbstractTokenParser { /** * {@inheritdoc} */ - public function parse(\Twig_Token $token) + public function parse(Token $token) { $values = null; - if (!$this->parser->getStream()->test(\Twig_Token::BLOCK_END_TYPE)) { + if (!$this->parser->getStream()->test(Token::BLOCK_END_TYPE)) { $values = $this->parser->getExpressionParser()->parseMultitargetExpression(); } - $this->parser->getStream()->expect(\Twig_Token::BLOCK_END_TYPE); + $this->parser->getStream()->expect(Token::BLOCK_END_TYPE); return new DumpNode($this->parser->getVarName(), $values, $token->getLine(), $this->getTag()); } diff --git a/src/Symfony/Bridge/Twig/TokenParser/FormThemeTokenParser.php b/src/Symfony/Bridge/Twig/TokenParser/FormThemeTokenParser.php index daf87824e7b21..12c2541851e63 100644 --- a/src/Symfony/Bridge/Twig/TokenParser/FormThemeTokenParser.php +++ b/src/Symfony/Bridge/Twig/TokenParser/FormThemeTokenParser.php @@ -12,39 +12,43 @@ namespace Symfony\Bridge\Twig\TokenParser; use Symfony\Bridge\Twig\Node\FormThemeNode; +use Twig\Node\Expression\ArrayExpression; +use Twig\Node\Node; +use Twig\Token; +use Twig\TokenParser\AbstractTokenParser; /** * Token Parser for the 'form_theme' tag. * * @author Fabien Potencier */ -class FormThemeTokenParser extends \Twig_TokenParser +class FormThemeTokenParser extends AbstractTokenParser { /** * Parses a token and returns a node. * - * @param \Twig_Token $token A Twig_Token instance + * @param Token $token * - * @return \Twig_Node A Twig_Node instance + * @return Node */ - public function parse(\Twig_Token $token) + public function parse(Token $token) { $lineno = $token->getLine(); $stream = $this->parser->getStream(); $form = $this->parser->getExpressionParser()->parseExpression(); - if ($this->parser->getStream()->test(\Twig_Token::NAME_TYPE, 'with')) { + if ($this->parser->getStream()->test(Token::NAME_TYPE, 'with')) { $this->parser->getStream()->next(); $resources = $this->parser->getExpressionParser()->parseExpression(); } else { - $resources = new \Twig_Node_Expression_Array(array(), $stream->getCurrent()->getLine()); + $resources = new ArrayExpression(array(), $stream->getCurrent()->getLine()); do { $resources->addElement($this->parser->getExpressionParser()->parseExpression()); - } while (!$stream->test(\Twig_Token::BLOCK_END_TYPE)); + } while (!$stream->test(Token::BLOCK_END_TYPE)); } - $stream->expect(\Twig_Token::BLOCK_END_TYPE); + $stream->expect(Token::BLOCK_END_TYPE); return new FormThemeNode($form, $resources, $lineno, $this->getTag()); } diff --git a/src/Symfony/Bridge/Twig/TokenParser/StopwatchTokenParser.php b/src/Symfony/Bridge/Twig/TokenParser/StopwatchTokenParser.php index 2983e4cb6b03b..82c58d40bbf8d 100644 --- a/src/Symfony/Bridge/Twig/TokenParser/StopwatchTokenParser.php +++ b/src/Symfony/Bridge/Twig/TokenParser/StopwatchTokenParser.php @@ -12,13 +12,16 @@ namespace Symfony\Bridge\Twig\TokenParser; use Symfony\Bridge\Twig\Node\StopwatchNode; +use Twig\Node\Expression\AssignNameExpression; +use Twig\Token; +use Twig\TokenParser\AbstractTokenParser; /** * Token Parser for the stopwatch tag. * * @author Wouter J */ -class StopwatchTokenParser extends \Twig_TokenParser +class StopwatchTokenParser extends AbstractTokenParser { protected $stopwatchIsAvailable; @@ -27,7 +30,7 @@ public function __construct($stopwatchIsAvailable) $this->stopwatchIsAvailable = $stopwatchIsAvailable; } - public function parse(\Twig_Token $token) + public function parse(Token $token) { $lineno = $token->getLine(); $stream = $this->parser->getStream(); @@ -35,20 +38,20 @@ public function parse(\Twig_Token $token) // {% stopwatch 'bar' %} $name = $this->parser->getExpressionParser()->parseExpression(); - $stream->expect(\Twig_Token::BLOCK_END_TYPE); + $stream->expect(Token::BLOCK_END_TYPE); // {% endstopwatch %} $body = $this->parser->subparse(array($this, 'decideStopwatchEnd'), true); - $stream->expect(\Twig_Token::BLOCK_END_TYPE); + $stream->expect(Token::BLOCK_END_TYPE); if ($this->stopwatchIsAvailable) { - return new StopwatchNode($name, $body, new \Twig_Node_Expression_AssignName($this->parser->getVarName(), $token->getLine()), $lineno, $this->getTag()); + return new StopwatchNode($name, $body, new AssignNameExpression($this->parser->getVarName(), $token->getLine()), $lineno, $this->getTag()); } return $body; } - public function decideStopwatchEnd(\Twig_Token $token) + public function decideStopwatchEnd(Token $token) { return $token->test('endstopwatch'); } diff --git a/src/Symfony/Bridge/Twig/TokenParser/TransChoiceTokenParser.php b/src/Symfony/Bridge/Twig/TokenParser/TransChoiceTokenParser.php index fa61a2f1486c5..2b4a9f3fc4636 100644 --- a/src/Symfony/Bridge/Twig/TokenParser/TransChoiceTokenParser.php +++ b/src/Symfony/Bridge/Twig/TokenParser/TransChoiceTokenParser.php @@ -12,6 +12,12 @@ namespace Symfony\Bridge\Twig\TokenParser; use Symfony\Bridge\Twig\Node\TransNode; +use Twig\Error\SyntaxError; +use Twig\Node\Expression\AbstractExpression; +use Twig\Node\Expression\ArrayExpression; +use Twig\Node\Node; +use Twig\Node\TextNode; +use Twig\Token; /** * Token Parser for the 'transchoice' tag. @@ -23,18 +29,18 @@ class TransChoiceTokenParser extends TransTokenParser /** * Parses a token and returns a node. * - * @param \Twig_Token $token A Twig_Token instance + * @param Token $token * - * @return \Twig_Node A Twig_Node instance + * @return Node * - * @throws \Twig_Error_Syntax + * @throws SyntaxError */ - public function parse(\Twig_Token $token) + public function parse(Token $token) { $lineno = $token->getLine(); $stream = $this->parser->getStream(); - $vars = new \Twig_Node_Expression_Array(array(), $lineno); + $vars = new ArrayExpression(array(), $lineno); $count = $this->parser->getExpressionParser()->parseExpression(); @@ -59,15 +65,15 @@ public function parse(\Twig_Token $token) $locale = $this->parser->getExpressionParser()->parseExpression(); } - $stream->expect(\Twig_Token::BLOCK_END_TYPE); + $stream->expect(Token::BLOCK_END_TYPE); $body = $this->parser->subparse(array($this, 'decideTransChoiceFork'), true); - if (!$body instanceof \Twig_Node_Text && !$body instanceof \Twig_Node_Expression) { - throw new \Twig_Error_Syntax('A message inside a transchoice tag must be a simple text.', $body->getTemplateLine(), $stream->getSourceContext()->getName()); + if (!$body instanceof TextNode && !$body instanceof AbstractExpression) { + throw new SyntaxError('A message inside a transchoice tag must be a simple text.', $body->getTemplateLine(), $stream->getSourceContext()->getName()); } - $stream->expect(\Twig_Token::BLOCK_END_TYPE); + $stream->expect(Token::BLOCK_END_TYPE); return new TransNode($body, $domain, $count, $vars, $locale, $lineno, $this->getTag()); } diff --git a/src/Symfony/Bridge/Twig/TokenParser/TransDefaultDomainTokenParser.php b/src/Symfony/Bridge/Twig/TokenParser/TransDefaultDomainTokenParser.php index 09832ea972d91..4096a011a300d 100644 --- a/src/Symfony/Bridge/Twig/TokenParser/TransDefaultDomainTokenParser.php +++ b/src/Symfony/Bridge/Twig/TokenParser/TransDefaultDomainTokenParser.php @@ -12,26 +12,29 @@ namespace Symfony\Bridge\Twig\TokenParser; use Symfony\Bridge\Twig\Node\TransDefaultDomainNode; +use Twig\Node\Node; +use Twig\Token; +use Twig\TokenParser\AbstractTokenParser; /** * Token Parser for the 'trans_default_domain' tag. * * @author Fabien Potencier */ -class TransDefaultDomainTokenParser extends \Twig_TokenParser +class TransDefaultDomainTokenParser extends AbstractTokenParser { /** * Parses a token and returns a node. * - * @param \Twig_Token $token A Twig_Token instance + * @param Token $token * - * @return \Twig_Node A Twig_Node instance + * @return Node */ - public function parse(\Twig_Token $token) + public function parse(Token $token) { $expr = $this->parser->getExpressionParser()->parseExpression(); - $this->parser->getStream()->expect(\Twig_Token::BLOCK_END_TYPE); + $this->parser->getStream()->expect(Token::BLOCK_END_TYPE); return new TransDefaultDomainNode($expr, $token->getLine(), $this->getTag()); } diff --git a/src/Symfony/Bridge/Twig/TokenParser/TransTokenParser.php b/src/Symfony/Bridge/Twig/TokenParser/TransTokenParser.php index 4c8e7d3eeea38..848a080710fa1 100644 --- a/src/Symfony/Bridge/Twig/TokenParser/TransTokenParser.php +++ b/src/Symfony/Bridge/Twig/TokenParser/TransTokenParser.php @@ -12,32 +12,39 @@ namespace Symfony\Bridge\Twig\TokenParser; use Symfony\Bridge\Twig\Node\TransNode; +use Twig\Error\SyntaxError; +use Twig\Node\Expression\AbstractExpression; +use Twig\Node\Expression\ArrayExpression; +use Twig\Node\Node; +use Twig\Node\TextNode; +use Twig\Token; +use Twig\TokenParser\AbstractTokenParser; /** * Token Parser for the 'trans' tag. * * @author Fabien Potencier */ -class TransTokenParser extends \Twig_TokenParser +class TransTokenParser extends AbstractTokenParser { /** * Parses a token and returns a node. * - * @param \Twig_Token $token A Twig_Token instance + * @param Token $token * - * @return \Twig_Node A Twig_Node instance + * @return Node * - * @throws \Twig_Error_Syntax + * @throws SyntaxError */ - public function parse(\Twig_Token $token) + public function parse(Token $token) { $lineno = $token->getLine(); $stream = $this->parser->getStream(); - $vars = new \Twig_Node_Expression_Array(array(), $lineno); + $vars = new ArrayExpression(array(), $lineno); $domain = null; $locale = null; - if (!$stream->test(\Twig_Token::BLOCK_END_TYPE)) { + if (!$stream->test(Token::BLOCK_END_TYPE)) { if ($stream->test('with')) { // {% trans with vars %} $stream->next(); @@ -54,20 +61,20 @@ public function parse(\Twig_Token $token) // {% trans into "fr" %} $stream->next(); $locale = $this->parser->getExpressionParser()->parseExpression(); - } elseif (!$stream->test(\Twig_Token::BLOCK_END_TYPE)) { - throw new \Twig_Error_Syntax('Unexpected token. Twig was looking for the "with", "from", or "into" keyword.', $stream->getCurrent()->getLine(), $stream->getSourceContext()->getName()); + } elseif (!$stream->test(Token::BLOCK_END_TYPE)) { + throw new SyntaxError('Unexpected token. Twig was looking for the "with", "from", or "into" keyword.', $stream->getCurrent()->getLine(), $stream->getSourceContext()->getName()); } } // {% trans %}message{% endtrans %} - $stream->expect(\Twig_Token::BLOCK_END_TYPE); + $stream->expect(Token::BLOCK_END_TYPE); $body = $this->parser->subparse(array($this, 'decideTransFork'), true); - if (!$body instanceof \Twig_Node_Text && !$body instanceof \Twig_Node_Expression) { - throw new \Twig_Error_Syntax('A message inside a trans tag must be a simple text.', $body->getTemplateLine(), $stream->getSourceContext()->getName()); + if (!$body instanceof TextNode && !$body instanceof AbstractExpression) { + throw new SyntaxError('A message inside a trans tag must be a simple text.', $body->getTemplateLine(), $stream->getSourceContext()->getName()); } - $stream->expect(\Twig_Token::BLOCK_END_TYPE); + $stream->expect(Token::BLOCK_END_TYPE); return new TransNode($body, $domain, null, $vars, $locale, $lineno, $this->getTag()); } diff --git a/src/Symfony/Bridge/Twig/Translation/TwigExtractor.php b/src/Symfony/Bridge/Twig/Translation/TwigExtractor.php index 35995dbd64518..bd35fe5a8b1eb 100644 --- a/src/Symfony/Bridge/Twig/Translation/TwigExtractor.php +++ b/src/Symfony/Bridge/Twig/Translation/TwigExtractor.php @@ -16,6 +16,9 @@ use Symfony\Component\Translation\Extractor\AbstractFileExtractor; use Symfony\Component\Translation\Extractor\ExtractorInterface; use Symfony\Component\Translation\MessageCatalogue; +use Twig\Environment; +use Twig\Error\Error; +use Twig\Source; /** * TwigExtractor extracts translation messages from a twig template. @@ -42,11 +45,11 @@ class TwigExtractor extends AbstractFileExtractor implements ExtractorInterface /** * The twig environment. * - * @var \Twig_Environment + * @var Environment */ private $twig; - public function __construct(\Twig_Environment $twig) + public function __construct(Environment $twig) { $this->twig = $twig; } @@ -60,12 +63,12 @@ public function extract($resource, MessageCatalogue $catalogue) foreach ($files as $file) { try { $this->extractTemplate(file_get_contents($file->getPathname()), $catalogue); - } catch (\Twig_Error $e) { + } catch (Error $e) { if ($file instanceof \SplFileInfo) { $path = $file->getRealPath() ?: $file->getPathname(); $name = $file instanceof SplFileInfo ? $file->getRelativePathname() : $path; if (method_exists($e, 'setSourceContext')) { - $e->setSourceContext(new \Twig_Source('', $name, $path)); + $e->setSourceContext(new Source('', $name, $path)); } else { $e->setTemplateName($name); } @@ -89,7 +92,7 @@ protected function extractTemplate($template, MessageCatalogue $catalogue) $visitor = $this->twig->getExtension('Symfony\Bridge\Twig\Extension\TranslationExtension')->getTranslationNodeVisitor(); $visitor->enable(); - $this->twig->parse($this->twig->tokenize(new \Twig_Source($template, ''))); + $this->twig->parse($this->twig->tokenize(new Source($template, ''))); foreach ($visitor->getMessages() as $message) { $catalogue->set(trim($message[0]), $this->prefix.trim($message[0]), $message[1] ?: $this->defaultDomain); diff --git a/src/Symfony/Bridge/Twig/TwigEngine.php b/src/Symfony/Bridge/Twig/TwigEngine.php index 760461b5be578..bc0a4fecc9af5 100644 --- a/src/Symfony/Bridge/Twig/TwigEngine.php +++ b/src/Symfony/Bridge/Twig/TwigEngine.php @@ -15,6 +15,11 @@ use Symfony\Component\Templating\StreamingEngineInterface; use Symfony\Component\Templating\TemplateNameParserInterface; use Symfony\Component\Templating\TemplateReferenceInterface; +use Twig\Environment; +use Twig\Error\Error; +use Twig\Error\LoaderError; +use Twig\Loader\ExistsLoaderInterface; +use Twig\Template; /** * This engine knows how to render Twig templates. @@ -26,13 +31,7 @@ class TwigEngine implements EngineInterface, StreamingEngineInterface protected $environment; protected $parser; - /** - * Constructor. - * - * @param \Twig_Environment $environment A \Twig_Environment instance - * @param TemplateNameParserInterface $parser A TemplateNameParserInterface instance - */ - public function __construct(\Twig_Environment $environment, TemplateNameParserInterface $parser) + public function __construct(Environment $environment, TemplateNameParserInterface $parser) { $this->environment = $environment; $this->parser = $parser; @@ -41,9 +40,9 @@ public function __construct(\Twig_Environment $environment, TemplateNameParserIn /** * {@inheritdoc} * - * It also supports \Twig_Template as name parameter. + * It also supports Template as name parameter. * - * @throws \Twig_Error if something went wrong like a thrown exception while rendering the template + * @throws Error if something went wrong like a thrown exception while rendering the template */ public function render($name, array $parameters = array()) { @@ -53,9 +52,9 @@ public function render($name, array $parameters = array()) /** * {@inheritdoc} * - * It also supports \Twig_Template as name parameter. + * It also supports Template as name parameter. * - * @throws \Twig_Error if something went wrong like a thrown exception while rendering the template + * @throws Error if something went wrong like a thrown exception while rendering the template */ public function stream($name, array $parameters = array()) { @@ -65,25 +64,25 @@ public function stream($name, array $parameters = array()) /** * {@inheritdoc} * - * It also supports \Twig_Template as name parameter. + * It also supports Template as name parameter. */ public function exists($name) { - if ($name instanceof \Twig_Template) { + if ($name instanceof Template) { return true; } $loader = $this->environment->getLoader(); - if ($loader instanceof \Twig_ExistsLoaderInterface || method_exists($loader, 'exists')) { + if ($loader instanceof ExistsLoaderInterface || method_exists($loader, 'exists')) { return $loader->exists((string) $name); } try { // cast possible TemplateReferenceInterface to string because the - // EngineInterface supports them but Twig_LoaderInterface does not + // EngineInterface supports them but LoaderInterface does not $loader->getSourceContext((string) $name)->getCode(); - } catch (\Twig_Error_Loader $e) { + } catch (LoaderError $e) { return false; } @@ -93,11 +92,11 @@ public function exists($name) /** * {@inheritdoc} * - * It also supports \Twig_Template as name parameter. + * It also supports Template as name parameter. */ public function supports($name) { - if ($name instanceof \Twig_Template) { + if ($name instanceof Template) { return true; } @@ -109,22 +108,22 @@ public function supports($name) /** * Loads the given template. * - * @param string|TemplateReferenceInterface|\Twig_Template $name A template name or an instance of - * TemplateReferenceInterface or \Twig_Template + * @param string|TemplateReferenceInterface|Template $name A template name or an instance of + * TemplateReferenceInterface or Template * - * @return \Twig_Template A \Twig_Template instance + * @return Template * * @throws \InvalidArgumentException if the template does not exist */ protected function load($name) { - if ($name instanceof \Twig_Template) { + if ($name instanceof Template) { return $name; } try { return $this->environment->loadTemplate((string) $name); - } catch (\Twig_Error_Loader $e) { + } catch (LoaderError $e) { throw new \InvalidArgumentException($e->getMessage(), $e->getCode(), $e); } } diff --git a/src/Symfony/Bridge/Twig/composer.json b/src/Symfony/Bridge/Twig/composer.json index 3bc0aa6d0cddf..3b6c4356e14ba 100644 --- a/src/Symfony/Bridge/Twig/composer.json +++ b/src/Symfony/Bridge/Twig/composer.json @@ -17,7 +17,7 @@ ], "require": { "php": ">=5.3.9", - "twig/twig": "~1.28|~2.0" + "twig/twig": "~1.34|~2.4" }, "require-dev": { "symfony/asset": "~2.7", diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fragment/LegacyContainerAwareHIncludeFragmentRendererTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Fragment/LegacyContainerAwareHIncludeFragmentRendererTest.php index cc85cdb02acb2..5fca1cc8b4674 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Fragment/LegacyContainerAwareHIncludeFragmentRendererTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fragment/LegacyContainerAwareHIncludeFragmentRendererTest.php @@ -25,7 +25,7 @@ public function testRender() $container = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerInterface')->getMock(); $container->expects($this->once()) ->method('get') - ->will($this->returnValue($this->getMockBuilder('\Twig_Environment')->disableOriginalConstructor()->getMock())) + ->will($this->returnValue($this->getMockBuilder('Twig\Environment')->disableOriginalConstructor()->getMock())) ; $renderer = new ContainerAwareHIncludeFragmentRenderer($container); $renderer->render('/', Request::create('/')); diff --git a/src/Symfony/Bundle/FrameworkBundle/composer.json b/src/Symfony/Bundle/FrameworkBundle/composer.json index ad1560ad179ee..76648774f3baa 100644 --- a/src/Symfony/Bundle/FrameworkBundle/composer.json +++ b/src/Symfony/Bundle/FrameworkBundle/composer.json @@ -24,7 +24,7 @@ "symfony/event-dispatcher": "~2.5", "symfony/finder": "^2.0.5", "symfony/http-foundation": "~2.7", - "symfony/http-kernel": "~2.7.25|^2.8.18", + "symfony/http-kernel": "~2.7.29|^2.8.22", "symfony/filesystem": "~2.3", "symfony/routing": "~2.7.24|^2.8.17", "symfony/security-core": "~2.6.13|~2.7.9|~2.8", diff --git a/src/Symfony/Bundle/SecurityBundle/Twig/Extension/LogoutUrlExtension.php b/src/Symfony/Bundle/SecurityBundle/Twig/Extension/LogoutUrlExtension.php index d1eae0ef20487..40c931795f659 100644 --- a/src/Symfony/Bundle/SecurityBundle/Twig/Extension/LogoutUrlExtension.php +++ b/src/Symfony/Bundle/SecurityBundle/Twig/Extension/LogoutUrlExtension.php @@ -14,6 +14,8 @@ @trigger_error('The '.__NAMESPACE__.'\LogoutUrlExtension class is deprecated since version 2.7 and will be removed in 3.0. Use Symfony\Bridge\Twig\Extension\LogoutUrlExtension instead.', E_USER_DEPRECATED); use Symfony\Bundle\SecurityBundle\Templating\Helper\LogoutUrlHelper; +use Twig\Extension\AbstractExtension; +use Twig\TwigFunction; /** * LogoutUrlHelper provides generator functions for the logout URL to Twig. @@ -22,7 +24,7 @@ * * @deprecated since version 2.7, to be removed in 3.0. Use Symfony\Bridge\Twig\Extension\LogoutUrlExtension instead. */ -class LogoutUrlExtension extends \Twig_Extension +class LogoutUrlExtension extends AbstractExtension { private $helper; @@ -37,8 +39,8 @@ public function __construct(LogoutUrlHelper $helper) public function getFunctions() { return array( - new \Twig_SimpleFunction('logout_url', array($this, 'getLogoutUrl')), - new \Twig_SimpleFunction('logout_path', array($this, 'getLogoutPath')), + new TwigFunction('logout_url', array($this, 'getLogoutUrl')), + new TwigFunction('logout_path', array($this, 'getLogoutPath')), ); } diff --git a/src/Symfony/Bundle/SecurityBundle/composer.json b/src/Symfony/Bundle/SecurityBundle/composer.json index 5251f0138aa56..3da10d429d4bf 100644 --- a/src/Symfony/Bundle/SecurityBundle/composer.json +++ b/src/Symfony/Bundle/SecurityBundle/composer.json @@ -37,7 +37,7 @@ "symfony/yaml": "^2.0.5", "symfony/expression-language": "~2.6", "doctrine/doctrine-bundle": "~1.2", - "twig/twig": "~1.28|~2.0", + "twig/twig": "~1.34|~2.4", "ircmaxell/password-compat": "~1.0" }, "autoload": { diff --git a/src/Symfony/Bundle/TwigBundle/CacheWarmer/TemplateCacheCacheWarmer.php b/src/Symfony/Bundle/TwigBundle/CacheWarmer/TemplateCacheCacheWarmer.php index 8557a2f55aca1..e5be1d5234d53 100644 --- a/src/Symfony/Bundle/TwigBundle/CacheWarmer/TemplateCacheCacheWarmer.php +++ b/src/Symfony/Bundle/TwigBundle/CacheWarmer/TemplateCacheCacheWarmer.php @@ -14,6 +14,7 @@ use Symfony\Component\HttpKernel\CacheWarmer\CacheWarmerInterface; use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Bundle\FrameworkBundle\CacheWarmer\TemplateFinderInterface; +use Twig\Error\Error; /** * Generates the Twig cache for all templates. @@ -65,7 +66,7 @@ public function warmUp($cacheDir) try { $twig->loadTemplate($template); - } catch (\Twig_Error $e) { + } catch (Error $e) { // problem during compilation, give up } } diff --git a/src/Symfony/Bundle/TwigBundle/Controller/ExceptionController.php b/src/Symfony/Bundle/TwigBundle/Controller/ExceptionController.php index b6972fc6354cd..0eab87de26e2b 100644 --- a/src/Symfony/Bundle/TwigBundle/Controller/ExceptionController.php +++ b/src/Symfony/Bundle/TwigBundle/Controller/ExceptionController.php @@ -17,6 +17,9 @@ use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Templating\TemplateReferenceInterface; +use Twig\Environment; +use Twig\Error\LoaderError; +use Twig\Loader\ExistsLoaderInterface; /** * ExceptionController renders error or exception pages for a given @@ -34,7 +37,7 @@ class ExceptionController */ protected $debug; - public function __construct(\Twig_Environment $twig, $debug) + public function __construct(Environment $twig, $debug) { $this->twig = $twig; $this->debug = $debug; @@ -131,7 +134,7 @@ protected function templateExists($template) $template = (string) $template; $loader = $this->twig->getLoader(); - if ($loader instanceof \Twig_ExistsLoaderInterface || method_exists($loader, 'exists')) { + if ($loader instanceof ExistsLoaderInterface || method_exists($loader, 'exists')) { return $loader->exists($template); } @@ -139,7 +142,7 @@ protected function templateExists($template) $loader->getSourceContext($template)->getCode(); return true; - } catch (\Twig_Error_Loader $e) { + } catch (LoaderError $e) { } return false; diff --git a/src/Symfony/Bundle/TwigBundle/Debug/TimedTwigEngine.php b/src/Symfony/Bundle/TwigBundle/Debug/TimedTwigEngine.php index e09479a2845ff..40f209999a635 100644 --- a/src/Symfony/Bundle/TwigBundle/Debug/TimedTwigEngine.php +++ b/src/Symfony/Bundle/TwigBundle/Debug/TimedTwigEngine.php @@ -17,6 +17,7 @@ use Symfony\Component\Templating\TemplateNameParserInterface; use Symfony\Component\Stopwatch\Stopwatch; use Symfony\Component\Config\FileLocatorInterface; +use Twig\Environment; /** * Times the time spent to render a template. @@ -29,15 +30,7 @@ class TimedTwigEngine extends TwigEngine { protected $stopwatch; - /** - * Constructor. - * - * @param \Twig_Environment $environment A \Twig_Environment instance - * @param TemplateNameParserInterface $parser A TemplateNameParserInterface instance - * @param FileLocatorInterface $locator A FileLocatorInterface instance - * @param Stopwatch $stopwatch A Stopwatch instance - */ - public function __construct(\Twig_Environment $environment, TemplateNameParserInterface $parser, FileLocatorInterface $locator, Stopwatch $stopwatch) + public function __construct(Environment $environment, TemplateNameParserInterface $parser, FileLocatorInterface $locator, Stopwatch $stopwatch) { parent::__construct($environment, $parser, $locator); diff --git a/src/Symfony/Bundle/TwigBundle/DependencyInjection/Configuration.php b/src/Symfony/Bundle/TwigBundle/DependencyInjection/Configuration.php index 008f9b7e769dd..1c27fe1c04af4 100644 --- a/src/Symfony/Bundle/TwigBundle/DependencyInjection/Configuration.php +++ b/src/Symfony/Bundle/TwigBundle/DependencyInjection/Configuration.php @@ -170,7 +170,7 @@ private function addTwigOptions(ArrayNodeDefinition $rootNode) ->variableNode('autoescape')->defaultValue('name')->end() ->scalarNode('autoescape_service')->defaultNull()->end() ->scalarNode('autoescape_service_method')->defaultNull()->end() - ->scalarNode('base_template_class')->example('Twig_Template')->cannotBeEmpty()->end() + ->scalarNode('base_template_class')->example('Twig\Template')->cannotBeEmpty()->end() ->scalarNode('cache')->defaultValue('%kernel.cache_dir%/twig')->end() ->scalarNode('charset')->defaultValue('%kernel.charset%')->end() ->booleanNode('debug')->defaultValue('%kernel.debug%')->end() diff --git a/src/Symfony/Bundle/TwigBundle/DependencyInjection/Configurator/EnvironmentConfigurator.php b/src/Symfony/Bundle/TwigBundle/DependencyInjection/Configurator/EnvironmentConfigurator.php index bf37559b9920c..1612b6eb5fec2 100644 --- a/src/Symfony/Bundle/TwigBundle/DependencyInjection/Configurator/EnvironmentConfigurator.php +++ b/src/Symfony/Bundle/TwigBundle/DependencyInjection/Configurator/EnvironmentConfigurator.php @@ -11,6 +11,11 @@ namespace Symfony\Bundle\TwigBundle\DependencyInjection\Configurator; +use Twig\Environment; + +// BC/FC with namespaced Twig +class_exists('Twig\Environment'); + /** * Twig environment configurator. * @@ -35,14 +40,14 @@ public function __construct($dateFormat, $intervalFormat, $timezone, $decimals, $this->thousandsSeparator = $thousandsSeparator; } - public function configure(\Twig_Environment $environment) + public function configure(Environment $environment) { - $environment->getExtension('Twig_Extension_Core')->setDateFormat($this->dateFormat, $this->intervalFormat); + $environment->getExtension('Twig\Extension\CoreExtension')->setDateFormat($this->dateFormat, $this->intervalFormat); if (null !== $this->timezone) { - $environment->getExtension('Twig_Extension_Core')->setTimezone($this->timezone); + $environment->getExtension('Twig\Extension\CoreExtension')->setTimezone($this->timezone); } - $environment->getExtension('Twig_Extension_Core')->setNumberFormat($this->decimals, $this->decimalPoint, $this->thousandsSeparator); + $environment->getExtension('Twig\Extension\CoreExtension')->setNumberFormat($this->decimals, $this->decimalPoint, $this->thousandsSeparator); } } diff --git a/src/Symfony/Bundle/TwigBundle/Extension/ActionsExtension.php b/src/Symfony/Bundle/TwigBundle/Extension/ActionsExtension.php index 8b4759ea270a8..5fee94d07c099 100644 --- a/src/Symfony/Bundle/TwigBundle/Extension/ActionsExtension.php +++ b/src/Symfony/Bundle/TwigBundle/Extension/ActionsExtension.php @@ -14,6 +14,8 @@ use Symfony\Bundle\TwigBundle\TokenParser\RenderTokenParser; use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\HttpKernel\Fragment\FragmentHandler; +use Twig\Extension\AbstractExtension; +use Twig\TokenParser\AbstractTokenParser; /** * Twig extension for Symfony actions helper. @@ -22,7 +24,7 @@ * * @deprecated since version 2.2, to be removed in 3.0. */ -class ActionsExtension extends \Twig_Extension +class ActionsExtension extends AbstractExtension { private $handler; @@ -69,7 +71,7 @@ public function renderUri($uri, array $options = array()) /** * Returns the token parser instance to add to the existing list. * - * @return array An array of \Twig_TokenParser instances + * @return AbstractTokenParser[] */ public function getTokenParsers() { diff --git a/src/Symfony/Bundle/TwigBundle/Extension/AssetsExtension.php b/src/Symfony/Bundle/TwigBundle/Extension/AssetsExtension.php index 976086920e07b..892e9cc739012 100644 --- a/src/Symfony/Bundle/TwigBundle/Extension/AssetsExtension.php +++ b/src/Symfony/Bundle/TwigBundle/Extension/AssetsExtension.php @@ -11,10 +11,12 @@ namespace Symfony\Bundle\TwigBundle\Extension; +@trigger_error('The '.__NAMESPACE__.'\AssetsExtension class is deprecated since version 2.7 and will be removed in 3.0. Use the Symfony\Bridge\Twig\Extension\AssetExtension class instead.', E_USER_DEPRECATED); + use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\Routing\RequestContext; - -@trigger_error('The '.__NAMESPACE__.'\AssetsExtension class is deprecated since version 2.7 and will be removed in 3.0. Use the Symfony\Bridge\Twig\Extension\AssetExtension class instead.', E_USER_DEPRECATED); +use Twig\Extension\AbstractExtension; +use Twig\TwigFunction; /** * Twig extension for Symfony assets helper. @@ -23,7 +25,7 @@ * * @deprecated since 2.7, to be removed in 3.0. Use Symfony\Bridge\Twig\Extension\AssetExtension instead. */ -class AssetsExtension extends \Twig_Extension +class AssetsExtension extends AbstractExtension { private $container; private $context; @@ -42,8 +44,8 @@ public function __construct(ContainerInterface $container, RequestContext $reque public function getFunctions() { return array( - new \Twig_SimpleFunction('asset', array($this, 'getAssetUrl')), - new \Twig_SimpleFunction('assets_version', array($this, 'getAssetsVersion')), + new TwigFunction('asset', array($this, 'getAssetUrl')), + new TwigFunction('assets_version', array($this, 'getAssetsVersion')), ); } diff --git a/src/Symfony/Bundle/TwigBundle/Loader/FilesystemLoader.php b/src/Symfony/Bundle/TwigBundle/Loader/FilesystemLoader.php index 53fe300e29a62..68a7b4560c95d 100644 --- a/src/Symfony/Bundle/TwigBundle/Loader/FilesystemLoader.php +++ b/src/Symfony/Bundle/TwigBundle/Loader/FilesystemLoader.php @@ -14,6 +14,8 @@ use Symfony\Component\Config\FileLocatorInterface; use Symfony\Component\Templating\TemplateNameParserInterface; use Symfony\Component\Templating\TemplateReferenceInterface; +use Twig\Error\LoaderError; +use Twig\Loader\FilesystemLoader as BaseFilesystemLoader; /** * FilesystemLoader extends the default Twig filesystem loader @@ -21,7 +23,7 @@ * * @author Fabien Potencier */ -class FilesystemLoader extends \Twig_Loader_Filesystem +class FilesystemLoader extends BaseFilesystemLoader { protected $locator; protected $parser; @@ -58,11 +60,11 @@ public function exists($name) * Otherwise the template is located using the locator from the twig library. * * @param string|TemplateReferenceInterface $template The template - * @param bool $throw When true, a \Twig_Error_Loader exception will be thrown if a template could not be found + * @param bool $throw When true, a LoaderError exception will be thrown if a template could not be found * * @return string The path to the template file * - * @throws \Twig_Error_Loader if the template could not be found + * @throws LoaderError if the template could not be found */ protected function findTemplate($template, $throw = true) { @@ -76,7 +78,7 @@ protected function findTemplate($template, $throw = true) $previous = null; try { $file = parent::findTemplate($logicalName); - } catch (\Twig_Error_Loader $e) { + } catch (LoaderError $e) { $twigLoaderException = $e; // for BC diff --git a/src/Symfony/Bundle/TwigBundle/Node/RenderNode.php b/src/Symfony/Bundle/TwigBundle/Node/RenderNode.php index 4e3b12dae1978..e9a378f399139 100644 --- a/src/Symfony/Bundle/TwigBundle/Node/RenderNode.php +++ b/src/Symfony/Bundle/TwigBundle/Node/RenderNode.php @@ -11,6 +11,10 @@ namespace Symfony\Bundle\TwigBundle\Node; +use Twig\Compiler; +use Twig\Node\Expression\AbstractExpression; +use Twig\Node\Node; + /** * Represents a render node. * @@ -18,19 +22,14 @@ * * @deprecated since version 2.2, to be removed in 3.0. */ -class RenderNode extends \Twig_Node +class RenderNode extends Node { - public function __construct(\Twig_Node_Expression $expr, \Twig_Node_Expression $options, $lineno, $tag = null) + public function __construct(AbstractExpression $expr, AbstractExpression $options, $lineno, $tag = null) { parent::__construct(array('expr' => $expr, 'options' => $options), array(), $lineno, $tag); } - /** - * Compiles the node to PHP. - * - * @param \Twig_Compiler $compiler A Twig_Compiler instance - */ - public function compile(\Twig_Compiler $compiler) + public function compile(Compiler $compiler) { $compiler ->addDebugInfo($this) diff --git a/src/Symfony/Bundle/TwigBundle/Resources/config/twig.xml b/src/Symfony/Bundle/TwigBundle/Resources/config/twig.xml index 457cb5c06abf1..0e5f6ec9a4a37 100644 --- a/src/Symfony/Bundle/TwigBundle/Resources/config/twig.xml +++ b/src/Symfony/Bundle/TwigBundle/Resources/config/twig.xml @@ -5,9 +5,9 @@ xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd"> - Twig_Environment + Twig\Environment Symfony\Bundle\TwigBundle\Loader\FilesystemLoader - Twig_Loader_Chain + Twig\Loader\ChainLoader Symfony\Bundle\TwigBundle\TwigEngine Symfony\Bundle\TwigBundle\CacheWarmer\TemplateCacheCacheWarmer Symfony\Bridge\Twig\Extension\TranslationExtension @@ -51,7 +51,7 @@ - + @@ -63,7 +63,7 @@ - + @@ -117,7 +117,7 @@ - + diff --git a/src/Symfony/Bundle/TwigBundle/Tests/Controller/ExceptionControllerTest.php b/src/Symfony/Bundle/TwigBundle/Tests/Controller/ExceptionControllerTest.php index b3ccd2af0199c..17f3ac17c87f2 100644 --- a/src/Symfony/Bundle/TwigBundle/Tests/Controller/ExceptionControllerTest.php +++ b/src/Symfony/Bundle/TwigBundle/Tests/Controller/ExceptionControllerTest.php @@ -15,13 +15,15 @@ use Symfony\Bundle\TwigBundle\Controller\ExceptionController; use Symfony\Component\Debug\Exception\FlattenException; use Symfony\Component\HttpFoundation\Request; +use Twig\Environment; +use Twig\Loader\ArrayLoader; class ExceptionControllerTest extends TestCase { public function testShowActionCanBeForcedToShowErrorPage() { - $twig = new \Twig_Environment( - new \Twig_Loader_Array(array( + $twig = new Environment( + new ArrayLoader(array( 'TwigBundle:Exception:error404.html.twig' => 'ok', )) ); @@ -40,8 +42,8 @@ public function testShowActionCanBeForcedToShowErrorPage() public function testFallbackToHtmlIfNoTemplateForRequestedFormat() { - $twig = new \Twig_Environment( - new \Twig_Loader_Array(array( + $twig = new Environment( + new ArrayLoader(array( 'TwigBundle:Exception:error.html.twig' => 'html', )) ); diff --git a/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/Compiler/ExtensionPassTest.php b/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/Compiler/ExtensionPassTest.php index b83c5645c510b..23160c4071d1d 100644 --- a/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/Compiler/ExtensionPassTest.php +++ b/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/Compiler/ExtensionPassTest.php @@ -26,7 +26,7 @@ public function testProcessDoesNotDropExistingFileLoaderMethodCalls() $container->register('twig.app_variable', '\Symfony\Bridge\Twig\AppVariable'); $container->register('templating', '\Symfony\Bundle\TwigBundle\TwigEngine'); - $nativeTwigLoader = new Definition('\Twig_Loader_Filesystem'); + $nativeTwigLoader = new Definition('\Twig\Loader\FilesystemLoader'); $nativeTwigLoader->addMethodCall('addPath', array()); $container->setDefinition('twig.loader.native_filesystem', $nativeTwigLoader); diff --git a/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/TwigExtensionTest.php b/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/TwigExtensionTest.php index 2637460ab8919..fb82ee8266dbf 100644 --- a/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/TwigExtensionTest.php +++ b/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/TwigExtensionTest.php @@ -66,7 +66,7 @@ public function testLoadEmptyConfiguration() $container->loadFromExtension('twig', array()); $this->compileContainer($container); - $this->assertEquals('Twig_Environment', $container->getParameter('twig.class'), '->load() loads the twig.xml file'); + $this->assertEquals('Twig\Environment', $container->getParameter('twig.class'), '->load() loads the twig.xml file'); $this->assertContains('form_div_layout.html.twig', $container->getParameter('twig.form.resources'), '->load() includes default template for form resources'); @@ -87,7 +87,7 @@ public function testLoadFullConfiguration($format) $this->loadFromFile($container, 'full', $format); $this->compileContainer($container); - $this->assertEquals('Twig_Environment', $container->getParameter('twig.class'), '->load() loads the twig.xml file'); + $this->assertEquals('Twig\Environment', $container->getParameter('twig.class'), '->load() loads the twig.xml file'); // Form resources $resources = $container->getParameter('twig.form.resources'); diff --git a/src/Symfony/Bundle/TwigBundle/Tests/Loader/FilesystemLoaderTest.php b/src/Symfony/Bundle/TwigBundle/Tests/Loader/FilesystemLoaderTest.php index a7abdecb87896..b9294e35b3c46 100644 --- a/src/Symfony/Bundle/TwigBundle/Tests/Loader/FilesystemLoaderTest.php +++ b/src/Symfony/Bundle/TwigBundle/Tests/Loader/FilesystemLoaderTest.php @@ -52,7 +52,7 @@ public function testExists() } /** - * @expectedException \Twig_Error_Loader + * @expectedException \Twig\Error\LoaderError */ public function testTwigErrorIfLocatorThrowsInvalid() { @@ -76,7 +76,7 @@ public function testTwigErrorIfLocatorThrowsInvalid() } /** - * @expectedException \Twig_Error_Loader + * @expectedException \Twig\Error\LoaderError */ public function testTwigErrorIfLocatorReturnsFalse() { @@ -100,7 +100,7 @@ public function testTwigErrorIfLocatorReturnsFalse() } /** - * @expectedException \Twig_Error_Loader + * @expectedException \Twig\Error\LoaderError * @expectedExceptionMessageRegExp /Unable to find template "name\.format\.engine" \(looked into: .*Tests.Loader.\.\..DependencyInjection.Fixtures.Resources.views\)/ */ public function testTwigErrorIfTemplateDoesNotExist() diff --git a/src/Symfony/Bundle/TwigBundle/Tests/TokenParser/LegacyRenderTokenParserTest.php b/src/Symfony/Bundle/TwigBundle/Tests/TokenParser/LegacyRenderTokenParserTest.php index 13881c108d603..5cba98cd45ff9 100644 --- a/src/Symfony/Bundle/TwigBundle/Tests/TokenParser/LegacyRenderTokenParserTest.php +++ b/src/Symfony/Bundle/TwigBundle/Tests/TokenParser/LegacyRenderTokenParserTest.php @@ -14,6 +14,11 @@ use Symfony\Bundle\TwigBundle\Tests\TestCase; use Symfony\Bundle\TwigBundle\TokenParser\RenderTokenParser; use Symfony\Bundle\TwigBundle\Node\RenderNode; +use Twig\Environment; +use Twig\Node\Expression\ArrayExpression; +use Twig\Node\Expression\ConstantExpression; +use Twig\Parser; +use Twig\Source; /** * @group legacy @@ -25,10 +30,10 @@ class LegacyRenderTokenParserTest extends TestCase */ public function testCompile($source, $expected) { - $env = new \Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock(), array('cache' => false, 'autoescape' => false, 'optimizations' => 0)); + $env = new Environment($this->getMockBuilder('Twig\Loader\LoaderInterface')->getMock(), array('cache' => false, 'autoescape' => false, 'optimizations' => 0)); $env->addTokenParser(new RenderTokenParser()); - $stream = $env->tokenize(new \Twig_Source($source, '')); - $parser = new \Twig_Parser($env); + $stream = $env->tokenize(new Source($source, '')); + $parser = new Parser($env); $this->assertEquals($expected, $parser->parse($stream)->getNode('body')->getNode(0)); } @@ -39,8 +44,8 @@ public function getTestsForRender() array( '{% render "foo" %}', new RenderNode( - new \Twig_Node_Expression_Constant('foo', 1), - new \Twig_Node_Expression_Array(array(), 1), + new ConstantExpression('foo', 1), + new ArrayExpression(array(), 1), 1, 'render' ), @@ -48,10 +53,10 @@ public function getTestsForRender() array( '{% render "foo", {foo: 1} %}', new RenderNode( - new \Twig_Node_Expression_Constant('foo', 1), - new \Twig_Node_Expression_Array(array( - new \Twig_Node_Expression_Constant('foo', 1), - new \Twig_Node_Expression_Constant('1', 1), + new ConstantExpression('foo', 1), + new ArrayExpression(array( + new ConstantExpression('foo', 1), + new ConstantExpression('1', 1), ), 1), 1, 'render' diff --git a/src/Symfony/Bundle/TwigBundle/TokenParser/RenderTokenParser.php b/src/Symfony/Bundle/TwigBundle/TokenParser/RenderTokenParser.php index b386c9b57fc62..cef083df3dc42 100644 --- a/src/Symfony/Bundle/TwigBundle/TokenParser/RenderTokenParser.php +++ b/src/Symfony/Bundle/TwigBundle/TokenParser/RenderTokenParser.php @@ -12,6 +12,10 @@ namespace Symfony\Bundle\TwigBundle\TokenParser; use Symfony\Bundle\TwigBundle\Node\RenderNode; +use Twig\Node\Expression\ArrayExpression; +use Twig\Node\Node; +use Twig\Token; +use Twig\TokenParser\AbstractTokenParser; /** * Token Parser for the render tag. @@ -20,29 +24,29 @@ * * @deprecated since version 2.2, to be removed in 3.0. */ -class RenderTokenParser extends \Twig_TokenParser +class RenderTokenParser extends AbstractTokenParser { /** * Parses a token and returns a node. * - * @param \Twig_Token $token A \Twig_Token instance + * @param Token $token * - * @return \Twig_Node A \Twig_Node instance + * @return Node */ - public function parse(\Twig_Token $token) + public function parse(Token $token) { $expr = $this->parser->getExpressionParser()->parseExpression(); // options - if ($this->parser->getStream()->test(\Twig_Token::PUNCTUATION_TYPE, ',')) { + if ($this->parser->getStream()->test(Token::PUNCTUATION_TYPE, ',')) { $this->parser->getStream()->next(); $options = $this->parser->getExpressionParser()->parseExpression(); } else { - $options = new \Twig_Node_Expression_Array(array(), $token->getLine()); + $options = new ArrayExpression(array(), $token->getLine()); } - $this->parser->getStream()->expect(\Twig_Token::BLOCK_END_TYPE); + $this->parser->getStream()->expect(Token::BLOCK_END_TYPE); return new RenderNode($expr, $options, $token->getLine(), $this->getTag()); } diff --git a/src/Symfony/Bundle/TwigBundle/TwigEngine.php b/src/Symfony/Bundle/TwigBundle/TwigEngine.php index 849e22348aefc..35e67b8735f72 100644 --- a/src/Symfony/Bundle/TwigBundle/TwigEngine.php +++ b/src/Symfony/Bundle/TwigBundle/TwigEngine.php @@ -17,6 +17,9 @@ use Symfony\Component\Templating\TemplateNameParserInterface; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Config\FileLocatorInterface; +use Twig\Environment; +use Twig\Error\Error; +use Twig\FileExtensionEscapingStrategy; /** * This engine renders Twig templates. @@ -27,14 +30,7 @@ class TwigEngine extends BaseEngine implements EngineInterface { protected $locator; - /** - * Constructor. - * - * @param \Twig_Environment $environment A \Twig_Environment instance - * @param TemplateNameParserInterface $parser A TemplateNameParserInterface instance - * @param FileLocatorInterface $locator A FileLocatorInterface instance - */ - public function __construct(\Twig_Environment $environment, TemplateNameParserInterface $parser, FileLocatorInterface $locator) + public function __construct(Environment $environment, TemplateNameParserInterface $parser, FileLocatorInterface $locator) { parent::__construct($environment, $parser); @@ -43,13 +39,13 @@ public function __construct(\Twig_Environment $environment, TemplateNameParserIn /** * @deprecated since version 2.7, to be removed in 3.0. - * Inject the escaping strategy on \Twig_Environment instead. + * Inject the escaping strategy on Twig instead. */ public function setDefaultEscapingStrategy($strategy) { - @trigger_error('The '.__METHOD__.' method is deprecated since version 2.7 and will be removed in 3.0. Inject the escaping strategy in the Twig_Environment object instead.', E_USER_DEPRECATED); + @trigger_error('The '.__METHOD__.' method is deprecated since version 2.7 and will be removed in 3.0. Inject the escaping strategy in the Twig\Environment object instead.', E_USER_DEPRECATED); - $this->environment->getExtension('Twig_Extension_Escaper')->setDefaultStrategy($strategy); + $this->environment->getExtension('Twig\Extension\EscaperExtension')->setDefaultStrategy($strategy); } /** @@ -58,9 +54,9 @@ public function setDefaultEscapingStrategy($strategy) */ public function guessDefaultEscapingStrategy($name) { - @trigger_error('The '.__METHOD__.' method is deprecated since version 2.7 and will be removed in 3.0. Use the Twig_FileExtensionEscapingStrategy::guess method instead.', E_USER_DEPRECATED); + @trigger_error('The '.__METHOD__.' method is deprecated since version 2.7 and will be removed in 3.0. Use the Twig\FileExtensionEscapingStrategy::guess method instead.', E_USER_DEPRECATED); - return \Twig_FileExtensionEscapingStrategy::guess($name); + return FileExtensionEscapingStrategy::guess($name); } /** @@ -70,7 +66,7 @@ public function render($name, array $parameters = array()) { try { return parent::render($name, $parameters); - } catch (\Twig_Error $e) { + } catch (Error $e) { if ($name instanceof TemplateReference && !method_exists($e, 'setSourceContext')) { try { // try to get the real name of the template where the error occurred @@ -88,7 +84,7 @@ public function render($name, array $parameters = array()) /** * {@inheritdoc} * - * @throws \Twig_Error if something went wrong like a thrown exception while rendering the template + * @throws Error if something went wrong like a thrown exception while rendering the template */ public function renderResponse($view, array $parameters = array(), Response $response = null) { diff --git a/src/Symfony/Bundle/TwigBundle/composer.json b/src/Symfony/Bundle/TwigBundle/composer.json index 4613ffb27af82..cd2f229e4ff88 100644 --- a/src/Symfony/Bundle/TwigBundle/composer.json +++ b/src/Symfony/Bundle/TwigBundle/composer.json @@ -19,7 +19,7 @@ "php": ">=5.3.9", "symfony/asset": "~2.7", "symfony/twig-bridge": "~2.7", - "twig/twig": "~1.28|~2.0", + "twig/twig": "~1.34|~2.4", "symfony/http-foundation": "~2.5", "symfony/http-kernel": "~2.7.23|^2.8.16" }, diff --git a/src/Symfony/Bundle/WebProfilerBundle/Controller/ExceptionController.php b/src/Symfony/Bundle/WebProfilerBundle/Controller/ExceptionController.php index fd0dbecd2bbec..3f9d873e1d40f 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Controller/ExceptionController.php +++ b/src/Symfony/Bundle/WebProfilerBundle/Controller/ExceptionController.php @@ -15,6 +15,9 @@ use Symfony\Component\Debug\ExceptionHandler; use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; use Symfony\Component\HttpFoundation\Response; +use Twig\Environment; +use Twig\Error\LoaderError; +use Twig\Loader\ExistsLoaderInterface; /** * ExceptionController. @@ -27,7 +30,7 @@ class ExceptionController protected $debug; protected $profiler; - public function __construct(Profiler $profiler = null, \Twig_Environment $twig, $debug) + public function __construct(Profiler $profiler = null, Environment $twig, $debug) { $this->profiler = $profiler; $this->twig = $twig; @@ -112,7 +115,7 @@ protected function getTemplate() protected function templateExists($template) { $loader = $this->twig->getLoader(); - if ($loader instanceof \Twig_ExistsLoaderInterface) { + if ($loader instanceof ExistsLoaderInterface) { return $loader->exists($template); } @@ -120,7 +123,7 @@ protected function templateExists($template) $loader->getSource($template); return true; - } catch (\Twig_Error_Loader $e) { + } catch (LoaderError $e) { } return false; diff --git a/src/Symfony/Bundle/WebProfilerBundle/Controller/ProfilerController.php b/src/Symfony/Bundle/WebProfilerBundle/Controller/ProfilerController.php index 24c83d5e1d8c6..355edde5c866b 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Controller/ProfilerController.php +++ b/src/Symfony/Bundle/WebProfilerBundle/Controller/ProfilerController.php @@ -19,6 +19,7 @@ use Symfony\Component\HttpFoundation\Request; use Symfony\Bundle\WebProfilerBundle\Profiler\TemplateManager; use Symfony\Component\Routing\Generator\UrlGeneratorInterface; +use Twig\Environment; /** * ProfilerController. @@ -39,11 +40,11 @@ class ProfilerController * * @param UrlGeneratorInterface $generator The URL Generator * @param Profiler $profiler The profiler - * @param \Twig_Environment $twig The twig environment + * @param Environment $twig The twig environment * @param array $templates The templates * @param string $toolbarPosition The toolbar position (top, bottom, normal, or null -- use the configuration) */ - public function __construct(UrlGeneratorInterface $generator, Profiler $profiler = null, \Twig_Environment $twig, array $templates, $toolbarPosition = 'normal') + public function __construct(UrlGeneratorInterface $generator, Profiler $profiler = null, Environment $twig, array $templates, $toolbarPosition = 'normal') { $this->generator = $generator; $this->profiler = $profiler; diff --git a/src/Symfony/Bundle/WebProfilerBundle/Controller/RouterController.php b/src/Symfony/Bundle/WebProfilerBundle/Controller/RouterController.php index b5d299e204184..c508346bf68a4 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Controller/RouterController.php +++ b/src/Symfony/Bundle/WebProfilerBundle/Controller/RouterController.php @@ -20,6 +20,7 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; use Symfony\Component\HttpKernel\Profiler\Profiler; use Symfony\Component\HttpKernel\DataCollector\RequestDataCollector; +use Twig\Environment; /** * RouterController. @@ -33,7 +34,7 @@ class RouterController private $matcher; private $routes; - public function __construct(Profiler $profiler = null, \Twig_Environment $twig, UrlMatcherInterface $matcher = null, RouteCollection $routes = null) + public function __construct(Profiler $profiler = null, Environment $twig, UrlMatcherInterface $matcher = null, RouteCollection $routes = null) { $this->profiler = $profiler; $this->twig = $twig; diff --git a/src/Symfony/Bundle/WebProfilerBundle/EventListener/WebDebugToolbarListener.php b/src/Symfony/Bundle/WebProfilerBundle/EventListener/WebDebugToolbarListener.php index 317dcc9a44dda..5d020fe914bb0 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/EventListener/WebDebugToolbarListener.php +++ b/src/Symfony/Bundle/WebProfilerBundle/EventListener/WebDebugToolbarListener.php @@ -18,6 +18,7 @@ use Symfony\Component\HttpKernel\KernelEvents; use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\Routing\Generator\UrlGeneratorInterface; +use Twig\Environment; /** * WebDebugToolbarListener injects the Web Debug Toolbar. @@ -41,7 +42,7 @@ class WebDebugToolbarListener implements EventSubscriberInterface protected $position; protected $excludedAjaxPaths; - public function __construct(\Twig_Environment $twig, $interceptRedirects = false, $mode = self::ENABLED, $position = 'bottom', UrlGeneratorInterface $urlGenerator = null, $excludedAjaxPaths = '^/bundles|^/_wdt') + public function __construct(Environment $twig, $interceptRedirects = false, $mode = self::ENABLED, $position = 'bottom', UrlGeneratorInterface $urlGenerator = null, $excludedAjaxPaths = '^/bundles|^/_wdt') { $this->twig = $twig; $this->urlGenerator = $urlGenerator; diff --git a/src/Symfony/Bundle/WebProfilerBundle/Profiler/TemplateManager.php b/src/Symfony/Bundle/WebProfilerBundle/Profiler/TemplateManager.php index ff5dce56f9cef..5b6b9f100461a 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Profiler/TemplateManager.php +++ b/src/Symfony/Bundle/WebProfilerBundle/Profiler/TemplateManager.php @@ -14,6 +14,11 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; use Symfony\Component\HttpKernel\Profiler\Profiler; use Symfony\Component\HttpKernel\Profiler\Profile; +use Twig\Environment; +use Twig\Error\LoaderError; +use Twig\Loader\ExistsLoaderInterface; +use Twig\Loader\SourceContextLoaderInterface; +use Twig\Template; /** * Profiler Templates Manager. @@ -27,14 +32,7 @@ class TemplateManager protected $templates; protected $profiler; - /** - * Constructor. - * - * @param Profiler $profiler - * @param \Twig_Environment $twig - * @param array $templates - */ - public function __construct(Profiler $profiler, \Twig_Environment $twig, array $templates) + public function __construct(Profiler $profiler, Environment $twig, array $templates) { $this->profiler = $profiler; $this->twig = $twig; @@ -67,7 +65,7 @@ public function getName(Profile $profile, $panel) * * @param Profile $profile * - * @return \Twig_Template[] + * @return Template[] * * @deprecated not used anymore internally */ @@ -123,19 +121,19 @@ public function getNames(Profile $profile) protected function templateExists($template) { $loader = $this->twig->getLoader(); - if ($loader instanceof \Twig_ExistsLoaderInterface) { + if ($loader instanceof ExistsLoaderInterface) { return $loader->exists($template); } try { - if ($loader instanceof \Twig_SourceContextLoaderInterface) { + if ($loader instanceof SourceContextLoaderInterface) { $loader->getSourceContext($template); } else { $loader->getSource($template); } return true; - } catch (\Twig_Error_Loader $e) { + } catch (LoaderError $e) { } return false; diff --git a/src/Symfony/Bundle/WebProfilerBundle/Tests/Controller/ProfilerControllerTest.php b/src/Symfony/Bundle/WebProfilerBundle/Tests/Controller/ProfilerControllerTest.php index a14869d4ec206..a2d005a8b0aec 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Tests/Controller/ProfilerControllerTest.php +++ b/src/Symfony/Bundle/WebProfilerBundle/Tests/Controller/ProfilerControllerTest.php @@ -24,7 +24,7 @@ class ProfilerControllerTest extends TestCase public function testEmptyToken($token) { $urlGenerator = $this->getMockBuilder('Symfony\Component\Routing\Generator\UrlGeneratorInterface')->getMock(); - $twig = $this->getMockBuilder('Twig_Environment')->disableOriginalConstructor()->getMock(); + $twig = $this->getMockBuilder('Twig\Environment')->disableOriginalConstructor()->getMock(); $profiler = $this ->getMockBuilder('Symfony\Component\HttpKernel\Profiler\Profiler') ->disableOriginalConstructor() @@ -48,7 +48,7 @@ public function getEmptyTokenCases() public function testReturns404onTokenNotFound() { $urlGenerator = $this->getMockBuilder('Symfony\Component\Routing\Generator\UrlGeneratorInterface')->getMock(); - $twig = $this->getMockBuilder('Twig_Environment')->disableOriginalConstructor()->getMock(); + $twig = $this->getMockBuilder('Twig\Environment')->disableOriginalConstructor()->getMock(); $profiler = $this ->getMockBuilder('Symfony\Component\HttpKernel\Profiler\Profiler') ->disableOriginalConstructor() @@ -76,7 +76,7 @@ public function testReturns404onTokenNotFound() public function testSearchResult() { $urlGenerator = $this->getMockBuilder('Symfony\Component\Routing\Generator\UrlGeneratorInterface')->getMock(); - $twig = $this->getMockBuilder('Twig_Environment')->disableOriginalConstructor()->getMock(); + $twig = $this->getMockBuilder('Twig\Environment')->disableOriginalConstructor()->getMock(); $profiler = $this ->getMockBuilder('Symfony\Component\HttpKernel\Profiler\Profiler') ->disableOriginalConstructor() diff --git a/src/Symfony/Bundle/WebProfilerBundle/Tests/DependencyInjection/WebProfilerExtensionTest.php b/src/Symfony/Bundle/WebProfilerBundle/Tests/DependencyInjection/WebProfilerExtensionTest.php index 2237e18b29e54..618385ce81b54 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Tests/DependencyInjection/WebProfilerExtensionTest.php +++ b/src/Symfony/Bundle/WebProfilerBundle/Tests/DependencyInjection/WebProfilerExtensionTest.php @@ -52,9 +52,9 @@ protected function setUp() $this->container->addScope(new Scope('request')); $this->container->register('request', 'Symfony\\Component\\HttpFoundation\\Request')->setScope('request'); $this->container->register('router', $this->getMockClass('Symfony\\Component\\Routing\\RouterInterface')); - $this->container->register('twig', 'Twig_Environment'); - $this->container->register('twig_loader', 'Twig_Loader_Array')->addArgument(array()); - $this->container->register('twig', 'Twig_Environment')->addArgument(new Reference('twig_loader')); + $this->container->register('twig', 'Twig\Environment'); + $this->container->register('twig_loader', 'Twig\Loader\ArrayLoader')->addArgument(array()); + $this->container->register('twig', 'Twig\Environment')->addArgument(new Reference('twig_loader')); $this->container->setParameter('kernel.bundles', array()); $this->container->setParameter('kernel.cache_dir', __DIR__); $this->container->setParameter('kernel.debug', false); diff --git a/src/Symfony/Bundle/WebProfilerBundle/Tests/EventListener/WebDebugToolbarListenerTest.php b/src/Symfony/Bundle/WebProfilerBundle/Tests/EventListener/WebDebugToolbarListenerTest.php index b730afe345aa4..6f32b2101341d 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Tests/EventListener/WebDebugToolbarListenerTest.php +++ b/src/Symfony/Bundle/WebProfilerBundle/Tests/EventListener/WebDebugToolbarListenerTest.php @@ -288,7 +288,7 @@ protected function getRequestMock($isXmlHttpRequest = false, $requestFormat = 'h protected function getTwigMock($render = 'WDT') { - $templating = $this->getMockBuilder('Twig_Environment')->disableOriginalConstructor()->getMock(); + $templating = $this->getMockBuilder('Twig\Environment')->disableOriginalConstructor()->getMock(); $templating->expects($this->any()) ->method('render') ->will($this->returnValue($render)); diff --git a/src/Symfony/Bundle/WebProfilerBundle/Tests/Profiler/TemplateManagerTest.php b/src/Symfony/Bundle/WebProfilerBundle/Tests/Profiler/TemplateManagerTest.php index 4ac2c7de5f0a2..7b8f9a8df51c0 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Tests/Profiler/TemplateManagerTest.php +++ b/src/Symfony/Bundle/WebProfilerBundle/Tests/Profiler/TemplateManagerTest.php @@ -13,6 +13,7 @@ use Symfony\Bundle\WebProfilerBundle\Tests\TestCase; use Symfony\Bundle\WebProfilerBundle\Profiler\TemplateManager; +use Twig\Environment; /** * Test for TemplateManager class. @@ -22,7 +23,7 @@ class TemplateManagerTest extends TestCase { /** - * @var \Twig_Environment + * @var Environment */ protected $twigEnvironment; @@ -46,7 +47,7 @@ protected function setUp() 'data_collector.foo' => array('foo', 'FooBundle:Collector:foo'), 'data_collector.bar' => array('bar', 'FooBundle:Collector:bar'), 'data_collector.baz' => array('baz', 'FooBundle:Collector:baz'), - ); + ); $this->templateManager = new TemplateManager($profiler, $twigEnvironment, $templates); } @@ -129,16 +130,16 @@ protected function mockProfile() protected function mockTwigEnvironment() { - $this->twigEnvironment = $this->getMockBuilder('Twig_Environment')->disableOriginalConstructor()->getMock(); + $this->twigEnvironment = $this->getMockBuilder('Twig\Environment')->disableOriginalConstructor()->getMock(); $this->twigEnvironment->expects($this->any()) ->method('loadTemplate') ->will($this->returnValue('loadedTemplate')); - if (interface_exists('\Twig_SourceContextLoaderInterface')) { - $loader = $this->getMockBuilder('\Twig_SourceContextLoaderInterface')->getMock(); + if (interface_exists('Twig\Loader\SourceContextLoaderInterface')) { + $loader = $this->getMockBuilder('Twig\Loader\SourceContextLoaderInterface')->getMock(); } else { - $loader = $this->getMockBuilder('\Twig_LoaderInterface')->getMock(); + $loader = $this->getMockBuilder('Twig\Loader\LoaderInterface')->getMock(); } $this->twigEnvironment->expects($this->any())->method('getLoader')->will($this->returnValue($loader)); diff --git a/src/Symfony/Bundle/WebProfilerBundle/Twig/WebProfilerExtension.php b/src/Symfony/Bundle/WebProfilerBundle/Twig/WebProfilerExtension.php index 13df2f443e9f0..8fc6b592deb42 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Twig/WebProfilerExtension.php +++ b/src/Symfony/Bundle/WebProfilerBundle/Twig/WebProfilerExtension.php @@ -12,13 +12,15 @@ namespace Symfony\Bundle\WebProfilerBundle\Twig; use Symfony\Component\HttpKernel\DataCollector\Util\ValueExporter; +use Twig\Extension\AbstractExtension; +use Twig\TwigFunction; /** * Twig extension for the profiler. * * @author Fabien Potencier */ -class WebProfilerExtension extends \Twig_Extension +class WebProfilerExtension extends AbstractExtension { /** * @var ValueExporter @@ -31,7 +33,7 @@ class WebProfilerExtension extends \Twig_Extension public function getFunctions() { return array( - new \Twig_SimpleFunction('profiler_dump', array($this, 'dumpValue')), + new TwigFunction('profiler_dump', array($this, 'dumpValue')), ); } diff --git a/src/Symfony/Bundle/WebProfilerBundle/composer.json b/src/Symfony/Bundle/WebProfilerBundle/composer.json index 8867a64eca35a..000b89795462d 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/composer.json +++ b/src/Symfony/Bundle/WebProfilerBundle/composer.json @@ -20,7 +20,7 @@ "symfony/http-kernel": "~2.4", "symfony/routing": "~2.2", "symfony/twig-bridge": "~2.7", - "twig/twig": "~1.28|~2.0" + "twig/twig": "~1.34|~2.4" }, "require-dev": { "symfony/config": "~2.2", diff --git a/src/Symfony/Component/HttpKernel/DataCollector/DumpDataCollector.php b/src/Symfony/Component/HttpKernel/DataCollector/DumpDataCollector.php index 9448ad180b4f3..049053150fef2 100644 --- a/src/Symfony/Component/HttpKernel/DataCollector/DumpDataCollector.php +++ b/src/Symfony/Component/HttpKernel/DataCollector/DumpDataCollector.php @@ -20,6 +20,7 @@ use Symfony\Component\VarDumper\Dumper\CliDumper; use Symfony\Component\VarDumper\Dumper\HtmlDumper; use Symfony\Component\VarDumper\Dumper\DataDumperInterface; +use Twig\Template; /** * @author Nicolas Grekas @@ -96,7 +97,7 @@ public function dump(Data $data) $line = $trace[$i]['line']; break; - } elseif (isset($trace[$i]['object']) && $trace[$i]['object'] instanceof \Twig_Template) { + } elseif (isset($trace[$i]['object']) && $trace[$i]['object'] instanceof Template) { $template = $trace[$i]['object']; $name = $template->getTemplateName(); $src = method_exists($template, 'getSourceContext') ? $template->getSourceContext()->getCode() : (method_exists($template, 'getSource') ? $template->getSource() : false); diff --git a/src/Symfony/Component/HttpKernel/Fragment/HIncludeFragmentRenderer.php b/src/Symfony/Component/HttpKernel/Fragment/HIncludeFragmentRenderer.php index 09f84ec3b8e01..e7d4aedb16404 100644 --- a/src/Symfony/Component/HttpKernel/Fragment/HIncludeFragmentRenderer.php +++ b/src/Symfony/Component/HttpKernel/Fragment/HIncludeFragmentRenderer.php @@ -16,6 +16,9 @@ use Symfony\Component\Templating\EngineInterface; use Symfony\Component\HttpKernel\Controller\ControllerReference; use Symfony\Component\HttpKernel\UriSigner; +use Twig\Environment; +use Twig\Error\LoaderError; +use Twig\Loader\ExistsLoaderInterface; /** * Implements the Hinclude rendering strategy. @@ -32,10 +35,10 @@ class HIncludeFragmentRenderer extends RoutableFragmentRenderer /** * Constructor. * - * @param EngineInterface|\Twig_Environment $templating An EngineInterface or a \Twig_Environment instance - * @param UriSigner $signer A UriSigner instance - * @param string $globalDefaultTemplate The global default content (it can be a template name or the content) - * @param string $charset + * @param EngineInterface|Environment $templating An EngineInterface or a Twig instance + * @param UriSigner $signer A UriSigner instance + * @param string $globalDefaultTemplate The global default content (it can be a template name or the content) + * @param string $charset */ public function __construct($templating = null, UriSigner $signer = null, $globalDefaultTemplate = null, $charset = 'utf-8') { @@ -48,14 +51,14 @@ public function __construct($templating = null, UriSigner $signer = null, $globa /** * Sets the templating engine to use to render the default content. * - * @param EngineInterface|\Twig_Environment|null $templating An EngineInterface or a \Twig_Environment instance + * @param EngineInterface|Environment|null $templating An EngineInterface or an Environment instance * * @throws \InvalidArgumentException */ public function setTemplating($templating) { - if (null !== $templating && !$templating instanceof EngineInterface && !$templating instanceof \Twig_Environment) { - throw new \InvalidArgumentException('The hinclude rendering strategy needs an instance of \Twig_Environment or Symfony\Component\Templating\EngineInterface'); + if (null !== $templating && !$templating instanceof EngineInterface && !$templating instanceof Environment) { + throw new \InvalidArgumentException('The hinclude rendering strategy needs an instance of Twig\Environment or Symfony\Component\Templating\EngineInterface'); } $this->templating = $templating; @@ -140,7 +143,7 @@ private function templateExists($template) } $loader = $this->templating->getLoader(); - if ($loader instanceof \Twig_ExistsLoaderInterface || method_exists($loader, 'exists')) { + if ($loader instanceof ExistsLoaderInterface || method_exists($loader, 'exists')) { return $loader->exists($template); } @@ -152,7 +155,7 @@ private function templateExists($template) } return true; - } catch (\Twig_Error_Loader $e) { + } catch (LoaderError $e) { } return false; diff --git a/src/Symfony/Component/HttpKernel/composer.json b/src/Symfony/Component/HttpKernel/composer.json index 7dec6ef11dfce..6b6ec3f17b886 100644 --- a/src/Symfony/Component/HttpKernel/composer.json +++ b/src/Symfony/Component/HttpKernel/composer.json @@ -40,7 +40,8 @@ "symfony/var-dumper": "~2.6" }, "conflict": { - "symfony/config": "<2.7" + "symfony/config": "<2.7", + "twig/twig": "<1.34|<2.4,>=2" }, "suggest": { "symfony/browser-kit": "", From e7c4149e78525dec0290aeda8f9c4fcdb149efe5 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Thu, 1 Jun 2017 23:47:36 +0200 Subject: [PATCH 0113/1099] [EventDispatcher] Fix ContainerAwareEventDispatcher::hasListeners(null) --- .../Component/EventDispatcher/ContainerAwareEventDispatcher.php | 2 +- .../EventDispatcher/Tests/AbstractEventDispatcherTest.php | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/EventDispatcher/ContainerAwareEventDispatcher.php b/src/Symfony/Component/EventDispatcher/ContainerAwareEventDispatcher.php index b92defe691257..dc2816f16906b 100644 --- a/src/Symfony/Component/EventDispatcher/ContainerAwareEventDispatcher.php +++ b/src/Symfony/Component/EventDispatcher/ContainerAwareEventDispatcher.php @@ -105,7 +105,7 @@ public function removeListener($eventName, $listener) public function hasListeners($eventName = null) { if (null === $eventName) { - return (bool) count($this->listenerIds) || (bool) count($this->listeners); + return $this->listenerIds || $this->listeners || parent::hasListeners(); } if (isset($this->listenerIds[$eventName])) { diff --git a/src/Symfony/Component/EventDispatcher/Tests/AbstractEventDispatcherTest.php b/src/Symfony/Component/EventDispatcher/Tests/AbstractEventDispatcherTest.php index bde6caa4eeb38..e5e9c2be83b43 100644 --- a/src/Symfony/Component/EventDispatcher/Tests/AbstractEventDispatcherTest.php +++ b/src/Symfony/Component/EventDispatcher/Tests/AbstractEventDispatcherTest.php @@ -56,6 +56,7 @@ public function testAddListener() { $this->dispatcher->addListener('pre.foo', array($this->listener, 'preFoo')); $this->dispatcher->addListener('post.foo', array($this->listener, 'postFoo')); + $this->assertTrue($this->dispatcher->hasListeners()); $this->assertTrue($this->dispatcher->hasListeners(self::preFoo)); $this->assertTrue($this->dispatcher->hasListeners(self::postFoo)); $this->assertCount(1, $this->dispatcher->getListeners(self::preFoo)); From e6f11da20e69863c83772f1275a130869e7390c6 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Thu, 1 Jun 2017 23:52:06 +0200 Subject: [PATCH 0114/1099] fix merge --- .../DependencyInjection/Compiler/CacheCollectorPass.php | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/CacheCollectorPass.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/CacheCollectorPass.php index 05e8a00a7925a..549cf2797c615 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/CacheCollectorPass.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/CacheCollectorPass.php @@ -50,11 +50,6 @@ public function process(ContainerBuilder $container) $definition->setTags(array()); $definition->setPublic(false); - if ($types = $definition->getAutowiringTypes(false)) { - $recorder->setAutowiringTypes($types); - $definition->setAutowiringTypes(array()); - } - $container->setDefinition($innerId, $definition); $container->setDefinition($id, $recorder); From 5f2b26e19df6857cc718063c99dd72c70deba3a5 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Fri, 2 Jun 2017 00:03:58 +0200 Subject: [PATCH 0115/1099] [FrameworkBundle] Fix FC with 4.0 having autowiring types removed --- .../DependencyInjection/Compiler/CacheCollectorPass.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/CacheCollectorPass.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/CacheCollectorPass.php index 05e8a00a7925a..60cdadb49b250 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/CacheCollectorPass.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/CacheCollectorPass.php @@ -50,7 +50,7 @@ public function process(ContainerBuilder $container) $definition->setTags(array()); $definition->setPublic(false); - if ($types = $definition->getAutowiringTypes(false)) { + if (method_exists($definition, 'getAutowiringTypes') && $types = $definition->getAutowiringTypes(false)) { $recorder->setAutowiringTypes($types); $definition->setAutowiringTypes(array()); } From ad1f35fc72ac2b805ec4b05c575fce63ed637c6b Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Thu, 18 May 2017 19:40:51 +0200 Subject: [PATCH 0116/1099] removed HHVM support --- .travis.yml | 17 ++----- .../WebServerBundle/Command/ServerCommand.php | 7 --- .../Cache/Adapter/PhpArrayAdapter.php | 2 +- .../Component/Cache/Simple/PhpArrayCache.php | 2 +- .../Cache/Tests/Adapter/AdapterTestCase.php | 9 ---- src/Symfony/Component/Cache/composer.json | 3 -- .../Resource/ReflectionClassResource.php | 47 +++---------------- src/Symfony/Component/Console/Application.php | 4 -- .../Debug/Tests/DebugClassLoaderTest.php | 3 -- .../Debug/Tests/ErrorHandlerTest.php | 34 -------------- .../Tests/Exception/FlattenExceptionTest.php | 2 +- ...UndefinedFunctionFatalErrorHandlerTest.php | 2 +- .../DependencyInjection/Loader/FileLoader.php | 2 +- .../Compiler/FactoryReturnTypePassTest.php | 8 +--- .../Tests/Fixtures/FactoryDummy.php | 1 - .../Tests/Loader/IniFileLoaderTest.php | 4 -- .../Component/Filesystem/Filesystem.php | 2 +- .../Filesystem/Tests/FilesystemTest.php | 12 ----- .../Iterator/RecursiveDirectoryIterator.php | 5 -- .../Component/HttpFoundation/JsonResponse.php | 23 ++++----- .../Component/HttpFoundation/Response.php | 3 +- .../Handler/MemcacheSessionHandlerTest.php | 4 -- .../Handler/MemcachedSessionHandlerTest.php | 4 -- .../Storage/Handler/PdoSessionHandlerTest.php | 8 ---- .../Bundle/Reader/IntlBundleReaderTest.php | 8 ---- .../AbstractIntlDateFormatterTest.php | 25 +++------- .../Component/Intl/Util/IntlTestHelper.php | 2 +- .../Component/Process/PhpExecutableFinder.php | 10 +--- src/Symfony/Component/Process/Process.php | 2 +- .../Process/Tests/ExecutableFinderTest.php | 4 +- .../Process/Tests/PhpExecutableFinderTest.php | 25 +--------- .../Dumper/PhpGeneratorDumperTest.php | 4 -- .../Normalizer/DataUriNormalizerTest.php | 10 +--- .../VarDumper/Caster/RedisCaster.php | 9 ---- .../VarDumper/Caster/ReflectionCaster.php | 7 --- .../Component/VarDumper/Cloner/VarCloner.php | 26 +++++----- .../Tests/Caster/RedisCasterTest.php | 22 +-------- .../VarDumper/Tests/Dumper/CliDumperTest.php | 15 ++---- .../VarDumper/Tests/Dumper/HtmlDumperTest.php | 5 +- 39 files changed, 61 insertions(+), 321 deletions(-) diff --git a/.travis.yml b/.travis.yml index 0df5d91c75ca1..66b0e596ecea6 100644 --- a/.travis.yml +++ b/.travis.yml @@ -62,17 +62,12 @@ before_install: export -f tfold # php.ini configuration - if [[ $PHP = hhvm* ]]; then - INI=/etc/hhvm/php.ini - else - INI=~/.phpenv/versions/$(phpenv version-name)/etc/conf.d/travis.ini - phpenv config-rm xdebug.ini || echo "xdebug not available" - fi + INI=~/.phpenv/versions/$(phpenv version-name)/etc/conf.d/travis.ini + phpenv config-rm xdebug.ini || echo "xdebug not available" echo date.timezone = Europe/Paris >> $INI echo memory_limit = -1 >> $INI echo session.gc_probability = 0 >> $INI echo opcache.enable_cli = 1 >> $INI - echo hhvm.jit = 0 >> $INI echo apc.enable_cli = 1 >> $INI echo extension = ldap.so >> $INI echo extension = redis.so >> $INI @@ -80,7 +75,7 @@ before_install: echo extension = mongodb.so >> $INI # Matrix lines for intermediate PHP versions are skipped for pull requests - if [[ ! $deps && ! $PHP = $MIN_PHP && ! $PHP = hhvm* && $TRAVIS_PULL_REQUEST != false ]]; then + if [[ ! $deps && ! $PHP = $MIN_PHP && $TRAVIS_PULL_REQUEST != false ]]; then deps=skip skip=1 else @@ -145,9 +140,7 @@ install: - if [[ ! $skip ]]; then $COMPOSER_UP; fi - if [[ ! $skip ]]; then ./phpunit install; fi - - | - # phpinfo - if [[ ! $PHP = hhvm* ]]; then php -i; else hhvm --php -r 'print_r($_SERVER);print_r(ini_get_all());'; fi + - php -i - | run_tests () { @@ -161,8 +154,6 @@ install: # Test the PhpUnit bridge on PHP 5.3, using the original phpunit script tfold src/Symfony/Bridge/PhpUnit \ "cd src/Symfony/Bridge/PhpUnit && wget https://phar.phpunit.de/phpunit-4.8.phar && phpenv global 5.3 && composer update --no-progress --ansi && php phpunit-4.8.phar" - elif [[ $PHP = hhvm* ]]; then - $PHPUNIT --exclude-group benchmark,intl-data else echo "$COMPONENTS" | parallel --gnu "tfold {} $PHPUNIT_X {}" tfold tty-group $PHPUNIT --group tty diff --git a/src/Symfony/Bundle/WebServerBundle/Command/ServerCommand.php b/src/Symfony/Bundle/WebServerBundle/Command/ServerCommand.php index 1df81a68a173b..046e5345729ec 100644 --- a/src/Symfony/Bundle/WebServerBundle/Command/ServerCommand.php +++ b/src/Symfony/Bundle/WebServerBundle/Command/ServerCommand.php @@ -22,11 +22,4 @@ */ abstract class ServerCommand extends Command { - /** - * {@inheritdoc} - */ - public function isEnabled() - { - return !defined('HHVM_VERSION') && parent::isEnabled(); - } } diff --git a/src/Symfony/Component/Cache/Adapter/PhpArrayAdapter.php b/src/Symfony/Component/Cache/Adapter/PhpArrayAdapter.php index 8671258d72c52..69b712dbb4f33 100644 --- a/src/Symfony/Component/Cache/Adapter/PhpArrayAdapter.php +++ b/src/Symfony/Component/Cache/Adapter/PhpArrayAdapter.php @@ -63,7 +63,7 @@ function ($key, $value, $isHit) { public static function create($file, CacheItemPoolInterface $fallbackPool) { // Shared memory is available in PHP 7.0+ with OPCache enabled and in HHVM - if (ini_get('opcache.enable') || defined('HHVM_VERSION')) { + if (ini_get('opcache.enable')) { if (!$fallbackPool instanceof AdapterInterface) { $fallbackPool = new ProxyAdapter($fallbackPool); } diff --git a/src/Symfony/Component/Cache/Simple/PhpArrayCache.php b/src/Symfony/Component/Cache/Simple/PhpArrayCache.php index 678d2ca8b3562..3dfc7767e6c92 100644 --- a/src/Symfony/Component/Cache/Simple/PhpArrayCache.php +++ b/src/Symfony/Component/Cache/Simple/PhpArrayCache.php @@ -46,7 +46,7 @@ public function __construct($file, CacheInterface $fallbackPool) public static function create($file, CacheInterface $fallbackPool) { // Shared memory is available in PHP 7.0+ with OPCache enabled and in HHVM - if (ini_get('opcache.enable') || defined('HHVM_VERSION')) { + if (ini_get('opcache.enable')) { return new static($file, $fallbackPool); } diff --git a/src/Symfony/Component/Cache/Tests/Adapter/AdapterTestCase.php b/src/Symfony/Component/Cache/Tests/Adapter/AdapterTestCase.php index c3cbd3bef7e54..08718143203e7 100644 --- a/src/Symfony/Component/Cache/Tests/Adapter/AdapterTestCase.php +++ b/src/Symfony/Component/Cache/Tests/Adapter/AdapterTestCase.php @@ -15,15 +15,6 @@ abstract class AdapterTestCase extends CachePoolTest { - protected function setUp() - { - parent::setUp(); - - if (!array_key_exists('testDeferredSaveWithoutCommit', $this->skippedTests) && defined('HHVM_VERSION')) { - $this->skippedTests['testDeferredSaveWithoutCommit'] = 'Destructors are called late on HHVM.'; - } - } - public function testDefaultLifeTime() { if (isset($this->skippedTests[__FUNCTION__])) { diff --git a/src/Symfony/Component/Cache/composer.json b/src/Symfony/Component/Cache/composer.json index 7a64053c4f8a3..510d910686224 100644 --- a/src/Symfony/Component/Cache/composer.json +++ b/src/Symfony/Component/Cache/composer.json @@ -34,9 +34,6 @@ "conflict": { "symfony/var-dumper": "<3.4" }, - "suggest": { - "symfony/polyfill-apcu": "For using ApcuAdapter on HHVM" - }, "autoload": { "psr-4": { "Symfony\\Component\\Cache\\": "" }, "exclude-from-classmap": [ diff --git a/src/Symfony/Component/Config/Resource/ReflectionClassResource.php b/src/Symfony/Component/Config/Resource/ReflectionClassResource.php index a8e1f9611b99a..b65991a0b755a 100644 --- a/src/Symfony/Component/Config/Resource/ReflectionClassResource.php +++ b/src/Symfony/Component/Config/Resource/ReflectionClassResource.php @@ -133,49 +133,14 @@ private function generateSignature(\ReflectionClass $class) } } - if (defined('HHVM_VERSION')) { - foreach ($class->getMethods(\ReflectionMethod::IS_PUBLIC | \ReflectionMethod::IS_PROTECTED) as $m) { - // workaround HHVM bug with variadics, see https://github.com/facebook/hhvm/issues/5762 - yield preg_replace('/^ @@.*/m', '', new ReflectionMethodHhvmWrapper($m->class, $m->name)); - } - } else { - foreach ($class->getMethods(\ReflectionMethod::IS_PUBLIC | \ReflectionMethod::IS_PROTECTED) as $m) { - yield preg_replace('/^ @@.*/m', '', $m); + foreach ($class->getMethods(\ReflectionMethod::IS_PUBLIC | \ReflectionMethod::IS_PROTECTED) as $m) { + yield preg_replace('/^ @@.*/m', '', $m); - $defaults = array(); - foreach ($m->getParameters() as $p) { - $defaults[$p->name] = $p->isDefaultValueAvailable() ? $p->getDefaultValue() : null; - } - yield print_r($defaults, true); + $defaults = array(); + foreach ($m->getParameters() as $p) { + $defaults[$p->name] = $p->isDefaultValueAvailable() ? $p->getDefaultValue() : null; } + yield print_r($defaults, true); } } } - -/** - * @internal - */ -class ReflectionMethodHhvmWrapper extends \ReflectionMethod -{ - public function getParameters() - { - $params = array(); - - foreach (parent::getParameters() as $i => $p) { - $params[] = new ReflectionParameterHhvmWrapper(array($this->class, $this->name), $i); - } - - return $params; - } -} - -/** - * @internal - */ -class ReflectionParameterHhvmWrapper extends \ReflectionParameter -{ - public function getDefaultValue() - { - return array($this->isVariadic(), $this->isDefaultValueAvailable() ? parent::getDefaultValue() : null); - } -} diff --git a/src/Symfony/Component/Console/Application.php b/src/Symfony/Component/Console/Application.php index 5a48a8d6764fc..7b3a4ca6fa2f8 100644 --- a/src/Symfony/Component/Console/Application.php +++ b/src/Symfony/Component/Console/Application.php @@ -667,10 +667,6 @@ public function renderException(\Exception $e, OutputInterface $output) $len = Helper::strlen($title); $width = $this->terminal->getWidth() ? $this->terminal->getWidth() - 1 : PHP_INT_MAX; - // HHVM only accepts 32 bits integer in str_split, even when PHP_INT_MAX is a 64 bit integer: https://github.com/facebook/hhvm/issues/1327 - if (defined('HHVM_VERSION') && $width > 1 << 31) { - $width = 1 << 31; - } $lines = array(); foreach (preg_split('/\r?\n/', $e->getMessage()) as $line) { foreach ($this->splitStringByWidth($line, $width - 4) as $line) { diff --git a/src/Symfony/Component/Debug/Tests/DebugClassLoaderTest.php b/src/Symfony/Component/Debug/Tests/DebugClassLoaderTest.php index 3f21b2a0adb24..034e6a3b2aec3 100644 --- a/src/Symfony/Component/Debug/Tests/DebugClassLoaderTest.php +++ b/src/Symfony/Component/Debug/Tests/DebugClassLoaderTest.php @@ -66,9 +66,6 @@ public function testStacking() if (class_exists('Symfony\Component\Debug\Exception\ContextErrorException', false)) { $this->markTestSkipped('The ContextErrorException class is already loaded.'); } - if (defined('HHVM_VERSION')) { - $this->markTestSkipped('HHVM is not handled in this test case.'); - } ErrorHandler::register(); diff --git a/src/Symfony/Component/Debug/Tests/ErrorHandlerTest.php b/src/Symfony/Component/Debug/Tests/ErrorHandlerTest.php index eada140ccab7e..85d62eecea3ba 100644 --- a/src/Symfony/Component/Debug/Tests/ErrorHandlerTest.php +++ b/src/Symfony/Component/Debug/Tests/ErrorHandlerTest.php @@ -489,38 +489,4 @@ public function testHandleErrorException() $this->assertInstanceOf('Symfony\Component\Debug\Exception\ClassNotFoundException', $args[0]); $this->assertStringStartsWith("Attempted to load class \"Foo\" from the global namespace.\nDid you forget a \"use\" statement", $args[0]->getMessage()); } - - public function testHandleFatalErrorOnHHVM() - { - try { - $handler = ErrorHandler::register(); - - $logger = $this->getMockBuilder('Psr\Log\LoggerInterface')->getMock(); - $logger - ->expects($this->once()) - ->method('log') - ->with( - $this->equalTo(LogLevel::CRITICAL), - $this->equalTo('Fatal Error: foo') - ) - ; - - $handler->setDefaultLogger($logger, E_ERROR); - - $error = array( - 'type' => E_ERROR + 0x1000000, // This error level is used by HHVM for fatal errors - 'message' => 'foo', - 'file' => 'bar', - 'line' => 123, - 'context' => array(123), - 'backtrace' => array(456), - ); - - call_user_func_array(array($handler, 'handleError'), $error); - $handler->handleFatalError($error); - } finally { - restore_error_handler(); - restore_exception_handler(); - } - } } diff --git a/src/Symfony/Component/Debug/Tests/Exception/FlattenExceptionTest.php b/src/Symfony/Component/Debug/Tests/Exception/FlattenExceptionTest.php index 4a0e6cbe4f234..d68f9a035e8f0 100644 --- a/src/Symfony/Component/Debug/Tests/Exception/FlattenExceptionTest.php +++ b/src/Symfony/Component/Debug/Tests/Exception/FlattenExceptionTest.php @@ -233,7 +233,7 @@ function () {}, $this->assertSame(array('object', 'stdClass'), $array[$i++]); $this->assertSame(array('object', 'Symfony\Component\HttpKernel\Exception\NotFoundHttpException'), $array[$i++]); $this->assertSame(array('incomplete-object', 'BogusTestClass'), $array[$i++]); - $this->assertSame(array('resource', defined('HHVM_VERSION') ? 'Directory' : 'stream'), $array[$i++]); + $this->assertSame(array('resource', 'stream'), $array[$i++]); $this->assertSame(array('resource', 'stream'), $array[$i++]); $args = $array[$i++]; diff --git a/src/Symfony/Component/Debug/Tests/FatalErrorHandler/UndefinedFunctionFatalErrorHandlerTest.php b/src/Symfony/Component/Debug/Tests/FatalErrorHandler/UndefinedFunctionFatalErrorHandlerTest.php index 1dc2120045c2c..60153fc5ec2f2 100644 --- a/src/Symfony/Component/Debug/Tests/FatalErrorHandler/UndefinedFunctionFatalErrorHandlerTest.php +++ b/src/Symfony/Component/Debug/Tests/FatalErrorHandler/UndefinedFunctionFatalErrorHandlerTest.php @@ -26,7 +26,7 @@ public function testUndefinedFunction($error, $translatedMessage) $exception = $handler->handleError($error, new FatalErrorException('', 0, $error['type'], $error['file'], $error['line'])); $this->assertInstanceOf('Symfony\Component\Debug\Exception\UndefinedFunctionException', $exception); - // class names are case insensitive and PHP/HHVM do not return the same + // class names are case insensitive and PHP do not return the same $this->assertSame(strtolower($translatedMessage), strtolower($exception->getMessage())); $this->assertSame($error['type'], $exception->getSeverity()); $this->assertSame($error['file'], $exception->getFile()); diff --git a/src/Symfony/Component/DependencyInjection/Loader/FileLoader.php b/src/Symfony/Component/DependencyInjection/Loader/FileLoader.php index 40cf8f9ee4cae..5bc7f347359e9 100644 --- a/src/Symfony/Component/DependencyInjection/Loader/FileLoader.php +++ b/src/Symfony/Component/DependencyInjection/Loader/FileLoader.php @@ -105,7 +105,7 @@ private function findClasses($namespace, $pattern, $excludePattern) $pattern = $parameterBag->unescapeValue($parameterBag->resolveValue($pattern)); $classes = array(); - $extRegexp = defined('HHVM_VERSION') ? '/\\.(?:php|hh)$/' : '/\\.php$/'; + $extRegexp = '/\\.php$/'; $prefixLen = null; foreach ($this->glob($pattern, true, $resource) as $path => $info) { if (null === $prefixLen) { diff --git a/src/Symfony/Component/DependencyInjection/Tests/Compiler/FactoryReturnTypePassTest.php b/src/Symfony/Component/DependencyInjection/Tests/Compiler/FactoryReturnTypePassTest.php index f37248a717d77..e4d16a1f60c5b 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Compiler/FactoryReturnTypePassTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Compiler/FactoryReturnTypePassTest.php @@ -52,12 +52,8 @@ public function testProcess() /** * @dataProvider returnTypesProvider */ - public function testReturnTypes($factory, $returnType, $hhvmSupport = true) + public function testReturnTypes($factory, $returnType) { - if (!$hhvmSupport && defined('HHVM_VERSION')) { - $this->markTestSkipped('Scalar typehints not supported by hhvm.'); - } - $container = new ContainerBuilder(); $service = $container->register('service'); @@ -73,7 +69,7 @@ public function returnTypesProvider() { return array( // must be loaded before the function as they are in the same file - array(array(FactoryDummy::class, 'createBuiltin'), null, false), + array(array(FactoryDummy::class, 'createBuiltin'), null), array(array(FactoryDummy::class, 'createParent'), FactoryParent::class), array(array(FactoryDummy::class, 'createSelf'), FactoryDummy::class), array(factoryFunction::class, FactoryDummy::class), diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/FactoryDummy.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/FactoryDummy.php index da984b562a39d..b7ceac7d8a4eb 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/FactoryDummy.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/FactoryDummy.php @@ -21,7 +21,6 @@ public function create(): \stdClass { } - // Not supported by hhvm public function createBuiltin(): int { } diff --git a/src/Symfony/Component/DependencyInjection/Tests/Loader/IniFileLoaderTest.php b/src/Symfony/Component/DependencyInjection/Tests/Loader/IniFileLoaderTest.php index 66fe419b9d806..84c934c08614f 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Loader/IniFileLoaderTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Loader/IniFileLoaderTest.php @@ -49,10 +49,6 @@ public function testTypeConversions($key, $value, $supported) */ public function testTypeConversionsWithNativePhp($key, $value, $supported) { - if (defined('HHVM_VERSION_ID')) { - return $this->markTestSkipped(); - } - if (!$supported) { $this->markTestSkipped(sprintf('Converting the value "%s" to "%s" is not supported by the IniFileLoader.', $key, $value)); } diff --git a/src/Symfony/Component/Filesystem/Filesystem.php b/src/Symfony/Component/Filesystem/Filesystem.php index a550e8da14f56..f5d20d00d9050 100644 --- a/src/Symfony/Component/Filesystem/Filesystem.php +++ b/src/Symfony/Component/Filesystem/Filesystem.php @@ -247,7 +247,7 @@ public function chgrp($files, $group, $recursive = false) $this->chgrp(new \FilesystemIterator($file), $group, true); } if (is_link($file) && function_exists('lchgrp')) { - if (true !== @lchgrp($file, $group) || (defined('HHVM_VERSION') && !posix_getgrnam($group))) { + if (true !== @lchgrp($file, $group)) { throw new IOException(sprintf('Failed to chgrp file "%s".', $file), 0, null, $file); } } else { diff --git a/src/Symfony/Component/Filesystem/Tests/FilesystemTest.php b/src/Symfony/Component/Filesystem/Tests/FilesystemTest.php index 2aa232d654e02..929ab582c8355 100644 --- a/src/Symfony/Component/Filesystem/Tests/FilesystemTest.php +++ b/src/Symfony/Component/Filesystem/Tests/FilesystemTest.php @@ -449,10 +449,6 @@ public function testChmodWithWrongModLeavesPreviousPermissionsUntouched() { $this->markAsSkippedIfChmodIsMissing(); - if (defined('HHVM_VERSION')) { - $this->markTestSkipped('chmod() changes permissions even when passing invalid modes on HHVM'); - } - $dir = $this->workspace.DIRECTORY_SEPARATOR.'file'; touch($dir); @@ -1426,10 +1422,6 @@ public function testDumpFileOverwritesAnExistingFile() public function testDumpFileWithFileScheme() { - if (defined('HHVM_VERSION')) { - $this->markTestSkipped('HHVM does not handle the file:// scheme correctly'); - } - $scheme = 'file://'; $filename = $scheme.$this->workspace.DIRECTORY_SEPARATOR.'foo'.DIRECTORY_SEPARATOR.'baz.txt'; @@ -1476,10 +1468,6 @@ public function testAppendToFile() public function testAppendToFileWithScheme() { - if (defined('HHVM_VERSION')) { - $this->markTestSkipped('HHVM does not handle the file:// scheme correctly'); - } - $scheme = 'file://'; $filename = $scheme.$this->workspace.DIRECTORY_SEPARATOR.'foo'.DIRECTORY_SEPARATOR.'baz.txt'; $this->filesystem->dumpFile($filename, 'foo'); diff --git a/src/Symfony/Component/Finder/Iterator/RecursiveDirectoryIterator.php b/src/Symfony/Component/Finder/Iterator/RecursiveDirectoryIterator.php index f56990aa70d31..8fcc9ac857ebf 100644 --- a/src/Symfony/Component/Finder/Iterator/RecursiveDirectoryIterator.php +++ b/src/Symfony/Component/Finder/Iterator/RecursiveDirectoryIterator.php @@ -132,11 +132,6 @@ public function isRewindable() return $this->rewindable; } - // workaround for an HHVM bug, should be removed when https://github.com/facebook/hhvm/issues/7281 is fixed - if ('' === $this->getPath()) { - return $this->rewindable = false; - } - if (false !== $stream = @opendir($this->getPath())) { $infos = stream_get_meta_data($stream); closedir($stream); diff --git a/src/Symfony/Component/HttpFoundation/JsonResponse.php b/src/Symfony/Component/HttpFoundation/JsonResponse.php index cf1a11ea2c07b..8794dda688d1d 100644 --- a/src/Symfony/Component/HttpFoundation/JsonResponse.php +++ b/src/Symfony/Component/HttpFoundation/JsonResponse.php @@ -139,23 +139,16 @@ public function setJson($json) */ public function setData($data = array()) { - if (defined('HHVM_VERSION')) { - // HHVM does not trigger any warnings and let exceptions - // thrown from a JsonSerializable object pass through. - // If only PHP did the same... + try { + // PHP 5.4 and up wrap exceptions thrown by JsonSerializable + // objects in a new exception that needs to be removed. + // Fortunately, PHP 5.5 and up do not trigger any warning anymore. $data = json_encode($data, $this->encodingOptions); - } else { - try { - // PHP 5.4 and up wrap exceptions thrown by JsonSerializable - // objects in a new exception that needs to be removed. - // Fortunately, PHP 5.5 and up do not trigger any warning anymore. - $data = json_encode($data, $this->encodingOptions); - } catch (\Exception $e) { - if ('Exception' === get_class($e) && 0 === strpos($e->getMessage(), 'Failed calling ')) { - throw $e->getPrevious() ?: $e; - } - throw $e; + } catch (\Exception $e) { + if ('Exception' === get_class($e) && 0 === strpos($e->getMessage(), 'Failed calling ')) { + throw $e->getPrevious() ?: $e; } + throw $e; } if (JSON_ERROR_NONE !== json_last_error()) { diff --git a/src/Symfony/Component/HttpFoundation/Response.php b/src/Symfony/Component/HttpFoundation/Response.php index 4af1e0bae2ecf..943226ccb5d1a 100644 --- a/src/Symfony/Component/HttpFoundation/Response.php +++ b/src/Symfony/Component/HttpFoundation/Response.php @@ -1258,8 +1258,7 @@ public static function closeOutputBuffers($targetLevel, $flush) { $status = ob_get_status(true); $level = count($status); - // PHP_OUTPUT_HANDLER_* are not defined on HHVM 3.3 - $flags = defined('PHP_OUTPUT_HANDLER_REMOVABLE') ? PHP_OUTPUT_HANDLER_REMOVABLE | ($flush ? PHP_OUTPUT_HANDLER_FLUSHABLE : PHP_OUTPUT_HANDLER_CLEANABLE) : -1; + $flags = PHP_OUTPUT_HANDLER_REMOVABLE | ($flush ? PHP_OUTPUT_HANDLER_FLUSHABLE : PHP_OUTPUT_HANDLER_CLEANABLE); while ($level-- > $targetLevel && ($s = $status[$level]) && (!isset($s['del']) ? !isset($s['flags']) || $flags === ($s['flags'] & $flags) : $s['del'])) { if ($flush) { diff --git a/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/MemcacheSessionHandlerTest.php b/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/MemcacheSessionHandlerTest.php index 06193c8befbeb..21c1fe33f0e06 100644 --- a/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/MemcacheSessionHandlerTest.php +++ b/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/MemcacheSessionHandlerTest.php @@ -31,10 +31,6 @@ class MemcacheSessionHandlerTest extends TestCase protected function setUp() { - if (defined('HHVM_VERSION')) { - $this->markTestSkipped('PHPUnit_MockObject cannot mock the Memcache class on HHVM. See https://github.com/sebastianbergmann/phpunit-mock-objects/pull/289'); - } - parent::setUp(); $this->memcache = $this->getMockBuilder('Memcache')->getMock(); $this->storage = new MemcacheSessionHandler( diff --git a/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/MemcachedSessionHandlerTest.php b/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/MemcachedSessionHandlerTest.php index 2e7be359efcff..5bb2db0699292 100644 --- a/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/MemcachedSessionHandlerTest.php +++ b/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/MemcachedSessionHandlerTest.php @@ -32,10 +32,6 @@ class MemcachedSessionHandlerTest extends TestCase protected function setUp() { - if (defined('HHVM_VERSION')) { - $this->markTestSkipped('PHPUnit_MockObject cannot mock the Memcached class on HHVM. See https://github.com/sebastianbergmann/phpunit-mock-objects/pull/289'); - } - parent::setUp(); if (version_compare(phpversion('memcached'), '2.2.0', '>=') && version_compare(phpversion('memcached'), '3.0.0b1', '<')) { diff --git a/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/PdoSessionHandlerTest.php b/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/PdoSessionHandlerTest.php index a47120f1807e2..94d702c020490 100644 --- a/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/PdoSessionHandlerTest.php +++ b/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/PdoSessionHandlerTest.php @@ -136,10 +136,6 @@ public function testReadWriteReadWithNullByte() public function testReadConvertsStreamToString() { - if (defined('HHVM_VERSION')) { - $this->markTestSkipped('PHPUnit_MockObject cannot mock the PDOStatement class on HHVM. See https://github.com/sebastianbergmann/phpunit-mock-objects/pull/289'); - } - $pdo = new MockPdo('pgsql'); $pdo->prepareResult = $this->getMockBuilder('PDOStatement')->getMock(); @@ -157,10 +153,6 @@ public function testReadConvertsStreamToString() public function testReadLockedConvertsStreamToString() { - if (defined('HHVM_VERSION')) { - $this->markTestSkipped('PHPUnit_MockObject cannot mock the PDOStatement class on HHVM. See https://github.com/sebastianbergmann/phpunit-mock-objects/pull/289'); - } - $pdo = new MockPdo('pgsql'); $selectStmt = $this->getMockBuilder('PDOStatement')->getMock(); $insertStmt = $this->getMockBuilder('PDOStatement')->getMock(); diff --git a/src/Symfony/Component/Intl/Tests/Data/Bundle/Reader/IntlBundleReaderTest.php b/src/Symfony/Component/Intl/Tests/Data/Bundle/Reader/IntlBundleReaderTest.php index cfffd2b7cc0d8..1ca785bf6a460 100644 --- a/src/Symfony/Component/Intl/Tests/Data/Bundle/Reader/IntlBundleReaderTest.php +++ b/src/Symfony/Component/Intl/Tests/Data/Bundle/Reader/IntlBundleReaderTest.php @@ -51,10 +51,6 @@ public function testReadFollowsAlias() public function testReadDoesNotFollowFallback() { - if (defined('HHVM_VERSION')) { - $this->markTestSkipped('ResourceBundle does not support disabling fallback properly on HHVM.'); - } - // "ro_MD" -> "ro" $data = $this->reader->read(__DIR__.'/Fixtures/res', 'ro_MD'); @@ -67,10 +63,6 @@ public function testReadDoesNotFollowFallback() public function testReadDoesNotFollowFallbackAlias() { - if (defined('HHVM_VERSION')) { - $this->markTestSkipped('ResourceBundle does not support disabling fallback properly on HHVM.'); - } - // "mo" = "ro_MD" -> "ro" $data = $this->reader->read(__DIR__.'/Fixtures/res', 'mo'); diff --git a/src/Symfony/Component/Intl/Tests/DateFormatter/AbstractIntlDateFormatterTest.php b/src/Symfony/Component/Intl/Tests/DateFormatter/AbstractIntlDateFormatterTest.php index 9c5cd9fdd11c0..2536bb3533403 100644 --- a/src/Symfony/Component/Intl/Tests/DateFormatter/AbstractIntlDateFormatterTest.php +++ b/src/Symfony/Component/Intl/Tests/DateFormatter/AbstractIntlDateFormatterTest.php @@ -326,7 +326,7 @@ public function testFormatTimezone($pattern, $timezone, $expected) public function formatTimezoneProvider() { - $cases = array( + return array( array('z', 'GMT', 'GMT'), array('zz', 'GMT', 'GMT'), array('zzz', 'GMT', 'GMT'), @@ -365,20 +365,13 @@ public function formatTimezoneProvider() array('zzzzz', 'Etc/Zulu', 'Coordinated Universal Time'), array('zzzzz', 'Etc/UCT', 'Coordinated Universal Time'), array('zzzzz', 'Etc/Greenwich', 'Greenwich Mean Time'), - ); - - if (!defined('HHVM_VERSION')) { - // these timezones are not considered valid in HHVM - $cases = array_merge($cases, array( - array('z', 'GMT+03:00', 'GMT+3'), - array('zz', 'GMT+03:00', 'GMT+3'), - array('zzz', 'GMT+03:00', 'GMT+3'), - array('zzzz', 'GMT+03:00', 'GMT+03:00'), - array('zzzzz', 'GMT+03:00', 'GMT+03:00'), - )); - } - return $cases; + array('z', 'GMT+03:00', 'GMT+3'), + array('zz', 'GMT+03:00', 'GMT+3'), + array('zzz', 'GMT+03:00', 'GMT+3'), + array('zzzz', 'GMT+03:00', 'GMT+03:00'), + array('zzzzz', 'GMT+03:00', 'GMT+03:00'), + ); } public function testFormatWithGmtTimezone() @@ -428,10 +421,6 @@ public function testFormatWithDateTimeZoneGmt() public function testFormatWithDateTimeZoneGmtOffset() { - if (defined('HHVM_VERSION_ID')) { - $this->markTestSkipped('See https://github.com/facebook/hhvm/issues/5875'); - } - $formatter = $this->getDateFormatter('en', IntlDateFormatter::MEDIUM, IntlDateFormatter::SHORT, new \DateTimeZone('GMT+03:00'), IntlDateFormatter::GREGORIAN, 'zzzz'); $this->assertEquals('GMT+03:00', $formatter->format(0)); diff --git a/src/Symfony/Component/Intl/Util/IntlTestHelper.php b/src/Symfony/Component/Intl/Util/IntlTestHelper.php index 12c3ff05913c5..ca9a0b59be437 100644 --- a/src/Symfony/Component/Intl/Util/IntlTestHelper.php +++ b/src/Symfony/Component/Intl/Util/IntlTestHelper.php @@ -42,7 +42,7 @@ public static function requireIntl(TestCase $testCase, $minimumIcuVersion = null // * the intl extension is loaded with version Intl::getIcuStubVersion() // * the intl extension is not loaded - if (($minimumIcuVersion || defined('HHVM_VERSION_ID')) && IcuVersion::compare(Intl::getIcuVersion(), $minimumIcuVersion, '<', 1)) { + if ($minimumIcuVersion && IcuVersion::compare(Intl::getIcuVersion(), $minimumIcuVersion, '<', 1)) { $testCase->markTestSkipped('ICU version '.$minimumIcuVersion.' is required.'); } diff --git a/src/Symfony/Component/Process/PhpExecutableFinder.php b/src/Symfony/Component/Process/PhpExecutableFinder.php index db31cc1b3ce8b..aba18e9c1c6ab 100644 --- a/src/Symfony/Component/Process/PhpExecutableFinder.php +++ b/src/Symfony/Component/Process/PhpExecutableFinder.php @@ -38,11 +38,6 @@ public function find($includeArgs = true) $args = $this->findArguments(); $args = $includeArgs && $args ? ' '.implode(' ', $args) : ''; - // HHVM support - if (defined('HHVM_VERSION')) { - return (getenv('PHP_BINARY') ?: PHP_BINARY).$args; - } - // PHP_BINARY return the current sapi executable if (PHP_BINARY && in_array(PHP_SAPI, array('cli', 'cli-server', 'phpdbg')) && is_file(PHP_BINARY)) { return PHP_BINARY.$args; @@ -78,10 +73,7 @@ public function find($includeArgs = true) public function findArguments() { $arguments = array(); - - if (defined('HHVM_VERSION')) { - $arguments[] = '--php'; - } elseif ('phpdbg' === PHP_SAPI) { + if ('phpdbg' === PHP_SAPI) { $arguments[] = '-qrr'; } diff --git a/src/Symfony/Component/Process/Process.php b/src/Symfony/Component/Process/Process.php index fb12d393abad7..cf471ee592b8b 100644 --- a/src/Symfony/Component/Process/Process.php +++ b/src/Symfony/Component/Process/Process.php @@ -1449,7 +1449,7 @@ protected function isSigchildEnabled() return self::$sigchild; } - if (!function_exists('phpinfo') || defined('HHVM_VERSION')) { + if (!function_exists('phpinfo')) { return self::$sigchild = false; } diff --git a/src/Symfony/Component/Process/Tests/ExecutableFinderTest.php b/src/Symfony/Component/Process/Tests/ExecutableFinderTest.php index bc692f6a75df6..68d6110e3a8d1 100644 --- a/src/Symfony/Component/Process/Tests/ExecutableFinderTest.php +++ b/src/Symfony/Component/Process/Tests/ExecutableFinderTest.php @@ -91,7 +91,7 @@ public function testFindWithOpenBaseDir() $this->markTestSkipped('Cannot test when open_basedir is set'); } - $this->iniSet('open_basedir', dirname(PHP_BINARY).(!defined('HHVM_VERSION') || HHVM_VERSION_ID >= 30800 ? PATH_SEPARATOR.'/' : '')); + $this->iniSet('open_basedir', dirname(PHP_BINARY).PATH_SEPARATOR.'/'); $finder = new ExecutableFinder(); $result = $finder->find($this->getPhpBinaryName()); @@ -109,7 +109,7 @@ public function testFindProcessInOpenBasedir() } $this->setPath(''); - $this->iniSet('open_basedir', PHP_BINARY.(!defined('HHVM_VERSION') || HHVM_VERSION_ID >= 30800 ? PATH_SEPARATOR.'/' : '')); + $this->iniSet('open_basedir', PHP_BINARY.PATH_SEPARATOR.'/'); $finder = new ExecutableFinder(); $result = $finder->find($this->getPhpBinaryName(), false); diff --git a/src/Symfony/Component/Process/Tests/PhpExecutableFinderTest.php b/src/Symfony/Component/Process/Tests/PhpExecutableFinderTest.php index b08ad5d3b734f..1055384cc59bb 100644 --- a/src/Symfony/Component/Process/Tests/PhpExecutableFinderTest.php +++ b/src/Symfony/Component/Process/Tests/PhpExecutableFinderTest.php @@ -24,10 +24,6 @@ class PhpExecutableFinderTest extends TestCase */ public function testFind() { - if (defined('HHVM_VERSION')) { - $this->markTestSkipped('Should not be executed in HHVM context.'); - } - $f = new PhpExecutableFinder(); $current = PHP_BINARY; @@ -37,23 +33,6 @@ public function testFind() $this->assertEquals($current, $f->find(false), '::find() returns the executable PHP'); } - /** - * tests find() with the env var / constant PHP_BINARY with HHVM. - */ - public function testFindWithHHVM() - { - if (!defined('HHVM_VERSION')) { - $this->markTestSkipped('Should be executed in HHVM context.'); - } - - $f = new PhpExecutableFinder(); - - $current = getenv('PHP_BINARY') ?: PHP_BINARY; - - $this->assertEquals($current.' --php', $f->find(), '::find() returns the executable PHP'); - $this->assertEquals($current, $f->find(false), '::find() returns the executable PHP'); - } - /** * tests find() with the env var PHP_PATH. */ @@ -61,9 +40,7 @@ public function testFindArguments() { $f = new PhpExecutableFinder(); - if (defined('HHVM_VERSION')) { - $this->assertEquals($f->findArguments(), array('--php'), '::findArguments() returns HHVM arguments'); - } elseif ('phpdbg' === PHP_SAPI) { + if ('phpdbg' === PHP_SAPI) { $this->assertEquals($f->findArguments(), array('-qrr'), '::findArguments() returns phpdbg arguments'); } else { $this->assertEquals($f->findArguments(), array(), '::findArguments() returns no arguments'); diff --git a/src/Symfony/Component/Routing/Tests/Generator/Dumper/PhpGeneratorDumperTest.php b/src/Symfony/Component/Routing/Tests/Generator/Dumper/PhpGeneratorDumperTest.php index f84802b35b255..4b2e5b196dc06 100644 --- a/src/Symfony/Component/Routing/Tests/Generator/Dumper/PhpGeneratorDumperTest.php +++ b/src/Symfony/Component/Routing/Tests/Generator/Dumper/PhpGeneratorDumperTest.php @@ -86,10 +86,6 @@ public function testDumpWithRoutes() public function testDumpWithTooManyRoutes() { - if (defined('HHVM_VERSION_ID')) { - $this->markTestSkipped('HHVM consumes too much memory on this test.'); - } - $this->routeCollection->add('Test', new Route('/testing/{foo}')); for ($i = 0; $i < 32769; ++$i) { $this->routeCollection->add('route_'.$i, new Route('/route_'.$i)); diff --git a/src/Symfony/Component/Serializer/Tests/Normalizer/DataUriNormalizerTest.php b/src/Symfony/Component/Serializer/Tests/Normalizer/DataUriNormalizerTest.php index 4bc94435992f8..e6bd915aebd43 100644 --- a/src/Symfony/Component/Serializer/Tests/Normalizer/DataUriNormalizerTest.php +++ b/src/Symfony/Component/Serializer/Tests/Normalizer/DataUriNormalizerTest.php @@ -156,7 +156,7 @@ public function testValidData($uri) public function validUriProvider() { - $data = array( + return array( array('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQAQMAAAAlPW0iAAAABlBMVEUAAAD///+l2Z/dAAAAM0lEQVR4nGP4/5/h/1+G/58ZDrAz3D/McH8yw83NDDeNGe4Ug9C9zwz3gVLMDA/A6P9/AFGGFyjOXZtQAAAAAElFTkSuQmCC'), array('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAIBAMAAAA2IaO4AAAAFVBMVEXk5OTn5+ft7e319fX29vb5+fn///++GUmVAAAALUlEQVQIHWNICnYLZnALTgpmMGYIFWYIZTA2ZFAzTTFlSDFVMwVyQhmAwsYMAKDaBy0axX/iAAAAAElFTkSuQmCC'), array('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAIBAMAAAA2IaO4AAAAFVBMVEXk5OTn5+ft7e319fX29vb5+fn///++GUmVAAAALUlEQVQIHWNICnYLZnALTgpmMGYIFWYIZTA2ZFAzTTFlSDFVMwVyQhmAwsYMAKDaBy0axX/iAAAAAElFTkSuQmCC '), @@ -167,14 +167,8 @@ public function validUriProvider() array('data:application/ld+json;base64,eyJAaWQiOiAiL2ZvbyJ9'), array('data:application/vnd.ms-word.document.macroenabled.12;base64,UEsDBBQABgAIAAAAIQBnzQ+udAEAADoFAAATAAgCW0NvbnRlbnRfVHlwZXNdLnhtbCCiBAIooAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC0lMtOwzAQRfdI/EPkLUrcskAINe0CyhIqUT7AtSepIX7Idl9/zzhpI1TRBFG6iZTM3HvPOJmMJltVJWtwXhqdk2E2IAloboTUZU7e58/pPUl8YFqwymjIyQ48mYyvr0bznQWfoFr7nCxDsA+Uer4ExXxmLGisFMYpFvDWldQy/slKoLeDwR3lRgfQIQ3Rg4xHT1CwVRWS6RYfNyQoJ8lj0xejcsKsrSRnAcs0VumPOgeV7xCutTiiS/dkGSrrHr+U1t+cTviwUB4lSBVHqwuoecXjdFJAMmMuvDCFDXRjnKDC8JVCUdY9XGRUPo2SrJUoxp2ZaraoAKtM6gPhyTQfdhX4X2QdnYcpCsmhDY5e1hkO3uM3oaqs8e2PhxBQcAmAvXMvwgYWbxej+GbeC1Jg7jy+uv/HaK17IQLuJjTX4dkctU1XJHbOnLEed939YezDUkZ1igNbcEF2f3VtIlqfPR/EfRcgfsim9Z9v/AUAAP//AwBQSwMEFAAGAAgAAAAhAMfCJ7z/AAAA3wIAAAsACAJfcmVscy8ucmVscyCiBAIooAACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACsks1KAzEQgO+C7xDm3s22iog024sIvYmsDzAm093o5odkqu3bG0XUhWUR7HH+Pr5JZr05uEG8Uso2eAXLqgZBXgdjfafgsb1bXIPIjN7gEDwpOFKGTXN+tn6gAbkM5d7GLArFZwU9c7yRMuueHOYqRPKlsgvJIZcwdTKifsGO5Kqur2T6zYBmxBRboyBtzQWI9hjpf2zpiNEgo9Qh0SKmMp3Yll1Ei6kjVmCCvi/p/NlRFTLIaaHLvwuF3c5qug1678jzlBcdmLwhM6+EMc4ZLU9pNO74kXkLyUjzlZ6zWZ32w7jfuyePdph4l+9a9Ryp+xCSo7Ns3gEAAP//AwBQSwMEFAAGAAgAAAAhABOqPof2AAAAMQMAABwACAF3b3JkL19yZWxzL2RvY3VtZW50LnhtbC5yZWxzIKIEASigAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAArJLLasMwEEX3hf6DmH0tO31QQuRsSiHb1v0ARR4/qCwJzfThv69oSOvQYLrw8l4x955Bs9l+Dla8Y6TeOwVFloNAZ3zdu1bBS/V4dQ+CWLtaW+9QwYgE2/LyYvOEVnMaoq4PJFKKIwUdc1hLSabDQVPmA7r00vg4aE4ytjJo86pblKs8v5NxmgHlSabY1Qrirr4GUY0B/5Ptm6Y3+ODN24COz1TID9w/I3NajlKsji2ygomZpUSQ50FulgRpvONK7y3+YvxYcxC3S0Jwmp0AfMuDWcwxFEsyEI8WJ59x0HP1q0Xr/1zD0TkiyJNDL78AAAD//wMAUEsDBBQABgAIAAAAIQAz6gHKYAIAAAIHAAARAAAAd29yZC9kb2N1bWVudC54bWykld1u2jAUx+8n7R2Q70sSCpRGQKVBh9A0qRrb9WQcJ7GIfSzbQLs32nPsxXacL7JNQ7QgFPt8+Of/sWNn+vAsi96BGytAzUjUD0mPKwaJUNmMfPv68WZCetZRldACFJ+RF27Jw/z9u+kxToDtJVeuhwhl46NmM5I7p+MgsCznktq+FMyAhdT1GcgA0lQwHhzBJMEgjMKypw0wbi3Ot6DqQC2pcRIuo0nKmu4gDCdoC9Uy/lUEmisMpmAkdWiaDEeY3V7fIFNTJ7aiEO7Fs8Yt5jAje6PimnHT6vBjYhQQH2TRJMO53Epo3TQjzCUiqyHLeslLeYHhBQoGZXOhT+v2VhoG8wZytuBOsUcdDa/b9KWhR2xOwEvkJ9UgWVTKzxOj8IId8Yh2xCUS/pyzUdJ9+Y5vW5rO4kaj1wEGfwN0dt3mrAzs9YkmrqOt1a5l+avkFax6k7ul2evEbHKq8QRKFq8zBYZuC1SEW9bDVe/515rM8YrbQvLiW43uYaypoetkRsLB8hb/Q1J6HX923ntX/9Ab43WafMHEcHQXLUaD1rXkKd0Xzkduw9FitChnMf7h5p9+/TwINQ183z9L9xZg5y+ojaPGIUb4+T1PUYmKv6/gA2U7EnRzH1XSZgYlSvuw5cw9mf+r22Dcex+j0eQ+LJXpbPMDo3gioug+LOfNsT+eDEuyT/hMPdIBHtxoGFXViyx3J3MLzoE82QVPO9Gc04TjFXgXTryZAriOme1dadbTMSgseq2mjFc5pRu/RCsjfNGFUPxJOIYqb8dN9VXhZbfa0OD08Zr/BgAA//8DAFBLAwQUAAYACAAAACEAJyDgAjMGAACMGgAAFQAAAHdvcmQvdGhlbWUvdGhlbWUxLnhtbOxZTYvbRhi+F/ofhO6OZVvyxxJvsGU7abObhOwmJcexNJYmO9KYmdHumhAoybFQKE1LDw301kJpG0igl/TUn7JtSptC/kJHI8uesccsaTawhNhgzcfzvvPM+848I1kXLx0n2DqElCGSdu3aBce2YBqQEKVR1761P6q0bYtxkIYAkxR27Rlk9qXtDz+4CLZ4DBNoCfuUbYGuHXM+3apWWSCaAbtApjAVfRNCE8BFlUbVkIIj4TfB1brjNKsJQKltpSARbvfj338Qzq5PJiiA9nbpfYjFT8pZ3hBgupf7hnOTfkYhyCQ2PKjlFzZjPqbWIcBdWwwUkqN9eMxtCwPGRUfXduTHrm5frC6MMN9gq9iN5GduNzcID+rSjkbjhaHrem6zt/AvAZiv44atYXPYXPiTABAEYqYFFxXr9Tv9gTfHKqCiaPA9aA0aNQ2v+G+s4Xte/tXwElQU3TX8aOQvY6iAiqJniEmr7rsaXoKKYnMN33J6A7el4SUoxig9WEM7XrPhl7NdQCYEXzHCO547atXn8CWqqqyuwj7lm9ZaAu4SOhIAmVzAUWrx2RROQCBwPsBoTJG1g6JYLLwpSAkTzU7dGTkN8Zt/XVmSEQFbECjWRVPA1ppyPhYLKJryrv2x8GorkFfPf3r1/Kl18uDZyYNfTx4+PHnwi8HqCkgj1erl91/8+/hT65+n37189JUZz1T8nz9/9sdvX5qBXAW++PrJX8+evPjm879/fGSA9ygYq/B9lEBmXYNH1k2SiIkZBoBj+noW+zFAqkUvjRhIQW5jQA95rKGvzQAGBlwf6hG8TYVMmICXs7sa4b2YZhwZgFfjRAPuEoL7hBrndDUfS41ClkbmwWmm4m4CcGga21/J7zCbivWOTC79GGo0b2CRchDBFHIr7yMHEBrM7iCkxXUXBZQwMuHWHWT1ATKGZB+NtdW0NLqCEpGXmYmgyLcWm93bVp9gk/sBPNSRYlcAbHIJsRbGyyDjIDEyBglWkTuAxyaSezMaaAFnXGQ6gphYwxAyZrK5Tmca3atCXsxp38WzREdSjg5MyB1AiIockAM/BsnUyBmlsYr9iB2IJQqsG4QbSRB9h+R1kQeQbkz3bQS1dJ++t28JZTUvkLwno6YtAYm+H2d4AqB0Xl3R8wSlp4r7iqx7b1fWhZC++PaxWXfPpaD3KDLuqFUZ34RbFW+f0BCdf+0egCy9AcV2MUDfS/d76X7npXvTfj57wV5qtLyJL2/VpZtk4337BGG8x2cY7jCp7kxMLxyJRlmRRovHhGksivPhNFxEgSxblPBPEI/3YjAVw9TkCBGbu46YNSVMnA+y2eg778BZskvCorVWK59MhQHgy3ZxvpTt4jTiRWuztXwEW7iXtUg+KpcEctvXIaEMppNoGEi0ysZTSMiZnQmLjoFFO3e/kYW8zLMi9p8F8n81PLdgJNYbwDDM81TYl9k980xvCqY+7bphep2c69lkWiOhLDedhLIMYxDC1eYzznVnmVKNXh6KdRqt9tvIdS4iK9qAU71mHYk91/CEmwBMu/ZE3BmKYjIV/liumwBHadcO+DzQ/0dZppTxAWBxAZNdxfwTxCG1MErEWlfTgNMlt1q9lc/xnJLrOOcvcvKiJhlOJjDgG1qWVdFXODH2viE4r5BMkN6LwyNrjDN6E4hAea1aHsAQMb6IZoiosriXUVyRq/lW1P4xW25RgKcxmJ8oqpgXcFle0FHmIZmuzkqvzyczjvIkvfGpe7pR3qGI5oYDJD81zfrx9g55hdVS9zVWhXSval2n1LpNp8SbHwgKteVgGrWcsYHaslWndoY3BMpwi6W56Yw469NgddXmB0R5Xylra68myPiuWPkDcbuaYc4kVXgsnhH88k/lQglka6kux9zKKOra9xyv5/p1z684bW9YcRuuU2l7vUal53mN2tCrOYN+/b4ICo+TmleMPRLPM3g2f/Ui29devyTlbfaFgCRVIt+rVKWxfP1Sq2uvX4r3LtZ+3m9bSETmXrM+6jQ6/Wal0+iNKu6g3650/Ga/Mmj6rcFo4Hvtzui+bR1KsNtr+G5z2K40a75fcZtOTr/dqbTcer3ntnrtodu7P4+1mHl5LcMreW3/BwAA//8DAFBLAwQKAAAAAAAAACEAahPYDYwlAACMJQAAFwAAAGRvY1Byb3BzL3RodW1ibmFpbC5qcGVn/9j/4AAQSkZJRgABAQAASABIAAD/4QCARXhpZgAATU0AKgAAAAgABAEaAAUAAAABAAAAPgEbAAUAAAABAAAARgEoAAMAAAABAAIAAIdpAAQAAAABAAAATgAAAAAAAABIAAAAAQAAAEgAAAABAAOgAQADAAAAAQABAACgAgAEAAAAAQAAAWmgAwAEAAAAAQAAAgAAAAAA/+0AOFBob3Rvc2hvcCAzLjAAOEJJTQQEAAAAAAAAOEJJTQQlAAAAAAAQ1B2M2Y8AsgTpgAmY7PhCfv/AABEIAgABaQMBEQACEQEDEQH/xAAfAAABBQEBAQEBAQAAAAAAAAAAAQIDBAUGBwgJCgv/xAC1EAACAQMDAgQDBQUEBAAAAX0BAgMABBEFEiExQQYTUWEHInEUMoGRoQgjQrHBFVLR8CQzYnKCCQoWFxgZGiUmJygpKjQ1Njc4OTpDREVGR0hJSlNUVVZXWFlaY2RlZmdoaWpzdHV2d3h5eoOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4eLj5OXm5+jp6vHy8/T19vf4+fr/xAAfAQADAQEBAQEBAQEBAAAAAAAAAQIDBAUGBwgJCgv/xAC1EQACAQIEBAMEBwUEBAABAncAAQIDEQQFITEGEkFRB2FxEyIygQgUQpGhscEJIzNS8BVictEKFiQ04SXxFxgZGiYnKCkqNTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqCg4SFhoeIiYqSk5SVlpeYmZqio6Slpqeoqaqys7S1tre4ubrCw8TFxsfIycrS09TV1tfY2dri4+Tl5ufo6ery8/T19vf4+fr/2wBDAAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQH/2wBDAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQH/3QAEAC7/2gAMAwEAAhEDEQA/AP7Yfgx8GPg9N8HvhRLL8KPhrLLL8NfAskkkngTws8kkj+F9LZ3d200s7uxLMzHczEk5JNAHpX/ClPg3/wBEl+GX/hBeFf8A5W0AH/ClPg3/ANEl+GX/AIQXhX/5W0AH/ClPg3/0SX4Zf+EF4V/+VtAB/wAKU+Df/RJfhl/4QXhX/wCVtAB/wpT4N/8ARJfhl/4QXhX/AOVtAB/wpT4N/wDRJfhl/wCEF4V/+VtAB/wpT4N/9El+GX/hBeFf/lbQAf8AClPg3/0SX4Zf+EF4V/8AlbQAf8KU+Df/AESX4Zf+EF4V/wDlbQAf8KU+Df8A0SX4Zf8AhBeFf/lbQAf8KU+Df/RJfhl/4QXhX/5W0AH/AApT4N/9El+GX/hBeFf/AJW0AH/ClPg3/wBEl+GX/hBeFf8A5W0AH/ClPg3/ANEl+GX/AIQXhX/5W0AH/ClPg3/0SX4Zf+EF4V/+VtAB/wAKU+Df/RJfhl/4QXhX/wCVtAB/wpT4N/8ARJfhl/4QXhX/AOVtAB/wpT4N/wDRJfhl/wCEF4V/+VtAB/wpT4N/9El+GX/hBeFf/lbQAf8AClPg3/0SX4Zf+EF4V/8AlbQAf8KU+Df/AESX4Zf+EF4V/wDlbQAf8KU+Df8A0SX4Zf8AhBeFf/lbQAf8KU+Df/RJfhl/4QXhX/5W0AH/AApT4N/9El+GX/hBeFf/AJW0AH/ClPg3/wBEl+GX/hBeFf8A5W0AH/ClPg3/ANEl+GX/AIQXhX/5W0AH/ClPg3/0SX4Zf+EF4V/+VtAB/wAKU+Df/RJfhl/4QXhX/wCVtAB/wpT4N/8ARJfhl/4QXhX/AOVtAB/wpT4N/wDRJfhl/wCEF4V/+VtAB/wpT4N/9El+GX/hBeFf/lbQAf8AClPg3/0SX4Zf+EF4V/8AlbQAf8KU+Df/AESX4Zf+EF4V/wDlbQAf8KU+Df8A0SX4Zf8AhBeFf/lbQAf8KU+Df/RJfhl/4QXhX/5W0AH/AApT4N/9El+GX/hBeFf/AJW0AH/ClPg3/wBEl+GX/hBeFf8A5W0AH/ClPg3/ANEl+GX/AIQXhX/5W0AH/ClPg3/0SX4Zf+EF4V/+VtAB/wAKU+Df/RJfhl/4QXhX/wCVtAB/wpT4N/8ARJfhl/4QXhX/AOVtAB/wpT4N/wDRJfhl/wCEF4V/+VtAB/wpT4N/9El+GX/hBeFf/lbQAf8AClPg3/0SX4Zf+EF4V/8AlbQB/Nd/wrT4c/8ARP8AwT/4Sug//INAH//Q/ur+Cn/JGvhJ/wBky8B/+orpVAHptABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQB/MvQB/9H+6v4Kf8ka+En/AGTLwH/6iulUAem0AFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFAH8y9AH/0v7q/gp/yRr4Sf8AZMvAf/qK6VQB6bQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAfzL0Af/T/ur+Cn/JGvhJ/wBky8B/+orpVAHptABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQB/MvQB/9T+6v4Kf8ka+En/AGTLwH/6iulUAem0AFABQAUAfP3j79pv4T/DT4n6P8IvFmr3Vj4w1jwRqvxN2GC3TSNH+G3hs6v/AMJj8QPEmsXV5a2Xh3wZ4JTSB/wlPiPVnttK0+81vwpokdxc+IPFfh/SdQAMPQ/2v/gXr2heH9WtvFlrZ6n4g8X6B4Gi8GatfaFpnjPS/Eev+N2+HyafrmjXWsxx6bdaV4lg1DTtasZbxtUstX0rUvCS6fP45gXwu4B6v8L/AIufDX40+GR4x+FfjDSPG3hk3ENqNW0eSZoPNu9I0rxFp7GO5ht7hbfV/DevaD4m0O7aL7LrnhjXtC8SaRPe6JrOmX10AejUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAfzL0Af/1f7q/gp/yRr4Sf8AZMvAf/qK6VQB6bQAUAFABQB4L8Vv2YvgX8b9UbWvij4Ct/FWqP4Yv/BbXsut+JtKlPhTV9K8WaFrWgf8SPWdMT+zNd0Lx14t0TXrbAXW9H1y70zVftliILeIA4/Rv2Jv2Y9AvvDuqaX8Mkg1Pwr4a8O+D9Dv5PF3ju6u7Xw74T+M9h+0J4e06aW68TzG/GnfGDTLTxglzqH2q7mKS6FczzeGbm50eUA9j+Gfwk+Hvwd0e80D4c+H/wDhHdJv5PDUl3a/2rrerec/hD4eeCvhT4dbz9c1LU7lP7O8A/DvwdoOI5lF3/Y/9qX32nWdQ1PUb0A9HoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoAKACgAoA/mXoA/9b+6v4Kf8ka+En/AGTLwH/6iulUAem0AFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFAH8y9AH/1/7q/gp/yRr4Sf8AZMvAf/qK6VQB6bQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAfzL0Af/Q/ur+Cn/JGvhJ/wBky8B/+orpVAHptABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQB/MvQB/9H+6v4Kf8ka+En/AGTLwH/6iulUAem0AFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFAH8y9AH/0v7q/gp/yRr4Sf8AZMvAf/qK6VQB6bQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAfzL0Af/T/ur+Cn/JGvhJ/wBky8B/+orpVAHptABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQB/MvQB/9T+6v4Kf8ka+En/AGTLwH/6iulUAem0AFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFAH8y9AH/1f7q/gp/yRr4Sf8AZMvAf/qK6VQB6bQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAfzL0Af/W/ur+Cn/JGvhJ/wBky8B/+orpVAHptABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQB/MvQB/9f+6v4Kf8ka+En/AGTLwH/6iulUAem0AFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFAH8y9AH/0P7q/gp/yRr4Sf8AZMvAf/qK6VQB6bQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAfzL0Af/R/ur+Cn/JGvhJ/wBky8B/+orpVAHptABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQB/MvQB/9L+6v4Kf8ka+En/AGTLwH/6iulUAem0AFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFAH8y9AH/0/7q/gp/yRr4Sf8AZMvAf/qK6VQB6bQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAfzL0Af/U/ur+Cn/JGvhJ/wBky8B/+orpVAHptABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQB/MvQB/9X+6v4Kf8ka+En/AGTLwH/6iulUAem0AFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFAH8y9AH/1v7q/gp/yRr4Sf8AZMvAf/qK6VQB6bQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAfzL0Af/X/ur+Cn/JGvhJ/wBky8B/+orpVAHptABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQB/MvQB/9D+6v4Kf8ka+En/AGTLwH/6iulUAem0AFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFAH8y9AH/0f7q/gp/yRr4Sf8AZMvAf/qK6VQB6bQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAfzL0Af/S/ur+Cn/JGvhJ/wBky8B/+orpVAHptABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQB/MvQB/9P+6v4Kf8ka+En/AGTLwH/6iulUAem0AFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFAH8y9AH/1P7q/gp/yRr4Sf8AZMvAf/qK6VQB6bQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAfzL0Af/V/ur+Cn/JGvhJ/wBky8B/+orpVAHptABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQB/MvQB/9b+6v4Kf8ka+En/AGTLwH/6iulUAem0AFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFAH8y9AH/1/7q/gp/yRr4Sf8AZMvAf/qK6VQB6bQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAfzL0Af/Q/ur+Cn/JGvhJ/wBky8B/+orpVAHptABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQB/MvQB/9H+6v4Kf8ka+En/AGTLwH/6iulUAem0AFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFAH8y9AH/0v7q/gp/yRr4Sf8AZMvAf/qK6VQB6bQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAfzL0Af/T/ur+Cn/JGvhJ/wBky8B/+orpVAHptABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQB/MvQB/9T+6v4Kf8ka+En/AGTLwH/6iulUAem0AFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFAH8y9AH/1f7q/gp/yRr4Sf8AZMvAf/qK6VQB6bQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAfzL0Af/W/ur+Cn/JGvhJ/wBky8B/+orpVAHptABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQB/MvQB/9f+6v4Kf8ka+En/AGTLwH/6iulUAem0AFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFAH8y9AH/0P7q/gp/yRr4Sf8AZMvAf/qK6VQB6bQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAfzL0Af/R/ur+Cn/JGvhJ/wBky8B/+orpVAHptABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQB/MvQB/9L+6v4Kf8ka+En/AGTLwH/6iulUAem0AFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFAH8y9AH/0/7q/gp/yRr4Sf8AZMvAf/qK6VQB6bQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAfzL0Af/U/ur+Cn/JGvhJ/wBky8B/+orpVAHptABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQB/MvQB/9X+6v4Kf8ka+En/AGTLwH/6iulUAem0AFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFAH8y9AH/1v7q/gp/yRr4Sf8AZMvAf/qK6VQB6bQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAfzL0Af/X/ur+Cn/JGvhJ/wBky8B/+orpVAHptABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQB/MvQB/9D+6v4Kf8ka+En/AGTLwH/6iulUAem0AFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFAH8y9AH/0f7q/gp/yRr4Sf8AZMvAf/qK6VQB6bQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAfzL0Af/S/ur+Cn/JGvhJ/wBky8B/+orpVAHptABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQB/MvQB/9P+6v4Kf8ka+En/AGTLwH/6iulUAem0AFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFAH8y9AH/1P7q/gp/yRr4Sf8AZMvAf/qK6VQB6bQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAfzL0Af/V/ur+Cn/JGvhJ/wBky8B/+orpVAHptABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQB/MvQB/9b+6v4Kf8ka+En/AGTLwH/6iulUAem0AFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFAH8y9AH/1/7q/gp/yRr4Sf8AZMvAf/qK6VQB6bQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAfzL0Af/Q/ur+Cn/JGvhJ/wBky8B/+orpVAHptABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQB/MvQB/9H+6v4Kf8ka+En/AGTLwH/6iulUAem0AFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFAH8y9AH/0v7q/gp/yRr4Sf8AZMvAf/qK6VQB6bQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAfzL0Af/T/ur+Cn/JGvhJ/wBky8B/+orpVAHptABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQB/MvQB/9T+6v4Kf8ka+En/AGTLwH/6iulUAem0AFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFAH8y9AH/1f7q/gp/yRr4Sf8AZMvAf/qK6VQB6bQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAFABQAUAfzL0Af/W/th+DHxn+D0Pwe+FEUvxX+GsUsXw18CxyRyeO/CySRyJ4X0tXR0bUgyOjAqysNysCDgg0Aelf8Lr+Df/AEVr4Zf+F74V/wDllQAf8Lr+Df8A0Vr4Zf8Ahe+Ff/llQAf8Lr+Df/RWvhl/4XvhX/5ZUAH/AAuv4N/9Fa+GX/he+Ff/AJZUAH/C6/g3/wBFa+GX/he+Ff8A5ZUAH/C6/g3/ANFa+GX/AIXvhX/5ZUAH/C6/g3/0Vr4Zf+F74V/+WVAB/wALr+Df/RWvhl/4XvhX/wCWVAB/wuv4N/8ARWvhl/4XvhX/AOWVAB/wuv4N/wDRWvhl/wCF74V/+WVAB/wuv4N/9Fa+GX/he+Ff/llQAf8AC6/g3/0Vr4Zf+F74V/8AllQAf8Lr+Df/AEVr4Zf+F74V/wDllQAf8Lr+Df8A0Vr4Zf8Ahe+Ff/llQAf8Lr+Df/RWvhl/4XvhX/5ZUAH/AAuv4N/9Fa+GX/he+Ff/AJZUAH/C6/g3/wBFa+GX/he+Ff8A5ZUAH/C6/g3/ANFa+GX/AIXvhX/5ZUAH/C6/g3/0Vr4Zf+F74V/+WVAB/wALr+Df/RWvhl/4XvhX/wCWVAB/wuv4N/8ARWvhl/4XvhX/AOWVAB/wuv4N/wDRWvhl/wCF74V/+WVAB/wuv4N/9Fa+GX/he+Ff/llQAf8AC6/g3/0Vr4Zf+F74V/8AllQAf8Lr+Df/AEVr4Zf+F74V/wDllQAf8Lr+Df8A0Vr4Zf8Ahe+Ff/llQAf8Lr+Df/RWvhl/4XvhX/5ZUAH/AAuv4N/9Fa+GX/he+Ff/AJZUAH/C6/g3/wBFa+GX/he+Ff8A5ZUAH/C6/g3/ANFa+GX/AIXvhX/5ZUAH/C6/g3/0Vr4Zf+F74V/+WVAB/wALr+Df/RWvhl/4XvhX/wCWVAB/wuv4N/8ARWvhl/4XvhX/AOWVAB/wuv4N/wDRWvhl/wCF74V/+WVAB/wuv4N/9Fa+GX/he+Ff/llQAf8AC6/g3/0Vr4Zf+F74V/8AllQAf8Lr+Df/AEVr4Zf+F74V/wDllQAf8Lr+Df8A0Vr4Zf8Ahe+Ff/llQAf8Lr+Df/RWvhl/4XvhX/5ZUAH/AAuv4N/9Fa+GX/he+Ff/AJZUAH/C6/g3/wBFa+GX/he+Ff8A5ZUAH/C6/g3/ANFa+GX/AIXvhX/5ZUAH/C6/g3/0Vr4Zf+F74V/+WVAB/wALr+Df/RWvhl/4XvhX/wCWVAH813/Cy/hz/wBFA8E/+FVoP/ydQB//2QAAUEsDBBQABgAIAAAAIQDSXhXfgQMAAEwJAAARAAAAd29yZC9zZXR0aW5ncy54bWy0Vltv2zYUfh/Q/2DouYolxXJdrU4RO/GaIl6D2H3ZGyVRNhFehEPKmjvsv++IFCNvDQp3Rf1i8nznzu8c+937PwUfHShopuQ8iC+iYERloUomd/Pg83YVzoKRNkSWhCtJ58GR6uD91atf3rWZpsagmh6hC6kzUcyDvTF1Nh7rYk8F0ReqphLBSoEgBq+wGwsCT00dFkrUxLCccWaO4ySKpkHvRs2DBmTWuwgFK0BpVZnOJFNVxQraf3kLOCeuM7lRRSOoNDbiGCjHHJTUe1Zr7038X28I7r2Tw7eKOAju9do4OqPcVkH5bHFOep1BDaqgWuMDCe4TZHIIPPnK0XPsC4zdl2hdoXkc2dNp5un3OUj+40Dzcypx0D3LgYDjSV+GKLK7nVRAco6sxHJGmFFwhbT8opQYtVlNocC3QU5PomDcASWtSMPNluQbo2pUORDM4U00c/D+WO+ptIT4A6nu8UmSOrzYEyCFobCpSYFtXSppQHGvV6rflVkirQG77iw0OdAHoAdG2wdWmAaoc2S5P5w2bo7QkSQCi/nXbKxViURvswbY+f3uDGxSsc/9xUAK5x5YSbddEzfmyOkKa9qwL/Ralh8bbRh6tA35gQy+lQC2GyN/wmffHmu6oqTrkf5JwewDrTir1wxAwZ0skR4/LRirKgoYgBFD18g6Bqq1ff5ASYnr9gfjjk9phMu71P7wqJTxqlF0GaXLdOky7dBzkPRNvEyTl5DbOJ29tdM0fo4qsm7xPYA/dRQaCWexJCIHRkbrbjWOO40cnhZMejynOOv0FNk0uQfD0AFaEM5XOHoesAmIrGS6vqGVPfM1gd3gt9eAF6W4Bj4+++pWBIXfQDW1Q1sgtaOGV4knboGIjElzz4SX6ybfeCuJ2+kEamT56QC2T0N72szgE9sRuyeWKla3gnD12FOJw6ajAV2TunZsynfxPOBstzdxRwCDtxJ/Qe0l3yU9llgscZi9kKKrDLX7wyBLvOxE79LLLgfZxMsmgyz1snSQTb1s2slwiVLgTD4hsf2xk1eKc9XS8sOAfyXyW7pg+OKbo8iH5fraYZxpnLQa97BR4LFfLRZPslIVd0hWPLl3i5LbWZIsHJza/W22yKMnbO0jrRZE07LHvGnqTP9adZ9Zsgiv45sknEzTRThLlrfhYpVcx8vrt9N0mfzdz4H/G3T1DwAAAP//AwBQSwMEFAAGAAgAAAAhAPC8NQHcAQAA8QUAABIAAAB3b3JkL2ZvbnRUYWJsZS54bWy8k9tq4zAQhu8LfQej+8ay4vRg6pQ0bWBh6cXSfQBFkW2xOhhJiTdvvyPZcQMhbJallUHI/4x+jT40j0+/lUx23DphdImyCUYJ18xshK5L9PN9dXOPEuep3lBpNC/Rnjv0NL++euyKymjvEtivXaFYiRrv2yJNHWu4om5iWq4hWBmrqIdfW6eK2l/b9oYZ1VIv1kIKv08JxrdosLGXuJiqEoy/GLZVXPu4P7VcgqPRrhGtO7h1l7h1xm5aaxh3Du6sZO+nqNCjTZafGCnBrHGm8hO4zFBRtILtGY4rJT8MZv9mQEYDxYpvtTaWriXAh0oSMEPzgX7SFZoqCCypFGsrYqCl2jieQWxHZYkwwSs8gzl8OZ6GGaUhkTXUOh5M+kTcyxVVQu4PKt160+ut8Kw5yDtqRaipDzlRQ2Dr1rhErxgGWa1Qr2QlykFYLEeFhKPiyAZlOio4KCz69BkPcReLPmMOnJn2AE5AvAvFXfLGu+SHUVSfAULwLYCYAY4AZvr5QMji9QjIEpS7+/xw/Q8gD38H0mO8HMgCypJnMDwDhnx4GfF1fD6G43cxYJh+BYahQZLvom782TYJzfFFbbIIFZPjVxHahOC75xMc8fL/2SbDws3/AAAA//8DAFBLAwQUAAYACAAAACEA4IvKVR8BAAARAgAAFAAAAHdvcmQvd2ViU2V0dGluZ3MueG1slNFRS8MwEAfwd8HvUPK+pRs6tKwbgkz2MgbVD5Cl1zWY5EIua7dv71nnRHyZbzku9+P+3Hx5dDbrIJJBX4rJOBcZeI218ftSvL2uRg8io6R8rSx6KMUJSCwXtzfzvuhhV0FK/JMyVjwVTpeiTSkUUpJuwSkaYwDPzQajU4nLuJdOxfdDGGl0QSWzM9akk5zm+UycmXiNgk1jNDyjPjjwaZiXESyL6Kk1gb61/hqtx1iHiBqIOI+zX55Txl+Yyd0fyBkdkbBJYw5z3migeHySDy9nf4D7/wHTC+B0sd57jGpn+QS8ScaYWPANlLXYbzcv8rOocYOpUh08UcUpLKyMhaETzBEsbSGuvW6zvuiULcXjTHBT/jrk4gMAAP//AwBQSwMEFAAGAAgAAAAhAJ/qVV97AQAAFQMAABEACAFkb2NQcm9wcy9jb3JlLnhtbCCiBAEooAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJySUU/CMBCA3038D0vfRzdQgssYiRqeJJoI0fhW2xtUtrZpDwb/3m6DIZHExLfe7ruvt7umk11ZBFuwTmo1JnEvIgEoroVUyzFZzKfhiAQOmRKs0ArGZA+OTLLrq5SbhGsLL1YbsCjBBd6kXMLNmKwQTUKp4ysomet5Qvlkrm3J0Id2SQ3ja7YE2o+iIS0BmWDIaC0MTWckB6XgndJsbNEIBKdQQAkKHY17MT2xCLZ0FwuazA+ylLg3cBE9Jjt652QHVlXVqwYN6vuP6fvs6bX51VCqelYcSJYKnqDEArKUno7+5DafX8Cx/dwF/swtMNQ2W6AspGMIGxsICGaSW+10jsFznksOTd2Rrbewhn2lrXDeeBZ5TIDjVhr0u23vO/vg6YI5nPll5xLE/f7vq3+X1BYLW1m/nyxuiC5MD8to2wUR+CEm7ciPmbfBw+N8SrJ+FA/DOAr7N/NolNzeJVH0UXd8Vn8SlocG/m08CtqhnT/k7BsAAP//AwBQSwMEFAAGAAgAAAAhAIGW/TkyCwAAZHIAAA8AAAB3b3JkL3N0eWxlcy54bWy8ndty27oVhu8703fg6Kq9cHyMnXi2s8d24tpTO9s7cppriIQk1CCh8uBDn74gSEmQF0FxAau+siVqfQDx4wewQFL67feXVEZPPC+Eys5G+x/2RhHPYpWIbHY2+vlwtfNpFBUlyxImVcbPRq+8GP3+5a9/+e35tChfJS8iDciK0zQ+G83LcnG6u1vEc56y4oNa8EwfnKo8ZaV+mc92U5Y/VoudWKULVoqJkKJ83T3Y2zsetZh8CEVNpyLmX1VcpTwrTfxuzqUmqqyYi0WxpD0PoT2rPFnkKuZFoU86lQ0vZSJbYfaPACgVca4KNS0/6JNpa2RQOnx/z/yXyjXgIw5wsAKk8enNLFM5m0jd+romkYaNvujmT1T8lU9ZJcuifpnf5+3L9pX5c6WysoieT1kRC/GgS9aQVGje9XlWiJE+wllRnheCdR6c1/90HomL0nr7QiRitFuXWPxXH3xi8mx0cLR857KuwcZ7kmWz5XvTfOfqh12TsxHPdn6O67cmmns2YvnO+LwO3G1PrPlrne5i9ar51Ju20V1Dd5Rx01/1UT69VfEjT8alPnA22quL0m/+vLnPhcp1nzwbff7cvjnmqbgWScIz64PZXCT815xnPwuerN//88r0q/aNWFWZ/v/w057RSxbJt5eYL+peqo9mrG6973WArD9diXXhJvw/S9h+22Zd8XPOaqtG+28RpvooxEEdUVhn282s3py7+RSqoMP3KujovQr6+F4FHb9XQSfvVdCn9yrIYP6fBYks4S+NEWExgLqN43AjmuMwG5rj8BKa47AKmuNwAprj6OhojqMfozmOborglCp29UKrsx86ens/d/sc4cfdPiX4cbfPAH7c7QO+H3f7+O7H3T6c+3G3j95+3O2DNZ7bLLWiG22zrAx22VSpMlMlj0r+Ek5jmWaZ/IWGV096PCc5SQJMM7K1E3EwLWbm9fYeYkzqP5+XdcoVqWk0FbMq12lvaMV59sSlTkAjliSaRwjMeVnljhbx6dM5n/KcZzGn7Nh0UCkyHmVVOiHomws2I2PxLCFuviWRZFBYdWhWlfPaJIKgU6cszlV41RQjGx9uRRHeVjUkuqik5ESs7zRdzLDCcwODCU8NDCY8MzCY8MTA0oyqiVoaUUu1NKIGa2lE7db0T6p2a2lE7dbSiNqtpYW324MopRni7VXH/vC9u0up6h3n4HqMxSxjegEQPt20e6bRPcvZLGeLeVTvH3dj7XPGlnOhktfogWJOW5Go1vWmi1zqsxZZFd6gGzQqc614RPZa8YgMtuKFW+xOL5PrBdo1TT4zriZlp2kNaZBpx0xWzYI23G2sDO9hawNcibwgs0E3lqAHf6+Xs7WcFCPfupbhFVuzwm31dlQirV6LJKilVPEjzTB8/brguU7LHoNJV0pK9cwTOuK4zFXT12zLHxhJBln+W7qYs0KYXGkDMXyqX16rju7YIviE7iUTGY1u33ZSJmREt4K4fri7jR7Uok4z64ahAV6oslQpGbPdCfzbLz75O00Fz3USnL0Sne050faQgV0KgkmmIamEiKSXmSITJHOo4f2Tv04UyxMa2n3Om9tDSk5EHLN00Sw6CLylx8VnPf4QrIYM718sF/W+EJWpHkhg1rZhUU3+zePwoe67ikh2hv6oSrP/aJa6JpoOF75M2MCFLxGMmnp6qPsvwclu4MJPdgNHdbKXkhWFcF5C9eZRne6SR32+4clfy1NS5dNK0jXgEkjWgksgWRMqWaVZQXnGhkd4woZHfb6EXcbwCLbkDO8fuUjIxDAwKiUMjEoGA6PSwMBIBQi/Q8eChd+mY8HC79VpYERLAAtG1c9Ip3+iqzwWjKqfGRhVPzMwqn5mYFT97PBrxKdTvQimm2IsJFWfs5B0E01W8nShcpa/EiG/ST5jBBukDe0+V9P6uQGVNTdxEyDrPWpJuNhucFQi/+ITsqrVLMp6EeyIMimVItpbW084JnLz3rVtYeaZi+AqmM32W/7EKVbjFozoMkADC5fNgoVPUxYsfJqyYOHTlAULn6YsWPg0ZcHC71++lyzmcyUTnjuM2FeRaLxgcXttCVyjHrRXfytm8zIaz1eXqGzM8d7WyOUu00bY9gK7Borjg56wO56IKl1WFD4BdHw4PNgYeiN4+aBWT/B6+bsR+XFgJCzzeHvkOrXbiDwZGAnL/DQw0oxSG5F9g/hXlj92doSTvv6z2phwdL6Tvl60Cu4stq8jrSK7uuBJXy/asEp0Hsf1JS6ozjDPuOOHmccdj3GRm4Kxk5sy2FduRJ/BfvAnUS9HMYOmKW91y8/b4g7NlDpo5PyzUs3Fpo2rpMOfRLzRq/2s4FEn53D41daNUcbdjoOHGzdi8LjjRgwegNyIQSORMxw1JLkpg8cmN2LwIOVGoEcrOCPgRisYjxutYLzPaAUpPqNVwCrAjRi8HHAj0EaFCLRRA1YKbgTKqCDcy6iQgjYqRKCNChFoo8IFGM6oMB5nVBjvY1RI8TEqpKCNChFoo0IE2qgQgTYqRKCN6rm2d4Z7GRVS0EaFCLRRIQJtVLNeDDAqjMcZFcb7GBVSfIwKKWijQgTaqBCBNipEoI0KEWijQgTKqCDcy6iQgjYqRKCNChFoozbPx/obFcbjjArjfYwKKT5GhRS0USECbVSIQBsVItBGhQi0USECZVQQ7mVUSEEbFSLQRoUItFHNpYMAo8J4nFFhvI9RIcXHqJCCNipEoI0KEWijQgTaqBCBNipEoIwKwr2MCiloo0IE2qgQ0dc/2+vqrmdD9vG7ns7HTIZfumor9cP+/gEbdTgctayVmzX8AZoLpR6jzqdlD02+MQwiJlIos0XtuBfE5poLpKir9X9c9j+WZtMDvymsfYDHXOgH8KOhkWBP5aivy9uRIMk76uvpdiRYdR71jb52JJgGj/oGXePL5Z1UejoCwX3DjBW87wjvG62tcNjEfWO0FQhbuG9ktgJhA/eNx1bgx6genN9GfxzYTserm6IBoa87WoQTN6GvW0KtlsMxNMZQ0dyEoeq5CUNldBNQejoxeGHdKLTCbpSf1NBmWKn9jeomYKWGBC+pAcZfaojylhqi/KSGAyNWakjASu0/OLsJXlIDjL/UEOUtNUT5SQ2nMqzUkICVGhKwUgdOyE6Mv9QQ5S01RPlJDRd3WKkhASs1JGClhgQvqQHGX2qI8pYaovykBlkyWmpIwEoNCVipIcFLaoDxlxqivKWGqD6pzS7KhtQoha1w3CLMCsRNyFYgbnC2Aj2yJSvaM1uyCJ7ZEtRqqTkuW7JFcxOGqucmDJXRTUDp6cTghXWj0Aq7UX5S47KlLqn9jeomYKXGZUtOqXHZUq/UuGypV2pctuSWGpctdUmNy5a6pPYfnN0EL6lx2VKv1LhsqVdqXLbklhqXLXVJjcuWuqTGZUtdUgdOyE6Mv9S4bKlXaly25JYaly11SY3LlrqkxmVLXVLjsiWn1LhsqVdqXLbUKzUuW3JLjcuWuqTGZUtdUuOypS6pcdmSU2pcttQrNS5b6pXakS3tPm/8aljNNr93pz9cvi54/cXx1gMzSfPFue1FQPPBm2T16151cF2TqP3Fs/ZtU+H2gmFTogmERcVzXVbcfuWXo6h7JYU+b5Yn+nAJinR8s6+pwvrkl59uG3N9EbT53MYFz94al3Vj99TWiMGq3vZpFHNV8XPbBbfVUddoIpsfw9P/3GSJBjy3v7DW1DV5YQ1KH7/kUt6x5tNq4f6o5NOyObq/Zx6ffXN80nxhoTM+N4OEE7C7WZnmZfvDd44Wb37CoL167Wj18yquMi61G3hHm5v7KUKbe13B5X/Fl/8BAAD//wMAUEsDBBQABgAIAAAAIQDtJ+K6ZQEAALUCAAAQAAgBZG9jUHJvcHMvYXBwLnhtbCCiBAEooAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJxSwUrFMBC8C/5D6d2XPkER2RcRRTyoCK/qOSTbNpgmIVnF9/durNaqN3Pand1MZobA2dvoqldM2Qa/qderpq7Q62Cs7zf1Q3t1cFJXmZQ3ygWPm3qHuT6T+3twn0LERBZzxRQ+b+qBKJ4KkfWAo8orHnuedCGNirhNvQhdZzVeBv0yoidx2DTHAt8IvUFzEGfCemI8faX/kpqgi7782O4i80locYxOEcq7ctOtTKARxIxCG0i51o4oG4bnBu5Vj1muQUwFPIVkctmZCrgYVFKaOD95BGLRwXmMzmpFnKu8tTqFHDqqbpW2nkIeqkIAYrkF7GGL+iVZ2pUnli3cWD8JmQoWllSfVBw+1c0dbLVyeMHuZadcRhDfQGF5zg+xDZfF9ef8J7iw9GRp2Eal8Ze5BQ5bRtGw1Pm1GYBrDj+5ws53fY/ma+fvoMT1OP1CuT5aNXw+wvnC2OL8PeQ7AAAA//8DAFBLAQItABQABgAIAAAAIQBnzQ+udAEAADoFAAATAAAAAAAAAAAAAAAAAAAAAABbQ29udGVudF9UeXBlc10ueG1sUEsBAi0AFAAGAAgAAAAhAMfCJ7z/AAAA3wIAAAsAAAAAAAAAAAAAAAAArQMAAF9yZWxzLy5yZWxzUEsBAi0AFAAGAAgAAAAhABOqPof2AAAAMQMAABwAAAAAAAAAAAAAAAAA3QYAAHdvcmQvX3JlbHMvZG9jdW1lbnQueG1sLnJlbHNQSwECLQAUAAYACAAAACEAM+oBymACAAACBwAAEQAAAAAAAAAAAAAAAAAVCQAAd29yZC9kb2N1bWVudC54bWxQSwECLQAUAAYACAAAACEAJyDgAjMGAACMGgAAFQAAAAAAAAAAAAAAAACkCwAAd29yZC90aGVtZS90aGVtZTEueG1sUEsBAi0ACgAAAAAAAAAhAGoT2A2MJQAAjCUAABcAAAAAAAAAAAAAAAAAChIAAGRvY1Byb3BzL3RodW1ibmFpbC5qcGVnUEsBAi0AFAAGAAgAAAAhANJeFd+BAwAATAkAABEAAAAAAAAAAAAAAAAAyzcAAHdvcmQvc2V0dGluZ3MueG1sUEsBAi0AFAAGAAgAAAAhAPC8NQHcAQAA8QUAABIAAAAAAAAAAAAAAAAAezsAAHdvcmQvZm9udFRhYmxlLnhtbFBLAQItABQABgAIAAAAIQDgi8pVHwEAABECAAAUAAAAAAAAAAAAAAAAAIc9AAB3b3JkL3dlYlNldHRpbmdzLnhtbFBLAQItABQABgAIAAAAIQCf6lVfewEAABUDAAARAAAAAAAAAAAAAAAAANg+AABkb2NQcm9wcy9jb3JlLnhtbFBLAQItABQABgAIAAAAIQCBlv05MgsAAGRyAAAPAAAAAAAAAAAAAAAAAIpBAAB3b3JkL3N0eWxlcy54bWxQSwECLQAUAAYACAAAACEA7SfiumUBAAC1AgAAEAAAAAAAAAAAAAAAAADpTAAAZG9jUHJvcHMvYXBwLnhtbFBLBQYAAAAADAAMAAYDAACETwAAAAA='), array('data:a!b#c&d-e^f_g+h.i/a!b#c&d-e^f_g+h.i;base64,foobar'), + array('data:text/plain;charset=utf-8;base64,SGVsbG8gV29ybGQh'), ); - - if (!defined('HHVM_VERSION')) { - // See https://github.com/facebook/hhvm/issues/6354 - $data[] = array('data:text/plain;charset=utf-8;base64,SGVsbG8gV29ybGQh'); - } - - return $data; } private function getContent(\SplFileObject $file) diff --git a/src/Symfony/Component/VarDumper/Caster/RedisCaster.php b/src/Symfony/Component/VarDumper/Caster/RedisCaster.php index 07a3a1b091126..3d7063f40a271 100644 --- a/src/Symfony/Component/VarDumper/Caster/RedisCaster.php +++ b/src/Symfony/Component/VarDumper/Caster/RedisCaster.php @@ -30,15 +30,6 @@ public static function castRedis(\Redis $c, array $a, Stub $stub, $isNested) { $prefix = Caster::PREFIX_VIRTUAL; - if (defined('HHVM_VERSION_ID')) { - if (isset($a[Caster::PREFIX_PROTECTED.'serializer'])) { - $ser = $a[Caster::PREFIX_PROTECTED.'serializer']; - $a[Caster::PREFIX_PROTECTED.'serializer'] = isset(self::$serializer[$ser]) ? new ConstStub(self::$serializer[$ser], $ser) : $ser; - } - - return $a; - } - if (!$connected = $c->isConnected()) { return $a + array( $prefix.'isConnected' => $connected, diff --git a/src/Symfony/Component/VarDumper/Caster/ReflectionCaster.php b/src/Symfony/Component/VarDumper/Caster/ReflectionCaster.php index 995447935227b..73828f0b33744 100644 --- a/src/Symfony/Component/VarDumper/Caster/ReflectionCaster.php +++ b/src/Symfony/Component/VarDumper/Caster/ReflectionCaster.php @@ -36,7 +36,6 @@ public static function castClosure(\Closure $c, array $a, Stub $stub, $isNested, $prefix = Caster::PREFIX_VIRTUAL; $c = new \ReflectionFunction($c); - $stub->class = 'Closure'; // HHVM generates unique class names for closures $a = static::castFunctionAbstract($c, $a, $stub, $isNested, $filter); if (isset($a[$prefix.'parameters'])) { @@ -213,9 +212,6 @@ public static function castFunctionAbstract(\ReflectionFunctionAbstract $c, arra self::addExtra($a, $c); } - // Added by HHVM - unset($a[Caster::PREFIX_DYNAMIC.'static']); - return $a; } @@ -230,9 +226,6 @@ public static function castParameter(\ReflectionParameter $c, array $a, Stub $st { $prefix = Caster::PREFIX_VIRTUAL; - // Added by HHVM - unset($a['info']); - self::addMap($a, $c, array( 'position' => 'getPosition', 'isVariadic' => 'isVariadic', diff --git a/src/Symfony/Component/VarDumper/Cloner/VarCloner.php b/src/Symfony/Component/VarDumper/Cloner/VarCloner.php index b6bf2412cb910..c99b5488cce3a 100644 --- a/src/Symfony/Component/VarDumper/Cloner/VarCloner.php +++ b/src/Symfony/Component/VarDumper/Cloner/VarCloner.php @@ -282,23 +282,19 @@ private static function initHashMask() self::$hashOffset = 16 - PHP_INT_SIZE; self::$hashMask = -1; - if (defined('HHVM_VERSION')) { - self::$hashOffset += 16; - } else { - // check if we are nested in an output buffering handler to prevent a fatal error with ob_start() below - $obFuncs = array('ob_clean', 'ob_end_clean', 'ob_flush', 'ob_end_flush', 'ob_get_contents', 'ob_get_flush'); - foreach (debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS) as $frame) { - if (isset($frame['function'][0]) && !isset($frame['class']) && 'o' === $frame['function'][0] && in_array($frame['function'], $obFuncs)) { - $frame['line'] = 0; - break; - } - } - if (!empty($frame['line'])) { - ob_start(); - debug_zval_dump($obj); - self::$hashMask = (int) substr(ob_get_clean(), 17); + // check if we are nested in an output buffering handler to prevent a fatal error with ob_start() below + $obFuncs = array('ob_clean', 'ob_end_clean', 'ob_flush', 'ob_end_flush', 'ob_get_contents', 'ob_get_flush'); + foreach (debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS) as $frame) { + if (isset($frame['function'][0]) && !isset($frame['class']) && 'o' === $frame['function'][0] && in_array($frame['function'], $obFuncs)) { + $frame['line'] = 0; + break; } } + if (!empty($frame['line'])) { + ob_start(); + debug_zval_dump($obj); + self::$hashMask = (int) substr(ob_get_clean(), 17); + } self::$hashMask ^= hexdec(substr(spl_object_hash($obj), self::$hashOffset, PHP_INT_SIZE)); } diff --git a/src/Symfony/Component/VarDumper/Tests/Caster/RedisCasterTest.php b/src/Symfony/Component/VarDumper/Tests/Caster/RedisCasterTest.php index af038192f5c8d..f00b3fa49599f 100644 --- a/src/Symfony/Component/VarDumper/Tests/Caster/RedisCasterTest.php +++ b/src/Symfony/Component/VarDumper/Tests/Caster/RedisCasterTest.php @@ -26,20 +26,11 @@ public function testNotConnected() { $redis = new \Redis(); - if (defined('HHVM_VERSION_ID')) { - $xCast = <<<'EODUMP' -Redis { - #host: "" -%A -} -EODUMP; - } else { - $xCast = <<<'EODUMP' + $xCast = <<<'EODUMP' Redis { isConnected: false } EODUMP; - } $this->assertDumpMatchesFormat($xCast, $redis); } @@ -52,15 +43,7 @@ public function testConnected() self::markTestSkipped($e['message']); } - if (defined('HHVM_VERSION_ID')) { - $xCast = <<<'EODUMP' -Redis { - #host: "127.0.0.1" -%A -} -EODUMP; - } else { - $xCast = <<<'EODUMP' + $xCast = <<<'EODUMP' Redis { +"socket": Redis Socket Buffer resource isConnected: true @@ -78,7 +61,6 @@ public function testConnected() } } EODUMP; - } $this->assertDumpMatchesFormat($xCast, $redis); } diff --git a/src/Symfony/Component/VarDumper/Tests/Dumper/CliDumperTest.php b/src/Symfony/Component/VarDumper/Tests/Dumper/CliDumperTest.php index c2291c6949668..b41328bd3e4fe 100644 --- a/src/Symfony/Component/VarDumper/Tests/Dumper/CliDumperTest.php +++ b/src/Symfony/Component/VarDumper/Tests/Dumper/CliDumperTest.php @@ -46,7 +46,6 @@ public function testGet() $intMax = PHP_INT_MAX; $res = (int) $var['res']; - $r = defined('HHVM_VERSION') ? '' : '#%d'; $this->assertStringMatchesFormat( << Closure {{$r} + "closure" => Closure {#%d class: "Symfony\Component\VarDumper\Tests\Dumper\CliDumperTest" - this: Symfony\Component\VarDumper\Tests\Dumper\CliDumperTest {{$r} …} + this: Symfony\Component\VarDumper\Tests\Dumper\CliDumperTest {#%d …} parameters: { \$a: {} &\$b: { @@ -231,10 +230,6 @@ public function testObjectCast() public function testClosedResource() { - if (defined('HHVM_VERSION') && HHVM_VERSION_ID < 30600) { - $this->markTestSkipped(); - } - $var = fopen(__FILE__, 'r'); fclose($var); @@ -325,11 +320,10 @@ public function testThrowingCaster() $dumper->dump($data, $out); $out = stream_get_contents($out, -1, 0); - $r = defined('HHVM_VERSION') ? '' : '#%d'; $this->assertStringMatchesFormat( <<cloneVar($var); $out = $dumper->dump($data, true); - $r = defined('HHVM_VERSION') ? '' : '#%d'; $this->assertStringMatchesFormat( <<#%d'; $this->assertStringMatchesFormat( <<array:24 [ @@ -75,10 +74,10 @@ public function testGet() +foo: "foo" +"bar": "bar" } - "closure" => Closure {{$r} + "closure" => Closure {#%d class: "Symfony\Component\VarDumper\Tests\Dumper\HtmlDumperTest" - this: HtmlDumperTest {{$r} &%s;} + this: HtmlDumperTest {#%d &%s;} parameters: { \$a: {} &\$b: { From 2125437c09756b36055fe72553f79d3edf79eff4 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Tue, 23 May 2017 07:48:36 +0200 Subject: [PATCH 0117/1099] [WebServerBundle] removed obsolete ServerCommand abstract class --- .../WebServerBundle/Command/ServerCommand.php | 25 ------------------- .../Command/ServerRunCommand.php | 3 ++- .../Command/ServerStartCommand.php | 3 ++- .../Command/ServerStatusCommand.php | 3 ++- .../Command/ServerStopCommand.php | 3 ++- 5 files changed, 8 insertions(+), 29 deletions(-) delete mode 100644 src/Symfony/Bundle/WebServerBundle/Command/ServerCommand.php diff --git a/src/Symfony/Bundle/WebServerBundle/Command/ServerCommand.php b/src/Symfony/Bundle/WebServerBundle/Command/ServerCommand.php deleted file mode 100644 index 046e5345729ec..0000000000000 --- a/src/Symfony/Bundle/WebServerBundle/Command/ServerCommand.php +++ /dev/null @@ -1,25 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\WebServerBundle\Command; - -use Symfony\Component\Console\Command\Command; - -/** - * Base methods for commands related to a local web server. - * - * @author Christian Flothmann - * - * @internal - */ -abstract class ServerCommand extends Command -{ -} diff --git a/src/Symfony/Bundle/WebServerBundle/Command/ServerRunCommand.php b/src/Symfony/Bundle/WebServerBundle/Command/ServerRunCommand.php index 53ce350e7fae2..8d181f291c42c 100644 --- a/src/Symfony/Bundle/WebServerBundle/Command/ServerRunCommand.php +++ b/src/Symfony/Bundle/WebServerBundle/Command/ServerRunCommand.php @@ -13,6 +13,7 @@ use Symfony\Bundle\WebServerBundle\WebServer; use Symfony\Bundle\WebServerBundle\WebServerConfig; +use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Input\InputInterface; @@ -26,7 +27,7 @@ * * @author Michał Pipa */ -class ServerRunCommand extends ServerCommand +class ServerRunCommand extends Command { private $documentRoot; private $environment; diff --git a/src/Symfony/Bundle/WebServerBundle/Command/ServerStartCommand.php b/src/Symfony/Bundle/WebServerBundle/Command/ServerStartCommand.php index 7cf83ab54e14e..95acd8ec3b7d1 100644 --- a/src/Symfony/Bundle/WebServerBundle/Command/ServerStartCommand.php +++ b/src/Symfony/Bundle/WebServerBundle/Command/ServerStartCommand.php @@ -13,6 +13,7 @@ use Symfony\Bundle\WebServerBundle\WebServer; use Symfony\Bundle\WebServerBundle\WebServerConfig; +use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; @@ -25,7 +26,7 @@ * * @author Christian Flothmann */ -class ServerStartCommand extends ServerCommand +class ServerStartCommand extends Command { private $documentRoot; private $environment; diff --git a/src/Symfony/Bundle/WebServerBundle/Command/ServerStatusCommand.php b/src/Symfony/Bundle/WebServerBundle/Command/ServerStatusCommand.php index 3e7d4c7ec4fd4..7c9f6980e8bb5 100644 --- a/src/Symfony/Bundle/WebServerBundle/Command/ServerStatusCommand.php +++ b/src/Symfony/Bundle/WebServerBundle/Command/ServerStatusCommand.php @@ -12,6 +12,7 @@ namespace Symfony\Bundle\WebServerBundle\Command; use Symfony\Bundle\WebServerBundle\WebServer; +use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; @@ -24,7 +25,7 @@ * * @author Christian Flothmann */ -class ServerStatusCommand extends ServerCommand +class ServerStatusCommand extends Command { /** * {@inheritdoc} diff --git a/src/Symfony/Bundle/WebServerBundle/Command/ServerStopCommand.php b/src/Symfony/Bundle/WebServerBundle/Command/ServerStopCommand.php index ccfb733066b80..fc5e2fd563dfe 100644 --- a/src/Symfony/Bundle/WebServerBundle/Command/ServerStopCommand.php +++ b/src/Symfony/Bundle/WebServerBundle/Command/ServerStopCommand.php @@ -12,6 +12,7 @@ namespace Symfony\Bundle\WebServerBundle\Command; use Symfony\Bundle\WebServerBundle\WebServer; +use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Output\ConsoleOutputInterface; @@ -23,7 +24,7 @@ * * @author Christian Flothmann */ -class ServerStopCommand extends ServerCommand +class ServerStopCommand extends Command { /** * {@inheritdoc} From 7f4824c987afea401a5e1ddb81256d91431093d8 Mon Sep 17 00:00:00 2001 From: Vincent AUBERT Date: Fri, 2 Jun 2017 07:32:06 +0200 Subject: [PATCH 0118/1099] add some \ on PHP_VERSION_ID for 2.8 --- src/Symfony/Component/Console/Tests/Command/CommandTest.php | 2 +- .../Component/DependencyInjection/Tests/ContainerTest.php | 2 +- src/Symfony/Component/DomCrawler/Crawler.php | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Component/Console/Tests/Command/CommandTest.php b/src/Symfony/Component/Console/Tests/Command/CommandTest.php index e77292f608c21..ac4aa22fbb772 100644 --- a/src/Symfony/Component/Console/Tests/Command/CommandTest.php +++ b/src/Symfony/Component/Console/Tests/Command/CommandTest.php @@ -386,7 +386,7 @@ public function testSetCodeWithStaticClosure() $tester = new CommandTester($command); $tester->execute(array()); - if (PHP_VERSION_ID < 70000) { + if (\PHP_VERSION_ID < 70000) { // Cannot bind static closures in PHP 5 $this->assertEquals('interact called'.PHP_EOL.'not bound'.PHP_EOL, $tester->getDisplay()); } else { diff --git a/src/Symfony/Component/DependencyInjection/Tests/ContainerTest.php b/src/Symfony/Component/DependencyInjection/Tests/ContainerTest.php index 834fef32b19cb..dbe18f607e968 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/ContainerTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/ContainerTest.php @@ -698,7 +698,7 @@ public function testThatCloningIsNotSupported() { $class = new \ReflectionClass('Symfony\Component\DependencyInjection\Container'); $clone = $class->getMethod('__clone'); - if (PHP_VERSION_ID >= 50400) { + if (\PHP_VERSION_ID >= 50400) { $this->assertFalse($class->isCloneable()); } $this->assertTrue($clone->isPrivate()); diff --git a/src/Symfony/Component/DomCrawler/Crawler.php b/src/Symfony/Component/DomCrawler/Crawler.php index bb429c2b6a122..094075bfc903a 100644 --- a/src/Symfony/Component/DomCrawler/Crawler.php +++ b/src/Symfony/Component/DomCrawler/Crawler.php @@ -1191,7 +1191,7 @@ private function createSubCrawler($nodes) private function triggerDeprecation($methodName, $useTrace = false) { if ($useTrace || defined('HHVM_VERSION')) { - if (PHP_VERSION_ID >= 50400) { + if (\PHP_VERSION_ID >= 50400) { $trace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 3); } else { $trace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS); From 3371db9f8cd332932495eaa592ccbbf0e9c66729 Mon Sep 17 00:00:00 2001 From: Romain Neutron Date: Thu, 1 Jun 2017 14:40:39 +0200 Subject: [PATCH 0119/1099] Fix optional cache warmers are always instantiated whereas they should be lazy-loaded --- .../CacheWarmer/TranslationsCacheWarmer.php | 22 +++++++++++++++-- .../Resources/config/translation.xml | 2 +- .../CacheWarmer/TemplateCacheWarmer.php | 24 +++++++++++++++++-- .../TwigBundle/Resources/config/twig.xml | 2 +- 4 files changed, 44 insertions(+), 6 deletions(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/CacheWarmer/TranslationsCacheWarmer.php b/src/Symfony/Bundle/FrameworkBundle/CacheWarmer/TranslationsCacheWarmer.php index 223f0216ba9ad..33f94650449fb 100644 --- a/src/Symfony/Bundle/FrameworkBundle/CacheWarmer/TranslationsCacheWarmer.php +++ b/src/Symfony/Bundle/FrameworkBundle/CacheWarmer/TranslationsCacheWarmer.php @@ -11,6 +11,7 @@ namespace Symfony\Bundle\FrameworkBundle\CacheWarmer; +use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\HttpKernel\CacheWarmer\CacheWarmerInterface; use Symfony\Component\HttpKernel\CacheWarmer\WarmableInterface; use Symfony\Component\Translation\TranslatorInterface; @@ -22,11 +23,24 @@ */ class TranslationsCacheWarmer implements CacheWarmerInterface { + private $container; private $translator; - public function __construct(TranslatorInterface $translator) + /** + * TranslationsCacheWarmer constructor. + * + * @param ContainerInterface|TranslatorInterface $container + */ + public function __construct($container) { - $this->translator = $translator; + // As this cache warmer is optional, dependencies should be lazy-loaded, that's why a container should be injected. + if ($container instanceof ContainerInterface) { + $this->container = $container; + } elseif ($container instanceof TranslatorInterface) { + $this->translator = $container; + } else { + throw new \InvalidArgumentException(sprintf('%s only accepts instance of Symfony\Component\DependencyInjection\ContainerInterface or Symfony\Component\Translation\TranslatorInterface as first argument.', __CLASS__)); + } } /** @@ -34,6 +48,10 @@ public function __construct(TranslatorInterface $translator) */ public function warmUp($cacheDir) { + if (null === $this->translator) { + $this->translator = $this->container->get('translator'); + } + if ($this->translator instanceof WarmableInterface) { $this->translator->warmUp($cacheDir); } diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/translation.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/translation.xml index ea85f517aa399..14226ba93083f 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/translation.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/translation.xml @@ -159,7 +159,7 @@ - + diff --git a/src/Symfony/Bundle/TwigBundle/CacheWarmer/TemplateCacheWarmer.php b/src/Symfony/Bundle/TwigBundle/CacheWarmer/TemplateCacheWarmer.php index 8946c1a98bb08..9a60a92e85375 100644 --- a/src/Symfony/Bundle/TwigBundle/CacheWarmer/TemplateCacheWarmer.php +++ b/src/Symfony/Bundle/TwigBundle/CacheWarmer/TemplateCacheWarmer.php @@ -11,6 +11,7 @@ namespace Symfony\Bundle\TwigBundle\CacheWarmer; +use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\HttpKernel\CacheWarmer\CacheWarmerInterface; use Twig\Environment; use Twig\Error\Error; @@ -22,12 +23,27 @@ */ class TemplateCacheWarmer implements CacheWarmerInterface { + private $container; private $twig; private $iterator; - public function __construct(Environment $twig, \Traversable $iterator) + /** + * TemplateCacheWarmer constructor. + * + * @param ContainerInterface|Environment $container + * @param \Traversable $iterator + */ + public function __construct($container, \Traversable $iterator) { - $this->twig = $twig; + // As this cache warmer is optional, dependencies should be lazy-loaded, that's why a container should be injected. + if ($container instanceof ContainerInterface) { + $this->container = $container; + } elseif ($container instanceof Environment) { + $this->twig = $container; + } else { + throw new \InvalidArgumentException(sprintf('%s only accepts instance of Symfony\Component\DependencyInjection\ContainerInterface or Environment as first argument.', __CLASS__)); + } + $this->iterator = $iterator; } @@ -36,6 +52,10 @@ public function __construct(Environment $twig, \Traversable $iterator) */ public function warmUp($cacheDir) { + if (null === $this->twig) { + $this->twig = $this->container->get('twig'); + } + foreach ($this->iterator as $template) { try { $this->twig->loadTemplate($template); diff --git a/src/Symfony/Bundle/TwigBundle/Resources/config/twig.xml b/src/Symfony/Bundle/TwigBundle/Resources/config/twig.xml index 86e7c45cd39a8..541ac4a559738 100644 --- a/src/Symfony/Bundle/TwigBundle/Resources/config/twig.xml +++ b/src/Symfony/Bundle/TwigBundle/Resources/config/twig.xml @@ -60,7 +60,7 @@ - + From 99e0836fd4ec6c3e3f101a867eba2eb4a2b8e543 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Fri, 2 Jun 2017 10:28:06 +0200 Subject: [PATCH 0120/1099] typo --- src/Symfony/Component/VarDumper/Tests/CliDumperTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/VarDumper/Tests/CliDumperTest.php b/src/Symfony/Component/VarDumper/Tests/CliDumperTest.php index 8edb39c19a8b4..5ee3a6c11ed48 100644 --- a/src/Symfony/Component/VarDumper/Tests/CliDumperTest.php +++ b/src/Symfony/Component/VarDumper/Tests/CliDumperTest.php @@ -272,7 +272,7 @@ public function testThrowingCaster() %sTemplate.php:%d: """ try {\\n \$this->doDisplay(\$context, \$blocks);\\n - } catch (Twig\Error \$e) {\\n + } catch (Twig%sError \$e) {\\n """ } } From 8d609d9bbaef38e6a84585c572bdb53100143845 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Fri, 2 Jun 2017 11:00:03 +0200 Subject: [PATCH 0121/1099] fix merge --- src/Symfony/Bridge/Twig/CHANGELOG.md | 2 +- src/Symfony/Bridge/Twig/Extension/FormExtension.php | 2 +- src/Symfony/Bridge/Twig/Extension/WorkflowExtension.php | 8 +++++--- src/Symfony/Bridge/Twig/Form/TwigRendererEngine.php | 2 +- .../Bridge/Twig/Tests/Extension/DumpExtensionTest.php | 2 +- .../Twig/Tests/Extension/HttpKernelExtensionTest.php | 2 +- .../Bridge/Twig/Tests/Extension/RuntimeLoaderProvider.php | 5 +++-- .../Bundle/TwigBundle/ContainerAwareRuntimeLoader.php | 3 ++- 8 files changed, 15 insertions(+), 11 deletions(-) diff --git a/src/Symfony/Bridge/Twig/CHANGELOG.md b/src/Symfony/Bridge/Twig/CHANGELOG.md index dee3db5a37655..04c7dfb43d0e3 100644 --- a/src/Symfony/Bridge/Twig/CHANGELOG.md +++ b/src/Symfony/Bridge/Twig/CHANGELOG.md @@ -28,7 +28,7 @@ CHANGELOG // ... $rendererEngine = new TwigRendererEngine(array('form_div_layout.html.twig'), $twig); // require Twig 1.30+ - $twig->addRuntimeLoader(new \Twig_FactoryRuntimeLoader(array( + $twig->addRuntimeLoader(new \Twig\RuntimeLoader\FactoryRuntimeLoader(array( TwigRenderer::class => function () use ($rendererEngine, $csrfTokenManager) { return new TwigRenderer($rendererEngine, $csrfTokenManager); }, diff --git a/src/Symfony/Bridge/Twig/Extension/FormExtension.php b/src/Symfony/Bridge/Twig/Extension/FormExtension.php index 2cff5996f6286..362879e43a89e 100644 --- a/src/Symfony/Bridge/Twig/Extension/FormExtension.php +++ b/src/Symfony/Bridge/Twig/Extension/FormExtension.php @@ -38,7 +38,7 @@ class FormExtension extends AbstractExtension implements InitRuntimeInterface public function __construct($renderer = null) { if ($renderer instanceof TwigRendererInterface) { - @trigger_error(sprintf('Passing a Twig Form Renderer to the "%s" constructor is deprecated since version 3.2 and won\'t be possible in 4.0. Pass the Twig_Environment to the TwigRendererEngine constructor instead.', static::class), E_USER_DEPRECATED); + @trigger_error(sprintf('Passing a Twig Form Renderer to the "%s" constructor is deprecated since version 3.2 and won\'t be possible in 4.0. Pass the Twig\Environment to the TwigRendererEngine constructor instead.', static::class), E_USER_DEPRECATED); } elseif (null !== $renderer && !(is_array($renderer) && isset($renderer[0], $renderer[1]) && $renderer[0] instanceof ContainerInterface)) { throw new \InvalidArgumentException(sprintf('Passing any arguments the constructor of %s is reserved for internal use.', __CLASS__)); } diff --git a/src/Symfony/Bridge/Twig/Extension/WorkflowExtension.php b/src/Symfony/Bridge/Twig/Extension/WorkflowExtension.php index 2e5459fa07e68..e93008c84af6d 100644 --- a/src/Symfony/Bridge/Twig/Extension/WorkflowExtension.php +++ b/src/Symfony/Bridge/Twig/Extension/WorkflowExtension.php @@ -13,13 +13,15 @@ use Symfony\Component\Workflow\Registry; use Symfony\Component\Workflow\Transition; +use Twig\Extension\AbstractExtension; +use Twig\TwigFunction; /** * WorkflowExtension. * * @author Grégoire Pineau */ -class WorkflowExtension extends \Twig_Extension +class WorkflowExtension extends AbstractExtension { private $workflowRegistry; @@ -31,8 +33,8 @@ public function __construct(Registry $workflowRegistry) public function getFunctions() { return array( - new \Twig_SimpleFunction('workflow_can', array($this, 'canTransition')), - new \Twig_SimpleFunction('workflow_transitions', array($this, 'getEnabledTransitions')), + new TwigFunction('workflow_can', array($this, 'canTransition')), + new TwigFunction('workflow_transitions', array($this, 'getEnabledTransitions')), ); } diff --git a/src/Symfony/Bridge/Twig/Form/TwigRendererEngine.php b/src/Symfony/Bridge/Twig/Form/TwigRendererEngine.php index 8e4790ed8db12..3805c7416f77c 100644 --- a/src/Symfony/Bridge/Twig/Form/TwigRendererEngine.php +++ b/src/Symfony/Bridge/Twig/Form/TwigRendererEngine.php @@ -31,7 +31,7 @@ class TwigRendererEngine extends AbstractRendererEngine implements TwigRendererE */ private $template; - public function __construct(array $defaultThemes = array(), \Twig_Environment $environment = null) + public function __construct(array $defaultThemes = array(), Environment $environment = null) { if (null === $environment) { @trigger_error(sprintf('Not passing a Twig Environment as the second argument for "%s" constructor is deprecated since version 3.2 and won\'t be possible in 4.0.', static::class), E_USER_DEPRECATED); diff --git a/src/Symfony/Bridge/Twig/Tests/Extension/DumpExtensionTest.php b/src/Symfony/Bridge/Twig/Tests/Extension/DumpExtensionTest.php index f71d81648b22f..ce80418c83ba7 100644 --- a/src/Symfony/Bridge/Twig/Tests/Extension/DumpExtensionTest.php +++ b/src/Symfony/Bridge/Twig/Tests/Extension/DumpExtensionTest.php @@ -123,7 +123,7 @@ public function testCustomDumper() '' ); $extension = new DumpExtension(new VarCloner(), $dumper); - $twig = new \Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock(), array( + $twig = new Environment($this->getMockBuilder('Twig\Loader\LoaderInterface')->getMock(), array( 'debug' => true, 'cache' => false, 'optimizations' => 0, diff --git a/src/Symfony/Bridge/Twig/Tests/Extension/HttpKernelExtensionTest.php b/src/Symfony/Bridge/Twig/Tests/Extension/HttpKernelExtensionTest.php index ee48ce058f833..9f19847eb8824 100644 --- a/src/Symfony/Bridge/Twig/Tests/Extension/HttpKernelExtensionTest.php +++ b/src/Symfony/Bridge/Twig/Tests/Extension/HttpKernelExtensionTest.php @@ -81,7 +81,7 @@ protected function renderTemplate(FragmentHandler $renderer, $template = '{{ ren $twig = new Environment($loader, array('debug' => true, 'cache' => false)); $twig->addExtension(new HttpKernelExtension()); - $loader = $this->getMockBuilder('Twig\Loader\RuntimeLoaderInterface')->getMock(); + $loader = $this->getMockBuilder('Twig\RuntimeLoader\RuntimeLoaderInterface')->getMock(); $loader->expects($this->any())->method('load')->will($this->returnValueMap(array( array('Symfony\Bridge\Twig\Extension\HttpKernelRuntime', new HttpKernelRuntime($renderer)), ))); diff --git a/src/Symfony/Bridge/Twig/Tests/Extension/RuntimeLoaderProvider.php b/src/Symfony/Bridge/Twig/Tests/Extension/RuntimeLoaderProvider.php index a6c397ffd4d90..90db2c5d6bd44 100644 --- a/src/Symfony/Bridge/Twig/Tests/Extension/RuntimeLoaderProvider.php +++ b/src/Symfony/Bridge/Twig/Tests/Extension/RuntimeLoaderProvider.php @@ -12,12 +12,13 @@ namespace Symfony\Bridge\Twig\Tests\Extension; use Symfony\Bridge\Twig\Form\TwigRenderer; +use Twig\Environment; trait RuntimeLoaderProvider { - protected function registerTwigRuntimeLoader(\Twig_Environment $environment, TwigRenderer $renderer) + protected function registerTwigRuntimeLoader(Environment $environment, TwigRenderer $renderer) { - $loader = $this->getMockBuilder('Twig_RuntimeLoaderInterface')->getMock(); + $loader = $this->getMockBuilder('Twig\RuntimeLoader\RuntimeLoaderInterface')->getMock(); $loader->expects($this->any())->method('load')->will($this->returnValueMap(array( array('Symfony\Bridge\Twig\Form\TwigRenderer', $renderer), ))); diff --git a/src/Symfony/Bundle/TwigBundle/ContainerAwareRuntimeLoader.php b/src/Symfony/Bundle/TwigBundle/ContainerAwareRuntimeLoader.php index 780454aed986e..94815467c0db2 100644 --- a/src/Symfony/Bundle/TwigBundle/ContainerAwareRuntimeLoader.php +++ b/src/Symfony/Bundle/TwigBundle/ContainerAwareRuntimeLoader.php @@ -13,13 +13,14 @@ use Psr\Log\LoggerInterface; use Symfony\Component\DependencyInjection\ContainerInterface; +use Twig\RuntimeLoader\RuntimeLoaderInterface; /** * Loads Twig extension runtimes via the service container. * * @author Fabien Potencier */ -class ContainerAwareRuntimeLoader implements \Twig_RuntimeLoaderInterface +class ContainerAwareRuntimeLoader implements RuntimeLoaderInterface { private $container; private $mapping; From 1945bcf6c7ceb2880fdc7e1e4bed2e1150a02843 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Fri, 2 Jun 2017 12:45:23 +0200 Subject: [PATCH 0122/1099] typo --- .../Doctrine/Tests/PropertyInfo/Fixtures/DoctrineDummy.php | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Symfony/Bridge/Doctrine/Tests/PropertyInfo/Fixtures/DoctrineDummy.php b/src/Symfony/Bridge/Doctrine/Tests/PropertyInfo/Fixtures/DoctrineDummy.php index 9ceae5150c7ab..580e75803db8f 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/PropertyInfo/Fixtures/DoctrineDummy.php +++ b/src/Symfony/Bridge/Doctrine/Tests/PropertyInfo/Fixtures/DoctrineDummy.php @@ -11,7 +11,6 @@ namespace Symfony\Bridge\Doctrine\Tests\PropertyInfo\Fixtures; -use Doctrine\ORM\Mapping as ORM; use Doctrine\ORM\Mapping\Column; use Doctrine\ORM\Mapping\Entity; use Doctrine\ORM\Mapping\Id; From d89670461df641dada9ea32529838a78044f3cd4 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Fri, 2 Jun 2017 14:59:20 +0200 Subject: [PATCH 0123/1099] Fix composer deps --- src/Symfony/Bundle/FrameworkBundle/composer.json | 8 ++++---- src/Symfony/Bundle/SecurityBundle/composer.json | 2 +- src/Symfony/Component/DependencyInjection/composer.json | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/composer.json b/src/Symfony/Bundle/FrameworkBundle/composer.json index 05fb5b96a6cbf..6db169024f67e 100644 --- a/src/Symfony/Bundle/FrameworkBundle/composer.json +++ b/src/Symfony/Bundle/FrameworkBundle/composer.json @@ -20,9 +20,9 @@ "ext-xml": "*", "symfony/cache": "~3.3", "symfony/class-loader": "~3.2", - "symfony/dependency-injection": "~3.3-beta2", + "symfony/dependency-injection": "~3.3", "symfony/config": "~3.3", - "symfony/event-dispatcher": "~3.3", + "symfony/event-dispatcher": "^3.3.1", "symfony/http-foundation": "~3.3", "symfony/http-kernel": "~3.3", "symfony/polyfill-mbstring": "~1.0", @@ -49,7 +49,7 @@ "symfony/serializer": "~3.3", "symfony/translation": "~3.2", "symfony/templating": "~2.8|~3.0", - "symfony/validator": "~3.3-rc2", + "symfony/validator": "~3.3", "symfony/workflow": "~3.3", "symfony/yaml": "~3.2", "symfony/property-info": "~3.3", @@ -69,7 +69,7 @@ "symfony/property-info": "<3.3", "symfony/serializer": "<3.3", "symfony/translation": "<3.2", - "symfony/validator": "<3.3-rc2", + "symfony/validator": "<3.3", "symfony/workflow": "<3.3" }, "suggest": { diff --git a/src/Symfony/Bundle/SecurityBundle/composer.json b/src/Symfony/Bundle/SecurityBundle/composer.json index 5c23309a46047..d0cd5fc6c953d 100644 --- a/src/Symfony/Bundle/SecurityBundle/composer.json +++ b/src/Symfony/Bundle/SecurityBundle/composer.json @@ -18,7 +18,7 @@ "require": { "php": ">=5.5.9", "symfony/security": "~3.3", - "symfony/dependency-injection": "~3.3-beta2", + "symfony/dependency-injection": "~3.3", "symfony/http-kernel": "~3.3", "symfony/polyfill-php70": "~1.0" }, diff --git a/src/Symfony/Component/DependencyInjection/composer.json b/src/Symfony/Component/DependencyInjection/composer.json index 7b0932881b464..3a2916635ffb8 100644 --- a/src/Symfony/Component/DependencyInjection/composer.json +++ b/src/Symfony/Component/DependencyInjection/composer.json @@ -32,7 +32,7 @@ "symfony/proxy-manager-bridge": "Generate service proxies to lazy load them" }, "conflict": { - "symfony/config": "<=3.3-beta1", + "symfony/config": "<3.3", "symfony/finder": "<3.3", "symfony/yaml": "<3.3" }, From b9c91cd88cf6dfd78fe874ba55c1e9333c83bef1 Mon Sep 17 00:00:00 2001 From: Romain Neutron Date: Fri, 2 Jun 2017 15:07:31 +0200 Subject: [PATCH 0124/1099] Deprecate passing a concrete service in optional cache warmers --- .../FrameworkBundle/CacheWarmer/RouterCacheWarmer.php | 2 ++ .../CacheWarmer/TranslationsCacheWarmer.php | 5 +++-- .../Bundle/TwigBundle/CacheWarmer/TemplateCacheWarmer.php | 7 ++++--- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/CacheWarmer/RouterCacheWarmer.php b/src/Symfony/Bundle/FrameworkBundle/CacheWarmer/RouterCacheWarmer.php index 256bebebe80b7..a650960c948e2 100644 --- a/src/Symfony/Bundle/FrameworkBundle/CacheWarmer/RouterCacheWarmer.php +++ b/src/Symfony/Bundle/FrameworkBundle/CacheWarmer/RouterCacheWarmer.php @@ -19,6 +19,8 @@ * Generates the router matcher and generator classes. * * @author Fabien Potencier + * + * @final since version 3.4, to be given a container instead in 4.0 */ class RouterCacheWarmer implements CacheWarmerInterface { diff --git a/src/Symfony/Bundle/FrameworkBundle/CacheWarmer/TranslationsCacheWarmer.php b/src/Symfony/Bundle/FrameworkBundle/CacheWarmer/TranslationsCacheWarmer.php index 33f94650449fb..8a416a2925650 100644 --- a/src/Symfony/Bundle/FrameworkBundle/CacheWarmer/TranslationsCacheWarmer.php +++ b/src/Symfony/Bundle/FrameworkBundle/CacheWarmer/TranslationsCacheWarmer.php @@ -29,7 +29,7 @@ class TranslationsCacheWarmer implements CacheWarmerInterface /** * TranslationsCacheWarmer constructor. * - * @param ContainerInterface|TranslatorInterface $container + * @param ContainerInterface $container */ public function __construct($container) { @@ -38,8 +38,9 @@ public function __construct($container) $this->container = $container; } elseif ($container instanceof TranslatorInterface) { $this->translator = $container; + @trigger_error(sprintf('Using a "%s" as first argument of %s is deprecated since version 3.4 and will be unsupported in version 4.0. Use a %s instead.', TranslatorInterface::class, __CLASS__, ContainerInterface::class), E_USER_DEPRECATED); } else { - throw new \InvalidArgumentException(sprintf('%s only accepts instance of Symfony\Component\DependencyInjection\ContainerInterface or Symfony\Component\Translation\TranslatorInterface as first argument.', __CLASS__)); + throw new \InvalidArgumentException(sprintf('%s only accepts instance of Symfony\Component\DependencyInjection\ContainerInterface as first argument.', __CLASS__)); } } diff --git a/src/Symfony/Bundle/TwigBundle/CacheWarmer/TemplateCacheWarmer.php b/src/Symfony/Bundle/TwigBundle/CacheWarmer/TemplateCacheWarmer.php index 9a60a92e85375..5d45efc7e2f0c 100644 --- a/src/Symfony/Bundle/TwigBundle/CacheWarmer/TemplateCacheWarmer.php +++ b/src/Symfony/Bundle/TwigBundle/CacheWarmer/TemplateCacheWarmer.php @@ -30,8 +30,8 @@ class TemplateCacheWarmer implements CacheWarmerInterface /** * TemplateCacheWarmer constructor. * - * @param ContainerInterface|Environment $container - * @param \Traversable $iterator + * @param ContainerInterface $container + * @param \Traversable $iterator */ public function __construct($container, \Traversable $iterator) { @@ -40,8 +40,9 @@ public function __construct($container, \Traversable $iterator) $this->container = $container; } elseif ($container instanceof Environment) { $this->twig = $container; + @trigger_error(sprintf('Using a "%s" as first argument of %s is deprecated since version 3.4 and will be unsupported in version 4.0. Use a %s instead.', Environment::class, __CLASS__, Container::class), E_USER_DEPRECATED); } else { - throw new \InvalidArgumentException(sprintf('%s only accepts instance of Symfony\Component\DependencyInjection\ContainerInterface or Environment as first argument.', __CLASS__)); + throw new \InvalidArgumentException(sprintf('%s only accepts instance of Symfony\Component\DependencyInjection\ContainerInterface as first argument.', __CLASS__)); } $this->iterator = $iterator; From 4ba59c9cdd3fa14bcd012dd6eb35ac015d5c2cc5 Mon Sep 17 00:00:00 2001 From: Romain Neutron Date: Fri, 2 Jun 2017 16:38:10 +0200 Subject: [PATCH 0125/1099] Implement ServiceSubscriberInterface in optional cache warmers --- .../CacheWarmer/TranslationsCacheWarmer.php | 17 ++++++++++++++--- .../Resources/config/translation.xml | 3 ++- .../CacheWarmer/TemplateCacheWarmer.php | 17 ++++++++++++++--- .../Bundle/TwigBundle/Resources/config/twig.xml | 3 ++- 4 files changed, 32 insertions(+), 8 deletions(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/CacheWarmer/TranslationsCacheWarmer.php b/src/Symfony/Bundle/FrameworkBundle/CacheWarmer/TranslationsCacheWarmer.php index 33f94650449fb..ac08766b8fca0 100644 --- a/src/Symfony/Bundle/FrameworkBundle/CacheWarmer/TranslationsCacheWarmer.php +++ b/src/Symfony/Bundle/FrameworkBundle/CacheWarmer/TranslationsCacheWarmer.php @@ -11,7 +11,8 @@ namespace Symfony\Bundle\FrameworkBundle\CacheWarmer; -use Symfony\Component\DependencyInjection\ContainerInterface; +use Psr\Container\ContainerInterface; +use Symfony\Component\DependencyInjection\ServiceSubscriberInterface; use Symfony\Component\HttpKernel\CacheWarmer\CacheWarmerInterface; use Symfony\Component\HttpKernel\CacheWarmer\WarmableInterface; use Symfony\Component\Translation\TranslatorInterface; @@ -21,7 +22,7 @@ * * @author Xavier Leune */ -class TranslationsCacheWarmer implements CacheWarmerInterface +class TranslationsCacheWarmer implements CacheWarmerInterface, ServiceSubscriberInterface { private $container; private $translator; @@ -39,7 +40,7 @@ public function __construct($container) } elseif ($container instanceof TranslatorInterface) { $this->translator = $container; } else { - throw new \InvalidArgumentException(sprintf('%s only accepts instance of Symfony\Component\DependencyInjection\ContainerInterface or Symfony\Component\Translation\TranslatorInterface as first argument.', __CLASS__)); + throw new \InvalidArgumentException(sprintf('%s only accepts instance of Psr\Container\ContainerInterface as first argument.', __CLASS__)); } } @@ -64,4 +65,14 @@ public function isOptional() { return true; } + + /** + * {@inheritdoc} + */ + public static function getSubscribedServices() + { + return array( + 'translator' => TranslatorInterface::class, + ); + } } diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/translation.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/translation.xml index 5f98febda6304..4f8999d0cb647 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/translation.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/translation.xml @@ -123,8 +123,9 @@ - + + diff --git a/src/Symfony/Bundle/TwigBundle/CacheWarmer/TemplateCacheWarmer.php b/src/Symfony/Bundle/TwigBundle/CacheWarmer/TemplateCacheWarmer.php index 9a60a92e85375..133743662f474 100644 --- a/src/Symfony/Bundle/TwigBundle/CacheWarmer/TemplateCacheWarmer.php +++ b/src/Symfony/Bundle/TwigBundle/CacheWarmer/TemplateCacheWarmer.php @@ -11,7 +11,8 @@ namespace Symfony\Bundle\TwigBundle\CacheWarmer; -use Symfony\Component\DependencyInjection\ContainerInterface; +use Psr\Container\ContainerInterface; +use Symfony\Component\DependencyInjection\ServiceSubscriberInterface; use Symfony\Component\HttpKernel\CacheWarmer\CacheWarmerInterface; use Twig\Environment; use Twig\Error\Error; @@ -21,7 +22,7 @@ * * @author Fabien Potencier */ -class TemplateCacheWarmer implements CacheWarmerInterface +class TemplateCacheWarmer implements CacheWarmerInterface, ServiceSubscriberInterface { private $container; private $twig; @@ -41,7 +42,7 @@ public function __construct($container, \Traversable $iterator) } elseif ($container instanceof Environment) { $this->twig = $container; } else { - throw new \InvalidArgumentException(sprintf('%s only accepts instance of Symfony\Component\DependencyInjection\ContainerInterface or Environment as first argument.', __CLASS__)); + throw new \InvalidArgumentException(sprintf('%s only accepts instance of Psr\Container\ContainerInterface as first argument.', __CLASS__)); } $this->iterator = $iterator; @@ -73,4 +74,14 @@ public function isOptional() { return true; } + + /** + * {@inheritdoc} + */ + public static function getSubscribedServices() + { + return array( + 'twig' => Environment::class, + ); + } } diff --git a/src/Symfony/Bundle/TwigBundle/Resources/config/twig.xml b/src/Symfony/Bundle/TwigBundle/Resources/config/twig.xml index 310ab14063a0b..bf53c2b2b28f6 100644 --- a/src/Symfony/Bundle/TwigBundle/Resources/config/twig.xml +++ b/src/Symfony/Bundle/TwigBundle/Resources/config/twig.xml @@ -45,7 +45,8 @@ - + + From 86bf26c466fa695a64b8836decc8a1c8b6296682 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Fri, 2 Jun 2017 19:23:28 +0200 Subject: [PATCH 0126/1099] [Config] Always protect ClassExistenceResource against bad parents --- .../Resource/ClassExistenceResource.php | 40 +++++++++---------- .../Resource/ClassExistenceResourceTest.php | 4 +- .../Compiler/AutowirePass.php | 6 +-- .../DependencyInjection/ContainerBuilder.php | 12 ++---- .../DependencyInjection/composer.json | 2 +- 5 files changed, 28 insertions(+), 36 deletions(-) diff --git a/src/Symfony/Component/Config/Resource/ClassExistenceResource.php b/src/Symfony/Component/Config/Resource/ClassExistenceResource.php index 040cfc510eb9b..8a86a4209961b 100644 --- a/src/Symfony/Component/Config/Resource/ClassExistenceResource.php +++ b/src/Symfony/Component/Config/Resource/ClassExistenceResource.php @@ -21,25 +21,21 @@ */ class ClassExistenceResource implements SelfCheckingResourceInterface, \Serializable { - const EXISTS_OK = 1; - const EXISTS_KO = 0; - const EXISTS_KO_WITH_THROWING_AUTOLOADER = -1; - private $resource; - private $existsStatus; + private $exists; private static $autoloadLevel = 0; private static $existsCache = array(); /** - * @param string $resource The fully-qualified class name - * @param int|null $existsStatus One of the self::EXISTS_* const if the existency check has already been done + * @param string $resource The fully-qualified class name + * @param bool|null $exists Boolean when the existency check has already been done */ - public function __construct($resource, $existsStatus = null) + public function __construct($resource, $exists = null) { $this->resource = $resource; - if (null !== $existsStatus) { - $this->existsStatus = (int) $existsStatus; + if (null !== $exists) { + $this->exists = (bool) $exists; } } @@ -64,11 +60,13 @@ public function getResource() */ public function isFresh($timestamp) { + $loaded = class_exists($this->resource, false) || interface_exists($this->resource, false) || trait_exists($this->resource, false); + if (null !== $exists = &self::$existsCache[$this->resource]) { - $exists = $exists || class_exists($this->resource, false) || interface_exists($this->resource, false) || trait_exists($this->resource, false); - } elseif (self::EXISTS_KO_WITH_THROWING_AUTOLOADER === $this->existsStatus) { + $exists = $exists || $loaded; + } elseif (!$exists = $loaded) { if (!self::$autoloadLevel++) { - spl_autoload_register('Symfony\Component\Config\Resource\ClassExistenceResource::throwOnRequiredClass'); + spl_autoload_register(__CLASS__.'::throwOnRequiredClass'); } try { @@ -77,18 +75,16 @@ public function isFresh($timestamp) $exists = false; } finally { if (!--self::$autoloadLevel) { - spl_autoload_unregister('Symfony\Component\Config\Resource\ClassExistenceResource::throwOnRequiredClass'); + spl_autoload_unregister(__CLASS__.'::throwOnRequiredClass'); } } - } else { - $exists = class_exists($this->resource) || interface_exists($this->resource, false) || trait_exists($this->resource, false); } - if (null === $this->existsStatus) { - $this->existsStatus = $exists ? self::EXISTS_OK : self::EXISTS_KO; + if (null === $this->exists) { + $this->exists = $exists; } - return self::EXISTS_OK === $this->existsStatus xor !$exists; + return $this->exists xor !$exists; } /** @@ -96,11 +92,11 @@ public function isFresh($timestamp) */ public function serialize() { - if (null === $this->existsStatus) { + if (null === $this->exists) { $this->isFresh(0); } - return serialize(array($this->resource, $this->existsStatus)); + return serialize(array($this->resource, $this->exists)); } /** @@ -108,7 +104,7 @@ public function serialize() */ public function unserialize($serialized) { - list($this->resource, $this->existsStatus) = unserialize($serialized); + list($this->resource, $this->exists) = unserialize($serialized); } /** diff --git a/src/Symfony/Component/Config/Tests/Resource/ClassExistenceResourceTest.php b/src/Symfony/Component/Config/Tests/Resource/ClassExistenceResourceTest.php index f429a33626564..3daef17ee1300 100644 --- a/src/Symfony/Component/Config/Tests/Resource/ClassExistenceResourceTest.php +++ b/src/Symfony/Component/Config/Tests/Resource/ClassExistenceResourceTest.php @@ -66,7 +66,7 @@ public function testExistsKo() $loadedClass = 123; - $res = new ClassExistenceResource('MissingFooClass', ClassExistenceResource::EXISTS_KO); + $res = new ClassExistenceResource('MissingFooClass', false); $this->assertSame(123, $loadedClass); } finally { @@ -76,7 +76,7 @@ public function testExistsKo() public function testConditionalClass() { - $res = new ClassExistenceResource(ConditionalClass::class, ClassExistenceResource::EXISTS_KO_WITH_THROWING_AUTOLOADER); + $res = new ClassExistenceResource(ConditionalClass::class, false); $this->assertFalse($res->isFresh(0)); } diff --git a/src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php b/src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php index 49138f91bea34..8382d303859e1 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php @@ -388,7 +388,7 @@ private function populateAvailableType($id, Definition $definition) unset($this->ambiguousServiceTypes[$type]); } - if ($definition->isDeprecated() || !$reflectionClass = $this->container->getReflectionClass($definition->getClass(), true)) { + if ($definition->isDeprecated() || !$reflectionClass = $this->container->getReflectionClass($definition->getClass())) { return; } @@ -444,7 +444,7 @@ private function set($type, $id) */ private function createAutowiredDefinition($type) { - if (!($typeHint = $this->container->getReflectionClass($type, true)) || !$typeHint->isInstantiable()) { + if (!($typeHint = $this->container->getReflectionClass($type)) || !$typeHint->isInstantiable()) { return; } @@ -478,7 +478,7 @@ private function createAutowiredDefinition($type) private function createTypeNotFoundMessage(TypedReference $reference, $label) { - if (!$r = $this->container->getReflectionClass($type = $reference->getType(), true)) { + if (!$r = $this->container->getReflectionClass($type = $reference->getType())) { $message = sprintf('has type "%s" but this class does not exist.', $type); } else { $message = $this->container->has($type) ? 'this service is abstract' : 'no such service exists'; diff --git a/src/Symfony/Component/DependencyInjection/ContainerBuilder.php b/src/Symfony/Component/DependencyInjection/ContainerBuilder.php index 3887e56fc244a..14dd957e9ea13 100644 --- a/src/Symfony/Component/DependencyInjection/ContainerBuilder.php +++ b/src/Symfony/Component/DependencyInjection/ContainerBuilder.php @@ -337,13 +337,12 @@ public function addClassResource(\ReflectionClass $class) * Retrieves the requested reflection class and registers it for resource tracking. * * @param string $class - * @param bool $koWithThrowingAutoloader Whether autoload should be protected against bad parents or not * * @return \ReflectionClass|null * * @final */ - public function getReflectionClass($class, $koWithThrowingAutoloader = false) + public function getReflectionClass($class) { if (!$class = $this->getParameterBag()->resolveValue($class)) { return; @@ -353,12 +352,9 @@ public function getReflectionClass($class, $koWithThrowingAutoloader = false) try { if (isset($this->classReflectors[$class])) { $classReflector = $this->classReflectors[$class]; - } elseif ($koWithThrowingAutoloader) { - $resource = new ClassExistenceResource($class, ClassExistenceResource::EXISTS_KO_WITH_THROWING_AUTOLOADER); - - $classReflector = $resource->isFresh(0) ? false : new \ReflectionClass($class); } else { - $classReflector = new \ReflectionClass($class); + $resource = new ClassExistenceResource($class, false); + $classReflector = $resource->isFresh(0) ? false : new \ReflectionClass($class); } } catch (\ReflectionException $e) { $classReflector = false; @@ -366,7 +362,7 @@ public function getReflectionClass($class, $koWithThrowingAutoloader = false) if ($this->trackResources) { if (!$classReflector) { - $this->addResource($resource ?: new ClassExistenceResource($class, ClassExistenceResource::EXISTS_KO)); + $this->addResource($resource ?: new ClassExistenceResource($class, false)); } elseif (!$classReflector->isInternal()) { $path = $classReflector->getFileName(); diff --git a/src/Symfony/Component/DependencyInjection/composer.json b/src/Symfony/Component/DependencyInjection/composer.json index 3a2916635ffb8..8c88d4f02a790 100644 --- a/src/Symfony/Component/DependencyInjection/composer.json +++ b/src/Symfony/Component/DependencyInjection/composer.json @@ -32,7 +32,7 @@ "symfony/proxy-manager-bridge": "Generate service proxies to lazy load them" }, "conflict": { - "symfony/config": "<3.3", + "symfony/config": "<3.3.1", "symfony/finder": "<3.3", "symfony/yaml": "<3.3" }, From 2a293692f273fdd5d3b97c0ab55ced82b868b2b0 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Fri, 2 Jun 2017 21:23:33 +0200 Subject: [PATCH 0127/1099] [Console] Add missing dev-dep --- src/Symfony/Component/Console/composer.json | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Symfony/Component/Console/composer.json b/src/Symfony/Component/Console/composer.json index 362d55d1af8e9..db76bf3b2c7a7 100644 --- a/src/Symfony/Component/Console/composer.json +++ b/src/Symfony/Component/Console/composer.json @@ -21,6 +21,7 @@ "symfony/debug": "~2.8|~3.0" }, "require-dev": { + "symfony/config": "~3.3", "symfony/http-kernel": "~2.8|~3.0", "symfony/event-dispatcher": "~2.8|~3.0", "symfony/dependency-injection": "~3.3", From d3e6a2d6f6d69e4f693a94a0c6edd52cbc91f513 Mon Sep 17 00:00:00 2001 From: Vincent AUBERT Date: Fri, 2 Jun 2017 19:45:13 +0200 Subject: [PATCH 0128/1099] minor #23043 add \ to PHP_VERSION_ID fixes #22650 --- src/Symfony/Bridge/Twig/DataCollector/TwigDataCollector.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Bridge/Twig/DataCollector/TwigDataCollector.php b/src/Symfony/Bridge/Twig/DataCollector/TwigDataCollector.php index 382ce13987cc3..f28c92422ae48 100644 --- a/src/Symfony/Bridge/Twig/DataCollector/TwigDataCollector.php +++ b/src/Symfony/Bridge/Twig/DataCollector/TwigDataCollector.php @@ -96,7 +96,7 @@ public function getHtmlCallGraph() public function getProfile() { if (null === $this->profile) { - if (PHP_VERSION_ID >= 70000) { + if (\PHP_VERSION_ID >= 70000) { $this->profile = unserialize($this->data['profile'], array('allowed_classes' => array('Twig_Profiler_Profile', 'Twig\Profiler\Profile'))); } else { $this->profile = unserialize($this->data['profile']); From 67895f4dd33b39fb84fcd6aa13d8eeb31cfae7dd Mon Sep 17 00:00:00 2001 From: Richard van Laak Date: Fri, 2 Jun 2017 10:44:49 +0200 Subject: [PATCH 0129/1099] [Yaml] Clarify "incompatible key casting" deprecation message --- src/Symfony/Component/Yaml/Parser.php | 3 ++- src/Symfony/Component/Yaml/Tests/ParserTest.php | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Component/Yaml/Parser.php b/src/Symfony/Component/Yaml/Parser.php index 42f61af9de0a4..4a5f2b91e06bf 100644 --- a/src/Symfony/Component/Yaml/Parser.php +++ b/src/Symfony/Component/Yaml/Parser.php @@ -237,7 +237,8 @@ private function doParse($value, $flags) } if (!(Yaml::PARSE_KEYS_AS_STRINGS & $flags) && !is_string($key)) { - @trigger_error('Implicit casting of incompatible mapping keys to strings is deprecated since version 3.3 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0. Pass the PARSE_KEYS_AS_STRING flag to explicitly enable the type casts.', E_USER_DEPRECATED); + $keyType = is_numeric($key) ? 'numeric key' : 'incompatible key type'; + @trigger_error(sprintf('Implicit casting of %s to string on line %d is deprecated since version 3.3 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0. Pass the PARSE_KEYS_AS_STRING flag to explicitly enable the type casts.', $keyType, $this->getRealCurrentLineNb()), E_USER_DEPRECATED); } // Convert float keys to strings, to avoid being converted to integers by PHP diff --git a/src/Symfony/Component/Yaml/Tests/ParserTest.php b/src/Symfony/Component/Yaml/Tests/ParserTest.php index a0bef9d528c81..a6c7b6ad12aff 100644 --- a/src/Symfony/Component/Yaml/Tests/ParserTest.php +++ b/src/Symfony/Component/Yaml/Tests/ParserTest.php @@ -1081,7 +1081,7 @@ public function testYamlDirective() /** * @group legacy - * @expectedDeprecation Implicit casting of incompatible mapping keys to strings is deprecated since version 3.3 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0. Pass the PARSE_KEYS_AS_STRING flag to explicitly enable the type casts. + * @expectedDeprecation Implicit casting of numeric key to string on line 1 is deprecated since version 3.3 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0. Pass the PARSE_KEYS_AS_STRING flag to explicitly enable the type casts. */ public function testFloatKeys() { @@ -1103,7 +1103,7 @@ public function testFloatKeys() /** * @group legacy - * @expectedDeprecation Implicit casting of incompatible mapping keys to strings is deprecated since version 3.3 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0. Pass the PARSE_KEYS_AS_STRING flag to explicitly enable the type casts. + * @expectedDeprecation Implicit casting of incompatible key type to string on line 1 is deprecated since version 3.3 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0. Pass the PARSE_KEYS_AS_STRING flag to explicitly enable the type casts. */ public function testBooleanKeys() { From 61685c7106c282b4e07f31f83b22f5dcd2410a40 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Sat, 3 Jun 2017 09:31:39 +0200 Subject: [PATCH 0130/1099] [Cache] fix Redis scheme detection --- src/Symfony/Component/Cache/Adapter/RedisAdapter.php | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/Cache/Adapter/RedisAdapter.php b/src/Symfony/Component/Cache/Adapter/RedisAdapter.php index 922d3d3e5150b..34f7c59926e3d 100644 --- a/src/Symfony/Component/Cache/Adapter/RedisAdapter.php +++ b/src/Symfony/Component/Cache/Adapter/RedisAdapter.php @@ -90,6 +90,11 @@ public static function createConnection($dsn, array $options = array()) $params['dbindex'] = $m[1]; $params['path'] = substr($params['path'], 0, -strlen($m[0])); } + if (isset($params['host'])) { + $scheme = 'tcp'; + } else { + $scheme = 'unix'; + } $params += array( 'host' => isset($params['host']) ? $params['host'] : $params['path'], 'port' => isset($params['host']) ? 6379 : null, @@ -120,7 +125,7 @@ public static function createConnection($dsn, array $options = array()) throw new InvalidArgumentException(sprintf('Redis connection failed (%s): %s', $e, $dsn)); } } elseif (is_a($class, \Predis\Client::class, true)) { - $params['scheme'] = isset($params['host']) ? 'tcp' : 'unix'; + $params['scheme'] = $scheme; $params['database'] = $params['dbindex'] ?: null; $params['password'] = $auth; $redis = new $class((new Factory())->create($params)); From 0068968dcc43b08827e6d3779cfc52f3eb206f80 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Sat, 3 Jun 2017 10:00:53 +0200 Subject: [PATCH 0131/1099] explain that a role can be an instance of Role Only mentioning the RoleInterface seems to be confusing as it is deprecated since Symfony 3.3. --- .../Security/Core/Authentication/Token/AbstractToken.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/Security/Core/Authentication/Token/AbstractToken.php b/src/Symfony/Component/Security/Core/Authentication/Token/AbstractToken.php index 0eee6d94a41c6..82e7fa672fdd8 100644 --- a/src/Symfony/Component/Security/Core/Authentication/Token/AbstractToken.php +++ b/src/Symfony/Component/Security/Core/Authentication/Token/AbstractToken.php @@ -43,7 +43,7 @@ public function __construct(array $roles = array()) if (is_string($role)) { $role = new Role($role); } elseif (!$role instanceof RoleInterface) { - throw new \InvalidArgumentException(sprintf('$roles must be an array of strings, or RoleInterface instances, but got %s.', gettype($role))); + throw new \InvalidArgumentException(sprintf('$roles must be an array of strings, Role instances or RoleInterface instances, but got %s.', gettype($role))); } $this->roles[] = $role; From 479895f6671fef54eb92c941802509a9ad338b01 Mon Sep 17 00:00:00 2001 From: Maxime Steinhausser Date: Sat, 3 Jun 2017 10:06:02 +0200 Subject: [PATCH 0132/1099] [Form][FrameworkBundle] Remove non-existing arg for data_collector.form --- .../Bundle/FrameworkBundle/Resources/config/form_debug.xml | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/form_debug.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/form_debug.xml index 843fc72bdb253..9c2dfad2ee639 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/form_debug.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/form_debug.xml @@ -24,7 +24,6 @@ - false From 761bcca314ceb7c066155b2a0674b83c0ad6e1c8 Mon Sep 17 00:00:00 2001 From: Maxime Steinhausser Date: Sat, 3 Jun 2017 09:59:53 +0200 Subject: [PATCH 0133/1099] [Form] Missing deprecated paths removal --- .../FrameworkBundle/Resources/config/form.xml | 1 - .../Resources/config/form_debug.xml | 1 - src/Symfony/Component/Form/CHANGELOG.md | 5 + .../Core/EventListener/ResizeFormListener.php | 6 +- .../DataCollector/FormDataCollector.php | 101 +++++++----------- .../DataCollector/FormDataExtractor.php | 11 -- .../DependencyInjectionExtension.php | 34 +----- src/Symfony/Component/Form/Form.php | 4 +- .../DependencyInjectionExtensionTest.php | 83 -------------- .../Component/Form/Tests/SimpleFormTest.php | 9 -- .../DataCollector/DataCollector.php | 2 +- 11 files changed, 50 insertions(+), 207 deletions(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/form.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/form.xml index ae0be68d1e439..f9655322287af 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/form.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/form.xml @@ -38,7 +38,6 @@ - null diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/form_debug.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/form_debug.xml index d7e4803f5cf5d..8990f7c6cddc7 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/form_debug.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/form_debug.xml @@ -26,7 +26,6 @@ - false diff --git a/src/Symfony/Component/Form/CHANGELOG.md b/src/Symfony/Component/Form/CHANGELOG.md index 9f5e6e23e7eba..8b3156de2dba1 100644 --- a/src/Symfony/Component/Form/CHANGELOG.md +++ b/src/Symfony/Component/Form/CHANGELOG.md @@ -13,6 +13,11 @@ CHANGELOG * removed the support for caching loaded choice lists in `LazyChoiceList`, cache the choice list in the used `ChoiceLoaderInterface` implementation instead + * removed the support for objects implementing both `\Traversable` and `\ArrayAccess` in `ResizeFormListener::preSubmit()` + * removed the ability to use `FormDataCollector` without the `symfony/var-dumper` component + * removed passing a `ValueExporter` instance to the `FormDataExtractor::__construct()` method + * removed passing guesser services ids as the fourth argument of `DependencyInjectionExtension::__construct()` + * removed the ability to validate an unsubmitted form. 3.3.0 ----- diff --git a/src/Symfony/Component/Form/Extension/Core/EventListener/ResizeFormListener.php b/src/Symfony/Component/Form/Extension/Core/EventListener/ResizeFormListener.php index c3218ae4ec1cf..3cab8ba0bd96f 100644 --- a/src/Symfony/Component/Form/Extension/Core/EventListener/ResizeFormListener.php +++ b/src/Symfony/Component/Form/Extension/Core/EventListener/ResizeFormListener.php @@ -102,11 +102,7 @@ public function preSubmit(FormEvent $event) $form = $event->getForm(); $data = $event->getData(); - if ($data instanceof \Traversable && $data instanceof \ArrayAccess) { - @trigger_error('Support for objects implementing both \Traversable and \ArrayAccess is deprecated since version 3.1 and will be removed in 4.0. Use an array instead.', E_USER_DEPRECATED); - } - - if (!is_array($data) && !($data instanceof \Traversable && $data instanceof \ArrayAccess)) { + if (!is_array($data)) { $data = array(); } diff --git a/src/Symfony/Component/Form/Extension/DataCollector/FormDataCollector.php b/src/Symfony/Component/Form/Extension/DataCollector/FormDataCollector.php index b088abc7962f6..0362c856cb7e6 100644 --- a/src/Symfony/Component/Form/Extension/DataCollector/FormDataCollector.php +++ b/src/Symfony/Component/Form/Extension/DataCollector/FormDataCollector.php @@ -16,7 +16,6 @@ use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\DataCollector\DataCollector; -use Symfony\Component\HttpKernel\DataCollector\Util\ValueExporter; use Symfony\Component\Validator\ConstraintViolationInterface; use Symfony\Component\VarDumper\Caster\Caster; use Symfony\Component\VarDumper\Caster\ClassStub; @@ -72,27 +71,23 @@ class FormDataCollector extends DataCollector implements FormDataCollectorInterf */ private $formsByView; - /** - * @var ValueExporter - */ - private $valueExporter; - /** * @var ClonerInterface */ private $cloner; - private $hasVarDumper; - public function __construct(FormDataExtractorInterface $dataExtractor) { + if (!class_exists(ClassStub::class)) { + throw new \LogicException(sprintf('The VarDumper component is needed for using the %s class. Install symfony/var-dumper version 3.4 or above.', __CLASS__)); + } + $this->dataExtractor = $dataExtractor; $this->data = array( 'forms' => array(), 'forms_by_hash' => array(), 'nb_errors' => 0, ); - $this->hasVarDumper = class_exists(ClassStub::class); } /** @@ -241,11 +236,9 @@ public function getData() public function serialize() { - if ($this->hasVarDumper) { - foreach ($this->data['forms_by_hash'] as &$form) { - if (isset($form['type_class']) && !$form['type_class'] instanceof ClassStub) { - $form['type_class'] = new ClassStub($form['type_class']); - } + foreach ($this->data['forms_by_hash'] as &$form) { + if (isset($form['type_class']) && !$form['type_class'] instanceof ClassStub) { + $form['type_class'] = new ClassStub($form['type_class']); } } @@ -261,55 +254,43 @@ protected function cloneVar($var, $isClass = false) return $var; } if (null === $this->cloner) { - if ($this->hasVarDumper) { - $this->cloner = new VarCloner(); - $this->cloner->setMaxItems(-1); - $this->cloner->addCasters(array( - '*' => function ($v, array $a, Stub $s, $isNested) { - foreach ($a as &$v) { - if (is_object($v) && !$v instanceof \DateTimeInterface) { - $v = new CutStub($v); - } + $this->cloner = new VarCloner(); + $this->cloner->setMaxItems(-1); + $this->cloner->addCasters(array( + '*' => function ($v, array $a, Stub $s, $isNested) { + foreach ($a as &$v) { + if (is_object($v) && !$v instanceof \DateTimeInterface) { + $v = new CutStub($v); } - - return $a; - }, - \Exception::class => function (\Exception $e, array $a, Stub $s) { - if (isset($a[$k = "\0Exception\0previous"])) { - unset($a[$k]); - ++$s->cut; - } - - return $a; - }, - FormInterface::class => function (FormInterface $f, array $a) { - return array( - Caster::PREFIX_VIRTUAL.'name' => $f->getName(), - Caster::PREFIX_VIRTUAL.'type_class' => new ClassStub(get_class($f->getConfig()->getType()->getInnerType())), - ); - }, - ConstraintViolationInterface::class => function (ConstraintViolationInterface $v, array $a) { - return array( - Caster::PREFIX_VIRTUAL.'root' => $v->getRoot(), - Caster::PREFIX_VIRTUAL.'path' => $v->getPropertyPath(), - Caster::PREFIX_VIRTUAL.'value' => $v->getInvalidValue(), - ); - }, - )); - } else { - @trigger_error(sprintf('Using the %s() method without the VarDumper component is deprecated since version 3.2 and won\'t be supported in 4.0. Install symfony/var-dumper version 3.2 or above.', __METHOD__), E_USER_DEPRECATED); - $this->cloner = false; - } - } - if (false !== $this->cloner) { - return $this->cloner->cloneVar($var, Caster::EXCLUDE_VERBOSE); - } - - if (null === $this->valueExporter) { - $this->valueExporter = new ValueExporter(); + } + + return $a; + }, + \Exception::class => function (\Exception $e, array $a, Stub $s) { + if (isset($a[$k = "\0Exception\0previous"])) { + unset($a[$k]); + ++$s->cut; + } + + return $a; + }, + FormInterface::class => function (FormInterface $f, array $a) { + return array( + Caster::PREFIX_VIRTUAL.'name' => $f->getName(), + Caster::PREFIX_VIRTUAL.'type_class' => new ClassStub(get_class($f->getConfig()->getType()->getInnerType())), + ); + }, + ConstraintViolationInterface::class => function (ConstraintViolationInterface $v, array $a) { + return array( + Caster::PREFIX_VIRTUAL.'root' => $v->getRoot(), + Caster::PREFIX_VIRTUAL.'path' => $v->getPropertyPath(), + Caster::PREFIX_VIRTUAL.'value' => $v->getInvalidValue(), + ); + }, + )); } - return $this->valueExporter->exportValue($var); + return $this->cloner->cloneVar($var, Caster::EXCLUDE_VERBOSE); } private function &recursiveBuildPreliminaryFormTree(FormInterface $form, array &$outputByHash) diff --git a/src/Symfony/Component/Form/Extension/DataCollector/FormDataExtractor.php b/src/Symfony/Component/Form/Extension/DataCollector/FormDataExtractor.php index de6fac41231de..355f4d13577c7 100644 --- a/src/Symfony/Component/Form/Extension/DataCollector/FormDataExtractor.php +++ b/src/Symfony/Component/Form/Extension/DataCollector/FormDataExtractor.php @@ -13,7 +13,6 @@ use Symfony\Component\Form\FormInterface; use Symfony\Component\Form\FormView; -use Symfony\Component\HttpKernel\DataCollector\Util\ValueExporter; use Symfony\Component\Validator\ConstraintViolationInterface; /** @@ -23,16 +22,6 @@ */ class FormDataExtractor implements FormDataExtractorInterface { - /** - * Constructs a new data extractor. - */ - public function __construct(ValueExporter $valueExporter = null, $triggerDeprecationNotice = true) - { - if (null !== $valueExporter && $triggerDeprecationNotice) { - @trigger_error('Passing a ValueExporter instance to '.__METHOD__.'() is deprecated in version 3.2 and will be removed in 4.0.', E_USER_DEPRECATED); - } - } - /** * {@inheritdoc} */ diff --git a/src/Symfony/Component/Form/Extension/DependencyInjection/DependencyInjectionExtension.php b/src/Symfony/Component/Form/Extension/DependencyInjection/DependencyInjectionExtension.php index 59e7eb766e4b4..3315be895c1d4 100644 --- a/src/Symfony/Component/Form/Extension/DependencyInjection/DependencyInjectionExtension.php +++ b/src/Symfony/Component/Form/Extension/DependencyInjection/DependencyInjectionExtension.php @@ -24,10 +24,6 @@ class DependencyInjectionExtension implements FormExtensionInterface private $typeExtensionServices; private $guesserServices; - // @deprecated to be removed in Symfony 4.0 - private $typeServiceIds; - private $guesserServiceIds; - /** * Constructor. * @@ -35,16 +31,8 @@ class DependencyInjectionExtension implements FormExtensionInterface * @param iterable[] $typeExtensionServices * @param iterable $guesserServices */ - public function __construct(ContainerInterface $typeContainer, array $typeExtensionServices, $guesserServices, array $guesserServiceIds = null) + public function __construct(ContainerInterface $typeContainer, array $typeExtensionServices, $guesserServices) { - if (null !== $guesserServiceIds) { - @trigger_error(sprintf('Passing four arguments to the %s::__construct() method is deprecated since Symfony 3.3 and will be disallowed in Symfony 4.0. The new constructor only accepts three arguments.', __CLASS__), E_USER_DEPRECATED); - $this->guesserServiceIds = $guesserServiceIds; - $this->typeServiceIds = $typeExtensionServices; - $typeExtensionServices = $guesserServices; - $guesserServices = $guesserServiceIds; - } - $this->typeContainer = $typeContainer; $this->typeExtensionServices = $typeExtensionServices; $this->guesserServices = $guesserServices; @@ -52,14 +40,6 @@ public function __construct(ContainerInterface $typeContainer, array $typeExtens public function getType($name) { - if (null !== $this->guesserServiceIds) { - if (!isset($this->typeServiceIds[$name])) { - throw new InvalidArgumentException(sprintf('The field type "%s" is not registered in the service container.', $name)); - } - - return $this->typeContainer->get($this->typeServiceIds[$name]); - } - if (!$this->typeContainer->has($name)) { throw new InvalidArgumentException(sprintf('The field type "%s" is not registered in the service container.', $name)); } @@ -69,10 +49,6 @@ public function getType($name) public function hasType($name) { - if (null !== $this->guesserServiceIds) { - return isset($this->typeServiceIds[$name]); - } - return $this->typeContainer->has($name); } @@ -82,10 +58,6 @@ public function getTypeExtensions($name) if (isset($this->typeExtensionServices[$name])) { foreach ($this->typeExtensionServices[$name] as $serviceId => $extension) { - if (null !== $this->guesserServiceIds) { - $extension = $this->typeContainer->get($serviceId = $extension); - } - $extensions[] = $extension; // validate result of getExtendedType() to ensure it is consistent with the service definition @@ -116,10 +88,6 @@ public function getTypeGuesser() $guessers = array(); foreach ($this->guesserServices as $serviceId => $service) { - if (null !== $this->guesserServiceIds) { - $service = $this->typeContainer->get($serviceId = $service); - } - $guessers[] = $service; } diff --git a/src/Symfony/Component/Form/Form.php b/src/Symfony/Component/Form/Form.php index cdbb0fe171824..57b0c5d20e63d 100644 --- a/src/Symfony/Component/Form/Form.php +++ b/src/Symfony/Component/Form/Form.php @@ -736,9 +736,7 @@ public function isEmpty() public function isValid() { if (!$this->submitted) { - @trigger_error('Call Form::isValid() with an unsubmitted form is deprecated since version 3.2 and will throw an exception in 4.0. Use Form::isSubmitted() before Form::isValid() instead.', E_USER_DEPRECATED); - - return false; + throw new LogicException('Cannot check if an unsubmitted form is valid. Call Form::isSubmitted() before Form::isValid().'); } if ($this->isDisabled()) { diff --git a/src/Symfony/Component/Form/Tests/Extension/DependencyInjection/DependencyInjectionExtensionTest.php b/src/Symfony/Component/Form/Tests/Extension/DependencyInjection/DependencyInjectionExtensionTest.php index 66a7bf07191d2..a94d57ec475a4 100644 --- a/src/Symfony/Component/Form/Tests/Extension/DependencyInjection/DependencyInjectionExtensionTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/DependencyInjection/DependencyInjectionExtensionTest.php @@ -12,7 +12,6 @@ namespace Symfony\Component\Form\Tests\Extension\DependencyInjection; use PHPUnit\Framework\TestCase; -use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException; use Symfony\Component\Form\Extension\DependencyInjection\DependencyInjectionExtension; use Symfony\Component\Form\FormTypeGuesserChain; use Symfony\Component\Form\FormTypeGuesserInterface; @@ -59,61 +58,6 @@ public function testThrowExceptionForInvalidExtendedType() $extension->getTypeExtensions('test'); } - /** - * @group legacy - * @expectedDeprecation Passing four arguments to the Symfony\Component\Form\Extension\DependencyInjection\DependencyInjectionExtension::__construct() method is deprecated since Symfony 3.3 and will be disallowed in Symfony 4.0. The new constructor only accepts three arguments. - */ - public function testLegacyGetTypeExtensions() - { - $container = $this->createContainerMock(); - - $services = array( - 'extension1' => $typeExtension1 = $this->createFormTypeExtensionMock('test'), - 'extension2' => $typeExtension2 = $this->createFormTypeExtensionMock('test'), - 'extension3' => $typeExtension3 = $this->createFormTypeExtensionMock('other'), - ); - - $container->expects($this->any()) - ->method('get') - ->willReturnCallback(function ($id) use ($services) { - if (isset($services[$id])) { - return $services[$id]; - } - - throw new ServiceNotFoundException($id); - }); - - $extension = new DependencyInjectionExtension($container, array(), array('test' => array('extension1', 'extension2'), 'other' => array('extension3')), array()); - - $this->assertTrue($extension->hasTypeExtensions('test')); - $this->assertFalse($extension->hasTypeExtensions('unknown')); - $this->assertSame(array($typeExtension1, $typeExtension2), $extension->getTypeExtensions('test')); - } - - /** - * @group legacy - * @expectedException \Symfony\Component\Form\Exception\InvalidArgumentException - * @expectedDeprecation Passing four arguments to the Symfony\Component\Form\Extension\DependencyInjection\DependencyInjectionExtension::__construct() method is deprecated since Symfony 3.3 and will be disallowed in Symfony 4.0. The new constructor only accepts three arguments. - */ - public function testLegacyThrowExceptionForInvalidExtendedType() - { - $formTypeExtension = $this->createFormTypeExtensionMock('unmatched'); - - $container = $this->createContainerMock(); - - $container->expects($this->any()) - ->method('get') - ->with('extension') - ->willReturn($formTypeExtension); - - $extension = new DependencyInjectionExtension($container, array(), array('test' => array('extension')), array()); - - $extensions = $extension->getTypeExtensions('test'); - - $this->assertCount(1, $extensions); - $this->assertSame($formTypeExtension, $extensions[0]); - } - public function testGetTypeGuesser() { $container = $this->createContainerMock(); @@ -130,33 +74,6 @@ public function testGetTypeGuesserReturnsNullWhenNoTypeGuessersHaveBeenConfigure $this->assertNull($extension->getTypeGuesser()); } - /** - * @group legacy - */ - public function testLegacyGetTypeGuesser() - { - $container = $this->createContainerMock(); - $container - ->expects($this->once()) - ->method('get') - ->with('foo') - ->willReturn($this->getMockBuilder(FormTypeGuesserInterface::class)->getMock()); - $extension = new DependencyInjectionExtension($container, array(), array(), array('foo')); - - $this->assertInstanceOf(FormTypeGuesserChain::class, $extension->getTypeGuesser()); - } - - /** - * @group legacy - */ - public function testLegacyGetTypeGuesserReturnsNullWhenNoTypeGuessersHaveBeenConfigured() - { - $container = $this->createContainerMock(); - $extension = new DependencyInjectionExtension($container, array(), array(), array()); - - $this->assertNull($extension->getTypeGuesser()); - } - private function createContainerMock() { return $this->getMockBuilder('Psr\Container\ContainerInterface') diff --git a/src/Symfony/Component/Form/Tests/SimpleFormTest.php b/src/Symfony/Component/Form/Tests/SimpleFormTest.php index a938a176ccd92..36caf2d15b9f8 100644 --- a/src/Symfony/Component/Form/Tests/SimpleFormTest.php +++ b/src/Symfony/Component/Form/Tests/SimpleFormTest.php @@ -313,15 +313,6 @@ public function testValidIfSubmittedAndDisabled() $this->assertTrue($form->isValid()); } - /** - * @group legacy - * @expectedDeprecation Call Form::isValid() with an unsubmitted form %s. - */ - public function testNotValidIfNotSubmitted() - { - $this->assertFalse($this->form->isValid()); - } - public function testNotValidIfErrors() { $form = $this->getBuilder()->getForm(); diff --git a/src/Symfony/Component/HttpKernel/DataCollector/DataCollector.php b/src/Symfony/Component/HttpKernel/DataCollector/DataCollector.php index 77c72f9562e75..a49686694daa8 100644 --- a/src/Symfony/Component/HttpKernel/DataCollector/DataCollector.php +++ b/src/Symfony/Component/HttpKernel/DataCollector/DataCollector.php @@ -57,7 +57,7 @@ protected function cloneVar($var) { if (null === self::$cloner) { if (!class_exists(ClassStub::class)) { - throw new \LogicException(sprintf('The VarDumper component is needed for the %s() method. Install symfony/var-dumper version 3.2 or above.', __METHOD__)); + throw new \LogicException(sprintf('The VarDumper component is needed for the %s() method. Install symfony/var-dumper version 3.4 or above.', __METHOD__)); } self::$cloner = new VarCloner(); From 6c87863a0e0896e360189b270a1964abe49c1c25 Mon Sep 17 00:00:00 2001 From: Maxime Steinhausser Date: Tue, 30 May 2017 19:05:33 +0200 Subject: [PATCH 0134/1099] [Profiler] Never wrap in code excerpts --- .../TwigBundle/Resources/views/exception.css.twig | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/Symfony/Bundle/TwigBundle/Resources/views/exception.css.twig b/src/Symfony/Bundle/TwigBundle/Resources/views/exception.css.twig index 1c8c76e78db4a..cb455274eecf9 100644 --- a/src/Symfony/Bundle/TwigBundle/Resources/views/exception.css.twig +++ b/src/Symfony/Bundle/TwigBundle/Resources/views/exception.css.twig @@ -95,7 +95,7 @@ header .container { display: flex; justify-content: space-between; } .trace-head .icon svg { height: 24px; width: 24px; } .trace-message { font-size: 14px; font-weight: normal; margin: .5em 0 0; } - +.trace-details { table-layout: fixed; } .trace-line { position: relative; padding-left: 36px; } .trace-line.sf-toggle:hover { background: #F5F5F5; } .trace-line a { color: #222; } @@ -108,12 +108,12 @@ header .container { display: flex; justify-content: space-between; } .trace-method { color: #B0413E; color: #222; font-weight: bold; color: #B0413E; } .trace-arguments { color: #222; color: #999; font-weight: normal; color: #795da3; color: #777; padding-left: 2px; } -.trace-code { background: #FFF; font-size: 12px; margin: 10px 0 2px; padding: 10px; } -.trace-code ol { margin: 0; } -.trace-code li { color: #969896; margin: 0; padding-left: 10px; } -.trace-code li + li { margin-top: 10px; } -.trace-code li.selected { background: #F8EEC7; padding: 3px 0 3px 10px; } -.trace-code li code { color: #222; } +.trace-code { background: #FFF; font-size: 12px; margin: 10px 0 2px; padding: 10px; overflow-x: auto; } +.trace-code ol { margin: 0; float: left; } +.trace-code li { color: #969896; margin: 0; padding-left: 10px; float: left; width: 100%; } +.trace-code li + li { margin-top: 5px; } +.trace-code li.selected { background: #F8EEC7; padding: 3px 0 3px 10px; margin-top: 2px; } +.trace-code li code { color: #222; white-space: nowrap; } .trace-as-text .stacktrace { line-height: 1.8; margin: 0 0 15px; white-space: pre-wrap; } From ff055ef7f377f524288a491255a33da00fbc15cc Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Sat, 3 Jun 2017 12:01:46 +0200 Subject: [PATCH 0135/1099] mitigate BC break with empty trusted_proxies --- .../DependencyInjection/Configuration.php | 6 +++- .../DependencyInjection/ConfigurationTest.php | 32 +++++++++++++++++++ 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php index 87d722b91e4d6..2ff614135983f 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php @@ -67,7 +67,11 @@ public function getConfigTreeBuilder() ->end() ->arrayNode('trusted_proxies') // @deprecated in version 3.3, to be removed in 4.0 ->beforeNormalization() - ->always() + ->ifTrue(function ($v) { return empty($v); }) + ->then(function () { @trigger_error('The "framework.trusted_proxies" configuration key has been removed in Symfony 3.3. Use the Request::setTrustedProxies() method in your front controller instead.', E_USER_DEPRECATED); }) + ->end() + ->beforeNormalization() + ->ifTrue(function ($v) { return !empty($v); }) ->thenInvalid('The "framework.trusted_proxies" configuration key has been removed in Symfony 3.3. Use the Request::setTrustedProxies() method in your front controller instead.') ->end() ->end() diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/ConfigurationTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/ConfigurationTest.php index 353e959c68ebf..96835c7be3f86 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/ConfigurationTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/ConfigurationTest.php @@ -43,6 +43,38 @@ public function testDoNoDuplicateDefaultFormResources() $this->assertEquals(array('FrameworkBundle:Form'), $config['templating']['form']['resources']); } + /** + * @group legacy + * @expectedDeprecation The "framework.trusted_proxies" configuration key has been removed in Symfony 3.3. Use the Request::setTrustedProxies() method in your front controller instead. + */ + public function testTrustedProxiesSetToNullIsDeprecated() + { + $processor = new Processor(); + $configuration = new Configuration(true); + $processor->processConfiguration($configuration, array(array('trusted_proxies' => null))); + } + + /** + * @group legacy + * @expectedDeprecation The "framework.trusted_proxies" configuration key has been removed in Symfony 3.3. Use the Request::setTrustedProxies() method in your front controller instead. + */ + public function testTrustedProxiesSetToEmptyArrayIsDeprecated() + { + $processor = new Processor(); + $configuration = new Configuration(true); + $processor->processConfiguration($configuration, array(array('trusted_proxies' => array()))); + } + + /** + * @expectedException \InvalidArgumentException + */ + public function testTrustedProxiesSetToNonEmptyArrayIsInvalid() + { + $processor = new Processor(); + $configuration = new Configuration(true); + $processor->processConfiguration($configuration, array(array('trusted_proxies' => array('127.0.0.1')))); + } + public function testAssetsCanBeEnabled() { $processor = new Processor(); From 9de898d69f755fe738839de087c20e3e547ca68e Mon Sep 17 00:00:00 2001 From: Maxime Steinhausser Date: Sat, 3 Jun 2017 13:10:54 +0200 Subject: [PATCH 0136/1099] [Form][Profiler] Fixes form collector triggering deprecations --- .../Resources/views/Collector/form.html.twig | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/form.html.twig b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/form.html.twig index 2f8b83049d158..02b77319ac249 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/form.html.twig +++ b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/form.html.twig @@ -525,7 +525,7 @@ Model Format {% if data.default_data.model is defined %} - {{ profiler_dump(data.default_data.model) }} + {{ profiler_dump(data.default_data.seek('model')) }} {% else %} same as normalized format {% endif %} @@ -533,13 +533,13 @@ Normalized Format - {{ profiler_dump(data.default_data.norm) }} + {{ profiler_dump(data.default_data.seek('norm')) }} View Format {% if data.default_data.view is defined %} - {{ profiler_dump(data.default_data.view) }} + {{ profiler_dump(data.default_data.seek('view')) }} {% else %} same as normalized format {% endif %} @@ -571,7 +571,7 @@ View Format {% if data.submitted_data.view is defined %} - {{ profiler_dump(data.submitted_data.view) }} + {{ profiler_dump(data.submitted_data.seek('view')) }} {% else %} same as normalized format {% endif %} @@ -579,13 +579,13 @@ Normalized Format - {{ profiler_dump(data.submitted_data.norm) }} + {{ profiler_dump(data.submitted_data.seek('norm')) }} Model Format {% if data.submitted_data.model is defined %} - {{ profiler_dump(data.submitted_data.model) }} + {{ profiler_dump(data.submitted_data.seek('model')) }} {% else %} same as normalized format {% endif %} @@ -630,7 +630,7 @@ {% if resolved_option_value == option_value %} same as passed value {% else %} - {{ profiler_dump(data.resolved_options[option]) }} + {{ profiler_dump(data.resolved_options.seek(option)) }} {% endif %} From eda1888f71c58c2f097c5c5cf00282207737078b Mon Sep 17 00:00:00 2001 From: Lars Strojny Date: Fri, 2 Jun 2017 19:36:18 +0200 Subject: [PATCH 0137/1099] Consistent error handling in remember me services --- .../Http/Firewall/RememberMeListener.php | 2 +- .../RememberMe/AbstractRememberMeServices.php | 32 ++++++++++++------- ...PersistentTokenBasedRememberMeServices.php | 1 + .../RememberMeServicesInterface.php | 5 +-- .../Tests/Firewall/RememberMeListenerTest.php | 6 ++-- 5 files changed, 30 insertions(+), 16 deletions(-) diff --git a/src/Symfony/Component/Security/Http/Firewall/RememberMeListener.php b/src/Symfony/Component/Security/Http/Firewall/RememberMeListener.php index bc859f9f5dce4..e075b2f419479 100644 --- a/src/Symfony/Component/Security/Http/Firewall/RememberMeListener.php +++ b/src/Symfony/Component/Security/Http/Firewall/RememberMeListener.php @@ -100,7 +100,7 @@ public function handle(GetResponseEvent $event) ); } - $this->rememberMeServices->loginFail($request); + $this->rememberMeServices->loginFail($request, $e); if (!$this->catchExceptions) { throw $e; diff --git a/src/Symfony/Component/Security/Http/RememberMe/AbstractRememberMeServices.php b/src/Symfony/Component/Security/Http/RememberMe/AbstractRememberMeServices.php index a462b5818b571..2a6f115307528 100644 --- a/src/Symfony/Component/Security/Http/RememberMe/AbstractRememberMeServices.php +++ b/src/Symfony/Component/Security/Http/RememberMe/AbstractRememberMeServices.php @@ -106,7 +106,7 @@ public function getSecret() final public function autoLogin(Request $request) { if (null === $cookie = $request->cookies->get($this->options['name'])) { - return; + return null; } if (null !== $this->logger) { @@ -128,24 +128,32 @@ final public function autoLogin(Request $request) return new RememberMeToken($user, $this->providerKey, $this->secret); } catch (CookieTheftException $e) { - $this->cancelCookie($request); + $this->loginFail($request, $e); throw $e; } catch (UsernameNotFoundException $e) { if (null !== $this->logger) { - $this->logger->info('User for remember-me cookie not found.'); + $this->logger->info('User for remember-me cookie not found.', array('exception' => $e)); } + + $this->loginFail($request, $e); } catch (UnsupportedUserException $e) { if (null !== $this->logger) { - $this->logger->warning('User class for remember-me cookie not supported.'); + $this->logger->warning('User class for remember-me cookie not supported.', array('exception' => $e)); } + + $this->loginFail($request, $e); } catch (AuthenticationException $e) { if (null !== $this->logger) { $this->logger->debug('Remember-Me authentication failed.', array('exception' => $e)); } - } - $this->cancelCookie($request); + $this->loginFail($request, $e); + } catch (\Exception $e) { + $this->loginFail($request, $e); + + throw $e; + } } /** @@ -164,12 +172,13 @@ public function logout(Request $request, Response $response, TokenInterface $tok * Implementation for RememberMeServicesInterface. Deletes the cookie when * an attempted authentication fails. * - * @param Request $request + * @param Request $request + * @param \Exception|null $exception */ - final public function loginFail(Request $request) + final public function loginFail(Request $request, \Exception $exception = null) { $this->cancelCookie($request); - $this->onLoginFail($request); + $this->onLoginFail($request, $exception); } /** @@ -226,9 +235,10 @@ final public function loginSuccess(Request $request, Response $response, TokenIn abstract protected function processAutoLoginCookie(array $cookieParts, Request $request); /** - * @param Request $request + * @param Request $request + * @param \Exception|null $exception */ - protected function onLoginFail(Request $request) + protected function onLoginFail(Request $request, \Exception $exception = null) { } diff --git a/src/Symfony/Component/Security/Http/RememberMe/PersistentTokenBasedRememberMeServices.php b/src/Symfony/Component/Security/Http/RememberMe/PersistentTokenBasedRememberMeServices.php index edfa208c40dc0..775aa39fdafeb 100644 --- a/src/Symfony/Component/Security/Http/RememberMe/PersistentTokenBasedRememberMeServices.php +++ b/src/Symfony/Component/Security/Http/RememberMe/PersistentTokenBasedRememberMeServices.php @@ -29,6 +29,7 @@ */ class PersistentTokenBasedRememberMeServices extends AbstractRememberMeServices { + /** @var TokenProviderInterface */ private $tokenProvider; /** diff --git a/src/Symfony/Component/Security/Http/RememberMe/RememberMeServicesInterface.php b/src/Symfony/Component/Security/Http/RememberMe/RememberMeServicesInterface.php index 5750a8c9d4804..80ea2fd4b0ad4 100644 --- a/src/Symfony/Component/Security/Http/RememberMe/RememberMeServicesInterface.php +++ b/src/Symfony/Component/Security/Http/RememberMe/RememberMeServicesInterface.php @@ -60,9 +60,10 @@ public function autoLogin(Request $request); * * This method needs to take care of invalidating the cookie. * - * @param Request $request + * @param Request $request + * @param \Exception|null $exception */ - public function loginFail(Request $request); + public function loginFail(Request $request, \Exception $exception = null); /** * Called whenever an interactive authentication attempt is successful diff --git a/src/Symfony/Component/Security/Http/Tests/Firewall/RememberMeListenerTest.php b/src/Symfony/Component/Security/Http/Tests/Firewall/RememberMeListenerTest.php index 2249dcbd2059d..932c5edc9623f 100644 --- a/src/Symfony/Component/Security/Http/Tests/Firewall/RememberMeListenerTest.php +++ b/src/Symfony/Component/Security/Http/Tests/Firewall/RememberMeListenerTest.php @@ -66,6 +66,8 @@ public function testOnCoreSecurityDoesNothingWhenNoCookieIsSet() public function testOnCoreSecurityIgnoresAuthenticationExceptionThrownByAuthenticationManagerImplementation() { list($listener, $tokenStorage, $service, $manager) = $this->getListener(); + $request = new Request(); + $exception = new AuthenticationException('Authentication failed.'); $tokenStorage ->expects($this->once()) @@ -82,9 +84,9 @@ public function testOnCoreSecurityIgnoresAuthenticationExceptionThrownByAuthenti $service ->expects($this->once()) ->method('loginFail') + ->with($request, $exception) ; - $exception = new AuthenticationException('Authentication failed.'); $manager ->expects($this->once()) ->method('authenticate') @@ -95,7 +97,7 @@ public function testOnCoreSecurityIgnoresAuthenticationExceptionThrownByAuthenti $event ->expects($this->once()) ->method('getRequest') - ->will($this->returnValue(new Request())) + ->will($this->returnValue($request)) ; $listener->handle($event); From 6dbdb1b750509264dd8061231f2491cb9ad7cd9a Mon Sep 17 00:00:00 2001 From: Oleg Voronkovich Date: Tue, 30 May 2017 20:42:15 +0300 Subject: [PATCH 0138/1099] [DependencyInjection] Use more clear message when unused environment variables detected --- .../Component/DependencyInjection/Dumper/PhpDumper.php | 2 +- .../DependencyInjection/Exception/EnvParameterException.php | 4 ++-- .../DependencyInjection/Tests/Dumper/PhpDumperTest.php | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php index 4431418d85848..dd514962ea47c 100644 --- a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php +++ b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php @@ -166,7 +166,7 @@ public function dump(array $options = array()) } } if ($unusedEnvs) { - throw new EnvParameterException($unusedEnvs); + throw new EnvParameterException($unusedEnvs, null, 'Environment variables "%s" are never used. Please, check your container\'s configuration.'); } return $code; diff --git a/src/Symfony/Component/DependencyInjection/Exception/EnvParameterException.php b/src/Symfony/Component/DependencyInjection/Exception/EnvParameterException.php index 44dbab45b6284..3839a4633be40 100644 --- a/src/Symfony/Component/DependencyInjection/Exception/EnvParameterException.php +++ b/src/Symfony/Component/DependencyInjection/Exception/EnvParameterException.php @@ -18,8 +18,8 @@ */ class EnvParameterException extends InvalidArgumentException { - public function __construct(array $usedEnvs, \Exception $previous = null) + public function __construct(array $envs, \Exception $previous = null, $message = 'Incompatible use of dynamic environment variables "%s" found in parameters.') { - parent::__construct(sprintf('Incompatible use of dynamic environment variables "%s" found in parameters.', implode('", "', $usedEnvs)), 0, $previous); + parent::__construct(sprintf($message, implode('", "', $envs)), 0, $previous); } } diff --git a/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php b/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php index 2ad701aa6d327..ee81219ef01d0 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php @@ -302,7 +302,7 @@ public function testEnvParameter() /** * @expectedException \Symfony\Component\DependencyInjection\Exception\EnvParameterException - * @expectedExceptionMessage Incompatible use of dynamic environment variables "FOO" found in parameters. + * @expectedExceptionMessage Environment variables "FOO" are never used. Please, check your container's configuration. */ public function testUnusedEnvParameter() { From 37afeeae7af881d35ea80b2baed55d812cc2eb02 Mon Sep 17 00:00:00 2001 From: Adam Szaraniec Date: Fri, 2 Jun 2017 20:31:09 +0400 Subject: [PATCH 0139/1099] Support for parsing PHP constants in yaml loader --- src/Symfony/Component/Validator/CHANGELOG.md | 1 + .../Validator/Mapping/Loader/YamlFileLoader.php | 2 +- .../Tests/Mapping/Loader/YamlFileLoaderTest.php | 13 +++++++++++++ .../Tests/Mapping/Loader/mapping-with-constants.yml | 8 ++++++++ 4 files changed, 23 insertions(+), 1 deletion(-) create mode 100644 src/Symfony/Component/Validator/Tests/Mapping/Loader/mapping-with-constants.yml diff --git a/src/Symfony/Component/Validator/CHANGELOG.md b/src/Symfony/Component/Validator/CHANGELOG.md index b35a4824104cc..8940a8230d4a1 100644 --- a/src/Symfony/Component/Validator/CHANGELOG.md +++ b/src/Symfony/Component/Validator/CHANGELOG.md @@ -18,6 +18,7 @@ CHANGELOG ----- * deprecated `Tests\Constraints\AbstractContraintValidatorTest` in favor of `Test\ConstraintValidatorTestCase` + * added support for PHP constants in YAML configuration files 3.1.0 ----- diff --git a/src/Symfony/Component/Validator/Mapping/Loader/YamlFileLoader.php b/src/Symfony/Component/Validator/Mapping/Loader/YamlFileLoader.php index f2e664750a485..f1727d370498d 100644 --- a/src/Symfony/Component/Validator/Mapping/Loader/YamlFileLoader.php +++ b/src/Symfony/Component/Validator/Mapping/Loader/YamlFileLoader.php @@ -116,7 +116,7 @@ protected function parseNodes(array $nodes) private function parseFile($path) { try { - $classes = $this->yamlParser->parse(file_get_contents($path), Yaml::PARSE_KEYS_AS_STRINGS); + $classes = $this->yamlParser->parse(file_get_contents($path), Yaml::PARSE_KEYS_AS_STRINGS | Yaml::PARSE_CONSTANT); } catch (ParseException $e) { throw new \InvalidArgumentException(sprintf('The file "%s" does not contain valid YAML.', $path), 0, $e); } diff --git a/src/Symfony/Component/Validator/Tests/Mapping/Loader/YamlFileLoaderTest.php b/src/Symfony/Component/Validator/Tests/Mapping/Loader/YamlFileLoaderTest.php index 671296e90ca0f..38861b377f2ce 100644 --- a/src/Symfony/Component/Validator/Tests/Mapping/Loader/YamlFileLoaderTest.php +++ b/src/Symfony/Component/Validator/Tests/Mapping/Loader/YamlFileLoaderTest.php @@ -124,6 +124,19 @@ public function testLoadClassMetadata() $this->assertEquals($expected, $metadata); } + public function testLoadClassMetadataWithConstants() + { + $loader = new YamlFileLoader(__DIR__.'/mapping-with-constants.yml'); + $metadata = new ClassMetadata('Symfony\Component\Validator\Tests\Fixtures\Entity'); + + $loader->loadClassMetadata($metadata); + + $expected = new ClassMetadata('Symfony\Component\Validator\Tests\Fixtures\Entity'); + $expected->addPropertyConstraint('firstName', new Range(array('max' => PHP_INT_MAX))); + + $this->assertEquals($expected, $metadata); + } + public function testLoadGroupSequenceProvider() { $loader = new YamlFileLoader(__DIR__.'/constraint-mapping.yml'); diff --git a/src/Symfony/Component/Validator/Tests/Mapping/Loader/mapping-with-constants.yml b/src/Symfony/Component/Validator/Tests/Mapping/Loader/mapping-with-constants.yml new file mode 100644 index 0000000000000..9352fe521e215 --- /dev/null +++ b/src/Symfony/Component/Validator/Tests/Mapping/Loader/mapping-with-constants.yml @@ -0,0 +1,8 @@ +namespaces: + custom: Symfony\Component\Validator\Tests\Fixtures\ + +Symfony\Component\Validator\Tests\Fixtures\Entity: + properties: + firstName: + - Range: + max: !php/const:PHP_INT_MAX From 9fe5102f469ad4527f08f54e72d90c209c2063bd Mon Sep 17 00:00:00 2001 From: Maxime Steinhausser Date: Sat, 3 Jun 2017 23:25:50 +0200 Subject: [PATCH 0140/1099] [WebProfilerBundle] Remove WebProfilerExtension::dumpValue() --- .../Bundle/WebProfilerBundle/CHANGELOG.md | 5 ++++ .../Twig/WebProfilerExtension.php | 26 +------------------ 2 files changed, 6 insertions(+), 25 deletions(-) diff --git a/src/Symfony/Bundle/WebProfilerBundle/CHANGELOG.md b/src/Symfony/Bundle/WebProfilerBundle/CHANGELOG.md index 64102cc761c34..9c1a66132925f 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/CHANGELOG.md +++ b/src/Symfony/Bundle/WebProfilerBundle/CHANGELOG.md @@ -1,6 +1,11 @@ CHANGELOG ========= +4.0.0 +----- + + * removed the `WebProfilerExtension::dumpValue()` method + 3.1.0 ----- diff --git a/src/Symfony/Bundle/WebProfilerBundle/Twig/WebProfilerExtension.php b/src/Symfony/Bundle/WebProfilerBundle/Twig/WebProfilerExtension.php index f552e5f206cfa..c714ff0642472 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Twig/WebProfilerExtension.php +++ b/src/Symfony/Bundle/WebProfilerBundle/Twig/WebProfilerExtension.php @@ -11,7 +11,6 @@ namespace Symfony\Bundle\WebProfilerBundle\Twig; -use Symfony\Component\HttpKernel\DataCollector\Util\ValueExporter; use Symfony\Component\VarDumper\Cloner\Data; use Symfony\Component\VarDumper\Dumper\HtmlDumper; use Twig\Environment; @@ -26,11 +25,6 @@ */ class WebProfilerExtension extends ProfilerExtension { - /** - * @var ValueExporter - */ - private $valueExporter; - /** * @var HtmlDumper */ @@ -69,12 +63,8 @@ public function leave(Profile $profile) */ public function getFunctions() { - $profilerDump = function (Environment $env, $value, $maxDepth = 0) { - return $value instanceof Data ? $this->dumpData($env, $value, $maxDepth) : twig_escape_filter($env, $this->dumpValue($value)); - }; - return array( - new TwigFunction('profiler_dump', $profilerDump, array('is_safe' => array('html'), 'needs_environment' => true)), + new TwigFunction('profiler_dump', array($this, 'dumpData'), array('is_safe' => array('html'), 'needs_environment' => true)), new TwigFunction('profiler_dump_log', array($this, 'dumpLog'), array('is_safe' => array('html'), 'needs_environment' => true)), ); } @@ -111,20 +101,6 @@ public function dumpLog(Environment $env, $message, Data $context = null) return ''.strtr($message, $replacements).''; } - /** - * @deprecated since 3.2, to be removed in 4.0. Use the dumpData() method instead. - */ - public function dumpValue($value) - { - @trigger_error(sprintf('The %s() method is deprecated since version 3.2 and will be removed in 4.0. Use the dumpData() method instead.', __METHOD__), E_USER_DEPRECATED); - - if (null === $this->valueExporter) { - $this->valueExporter = new ValueExporter(); - } - - return $this->valueExporter->exportValue($value); - } - /** * {@inheritdoc} */ From a4caa16659cd1b22b6b17c4ba5562104f8fd6a8c Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Sun, 4 Jun 2017 10:04:58 +0200 Subject: [PATCH 0141/1099] fix used class name in deprecation message --- .../Bundle/TwigBundle/CacheWarmer/TemplateCacheWarmer.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Bundle/TwigBundle/CacheWarmer/TemplateCacheWarmer.php b/src/Symfony/Bundle/TwigBundle/CacheWarmer/TemplateCacheWarmer.php index a749ce57ac1ce..40673f4913e9a 100644 --- a/src/Symfony/Bundle/TwigBundle/CacheWarmer/TemplateCacheWarmer.php +++ b/src/Symfony/Bundle/TwigBundle/CacheWarmer/TemplateCacheWarmer.php @@ -41,7 +41,7 @@ public function __construct($container, \Traversable $iterator) $this->container = $container; } elseif ($container instanceof Environment) { $this->twig = $container; - @trigger_error(sprintf('Using a "%s" as first argument of %s is deprecated since version 3.4 and will be unsupported in version 4.0. Use a %s instead.', Environment::class, __CLASS__, Container::class), E_USER_DEPRECATED); + @trigger_error(sprintf('Using a "%s" as first argument of %s is deprecated since version 3.4 and will be unsupported in version 4.0. Use a %s instead.', Environment::class, __CLASS__, ContainerInterface::class), E_USER_DEPRECATED); } else { throw new \InvalidArgumentException(sprintf('%s only accepts instance of Psr\Container\ContainerInterface as first argument.', __CLASS__)); } From 5b819ebfee02bf295b3c76d4d879a96c5a26cbab Mon Sep 17 00:00:00 2001 From: Maxime Steinhausser Date: Sun, 4 Jun 2017 20:05:07 +0200 Subject: [PATCH 0142/1099] Remove closure-proxy leftovers --- .../FrameworkBundle/Console/Descriptor/Descriptor.php | 7 ------- .../FrameworkBundle/Console/Descriptor/JsonDescriptor.php | 2 +- .../Console/Descriptor/MarkdownDescriptor.php | 3 +-- .../FrameworkBundle/Console/Descriptor/TextDescriptor.php | 8 +------- .../FrameworkBundle/Console/Descriptor/XmlDescriptor.php | 2 +- .../EventDispatcher/ContainerAwareEventDispatcher.php | 6 +++--- 6 files changed, 7 insertions(+), 21 deletions(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/Descriptor.php b/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/Descriptor.php index acaec0bf5dbab..206b01e4f056e 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/Descriptor.php +++ b/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/Descriptor.php @@ -307,11 +307,4 @@ protected function sortServiceIds(array $serviceIds) return $serviceIds; } - - protected function formatClosure(\Closure $closure) - { - $r = new \ReflectionFunction($closure); - - return 'closure'; - } } diff --git a/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/JsonDescriptor.php b/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/JsonDescriptor.php index d49c57adfec2e..6755369c06252 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/JsonDescriptor.php +++ b/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/JsonDescriptor.php @@ -370,7 +370,7 @@ private function getCallableData($callable, array $options = array()) } if ($callable instanceof \Closure) { - $data['type'] = $this->formatClosure($callable); + $data['type'] = 'closure'; return $data; } diff --git a/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/MarkdownDescriptor.php b/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/MarkdownDescriptor.php index 59e382d3a9cad..81c6c4a69a2f6 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/MarkdownDescriptor.php +++ b/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/MarkdownDescriptor.php @@ -349,8 +349,7 @@ protected function describeCallable($callable, array $options = array()) } if ($callable instanceof \Closure) { - $formatted = $this->formatClosure($callable); - $string .= "\n- Type: `$formatted`"; + $string .= "\n- Type: `closure`"; return $this->write($string."\n"); } diff --git a/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/TextDescriptor.php b/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/TextDescriptor.php index 06a404080d32d..861f3c21c4dd5 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/TextDescriptor.php +++ b/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/TextDescriptor.php @@ -474,13 +474,7 @@ private function formatCallable($callable) } if ($callable instanceof \Closure) { - $formatted = $this->formatClosure($callable); - - if ('closure' === $formatted) { - return '\Closure()'; - } - - return $formatted.'()'; + return '\Closure()'; } if (method_exists($callable, '__invoke')) { diff --git a/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/XmlDescriptor.php b/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/XmlDescriptor.php index f1770d8c3c453..5baa8de11c730 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/XmlDescriptor.php +++ b/src/Symfony/Bundle/FrameworkBundle/Console/Descriptor/XmlDescriptor.php @@ -593,7 +593,7 @@ private function getCallableDocument($callable) } if ($callable instanceof \Closure) { - $callableXML->setAttribute('type', $this->formatClosure($callable)); + $callableXML->setAttribute('type', 'closure'); return $dom; } diff --git a/src/Symfony/Component/EventDispatcher/ContainerAwareEventDispatcher.php b/src/Symfony/Component/EventDispatcher/ContainerAwareEventDispatcher.php index a57dd86eaf7cb..fc7b30f9ccc65 100644 --- a/src/Symfony/Component/EventDispatcher/ContainerAwareEventDispatcher.php +++ b/src/Symfony/Component/EventDispatcher/ContainerAwareEventDispatcher.php @@ -21,7 +21,7 @@ * @author Bernhard Schussek * @author Jordan Alliot * - * @deprecated since 3.3, to be removed in 4.0. Use EventDispatcher with closure-proxy injection instead. + * @deprecated since 3.3, to be removed in 4.0. Use EventDispatcher with closure factories instead. */ class ContainerAwareEventDispatcher extends EventDispatcher { @@ -60,7 +60,7 @@ public function __construct(ContainerInterface $container) $class = get_parent_class($class); } if (__CLASS__ !== $class) { - @trigger_error(sprintf('The %s class is deprecated since version 3.3 and will be removed in 4.0. Use EventDispatcher with closure-proxy injection instead.', __CLASS__), E_USER_DEPRECATED); + @trigger_error(sprintf('The %s class is deprecated since version 3.3 and will be removed in 4.0. Use EventDispatcher with closure factories instead.', __CLASS__), E_USER_DEPRECATED); } } @@ -78,7 +78,7 @@ public function __construct(ContainerInterface $container) */ public function addListenerService($eventName, $callback, $priority = 0) { - @trigger_error(sprintf('The %s class is deprecated since version 3.3 and will be removed in 4.0. Use EventDispatcher with closure-proxy injection instead.', __CLASS__), E_USER_DEPRECATED); + @trigger_error(sprintf('The %s class is deprecated since version 3.3 and will be removed in 4.0. Use EventDispatcher with closure factories instead.', __CLASS__), E_USER_DEPRECATED); if (!is_array($callback) || 2 !== count($callback)) { throw new \InvalidArgumentException('Expected an array("service", "method") argument'); From 405f64bb0143516475d087d0ae23c7f2fcd9c76f Mon Sep 17 00:00:00 2001 From: Martin Kirilov Date: Mon, 5 Jun 2017 03:15:00 +0300 Subject: [PATCH 0143/1099] [Cache] MemcachedAdapter not working with TagAwareAdapter It seems that when MemcachedAdapter is used with TagAwareAdapter, it fails to fetch items, even though I thoroughly tested fetching items with the exact same keys under the same namespace. Turns out the issue lies in `const TAGS_PREFIX = "\0tags\0";` for unknown to me reasons. Hardcoding that to '__tags__' in my project did the trick and I've been using it for a couple of days now and it seems fine. The reason I had to completely copy/paste this file in my local project is self:: instead of static:: usage. I am not sure whether that is a mistake or is done on purpose, but in order to have this work for me I need to be able to override that constant. Going with static:: seems like a good solution to me, then I can set whatever prefix I need for the tags. --- src/Symfony/Component/Cache/Adapter/AbstractAdapter.php | 3 +++ src/Symfony/Component/Cache/Adapter/TagAwareAdapter.php | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/Cache/Adapter/AbstractAdapter.php b/src/Symfony/Component/Cache/Adapter/AbstractAdapter.php index 4a788963ea74b..b5f6a61b56b03 100644 --- a/src/Symfony/Component/Cache/Adapter/AbstractAdapter.php +++ b/src/Symfony/Component/Cache/Adapter/AbstractAdapter.php @@ -426,6 +426,9 @@ private function generateItems($items, &$keys) try { foreach ($items as $id => $value) { + if (!isset($keys[$id])) { + $id = key($keys); + } $key = $keys[$id]; unset($keys[$id]); yield $key => $f($key, $value, true); diff --git a/src/Symfony/Component/Cache/Adapter/TagAwareAdapter.php b/src/Symfony/Component/Cache/Adapter/TagAwareAdapter.php index b8c4a08021b70..03ed203bec9cc 100644 --- a/src/Symfony/Component/Cache/Adapter/TagAwareAdapter.php +++ b/src/Symfony/Component/Cache/Adapter/TagAwareAdapter.php @@ -261,7 +261,7 @@ private function generateItems($items, array $tagKeys) foreach ($items as $key => $item) { if (!$tagKeys) { - yield $key => isset($invalidKeys[self::TAGS_PREFIX.$key]) ? $f($key, null, $item) : $item; + yield $key => isset($invalidKeys[static::TAGS_PREFIX.$key]) ? $f($key, null, $item) : $item; continue; } if (!isset($tagKeys[$key])) { @@ -287,7 +287,7 @@ private function generateItems($items, array $tagKeys) $itemTags = $tagVersions = $tagKeys = null; foreach ($bufferedItems as $key => $item) { - yield $key => isset($invalidKeys[self::TAGS_PREFIX.$key]) ? $f($key, null, $item) : $item; + yield $key => isset($invalidKeys[static::TAGS_PREFIX.$key]) ? $f($key, null, $item) : $item; } $bufferedItems = null; } From 213233305903d659b012acc2ae088a647e85ac4a Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Mon, 5 Jun 2017 14:57:44 +0200 Subject: [PATCH 0144/1099] [HttpFoundation][FrameworkBundle] Revert "trusted proxies" BC break --- .../Bundle/FrameworkBundle/CHANGELOG.md | 2 +- .../DependencyInjection/Configuration.php | 36 ++++++++-- .../FrameworkExtension.php | 3 + .../DependencyInjection/ConfigurationTest.php | 72 ++++++++++++++++++- .../Component/HttpFoundation/CHANGELOG.md | 2 +- .../Component/HttpFoundation/Request.php | 30 ++++---- .../HttpFoundation/Tests/RequestTest.php | 2 +- 7 files changed, 123 insertions(+), 24 deletions(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md b/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md index d25f4547d3123..b760d28997611 100644 --- a/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md +++ b/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md @@ -7,7 +7,7 @@ CHANGELOG * Not defining the `type` option of the `framework.workflows.*` configuration entries is deprecated. The default value will be `state_machine` in Symfony 4.0. * Deprecated the `CompilerDebugDumpPass` class - * [BC BREAK] Removed the "framework.trusted_proxies" configuration option and the corresponding "kernel.trusted_proxies" parameter + * Deprecated the "framework.trusted_proxies" configuration option and the corresponding "kernel.trusted_proxies" parameter * Added a new new version strategy option called json_manifest_path that allows you to use the `JsonManifestVersionStrategy`. * Added `Symfony\Bundle\FrameworkBundle\Controller\AbstractController`. It provides diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php index 2ff614135983f..611bfad97db82 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php @@ -65,14 +65,38 @@ public function getConfigTreeBuilder() ->info("Set true to enable support for the '_method' request parameter to determine the intended HTTP method on POST requests. Note: When using the HttpCache, you need to call the method in your front controller instead") ->defaultTrue() ->end() - ->arrayNode('trusted_proxies') // @deprecated in version 3.3, to be removed in 4.0 + ->arrayNode('trusted_proxies') ->beforeNormalization() - ->ifTrue(function ($v) { return empty($v); }) - ->then(function () { @trigger_error('The "framework.trusted_proxies" configuration key has been removed in Symfony 3.3. Use the Request::setTrustedProxies() method in your front controller instead.', E_USER_DEPRECATED); }) + ->ifTrue(function ($v) { + @trigger_error('The "framework.trusted_proxies" configuration key has been deprecated in Symfony 3.3. Use the Request::setTrustedProxies() method in your front controller instead.', E_USER_DEPRECATED); + + return !is_array($v) && null !== $v; + }) + ->then(function ($v) { return is_bool($v) ? array() : preg_split('/\s*,\s*/', $v); }) ->end() - ->beforeNormalization() - ->ifTrue(function ($v) { return !empty($v); }) - ->thenInvalid('The "framework.trusted_proxies" configuration key has been removed in Symfony 3.3. Use the Request::setTrustedProxies() method in your front controller instead.') + ->prototype('scalar') + ->validate() + ->ifTrue(function ($v) { + if (empty($v)) { + return false; + } + + if (false !== strpos($v, '/')) { + if ('0.0.0.0/0' === $v) { + return false; + } + + list($v, $mask) = explode('/', $v, 2); + + if (strcmp($mask, (int) $mask) || $mask < 1 || $mask > (false !== strpos($v, ':') ? 128 : 32)) { + return true; + } + } + + return !filter_var($v, FILTER_VALIDATE_IP); + }) + ->thenInvalid('Invalid proxy IP "%s"') + ->end() ->end() ->end() ->scalarNode('ide')->defaultNull()->end() diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php index 4e664f1fe888c..b607cdd2bf563 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php @@ -146,6 +146,9 @@ public function load(array $configs, ContainerBuilder $container) $container->setParameter('kernel.http_method_override', $config['http_method_override']); $container->setParameter('kernel.trusted_hosts', $config['trusted_hosts']); + if ($config['trusted_proxies']) { + $container->setParameter('kernel.trusted_proxies', $config['trusted_proxies']); + } $container->setParameter('kernel.default_locale', $config['default_locale']); if (!$container->hasParameter('debug.file_link_format')) { diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/ConfigurationTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/ConfigurationTest.php index 96835c7be3f86..0d2578db040af 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/ConfigurationTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/ConfigurationTest.php @@ -45,7 +45,7 @@ public function testDoNoDuplicateDefaultFormResources() /** * @group legacy - * @expectedDeprecation The "framework.trusted_proxies" configuration key has been removed in Symfony 3.3. Use the Request::setTrustedProxies() method in your front controller instead. + * @expectedDeprecation The "framework.trusted_proxies" configuration key has been deprecated in Symfony 3.3. Use the Request::setTrustedProxies() method in your front controller instead. */ public function testTrustedProxiesSetToNullIsDeprecated() { @@ -56,7 +56,7 @@ public function testTrustedProxiesSetToNullIsDeprecated() /** * @group legacy - * @expectedDeprecation The "framework.trusted_proxies" configuration key has been removed in Symfony 3.3. Use the Request::setTrustedProxies() method in your front controller instead. + * @expectedDeprecation The "framework.trusted_proxies" configuration key has been deprecated in Symfony 3.3. Use the Request::setTrustedProxies() method in your front controller instead. */ public function testTrustedProxiesSetToEmptyArrayIsDeprecated() { @@ -66,7 +66,8 @@ public function testTrustedProxiesSetToEmptyArrayIsDeprecated() } /** - * @expectedException \InvalidArgumentException + * @group legacy + * @expectedDeprecation The "framework.trusted_proxies" configuration key has been deprecated in Symfony 3.3. Use the Request::setTrustedProxies() method in your front controller instead. */ public function testTrustedProxiesSetToNonEmptyArrayIsInvalid() { @@ -75,6 +76,70 @@ public function testTrustedProxiesSetToNonEmptyArrayIsInvalid() $processor->processConfiguration($configuration, array(array('trusted_proxies' => array('127.0.0.1')))); } + /** + * @group legacy + * @dataProvider getTestValidTrustedProxiesData + */ + public function testValidTrustedProxies($trustedProxies, $processedProxies) + { + $processor = new Processor(); + $configuration = new Configuration(true); + $config = $processor->processConfiguration($configuration, array(array( + 'secret' => 's3cr3t', + 'trusted_proxies' => $trustedProxies, + ))); + + $this->assertEquals($processedProxies, $config['trusted_proxies']); + } + + public function getTestValidTrustedProxiesData() + { + return array( + array(array('127.0.0.1'), array('127.0.0.1')), + array(array('::1'), array('::1')), + array(array('127.0.0.1', '::1'), array('127.0.0.1', '::1')), + array(null, array()), + array(false, array()), + array(array(), array()), + array(array('10.0.0.0/8'), array('10.0.0.0/8')), + array(array('::ffff:0:0/96'), array('::ffff:0:0/96')), + array(array('0.0.0.0/0'), array('0.0.0.0/0')), + ); + } + + /** + * @group legacy + * @expectedException \Symfony\Component\Config\Definition\Exception\InvalidConfigurationException + */ + public function testInvalidTypeTrustedProxies() + { + $processor = new Processor(); + $configuration = new Configuration(true); + $processor->processConfiguration($configuration, array( + array( + 'secret' => 's3cr3t', + 'trusted_proxies' => 'Not an IP address', + ), + )); + } + + /** + * @group legacy + * @expectedException \Symfony\Component\Config\Definition\Exception\InvalidConfigurationException + */ + public function testInvalidValueTrustedProxies() + { + $processor = new Processor(); + $configuration = new Configuration(true); + + $processor->processConfiguration($configuration, array( + array( + 'secret' => 's3cr3t', + 'trusted_proxies' => array('Not an IP address'), + ), + )); + } + public function testAssetsCanBeEnabled() { $processor = new Processor(); @@ -156,6 +221,7 @@ protected static function getBundleDefaultConfig() { return array( 'http_method_override' => true, + 'trusted_proxies' => array(), 'ide' => null, 'default_locale' => 'en', 'csrf_protection' => array( diff --git a/src/Symfony/Component/HttpFoundation/CHANGELOG.md b/src/Symfony/Component/HttpFoundation/CHANGELOG.md index ac812fe1527a0..e1fdf77b9b8ae 100644 --- a/src/Symfony/Component/HttpFoundation/CHANGELOG.md +++ b/src/Symfony/Component/HttpFoundation/CHANGELOG.md @@ -4,7 +4,7 @@ CHANGELOG 3.3.0 ----- - * [BC BREAK] the `Request::setTrustedProxies()` method takes a new `$trustedHeaderSet` argument, + * the `Request::setTrustedProxies()` method takes a new `$trustedHeaderSet` argument, see http://symfony.com/doc/current/components/http_foundation/trusting_proxies.html for more info, * deprecated the `Request::setTrustedHeaderName()` and `Request::getTrustedHeaderName()` methods, * added `File\Stream`, to be passed to `BinaryFileResponse` when the size of the served file is unknown, diff --git a/src/Symfony/Component/HttpFoundation/Request.php b/src/Symfony/Component/HttpFoundation/Request.php index 75d15df3120b9..13ff1e05528fe 100644 --- a/src/Symfony/Component/HttpFoundation/Request.php +++ b/src/Symfony/Component/HttpFoundation/Request.php @@ -581,7 +581,7 @@ public function overrideGlobals() * You should only list the reverse proxies that you manage directly. * * @param array $proxies A list of trusted proxies - * @param int $trustedHeaderSet A bit field of Request::HEADER_*, usually either Request::HEADER_FORWARDED or Request::HEADER_X_FORWARDED_ALL, to set which headers to trust from your proxies + * @param int $trustedHeaderSet A bit field of Request::HEADER_*, to set which headers to trust from your proxies * * @throws \InvalidArgumentException When $trustedHeaderSet is invalid */ @@ -590,10 +590,11 @@ public static function setTrustedProxies(array $proxies/*, int $trustedHeaderSet self::$trustedProxies = $proxies; if (2 > func_num_args()) { - // @deprecated code path in 3.3, to be replaced by mandatory argument in 4.0. - throw new \InvalidArgumentException(sprintf('The %s() method expects a bit field of Request::HEADER_* as second argument. Defining it is required since version 3.3. See http://symfony.com/doc/current/components/http_foundation/trusting_proxies.html for more info.', __METHOD__)); + @trigger_error(sprintf('The %s() method expects a bit field of Request::HEADER_* as second argument since version 3.3. Defining it will be required in 4.0. ', __METHOD__), E_USER_DEPRECATED); + + return; } - $trustedHeaderSet = func_get_arg(1); + $trustedHeaderSet = (int) func_get_arg(1); foreach (self::$trustedHeaderNames as $header => $name) { self::$trustedHeaders[$header] = $header & $trustedHeaderSet ? $name : null; @@ -665,11 +666,11 @@ public static function getTrustedHosts() * * @throws \InvalidArgumentException * - * @deprecated since version 3.3, to be removed in 4.0. Use "X-Forwarded-*" headers or the "Forwarded" header defined in RFC7239, and the $trustedHeaderSet argument of the Request::setTrustedProxies() method instead. + * @deprecated since version 3.3, to be removed in 4.0. Use the $trustedHeaderSet argument of the Request::setTrustedProxies() method instead. */ public static function setTrustedHeaderName($key, $value) { - @trigger_error(sprintf('The "%s()" method is deprecated since version 3.3 and will be removed in 4.0. Use "X-Forwarded-*" headers or the "Forwarded" header defined in RFC7239, and the $trustedHeaderSet argument of the Request::setTrustedProxies() method instead.', __METHOD__), E_USER_DEPRECATED); + @trigger_error(sprintf('The "%s()" method is deprecated since version 3.3 and will be removed in 4.0. Use the $trustedHeaderSet argument of the Request::setTrustedProxies() method instead.', __METHOD__), E_USER_DEPRECATED); if (!array_key_exists($key, self::$trustedHeaders)) { throw new \InvalidArgumentException(sprintf('Unable to set the trusted header name for key "%s".', $key)); @@ -679,6 +680,9 @@ public static function setTrustedHeaderName($key, $value) if (null !== $value) { self::$trustedHeaderNames[$key] = $value; + self::$trustedHeaderSet |= $key; + } else { + self::$trustedHeaderSet &= ~$key; } } @@ -886,8 +890,8 @@ public function getClientIps() * adding the IP address where it received the request from. * * If your reverse proxy uses a different header name than "X-Forwarded-For", - * ("Client-Ip" for instance), configure it via "setTrustedHeaderName()" with - * the "client-ip" key. + * ("Client-Ip" for instance), configure it via the $trustedHeaderSet + * argument of the Request::setTrustedProxies() method instead. * * @return string|null The client IP address * @@ -993,7 +997,8 @@ public function getScheme() * The "X-Forwarded-Port" header must contain the client port. * * If your reverse proxy uses a different header name than "X-Forwarded-Port", - * configure it via "setTrustedHeaderName()" with the "client-port" key. + * configure it via via the $trustedHeaderSet argument of the + * Request::setTrustedProxies() method instead. * * @return int|string can be a string if fetched from the server bag */ @@ -1210,8 +1215,8 @@ public function getQueryString() * The "X-Forwarded-Proto" header must contain the protocol: "https" or "http". * * If your reverse proxy uses a different header name than "X-Forwarded-Proto" - * ("SSL_HTTPS" for instance), configure it via "setTrustedHeaderName()" with - * the "client-proto" key. + * ("SSL_HTTPS" for instance), configure it via the $trustedHeaderSet + * argument of the Request::setTrustedProxies() method instead. * * @return bool */ @@ -1235,7 +1240,8 @@ public function isSecure() * The "X-Forwarded-Host" header must contain the client host name. * * If your reverse proxy uses a different header name than "X-Forwarded-Host", - * configure it via "setTrustedHeaderName()" with the "client-host" key. + * configure it via the $trustedHeaderSet argument of the + * Request::setTrustedProxies() method instead. * * @return string * diff --git a/src/Symfony/Component/HttpFoundation/Tests/RequestTest.php b/src/Symfony/Component/HttpFoundation/Tests/RequestTest.php index 9042fc49ba824..b36fbb7e96258 100644 --- a/src/Symfony/Component/HttpFoundation/Tests/RequestTest.php +++ b/src/Symfony/Component/HttpFoundation/Tests/RequestTest.php @@ -1729,7 +1729,7 @@ public function testTrustedProxiesXForwardedFor() /** * @group legacy - * @expectedDeprecation The "Symfony\Component\HttpFoundation\Request::setTrustedHeaderName()" method is deprecated since version 3.3 and will be removed in 4.0. Use "X-Forwarded-*" headers or the "Forwarded" header defined in RFC7239, and the $trustedHeaderSet argument of the Request::setTrustedProxies() method instead. + * @expectedDeprecation The "Symfony\Component\HttpFoundation\Request::setTrustedHeaderName()" method is deprecated since version 3.3 and will be removed in 4.0. Use the $trustedHeaderSet argument of the Request::setTrustedProxies() method instead. */ public function testLegacyTrustedProxies() { From 28aaa8eb05fd037ab3740f3123153dc2a6f275a4 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Mon, 5 Jun 2017 10:23:13 +0200 Subject: [PATCH 0145/1099] [Cache] Fallback to positional when keyed results are broken --- .../Component/Cache/Adapter/AbstractAdapter.php | 3 +++ .../Component/Cache/Adapter/MemcachedAdapter.php | 12 ++++++++++++ src/Symfony/Component/Cache/Simple/AbstractCache.php | 3 +++ .../Tests/Adapter/TraceableTagAwareAdapterTest.php | 3 +++ .../Component/Cache/Tests/Simple/CacheTestCase.php | 9 +++++++++ 5 files changed, 30 insertions(+) diff --git a/src/Symfony/Component/Cache/Adapter/AbstractAdapter.php b/src/Symfony/Component/Cache/Adapter/AbstractAdapter.php index c761b9a2010bf..e4fa4c97b7ba9 100644 --- a/src/Symfony/Component/Cache/Adapter/AbstractAdapter.php +++ b/src/Symfony/Component/Cache/Adapter/AbstractAdapter.php @@ -266,6 +266,9 @@ private function generateItems($items, &$keys) try { foreach ($items as $id => $value) { + if (!isset($keys[$id])) { + $id = key($keys); + } $key = $keys[$id]; unset($keys[$id]); yield $key => $f($key, $value, true); diff --git a/src/Symfony/Component/Cache/Adapter/MemcachedAdapter.php b/src/Symfony/Component/Cache/Adapter/MemcachedAdapter.php index 5c8784e69cf44..3acf8bdb86c6a 100644 --- a/src/Symfony/Component/Cache/Adapter/MemcachedAdapter.php +++ b/src/Symfony/Component/Cache/Adapter/MemcachedAdapter.php @@ -19,6 +19,18 @@ class MemcachedAdapter extends AbstractAdapter protected $maxIdLength = 250; + /** + * Constructor. + * + * Using a MemcachedAdapter with a TagAwareAdapter for storing tags is discouraged. + * Using a RedisAdapter is recommended instead. If you cannot do otherwise, be aware that: + * - the Memcached::OPT_BINARY_PROTOCOL must be enabled + * (that's the default when using MemcachedAdapter::createConnection()); + * - tags eviction by Memcached's LRU algorithm will break by-tags invalidation; + * your Memcached memory should be large enough to never trigger LRU. + * + * Using a MemcachedAdapter as a pure items store is fine. + */ public function __construct(\Memcached $client, $namespace = '', $defaultLifetime = 0) { $this->init($client, $namespace, $defaultLifetime); diff --git a/src/Symfony/Component/Cache/Simple/AbstractCache.php b/src/Symfony/Component/Cache/Simple/AbstractCache.php index 4c44b9b323bb0..bbd35780fd5c4 100644 --- a/src/Symfony/Component/Cache/Simple/AbstractCache.php +++ b/src/Symfony/Component/Cache/Simple/AbstractCache.php @@ -162,6 +162,9 @@ private function generateValues($values, &$keys, $default) { try { foreach ($values as $id => $value) { + if (!isset($keys[$id])) { + $id = key($keys); + } $key = $keys[$id]; unset($keys[$id]); yield $key => $value; diff --git a/src/Symfony/Component/Cache/Tests/Adapter/TraceableTagAwareAdapterTest.php b/src/Symfony/Component/Cache/Tests/Adapter/TraceableTagAwareAdapterTest.php index 38f3c6c087dfc..9b50bfabe65b7 100644 --- a/src/Symfony/Component/Cache/Tests/Adapter/TraceableTagAwareAdapterTest.php +++ b/src/Symfony/Component/Cache/Tests/Adapter/TraceableTagAwareAdapterTest.php @@ -15,6 +15,9 @@ use Symfony\Component\Cache\Adapter\TagAwareAdapter; use Symfony\Component\Cache\Adapter\TraceableTagAwareAdapter; +/** + * @group time-sensitive + */ class TraceableTagAwareAdapterTest extends TraceableAdapterTest { public function testInvalidateTags() diff --git a/src/Symfony/Component/Cache/Tests/Simple/CacheTestCase.php b/src/Symfony/Component/Cache/Tests/Simple/CacheTestCase.php index 81d412bd66354..b3799ebcda24c 100644 --- a/src/Symfony/Component/Cache/Tests/Simple/CacheTestCase.php +++ b/src/Symfony/Component/Cache/Tests/Simple/CacheTestCase.php @@ -15,6 +15,15 @@ abstract class CacheTestCase extends SimpleCacheTest { + public static function validKeys() + { + if (defined('HHVM_VERSION')) { + return parent::validKeys(); + } + + return array_merge(parent::validKeys(), array(array("a\0b"))); + } + public function testDefaultLifeTime() { if (isset($this->skippedTests[__FUNCTION__])) { From 1ab3e413d4e732f53841c4d8db900a8edb01d50a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Wed, 31 May 2017 08:51:10 +0200 Subject: [PATCH 0146/1099] [DependencyInjection] Fix named args support in ChildDefinition --- .../DependencyInjection/ChildDefinition.php | 16 +++++----------- .../Tests/ChildDefinitionTest.php | 4 ++++ 2 files changed, 9 insertions(+), 11 deletions(-) diff --git a/src/Symfony/Component/DependencyInjection/ChildDefinition.php b/src/Symfony/Component/DependencyInjection/ChildDefinition.php index dd02f860677f8..5701caa474e57 100644 --- a/src/Symfony/Component/DependencyInjection/ChildDefinition.php +++ b/src/Symfony/Component/DependencyInjection/ChildDefinition.php @@ -62,7 +62,7 @@ public function setParent($parent) * If replaceArgument() has been used to replace an argument, this method * will return the replacement value. * - * @param int $index + * @param int|string $index * * @return mixed The argument value * @@ -74,13 +74,7 @@ public function getArgument($index) return $this->arguments['index_'.$index]; } - $lastIndex = count(array_filter(array_keys($this->arguments), 'is_int')) - 1; - - if ($index < 0 || $index > $lastIndex) { - throw new OutOfBoundsException(sprintf('The index "%d" is not in the range [0, %d].', $index, $lastIndex)); - } - - return $this->arguments[$index]; + return parent::getArgument($index); } /** @@ -91,8 +85,8 @@ public function getArgument($index) * certain conventions when you want to overwrite the arguments of the * parent definition, otherwise your arguments will only be appended. * - * @param int $index - * @param mixed $value + * @param int|string $index + * @param mixed $value * * @return self the current instance * @@ -105,7 +99,7 @@ public function replaceArgument($index, $value) } elseif (0 === strpos($index, '$')) { $this->arguments[$index] = $value; } else { - throw new InvalidArgumentException('$index must be an integer.'); + throw new InvalidArgumentException('The argument must be an existing index or the name of a constructor\'s parameter.'); } return $this; diff --git a/src/Symfony/Component/DependencyInjection/Tests/ChildDefinitionTest.php b/src/Symfony/Component/DependencyInjection/Tests/ChildDefinitionTest.php index a367a8b2c4d03..a941b960746be 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/ChildDefinitionTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/ChildDefinitionTest.php @@ -113,6 +113,10 @@ public function testReplaceArgument() $this->assertSame('baz', $def->getArgument(1)); $this->assertSame(array(0 => 'foo', 1 => 'bar', 'index_1' => 'baz'), $def->getArguments()); + + $this->assertSame($def, $def->replaceArgument('$bar', 'val')); + $this->assertSame('val', $def->getArgument('$bar')); + $this->assertSame(array(0 => 'foo', 1 => 'bar', 'index_1' => 'baz', '$bar' => 'val'), $def->getArguments()); } /** From 21ef0655942c0e75a3d58cc989f8ab26beb693e0 Mon Sep 17 00:00:00 2001 From: Maxime Steinhausser Date: Thu, 1 Jun 2017 11:17:30 +0200 Subject: [PATCH 0147/1099] [HttpKernel][Debug] Fix missing trace on deprecations collected during bootstrapping & silenced errors --- src/Symfony/Component/Debug/ErrorHandler.php | 54 ++++++++++++++----- .../Debug/Exception/SilencedErrorContext.php | 14 ++++- .../Debug/Tests/ErrorHandlerTest.php | 8 ++- .../DataCollector/LoggerDataCollector.php | 46 ++++++++++++---- src/Symfony/Component/HttpKernel/Kernel.php | 21 +++++++- .../VarDumper/Caster/ExceptionCaster.php | 14 +++-- 6 files changed, 124 insertions(+), 33 deletions(-) diff --git a/src/Symfony/Component/Debug/ErrorHandler.php b/src/Symfony/Component/Debug/ErrorHandler.php index d6c4d10d2934a..e25b5a6dd8b2a 100644 --- a/src/Symfony/Component/Debug/ErrorHandler.php +++ b/src/Symfony/Component/Debug/ErrorHandler.php @@ -100,6 +100,8 @@ class ErrorHandler private static $stackedErrors = array(); private static $stackedErrorLevels = array(); private static $toStringException = null; + private static $silencedErrorCache = array(); + private static $silencedErrorCount = 0; private static $exitCode = 0; /** @@ -407,7 +409,24 @@ public function handleError($type, $message, $file, $line) $errorAsException = self::$toStringException; self::$toStringException = null; } elseif (!$throw && !($type & $level)) { - $errorAsException = new SilencedErrorContext($type, $file, $line); + if (isset(self::$silencedErrorCache[$message])) { + $lightTrace = null; + $errorAsException = self::$silencedErrorCache[$message]; + ++$errorAsException->count; + } else { + $lightTrace = $this->tracedErrors & $type ? $this->cleanTrace(debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS), $type, $file, $line, false) : array(); + $errorAsException = new SilencedErrorContext($type, $file, $line, $lightTrace); + } + + if (100 < ++self::$silencedErrorCount) { + self::$silencedErrorCache = $lightTrace = array(); + self::$silencedErrorCount = 1; + } + self::$silencedErrorCache[$message] = $errorAsException; + + if (null === $lightTrace) { + return; + } } else { if ($scope) { $errorAsException = new ContextErrorException($logMessage, 0, $type, $file, $line, $context); @@ -418,19 +437,7 @@ public function handleError($type, $message, $file, $line) // Clean the trace by removing function arguments and the first frames added by the error handler itself. if ($throw || $this->tracedErrors & $type) { $backtrace = $backtrace ?: $errorAsException->getTrace(); - $lightTrace = $backtrace; - - for ($i = 0; isset($backtrace[$i]); ++$i) { - if (isset($backtrace[$i]['file'], $backtrace[$i]['line']) && $backtrace[$i]['line'] === $line && $backtrace[$i]['file'] === $file) { - $lightTrace = array_slice($lightTrace, 1 + $i); - break; - } - } - if (!($throw || $this->scopedErrors & $type)) { - for ($i = 0; isset($lightTrace[$i]); ++$i) { - unset($lightTrace[$i]['args']); - } - } + $lightTrace = $this->cleanTrace($backtrace, $type, $file, $line, $throw); $this->traceReflector->setValue($errorAsException, $lightTrace); } else { $this->traceReflector->setValue($errorAsException, array()); @@ -687,4 +694,23 @@ protected function getFatalErrorHandlers() new ClassNotFoundFatalErrorHandler(), ); } + + private function cleanTrace($backtrace, $type, $file, $line, $throw) + { + $lightTrace = $backtrace; + + for ($i = 0; isset($backtrace[$i]); ++$i) { + if (isset($backtrace[$i]['file'], $backtrace[$i]['line']) && $backtrace[$i]['line'] === $line && $backtrace[$i]['file'] === $file) { + $lightTrace = array_slice($lightTrace, 1 + $i); + break; + } + } + if (!($throw || $this->scopedErrors & $type)) { + for ($i = 0; isset($lightTrace[$i]); ++$i) { + unset($lightTrace[$i]['args']); + } + } + + return $lightTrace; + } } diff --git a/src/Symfony/Component/Debug/Exception/SilencedErrorContext.php b/src/Symfony/Component/Debug/Exception/SilencedErrorContext.php index 0c3a0e1d9fb58..4be83491b9df7 100644 --- a/src/Symfony/Component/Debug/Exception/SilencedErrorContext.php +++ b/src/Symfony/Component/Debug/Exception/SilencedErrorContext.php @@ -18,15 +18,20 @@ */ class SilencedErrorContext implements \JsonSerializable { + public $count = 1; + private $severity; private $file; private $line; + private $trace; - public function __construct($severity, $file, $line) + public function __construct($severity, $file, $line, array $trace = array(), $count = 1) { $this->severity = $severity; $this->file = $file; $this->line = $line; + $this->trace = $trace; + $this->count = $count; } public function getSeverity() @@ -44,12 +49,19 @@ public function getLine() return $this->line; } + public function getTrace() + { + return $this->trace; + } + public function JsonSerialize() { return array( 'severity' => $this->severity, 'file' => $this->file, 'line' => $this->line, + 'trace' => $this->trace, + 'count' => $this->count, ); } } diff --git a/src/Symfony/Component/Debug/Tests/ErrorHandlerTest.php b/src/Symfony/Component/Debug/Tests/ErrorHandlerTest.php index 2fccf2dbe7a9b..a14accf3df9a0 100644 --- a/src/Symfony/Component/Debug/Tests/ErrorHandlerTest.php +++ b/src/Symfony/Component/Debug/Tests/ErrorHandlerTest.php @@ -221,12 +221,17 @@ public function testHandleError() $logger = $this->getMockBuilder('Psr\Log\LoggerInterface')->getMock(); - $logArgCheck = function ($level, $message, $context) { + $line = null; + $logArgCheck = function ($level, $message, $context) use (&$line) { $this->assertEquals('Notice: Undefined variable: undefVar', $message); $this->assertArrayHasKey('exception', $context); $exception = $context['exception']; $this->assertInstanceOf(SilencedErrorContext::class, $exception); $this->assertSame(E_NOTICE, $exception->getSeverity()); + $this->assertSame(__FILE__, $exception->getFile()); + $this->assertSame($line, $exception->getLine()); + $this->assertNotEmpty($exception->getTrace()); + $this->assertSame(1, $exception->count); }; $logger @@ -239,6 +244,7 @@ public function testHandleError() $handler->setDefaultLogger($logger, E_NOTICE); $handler->screamAt(E_NOTICE); unset($undefVar); + $line = __LINE__ + 1; @$undefVar++; restore_error_handler(); diff --git a/src/Symfony/Component/HttpKernel/DataCollector/LoggerDataCollector.php b/src/Symfony/Component/HttpKernel/DataCollector/LoggerDataCollector.php index 7ae1fbbd61537..f45f99718d318 100644 --- a/src/Symfony/Component/HttpKernel/DataCollector/LoggerDataCollector.php +++ b/src/Symfony/Component/HttpKernel/DataCollector/LoggerDataCollector.php @@ -49,10 +49,8 @@ public function collect(Request $request, Response $response, \Exception $except public function lateCollect() { if (null !== $this->logger) { - $this->data = $this->computeErrorsCount(); - $containerDeprecationLogs = $this->getContainerDeprecationLogs(); - $this->data['deprecation_count'] += count($containerDeprecationLogs); + $this->data = $this->computeErrorsCount($containerDeprecationLogs); $this->data['compiler_logs'] = $this->getContainerCompilerLogs(); $this->data['logs'] = $this->sanitizeLogs(array_merge($this->logger->getLogs(), $containerDeprecationLogs)); $this->data = $this->cloneVar($this->data); @@ -113,11 +111,10 @@ private function getContainerDeprecationLogs() return array(); } - $stubs = array(); $bootTime = filemtime($file); $logs = array(); foreach (unserialize(file_get_contents($file)) as $log) { - $log['context'] = array('exception' => new SilencedErrorContext($log['type'], $log['file'], $log['line'])); + $log['context'] = array('exception' => new SilencedErrorContext($log['type'], $log['file'], $log['line'], $log['trace'], $log['count'])); $log['timestamp'] = $bootTime; $log['priority'] = 100; $log['priorityName'] = 'DEBUG'; @@ -159,15 +156,34 @@ private function sanitizeLogs($logs) continue; } + $message = $log['message']; $exception = $log['context']['exception']; - $errorId = md5("{$exception->getSeverity()}/{$exception->getLine()}/{$exception->getFile()}\0{$log['message']}", true); + + if ($exception instanceof SilencedErrorContext) { + if (isset($silencedLogs[$h = spl_object_hash($exception)])) { + continue; + } + $silencedLogs[$h] = true; + + if (!isset($sanitizedLogs[$message])) { + $sanitizedLogs[$message] = $log + array( + 'errorCount' => 0, + 'scream' => true, + ); + } + $sanitizedLogs[$message]['errorCount'] += $exception->count; + + continue; + } + + $errorId = md5("{$exception->getSeverity()}/{$exception->getLine()}/{$exception->getFile()}\0{$message}", true); if (isset($sanitizedLogs[$errorId])) { ++$sanitizedLogs[$errorId]['errorCount']; } else { $log += array( 'errorCount' => 1, - 'scream' => $exception instanceof SilencedErrorContext, + 'scream' => false, ); $sanitizedLogs[$errorId] = $log; @@ -196,8 +212,9 @@ private function isSilencedOrDeprecationErrorLog(array $log) return false; } - private function computeErrorsCount() + private function computeErrorsCount(array $containerDeprecationLogs) { + $silencedLogs = array(); $count = array( 'error_count' => $this->logger->countErrors(), 'deprecation_count' => 0, @@ -220,14 +237,23 @@ private function computeErrorsCount() } if ($this->isSilencedOrDeprecationErrorLog($log)) { - if ($log['context']['exception'] instanceof SilencedErrorContext) { - ++$count['scream_count']; + $exception = $log['context']['exception']; + if ($exception instanceof SilencedErrorContext) { + if (isset($silencedLogs[$h = spl_object_hash($exception)])) { + continue; + } + $silencedLogs[$h] = true; + $count['scream_count'] += $exception->count; } else { ++$count['deprecation_count']; } } } + foreach ($containerDeprecationLogs as $deprecationLog) { + $count['deprecation_count'] += $deprecationLog['count']; + } + ksort($count['priorities']); return $count; diff --git a/src/Symfony/Component/HttpKernel/Kernel.php b/src/Symfony/Component/HttpKernel/Kernel.php index c9724c61f9ab9..5c5f6a0921625 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -545,11 +545,28 @@ protected function initializeContainer() return $previousHandler ? $previousHandler($type, $message, $file, $line) : false; } - $collectedLogs[] = array( + if (isset($collectedLogs[$message])) { + ++$collectedLogs[$message]['count']; + + return; + } + + $backtrace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS); + // Clean the trace by removing first frames added by the error handler itself. + for ($i = 0; isset($backtrace[$i]); ++$i) { + if (isset($backtrace[$i]['file'], $backtrace[$i]['line']) && $backtrace[$i]['line'] === $line && $backtrace[$i]['file'] === $file) { + $backtrace = array_slice($backtrace, 1 + $i); + break; + } + } + + $collectedLogs[$message] = array( 'type' => $type, 'message' => $message, 'file' => $file, 'line' => $line, + 'trace' => $backtrace, + 'count' => 1, ); }); } @@ -562,7 +579,7 @@ protected function initializeContainer() if ($this->debug) { restore_error_handler(); - file_put_contents($this->getCacheDir().'/'.$class.'Deprecations.log', serialize($collectedLogs)); + file_put_contents($this->getCacheDir().'/'.$class.'Deprecations.log', serialize(array_values($collectedLogs))); file_put_contents($this->getCacheDir().'/'.$class.'Compiler.log', null !== $container ? implode("\n", $container->getCompiler()->getLog()) : ''); } } diff --git a/src/Symfony/Component/VarDumper/Caster/ExceptionCaster.php b/src/Symfony/Component/VarDumper/Caster/ExceptionCaster.php index e2a4200c52503..11ddf25b0b056 100644 --- a/src/Symfony/Component/VarDumper/Caster/ExceptionCaster.php +++ b/src/Symfony/Component/VarDumper/Caster/ExceptionCaster.php @@ -83,7 +83,6 @@ public static function castThrowingCasterException(ThrowingCasterException $e, a public static function castSilencedErrorContext(SilencedErrorContext $e, array $a, Stub $stub, $isNested) { $sPrefix = "\0".SilencedErrorContext::class."\0"; - $xPrefix = "\0Exception\0"; if (!isset($a[$s = $sPrefix.'severity'])) { return $a; @@ -93,12 +92,17 @@ public static function castSilencedErrorContext(SilencedErrorContext $e, array $ $a[$s] = new ConstStub(self::$errorTypes[$a[$s]], $a[$s]); } - $trace = array( + $trace = array(array( 'file' => $a[$sPrefix.'file'], 'line' => $a[$sPrefix.'line'], - ); - unset($a[$sPrefix.'file'], $a[$sPrefix.'line']); - $a[Caster::PREFIX_VIRTUAL.'trace'] = new TraceStub(array($trace)); + )); + + if (isset($a[$sPrefix.'trace'])) { + $trace = array_merge($trace, $a[$sPrefix.'trace']); + } + + unset($a[$sPrefix.'file'], $a[$sPrefix.'line'], $a[$sPrefix.'trace']); + $a[Caster::PREFIX_VIRTUAL.'trace'] = new TraceStub($trace); return $a; } From f16a9dafeaacc897ea080a5a76d19c5a9b44232a Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Mon, 5 Jun 2017 10:31:48 -0700 Subject: [PATCH 0148/1099] updated CHANGELOG for 3.3.1 --- CHANGELOG-3.3.md | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/CHANGELOG-3.3.md b/CHANGELOG-3.3.md index 17b9ed1ed3073..8a6626da32d0f 100644 --- a/CHANGELOG-3.3.md +++ b/CHANGELOG-3.3.md @@ -7,6 +7,36 @@ in 3.3 minor versions. To get the diff for a specific change, go to https://github.com/symfony/symfony/commit/XXX where XXX is the change hash To get the diff between two versions, go to https://github.com/symfony/symfony/compare/v3.3.0...v3.3.1 +* 3.3.1 (2017-06-05) + + * bug #23067 [HttpFoundation][FrameworkBundle] Revert "trusted proxies" BC break (nicolas-grekas) + * bug #23065 [Cache] Fallback to positional when keyed results are broken (nicolas-grekas) + * bug #22981 [DependencyInjection] Fix named args support in ChildDefinition (dunglas) + * bug #23050 [Form][Profiler] Fixes form collector triggering deprecations (ogizanagi) + * bug #22971 [Profiler] Fix code excerpt wrapping (ogizanagi) + * bug #23049 [FrameworkBundle] mitigate BC break with empty trusted_proxies (xabbuh) + * bug #23045 [Cache] fix Redis scheme detection (xabbuh) + * bug #23013 Parse the _controller format in sub-requests (weaverryan) + * bug #23015 [PhpUnitBridge] Fix detection of PHPUnit 5 (enumag) + * bug #23041 [Config] Always protected ClassExistenceResource against bad parents (nicolas-grekas) + * bug #22988 [PropertyInfo][DoctrineBridge] The bigint Doctrine's type must be converted to string (dunglas) + * bug #23014 Fix optional cache warmers are always instantiated whereas they should be lazy-loaded (romainneutron) + * feature #23022 [Di] Remove closure-proxy arguments (nicolas-grekas) + * bug #23024 [EventDispatcher] Fix ContainerAwareEventDispatcher::hasListeners(null) (nicolas-grekas) + * bug #23008 [EventDispatcher] Handle laziness internally instead of relying on ClosureProxyArgument (nicolas-grekas) + * bug #23018 [FrameworkBundle] Fix CacheCollectorPass priority (chalasr) + * bug #23009 [Routing] Allow GET requests to be redirected. Fixes #23004 (frankdejonge) + * bug #22996 [Form] Fix \IntlDateFormatter timezone parameter usage to bypass PHP bug #66323 (romainneutron) + * bug #22965 [Cache] Ignore missing annotations.php (ro0NL) + * bug #22993 [DI] Autowiring exception thrown when inlined service is removed (weaverryan) + * bug #22999 Better DI type deprecation message (weaverryan) + * bug #22985 [Config] Allow empty globs (nicolas-grekas) + * bug #22961 [HttpKernel] Support unknown format in LoggerDataCollector (iltar) + * bug #22991 [DI] Don't throw Autowire exception for removed service with private __construct (weaverryan) + * bug #22968 [Profiler] Fix text selection & click on file links on exception pages (ogizanagi) + * bug #22994 Harden the debugging of Twig filters and functions (stof) + * bug #22960 [Cache] Fix decoration of TagAware adapters in dev (chalasr) + * 3.3.0 (2017-05-29) * bug #22940 [Config] Fallback to regular import when glob fails (nicolas-grekas) From af5522ebf8c11352b0f5698992954db4b50ae510 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Mon, 5 Jun 2017 10:31:57 -0700 Subject: [PATCH 0149/1099] updated VERSION for 3.3.1 --- src/Symfony/Component/HttpKernel/Kernel.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/HttpKernel/Kernel.php b/src/Symfony/Component/HttpKernel/Kernel.php index ec728417eec78..b9a95ac99dbe2 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -61,12 +61,12 @@ abstract class Kernel implements KernelInterface, TerminableInterface private $projectDir; - const VERSION = '3.3.1-DEV'; + const VERSION = '3.3.1'; const VERSION_ID = 30301; const MAJOR_VERSION = 3; const MINOR_VERSION = 3; const RELEASE_VERSION = 1; - const EXTRA_VERSION = 'DEV'; + const EXTRA_VERSION = ''; const END_OF_MAINTENANCE = '01/2018'; const END_OF_LIFE = '07/2018'; From 7061bfbf3a5e2f32a20f9934ed80e5df010103b2 Mon Sep 17 00:00:00 2001 From: Yonel Ceruto Date: Mon, 5 Jun 2017 13:09:00 -0400 Subject: [PATCH 0150/1099] show unique inherited roles --- .../SecurityBundle/DataCollector/SecurityDataCollector.php | 2 +- .../Tests/DataCollector/SecurityDataCollectorTest.php | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Bundle/SecurityBundle/DataCollector/SecurityDataCollector.php b/src/Symfony/Bundle/SecurityBundle/DataCollector/SecurityDataCollector.php index 092c627fa9862..c9f2599526a70 100644 --- a/src/Symfony/Bundle/SecurityBundle/DataCollector/SecurityDataCollector.php +++ b/src/Symfony/Bundle/SecurityBundle/DataCollector/SecurityDataCollector.php @@ -82,7 +82,7 @@ public function collect(Request $request, Response $response, \Exception $except 'token_class' => get_class($token), 'user' => $token->getUsername(), 'roles' => array_map(function (RoleInterface $role) { return $role->getRole(); }, $assignedRoles), - 'inherited_roles' => array_map(function (RoleInterface $role) { return $role->getRole(); }, $inheritedRoles), + 'inherited_roles' => array_unique(array_map(function (RoleInterface $role) { return $role->getRole(); }, $inheritedRoles)), 'supports_role_hierarchy' => null !== $this->roleHierarchy, ); } diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DataCollector/SecurityDataCollectorTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/DataCollector/SecurityDataCollectorTest.php index 0357b612060c4..e8f808f98ee94 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/DataCollector/SecurityDataCollectorTest.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DataCollector/SecurityDataCollectorTest.php @@ -111,6 +111,11 @@ public function provideRoles() array('ROLE_ADMIN'), array('ROLE_USER', 'ROLE_ALLOWED_TO_SWITCH'), ), + array( + array('ROLE_ADMIN', 'ROLE_OPERATOR'), + array('ROLE_ADMIN', 'ROLE_OPERATOR'), + array('ROLE_USER', 'ROLE_ALLOWED_TO_SWITCH'), + ), ); } @@ -118,6 +123,7 @@ private function getRoleHierarchy() { return new RoleHierarchy(array( 'ROLE_ADMIN' => array('ROLE_USER', 'ROLE_ALLOWED_TO_SWITCH'), + 'ROLE_OPERATOR' => array('ROLE_USER'), )); } From 25df7a19a8a7c3cd072bb5db058a42b1c7cc2c0d Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Mon, 5 Jun 2017 11:41:08 -0700 Subject: [PATCH 0151/1099] bumped Symfony version to 3.3.2 --- 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 b9a95ac99dbe2..85c7b2720184b 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -61,12 +61,12 @@ abstract class Kernel implements KernelInterface, TerminableInterface private $projectDir; - const VERSION = '3.3.1'; - const VERSION_ID = 30301; + const VERSION = '3.3.2-DEV'; + const VERSION_ID = 30302; const MAJOR_VERSION = 3; const MINOR_VERSION = 3; - const RELEASE_VERSION = 1; - const EXTRA_VERSION = ''; + const RELEASE_VERSION = 2; + const EXTRA_VERSION = 'DEV'; const END_OF_MAINTENANCE = '01/2018'; const END_OF_LIFE = '07/2018'; From 1da8e71b6ceb997b6a1ccb2bd0873102e54d02d7 Mon Sep 17 00:00:00 2001 From: Dany Maillard Date: Sun, 30 Apr 2017 15:22:14 +0200 Subject: [PATCH 0152/1099] Add filter in VarDumperTestTrait --- UPGRADE-4.0.md | 33 +++++++++++++++++++ .../VarDumper/Test/VarDumperTestTrait.php | 24 ++++++++++---- 2 files changed, 51 insertions(+), 6 deletions(-) diff --git a/UPGRADE-4.0.md b/UPGRADE-4.0.md index 6424371880704..f49f9cd742f9d 100644 --- a/UPGRADE-4.0.md +++ b/UPGRADE-4.0.md @@ -540,6 +540,39 @@ Validator changed to `true` as of 4.0. If you need the previous behaviour ensure to set the option to `false`. +VarDumper +--------- + + * The `VarDumperTestTrait::assertDumpEquals()` method expects a 3rd `$context = null` + argument and moves `$message = ''` argument at 4th position. + + Before: + + ```php + VarDumperTestTrait::assertDumpEquals($dump, $data, $message = ''); + ``` + + After: + + ```php + VarDumperTestTrait::assertDumpEquals($dump, $data, $filter = 0, $message = ''); + ``` + + * The `VarDumperTestTrait::assertDumpMatchesFormat()` method expects a 3rd `$context = null` + argument and moves `$message = ''` argument at 4th position. + + Before: + + ```php + VarDumperTestTrait::assertDumpMatchesFormat($dump, $data, $message = ''); + ``` + + After: + + ```php + VarDumperTestTrait::assertDumpMatchesFormat($dump, $data, $filter = 0, $message = ''); + ``` + Workflow -------- diff --git a/src/Symfony/Component/VarDumper/Test/VarDumperTestTrait.php b/src/Symfony/Component/VarDumper/Test/VarDumperTestTrait.php index 40ec83d132221..d41ec63087d8f 100644 --- a/src/Symfony/Component/VarDumper/Test/VarDumperTestTrait.php +++ b/src/Symfony/Component/VarDumper/Test/VarDumperTestTrait.php @@ -19,17 +19,29 @@ */ trait VarDumperTestTrait { - public function assertDumpEquals($dump, $data, $message = '') + public function assertDumpEquals($dump, $data, $filter = 0, $message = '') { - $this->assertSame(rtrim($dump), $this->getDump($data), $message); + if (is_string($filter)) { + @trigger_error(sprintf('The $message argument of the %s() at 3rd position is deprecated since version 3.4 and will be moved at 4th position in 4.0.', __METHOD__), E_USER_DEPRECATED); + $message = $filter; + $filter = 0; + } + + $this->assertSame(rtrim($dump), $this->getDump($data, null, $filter), $message); } - public function assertDumpMatchesFormat($dump, $data, $message = '') + public function assertDumpMatchesFormat($dump, $data, $filter = 0, $message = '') { - $this->assertStringMatchesFormat(rtrim($dump), $this->getDump($data), $message); + if (is_string($filter)) { + @trigger_error(sprintf('The $message argument of the %s() at 3rd position is deprecated since version 3.4 and will be moved at 4th position in 4.0.', __METHOD__), E_USER_DEPRECATED); + $message = $filter; + $filter = 0; + } + + $this->assertStringMatchesFormat(rtrim($dump), $this->getDump($data, null, $filter), $message); } - protected function getDump($data, $key = null) + protected function getDump($data, $key = null, $filter = 0) { $flags = getenv('DUMP_LIGHT_ARRAY') ? CliDumper::DUMP_LIGHT_ARRAY : 0; $flags |= getenv('DUMP_STRING_LENGTH') ? CliDumper::DUMP_STRING_LENGTH : 0; @@ -38,7 +50,7 @@ protected function getDump($data, $key = null) $cloner->setMaxItems(-1); $dumper = new CliDumper(null, null, $flags); $dumper->setColors(false); - $data = $cloner->cloneVar($data)->withRefHandles(false); + $data = $cloner->cloneVar($data, $filter)->withRefHandles(false); if (null !== $key && null === $data = $data->seek($key)) { return; } From a1cdc2d46e894d123c527bf204f18d4675163335 Mon Sep 17 00:00:00 2001 From: Maxime Steinhausser Date: Mon, 5 Jun 2017 22:05:32 +0200 Subject: [PATCH 0153/1099] [TwigBridge] Fix namespaced classes --- .../NodeVisitor/TranslationDefaultDomainNodeVisitor.php | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Bridge/Twig/NodeVisitor/TranslationDefaultDomainNodeVisitor.php b/src/Symfony/Bridge/Twig/NodeVisitor/TranslationDefaultDomainNodeVisitor.php index c69ca843e83ea..b3c89d18eb2bd 100644 --- a/src/Symfony/Bridge/Twig/NodeVisitor/TranslationDefaultDomainNodeVisitor.php +++ b/src/Symfony/Bridge/Twig/NodeVisitor/TranslationDefaultDomainNodeVisitor.php @@ -14,6 +14,7 @@ use Symfony\Bridge\Twig\Node\TransNode; use Symfony\Bridge\Twig\Node\TransDefaultDomainNode; use Twig\Environment; +use Twig\Node\BlockNode; use Twig\Node\Expression\ArrayExpression; use Twig\Node\Expression\AssignNameExpression; use Twig\Node\Expression\ConstantExpression; @@ -21,6 +22,7 @@ use Twig\Node\Expression\NameExpression; use Twig\Node\ModuleNode; use Twig\Node\Node; +use Twig\Node\SetNode; use Twig\NodeVisitor\AbstractNodeVisitor; /** @@ -48,7 +50,7 @@ public function __construct() */ protected function doEnterNode(Node $node, Environment $env) { - if ($node instanceof Node_Block || $node instanceof ModuleNode) { + if ($node instanceof BlockNode || $node instanceof ModuleNode) { $this->scope = $this->scope->enter(); } @@ -62,7 +64,7 @@ protected function doEnterNode(Node $node, Environment $env) $name = new AssignNameExpression($var, $node->getTemplateLine()); $this->scope->set('domain', new NameExpression($var, $node->getTemplateLine())); - return new Node_Set(false, new Node(array($name)), new Node(array($node->getNode('expr'))), $node->getTemplateLine()); + return new SetNode(false, new Node(array($name)), new Node(array($node->getNode('expr'))), $node->getTemplateLine()); } } @@ -104,7 +106,7 @@ protected function doLeaveNode(Node $node, Environment $env) return false; } - if ($node instanceof Node_Block || $node instanceof ModuleNode) { + if ($node instanceof BlockNode || $node instanceof ModuleNode) { $this->scope = $this->scope->leave(); } From c1a645596536d5d2476be3070440319a9c37a163 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Mon, 5 Jun 2017 20:59:50 -0700 Subject: [PATCH 0154/1099] updated CHANGELOG for 3.3.2 --- CHANGELOG-3.3.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/CHANGELOG-3.3.md b/CHANGELOG-3.3.md index 8a6626da32d0f..6c3cb3540ff0c 100644 --- a/CHANGELOG-3.3.md +++ b/CHANGELOG-3.3.md @@ -7,6 +7,13 @@ in 3.3 minor versions. To get the diff for a specific change, go to https://github.com/symfony/symfony/commit/XXX where XXX is the change hash To get the diff between two versions, go to https://github.com/symfony/symfony/compare/v3.3.0...v3.3.1 +* 3.3.2 (2017-06-06) + + * bug #23073 [TwigBridge] Fix namespaced classes (ogizanagi) + * bug #23063 [Cache] Fix extensibility of TagAwareAdapter::TAGS_PREFIX (wucdbm) + * bug #22936 [Form] Mix attr option between guessed options and user options (yceruto) + * bug #22976 [DependencyInjection] Use more clear message when unused environment variables detected (voronkovich) + * 3.3.1 (2017-06-05) * bug #23067 [HttpFoundation][FrameworkBundle] Revert "trusted proxies" BC break (nicolas-grekas) From adf3a020e00f7e10b6c42808277efbeb972c7c22 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Mon, 5 Jun 2017 20:59:58 -0700 Subject: [PATCH 0155/1099] updated VERSION for 3.3.2 --- 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 85c7b2720184b..0cab79884c08c 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -61,12 +61,12 @@ abstract class Kernel implements KernelInterface, TerminableInterface private $projectDir; - const VERSION = '3.3.2-DEV'; + const VERSION = '3.3.2'; const VERSION_ID = 30302; const MAJOR_VERSION = 3; const MINOR_VERSION = 3; const RELEASE_VERSION = 2; - const EXTRA_VERSION = 'DEV'; + const EXTRA_VERSION = ''; const END_OF_MAINTENANCE = '01/2018'; const END_OF_LIFE = '07/2018'; From f322107d64f574f5832c8695d962ce23d6ed30a6 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Mon, 5 Jun 2017 21:14:06 -0700 Subject: [PATCH 0156/1099] bumped Symfony version to 3.3.3 --- 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 0cab79884c08c..081e0e7bbaa21 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -61,12 +61,12 @@ abstract class Kernel implements KernelInterface, TerminableInterface private $projectDir; - const VERSION = '3.3.2'; - const VERSION_ID = 30302; + const VERSION = '3.3.3-DEV'; + const VERSION_ID = 30303; const MAJOR_VERSION = 3; const MINOR_VERSION = 3; - const RELEASE_VERSION = 2; - const EXTRA_VERSION = ''; + const RELEASE_VERSION = 3; + const EXTRA_VERSION = 'DEV'; const END_OF_MAINTENANCE = '01/2018'; const END_OF_LIFE = '07/2018'; From f1edfa7ec22c52b07882cdc2ff2b2d7092fe7f65 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9goire=20Pineau?= Date: Tue, 6 Jun 2017 17:10:52 +0200 Subject: [PATCH 0157/1099] [MonologBridge] Do not silence errors in ServerLogHandler::formatRecord --- src/Symfony/Bridge/Monolog/Handler/ServerLogHandler.php | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Bridge/Monolog/Handler/ServerLogHandler.php b/src/Symfony/Bridge/Monolog/Handler/ServerLogHandler.php index fb258808f3836..d1d4968df4cda 100644 --- a/src/Symfony/Bridge/Monolog/Handler/ServerLogHandler.php +++ b/src/Symfony/Bridge/Monolog/Handler/ServerLogHandler.php @@ -51,9 +51,15 @@ public function handle(array $record) if (!$this->socket = $this->socket ?: $this->createSocket()) { return false === $this->bubble; } + } finally { + restore_error_handler(); + } - $recordFormatted = $this->formatRecord($record); + $recordFormatted = $this->formatRecord($record); + set_error_handler(self::class.'::nullErrorHandler'); + + try { if (-1 === stream_socket_sendto($this->socket, $recordFormatted)) { stream_socket_shutdown($this->socket, STREAM_SHUT_RDWR); From b58f060fda0953139abc4b9ff99ff4878e3d4638 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Wed, 7 Jun 2017 09:53:54 +0200 Subject: [PATCH 0158/1099] [FrameworkBundle] Fix perf issue in CacheClearCommand::warmup() --- .../FrameworkBundle/Command/CacheClearCommand.php | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/CacheClearCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/CacheClearCommand.php index 84c2fae7d4db8..5e9014bfc5ddd 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/CacheClearCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/CacheClearCommand.php @@ -141,7 +141,7 @@ protected function warmup($warmupDir, $realCacheDir, $enableOptionalWarmers = tr $safeTempKernel = str_replace('\\', '\\\\', get_class($tempKernel)); $realKernelFQN = get_class($realKernel); - foreach (Finder::create()->files()->name('*.meta')->in($warmupDir) as $file) { + foreach (Finder::create()->files()->depth('<3')->name('*.meta')->in($warmupDir) as $file) { file_put_contents($file, preg_replace( '/(C\:\d+\:)"'.$safeTempKernel.'"/', sprintf('$1"%s"', $realKernelFQN), @@ -153,14 +153,16 @@ protected function warmup($warmupDir, $realCacheDir, $enableOptionalWarmers = tr $search = array($warmupDir, str_replace('\\', '\\\\', $warmupDir)); $replace = str_replace('\\', '/', $realCacheDir); foreach (Finder::create()->files()->in($warmupDir) as $file) { - $content = str_replace($search, $replace, file_get_contents($file)); - file_put_contents($file, $content); + $content = str_replace($search, $replace, file_get_contents($file), $count); + if ($count) { + file_put_contents($file, $content); + } } // fix references to container's class $tempContainerClass = get_class($tempKernel->getContainer()); $realContainerClass = get_class($realKernel->getContainer()); - foreach (Finder::create()->files()->name($tempContainerClass.'*')->in($warmupDir) as $file) { + foreach (Finder::create()->files()->depth('<2')->name($tempContainerClass.'*')->in($warmupDir) as $file) { $content = str_replace($tempContainerClass, $realContainerClass, file_get_contents($file)); file_put_contents($file, $content); rename($file, str_replace(DIRECTORY_SEPARATOR.$tempContainerClass, DIRECTORY_SEPARATOR.$realContainerClass, $file)); From c2f796fa1501107a2328a89723e7e73994b317e0 Mon Sep 17 00:00:00 2001 From: Guilhem Niot Date: Fri, 2 Jun 2017 20:02:43 +0200 Subject: [PATCH 0159/1099] Automatically enable the routing annotation loader --- composer.json | 3 +- .../Bundle/FrameworkBundle/CHANGELOG.md | 2 +- .../FrameworkExtension.php | 26 ++++++++++ .../AnnotatedRouteControllerLoader.php | 52 +++++++++++++++++++ .../app/AnnotatedController/bundles.php | 2 - .../Bundle/FrameworkBundle/composer.json | 5 +- src/Symfony/Component/Routing/CHANGELOG.md | 7 ++- .../RoutingResolverPass.php | 5 +- 8 files changed, 92 insertions(+), 10 deletions(-) create mode 100644 src/Symfony/Bundle/FrameworkBundle/Routing/AnnotatedRouteControllerLoader.php diff --git a/composer.json b/composer.json index b664499252911..68f1d35058f4f 100644 --- a/composer.json +++ b/composer.json @@ -98,8 +98,7 @@ "symfony/phpunit-bridge": "~3.2", "symfony/polyfill-apcu": "~1.1", "symfony/security-acl": "~2.8|~3.0", - "phpdocumentor/reflection-docblock": "^3.0", - "sensio/framework-extra-bundle": "^3.0.2" + "phpdocumentor/reflection-docblock": "^3.0" }, "conflict": { "phpdocumentor/reflection-docblock": "<3.0", diff --git a/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md b/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md index d25f4547d3123..f44ba083c3464 100644 --- a/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md +++ b/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md @@ -48,7 +48,7 @@ CHANGELOG `Symfony\Component\Validator\DependencyInjection\AddConstraintValidatorsPass` instead * Deprecated `ValidateWorkflowsPass`, use `Symfony\Component\Workflow\DependencyInjection\ValidateWorkflowsPass` instead - * Deprecated `ConstraintValidatorFactory`, use + * Deprecated `ConstraintValidatorFactory`, use `Symfony\Component\Validator\ContainerConstraintValidatorFactory` instead. 3.2.0 diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php index 1fda255004e4c..e9dbe33a7a080 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php @@ -15,6 +15,7 @@ use Symfony\Bridge\Monolog\Processor\DebugProcessor; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Bundle\FrameworkBundle\Controller\Controller; +use Symfony\Bundle\FrameworkBundle\Routing\AnnotatedRouteControllerLoader; use Symfony\Component\Cache\Adapter\AdapterInterface; use Symfony\Component\Cache\Adapter\ArrayAdapter; use Symfony\Component\Config\FileLocator; @@ -48,6 +49,8 @@ use Symfony\Component\PropertyInfo\PropertyDescriptionExtractorInterface; use Symfony\Component\PropertyInfo\PropertyListExtractorInterface; use Symfony\Component\PropertyInfo\PropertyTypeExtractorInterface; +use Symfony\Component\Routing\Loader\AnnotationDirectoryLoader; +use Symfony\Component\Routing\Loader\AnnotationFileLoader; use Symfony\Component\Serializer\Encoder\CsvEncoder; use Symfony\Component\Serializer\Encoder\DecoderInterface; use Symfony\Component\Serializer\Encoder\EncoderInterface; @@ -692,6 +695,29 @@ private function registerRouterConfiguration(array $config, ContainerBuilder $co $container->findDefinition('router.default')->getClass(), )); } + + if ($this->annotationsConfigEnabled) { + $container->register('routing.loader.annotation', AnnotatedRouteControllerLoader::class) + ->setPublic(false) + ->addTag('routing.loader', array('priority' => -10)) + ->addArgument(new Reference('annotation_reader')); + + $container->register('routing.loader.directory', AnnotationDirectoryLoader::class) + ->setPublic(false) + ->addTag('routing.loader', array('priority' => -10)) + ->setArguments(array( + new Reference('file_locator'), + new Reference('routing.loader.annotation'), + )); + + $container->register('routing.loader.file', AnnotationFileLoader::class) + ->setPublic(false) + ->addTag('routing.loader', array('priority' => -10)) + ->setArguments(array( + new Reference('file_locator'), + new Reference('routing.loader.annotation'), + )); + } } /** diff --git a/src/Symfony/Bundle/FrameworkBundle/Routing/AnnotatedRouteControllerLoader.php b/src/Symfony/Bundle/FrameworkBundle/Routing/AnnotatedRouteControllerLoader.php new file mode 100644 index 0000000000000..f5777af95a7e5 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Routing/AnnotatedRouteControllerLoader.php @@ -0,0 +1,52 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\FrameworkBundle\Routing; + +use Symfony\Component\Routing\Loader\AnnotationClassLoader; +use Symfony\Component\Routing\Route; + +/** + * AnnotatedRouteControllerLoader is an implementation of AnnotationClassLoader + * that sets the '_controller' default based on the class and method names. + * + * @author Fabien Potencier + */ +class AnnotatedRouteControllerLoader extends AnnotationClassLoader +{ + /** + * Configures the _controller default parameter of a given Route instance. + * + * @param mixed $annot The annotation class instance + */ + protected function configureRoute(Route $route, \ReflectionClass $class, \ReflectionMethod $method, $annot) + { + $route->setDefault('_controller', $class->getName().'::'.$method->getName()); + } + + /** + * Makes the default route name more sane by removing common keywords. + * + * @return string + */ + protected function getDefaultRouteName(\ReflectionClass $class, \ReflectionMethod $method) + { + return preg_replace(array( + '/(bundle|controller)_/', + '/action(_\d+)?$/', + '/__/', + ), array( + '_', + '\\1', + '_', + ), parent::getDefaultRouteName($class, $method)); + } +} diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/AnnotatedController/bundles.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/AnnotatedController/bundles.php index f3290d7728541..a73987bcc986a 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/AnnotatedController/bundles.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/AnnotatedController/bundles.php @@ -11,10 +11,8 @@ use Symfony\Bundle\FrameworkBundle\Tests\Functional\Bundle\TestBundle\TestBundle; use Symfony\Bundle\FrameworkBundle\FrameworkBundle; -use Sensio\Bundle\FrameworkExtraBundle\SensioFrameworkExtraBundle; return array( new FrameworkBundle(), new TestBundle(), - new SensioFrameworkExtraBundle(), ); diff --git a/src/Symfony/Bundle/FrameworkBundle/composer.json b/src/Symfony/Bundle/FrameworkBundle/composer.json index d7b5f20a6771c..2b11a0d737d31 100644 --- a/src/Symfony/Bundle/FrameworkBundle/composer.json +++ b/src/Symfony/Bundle/FrameworkBundle/composer.json @@ -28,7 +28,7 @@ "symfony/polyfill-mbstring": "~1.0", "symfony/filesystem": "~2.8|~3.0|~4.0", "symfony/finder": "~2.8|~3.0|~4.0", - "symfony/routing": "~3.3|~4.0", + "symfony/routing": "~3.4|~4.0", "symfony/stopwatch": "~2.8|~3.0|~4.0", "doctrine/cache": "~1.0" }, @@ -57,8 +57,7 @@ "symfony/web-link": "~3.3|~4.0", "doctrine/annotations": "~1.0", "phpdocumentor/reflection-docblock": "^3.0", - "twig/twig": "~1.34|~2.4", - "sensio/framework-extra-bundle": "^3.0.2" + "twig/twig": "~1.34|~2.4" }, "conflict": { "phpdocumentor/reflection-docblock": "<3.0", diff --git a/src/Symfony/Component/Routing/CHANGELOG.md b/src/Symfony/Component/Routing/CHANGELOG.md index d04581f405069..07f8280fe51ed 100644 --- a/src/Symfony/Component/Routing/CHANGELOG.md +++ b/src/Symfony/Component/Routing/CHANGELOG.md @@ -1,6 +1,11 @@ CHANGELOG ========= +3.4.0 +----- + + * Added support for prioritized routing loaders. + 3.3.0 ----- @@ -19,7 +24,7 @@ CHANGELOG * Added support for `bool`, `int`, `float`, `string`, `list` and `map` defaults in XML configurations. * Added support for UTF-8 requirements - + 2.8.0 ----- diff --git a/src/Symfony/Component/Routing/DependencyInjection/RoutingResolverPass.php b/src/Symfony/Component/Routing/DependencyInjection/RoutingResolverPass.php index 73a8f8511dafd..4af0a5a28668b 100644 --- a/src/Symfony/Component/Routing/DependencyInjection/RoutingResolverPass.php +++ b/src/Symfony/Component/Routing/DependencyInjection/RoutingResolverPass.php @@ -14,6 +14,7 @@ use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; +use Symfony\Component\DependencyInjection\Compiler\PriorityTaggedServiceTrait; /** * Adds tagged routing.loader services to routing.resolver service. @@ -22,6 +23,8 @@ */ class RoutingResolverPass implements CompilerPassInterface { + use PriorityTaggedServiceTrait; + private $resolverServiceId; private $loaderTag; @@ -39,7 +42,7 @@ public function process(ContainerBuilder $container) $definition = $container->getDefinition($this->resolverServiceId); - foreach ($container->findTaggedServiceIds($this->loaderTag, true) as $id => $attributes) { + foreach ($this->findAndSortTaggedServices($this->loaderTag, $container) as $id) { $definition->addMethodCall('addLoader', array(new Reference($id))); } } From 4442c636c848dafdd251760a7569a158de869a67 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Wed, 7 Jun 2017 12:41:51 +0200 Subject: [PATCH 0160/1099] [SecurityBundle] Made 2 service aliases private --- .../Bundle/SecurityBundle/Resources/config/security.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Bundle/SecurityBundle/Resources/config/security.xml b/src/Symfony/Bundle/SecurityBundle/Resources/config/security.xml index 4b7dba5e45be8..79435ff5d4619 100644 --- a/src/Symfony/Bundle/SecurityBundle/Resources/config/security.xml +++ b/src/Symfony/Bundle/SecurityBundle/Resources/config/security.xml @@ -19,7 +19,7 @@ %security.access.always_authenticate_before_granting% - + @@ -59,7 +59,7 @@ - + From 60f50466618aa1d86970205779d81242ddc5cba3 Mon Sep 17 00:00:00 2001 From: Guilhem Niot Date: Thu, 25 May 2017 11:38:18 +0200 Subject: [PATCH 0161/1099] [Yaml] Deprecate using the non-specific tag --- UPGRADE-3.4.md | 8 +++++++- UPGRADE-4.0.md | 3 +++ src/Symfony/Component/Yaml/CHANGELOG.md | 6 ++++++ src/Symfony/Component/Yaml/Inline.php | 2 ++ .../Yaml/Tests/Fixtures/YtsSpecificationExamples.yml | 1 + src/Symfony/Component/Yaml/Tests/ParserTest.php | 2 +- 6 files changed, 20 insertions(+), 2 deletions(-) diff --git a/UPGRADE-3.4.md b/UPGRADE-3.4.md index 21db4d1ed6194..84ff3ac3724ef 100644 --- a/UPGRADE-3.4.md +++ b/UPGRADE-3.4.md @@ -10,7 +10,7 @@ Finder ------ * The `Symfony\Component\Finder\Iterator\FilterIterator` class has been - deprecated and will be removed in 4.0 as it used to fix a bug which existed + deprecated and will be removed in 4.0 as it used to fix a bug which existed before version 5.5.23/5.6.7. Validator @@ -18,3 +18,9 @@ Validator * Not setting the `strict` option of the `Choice` constraint to `true` is deprecated and will throw an exception in Symfony 4.0. + +Yaml +---- + + * Using the non-specific tag `!` is deprecated and will have a different + behavior in 4.0. Use a plain integer or `!!float` instead. diff --git a/UPGRADE-4.0.md b/UPGRADE-4.0.md index 9bf6e0bda02a2..8a7bf84b73209 100644 --- a/UPGRADE-4.0.md +++ b/UPGRADE-4.0.md @@ -685,3 +685,6 @@ Yaml * The constructor arguments `$offset`, `$totalNumberOfLines` and `$skippedLineNumbers` of the `Parser` class were removed. + + * The behavior of the non-specific tag `!` is changed and now forces + non-evaluating your values. diff --git a/src/Symfony/Component/Yaml/CHANGELOG.md b/src/Symfony/Component/Yaml/CHANGELOG.md index 892910c832794..172544aa97a8b 100644 --- a/src/Symfony/Component/Yaml/CHANGELOG.md +++ b/src/Symfony/Component/Yaml/CHANGELOG.md @@ -1,6 +1,12 @@ CHANGELOG ========= +3.4.0 +----- + + * Deprecated using the non-specific tag `!` as its behavior will change in 4.0. + It will force non-evaluating your values in 4.0. Use plain integers or `!!float` instead. + 3.3.0 ----- diff --git a/src/Symfony/Component/Yaml/Inline.php b/src/Symfony/Component/Yaml/Inline.php index 7ad53692eb000..73a2c6c21a238 100644 --- a/src/Symfony/Component/Yaml/Inline.php +++ b/src/Symfony/Component/Yaml/Inline.php @@ -611,6 +611,8 @@ private static function evaluateScalar($scalar, $flags, $references = array()) case 0 === strpos($scalar, '!str'): return (string) substr($scalar, 5); case 0 === strpos($scalar, '! '): + @trigger_error('Using the non-specific tag "!" is deprecated since version 3.4 as its behavior will change in 4.0. It will force non-evaluating your values in 4.0. Use plain integers or !!float instead.', E_USER_DEPRECATED); + return (int) self::parseScalar(substr($scalar, 2), $flags); case 0 === strpos($scalar, '!php/object:'): if (self::$objectSupport) { diff --git a/src/Symfony/Component/Yaml/Tests/Fixtures/YtsSpecificationExamples.yml b/src/Symfony/Component/Yaml/Tests/Fixtures/YtsSpecificationExamples.yml index 45e27b7b7410e..fbdfffcc690d5 100644 --- a/src/Symfony/Component/Yaml/Tests/Fixtures/YtsSpecificationExamples.yml +++ b/src/Symfony/Component/Yaml/Tests/Fixtures/YtsSpecificationExamples.yml @@ -928,6 +928,7 @@ documents: 2 --- test: Explicit typing +deprecated: Using the non-specific tag "!" is deprecated since version 3.4 as its behavior will change in 4.0. yaml: | integer: 12 also int: ! "12" diff --git a/src/Symfony/Component/Yaml/Tests/ParserTest.php b/src/Symfony/Component/Yaml/Tests/ParserTest.php index a6c7b6ad12aff..c3fff335eb643 100644 --- a/src/Symfony/Component/Yaml/Tests/ParserTest.php +++ b/src/Symfony/Component/Yaml/Tests/ParserTest.php @@ -61,7 +61,7 @@ public function testSpecifications($expected, $yaml, $comment, $deprecated) restore_error_handler(); $this->assertCount(1, $deprecations); - $this->assertContains('Using the comma as a group separator for floats is deprecated since version 3.2 and will be removed in 4.0.', $deprecations[0]); + $this->assertContains(true !== $deprecated ? $deprecated : 'Using the comma as a group separator for floats is deprecated since version 3.2 and will be removed in 4.0.', $deprecations[0]); } } From 5d13f0dfacb829536472ea2515671c3a63139a99 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Wed, 7 Jun 2017 11:49:46 -0700 Subject: [PATCH 0162/1099] updated CHANGELOG for 2.7.29 --- CHANGELOG-2.7.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/CHANGELOG-2.7.md b/CHANGELOG-2.7.md index fb402c9aaf2ca..c93959532d398 100644 --- a/CHANGELOG-2.7.md +++ b/CHANGELOG-2.7.md @@ -7,6 +7,15 @@ in 2.7 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/v2.7.0...v2.7.1 +* 2.7.29 (2017-06-07) + + * bug #23069 [SecurityBundle] Show unique Inherited roles in profile panel (yceruto) + * bug #23073 [TwigBridge] Fix namespaced classes (ogizanagi) + * bug #22936 [Form] Mix attr option between guessed options and user options (yceruto) + * bug #23024 [EventDispatcher] Fix ContainerAwareEventDispatcher::hasListeners(null) (nicolas-grekas) + * bug #22996 [Form] Fix \IntlDateFormatter timezone parameter usage to bypass PHP bug #66323 (romainneutron) + * bug #22994 Harden the debugging of Twig filters and functions (stof) + * 2.7.28 (2017-05-29) * bug #22847 [Console] ChoiceQuestion must have choices (ro0NL) From fc56c4ed8cc1484d114124a28482fe96e74f5c76 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Wed, 7 Jun 2017 11:50:25 -0700 Subject: [PATCH 0163/1099] update CONTRIBUTORS for 2.7.29 --- CONTRIBUTORS.md | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index 66212cf3bf4c4..532b8a261c4f2 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -20,13 +20,13 @@ Symfony is the result of the work of many people who made the code better - Javier Eguiluz (javier.eguiluz) - Hugo Hamon (hhamon) - Abdellatif Ait boudad (aitboudad) + - Romain Neutron (romain) - Pascal Borreli (pborreli) - Wouter De Jong (wouterj) - - Romain Neutron (romain) - - Grégoire Pineau (lyrixx) - Robin Chalas (chalas_r) - - Joseph Bielawski (stloyd) - Maxime Steinhausser (ogizanagi) + - Grégoire Pineau (lyrixx) + - Joseph Bielawski (stloyd) - Karma Dordrak (drak) - Lukas Kahwe Smith (lsmith) - Martin Hasoň (hason) @@ -72,8 +72,8 @@ Symfony is the result of the work of many people who made the code better - Dariusz Górecki (canni) - Titouan Galopin (tgalopin) - Douglas Greenshields (shieldo) - - Konstantin Myakshin (koc) - Jáchym Toušek (enumag) + - Konstantin Myakshin (koc) - Lee McDermott - Brandon Turner - Luis Cordova (cordoval) @@ -112,10 +112,10 @@ Symfony is the result of the work of many people who made the code better - Jacob Dreesen (jdreesen) - Tobias Nyholm (tobias) - Tomáš Votruba (tomas_votruba) + - Yonel Ceruto González (yonelceruto) - Fabien Pennequin (fabienpennequin) - Gordon Franke (gimler) - Eric GELOEN (gelo) - - Yonel Ceruto González (yonelceruto) - Daniel Wehner (dawehner) - Tugdual Saunier (tucksaun) - Théo FIDRY (theofidry) @@ -130,6 +130,7 @@ Symfony is the result of the work of many people who made the code better - Daniel Gomes (danielcsgomes) - Hidenori Goto (hidenorigoto) - Guilherme Blanco (guilhermeblanco) + - Vincent AUBERT (vincent) - Pablo Godel (pgodel) - Jérémie Augustin (jaugustin) - Andréia Bohner (andreia) @@ -140,10 +141,10 @@ Symfony is the result of the work of many people who made the code better - Joel Wurtz (brouznouf) - Philipp Wahala (hifi) - Vyacheslav Pavlov + - Richard van Laak (rvanlaak) - Javier Spagnoletti (phansys) - Richard Shank (iampersistent) - Thomas Rabaix (rande) - - Vincent AUBERT (vincent) - Rouven Weßling (realityking) - Teoh Han Hui (teohhanhui) - Jérôme Vasseur (jvasseur) @@ -151,7 +152,6 @@ Symfony is the result of the work of many people who made the code better - Helmer Aaviksoo - Grégoire Paris (greg0ire) - Hiromi Hishida (77web) - - Richard van Laak (rvanlaak) - Matthieu Ouellette-Vachon (maoueh) - Michał Pipa (michal.pipa) - Amal Raghav (kertz) @@ -242,6 +242,7 @@ Symfony is the result of the work of many people who made the code better - Uwe Jäger (uwej711) - Eugene Leonovich (rybakit) - Filippo Tessarotto + - Oleg Voronkovich - Joseph Rouff (rouffj) - Félix Labrecque (woodspire) - GordonsLondon @@ -277,7 +278,6 @@ Symfony is the result of the work of many people who made the code better - Jordan Samouh (jordansamouh) - Chris Smith (cs278) - Florian Klein (docteurklein) - - Oleg Voronkovich - Manuel Kiessling (manuelkiessling) - Atsuhiro KUBO (iteman) - Andrew Moore (finewolf) @@ -387,6 +387,7 @@ Symfony is the result of the work of many people who made the code better - Emanuele Gaspari (inmarelibero) - Sébastien Santoro (dereckson) - Brian King + - Frank de Jonge (frenkynet) - Michel Salib (michelsalib) - geoffrey - Steffen Roßkamp @@ -523,7 +524,6 @@ Symfony is the result of the work of many people who made the code better - Romain Pierre (romain-pierre) - Jan Behrens - Mantas Var (mvar) - - Frank de Jonge (frenkynet) - Sebastian Krebs - Jean-Christophe Cuvelier [Artack] - Christopher Davis (chrisguitarguy) @@ -1278,6 +1278,7 @@ Symfony is the result of the work of many people who made the code better - ged15 - Daan van Renterghem - Nicole Cordes + - Martin Kirilov - Bram Van der Sype (brammm) - Christopher Hertel (chertel) - Guile (guile) From c713d698278c665065d5a06102a202d97bd566b3 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Wed, 7 Jun 2017 11:50:32 -0700 Subject: [PATCH 0164/1099] updated VERSION for 2.7.29 --- 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 d20b6e2a16aed..0ffd46d11f7b1 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -58,12 +58,12 @@ abstract class Kernel implements KernelInterface, TerminableInterface protected $startTime; protected $loadClassCache; - const VERSION = '2.7.29-DEV'; + const VERSION = '2.7.29'; const VERSION_ID = 20729; const MAJOR_VERSION = 2; const MINOR_VERSION = 7; const RELEASE_VERSION = 29; - const EXTRA_VERSION = 'DEV'; + const EXTRA_VERSION = ''; const END_OF_MAINTENANCE = '05/2018'; const END_OF_LIFE = '05/2019'; From bcb80569cb23c74ab500d0507f25db4eb1a45cf3 Mon Sep 17 00:00:00 2001 From: Gonzalo Vilaseca Date: Wed, 7 Jun 2017 20:32:30 +0100 Subject: [PATCH 0165/1099] Cache ipCheck --- .../Component/HttpFoundation/IpUtils.php | 28 +++++++++++++------ 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/src/Symfony/Component/HttpFoundation/IpUtils.php b/src/Symfony/Component/HttpFoundation/IpUtils.php index 28093be43403f..eba603b15df01 100644 --- a/src/Symfony/Component/HttpFoundation/IpUtils.php +++ b/src/Symfony/Component/HttpFoundation/IpUtils.php @@ -18,6 +18,8 @@ */ class IpUtils { + private static $checkedIps = array(); + /** * This class should not be instantiated. */ @@ -61,26 +63,31 @@ public static function checkIp($requestIp, $ips) */ public static function checkIp4($requestIp, $ip) { + $cacheKey = $requestIp.'-'.$ip; + if (isset(self::$checkedIps[$cacheKey])) { + return self::$checkedIps[$cacheKey]; + } + if (!filter_var($requestIp, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) { - return false; + return self::$checkedIps[$cacheKey] = false; } if (false !== strpos($ip, '/')) { list($address, $netmask) = explode('/', $ip, 2); if ($netmask === '0') { - return filter_var($address, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4); + return self::$checkedIps[$cacheKey] = filter_var($address, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4); } if ($netmask < 0 || $netmask > 32) { - return false; + return self::$checkedIps[$cacheKey] = false; } } else { $address = $ip; $netmask = 32; } - return 0 === substr_compare(sprintf('%032b', ip2long($requestIp)), sprintf('%032b', ip2long($address)), 0, $netmask); + return self::$checkedIps[$cacheKey] = 0 === substr_compare(sprintf('%032b', ip2long($requestIp)), sprintf('%032b', ip2long($address)), 0, $netmask); } /** @@ -100,6 +107,11 @@ public static function checkIp4($requestIp, $ip) */ public static function checkIp6($requestIp, $ip) { + $cacheKey = $requestIp.'-'.$ip; + if (isset(self::$checkedIps[$cacheKey])) { + return self::$checkedIps[$cacheKey]; + } + if (!((extension_loaded('sockets') && defined('AF_INET6')) || @inet_pton('::1'))) { throw new \RuntimeException('Unable to check Ipv6. Check that PHP was not compiled with option "disable-ipv6".'); } @@ -108,7 +120,7 @@ public static function checkIp6($requestIp, $ip) list($address, $netmask) = explode('/', $ip, 2); if ($netmask < 1 || $netmask > 128) { - return false; + return self::$checkedIps[$cacheKey] = false; } } else { $address = $ip; @@ -119,7 +131,7 @@ public static function checkIp6($requestIp, $ip) $bytesTest = unpack('n*', @inet_pton($requestIp)); if (!$bytesAddr || !$bytesTest) { - return false; + return self::$checkedIps[$cacheKey] = false; } for ($i = 1, $ceil = ceil($netmask / 16); $i <= $ceil; ++$i) { @@ -127,10 +139,10 @@ public static function checkIp6($requestIp, $ip) $left = ($left <= 16) ? $left : 16; $mask = ~(0xffff >> $left) & 0xffff; if (($bytesAddr[$i] & $mask) != ($bytesTest[$i] & $mask)) { - return false; + return self::$checkedIps[$cacheKey] = false; } } - return true; + return self::$checkedIps[$cacheKey] = true; } } From ccb6543839c8800841b6721a8581f6a7b9e42158 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Wed, 7 Jun 2017 13:11:41 -0700 Subject: [PATCH 0166/1099] bumped Symfony version to 2.7.30 --- 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 0ffd46d11f7b1..6b540518fcbc4 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -58,12 +58,12 @@ abstract class Kernel implements KernelInterface, TerminableInterface protected $startTime; protected $loadClassCache; - const VERSION = '2.7.29'; - const VERSION_ID = 20729; + const VERSION = '2.7.30-DEV'; + const VERSION_ID = 20730; const MAJOR_VERSION = 2; const MINOR_VERSION = 7; - const RELEASE_VERSION = 29; - const EXTRA_VERSION = ''; + const RELEASE_VERSION = 30; + const EXTRA_VERSION = 'DEV'; const END_OF_MAINTENANCE = '05/2018'; const END_OF_LIFE = '05/2019'; From a9f289abbc556a5e21c1889ab1c4efbf3a6521c4 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Wed, 7 Jun 2017 13:12:24 -0700 Subject: [PATCH 0167/1099] updated CHANGELOG for 2.8.22 --- CHANGELOG-2.8.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/CHANGELOG-2.8.md b/CHANGELOG-2.8.md index b73a0f1a2b18b..da6f2aeebb9fb 100644 --- a/CHANGELOG-2.8.md +++ b/CHANGELOG-2.8.md @@ -7,6 +7,16 @@ in 2.8 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/v2.8.0...v2.8.1 +* 2.8.22 (2017-06-07) + + * bug #23073 [TwigBridge] Fix namespaced classes (ogizanagi) + * bug #22936 [Form] Mix attr option between guessed options and user options (yceruto) + * bug #22988 [PropertyInfo][DoctrineBridge] The bigint Doctrine's type must be converted to string (dunglas) + * bug #23014 Fix optional cache warmers are always instantiated whereas they should be lazy-loaded (romainneutron) + * bug #23024 [EventDispatcher] Fix ContainerAwareEventDispatcher::hasListeners(null) (nicolas-grekas) + * bug #22996 [Form] Fix \IntlDateFormatter timezone parameter usage to bypass PHP bug #66323 (romainneutron) + * bug #22994 Harden the debugging of Twig filters and functions (stof) + * 2.8.21 (2017-05-29) * bug #22847 [Console] ChoiceQuestion must have choices (ro0NL) From 0d52ccb5ff8b757265537e74cef4b82ac52ea87d Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Wed, 7 Jun 2017 13:12:31 -0700 Subject: [PATCH 0168/1099] updated VERSION for 2.8.22 --- 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 ed7d33b583903..97e83f8d59c80 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -59,12 +59,12 @@ abstract class Kernel implements KernelInterface, TerminableInterface protected $startTime; protected $loadClassCache; - const VERSION = '2.8.22-DEV'; + const VERSION = '2.8.22'; const VERSION_ID = 20822; const MAJOR_VERSION = 2; const MINOR_VERSION = 8; const RELEASE_VERSION = 22; - const EXTRA_VERSION = 'DEV'; + const EXTRA_VERSION = ''; const END_OF_MAINTENANCE = '11/2018'; const END_OF_LIFE = '11/2019'; From e8497bb57d95fe96c0660c9a559c77182e9302f3 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Wed, 7 Jun 2017 13:30:46 -0700 Subject: [PATCH 0169/1099] bumped Symfony version to 2.8.23 --- 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 97e83f8d59c80..37e10de8c64c4 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -59,12 +59,12 @@ abstract class Kernel implements KernelInterface, TerminableInterface protected $startTime; protected $loadClassCache; - const VERSION = '2.8.22'; - const VERSION_ID = 20822; + const VERSION = '2.8.23-DEV'; + const VERSION_ID = 20823; const MAJOR_VERSION = 2; const MINOR_VERSION = 8; - const RELEASE_VERSION = 22; - const EXTRA_VERSION = ''; + const RELEASE_VERSION = 23; + const EXTRA_VERSION = 'DEV'; const END_OF_MAINTENANCE = '11/2018'; const END_OF_LIFE = '11/2019'; From 45b961de2eec3faaebfaea9a1ebde32ec1488efe Mon Sep 17 00:00:00 2001 From: tsufeki Date: Wed, 7 Jun 2017 21:53:51 +0200 Subject: [PATCH 0170/1099] [PropertyAccess] Do not silence TypeErrors from client code. --- .../PropertyAccess/PropertyAccessor.php | 3 ++ .../Fixtures/TestClassTypeErrorInsideCall.php | 28 +++++++++++++++++++ .../Tests/PropertyAccessorTest.php | 12 ++++++++ 3 files changed, 43 insertions(+) create mode 100644 src/Symfony/Component/PropertyAccess/Tests/Fixtures/TestClassTypeErrorInsideCall.php diff --git a/src/Symfony/Component/PropertyAccess/PropertyAccessor.php b/src/Symfony/Component/PropertyAccess/PropertyAccessor.php index 69d7fc0e9f1aa..cd572d21b5d97 100644 --- a/src/Symfony/Component/PropertyAccess/PropertyAccessor.php +++ b/src/Symfony/Component/PropertyAccess/PropertyAccessor.php @@ -244,6 +244,9 @@ public function setValue(&$objectOrArray, $propertyPath, $value) } } catch (\TypeError $e) { self::throwInvalidArgumentException($e->getMessage(), $e->getTrace(), 0); + + // It wasn't thrown in this class so rethrow it + throw $e; } finally { if (\PHP_VERSION_ID < 70000 && false !== self::$previousErrorHandler) { restore_error_handler(); diff --git a/src/Symfony/Component/PropertyAccess/Tests/Fixtures/TestClassTypeErrorInsideCall.php b/src/Symfony/Component/PropertyAccess/Tests/Fixtures/TestClassTypeErrorInsideCall.php new file mode 100644 index 0000000000000..44a93900fae34 --- /dev/null +++ b/src/Symfony/Component/PropertyAccess/Tests/Fixtures/TestClassTypeErrorInsideCall.php @@ -0,0 +1,28 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\PropertyAccess\Tests\Fixtures; + +class TestClassTypeErrorInsideCall +{ + public function expectsDateTime(\DateTime $date) + { + } + + public function getProperty() + { + } + + public function setProperty($property) + { + $this->expectsDateTime(null); // throws TypeError + } +} diff --git a/src/Symfony/Component/PropertyAccess/Tests/PropertyAccessorTest.php b/src/Symfony/Component/PropertyAccess/Tests/PropertyAccessorTest.php index e2ef9296ed50f..ec928a31e88cd 100644 --- a/src/Symfony/Component/PropertyAccess/Tests/PropertyAccessorTest.php +++ b/src/Symfony/Component/PropertyAccess/Tests/PropertyAccessorTest.php @@ -21,6 +21,7 @@ use Symfony\Component\PropertyAccess\Tests\Fixtures\Ticket5775Object; use Symfony\Component\PropertyAccess\Tests\Fixtures\TestClassSetValue; use Symfony\Component\PropertyAccess\Tests\Fixtures\TestClassIsWritable; +use Symfony\Component\PropertyAccess\Tests\Fixtures\TestClassTypeErrorInsideCall; use Symfony\Component\PropertyAccess\Tests\Fixtures\TypeHinted; class PropertyAccessorTest extends TestCase @@ -578,4 +579,15 @@ public function testThrowTypeErrorWithInterface() $this->propertyAccessor->setValue($object, 'countable', 'This is a string, \Countable expected.'); } + + /** + * @requires PHP 7.0 + * @expectedException \TypeError + */ + public function testThrowTypeErrorInsideSetterCall() + { + $object = new TestClassTypeErrorInsideCall(); + + $this->propertyAccessor->setValue($object, 'property', 'foo'); + } } From 2f350d1d389d697c920b8e62a4a8080b75a7fcd4 Mon Sep 17 00:00:00 2001 From: Javan Eskander Date: Thu, 8 Jun 2017 17:18:54 +1000 Subject: [PATCH 0171/1099] Fixed PHPdoc return references in FormBuilderInterface --- src/Symfony/Component/Form/FormBuilderInterface.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/Form/FormBuilderInterface.php b/src/Symfony/Component/Form/FormBuilderInterface.php index 1145ab26420c0..c19cc903beeba 100644 --- a/src/Symfony/Component/Form/FormBuilderInterface.php +++ b/src/Symfony/Component/Form/FormBuilderInterface.php @@ -27,7 +27,7 @@ interface FormBuilderInterface extends \Traversable, \Countable, FormConfigBuild * @param string|FormTypeInterface $type * @param array $options * - * @return $this + * @return self */ public function add($child, $type = null, array $options = array()); @@ -58,7 +58,7 @@ public function get($name); * * @param string $name * - * @return $this + * @return self */ public function remove($name); From aadf263db42dfeac706939228d191beaefad886f Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Wed, 7 Jun 2017 11:23:32 +0200 Subject: [PATCH 0172/1099] [Cache] APCu isSupported() should return true when apc.enable_cli=Off --- src/Symfony/Component/Cache/Adapter/ApcuAdapter.php | 4 ++-- src/Symfony/Component/Cache/Adapter/PhpFilesAdapter.php | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Symfony/Component/Cache/Adapter/ApcuAdapter.php b/src/Symfony/Component/Cache/Adapter/ApcuAdapter.php index 0a3887eba091f..6687bd4272d1d 100644 --- a/src/Symfony/Component/Cache/Adapter/ApcuAdapter.php +++ b/src/Symfony/Component/Cache/Adapter/ApcuAdapter.php @@ -21,7 +21,7 @@ class ApcuAdapter extends AbstractAdapter { public static function isSupported() { - return function_exists('apcu_fetch') && ini_get('apc.enabled') && !('cli' === PHP_SAPI && !ini_get('apc.enable_cli')); + return function_exists('apcu_fetch') && ini_get('apc.enabled'); } public function __construct($namespace = '', $defaultLifetime = 0, $version = null) @@ -69,7 +69,7 @@ protected function doHave($id) */ protected function doClear($namespace) { - return isset($namespace[0]) && class_exists('APCuIterator', false) + return isset($namespace[0]) && class_exists('APCuIterator', false) && ('cli' !== PHP_SAPI || ini_get('apc.enable_cli')) ? apcu_delete(new \APCuIterator(sprintf('/^%s/', preg_quote($namespace, '/')), APC_ITER_KEY)) : apcu_clear_cache(); } diff --git a/src/Symfony/Component/Cache/Adapter/PhpFilesAdapter.php b/src/Symfony/Component/Cache/Adapter/PhpFilesAdapter.php index befa38d8d46df..88107cb9899dc 100644 --- a/src/Symfony/Component/Cache/Adapter/PhpFilesAdapter.php +++ b/src/Symfony/Component/Cache/Adapter/PhpFilesAdapter.php @@ -26,7 +26,7 @@ class PhpFilesAdapter extends AbstractAdapter public static function isSupported() { - return function_exists('opcache_compile_file') && ini_get('opcache.enable'); + return function_exists('opcache_invalidate') && ini_get('opcache.enable'); } public function __construct($namespace = '', $defaultLifetime = 0, $directory = null) @@ -118,7 +118,7 @@ protected function doSave(array $values, $lifetime) $ok = $this->write($file, ' Date: Thu, 8 Jun 2017 15:38:34 +0200 Subject: [PATCH 0173/1099] [Security] Fix annotation --- .../Core/Authentication/Token/UsernamePasswordToken.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/Security/Core/Authentication/Token/UsernamePasswordToken.php b/src/Symfony/Component/Security/Core/Authentication/Token/UsernamePasswordToken.php index 71d19adc14f2b..7bfc556bdbf25 100644 --- a/src/Symfony/Component/Security/Core/Authentication/Token/UsernamePasswordToken.php +++ b/src/Symfony/Component/Security/Core/Authentication/Token/UsernamePasswordToken.php @@ -27,7 +27,7 @@ class UsernamePasswordToken extends AbstractToken * Constructor. * * @param string|object $user The username (like a nickname, email address, etc.), or a UserInterface instance or an object implementing a __toString method - * @param string $credentials This usually is the password of the user + * @param mixed $credentials This usually is the password of the user * @param string $providerKey The provider key * @param (RoleInterface|string)[] $roles An array of roles * From f82b6185a4c043676fd33df3c0c331a6f97560ae Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Thu, 8 Jun 2017 16:28:59 +0200 Subject: [PATCH 0174/1099] [Yaml] Remove line number in deprecation notices --- src/Symfony/Component/Yaml/Inline.php | 8 ++++---- src/Symfony/Component/Yaml/Parser.php | 12 ++++++------ src/Symfony/Component/Yaml/Tests/ParserTest.php | 6 +++--- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/Symfony/Component/Yaml/Inline.php b/src/Symfony/Component/Yaml/Inline.php index 7ad53692eb000..6789f79efb6cf 100644 --- a/src/Symfony/Component/Yaml/Inline.php +++ b/src/Symfony/Component/Yaml/Inline.php @@ -493,7 +493,7 @@ private static function parseMapping($mapping, $flags, &$i = 0, $references = ar if (!(Yaml::PARSE_KEYS_AS_STRINGS & $flags)) { $evaluatedKey = self::evaluateScalar($key, $flags, $references); - if ('' !== $key && $evaluatedKey !== $key && !is_string($evaluatedKey)) { + if ('' !== $key && $evaluatedKey !== $key && !is_string($evaluatedKey) && !is_int($evaluatedKey)) { @trigger_error('Implicit casting of incompatible mapping keys to strings is deprecated since version 3.3 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0. Pass the PARSE_KEYS_AS_STRING flag to explicitly enable the type casts.', E_USER_DEPRECATED); } } @@ -519,7 +519,7 @@ private static function parseMapping($mapping, $flags, &$i = 0, $references = ar // Parser cannot abort this mapping earlier, since lines // are processed sequentially. if (isset($output[$key])) { - @trigger_error(sprintf('Duplicate key "%s" detected on line %d whilst parsing YAML. Silent handling of duplicate mapping keys in YAML is deprecated since version 3.2 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0.', $key, self::$parsedLineNumber + 1), E_USER_DEPRECATED); + @trigger_error(sprintf('Duplicate key "%s" detected whilst parsing YAML. Silent handling of duplicate mapping keys in YAML is deprecated since version 3.2 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0.', $key), E_USER_DEPRECATED); $duplicate = true; } break; @@ -530,7 +530,7 @@ private static function parseMapping($mapping, $flags, &$i = 0, $references = ar // Parser cannot abort this mapping earlier, since lines // are processed sequentially. if (isset($output[$key])) { - @trigger_error(sprintf('Duplicate key "%s" detected on line %d whilst parsing YAML. Silent handling of duplicate mapping keys in YAML is deprecated since version 3.2 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0.', $key, self::$parsedLineNumber + 1), E_USER_DEPRECATED); + @trigger_error(sprintf('Duplicate key "%s" detected whilst parsing YAML. Silent handling of duplicate mapping keys in YAML is deprecated since version 3.2 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0.', $key), E_USER_DEPRECATED); $duplicate = true; } break; @@ -540,7 +540,7 @@ private static function parseMapping($mapping, $flags, &$i = 0, $references = ar // Parser cannot abort this mapping earlier, since lines // are processed sequentially. if (isset($output[$key])) { - @trigger_error(sprintf('Duplicate key "%s" detected on line %d whilst parsing YAML. Silent handling of duplicate mapping keys in YAML is deprecated since version 3.2 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0.', $key, self::$parsedLineNumber + 1), E_USER_DEPRECATED); + @trigger_error(sprintf('Duplicate key "%s" detected whilst parsing YAML. Silent handling of duplicate mapping keys in YAML is deprecated since version 3.2 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0.', $key), E_USER_DEPRECATED); $duplicate = true; } --$i; diff --git a/src/Symfony/Component/Yaml/Parser.php b/src/Symfony/Component/Yaml/Parser.php index 4a5f2b91e06bf..29fcf8da5cec8 100644 --- a/src/Symfony/Component/Yaml/Parser.php +++ b/src/Symfony/Component/Yaml/Parser.php @@ -236,9 +236,9 @@ private function doParse($value, $flags) throw $e; } - if (!(Yaml::PARSE_KEYS_AS_STRINGS & $flags) && !is_string($key)) { - $keyType = is_numeric($key) ? 'numeric key' : 'incompatible key type'; - @trigger_error(sprintf('Implicit casting of %s to string on line %d is deprecated since version 3.3 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0. Pass the PARSE_KEYS_AS_STRING flag to explicitly enable the type casts.', $keyType, $this->getRealCurrentLineNb()), E_USER_DEPRECATED); + if (!(Yaml::PARSE_KEYS_AS_STRINGS & $flags) && !is_string($key) && !is_int($key)) { + $keyType = is_numeric($key) ? 'numeric key' : 'non-string key'; + @trigger_error(sprintf('Implicit casting of %s to string is deprecated since version 3.3 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0. Pass the PARSE_KEYS_AS_STRING flag to explicitly enable the type casts.', $keyType), E_USER_DEPRECATED); } // Convert float keys to strings, to avoid being converted to integers by PHP @@ -312,7 +312,7 @@ private function doParse($value, $flags) $data[$key] = null; } } else { - @trigger_error(sprintf('Duplicate key "%s" detected on line %d whilst parsing YAML. Silent handling of duplicate mapping keys in YAML is deprecated since version 3.2 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0.', $key, $this->getRealCurrentLineNb() + 1), E_USER_DEPRECATED); + @trigger_error(sprintf('Duplicate key "%s" detected whilst parsing YAML. Silent handling of duplicate mapping keys in YAML is deprecated since version 3.2 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0.', $key), E_USER_DEPRECATED); } } else { // remember the parsed line number here in case we need it to provide some contexts in error messages below @@ -327,7 +327,7 @@ private function doParse($value, $flags) $data[$key] = $value; } } else { - @trigger_error(sprintf('Duplicate key "%s" detected on line %d whilst parsing YAML. Silent handling of duplicate mapping keys in YAML is deprecated since version 3.2 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0.', $key, $realCurrentLineNbKey + 1), E_USER_DEPRECATED); + @trigger_error(sprintf('Duplicate key "%s" detected whilst parsing YAML. Silent handling of duplicate mapping keys in YAML is deprecated since version 3.2 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0.', $key), E_USER_DEPRECATED); } } } else { @@ -337,7 +337,7 @@ private function doParse($value, $flags) if ($allowOverwrite || !isset($data[$key])) { $data[$key] = $value; } else { - @trigger_error(sprintf('Duplicate key "%s" detected on line %d whilst parsing YAML. Silent handling of duplicate mapping keys in YAML is deprecated since version 3.2 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0.', $key, $this->getRealCurrentLineNb() + 1), E_USER_DEPRECATED); + @trigger_error(sprintf('Duplicate key "%s" detected whilst parsing YAML. Silent handling of duplicate mapping keys in YAML is deprecated since version 3.2 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0.', $key), E_USER_DEPRECATED); } } if ($isRef) { diff --git a/src/Symfony/Component/Yaml/Tests/ParserTest.php b/src/Symfony/Component/Yaml/Tests/ParserTest.php index a6c7b6ad12aff..a296a3300125d 100644 --- a/src/Symfony/Component/Yaml/Tests/ParserTest.php +++ b/src/Symfony/Component/Yaml/Tests/ParserTest.php @@ -853,7 +853,7 @@ public function testMappingDuplicateKeyFlow() /** * @group legacy * @dataProvider getParseExceptionOnDuplicateData - * @expectedDeprecation Duplicate key "%s" detected on line %d whilst parsing YAML. Silent handling of duplicate mapping keys in YAML is deprecated %s. + * @expectedDeprecation Duplicate key "%s" detected whilst parsing YAML. Silent handling of duplicate mapping keys in YAML is deprecated %s. * throws \Symfony\Component\Yaml\Exception\ParseException in 4.0 */ public function testParseExceptionOnDuplicate($input, $duplicateKey, $lineNumber) @@ -1081,7 +1081,7 @@ public function testYamlDirective() /** * @group legacy - * @expectedDeprecation Implicit casting of numeric key to string on line 1 is deprecated since version 3.3 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0. Pass the PARSE_KEYS_AS_STRING flag to explicitly enable the type casts. + * @expectedDeprecation Implicit casting of numeric key to string is deprecated since version 3.3 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0. Pass the PARSE_KEYS_AS_STRING flag to explicitly enable the type casts. */ public function testFloatKeys() { @@ -1103,7 +1103,7 @@ public function testFloatKeys() /** * @group legacy - * @expectedDeprecation Implicit casting of incompatible key type to string on line 1 is deprecated since version 3.3 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0. Pass the PARSE_KEYS_AS_STRING flag to explicitly enable the type casts. + * @expectedDeprecation Implicit casting of non-string key to string is deprecated since version 3.3 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0. Pass the PARSE_KEYS_AS_STRING flag to explicitly enable the type casts. */ public function testBooleanKeys() { From 0821c5a059c1d65fbc7cb9ae37f950e601f9c85f Mon Sep 17 00:00:00 2001 From: Roland Franssen Date: Thu, 25 May 2017 17:49:46 +0200 Subject: [PATCH 0175/1099] [VarDumper] Cyclic searching dumps --- src/Symfony/Component/VarDumper/Dumper/HtmlDumper.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/VarDumper/Dumper/HtmlDumper.php b/src/Symfony/Component/VarDumper/Dumper/HtmlDumper.php index cf94b1af93039..ad10481d2f514 100644 --- a/src/Symfony/Component/VarDumper/Dumper/HtmlDumper.php +++ b/src/Symfony/Component/VarDumper/Dumper/HtmlDumper.php @@ -425,7 +425,7 @@ function xpathString(str) { if (this.isEmpty()) { return this.current(); } - this.idx = this.idx < (this.nodes.length - 1) ? this.idx + 1 : this.idx; + this.idx = this.idx < (this.nodes.length - 1) ? this.idx + 1 : 0; return this.current(); }, @@ -433,7 +433,7 @@ function xpathString(str) { if (this.isEmpty()) { return this.current(); } - this.idx = this.idx > 0 ? this.idx - 1 : this.idx; + this.idx = this.idx > 0 ? this.idx - 1 : (this.nodes.length - 1); return this.current(); }, From 73f24e8f48ecf6136ae45dd0f63c411c1d4c6c13 Mon Sep 17 00:00:00 2001 From: Roland Franssen Date: Thu, 25 May 2017 18:38:14 +0200 Subject: [PATCH 0176/1099] search case insensitive --- src/Symfony/Component/VarDumper/Dumper/HtmlDumper.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/VarDumper/Dumper/HtmlDumper.php b/src/Symfony/Component/VarDumper/Dumper/HtmlDumper.php index ad10481d2f514..e57d04065b6be 100644 --- a/src/Symfony/Component/VarDumper/Dumper/HtmlDumper.php +++ b/src/Symfony/Component/VarDumper/Dumper/HtmlDumper.php @@ -507,7 +507,7 @@ function showCurrent(state) return; } - var xpathResult = doc.evaluate('//pre[@id="' + root.id + '"]//span[@class="sf-dump-str" or @class="sf-dump-key" or @class="sf-dump-public" or @class="sf-dump-protected" or @class="sf-dump-private"][contains(child::text(), ' + xpathString(searchQuery) + ')]', document, null, XPathResult.ORDERED_NODE_ITERATOR_TYPE, null); + var xpathResult = doc.evaluate('//pre[@id="' + root.id + '"]//span[@class="sf-dump-str" or @class="sf-dump-key" or @class="sf-dump-public" or @class="sf-dump-protected" or @class="sf-dump-private"][contains(translate(child::text(), ' + xpathString(searchQuery.toUpperCase()) + ', ' + xpathString(searchQuery.toLowerCase()) + '), ' + xpathString(searchQuery.toLowerCase()) + ')]', document, null, XPathResult.ORDERED_NODE_ITERATOR_TYPE, null); while (node = xpathResult.iterateNext()) state.nodes.push(node); From c1fa308c0a9ddf6b22c81fbe5fccae46e1118ca1 Mon Sep 17 00:00:00 2001 From: Robin Chalas Date: Fri, 9 Jun 2017 14:05:05 +0200 Subject: [PATCH 0177/1099] Fix non-dumped voters in security panel --- .../SecurityBundle/Resources/views/Collector/security.html.twig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Bundle/SecurityBundle/Resources/views/Collector/security.html.twig b/src/Symfony/Bundle/SecurityBundle/Resources/views/Collector/security.html.twig index 073d0d869d8f0..9cd6ec4d78db2 100644 --- a/src/Symfony/Bundle/SecurityBundle/Resources/views/Collector/security.html.twig +++ b/src/Symfony/Bundle/SecurityBundle/Resources/views/Collector/security.html.twig @@ -222,7 +222,7 @@ {% for voter in collector.voters %} {{ loop.index }} - {{ voter }} + {{ profiler_dump(voter) }} {% endfor %} From 3aa8861a424c98351057adab1c176c79fd7004d8 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Thu, 8 Jun 2017 20:25:37 +0200 Subject: [PATCH 0178/1099] [Process] Deprecate ProcessBuilder --- UPGRADE-3.4.md | 6 ++++++ UPGRADE-4.0.md | 3 +++ src/Symfony/Bundle/WebServerBundle/WebServer.php | 9 ++++----- src/Symfony/Bundle/WebServerBundle/composer.json | 2 +- .../Component/Console/Helper/ProcessHelper.php | 3 +-- .../Console/Tests/Helper/ProcessHelperTest.php | 5 ++--- src/Symfony/Component/Console/composer.json | 5 +++-- src/Symfony/Component/Process/CHANGELOG.md | 5 +++++ src/Symfony/Component/Process/ProcessBuilder.php | 12 ++++-------- .../Component/Process/Tests/ProcessBuilderTest.php | 6 +++--- 10 files changed, 32 insertions(+), 24 deletions(-) diff --git a/UPGRADE-3.4.md b/UPGRADE-3.4.md index 6858520efe164..e1c4af06c6a38 100644 --- a/UPGRADE-3.4.md +++ b/UPGRADE-3.4.md @@ -26,6 +26,12 @@ FrameworkBundle * The `KernelTestCase::getPhpUnitXmlDir()` and `KernelTestCase::getPhpUnitCliConfigArgument()` methods are deprecated since 3.4 and will be removed in 4.0. +Process +------- + + * The `Symfony\Component\Process\ProcessBuilder` class has been deprecated, + use the `Symfony\Component\Process\Process` class directly instead. + Validator --------- diff --git a/UPGRADE-4.0.md b/UPGRADE-4.0.md index 27cbc04fe0ac3..fce693437fdfe 100644 --- a/UPGRADE-4.0.md +++ b/UPGRADE-4.0.md @@ -420,6 +420,9 @@ Ldap Process ------- + * The `Symfony\Component\Process\ProcessBuilder` class has been removed, + use the `Symfony\Component\Process\Process` class directly instead. + * The `ProcessUtils::escapeArgument()` method has been removed, use a command line array or give env vars to the `Process::start/run()` method instead. * Environment variables are always inherited in sub-processes. diff --git a/src/Symfony/Bundle/WebServerBundle/WebServer.php b/src/Symfony/Bundle/WebServerBundle/WebServer.php index b65cec1cb768b..8edbe2bf56ec2 100644 --- a/src/Symfony/Bundle/WebServerBundle/WebServer.php +++ b/src/Symfony/Bundle/WebServerBundle/WebServer.php @@ -13,7 +13,6 @@ use Symfony\Component\Process\PhpExecutableFinder; use Symfony\Component\Process\Process; -use Symfony\Component\Process\ProcessBuilder; use Symfony\Component\Process\Exception\RuntimeException; /** @@ -151,11 +150,11 @@ private function createServerProcess(WebServerConfig $config) throw new \RuntimeException('Unable to find the PHP binary.'); } - $builder = new ProcessBuilder(array($binary, '-S', $config->getAddress(), $config->getRouter())); - $builder->setWorkingDirectory($config->getDocumentRoot()); - $builder->setTimeout(null); + $process = new Process(array($binary, '-S', $config->getAddress(), $config->getRouter())); + $process->setWorkingDirectory($config->getDocumentRoot()); + $process->setTimeout(null); - return $builder->getProcess(); + return $process; } private function getDefaultPidFile() diff --git a/src/Symfony/Bundle/WebServerBundle/composer.json b/src/Symfony/Bundle/WebServerBundle/composer.json index 306b0deffe2a7..e1870b70d0a80 100644 --- a/src/Symfony/Bundle/WebServerBundle/composer.json +++ b/src/Symfony/Bundle/WebServerBundle/composer.json @@ -19,7 +19,7 @@ "php": ">=5.5.9", "symfony/console": "~2.8.8|~3.0.8|~3.1.2|~3.2|~4.0", "symfony/http-kernel": "~3.3|~4.0", - "symfony/process": "~2.8|~3.0|~4.0" + "symfony/process": "~3.3|~4.0" }, "autoload": { "psr-4": { "Symfony\\Bundle\\WebServerBundle\\": "" }, diff --git a/src/Symfony/Component/Console/Helper/ProcessHelper.php b/src/Symfony/Component/Console/Helper/ProcessHelper.php index 2c46a2c39d0b2..5010607511468 100644 --- a/src/Symfony/Component/Console/Helper/ProcessHelper.php +++ b/src/Symfony/Component/Console/Helper/ProcessHelper.php @@ -15,7 +15,6 @@ use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Process\Exception\ProcessFailedException; use Symfony\Component\Process\Process; -use Symfony\Component\Process\ProcessBuilder; /** * The ProcessHelper class provides helpers to run external processes. @@ -45,7 +44,7 @@ public function run(OutputInterface $output, $cmd, $error = null, callable $call $formatter = $this->getHelperSet()->get('debug_formatter'); if (is_array($cmd)) { - $process = ProcessBuilder::create($cmd)->getProcess(); + $process = new Process($cmd); } elseif ($cmd instanceof Process) { $process = $cmd; } else { diff --git a/src/Symfony/Component/Console/Tests/Helper/ProcessHelperTest.php b/src/Symfony/Component/Console/Tests/Helper/ProcessHelperTest.php index 8069bcccc96ab..eb619539ee92f 100644 --- a/src/Symfony/Component/Console/Tests/Helper/ProcessHelperTest.php +++ b/src/Symfony/Component/Console/Tests/Helper/ProcessHelperTest.php @@ -17,7 +17,6 @@ use Symfony\Component\Console\Output\StreamOutput; use Symfony\Component\Console\Helper\ProcessHelper; use Symfony\Component\Process\Process; -use Symfony\Component\Process\ProcessBuilder; class ProcessHelperTest extends TestCase { @@ -85,8 +84,8 @@ public function provideCommandsAndOutput() EOT; $errorMessage = 'An error occurred'; - $args = new ProcessBuilder(array('php', '-r', 'echo 42;')); - $args = $args->getProcess()->getCommandLine(); + $args = new Process(array('php', '-r', 'echo 42;')); + $args = $args->getCommandLine(); $successOutputProcessDebug = str_replace("'php' '-r' 'echo 42;'", $args, $successOutputProcessDebug); return array( diff --git a/src/Symfony/Component/Console/composer.json b/src/Symfony/Component/Console/composer.json index 9af71348cc464..5f7fe6ec1aa3b 100644 --- a/src/Symfony/Component/Console/composer.json +++ b/src/Symfony/Component/Console/composer.json @@ -26,7 +26,7 @@ "symfony/event-dispatcher": "~2.8|~3.0|~4.0", "symfony/dependency-injection": "~3.3|~4.0", "symfony/filesystem": "~2.8|~3.0|~4.0", - "symfony/process": "~2.8|~3.0|~4.0", + "symfony/process": "~3.3|~4.0", "psr/log": "~1.0" }, "suggest": { @@ -36,7 +36,8 @@ "psr/log": "For using the console logger" }, "conflict": { - "symfony/dependency-injection": "<3.3" + "symfony/dependency-injection": "<3.3", + "symfony/process": "<3.3" }, "autoload": { "psr-4": { "Symfony\\Component\\Console\\": "" }, diff --git a/src/Symfony/Component/Process/CHANGELOG.md b/src/Symfony/Component/Process/CHANGELOG.md index bb719be711524..7193c498d4326 100644 --- a/src/Symfony/Component/Process/CHANGELOG.md +++ b/src/Symfony/Component/Process/CHANGELOG.md @@ -1,6 +1,11 @@ CHANGELOG ========= +3.4.0 +----- + + * deprecated the ProcessBuilder class + 3.3.0 ----- diff --git a/src/Symfony/Component/Process/ProcessBuilder.php b/src/Symfony/Component/Process/ProcessBuilder.php index 2a5bb2bc3f035..5a54689875d8e 100644 --- a/src/Symfony/Component/Process/ProcessBuilder.php +++ b/src/Symfony/Component/Process/ProcessBuilder.php @@ -11,6 +11,8 @@ namespace Symfony\Component\Process; +@trigger_error(sprintf('The %s class is deprecated since version 3.4 and will be removed in 4.0. Use the Process class instead.', ProcessBuilder::class), E_USER_DEPRECATED); + use Symfony\Component\Process\Exception\InvalidArgumentException; use Symfony\Component\Process\Exception\LogicException; @@ -18,6 +20,8 @@ * Process builder. * * @author Kris Wallsmith + * + * @deprecated since version 3.4, to be removed in 4.0. Use the Process class instead. */ class ProcessBuilder { @@ -120,13 +124,9 @@ public function setWorkingDirectory($cwd) * @param bool $inheritEnv * * @return $this - * - * @deprecated since version 3.3, to be removed in 4.0. */ public function inheritEnvironmentVariables($inheritEnv = true) { - @trigger_error(sprintf('The %s() method is deprecated since version 3.3 and will be removed in 4.0.', __METHOD__), E_USER_DEPRECATED); - $this->inheritEnv = $inheritEnv; return $this; @@ -221,13 +221,9 @@ public function setTimeout($timeout) * @param string $value The option value * * @return $this - * - * @deprecated since version 3.3, to be removed in 4.0. */ public function setOption($name, $value) { - @trigger_error(sprintf('The %s() method is deprecated since version 3.3 and will be removed in 4.0.', __METHOD__), E_USER_DEPRECATED); - $this->options[$name] = $value; return $this; diff --git a/src/Symfony/Component/Process/Tests/ProcessBuilderTest.php b/src/Symfony/Component/Process/Tests/ProcessBuilderTest.php index 34bb3732722e5..c1a67afa18bbb 100644 --- a/src/Symfony/Component/Process/Tests/ProcessBuilderTest.php +++ b/src/Symfony/Component/Process/Tests/ProcessBuilderTest.php @@ -14,11 +14,11 @@ use PHPUnit\Framework\TestCase; use Symfony\Component\Process\ProcessBuilder; +/** + * @group legacy + */ class ProcessBuilderTest extends TestCase { - /** - * @group legacy - */ public function testInheritEnvironmentVars() { $proc = ProcessBuilder::create() From 8b7de02413a9bc7da7c91127c826570a75b807c4 Mon Sep 17 00:00:00 2001 From: Robin Chalas Date: Fri, 9 Jun 2017 13:21:59 +0200 Subject: [PATCH 0179/1099] [EventDispatcher] Remove dead code in WrappedListener --- .../EventDispatcher/Debug/WrappedListener.php | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/Symfony/Component/EventDispatcher/Debug/WrappedListener.php b/src/Symfony/Component/EventDispatcher/Debug/WrappedListener.php index 4029883dd98c7..f7b0273e15aaa 100644 --- a/src/Symfony/Component/EventDispatcher/Debug/WrappedListener.php +++ b/src/Symfony/Component/EventDispatcher/Debug/WrappedListener.php @@ -15,7 +15,6 @@ use Symfony\Component\EventDispatcher\Event; use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Symfony\Component\VarDumper\Caster\ClassStub; -use Symfony\Component\VarDumper\Cloner\VarCloner; /** * @author Fabien Potencier @@ -30,8 +29,7 @@ class WrappedListener private $dispatcher; private $pretty; private $stub; - - private static $cloner; + private static $hasClassStub; public function __construct($listener, $name, Stopwatch $stopwatch, EventDispatcherInterface $dispatcher = null) { @@ -58,8 +56,8 @@ public function __construct($listener, $name, Stopwatch $stopwatch, EventDispatc $this->name = $name; } - if (null === self::$cloner) { - self::$cloner = class_exists(ClassStub::class) ? new VarCloner() : false; + if (null === self::$hasClassStub) { + self::$hasClassStub = class_exists(ClassStub::class); } } @@ -86,7 +84,7 @@ public function getPretty() public function getInfo($eventName) { if (null === $this->stub) { - $this->stub = false === self::$cloner ? $this->pretty.'()' : new ClassStub($this->pretty.'()', $this->listener); + $this->stub = self::$hasClassStub ? new ClassStub($this->pretty.'()', $this->listener) : $this->pretty.'()'; } return array( From e3ee6bc349b76d042480fbae8daf1d4aa57fe25a Mon Sep 17 00:00:00 2001 From: Robin Chalas Date: Fri, 9 Jun 2017 10:00:19 +0200 Subject: [PATCH 0180/1099] Lazy load security listeners --- UPGRADE-3.4.md | 7 ++++++- src/Symfony/Bundle/SecurityBundle/CHANGELOG.md | 5 +++++ .../DependencyInjection/SecurityExtension.php | 2 +- .../Bundle/SecurityBundle/Security/FirewallContext.php | 10 +++++++++- .../DependencyInjection/CompleteConfigurationTest.php | 2 +- 5 files changed, 22 insertions(+), 4 deletions(-) diff --git a/UPGRADE-3.4.md b/UPGRADE-3.4.md index e1c4af06c6a38..e13d9b7febf64 100644 --- a/UPGRADE-3.4.md +++ b/UPGRADE-3.4.md @@ -4,7 +4,7 @@ UPGRADE FROM 3.3 to 3.4 DependencyInjection ------------------- - * Top-level anonymous services in XML are deprecated and will throw an exception in Symfony 4.0. + * Top-level anonymous services in XML are deprecated and will throw an exception in Symfony 4.0. Finder ------ @@ -32,6 +32,11 @@ Process * The `Symfony\Component\Process\ProcessBuilder` class has been deprecated, use the `Symfony\Component\Process\Process` class directly instead. +SecurityBundle +-------------- + + * `FirewallContext::getListeners()` now returns `\Traversable|array` + Validator --------- diff --git a/src/Symfony/Bundle/SecurityBundle/CHANGELOG.md b/src/Symfony/Bundle/SecurityBundle/CHANGELOG.md index 4185d409fb445..32d00431262b7 100644 --- a/src/Symfony/Bundle/SecurityBundle/CHANGELOG.md +++ b/src/Symfony/Bundle/SecurityBundle/CHANGELOG.md @@ -1,6 +1,11 @@ CHANGELOG ========= +3.4.0 +----- + + * [BC BREAK] `FirewallContext::getListeners()` now returns `\Traversable|array` + 3.3.0 ----- diff --git a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php index 5fd31ec4fdab6..6209d763cd81a 100644 --- a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php +++ b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php @@ -265,7 +265,7 @@ private function createFirewalls($config, ContainerBuilder $container) $contextId = 'security.firewall.map.context.'.$name; $context = $container->setDefinition($contextId, new ChildDefinition('security.firewall.context')); $context - ->replaceArgument(0, $listeners) + ->replaceArgument(0, new IteratorArgument($listeners)) ->replaceArgument(1, $exceptionListener) ->replaceArgument(2, new Reference($configId)) ; diff --git a/src/Symfony/Bundle/SecurityBundle/Security/FirewallContext.php b/src/Symfony/Bundle/SecurityBundle/Security/FirewallContext.php index 02f2739ed8a2f..bfac97d6cfcc2 100644 --- a/src/Symfony/Bundle/SecurityBundle/Security/FirewallContext.php +++ b/src/Symfony/Bundle/SecurityBundle/Security/FirewallContext.php @@ -25,7 +25,12 @@ class FirewallContext private $exceptionListener; private $config; - public function __construct(array $listeners, ExceptionListener $exceptionListener = null, FirewallConfig $config = null) + /** + * @param \Traversable|array $listeners + * @param ExceptionListener|null $exceptionListener + * @param FirewallConfig|null $firewallConfig + */ + public function __construct($listeners, ExceptionListener $exceptionListener = null, FirewallConfig $config = null) { $this->listeners = $listeners; $this->exceptionListener = $exceptionListener; @@ -47,6 +52,9 @@ public function getContext() return array($this->getListeners(), $this->getExceptionListener()); } + /** + * @return \Traversable|array + */ public function getListeners() { return $this->listeners; diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/CompleteConfigurationTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/CompleteConfigurationTest.php index 6ef0e305ec4f6..220e39b09a723 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/CompleteConfigurationTest.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/CompleteConfigurationTest.php @@ -72,7 +72,7 @@ public function testFirewalls() foreach (array_keys($arguments[1]->getValues()) as $contextId) { $contextDef = $container->getDefinition($contextId); $arguments = $contextDef->getArguments(); - $listeners[] = array_map('strval', $arguments['index_0']); + $listeners[] = array_map('strval', $arguments['index_0']->getValues()); $configDef = $container->getDefinition((string) $arguments['index_2']); $configs[] = array_values($configDef->getArguments()); From c9c3495fc0bf00609f5bf49ac54d99fd703dd755 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Sat, 10 Jun 2017 13:08:03 +0100 Subject: [PATCH 0181/1099] remove now useless condition --- src/Symfony/Component/Console/Helper/ProcessHelper.php | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/Symfony/Component/Console/Helper/ProcessHelper.php b/src/Symfony/Component/Console/Helper/ProcessHelper.php index 5010607511468..82935baeaa81d 100644 --- a/src/Symfony/Component/Console/Helper/ProcessHelper.php +++ b/src/Symfony/Component/Console/Helper/ProcessHelper.php @@ -43,9 +43,7 @@ public function run(OutputInterface $output, $cmd, $error = null, callable $call $formatter = $this->getHelperSet()->get('debug_formatter'); - if (is_array($cmd)) { - $process = new Process($cmd); - } elseif ($cmd instanceof Process) { + if ($cmd instanceof Process) { $process = $cmd; } else { $process = new Process($cmd); From 232caad8765503ca36a0f675ba37a1d60bc4e42a Mon Sep 17 00:00:00 2001 From: Pierre du Plessis Date: Fri, 9 Jun 2017 21:12:04 +0200 Subject: [PATCH 0182/1099] Remove deprecated each function --- .../Tests/DependencyInjection/TwigExtensionTest.php | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/TwigExtensionTest.php b/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/TwigExtensionTest.php index fb82ee8266dbf..f5809cc045c42 100644 --- a/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/TwigExtensionTest.php +++ b/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/TwigExtensionTest.php @@ -170,9 +170,10 @@ public function testGlobalsWithDifferentTypesAndValues() $calls = $container->getDefinition('twig')->getMethodCalls(); foreach (array_slice($calls, 1) as $call) { - list($name, $value) = each($globals); - $this->assertEquals($name, $call[1][0]); - $this->assertSame($value, $call[1][1]); + $this->assertEquals(key($globals), $call[1][0]); + $this->assertSame(current($globals), $call[1][1]); + + next($globals); } } From 598ae56cc96bfe0496f0a892085d39cba752304e Mon Sep 17 00:00:00 2001 From: Vladimir Reznichenko Date: Sun, 28 May 2017 16:12:41 +0200 Subject: [PATCH 0183/1099] SCA with Php Inspections (EA Extended): 2.7 --- .../Bundle/FrameworkBundle/Templating/Helper/AssetsHelper.php | 2 +- src/Symfony/Bundle/TwigBundle/Loader/FilesystemLoader.php | 1 - .../DependencyInjection/Tests/ContainerBuilderTest.php | 2 +- src/Symfony/Component/Filesystem/Tests/LockHandlerTest.php | 2 +- .../Form/ChoiceList/Factory/DefaultChoiceListFactory.php | 2 +- src/Symfony/Component/Form/FormRenderer.php | 2 +- src/Symfony/Component/Security/Acl/Dbal/Schema.php | 2 +- .../Security/Core/Authorization/AccessDecisionManager.php | 2 -- 8 files changed, 6 insertions(+), 9 deletions(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/Templating/Helper/AssetsHelper.php b/src/Symfony/Bundle/FrameworkBundle/Templating/Helper/AssetsHelper.php index 6acc04539393d..172417924c921 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Templating/Helper/AssetsHelper.php +++ b/src/Symfony/Bundle/FrameworkBundle/Templating/Helper/AssetsHelper.php @@ -78,7 +78,7 @@ public function getVersion($path = null, $packageName = null) // packageName is null and path not, so path is a path or a packageName try { - $package = $this->packages->getPackage($path); + $this->packages->getPackage($path); } catch (\InvalidArgumentException $e) { // path is not a package, so it should be a path return $this->packages->getVersion($path); diff --git a/src/Symfony/Bundle/TwigBundle/Loader/FilesystemLoader.php b/src/Symfony/Bundle/TwigBundle/Loader/FilesystemLoader.php index 53fe300e29a62..74d1d1214ffed 100644 --- a/src/Symfony/Bundle/TwigBundle/Loader/FilesystemLoader.php +++ b/src/Symfony/Bundle/TwigBundle/Loader/FilesystemLoader.php @@ -73,7 +73,6 @@ protected function findTemplate($template, $throw = true) } $file = null; - $previous = null; try { $file = parent::findTemplate($logicalName); } catch (\Twig_Error_Loader $e) { diff --git a/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php b/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php index cefe0a02aa829..f4274b80a4443 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php @@ -108,7 +108,7 @@ public function testGet() } $builder->register('foobar', 'stdClass')->setScope('container'); - $this->assertTrue($builder->get('bar') === $builder->get('bar'), '->get() always returns the same instance if the service is shared'); + $this->assertSame($builder->get('bar'), $builder->get('bar'), '->get() always returns the same instance if the service is shared'); } /** diff --git a/src/Symfony/Component/Filesystem/Tests/LockHandlerTest.php b/src/Symfony/Component/Filesystem/Tests/LockHandlerTest.php index 0791cebc694b8..9ed871ea5a2a3 100644 --- a/src/Symfony/Component/Filesystem/Tests/LockHandlerTest.php +++ b/src/Symfony/Component/Filesystem/Tests/LockHandlerTest.php @@ -49,7 +49,7 @@ public function testErrorHandlingInLockIfLockPathBecomesUnwritable() $this->markTestSkipped('This test cannot run on Windows.'); } - $lockPath = sys_get_temp_dir().'/'.uniqid(); + $lockPath = sys_get_temp_dir().'/'.uniqid('', true); $e = null; $wrongMessage = null; diff --git a/src/Symfony/Component/Form/ChoiceList/Factory/DefaultChoiceListFactory.php b/src/Symfony/Component/Form/ChoiceList/Factory/DefaultChoiceListFactory.php index e08c9e51276be..fd24ccbeb11da 100644 --- a/src/Symfony/Component/Form/ChoiceList/Factory/DefaultChoiceListFactory.php +++ b/src/Symfony/Component/Form/ChoiceList/Factory/DefaultChoiceListFactory.php @@ -89,7 +89,7 @@ public function createView(ChoiceListInterface $list, $preferredChoices = null, if (!is_callable($preferredChoices) && !empty($preferredChoices)) { $preferredChoices = function ($choice) use ($preferredChoices) { - return false !== array_search($choice, $preferredChoices, true); + return in_array($choice, $preferredChoices, true); }; } diff --git a/src/Symfony/Component/Form/FormRenderer.php b/src/Symfony/Component/Form/FormRenderer.php index 15a8d08430cfe..9d1c075bb5fa7 100644 --- a/src/Symfony/Component/Form/FormRenderer.php +++ b/src/Symfony/Component/Form/FormRenderer.php @@ -316,6 +316,6 @@ public function searchAndRenderBlock(FormView $view, $blockNameSuffix, array $va */ public function humanize($text) { - return ucfirst(trim(strtolower(preg_replace(array('/([A-Z])/', '/[_\s]+/'), array('_$1', ' '), $text)))); + return ucfirst(strtolower(trim(preg_replace(array('/([A-Z])/', '/[_\s]+/'), array('_$1', ' '), $text)))); } } diff --git a/src/Symfony/Component/Security/Acl/Dbal/Schema.php b/src/Symfony/Component/Security/Acl/Dbal/Schema.php index ed9327ce7b139..864d0091af3ef 100644 --- a/src/Symfony/Component/Security/Acl/Dbal/Schema.php +++ b/src/Symfony/Component/Security/Acl/Dbal/Schema.php @@ -21,7 +21,7 @@ */ final class Schema extends BaseSchema { - protected $options; + private $options; /** * Constructor. diff --git a/src/Symfony/Component/Security/Core/Authorization/AccessDecisionManager.php b/src/Symfony/Component/Security/Core/Authorization/AccessDecisionManager.php index b8b6a776e9b8e..c18c2cbf09f0f 100644 --- a/src/Symfony/Component/Security/Core/Authorization/AccessDecisionManager.php +++ b/src/Symfony/Component/Security/Core/Authorization/AccessDecisionManager.php @@ -144,7 +144,6 @@ private function decideConsensus(TokenInterface $token, array $attributes, $obje { $grant = 0; $deny = 0; - $abstain = 0; foreach ($this->voters as $voter) { $result = $voter->vote($token, $object, $attributes); @@ -160,7 +159,6 @@ private function decideConsensus(TokenInterface $token, array $attributes, $obje break; default: - ++$abstain; break; } From b57895ccafe8a6de72846f9e1ce0e524964405e7 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Sat, 10 Jun 2017 17:54:55 -0700 Subject: [PATCH 0184/1099] [FrameworkBundle] deprecated validator.mapping.cache.doctrine.apc --- UPGRADE-3.4.md | 2 ++ UPGRADE-4.0.md | 2 ++ .../DependencyInjection/Configuration.php | 13 ++++++++++++- .../FrameworkBundle/Resources/config/validator.xml | 1 + 4 files changed, 17 insertions(+), 1 deletion(-) diff --git a/UPGRADE-3.4.md b/UPGRADE-3.4.md index e13d9b7febf64..34786d5464705 100644 --- a/UPGRADE-3.4.md +++ b/UPGRADE-3.4.md @@ -16,6 +16,8 @@ Finder FrameworkBundle --------------- + * The `validator.mapping.cache.doctrine.apc` service has been deprecated. + * Using the `KERNEL_DIR` environment variable or the automatic guessing based on the `phpunit.xml` / `phpunit.xml.dist` file location is deprecated since 3.4. Set the `KERNEL_CLASS` environment variable to the fully-qualified class name diff --git a/UPGRADE-4.0.md b/UPGRADE-4.0.md index fce693437fdfe..f6547fd0a0403 100644 --- a/UPGRADE-4.0.md +++ b/UPGRADE-4.0.md @@ -227,6 +227,8 @@ Form FrameworkBundle --------------- + * The `validator.mapping.cache.doctrine.apc` service has been removed. + * The `cache:clear` command does not warmup the cache anymore. Warmup should be done via the `cache:warmup` command. diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php index 611bfad97db82..350d632741a3e 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php @@ -661,7 +661,18 @@ private function addValidationSection(ArrayNodeDefinition $rootNode) ->info('validation configuration') ->{!class_exists(FullStack::class) && class_exists(Validation::class) ? 'canBeDisabled' : 'canBeEnabled'}() ->children() - ->scalarNode('cache')->end() + ->scalarNode('cache') + ->beforeNormalization() + // Can be removed in 4.0, when validator.mapping.cache.apc is removed + ->ifString()->then(function ($v) { + if ('validator.mapping.cache.apc' === $v && !class_exists('Doctrine\Common\Cache\ApcCache')) { + throw new LogicException('Doctrine APC cache for the validator cannot be enabled as the Doctrine Cache package is not installed.'); + } + + return $v; + }) + ->end() + ->end() ->booleanNode('enable_annotations')->{!class_exists(FullStack::class) && class_exists(Annotation::class) ? 'defaultTrue' : 'defaultFalse'}()->end() ->arrayNode('static_method') ->defaultValue(array('loadValidatorMetadata')) diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/validator.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/validator.xml index 5f505e859c82b..aa472d380cb33 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/validator.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/validator.xml @@ -57,6 +57,7 @@ + The "%service_id%" service is deprecated since Symfony 3.4 and will be removed in 4.0. Use a Psr6 cache like "validator.mapping.cache.symfony" instead. From a4d799ad0ede712c8ce6cd2f549700e29183f047 Mon Sep 17 00:00:00 2001 From: Guilhem Niot Date: Sun, 11 Jun 2017 11:30:54 +0200 Subject: [PATCH 0185/1099] [FrameworkBundle] Fix colliding service ids --- .../DependencyInjection/FrameworkExtension.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php index eb6ee7aeace87..3cdeb6afcb0b1 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php @@ -705,7 +705,7 @@ private function registerRouterConfiguration(array $config, ContainerBuilder $co ->addTag('routing.loader', array('priority' => -10)) ->addArgument(new Reference('annotation_reader')); - $container->register('routing.loader.directory', AnnotationDirectoryLoader::class) + $container->register('routing.loader.annotation.directory', AnnotationDirectoryLoader::class) ->setPublic(false) ->addTag('routing.loader', array('priority' => -10)) ->setArguments(array( @@ -713,7 +713,7 @@ private function registerRouterConfiguration(array $config, ContainerBuilder $co new Reference('routing.loader.annotation'), )); - $container->register('routing.loader.file', AnnotationFileLoader::class) + $container->register('routing.loader.annotation.file', AnnotationFileLoader::class) ->setPublic(false) ->addTag('routing.loader', array('priority' => -10)) ->setArguments(array( From 9251a2143d69a9add8520aea485e590d149bdf75 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Mon, 12 Jun 2017 11:39:35 +0200 Subject: [PATCH 0186/1099] [DI] Fix keys resolution in ResolveParameterPlaceHoldersPass --- .../Compiler/ResolveParameterPlaceHoldersPass.php | 10 +++++++--- .../Compiler/ResolveParameterPlaceHoldersPassTest.php | 8 ++++---- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/src/Symfony/Component/DependencyInjection/Compiler/ResolveParameterPlaceHoldersPass.php b/src/Symfony/Component/DependencyInjection/Compiler/ResolveParameterPlaceHoldersPass.php index 2444e441ee53e..69d48d9ef246b 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/ResolveParameterPlaceHoldersPass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/ResolveParameterPlaceHoldersPass.php @@ -65,10 +65,14 @@ protected function processValue($value, $isRoot = false) if (isset($changes['file'])) { $value->setFile($this->bag->resolveValue($value->getFile())); } - $value->setProperties($this->bag->resolveValue($value->getProperties())); - $value->setMethodCalls($this->bag->resolveValue($value->getMethodCalls())); } - return parent::processValue($value, $isRoot); + $value = parent::processValue($value, $isRoot); + + if ($value && is_array($value)) { + $value = array_combine($this->bag->resolveValue(array_keys($value)), $value); + } + + return $value; } } diff --git a/src/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveParameterPlaceHoldersPassTest.php b/src/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveParameterPlaceHoldersPassTest.php index 50be82d741119..b9459729e2e80 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveParameterPlaceHoldersPassTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveParameterPlaceHoldersPassTest.php @@ -41,12 +41,12 @@ public function testFactoryParametersShouldBeResolved() public function testArgumentParametersShouldBeResolved() { - $this->assertSame(array('bar', 'baz'), $this->fooDefinition->getArguments()); + $this->assertSame(array('bar', array('bar' => 'baz')), $this->fooDefinition->getArguments()); } public function testMethodCallParametersShouldBeResolved() { - $this->assertSame(array(array('foobar', array('bar', 'baz'))), $this->fooDefinition->getMethodCalls()); + $this->assertSame(array(array('foobar', array('bar', array('bar' => 'baz')))), $this->fooDefinition->getMethodCalls()); } public function testPropertyParametersShouldBeResolved() @@ -71,7 +71,7 @@ private function createContainerBuilder() $containerBuilder->setParameter('foo.class', 'Foo'); $containerBuilder->setParameter('foo.factory.class', 'FooFactory'); $containerBuilder->setParameter('foo.arg1', 'bar'); - $containerBuilder->setParameter('foo.arg2', 'baz'); + $containerBuilder->setParameter('foo.arg2', array('%foo.arg1%' => 'baz')); $containerBuilder->setParameter('foo.method', 'foobar'); $containerBuilder->setParameter('foo.property.name', 'bar'); $containerBuilder->setParameter('foo.property.value', 'baz'); @@ -80,7 +80,7 @@ private function createContainerBuilder() $fooDefinition = $containerBuilder->register('foo', '%foo.class%'); $fooDefinition->setFactory(array('%foo.factory.class%', 'getFoo')); - $fooDefinition->setArguments(array('%foo.arg1%', '%foo.arg2%')); + $fooDefinition->setArguments(array('%foo.arg1%', array('%foo.arg1%' => 'baz'))); $fooDefinition->addMethodCall('%foo.method%', array('%foo.arg1%', '%foo.arg2%')); $fooDefinition->setProperty('%foo.property.name%', '%foo.property.value%'); $fooDefinition->setFile('%foo.file%'); From 79bc4b017d340de96c1e7de705a3ad77140d184f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9goire=20Pineau?= Date: Mon, 12 Jun 2017 13:49:55 +0200 Subject: [PATCH 0187/1099] [Workflow] Added more keywords in the composer.json --- src/Symfony/Component/Workflow/composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/Workflow/composer.json b/src/Symfony/Component/Workflow/composer.json index b30d50091e1d6..f64d3cf8a4cd7 100644 --- a/src/Symfony/Component/Workflow/composer.json +++ b/src/Symfony/Component/Workflow/composer.json @@ -2,7 +2,7 @@ "name": "symfony/workflow", "type": "library", "description": "Symfony Workflow Component", - "keywords": ["workflow", "petrinet", "place", "transition"], + "keywords": ["workflow", "petrinet", "place", "transition", "statemachine", "state"], "homepage": "http://symfony.com", "license": "MIT", "authors": [ From 0ec8b1c1ff12cf422d846c6750287279762637b9 Mon Sep 17 00:00:00 2001 From: Christophe Coevoet Date: Mon, 12 Jun 2017 15:35:45 +0200 Subject: [PATCH 0188/1099] Fix the conditional definition of the SymfonyTestsListener --- .../Bridge/PhpUnit/SymfonyTestsListener.php | 82 +++++++++---------- 1 file changed, 41 insertions(+), 41 deletions(-) diff --git a/src/Symfony/Bridge/PhpUnit/SymfonyTestsListener.php b/src/Symfony/Bridge/PhpUnit/SymfonyTestsListener.php index 2dad6ef0095bc..c11fde9526eab 100644 --- a/src/Symfony/Bridge/PhpUnit/SymfonyTestsListener.php +++ b/src/Symfony/Bridge/PhpUnit/SymfonyTestsListener.php @@ -18,53 +18,53 @@ if (class_exists('PHPUnit_Runner_Version') && version_compare(\PHPUnit_Runner_Version::id(), '6.0.0', '<')) { class_alias('Symfony\Bridge\PhpUnit\Legacy\SymfonyTestsListener', 'Symfony\Bridge\PhpUnit\SymfonyTestsListener'); - - return; -} - -/** - * Collects and replays skipped tests. - * - * @author Nicolas Grekas - * - * @final - */ -class SymfonyTestsListener extends BaseTestListener -{ - private $trait; - - public function __construct(array $mockedNamespaces = array()) +// Using an early return instead of a else does not work when using the PHPUnit phar due to some weird PHP behavior (the class +// gets defined without executing the code before it and so the definition is not properly conditional) +} else { + /** + * Collects and replays skipped tests. + * + * @author Nicolas Grekas + * + * @final + */ + class SymfonyTestsListener extends BaseTestListener { - $this->trait = new Legacy\SymfonyTestsListenerTrait($mockedNamespaces); - } + private $trait; - public function globalListenerDisabled() - { - $this->trait->globalListenerDisabled(); - } + public function __construct(array $mockedNamespaces = array()) + { + $this->trait = new Legacy\SymfonyTestsListenerTrait($mockedNamespaces); + } - public function startTestSuite(TestSuite $suite) - { - return $this->trait->startTestSuite($suite); - } + public function globalListenerDisabled() + { + $this->trait->globalListenerDisabled(); + } - public function addSkippedTest(Test $test, \Exception $e, $time) - { - return $this->trait->addSkippedTest($test, $e, $time); - } + public function startTestSuite(TestSuite $suite) + { + return $this->trait->startTestSuite($suite); + } - public function startTest(Test $test) - { - return $this->trait->startTest($test); - } + public function addSkippedTest(Test $test, \Exception $e, $time) + { + return $this->trait->addSkippedTest($test, $e, $time); + } - public function addWarning(Test $test, Warning $e, $time) - { - return $this->trait->addWarning($test, $e, $time); - } + public function startTest(Test $test) + { + return $this->trait->startTest($test); + } - public function endTest(Test $test, $time) - { - return $this->trait->endTest($test, $time); + public function addWarning(Test $test, Warning $e, $time) + { + return $this->trait->addWarning($test, $e, $time); + } + + public function endTest(Test $test, $time) + { + return $this->trait->endTest($test, $time); + } } } From 8d70ca0ff4900dd1f7566c2092b1727fc8fa6bb1 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Mon, 12 Jun 2017 15:27:27 +0100 Subject: [PATCH 0189/1099] drop hard dependency on the Stopwatch component --- UPGRADE-3.4.md | 2 ++ src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md | 6 ++++-- .../DependencyInjection/FrameworkExtension.php | 10 ++++++++-- .../FrameworkBundle/Resources/config/debug_prod.xml | 3 --- src/Symfony/Bundle/FrameworkBundle/composer.json | 2 +- 5 files changed, 15 insertions(+), 8 deletions(-) diff --git a/UPGRADE-3.4.md b/UPGRADE-3.4.md index e13d9b7febf64..ada9848cd7ecc 100644 --- a/UPGRADE-3.4.md +++ b/UPGRADE-3.4.md @@ -16,6 +16,8 @@ Finder FrameworkBundle --------------- + * The `symfony/stopwatch` dependency has been removed, require it via `composer + require symfony/stopwatch` in your `dev` environment. * Using the `KERNEL_DIR` environment variable or the automatic guessing based on the `phpunit.xml` / `phpunit.xml.dist` file location is deprecated since 3.4. Set the `KERNEL_CLASS` environment variable to the fully-qualified class name diff --git a/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md b/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md index f5aa2c8f04f99..367520eac741d 100644 --- a/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md +++ b/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md @@ -4,8 +4,10 @@ CHANGELOG 3.4.0 ----- -* Deprecated using the `KERNEL_DIR` environment variable with `KernelTestCase::getKernelClass()`. -* Deprecated the `KernelTestCase::getPhpUnitXmlDir()` and `KernelTestCase::getPhpUnitCliConfigArgument()` methods. + * The `symfony/stopwatch` dependency has been removed, require it via `composer + require symfony/stopwatch` in your `dev` environment. + * Deprecated using the `KERNEL_DIR` environment variable with `KernelTestCase::getKernelClass()`. + * Deprecated the `KernelTestCase::getPhpUnitXmlDir()` and `KernelTestCase::getPhpUnitCliConfigArgument()` methods. 3.3.0 ----- diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php index eb6ee7aeace87..d03010b968b0c 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php @@ -61,6 +61,7 @@ use Symfony\Component\Serializer\Normalizer\DenormalizerInterface; use Symfony\Component\Serializer\Normalizer\JsonSerializableNormalizer; use Symfony\Component\Serializer\Normalizer\NormalizerInterface; +use Symfony\Component\Stopwatch\Stopwatch; use Symfony\Component\Validator\ConstraintValidatorInterface; use Symfony\Component\Validator\ObjectInitializerInterface; use Symfony\Component\WebLink\HttpHeaderSerializer; @@ -639,9 +640,14 @@ private function registerDebugConfiguration(array $config, ContainerBuilder $con { $loader->load('debug_prod.xml'); + if (class_exists(Stopwatch::class)) { + $container->register('debug.stopwatch', Stopwatch::class); + $container->setAlias(Stopwatch::class, 'debug.stopwatch'); + } + $debug = $container->getParameter('kernel.debug'); - if ($debug) { + if ($debug && class_exists(Stopwatch::class)) { $loader->load('debug.xml'); } @@ -881,7 +887,7 @@ private function registerTemplatingConfiguration(array $config, ContainerBuilder $container->setParameter('templating.helper.form.resources', $config['form']['resources']); - if ($container->getParameter('kernel.debug')) { + if ($container->getParameter('kernel.debug') && class_exists(Stopwatch::class)) { $loader->load('templating_debug.xml'); $container->setDefinition('templating.engine.php', $container->findDefinition('debug.templating.engine.php')); diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/debug_prod.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/debug_prod.xml index 60635b3c000be..fc4efe4e02253 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/debug_prod.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/debug_prod.xml @@ -23,9 +23,6 @@ true - - - %debug.file_link_format% diff --git a/src/Symfony/Bundle/FrameworkBundle/composer.json b/src/Symfony/Bundle/FrameworkBundle/composer.json index 2b11a0d737d31..3e81a3e779d69 100644 --- a/src/Symfony/Bundle/FrameworkBundle/composer.json +++ b/src/Symfony/Bundle/FrameworkBundle/composer.json @@ -29,7 +29,6 @@ "symfony/filesystem": "~2.8|~3.0|~4.0", "symfony/finder": "~2.8|~3.0|~4.0", "symfony/routing": "~3.4|~4.0", - "symfony/stopwatch": "~2.8|~3.0|~4.0", "doctrine/cache": "~1.0" }, "require-dev": { @@ -47,6 +46,7 @@ "symfony/security-core": "~3.2|~4.0", "symfony/security-csrf": "~2.8|~3.0|~4.0", "symfony/serializer": "~3.3|~4.0", + "symfony/stopwatch": "~2.8|~3.0|~4.0", "symfony/translation": "~3.2|~4.0", "symfony/templating": "~2.8|~3.0|~4.0", "symfony/validator": "~3.3|~4.0", From a4e336ea3494a5acc9343d537254807df10ee3a6 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Sat, 10 Jun 2017 17:55:29 -0700 Subject: [PATCH 0190/1099] [FrameworkBundle] removed doctrine/cache as a dependency --- UPGRADE-3.4.md | 3 +++ src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md | 2 ++ .../FrameworkBundle/DependencyInjection/Configuration.php | 4 ++-- .../DependencyInjection/FrameworkExtension.php | 4 ++++ src/Symfony/Bundle/FrameworkBundle/composer.json | 4 ++-- 5 files changed, 13 insertions(+), 4 deletions(-) diff --git a/UPGRADE-3.4.md b/UPGRADE-3.4.md index 34786d5464705..d7d1b00591249 100644 --- a/UPGRADE-3.4.md +++ b/UPGRADE-3.4.md @@ -16,6 +16,9 @@ Finder FrameworkBundle --------------- + * The `doctrine/cache` dependency has been removed; require it via `composer + require doctrine/cache` if you are using Doctrine cache in your project. + * The `validator.mapping.cache.doctrine.apc` service has been deprecated. * Using the `KERNEL_DIR` environment variable or the automatic guessing based diff --git a/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md b/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md index f5aa2c8f04f99..458877a67c7a6 100644 --- a/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md +++ b/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md @@ -4,6 +4,8 @@ CHANGELOG 3.4.0 ----- +* Removed `doctrine/cache` from the list of required dependencies in `composer.json` +* Deprecated `validator.mapping.cache.doctrine.apc` service * Deprecated using the `KERNEL_DIR` environment variable with `KernelTestCase::getKernelClass()`. * Deprecated the `KernelTestCase::getPhpUnitXmlDir()` and `KernelTestCase::getPhpUnitCliConfigArgument()` methods. diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php index 350d632741a3e..3f9c4eee02421 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php @@ -663,9 +663,9 @@ private function addValidationSection(ArrayNodeDefinition $rootNode) ->children() ->scalarNode('cache') ->beforeNormalization() - // Can be removed in 4.0, when validator.mapping.cache.apc is removed + // Can be removed in 4.0, when validator.mapping.cache.doctrine.apc is removed ->ifString()->then(function ($v) { - if ('validator.mapping.cache.apc' === $v && !class_exists('Doctrine\Common\Cache\ApcCache')) { + if ('validator.mapping.cache.doctrine.apc' === $v && !class_exists('Doctrine\Common\Cache\ApcCache')) { throw new LogicException('Doctrine APC cache for the validator cannot be enabled as the Doctrine Cache package is not installed.'); } diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php index eb6ee7aeace87..e25318d39bf44 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php @@ -1220,6 +1220,10 @@ private function registerAnnotationsConfiguration(array $config, ContainerBuilde $loader->load('annotations.xml'); if ('none' !== $config['cache']) { + if (!class_exists('Doctrine\Common\Cache\CacheProvider')) { + throw new LogicException('Annotations cannot be enabled as the Doctrine Cache library is not installed.'); + } + $cacheService = $config['cache']; if ('php_array' === $config['cache']) { diff --git a/src/Symfony/Bundle/FrameworkBundle/composer.json b/src/Symfony/Bundle/FrameworkBundle/composer.json index 2b11a0d737d31..48cd6d9f72752 100644 --- a/src/Symfony/Bundle/FrameworkBundle/composer.json +++ b/src/Symfony/Bundle/FrameworkBundle/composer.json @@ -29,10 +29,10 @@ "symfony/filesystem": "~2.8|~3.0|~4.0", "symfony/finder": "~2.8|~3.0|~4.0", "symfony/routing": "~3.4|~4.0", - "symfony/stopwatch": "~2.8|~3.0|~4.0", - "doctrine/cache": "~1.0" + "symfony/stopwatch": "~2.8|~3.0|~4.0" }, "require-dev": { + "doctrine/cache": "~1.0", "fig/link-util": "^1.0", "symfony/asset": "~3.3|~4.0", "symfony/browser-kit": "~2.8|~3.0|~4.0", From fddd754c0a28e56bc97a8d5693b5ff83d1f3d237 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Mon, 5 Jun 2017 22:55:00 +0200 Subject: [PATCH 0191/1099] add back support for legacy constant values --- src/Symfony/Component/HttpFoundation/Request.php | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/HttpFoundation/Request.php b/src/Symfony/Component/HttpFoundation/Request.php index 13ff1e05528fe..6fd0707b059ff 100644 --- a/src/Symfony/Component/HttpFoundation/Request.php +++ b/src/Symfony/Component/HttpFoundation/Request.php @@ -672,7 +672,17 @@ public static function setTrustedHeaderName($key, $value) { @trigger_error(sprintf('The "%s()" method is deprecated since version 3.3 and will be removed in 4.0. Use the $trustedHeaderSet argument of the Request::setTrustedProxies() method instead.', __METHOD__), E_USER_DEPRECATED); - if (!array_key_exists($key, self::$trustedHeaders)) { + if ('forwarded' === $key) { + $key = self::HEADER_FORWARDED; + } elseif ('client_ip' === $key) { + $key = self::HEADER_CLIENT_IP; + } elseif ('client_host' === $key) { + $key = self::HEADER_CLIENT_HOST; + } elseif ('client_proto' === $key) { + $key = self::HEADER_CLIENT_PROTO; + } elseif ('client_port' === $key) { + $key = self::HEADER_CLIENT_PORT; + } elseif (!array_key_exists($key, self::$trustedHeaders)) { throw new \InvalidArgumentException(sprintf('Unable to set the trusted header name for key "%s".', $key)); } From 2ea26c1ffe76007fc93628bbe86783c7e11fdc1e Mon Sep 17 00:00:00 2001 From: Christophe Coevoet Date: Tue, 13 Jun 2017 10:29:19 +0200 Subject: [PATCH 0192/1099] Fix the usage of FrameworkBundle in debug mode without Stopwatch --- .../DependencyInjection/FrameworkExtension.php | 4 ++++ src/Symfony/Bundle/FrameworkBundle/Resources/config/debug.xml | 4 ---- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php index 71fbfdfeaaadf..6ad4cb5b9d01c 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php @@ -647,6 +647,10 @@ private function registerDebugConfiguration(array $config, ContainerBuilder $con $debug = $container->getParameter('kernel.debug'); + if ($debug) { + $container->setParameter('debug.container.dump', '%kernel.cache_dir%/%kernel.container_class%.xml'); + } + if ($debug && class_exists(Stopwatch::class)) { $loader->load('debug.xml'); } diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/debug.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/debug.xml index 58a086b2129bf..aa988dc5b93cf 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/debug.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/debug.xml @@ -4,10 +4,6 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd"> - - %kernel.cache_dir%/%kernel.container_class%.xml - - From 369f19fcfd8569015a576270c9498fe7a2095ab3 Mon Sep 17 00:00:00 2001 From: Robin Chalas Date: Fri, 2 Jun 2017 16:08:16 +0200 Subject: [PATCH 0193/1099] Give info about called security listeners in profiler --- .../Bundle/SecurityBundle/CHANGELOG.md | 1 + .../DataCollector/SecurityDataCollector.php | 17 ++++- .../Debug/TraceableFirewallListener.php | 43 +++++++++++ .../SecurityBundle/Debug/WrappedListener.php | 76 +++++++++++++++++++ .../Resources/config/collectors.xml | 1 + .../Resources/config/security_debug.xml | 9 +++ .../views/Collector/security.html.twig | 42 ++++++++++ .../SecurityDataCollectorTest.php | 51 ++++++++++++- .../Debug/TraceableFirewallListenerTest.php | 65 ++++++++++++++++ .../Bundle/SecurityBundle/composer.json | 6 +- .../Component/Security/Http/Firewall.php | 20 +++-- 11 files changed, 317 insertions(+), 14 deletions(-) create mode 100644 src/Symfony/Bundle/SecurityBundle/Debug/TraceableFirewallListener.php create mode 100644 src/Symfony/Bundle/SecurityBundle/Debug/WrappedListener.php create mode 100644 src/Symfony/Bundle/SecurityBundle/Tests/Debug/TraceableFirewallListenerTest.php diff --git a/src/Symfony/Bundle/SecurityBundle/CHANGELOG.md b/src/Symfony/Bundle/SecurityBundle/CHANGELOG.md index 32d00431262b7..a9d10bd8dacc8 100644 --- a/src/Symfony/Bundle/SecurityBundle/CHANGELOG.md +++ b/src/Symfony/Bundle/SecurityBundle/CHANGELOG.md @@ -5,6 +5,7 @@ CHANGELOG ----- * [BC BREAK] `FirewallContext::getListeners()` now returns `\Traversable|array` + * added info about called security listeners in profiler 3.3.0 ----- diff --git a/src/Symfony/Bundle/SecurityBundle/DataCollector/SecurityDataCollector.php b/src/Symfony/Bundle/SecurityBundle/DataCollector/SecurityDataCollector.php index 508d98b52f67e..d25a5be606ec9 100644 --- a/src/Symfony/Bundle/SecurityBundle/DataCollector/SecurityDataCollector.php +++ b/src/Symfony/Bundle/SecurityBundle/DataCollector/SecurityDataCollector.php @@ -19,6 +19,7 @@ use Symfony\Component\HttpKernel\DataCollector\DataCollector; use Symfony\Component\HttpKernel\DataCollector\LateDataCollectorInterface; use Symfony\Component\Security\Core\Role\RoleInterface; +use Symfony\Bundle\SecurityBundle\Debug\TraceableFirewallListener; use Symfony\Component\Security\Http\Logout\LogoutUrlGenerator; use Symfony\Component\Security\Core\Authorization\AccessDecisionManagerInterface; use Symfony\Component\Security\Core\Authorization\TraceableAccessDecisionManager; @@ -39,6 +40,7 @@ class SecurityDataCollector extends DataCollector implements LateDataCollectorIn private $logoutUrlGenerator; private $accessDecisionManager; private $firewallMap; + private $firewall; private $hasVarDumper; /** @@ -49,14 +51,16 @@ class SecurityDataCollector extends DataCollector implements LateDataCollectorIn * @param LogoutUrlGenerator|null $logoutUrlGenerator * @param AccessDecisionManagerInterface|null $accessDecisionManager * @param FirewallMapInterface|null $firewallMap + * @param TraceableFirewallListener|null $firewall */ - public function __construct(TokenStorageInterface $tokenStorage = null, RoleHierarchyInterface $roleHierarchy = null, LogoutUrlGenerator $logoutUrlGenerator = null, AccessDecisionManagerInterface $accessDecisionManager = null, FirewallMapInterface $firewallMap = null) + public function __construct(TokenStorageInterface $tokenStorage = null, RoleHierarchyInterface $roleHierarchy = null, LogoutUrlGenerator $logoutUrlGenerator = null, AccessDecisionManagerInterface $accessDecisionManager = null, FirewallMapInterface $firewallMap = null, TraceableFirewallListener $firewall = null) { $this->tokenStorage = $tokenStorage; $this->roleHierarchy = $roleHierarchy; $this->logoutUrlGenerator = $logoutUrlGenerator; $this->accessDecisionManager = $accessDecisionManager; $this->firewallMap = $firewallMap; + $this->firewall = $firewall; $this->hasVarDumper = class_exists(ClassStub::class); } @@ -167,6 +171,12 @@ public function collect(Request $request, Response $response, \Exception $except ); } } + + // collect firewall listeners information + $this->data['listeners'] = array(); + if ($this->firewall) { + $this->data['listeners'] = $this->firewall->getWrappedListeners(); + } } public function lateCollect() @@ -305,6 +315,11 @@ public function getFirewall() return $this->data['firewall']; } + public function getListeners() + { + return $this->data['listeners']; + } + /** * {@inheritdoc} */ diff --git a/src/Symfony/Bundle/SecurityBundle/Debug/TraceableFirewallListener.php b/src/Symfony/Bundle/SecurityBundle/Debug/TraceableFirewallListener.php new file mode 100644 index 0000000000000..7c45a60c1a900 --- /dev/null +++ b/src/Symfony/Bundle/SecurityBundle/Debug/TraceableFirewallListener.php @@ -0,0 +1,43 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\SecurityBundle\Debug; + +use Symfony\Bundle\SecurityBundle\EventListener\FirewallListener; +use Symfony\Component\HttpKernel\Event\GetResponseEvent; + +/** + * Firewall collecting called listeners. + * + * @author Robin Chalas + */ +final class TraceableFirewallListener extends FirewallListener +{ + private $wrappedListeners; + + public function getWrappedListeners() + { + return $this->wrappedListeners; + } + + protected function handleRequest(GetResponseEvent $event, $listeners) + { + foreach ($listeners as $listener) { + $wrappedListener = new WrappedListener($listener); + $wrappedListener->handle($event); + $this->wrappedListeners[] = $wrappedListener->getInfo(); + + if ($event->hasResponse()) { + break; + } + } + } +} diff --git a/src/Symfony/Bundle/SecurityBundle/Debug/WrappedListener.php b/src/Symfony/Bundle/SecurityBundle/Debug/WrappedListener.php new file mode 100644 index 0000000000000..435ecc5feb573 --- /dev/null +++ b/src/Symfony/Bundle/SecurityBundle/Debug/WrappedListener.php @@ -0,0 +1,76 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\SecurityBundle\Debug; + +use Symfony\Component\HttpKernel\Event\GetResponseEvent; +use Symfony\Component\Security\Http\Firewall\ListenerInterface; +use Symfony\Component\VarDumper\Caster\ClassStub; + +/** + * Wraps a security listener for calls record. + * + * @author Robin Chalas + */ +final class WrappedListener implements ListenerInterface +{ + private $response; + private $listener; + private $time; + private $stub; + private static $hasVarDumper; + + public function __construct(ListenerInterface $listener) + { + $this->listener = $listener; + + if (null === self::$hasVarDumper) { + self::$hasVarDumper = class_exists(ClassStub::class); + } + } + + /** + * {@inheritdoc} + */ + public function handle(GetResponseEvent $event) + { + $startTime = microtime(true); + $this->listener->handle($event); + $this->time = microtime(true) - $startTime; + $this->response = $event->getResponse(); + } + + /** + * Proxies all method calls to the original listener. + */ + public function __call($method, $arguments) + { + return call_user_func_array(array($this->listener, $method), $arguments); + } + + public function getWrappedListener() + { + return $this->listener; + } + + public function getInfo() + { + if (null === $this->stub) { + $this->stub = self::$hasVarDumper ? new ClassStub(get_class($this->listener)) : get_class($this->listener); + } + + return array( + 'response' => $this->response, + 'time' => $this->time, + 'stub' => $this->stub, + ); + } +} diff --git a/src/Symfony/Bundle/SecurityBundle/Resources/config/collectors.xml b/src/Symfony/Bundle/SecurityBundle/Resources/config/collectors.xml index 50ee3bba2b897..a8170af900ff9 100644 --- a/src/Symfony/Bundle/SecurityBundle/Resources/config/collectors.xml +++ b/src/Symfony/Bundle/SecurityBundle/Resources/config/collectors.xml @@ -14,6 +14,7 @@ + diff --git a/src/Symfony/Bundle/SecurityBundle/Resources/config/security_debug.xml b/src/Symfony/Bundle/SecurityBundle/Resources/config/security_debug.xml index f836925ef8fd0..6087f9ee5b19e 100644 --- a/src/Symfony/Bundle/SecurityBundle/Resources/config/security_debug.xml +++ b/src/Symfony/Bundle/SecurityBundle/Resources/config/security_debug.xml @@ -10,5 +10,14 @@ + + + + + + + + + diff --git a/src/Symfony/Bundle/SecurityBundle/Resources/views/Collector/security.html.twig b/src/Symfony/Bundle/SecurityBundle/Resources/views/Collector/security.html.twig index 9cd6ec4d78db2..46804a4d2ed2e 100644 --- a/src/Symfony/Bundle/SecurityBundle/Resources/views/Collector/security.html.twig +++ b/src/Symfony/Bundle/SecurityBundle/Resources/views/Collector/security.html.twig @@ -150,6 +150,8 @@ {% if collector.firewall.security_enabled %} +

Configuration

+ @@ -188,6 +190,46 @@
+ +

Listeners

+ + {% if collector.listeners|default([]) is empty %} +
+

No security listeners have been recorded. Check that debugging is enabled in the kernel.

+
+ {% else %} + + + + + + + + + + {% set previous_event = (collector.listeners|first) %} + {% for listener in collector.listeners %} + {% if loop.first or listener != previous_event %} + {% if not loop.first %} + + {% endif %} + + + {% set previous_event = listener %} + {% endif %} + + + + + + + + {% if loop.last %} + + {% endif %} + {% endfor %} +
ListenerDurationResponse
{{ profiler_dump(listener.stub) }}{{ '%0.2f'|format(listener.time * 1000) }} ms{{ listener.response ? profiler_dump(listener.response) : '(none)' }}
+ {% endif %} {% endif %} {% elseif collector.enabled %}
diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DataCollector/SecurityDataCollectorTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/DataCollector/SecurityDataCollectorTest.php index f155f901c9c3c..1c75641daf697 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/DataCollector/SecurityDataCollectorTest.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DataCollector/SecurityDataCollectorTest.php @@ -13,13 +13,19 @@ use PHPUnit\Framework\TestCase; use Symfony\Bundle\SecurityBundle\DataCollector\SecurityDataCollector; +use Symfony\Bundle\SecurityBundle\Debug\TraceableFirewallListener; use Symfony\Bundle\SecurityBundle\Security\FirewallConfig; use Symfony\Bundle\SecurityBundle\Security\FirewallMap; +use Symfony\Component\EventDispatcher\EventDispatcher; +use Symfony\Component\HttpKernel\Event\GetResponseEvent; +use Symfony\Component\HttpKernel\HttpKernelInterface; use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage; use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken; use Symfony\Component\Security\Core\Role\Role; use Symfony\Component\Security\Core\Role\RoleHierarchy; +use Symfony\Component\Security\Http\Firewall\ListenerInterface; use Symfony\Component\Security\Http\FirewallMapInterface; +use Symfony\Component\Security\Http\Logout\LogoutUrlGenerator; class SecurityDataCollectorTest extends TestCase { @@ -89,7 +95,7 @@ public function testGetFirewall() ->with($request) ->willReturn($firewallConfig); - $collector = new SecurityDataCollector(null, null, null, null, $firewallMap); + $collector = new SecurityDataCollector(null, null, null, null, $firewallMap, new TraceableFirewallListener($firewallMap, new EventDispatcher(), new LogoutUrlGenerator())); $collector->collect($request, $this->getResponse()); $collector->lateCollect(); $collected = $collector->getFirewall(); @@ -124,7 +130,7 @@ public function testGetFirewallReturnsNull() ->disableOriginalConstructor() ->getMock(); - $collector = new SecurityDataCollector(null, null, null, null, $firewallMap); + $collector = new SecurityDataCollector(null, null, null, null, $firewallMap, new TraceableFirewallListener($firewallMap, new EventDispatcher(), new LogoutUrlGenerator())); $collector->collect($request, $response); $this->assertNull($collector->getFirewall()); @@ -134,11 +140,50 @@ public function testGetFirewallReturnsNull() ->disableOriginalConstructor() ->getMock(); - $collector = new SecurityDataCollector(null, null, null, null, $firewallMap); + $collector = new SecurityDataCollector(null, null, null, null, $firewallMap, new TraceableFirewallListener($firewallMap, new EventDispatcher(), new LogoutUrlGenerator())); $collector->collect($request, $response); $this->assertNull($collector->getFirewall()); } + /** + * @group time-sensitive + */ + public function testGetListeners() + { + $request = $this->getRequest(); + $event = new GetResponseEvent($this->getMockBuilder(HttpKernelInterface::class)->getMock(), $request, HttpKernelInterface::MASTER_REQUEST); + $event->setResponse($response = $this->getResponse()); + $listener = $this->getMockBuilder(ListenerInterface::class)->getMock(); + $listener + ->expects($this->once()) + ->method('handle') + ->with($event); + $firewallMap = $this + ->getMockBuilder(FirewallMap::class) + ->disableOriginalConstructor() + ->getMock(); + $firewallMap + ->expects($this->any()) + ->method('getFirewallConfig') + ->with($request) + ->willReturn(null); + $firewallMap + ->expects($this->once()) + ->method('getListeners') + ->with($request) + ->willReturn(array(array($listener), null)); + + $firewall = new TraceableFirewallListener($firewallMap, new EventDispatcher(), new LogoutUrlGenerator()); + $firewall->onKernelRequest($event); + + $collector = new SecurityDataCollector(null, null, null, null, $firewallMap, $firewall); + $collector->collect($request, $response); + + $this->assertNotEmpty($collected = $collector->getListeners()[0]); + $collector->lateCollect(); + $this->addToAssertionCount(1); + } + public function provideRoles() { return array( diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Debug/TraceableFirewallListenerTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/Debug/TraceableFirewallListenerTest.php new file mode 100644 index 0000000000000..3ddbb1fd4c438 --- /dev/null +++ b/src/Symfony/Bundle/SecurityBundle/Tests/Debug/TraceableFirewallListenerTest.php @@ -0,0 +1,65 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\SecurityBundle\Tests; + +use PHPUnit\Framework\TestCase; +use Symfony\Bundle\SecurityBundle\Debug\TraceableFirewallListener; +use Symfony\Bundle\SecurityBundle\Security\FirewallMap; +use Symfony\Component\EventDispatcher\EventDispatcher; +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\HttpKernel\Event\GetResponseEvent; +use Symfony\Component\HttpKernel\HttpKernelInterface; +use Symfony\Component\Security\Http\Firewall\ListenerInterface; +use Symfony\Component\Security\Http\Logout\LogoutUrlGenerator; +use Symfony\Component\VarDumper\Caster\ClassStub; + +/** + * @group time-sensitive + */ +class TraceableFirewallListenerTest extends TestCase +{ + public function testOnKernelRequestRecordsListeners() + { + $request = new Request(); + $event = new GetResponseEvent($this->getMockBuilder(HttpKernelInterface::class)->getMock(), $request, HttpKernelInterface::MASTER_REQUEST); + $event->setResponse($response = new Response()); + $listener = $this->getMockBuilder(ListenerInterface::class)->getMock(); + $listener + ->expects($this->once()) + ->method('handle') + ->with($event); + $firewallMap = $this + ->getMockBuilder(FirewallMap::class) + ->disableOriginalConstructor() + ->getMock(); + $firewallMap + ->expects($this->once()) + ->method('getFirewallConfig') + ->with($request) + ->willReturn(null); + $firewallMap + ->expects($this->once()) + ->method('getListeners') + ->with($request) + ->willReturn(array(array($listener), null)); + + $firewall = new TraceableFirewallListener($firewallMap, new EventDispatcher(), new LogoutUrlGenerator()); + $firewall->onKernelRequest($event); + + $listeners = $firewall->getWrappedListeners(); + $this->assertCount(1, $listeners); + $this->assertSame($response, $listeners[0]['response']); + $this->assertInstanceOf(ClassStub::class, $listeners[0]['stub']); + $this->assertSame(get_class($listener), (string) $listeners[0]['stub']); + } +} diff --git a/src/Symfony/Bundle/SecurityBundle/composer.json b/src/Symfony/Bundle/SecurityBundle/composer.json index 19d724fc769c6..31c2731e15272 100644 --- a/src/Symfony/Bundle/SecurityBundle/composer.json +++ b/src/Symfony/Bundle/SecurityBundle/composer.json @@ -17,7 +17,7 @@ ], "require": { "php": ">=5.5.9", - "symfony/security": "~3.3|~4.0", + "symfony/security": "~3.4|~4.0", "symfony/dependency-injection": "~3.3|~4.0", "symfony/http-kernel": "~3.3|~4.0", "symfony/polyfill-php70": "~1.0" @@ -28,6 +28,7 @@ "symfony/console": "~3.2|~4.0", "symfony/css-selector": "~2.8|~3.0|~4.0", "symfony/dom-crawler": "~2.8|~3.0|~4.0", + "symfony/event-dispatcher": "~3.3|~4.0", "symfony/form": "^2.8.18|^3.2.5|~4.0", "symfony/framework-bundle": "^3.2.8|~4.0", "symfony/http-foundation": "~2.8|~3.0|~4.0", @@ -44,7 +45,8 @@ "twig/twig": "~1.34|~2.4" }, "conflict": { - "symfony/var-dumper": "<3.3" + "symfony/var-dumper": "<3.3", + "symfony/event-dispatcher": "<3.3" }, "suggest": { "symfony/security-acl": "For using the ACL functionality of this bundle" diff --git a/src/Symfony/Component/Security/Http/Firewall.php b/src/Symfony/Component/Security/Http/Firewall.php index 7bad47a5bed01..fde2a624cf0e4 100644 --- a/src/Symfony/Component/Security/Http/Firewall.php +++ b/src/Symfony/Component/Security/Http/Firewall.php @@ -64,14 +64,7 @@ public function onKernelRequest(GetResponseEvent $event) $exceptionListener->register($this->dispatcher); } - // initiate the listener chain - foreach ($listeners as $listener) { - $listener->handle($event); - - if ($event->hasResponse()) { - break; - } - } + return $this->handleRequest($event, $listeners); } public function onKernelFinishRequest(FinishRequestEvent $event) @@ -94,4 +87,15 @@ public static function getSubscribedEvents() KernelEvents::FINISH_REQUEST => 'onKernelFinishRequest', ); } + + protected function handleRequest(GetResponseEvent $event, $listeners) + { + foreach ($listeners as $listener) { + $listener->handle($event); + + if ($event->hasResponse()) { + break; + } + } + } } From 3f7fd432dfb3a2e3ab92b1681d6ec25a32cd1574 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Malte=20Bl=C3=A4ttermann?= Date: Sun, 11 Jun 2017 22:11:35 +0200 Subject: [PATCH 0194/1099] Fix Usage with anonymous classes Replace forbidden characters in the the class names of Anonymous Classes in form of "class@anonymous /symfony/src/Symfony/Component/PropertyAccess/Tests/PropertyAccessorTest.php0x7f3f5f267ad5" Wrapped in eval to avoid PHP parsing errors < 7 --- .../PropertyAccess/PropertyAccessor.php | 4 +- .../Tests/PropertyAccessorTest.php | 60 +++++++++++++++++++ 2 files changed, 62 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/PropertyAccess/PropertyAccessor.php b/src/Symfony/Component/PropertyAccess/PropertyAccessor.php index 69d7fc0e9f1aa..131576e261fcf 100644 --- a/src/Symfony/Component/PropertyAccess/PropertyAccessor.php +++ b/src/Symfony/Component/PropertyAccess/PropertyAccessor.php @@ -523,7 +523,7 @@ private function readProperty($zval, $property) */ private function getReadAccessInfo($class, $property) { - $key = $class.'..'.$property; + $key = (false !== strpos($class, '@') ? rawurlencode($class) : $class).'..'.$property; if (isset($this->readPropertyCache[$key])) { return $this->readPropertyCache[$key]; @@ -702,7 +702,7 @@ private function writeCollection($zval, $property, $collection, $addMethod, $rem */ private function getWriteAccessInfo($class, $property, $value) { - $key = $class.'..'.$property; + $key = (false !== strpos($class, '@') ? rawurlencode($class) : $class).'..'.$property; if (isset($this->writePropertyCache[$key])) { return $this->writePropertyCache[$key]; diff --git a/src/Symfony/Component/PropertyAccess/Tests/PropertyAccessorTest.php b/src/Symfony/Component/PropertyAccess/Tests/PropertyAccessorTest.php index e2ef9296ed50f..e23f6cd6dba30 100644 --- a/src/Symfony/Component/PropertyAccess/Tests/PropertyAccessorTest.php +++ b/src/Symfony/Component/PropertyAccess/Tests/PropertyAccessorTest.php @@ -578,4 +578,64 @@ public function testThrowTypeErrorWithInterface() $this->propertyAccessor->setValue($object, 'countable', 'This is a string, \Countable expected.'); } + + /** + * @requires PHP 7.0 + */ + public function testAnonymousClassRead() + { + $value = 'bar'; + + $obj = $this->generateAnonymousClass($value); + + $propertyAccessor = new PropertyAccessor(false, false, new ArrayAdapter()); + + $this->assertEquals($value, $propertyAccessor->getValue($obj, 'foo')); + } + + /** + * @requires PHP 7.0 + */ + public function testAnonymousClassWrite() + { + $value = 'bar'; + + $obj = $this->generateAnonymousClass(''); + + $propertyAccessor = new PropertyAccessor(false, false, new ArrayAdapter()); + $propertyAccessor->setValue($obj, 'foo', $value); + + $this->assertEquals($value, $propertyAccessor->getValue($obj, 'foo')); + } + + private function generateAnonymousClass($value) + { + $obj = eval('return new class($value) + { + private $foo; + + public function __construct($foo) + { + $this->foo = $foo; + } + + /** + * @return mixed + */ + public function getFoo() + { + return $this->foo; + } + + /** + * @param mixed $foo + */ + public function setFoo($foo) + { + $this->foo = $foo; + } + };'); + + return $obj; + } } From 7c3d0c7a46a48a8174fd72cc649bacf0c3ae7cb2 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Mon, 12 Jun 2017 13:31:43 +0200 Subject: [PATCH 0195/1099] [DI] Reference instead of inline for array-params --- .../Compiler/PassConfig.php | 2 +- .../ResolveParameterPlaceHoldersPass.php | 10 +- .../DependencyInjection/Dumper/PhpDumper.php | 25 ++- .../Tests/Dumper/PhpDumperTest.php | 14 ++ .../Tests/Fixtures/php/services10.php | 10 +- .../Tests/Fixtures/php/services12.php | 10 +- .../Tests/Fixtures/php/services26.php | 10 +- .../Tests/Fixtures/php/services8.php | 10 +- .../Tests/Fixtures/php/services9_compiled.php | 10 +- .../Fixtures/php/services_array_params.php | 179 ++++++++++++++++++ 10 files changed, 252 insertions(+), 28 deletions(-) create mode 100644 src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_array_params.php diff --git a/src/Symfony/Component/DependencyInjection/Compiler/PassConfig.php b/src/Symfony/Component/DependencyInjection/Compiler/PassConfig.php index 5ee8f98851438..57ecc42ea0272 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/PassConfig.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/PassConfig.php @@ -51,7 +51,7 @@ public function __construct() new ResolveDefinitionTemplatesPass(), new ServiceLocatorTagPass(), new DecoratorServicePass(), - new ResolveParameterPlaceHoldersPass(), + new ResolveParameterPlaceHoldersPass(false), new ResolveFactoryClassPass(), new FactoryReturnTypePass($resolveClassPass), new CheckDefinitionValidityPass(), diff --git a/src/Symfony/Component/DependencyInjection/Compiler/ResolveParameterPlaceHoldersPass.php b/src/Symfony/Component/DependencyInjection/Compiler/ResolveParameterPlaceHoldersPass.php index 69d48d9ef246b..75e629ab6f083 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/ResolveParameterPlaceHoldersPass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/ResolveParameterPlaceHoldersPass.php @@ -23,6 +23,12 @@ class ResolveParameterPlaceHoldersPass extends AbstractRecursivePass { private $bag; + private $resolveArrays; + + public function __construct($resolveArrays = true) + { + $this->resolveArrays = $resolveArrays; + } /** * {@inheritdoc} @@ -55,7 +61,9 @@ public function process(ContainerBuilder $container) protected function processValue($value, $isRoot = false) { if (is_string($value)) { - return $this->bag->resolveValue($value); + $v = $this->bag->resolveValue($value); + + return $this->resolveArrays || !$v || !is_array($v) ? $v : $value; } if ($value instanceof Definition) { $changes = $value->getChanges(); diff --git a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php index 6c2f1bf6e84fb..eaa0bddca7109 100644 --- a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php +++ b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php @@ -1061,10 +1061,12 @@ private function addDefaultParametersMethod() */ public function getParameter($name) { - $name = strtolower($name); + if (!(isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters))) { + $name = strtolower($name); - if (!(isset($this->parameters[$name]) || array_key_exists($name, $this->parameters) || isset($this->loadedDynamicParameters[$name]))) { - throw new InvalidArgumentException(sprintf('The parameter "%s" must be defined.', $name)); + if (!(isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters))) { + throw new InvalidArgumentException(sprintf('The parameter "%s" must be defined.', $name)); + } } if (isset($this->loadedDynamicParameters[$name])) { return $this->loadedDynamicParameters[$name] ? $this->dynamicParameters[$name] : $this->getDynamicParameter($name); @@ -1080,7 +1082,7 @@ public function hasParameter($name) { $name = strtolower($name); - return isset($this->parameters[$name]) || array_key_exists($name, $this->parameters) || isset($this->loadedDynamicParameters[$name]); + return isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters); } /** @@ -1580,11 +1582,22 @@ private function dumpLiteralClass($class) */ private function dumpParameter($name) { + $name = strtolower($name); + if ($this->container->isCompiled() && $this->container->hasParameter($name)) { - return $this->dumpValue($this->container->getParameter($name), false); + $value = $this->container->getParameter($name); + $dumpedValue = $this->dumpValue($value, false); + + if (!$value || !is_array($value)) { + return $dumpedValue; + } + + if (!preg_match("/\\\$this->(?:getEnv\('\w++'\)|targetDirs\[\d++\])/", $dumpedValue)) { + return sprintf("\$this->parameters['%s']", $name); + } } - return sprintf("\$this->getParameter('%s')", strtolower($name)); + return sprintf("\$this->getParameter('%s')", $name); } /** diff --git a/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php b/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php index bd8a95bab91eb..c7dd29859160f 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php @@ -584,4 +584,18 @@ public function testPrivateWithIgnoreOnInvalidReference() $container = new \Symfony_DI_PhpDumper_Test_Private_With_Ignore_On_Invalid_Reference(); $this->assertInstanceOf('BazClass', $container->get('bar')->getBaz()); } + + public function testArrayParameters() + { + $container = new ContainerBuilder(); + $container->setParameter('array_1', array(123)); + $container->setParameter('array_2', array(__DIR__)); + $container->register('bar', 'BarClass') + ->addMethodCall('setBaz', array('%array_1%', '%array_2%', '%%array_1%%')); + $container->compile(); + + $dumper = new PhpDumper($container); + + $this->assertStringEqualsFile(self::$fixturesPath.'/php/services_array_params.php', str_replace('\\\\Dumper', '/Dumper', $dumper->dump(array('file' => self::$fixturesPath.'/php/services_array_params.php')))); + } } diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services10.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services10.php index 1cc1cc3d1644b..a5c3fd454c706 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services10.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services10.php @@ -80,10 +80,12 @@ protected function getTestService() */ public function getParameter($name) { - $name = strtolower($name); + if (!(isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters))) { + $name = strtolower($name); - if (!(isset($this->parameters[$name]) || array_key_exists($name, $this->parameters) || isset($this->loadedDynamicParameters[$name]))) { - throw new InvalidArgumentException(sprintf('The parameter "%s" must be defined.', $name)); + if (!(isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters))) { + throw new InvalidArgumentException(sprintf('The parameter "%s" must be defined.', $name)); + } } if (isset($this->loadedDynamicParameters[$name])) { return $this->loadedDynamicParameters[$name] ? $this->dynamicParameters[$name] : $this->getDynamicParameter($name); @@ -99,7 +101,7 @@ public function hasParameter($name) { $name = strtolower($name); - return isset($this->parameters[$name]) || array_key_exists($name, $this->parameters) || isset($this->loadedDynamicParameters[$name]); + return isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters); } /** diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services12.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services12.php index 511127c1008d3..1ff201baf495b 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services12.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services12.php @@ -84,10 +84,12 @@ protected function getTestService() */ public function getParameter($name) { - $name = strtolower($name); + if (!(isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters))) { + $name = strtolower($name); - if (!(isset($this->parameters[$name]) || array_key_exists($name, $this->parameters) || isset($this->loadedDynamicParameters[$name]))) { - throw new InvalidArgumentException(sprintf('The parameter "%s" must be defined.', $name)); + if (!(isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters))) { + throw new InvalidArgumentException(sprintf('The parameter "%s" must be defined.', $name)); + } } if (isset($this->loadedDynamicParameters[$name])) { return $this->loadedDynamicParameters[$name] ? $this->dynamicParameters[$name] : $this->getDynamicParameter($name); @@ -103,7 +105,7 @@ public function hasParameter($name) { $name = strtolower($name); - return isset($this->parameters[$name]) || array_key_exists($name, $this->parameters) || isset($this->loadedDynamicParameters[$name]); + return isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters); } /** diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services26.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services26.php index 809d70da5e52a..b2b2da68ffa81 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services26.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services26.php @@ -82,10 +82,12 @@ protected function getTestService() */ public function getParameter($name) { - $name = strtolower($name); + if (!(isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters))) { + $name = strtolower($name); - if (!(isset($this->parameters[$name]) || array_key_exists($name, $this->parameters) || isset($this->loadedDynamicParameters[$name]))) { - throw new InvalidArgumentException(sprintf('The parameter "%s" must be defined.', $name)); + if (!(isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters))) { + throw new InvalidArgumentException(sprintf('The parameter "%s" must be defined.', $name)); + } } if (isset($this->loadedDynamicParameters[$name])) { return $this->loadedDynamicParameters[$name] ? $this->dynamicParameters[$name] : $this->getDynamicParameter($name); @@ -101,7 +103,7 @@ public function hasParameter($name) { $name = strtolower($name); - return isset($this->parameters[$name]) || array_key_exists($name, $this->parameters) || isset($this->loadedDynamicParameters[$name]); + return isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters); } /** diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services8.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services8.php index bfc1d68bd1ef6..f85e3251be8bd 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services8.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services8.php @@ -64,10 +64,12 @@ public function isFrozen() */ public function getParameter($name) { - $name = strtolower($name); + if (!(isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters))) { + $name = strtolower($name); - if (!(isset($this->parameters[$name]) || array_key_exists($name, $this->parameters) || isset($this->loadedDynamicParameters[$name]))) { - throw new InvalidArgumentException(sprintf('The parameter "%s" must be defined.', $name)); + if (!(isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters))) { + throw new InvalidArgumentException(sprintf('The parameter "%s" must be defined.', $name)); + } } if (isset($this->loadedDynamicParameters[$name])) { return $this->loadedDynamicParameters[$name] ? $this->dynamicParameters[$name] : $this->getDynamicParameter($name); @@ -83,7 +85,7 @@ public function hasParameter($name) { $name = strtolower($name); - return isset($this->parameters[$name]) || array_key_exists($name, $this->parameters) || isset($this->loadedDynamicParameters[$name]); + return isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters); } /** diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_compiled.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_compiled.php index 08707b3b692c1..76f0b74938bd3 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_compiled.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_compiled.php @@ -391,10 +391,12 @@ protected function getServiceFromStaticMethodService() */ public function getParameter($name) { - $name = strtolower($name); + if (!(isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters))) { + $name = strtolower($name); - if (!(isset($this->parameters[$name]) || array_key_exists($name, $this->parameters) || isset($this->loadedDynamicParameters[$name]))) { - throw new InvalidArgumentException(sprintf('The parameter "%s" must be defined.', $name)); + if (!(isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters))) { + throw new InvalidArgumentException(sprintf('The parameter "%s" must be defined.', $name)); + } } if (isset($this->loadedDynamicParameters[$name])) { return $this->loadedDynamicParameters[$name] ? $this->dynamicParameters[$name] : $this->getDynamicParameter($name); @@ -410,7 +412,7 @@ public function hasParameter($name) { $name = strtolower($name); - return isset($this->parameters[$name]) || array_key_exists($name, $this->parameters) || isset($this->loadedDynamicParameters[$name]); + return isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters); } /** diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_array_params.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_array_params.php new file mode 100644 index 0000000000000..befc22d9cbefb --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_array_params.php @@ -0,0 +1,179 @@ +targetDirs[$i] = $dir = dirname($dir); + } + $this->parameters = $this->getDefaultParameters(); + + $this->services = array(); + $this->methodMap = array( + 'bar' => 'getBarService', + ); + + $this->aliases = array(); + } + + /** + * {@inheritdoc} + */ + public function compile() + { + throw new LogicException('You cannot compile a dumped container that was already compiled.'); + } + + /** + * {@inheritdoc} + */ + public function isCompiled() + { + return true; + } + + /** + * {@inheritdoc} + */ + public function isFrozen() + { + @trigger_error(sprintf('The %s() method is deprecated since version 3.3 and will be removed in 4.0. Use the isCompiled() method instead.', __METHOD__), E_USER_DEPRECATED); + + return true; + } + + /** + * Gets the 'bar' service. + * + * This service is shared. + * This method always returns the same instance of the service. + * + * @return \BarClass A BarClass instance + */ + protected function getBarService() + { + $this->services['bar'] = $instance = new \BarClass(); + + $instance->setBaz($this->parameters['array_1'], $this->getParameter('array_2'), '%array_1%'); + + return $instance; + } + + /** + * {@inheritdoc} + */ + public function getParameter($name) + { + if (!(isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters))) { + $name = strtolower($name); + + if (!(isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters))) { + throw new InvalidArgumentException(sprintf('The parameter "%s" must be defined.', $name)); + } + } + if (isset($this->loadedDynamicParameters[$name])) { + return $this->loadedDynamicParameters[$name] ? $this->dynamicParameters[$name] : $this->getDynamicParameter($name); + } + + return $this->parameters[$name]; + } + + /** + * {@inheritdoc} + */ + public function hasParameter($name) + { + $name = strtolower($name); + + return isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters); + } + + /** + * {@inheritdoc} + */ + public function setParameter($name, $value) + { + throw new LogicException('Impossible to call set() on a frozen ParameterBag.'); + } + + /** + * {@inheritdoc} + */ + public function getParameterBag() + { + if (null === $this->parameterBag) { + $parameters = $this->parameters; + foreach ($this->loadedDynamicParameters as $name => $loaded) { + $parameters[$name] = $loaded ? $this->dynamicParameters[$name] : $this->getDynamicParameter($name); + } + $this->parameterBag = new FrozenParameterBag($parameters); + } + + return $this->parameterBag; + } + + private $loadedDynamicParameters = array( + 'array_2' => false, + ); + private $dynamicParameters = array(); + + /** + * Computes a dynamic parameter. + * + * @param string The name of the dynamic parameter to load + * + * @return mixed The value of the dynamic parameter + * + * @throws InvalidArgumentException When the dynamic parameter does not exist + */ + private function getDynamicParameter($name) + { + switch ($name) { + case 'array_2': $value = array( + 0 => ($this->targetDirs[2].'/Dumper'), + ); break; + default: throw new InvalidArgumentException(sprintf('The dynamic parameter "%s" must be defined.', $name)); + } + $this->loadedDynamicParameters[$name] = true; + + return $this->dynamicParameters[$name] = $value; + } + + /** + * Gets the default parameters. + * + * @return array An array of the default parameters + */ + protected function getDefaultParameters() + { + return array( + 'array_1' => array( + 0 => 123, + ), + ); + } +} From ba0a917550f339206fffecac7a9c1376ce384233 Mon Sep 17 00:00:00 2001 From: Robin Chalas Date: Tue, 13 Jun 2017 13:32:22 +0200 Subject: [PATCH 0196/1099] Fix merge (phpdoc => typehint) --- .../SecurityBundle/Security/FirewallContext.php | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/src/Symfony/Bundle/SecurityBundle/Security/FirewallContext.php b/src/Symfony/Bundle/SecurityBundle/Security/FirewallContext.php index 2122d69607401..2375e6b0e3ab6 100644 --- a/src/Symfony/Bundle/SecurityBundle/Security/FirewallContext.php +++ b/src/Symfony/Bundle/SecurityBundle/Security/FirewallContext.php @@ -25,12 +25,7 @@ class FirewallContext private $exceptionListener; private $config; - /** - * @param \Traversable|array $listeners - * @param ExceptionListener|null $exceptionListener - * @param FirewallConfig|null $firewallConfig - */ - public function __construct($listeners, ExceptionListener $exceptionListener = null, FirewallConfig $config = null) + public function __construct(iterable $listeners, ExceptionListener $exceptionListener = null, FirewallConfig $config = null) { $this->listeners = $listeners; $this->exceptionListener = $exceptionListener; @@ -42,10 +37,7 @@ public function getConfig() return $this->config; } - /** - * @return \Traversable|array - */ - public function getListeners() + public function getListeners(): iterable { return $this->listeners; } From 2dfde588513afcc8eadc9cd68081dc94bd199c83 Mon Sep 17 00:00:00 2001 From: "Alexander M. Turek" Date: Tue, 13 Jun 2017 17:15:58 +0200 Subject: [PATCH 0197/1099] Add Doctrine Cache to dev dependencies to fix failing unit tests. --- src/Symfony/Bundle/TwigBundle/composer.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Bundle/TwigBundle/composer.json b/src/Symfony/Bundle/TwigBundle/composer.json index 0cfc9e657fff8..4441d570987af 100644 --- a/src/Symfony/Bundle/TwigBundle/composer.json +++ b/src/Symfony/Bundle/TwigBundle/composer.json @@ -35,7 +35,8 @@ "symfony/yaml": "~2.8|~3.0|~4.0", "symfony/framework-bundle": "^3.2.8|~4.0", "symfony/web-link": "~3.3|~4.0", - "doctrine/annotations": "~1.0" + "doctrine/annotations": "~1.0", + "doctrine/cache": "~1.0" }, "conflict": { "symfony/dependency-injection": "<3.3" From f09893bed4fe8bedee14af2ccd9562f90282b671 Mon Sep 17 00:00:00 2001 From: Dan Wilga Date: Fri, 9 Jun 2017 15:14:01 -0400 Subject: [PATCH 0198/1099] [Routing] Revert the change in [#b42018] with respect to Routing/Route.php --- src/Symfony/Component/Routing/Route.php | 6 +---- .../Tests/Fixtures/CustomCompiledRoute.php | 18 +++++++++++++ .../Tests/Fixtures/CustomRouteCompiler.php | 26 +++++++++++++++++++ .../Component/Routing/Tests/RouteTest.php | 18 +++++++++++++ 4 files changed, 63 insertions(+), 5 deletions(-) create mode 100644 src/Symfony/Component/Routing/Tests/Fixtures/CustomCompiledRoute.php create mode 100644 src/Symfony/Component/Routing/Tests/Fixtures/CustomRouteCompiler.php diff --git a/src/Symfony/Component/Routing/Route.php b/src/Symfony/Component/Routing/Route.php index 34b1b75765dc6..69a7cade10c33 100644 --- a/src/Symfony/Component/Routing/Route.php +++ b/src/Symfony/Component/Routing/Route.php @@ -116,11 +116,7 @@ public function serialize() */ public function unserialize($serialized) { - if (\PHP_VERSION_ID >= 70000) { - $data = unserialize($serialized, array('allowed_classes' => array(CompiledRoute::class))); - } else { - $data = unserialize($serialized); - } + $data = unserialize($serialized); $this->path = $data['path']; $this->host = $data['host']; $this->defaults = $data['defaults']; diff --git a/src/Symfony/Component/Routing/Tests/Fixtures/CustomCompiledRoute.php b/src/Symfony/Component/Routing/Tests/Fixtures/CustomCompiledRoute.php new file mode 100644 index 0000000000000..0f6e198c923d9 --- /dev/null +++ b/src/Symfony/Component/Routing/Tests/Fixtures/CustomCompiledRoute.php @@ -0,0 +1,18 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing\Tests\Fixtures; + +use Symfony\Component\Routing\CompiledRoute; + +class CustomCompiledRoute extends CompiledRoute +{ +} diff --git a/src/Symfony/Component/Routing/Tests/Fixtures/CustomRouteCompiler.php b/src/Symfony/Component/Routing/Tests/Fixtures/CustomRouteCompiler.php new file mode 100644 index 0000000000000..c2e2afd9afcd9 --- /dev/null +++ b/src/Symfony/Component/Routing/Tests/Fixtures/CustomRouteCompiler.php @@ -0,0 +1,26 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing\Tests\Fixtures; + +use Symfony\Component\Routing\Route; +use Symfony\Component\Routing\RouteCompiler; + +class CustomRouteCompiler extends RouteCompiler +{ + /** + * {@inheritdoc} + */ + public static function compile(Route $route) + { + return new CustomCompiledRoute('', '', array(), array()); + } +} diff --git a/src/Symfony/Component/Routing/Tests/RouteTest.php b/src/Symfony/Component/Routing/Tests/RouteTest.php index b65dfb54085c1..ff7e320c5fc95 100644 --- a/src/Symfony/Component/Routing/Tests/RouteTest.php +++ b/src/Symfony/Component/Routing/Tests/RouteTest.php @@ -220,6 +220,24 @@ public function testSerializeWhenCompiled() $this->assertNotSame($route, $unserialized); } + /** + * Tests that unserialization does not fail when the compiled Route is of a + * class other than CompiledRoute, such as a subclass of it. + */ + public function testSerializeWhenCompiledWithClass() + { + $route = new Route('/', array(), array(), array('compiler_class' => '\Symfony\Component\Routing\Tests\Fixtures\CustomRouteCompiler')); + $this->assertInstanceOf('\Symfony\Component\Routing\Tests\Fixtures\CustomCompiledRoute', $route->compile(), '->compile() returned a proper route'); + + $serialized = serialize($route); + try { + $unserialized = unserialize($serialized); + $this->assertInstanceOf('\Symfony\Component\Routing\Tests\Fixtures\CustomCompiledRoute', $unserialized->compile(), 'the unserialized route compiled successfully'); + } catch (\Exception $e) { + $this->fail('unserializing a route which uses a custom compiled route class'); + } + } + /** * Tests that the serialized representation of a route in one symfony version * also works in later symfony versions, i.e. the unserialized route is in the From f7afa777d883d32c70f60f2107c856400799cd85 Mon Sep 17 00:00:00 2001 From: Robin Chalas Date: Tue, 13 Jun 2017 11:38:29 +0200 Subject: [PATCH 0199/1099] [FrameworkBundle] Deprecate useless --no-prefix option --- UPGRADE-3.4.md | 4 ++++ UPGRADE-4.0.md | 3 +++ .../Command/TranslationUpdateCommand.php | 10 ++++++++-- 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/UPGRADE-3.4.md b/UPGRADE-3.4.md index de430ca547c9d..ea2ab928a55ec 100644 --- a/UPGRADE-3.4.md +++ b/UPGRADE-3.4.md @@ -34,6 +34,10 @@ FrameworkBundle * The `KernelTestCase::getPhpUnitXmlDir()` and `KernelTestCase::getPhpUnitCliConfigArgument()` methods are deprecated since 3.4 and will be removed in 4.0. + * The `--no-prefix` option of the `translation:update` command is deprecated and + will be removed in 4.0. Use the `--prefix` option with an empty string as value + instead (e.g. `--prefix=""`) + Process ------- diff --git a/UPGRADE-4.0.md b/UPGRADE-4.0.md index f6547fd0a0403..01321f2a50922 100644 --- a/UPGRADE-4.0.md +++ b/UPGRADE-4.0.md @@ -345,6 +345,9 @@ FrameworkBundle * The `Symfony\Bundle\FrameworkBundle\Validator\ConstraintValidatorFactory` class has been removed. Use `Symfony\Component\Validator\ContainerConstraintValidatorFactory` instead. + * The `--no-prefix` option of the `translation:update` command has + been removed. + HttpFoundation -------------- diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/TranslationUpdateCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/TranslationUpdateCommand.php index f88747cfa61f8..0d5b4fb873612 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/TranslationUpdateCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/TranslationUpdateCommand.php @@ -39,7 +39,7 @@ protected function configure() new InputArgument('locale', InputArgument::REQUIRED, 'The locale'), new InputArgument('bundle', InputArgument::OPTIONAL, 'The bundle name or directory where to load the messages, defaults to app/Resources folder'), new InputOption('prefix', null, InputOption::VALUE_OPTIONAL, 'Override the default prefix', '__'), - new InputOption('no-prefix', null, InputOption::VALUE_NONE, 'If set, no prefix is added to the translations'), + new InputOption('no-prefix', null, InputOption::VALUE_NONE, '[DEPRECATED] If set, no prefix is added to the translations'), new InputOption('output-format', null, InputOption::VALUE_OPTIONAL, 'Override the default output format', 'yml'), new InputOption('dump-messages', null, InputOption::VALUE_NONE, 'Should the messages be dumped in the console'), new InputOption('force', null, InputOption::VALUE_NONE, 'Should the update be done'), @@ -135,7 +135,13 @@ protected function execute(InputInterface $input, OutputInterface $output) $extractedCatalogue = new MessageCatalogue($input->getArgument('locale')); $errorIo->comment('Parsing templates...'); $extractor = $this->getContainer()->get('translation.extractor'); - $extractor->setPrefix($input->getOption('no-prefix') ? '' : $input->getOption('prefix')); + $prefix = $input->getOption('prefix'); + // @deprecated since version 3.4, to be removed in 4.0 along with the --no-prefix option + if ($input->getOption('no-prefix')) { + @trigger_error('The "--no-prefix" option is deprecated since version 3.4 and will be removed in 4.0. Use the "--prefix" option with an empty string as value instead.', E_USER_DEPRECATED); + $prefix = ''; + } + $extractor->setPrefix($prefix); foreach ($transPaths as $path) { $path .= 'views'; if (is_dir($path)) { From abd900733749178770242bf85b4bcd0b734928e3 Mon Sep 17 00:00:00 2001 From: Maxime Steinhausser Date: Tue, 13 Jun 2017 20:21:13 +0200 Subject: [PATCH 0200/1099] [FrameworkBundle] Remove unnecessary use --- .../Bundle/FrameworkBundle/Controller/AbstractController.php | 1 - .../FrameworkBundle/Tests/Controller/AbstractControllerTest.php | 1 - 2 files changed, 2 deletions(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/Controller/AbstractController.php b/src/Symfony/Bundle/FrameworkBundle/Controller/AbstractController.php index 6d0cee247da77..def76d9defba2 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Controller/AbstractController.php +++ b/src/Symfony/Bundle/FrameworkBundle/Controller/AbstractController.php @@ -16,7 +16,6 @@ use Symfony\Component\DependencyInjection\ServiceSubscriberInterface; use Symfony\Component\Form\FormFactoryInterface; use Symfony\Component\HttpFoundation\RequestStack; -use Symfony\Component\HttpFoundation\Session\Session; use Symfony\Component\HttpFoundation\Session\SessionInterface; use Symfony\Component\HttpKernel\HttpKernelInterface; use Symfony\Component\Routing\RouterInterface; diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/AbstractControllerTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/AbstractControllerTest.php index 937cbfc7286d0..6783ec25c5ab5 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/AbstractControllerTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/AbstractControllerTest.php @@ -13,7 +13,6 @@ use Psr\Container\ContainerInterface; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; -use Symfony\Component\HttpFoundation\File\File; class AbstractControllerTest extends ControllerTraitTest { From 6d28c43f0a1e1474f8058d6915b3b6d26d722310 Mon Sep 17 00:00:00 2001 From: Maxime Steinhausser Date: Tue, 13 Jun 2017 20:17:23 +0200 Subject: [PATCH 0201/1099] [FrameworkBundle] Remove KernelTestCase deprecated code --- .../Bundle/FrameworkBundle/CHANGELOG.md | 2 + .../FrameworkBundle/Test/KernelTestCase.php | 114 +----------------- 2 files changed, 7 insertions(+), 109 deletions(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md b/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md index 44d39a9d660ed..9b626ac1a4a7b 100644 --- a/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md +++ b/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md @@ -17,6 +17,8 @@ CHANGELOG * Removed `ConstraintValidatorFactory` * Removed class parameters related to routing * Removed absolute template paths support in the template name parser + * Removed support of the `KERNEL_DIR` environment variable with `KernelTestCase::getKernelClass()`. + * Removed the `KernelTestCase::getPhpUnitXmlDir()` and `KernelTestCase::getPhpUnitCliConfigArgument()` methods. 3.4.0 ----- diff --git a/src/Symfony/Bundle/FrameworkBundle/Test/KernelTestCase.php b/src/Symfony/Bundle/FrameworkBundle/Test/KernelTestCase.php index 802259eedbfee..9d49c3257d160 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Test/KernelTestCase.php +++ b/src/Symfony/Bundle/FrameworkBundle/Test/KernelTestCase.php @@ -13,7 +13,6 @@ use PHPUnit\Framework\TestCase; use Symfony\Component\DependencyInjection\ResettableContainerInterface; -use Symfony\Component\Finder\Finder; use Symfony\Component\HttpKernel\KernelInterface; /** @@ -31,124 +30,21 @@ abstract class KernelTestCase extends TestCase protected static $kernel; /** - * Finds the directory where the phpunit.xml(.dist) is stored. - * - * If you run tests with the PHPUnit CLI tool, everything will work as expected. - * If not, override this method in your test classes. - * - * @return string The directory where phpunit.xml(.dist) is stored - * - * @throws \RuntimeException - * - * @deprecated since 3.4 and will be removed in 4.0. - */ - protected static function getPhpUnitXmlDir() - { - @trigger_error(sprintf('The %s() method is deprecated since 3.4 and will be removed in 4.0.', __METHOD__), E_USER_DEPRECATED); - - if (!isset($_SERVER['argv']) || false === strpos($_SERVER['argv'][0], 'phpunit')) { - throw new \RuntimeException('You must override the KernelTestCase::createKernel() method.'); - } - - $dir = static::getPhpUnitCliConfigArgument(); - if (null === $dir && - (is_file(getcwd().DIRECTORY_SEPARATOR.'phpunit.xml') || - is_file(getcwd().DIRECTORY_SEPARATOR.'phpunit.xml.dist'))) { - $dir = getcwd(); - } - - // Can't continue - if (null === $dir) { - throw new \RuntimeException('Unable to guess the Kernel directory.'); - } - - if (!is_dir($dir)) { - $dir = dirname($dir); - } - - return $dir; - } - - /** - * Finds the value of the CLI configuration option. - * - * PHPUnit will use the last configuration argument on the command line, so this only returns - * the last configuration argument. - * - * @return string The value of the PHPUnit CLI configuration option - * - * @deprecated since 3.4 and will be removed in 4.0. - */ - private static function getPhpUnitCliConfigArgument() - { - @trigger_error(sprintf('The %s() method is deprecated since 3.4 and will be removed in 4.0.', __METHOD__), E_USER_DEPRECATED); - - $dir = null; - $reversedArgs = array_reverse($_SERVER['argv']); - foreach ($reversedArgs as $argIndex => $testArg) { - if (preg_match('/^-[^ \-]*c$/', $testArg) || $testArg === '--configuration') { - $dir = realpath($reversedArgs[$argIndex - 1]); - break; - } elseif (0 === strpos($testArg, '--configuration=')) { - $argPath = substr($testArg, strlen('--configuration=')); - $dir = realpath($argPath); - break; - } elseif (0 === strpos($testArg, '-c')) { - $argPath = substr($testArg, strlen('-c')); - $dir = realpath($argPath); - break; - } - } - - return $dir; - } - - /** - * Attempts to guess the kernel location. - * - * When the Kernel is located, the file is required. - * * @return string The Kernel class name * * @throws \RuntimeException + * @throws \LogicException */ protected static function getKernelClass() { - if (isset($_SERVER['KERNEL_CLASS'])) { - if (!class_exists($class = $_SERVER['KERNEL_CLASS'])) { - throw new \RuntimeException(sprintf('Class "%s" doesn\'t exist or cannot be autoloaded. Check that the KERNEL_CLASS value in phpunit.xml matches the fully-qualified class name of your Kernel or override the %s::createKernel() method.', $class, static::class)); - } - - return $class; - } else { - @trigger_error(sprintf('Using the KERNEL_DIR environment variable or the automatic guessing based on the phpunit.xml / phpunit.xml.dist file location is deprecated since 3.4. Set the KERNEL_CLASS environment variable to the fully-qualified class name of your Kernel instead. Not setting the KERNEL_CLASS environment variable will throw an exception on 4.0 unless you override the %1$::createKernel() or %1$::getKernelClass() method.', static::class), E_USER_DEPRECATED); - } - - if (isset($_SERVER['KERNEL_DIR'])) { - $dir = $_SERVER['KERNEL_DIR']; - - if (!is_dir($dir)) { - $phpUnitDir = static::getPhpUnitXmlDir(); - if (is_dir("$phpUnitDir/$dir")) { - $dir = "$phpUnitDir/$dir"; - } - } - } else { - $dir = static::getPhpUnitXmlDir(); + if (!isset($_SERVER['KERNEL_CLASS'])) { + throw new \LogicException(sprintf('You must set the KERNEL_CLASS environment variable to the fully-qualified class name of your Kernel in phpunit.xml / phpunit.xml.dist or override the %1$::createKernel() or %1$::getKernelClass() method.', static::class)); } - $finder = new Finder(); - $finder->name('*Kernel.php')->depth(0)->in($dir); - $results = iterator_to_array($finder); - if (!count($results)) { - throw new \RuntimeException('Either set KERNEL_DIR in your phpunit.xml according to https://symfony.com/doc/current/book/testing.html#your-first-functional-test or override the WebTestCase::createKernel() method.'); + if (!class_exists($class = $_SERVER['KERNEL_CLASS'])) { + throw new \RuntimeException(sprintf('Class "%s" doesn\'t exist or cannot be autoloaded. Check that the KERNEL_CLASS value in phpunit.xml matches the fully-qualified class name of your Kernel or override the %s::createKernel() method.', $class, static::class)); } - $file = current($results); - $class = $file->getBasename('.php'); - - require_once $file; - return $class; } From 55a8d35e64c4e8b52eac9ef3941de94f74ead133 Mon Sep 17 00:00:00 2001 From: Robin Chalas Date: Tue, 13 Jun 2017 22:44:19 +0200 Subject: [PATCH 0202/1099] [Yaml] Fix linting yaml with constants as keys --- src/Symfony/Component/Yaml/Command/LintCommand.php | 3 ++- .../Yaml/Tests/Command/LintCommandTest.php | 14 ++++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/Yaml/Command/LintCommand.php b/src/Symfony/Component/Yaml/Command/LintCommand.php index 48f6d94a03915..271f2d8474109 100644 --- a/src/Symfony/Component/Yaml/Command/LintCommand.php +++ b/src/Symfony/Component/Yaml/Command/LintCommand.php @@ -18,6 +18,7 @@ use Symfony\Component\Console\Style\SymfonyStyle; use Symfony\Component\Yaml\Exception\ParseException; use Symfony\Component\Yaml\Parser; +use Symfony\Component\Yaml\Yaml; /** * Validates YAML files syntax and outputs encountered errors. @@ -111,7 +112,7 @@ private function validate($content, $file = null) }); try { - $this->getParser()->parse($content); + $this->getParser()->parse($content, Yaml::PARSE_CONSTANT); } catch (ParseException $e) { return array('file' => $file, 'valid' => false, 'message' => $e->getMessage()); } finally { diff --git a/src/Symfony/Component/Yaml/Tests/Command/LintCommandTest.php b/src/Symfony/Component/Yaml/Tests/Command/LintCommandTest.php index ce6ad480cf2b6..75aa067f22890 100644 --- a/src/Symfony/Component/Yaml/Tests/Command/LintCommandTest.php +++ b/src/Symfony/Component/Yaml/Tests/Command/LintCommandTest.php @@ -51,6 +51,15 @@ public function testLintIncorrectFile() $this->assertContains('Unable to parse at line 3 (near "bar").', trim($tester->getDisplay())); } + public function testConstantAsKey() + { + $yaml = <<createCommandTester()->execute(array('filename' => $this->createFile($yaml)), array('verbosity' => OutputInterface::VERBOSITY_VERBOSE, 'decorated' => false)); + $this->assertSame(0, $ret, 'lint:yaml exits with code 0 in case of success'); + } + /** * @expectedException \RuntimeException */ @@ -105,3 +114,8 @@ protected function tearDown() rmdir(sys_get_temp_dir().'/framework-yml-lint-test'); } } + +class Foo +{ + const TEST = 'foo'; +} From 78f028cc758338c270011bd826b13e7f485d8dc5 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Tue, 13 Jun 2017 17:54:13 -0700 Subject: [PATCH 0203/1099] fixed CS --- .../Csrf/EventListener/CsrfValidationListenerTest.php | 1 - src/Symfony/Component/VarDumper/Dumper/CliDumper.php | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Component/Form/Tests/Extension/Csrf/EventListener/CsrfValidationListenerTest.php b/src/Symfony/Component/Form/Tests/Extension/Csrf/EventListener/CsrfValidationListenerTest.php index fc0dee140b047..47f9e43294ba0 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Csrf/EventListener/CsrfValidationListenerTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Csrf/EventListener/CsrfValidationListenerTest.php @@ -12,7 +12,6 @@ namespace Symfony\Component\Form\Tests\Extension\Csrf\EventListener; use PHPUnit\Framework\TestCase; -use Symfony\Component\Form\Form; use Symfony\Component\Form\FormBuilder; use Symfony\Component\Form\FormEvent; use Symfony\Component\Form\Extension\Csrf\EventListener\CsrfValidationListener; diff --git a/src/Symfony/Component/VarDumper/Dumper/CliDumper.php b/src/Symfony/Component/VarDumper/Dumper/CliDumper.php index 59ba119e42914..822736abd5561 100644 --- a/src/Symfony/Component/VarDumper/Dumper/CliDumper.php +++ b/src/Symfony/Component/VarDumper/Dumper/CliDumper.php @@ -125,9 +125,9 @@ public function dumpScalar(Cursor $cursor, $type, $value) $style = 'num'; switch (true) { - case INF === $value: $value = 'INF'; break; + case INF === $value: $value = 'INF'; break; case -INF === $value: $value = '-INF'; break; - case is_nan($value): $value = 'NAN'; break; + case is_nan($value): $value = 'NAN'; break; default: $value = (string) $value; if (false === strpos($value, $this->decimalPoint)) { From 44955bea53f6a9cbc9e8adab2a50db91fdd77b35 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Tue, 13 Jun 2017 20:10:15 +0200 Subject: [PATCH 0204/1099] [Config] Fix ** GlobResource on Windows --- src/Symfony/Component/Config/Resource/GlobResource.php | 2 +- .../Component/Config/Tests/Resource/GlobResourceTest.php | 9 +++++++++ src/Symfony/Component/Config/composer.json | 2 ++ 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/Config/Resource/GlobResource.php b/src/Symfony/Component/Config/Resource/GlobResource.php index 67625201530f5..20cab1e81d55d 100644 --- a/src/Symfony/Component/Config/Resource/GlobResource.php +++ b/src/Symfony/Component/Config/Resource/GlobResource.php @@ -134,7 +134,7 @@ function (\SplFileInfo $file) { return '.' !== $file->getBasename()[0]; } $prefixLen = strlen($this->prefix); foreach ($finder->followLinks()->sortByName()->in($this->prefix) as $path => $info) { - if (preg_match($regex, substr($path, $prefixLen)) && $info->isFile()) { + if (preg_match($regex, substr('\\' === \DIRECTORY_SEPARATOR ? str_replace('\\', '/', $path) : $path, $prefixLen)) && $info->isFile()) { yield $path => $info; } } diff --git a/src/Symfony/Component/Config/Tests/Resource/GlobResourceTest.php b/src/Symfony/Component/Config/Tests/Resource/GlobResourceTest.php index b84cc9d3ae3b9..bf7291fdd66b8 100644 --- a/src/Symfony/Component/Config/Tests/Resource/GlobResourceTest.php +++ b/src/Symfony/Component/Config/Tests/Resource/GlobResourceTest.php @@ -36,6 +36,15 @@ public function testIterator() $this->assertEquals(array($file => new \SplFileInfo($file)), $paths); $this->assertInstanceOf('SplFileInfo', current($paths)); $this->assertSame($dir, $resource->getPrefix()); + + $resource = new GlobResource($dir, '/**/Resource', true); + + $paths = iterator_to_array($resource); + + $file = $dir.DIRECTORY_SEPARATOR.'Resource'.DIRECTORY_SEPARATOR.'ConditionalClass.php'; + $this->assertEquals(array($file => $file), $paths); + $this->assertInstanceOf('SplFileInfo', current($paths)); + $this->assertSame($dir, $resource->getPrefix()); } public function testIsFreshNonRecursiveDetectsNewFile() diff --git a/src/Symfony/Component/Config/composer.json b/src/Symfony/Component/Config/composer.json index 88090d463da63..7a51c91ed591a 100644 --- a/src/Symfony/Component/Config/composer.json +++ b/src/Symfony/Component/Config/composer.json @@ -20,10 +20,12 @@ "symfony/filesystem": "~2.8|~3.0" }, "require-dev": { + "symfony/finder": "~3.3", "symfony/yaml": "~3.0", "symfony/dependency-injection": "~3.3" }, "conflict": { + "symfony/finder": "<3.3", "symfony/dependency-injection": "<3.3" }, "suggest": { From d8d0f877934ca63403cba4949c9293dfc943fb3a Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Wed, 14 Jun 2017 09:33:02 +0200 Subject: [PATCH 0205/1099] [TwigBundle] Add Doctrine Cache to dev dependencies --- src/Symfony/Bundle/TwigBundle/composer.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Bundle/TwigBundle/composer.json b/src/Symfony/Bundle/TwigBundle/composer.json index 11f071b19c32b..1b3cc91c1969c 100644 --- a/src/Symfony/Bundle/TwigBundle/composer.json +++ b/src/Symfony/Bundle/TwigBundle/composer.json @@ -35,7 +35,8 @@ "symfony/yaml": "~2.8|~3.0", "symfony/framework-bundle": "^3.2.8", "symfony/web-link": "~3.3", - "doctrine/annotations": "~1.0" + "doctrine/annotations": "~1.0", + "doctrine/cache": "~1.0" }, "conflict": { "symfony/dependency-injection": "<3.3" From 408e56e404973232fac7c114e979025e72464d77 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Wed, 14 Jun 2017 10:52:56 +0200 Subject: [PATCH 0206/1099] Fix AutowiringTypesTest transient tests --- .../Bundle/FrameworkBundle/Tests/Functional/WebTestCase.php | 2 +- .../Bundle/SecurityBundle/Tests/Functional/WebTestCase.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/WebTestCase.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/WebTestCase.php index 2861297fe0256..a1c50e59fdb90 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/WebTestCase.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/WebTestCase.php @@ -68,6 +68,6 @@ protected static function createKernel(array $options = array()) protected static function getVarDir() { - return substr(strrchr(get_called_class(), '\\'), 1); + return 'FB'.substr(strrchr(get_called_class(), '\\'), 1); } } diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/WebTestCase.php b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/WebTestCase.php index 8bace799a37a8..bb98a2a065ca0 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/WebTestCase.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/WebTestCase.php @@ -68,6 +68,6 @@ protected static function createKernel(array $options = array()) protected static function getVarDir() { - return substr(strrchr(get_called_class(), '\\'), 1); + return 'SB'.substr(strrchr(get_called_class(), '\\'), 1); } } From d7238c9d96df18d7b71306f91b014f946b6c1c7a Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Wed, 14 Jun 2017 17:32:02 +0200 Subject: [PATCH 0207/1099] [VarDumper] fixes --- src/Symfony/Component/VarDumper/Caster/ResourceCaster.php | 2 +- src/Symfony/Component/VarDumper/Caster/SplCaster.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/VarDumper/Caster/ResourceCaster.php b/src/Symfony/Component/VarDumper/Caster/ResourceCaster.php index 903641f69c636..d70c09ac4da62 100644 --- a/src/Symfony/Component/VarDumper/Caster/ResourceCaster.php +++ b/src/Symfony/Component/VarDumper/Caster/ResourceCaster.php @@ -45,7 +45,7 @@ public static function castStream($stream, array $a, Stub $stub, $isNested) public static function castStreamContext($stream, array $a, Stub $stub, $isNested) { - return stream_context_get_params($stream); + return @stream_context_get_params($stream) ?: $a; } public static function castGd($gd, array $a, Stub $stub, $isNested) diff --git a/src/Symfony/Component/VarDumper/Caster/SplCaster.php b/src/Symfony/Component/VarDumper/Caster/SplCaster.php index b0b57e3cda598..d50419f624394 100644 --- a/src/Symfony/Component/VarDumper/Caster/SplCaster.php +++ b/src/Symfony/Component/VarDumper/Caster/SplCaster.php @@ -86,7 +86,7 @@ public static function castObjectStorage(\SplObjectStorage $c, array $a, Stub $s $storage = array(); unset($a[Caster::PREFIX_DYNAMIC."\0gcdata"]); // Don't hit https://bugs.php.net/65967 - foreach ($c as $obj) { + foreach (clone $c as $obj) { $storage[spl_object_hash($obj)] = array( 'object' => $obj, 'info' => $c->getInfo(), From 71c1b6f5bf2f0aaa42bdca058f3e6a24148ad28e Mon Sep 17 00:00:00 2001 From: Vincent AUBERT Date: Sat, 10 Jun 2017 18:29:28 +0200 Subject: [PATCH 0208/1099] fixes #21606 --- .../HttpFoundation/Session/Storage/NativeSessionStorage.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.php b/src/Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.php index 36a20550b07cf..987f2f25b47ef 100644 --- a/src/Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.php +++ b/src/Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.php @@ -340,6 +340,7 @@ public function setOptions(array $options) 'use_only_cookies', 'use_trans_sid', 'upload_progress.enabled', 'upload_progress.cleanup', 'upload_progress.prefix', 'upload_progress.name', 'upload_progress.freq', 'upload_progress.min-freq', 'url_rewriter.tags', + 'sid_length', 'sid_bits_per_character', 'trans_sid_hosts', 'trans_sid_tags', )); foreach ($options as $key => $value) { From b92929b0be19d80c2c29cb450e668cebdcf41c6b Mon Sep 17 00:00:00 2001 From: Roland Franssen Date: Tue, 13 Jun 2017 09:16:03 +0200 Subject: [PATCH 0209/1099] [WebProfilerBundle] Sticky ajax window --- .../Resources/views/Profiler/toolbar.css.twig | 13 ++++++++++--- .../Resources/views/Profiler/toolbar_js.html.twig | 5 +++++ 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/toolbar.css.twig b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/toolbar.css.twig index 3a8f6e0fbadc9..2741a50194428 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/toolbar.css.twig +++ b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/toolbar.css.twig @@ -252,6 +252,10 @@ line-height: 17px; } +.sf-toolbar-block-ajax .sf-toolbar-icon { + cursor: pointer; +} + .sf-toolbar-status-green .sf-toolbar-label, .sf-toolbar-status-yellow .sf-toolbar-label, .sf-toolbar-status-red .sf-toolbar-label { @@ -295,15 +299,18 @@ margin-left: 4px; } -.sf-toolbar-block:hover { +.sf-toolbar-block:hover, +.sf-toolbar-block.hover { position: relative; } -.sf-toolbar-block:hover .sf-toolbar-icon { +.sf-toolbar-block:hover .sf-toolbar-icon, +.sf-toolbar-block.hover .sf-toolbar-icon { background-color: #444; position: relative; z-index: 10002; } -.sf-toolbar-block:hover .sf-toolbar-info { +.sf-toolbar-block:hover .sf-toolbar-info, +.sf-toolbar-block.hover .sf-toolbar-info { display: block; padding: 10px; max-width: 480px; diff --git a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/toolbar_js.html.twig b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/toolbar_js.html.twig index 3f561d7e08360..ec54c2fb9e5bf 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/toolbar_js.html.twig +++ b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/toolbar_js.html.twig @@ -93,6 +93,11 @@ Sfjs.setPreference('toolbar/displayState', 'block'); }); Sfjs.renderAjaxRequests(); + Sfjs.addEventListener(document.querySelector('.sf-toolbar-block-ajax > .sf-toolbar-icon'), 'click', function (event) { + event.preventDefault(); + + Sfjs.toggleClass(this.parentNode, 'hover'); + }); }, function(xhr) { if (xhr.status !== 0) { From 86911b5087c373002b1ea38e601cf7557af70f85 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Wed, 14 Jun 2017 12:31:53 -0700 Subject: [PATCH 0210/1099] [HttpFoundation] removed obsolete ini settings for sessions --- .../Session/Storage/NativeSessionStorage.php | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.php b/src/Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.php index 0cc818eaad02a..a3e62b0059e82 100644 --- a/src/Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.php +++ b/src/Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.php @@ -71,13 +71,10 @@ class NativeSessionStorage implements SessionStorageInterface * cookie_lifetime, "0" * cookie_path, "/" * cookie_secure, "" - * entropy_file, "" - * entropy_length, "0" * gc_divisor, "100" * gc_maxlifetime, "1440" * gc_probability, "1" * hash_bits_per_character, "4" - * hash_function, "0" * name, "PHPSESSID" * referer_check, "" * serialize_handler, "php" @@ -328,9 +325,9 @@ public function setOptions(array $options) $validOptions = array_flip(array( 'cache_limiter', 'cookie_domain', 'cookie_httponly', 'cookie_lifetime', 'cookie_path', 'cookie_secure', - 'entropy_file', 'entropy_length', 'gc_divisor', - 'gc_maxlifetime', 'gc_probability', 'hash_bits_per_character', - 'hash_function', 'name', 'referer_check', + 'gc_divisor', + 'gc_maxlifetime', 'gc_probability', + 'name', 'referer_check', 'serialize_handler', 'use_strict_mode', 'use_cookies', 'use_only_cookies', 'use_trans_sid', 'upload_progress.enabled', 'upload_progress.cleanup', 'upload_progress.prefix', 'upload_progress.name', From c6b9101e066f85552f6326bdc6594cb335a5dc6f Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Wed, 14 Jun 2017 12:35:44 -0700 Subject: [PATCH 0211/1099] [HttpFoundation] added missing docs --- .../HttpFoundation/Session/Storage/NativeSessionStorage.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.php b/src/Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.php index 987f2f25b47ef..812f5f2e4fcc0 100644 --- a/src/Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.php +++ b/src/Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.php @@ -92,6 +92,10 @@ class NativeSessionStorage implements SessionStorageInterface * upload_progress.freq, "1%" * upload_progress.min-freq, "1" * url_rewriter.tags, "a=href,area=href,frame=src,form=,fieldset=" + * sid_length, "32" + * sid_bits_per_character, "5" + * trans_sid_hosts, $_SERVER['HTTP_HOST'] + * trans_sid_tags, "a=href,area=href,frame=src,form=" * * @param array $options Session configuration options * @param AbstractProxy|NativeSessionHandler|\SessionHandlerInterface|null $handler From 69e84633dd8ce763c8226acae45afc10dff155c2 Mon Sep 17 00:00:00 2001 From: Matthias Pigulla Date: Sat, 10 Jun 2017 12:29:45 +0200 Subject: [PATCH 0212/1099] Add tests for ResponseCacheStrategy to document some more edge cases --- .../HttpCache/ResponseCacheStrategyTest.php | 62 +++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/src/Symfony/Component/HttpKernel/Tests/HttpCache/ResponseCacheStrategyTest.php b/src/Symfony/Component/HttpKernel/Tests/HttpCache/ResponseCacheStrategyTest.php index f30a3b6ad94ab..a37a85bc436a9 100644 --- a/src/Symfony/Component/HttpKernel/Tests/HttpCache/ResponseCacheStrategyTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/HttpCache/ResponseCacheStrategyTest.php @@ -75,4 +75,66 @@ public function testSharedMaxAgeNotSetIfNotSetInMasterRequest() $this->assertFalse($response->headers->hasCacheControlDirective('s-maxage')); } + + public function testMasterResponseNotCacheableWhenEmbeddedResponseRequiresValidation() + { + $cacheStrategy = new ResponseCacheStrategy(); + + $embeddedResponse = new Response(); + $embeddedResponse->setLastModified(new \DateTime()); + $cacheStrategy->add($embeddedResponse); + + $masterResponse = new Response(); + $masterResponse->setSharedMaxAge(3600); + $cacheStrategy->update($masterResponse); + + $this->assertTrue($masterResponse->headers->hasCacheControlDirective('no-cache')); + $this->assertTrue($masterResponse->headers->hasCacheControlDirective('must-revalidate')); + $this->assertFalse($masterResponse->isFresh()); + } + + public function testValidationOnMasterResponseIsNotPossibleWhenItContainsEmbeddedResponses() + { + $cacheStrategy = new ResponseCacheStrategy(); + + // This master response uses the "validation" model + $masterResponse = new Response(); + $masterResponse->setLastModified(new \DateTime()); + $masterResponse->setEtag('foo'); + + // Embedded response uses "expiry" model + $embeddedResponse = new Response(); + $masterResponse->setSharedMaxAge(3600); + $cacheStrategy->add($embeddedResponse); + + $cacheStrategy->update($masterResponse); + + $this->assertFalse($masterResponse->isValidateable()); + $this->assertFalse($masterResponse->headers->has('Last-Modified')); + $this->assertFalse($masterResponse->headers->has('ETag')); + $this->assertTrue($masterResponse->headers->hasCacheControlDirective('no-cache')); + $this->assertTrue($masterResponse->headers->hasCacheControlDirective('must-revalidate')); + } + + public function testMasterResponseWithValidationIsUnchangedWhenThereIsNoEmbeddedResponse() + { + $cacheStrategy = new ResponseCacheStrategy(); + + $masterResponse = new Response(); + $masterResponse->setLastModified(new \DateTime()); + $cacheStrategy->update($masterResponse); + + $this->assertTrue($masterResponse->isValidateable()); + } + + public function testMasterResponseWithExpirationIsUnchangedWhenThereIsNoEmbeddedResponse() + { + $cacheStrategy = new ResponseCacheStrategy(); + + $masterResponse = new Response(); + $masterResponse->setSharedMaxAge(3600); + $cacheStrategy->update($masterResponse); + + $this->assertTrue($masterResponse->isFresh()); + } } From 3ccbc479da5812d91fa09befe80279ec3cd1ee1f Mon Sep 17 00:00:00 2001 From: VolCh Date: Wed, 7 Jun 2017 14:57:47 +0300 Subject: [PATCH 0213/1099] [Filesystem] added workaround in Filesystem::rename for PHP bug --- src/Symfony/Component/Filesystem/Filesystem.php | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/Symfony/Component/Filesystem/Filesystem.php b/src/Symfony/Component/Filesystem/Filesystem.php index edfc1b9d46a23..e60d4690738ad 100644 --- a/src/Symfony/Component/Filesystem/Filesystem.php +++ b/src/Symfony/Component/Filesystem/Filesystem.php @@ -276,6 +276,13 @@ public function rename($origin, $target, $overwrite = false) } if (true !== @rename($origin, $target)) { + if (is_dir($origin)) { + // See https://bugs.php.net/bug.php?id=54097 & http://php.net/manual/en/function.rename.php#113943 + $this->mirror($origin, $target, null, array('override' => $overwrite, 'delete' => $overwrite)); + $this->remove($origin); + + return; + } throw new IOException(sprintf('Cannot rename "%s" to "%s".', $origin, $target), 0, null, $target); } } From 2a9e65dea9f4afb13d8e47a87ea754e4a182fc31 Mon Sep 17 00:00:00 2001 From: Matthias Pigulla Date: Sat, 3 Jun 2017 23:06:14 +0200 Subject: [PATCH 0214/1099] [Translation][FrameworkBundle] Fix resource loading order inconsistency reported in #23034 --- .../Tests/Translation/TranslatorTest.php | 45 +++++++++++++++++++ .../Translation/Translator.php | 29 +++++++++--- 2 files changed, 67 insertions(+), 7 deletions(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Translation/TranslatorTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Translation/TranslatorTest.php index 361bcf001b560..75f4281952227 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Translation/TranslatorTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Translation/TranslatorTest.php @@ -135,6 +135,51 @@ public function testGetDefaultLocale() $this->assertSame('en', $translator->getLocale()); } + /** @dataProvider getDebugModeAndCacheDirCombinations */ + public function testResourceFilesOptionLoadsBeforeOtherAddedResources($debug, $enableCache) + { + $someCatalogue = $this->getCatalogue('some_locale', array()); + + $loader = $this->getMockBuilder('Symfony\Component\Translation\Loader\LoaderInterface')->getMock(); + + $loader->expects($this->at(0)) + ->method('load') + /* The "messages.some_locale.loader" is passed via the resource_file option and shall be loaded first */ + ->with('messages.some_locale.loader', 'some_locale', 'messages') + ->willReturn($someCatalogue); + + $loader->expects($this->at(1)) + ->method('load') + /* This resource is added by an addResource() call and shall be loaded after the resource_files */ + ->with('second_resource.some_locale.loader', 'some_locale', 'messages') + ->willReturn($someCatalogue); + + $options = array( + 'resource_files' => array('some_locale' => array('messages.some_locale.loader')), + 'debug' => $debug, + ); + + if ($enableCache) { + $options['cache_dir'] = $this->tmpDir; + } + + /** @var Translator $translator */ + $translator = $this->createTranslator($loader, $options); + $translator->addResource('loader', 'second_resource.some_locale.loader', 'some_locale', 'messages'); + + $translator->trans('some_message', array(), null, 'some_locale'); + } + + public function getDebugModeAndCacheDirCombinations() + { + return array( + array(false, false), + array(true, false), + array(false, true), + array(true, true), + ); + } + protected function getCatalogue($locale, $messages, $resources = array()) { $catalogue = new MessageCatalogue($locale); diff --git a/src/Symfony/Bundle/FrameworkBundle/Translation/Translator.php b/src/Symfony/Bundle/FrameworkBundle/Translation/Translator.php index fba6d70d6978b..9fdfb645d372a 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Translation/Translator.php +++ b/src/Symfony/Bundle/FrameworkBundle/Translation/Translator.php @@ -37,6 +37,14 @@ class Translator extends BaseTranslator implements WarmableInterface */ private $resourceLocales; + /** + * Holds parameters from addResource() calls so we can defer the actual + * parent::addResource() calls until initialize() is executed. + * + * @var array + */ + private $resources = array(); + /** * Constructor. * @@ -65,9 +73,7 @@ public function __construct(ContainerInterface $container, MessageSelector $sele $this->options = array_merge($this->options, $options); $this->resourceLocales = array_keys($this->options['resource_files']); - if (null !== $this->options['cache_dir'] && $this->options['debug']) { - $this->loadResources(); - } + $this->addResourceFiles($this->options['resource_files']); parent::__construct($container->getParameter('kernel.default_locale'), $selector, $this->options['cache_dir'], $this->options['debug']); } @@ -93,6 +99,11 @@ public function warmUp($cacheDir) } } + public function addResource($format, $resource, $locale, $domain = null) + { + $this->resources[] = array($format, $resource, $locale, $domain); + } + /** * {@inheritdoc} */ @@ -104,7 +115,12 @@ protected function initializeCatalogue($locale) protected function initialize() { - $this->loadResources(); + foreach ($this->resources as $key => $params) { + list($format, $resource, $locale, $domain) = $params; + parent::addResource($format, $resource, $locale, $domain); + } + $this->resources = array(); + foreach ($this->loaderIds as $id => $aliases) { foreach ($aliases as $alias) { $this->addLoader($alias, $this->container->get($id)); @@ -112,14 +128,13 @@ protected function initialize() } } - private function loadResources() + private function addResourceFiles($filesByLocale) { - foreach ($this->options['resource_files'] as $locale => $files) { + foreach ($filesByLocale as $locale => $files) { foreach ($files as $key => $file) { // filename is domain.locale.format list($domain, $locale, $format) = explode('.', basename($file), 3); $this->addResource($format, $file, $locale, $domain); - unset($this->options['resource_files'][$locale][$key]); } } } From 8c26aab0fe34d8dd726c25677f7c27b55b8a847a Mon Sep 17 00:00:00 2001 From: Roland Franssen Date: Wed, 7 Jun 2017 11:18:23 +0200 Subject: [PATCH 0215/1099] [FrameworkBundle] Dont set pre-defined esi/ssi services --- .../FrameworkBundle/HttpCache/HttpCache.php | 3 +-- .../EventListener/SurrogateListener.php | 18 ++++++++++++++++-- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/HttpCache/HttpCache.php b/src/Symfony/Bundle/FrameworkBundle/HttpCache/HttpCache.php index fad4adc04434d..06aa922210569 100644 --- a/src/Symfony/Bundle/FrameworkBundle/HttpCache/HttpCache.php +++ b/src/Symfony/Bundle/FrameworkBundle/HttpCache/HttpCache.php @@ -54,8 +54,7 @@ public function __construct(HttpKernelInterface $kernel, $cacheDir = null) protected function forward(Request $request, $raw = false, Response $entry = null) { $this->getKernel()->boot(); - $this->getKernel()->getContainer()->set('cache', $this); - $this->getKernel()->getContainer()->set($this->getSurrogate()->getName(), $this->getSurrogate()); + $this->getKernel()->getContainer()->set('cache', $this); // to be removed in 4.0? return parent::forward($request, $raw, $entry); } diff --git a/src/Symfony/Component/HttpKernel/EventListener/SurrogateListener.php b/src/Symfony/Component/HttpKernel/EventListener/SurrogateListener.php index dc815a216f6c0..a207ab673171b 100644 --- a/src/Symfony/Component/HttpKernel/EventListener/SurrogateListener.php +++ b/src/Symfony/Component/HttpKernel/EventListener/SurrogateListener.php @@ -12,6 +12,7 @@ namespace Symfony\Component\HttpKernel\EventListener; use Symfony\Component\HttpKernel\Event\FilterResponseEvent; +use Symfony\Component\HttpKernel\HttpCache\HttpCache; use Symfony\Component\HttpKernel\HttpCache\SurrogateInterface; use Symfony\Component\HttpKernel\KernelEvents; use Symfony\Component\EventDispatcher\EventSubscriberInterface; @@ -42,11 +43,24 @@ public function __construct(SurrogateInterface $surrogate = null) */ public function onKernelResponse(FilterResponseEvent $event) { - if (!$event->isMasterRequest() || null === $this->surrogate) { + if (!$event->isMasterRequest()) { return; } - $this->surrogate->addSurrogateControl($event->getResponse()); + $kernel = $event->getKernel(); + $surrogate = $this->surrogate; + if ($kernel instanceof HttpCache) { + $surrogate = $kernel->getSurrogate(); + if (null !== $this->surrogate && $this->surrogate->getName() !== $surrogate->getName()) { + $surrogate = $this->surrogate; + } + } + + if (null === $surrogate) { + return; + } + + $surrogate->addSurrogateControl($event->getResponse()); } public static function getSubscribedEvents() From b3203cb8abb98148b83bc64fc41783ee8708e1b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20TAMARELLE?= Date: Mon, 29 May 2017 19:01:45 +0200 Subject: [PATCH 0216/1099] [SecurityBundle] Move cache of the firewall context into the request parameters --- .../SecurityBundle/Security/FirewallMap.php | 21 +++-- .../Tests/Security/FirewallMapTest.php | 79 +++++++++++++++++++ 2 files changed, 95 insertions(+), 5 deletions(-) create mode 100644 src/Symfony/Bundle/SecurityBundle/Tests/Security/FirewallMapTest.php diff --git a/src/Symfony/Bundle/SecurityBundle/Security/FirewallMap.php b/src/Symfony/Bundle/SecurityBundle/Security/FirewallMap.php index f833a63e65966..77fe45f8a8267 100644 --- a/src/Symfony/Bundle/SecurityBundle/Security/FirewallMap.php +++ b/src/Symfony/Bundle/SecurityBundle/Security/FirewallMap.php @@ -11,6 +11,7 @@ namespace Symfony\Bundle\SecurityBundle\Security; +use Symfony\Bundle\SecurityBundle\Security\FirewallContext; use Symfony\Component\Security\Http\FirewallMapInterface; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\DependencyInjection\ContainerInterface; @@ -26,13 +27,11 @@ class FirewallMap implements FirewallMapInterface { protected $container; protected $map; - private $contexts; public function __construct(ContainerInterface $container, array $map) { $this->container = $container; $this->map = $map; - $this->contexts = new \SplObjectStorage(); } /** @@ -63,15 +62,27 @@ public function getFirewallConfig(Request $request) return $context->getConfig(); } + /** + * @return FirewallContext + */ private function getFirewallContext(Request $request) { - if ($this->contexts->contains($request)) { - return $this->contexts[$request]; + if ($request->attributes->has('_firewall_context')) { + $storedContextId = $request->attributes->get('_firewall_context'); + foreach ($this->map as $contextId => $requestMatcher) { + if ($contextId === $storedContextId) { + return $this->container->get($contextId); + } + } + + $request->attributes->remove('_firewall_context'); } foreach ($this->map as $contextId => $requestMatcher) { if (null === $requestMatcher || $requestMatcher->matches($request)) { - return $this->contexts[$request] = $this->container->get($contextId); + $request->attributes->set('_firewall_context', $contextId); + + return $this->container->get($contextId); } } } diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Security/FirewallMapTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/Security/FirewallMapTest.php new file mode 100644 index 0000000000000..a94d8c2026d8f --- /dev/null +++ b/src/Symfony/Bundle/SecurityBundle/Tests/Security/FirewallMapTest.php @@ -0,0 +1,79 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\SecurityBundle\Tests\Security; + +use PHPUnit\Framework\TestCase; +use Symfony\Bundle\SecurityBundle\Security\FirewallContext; +use Symfony\Bundle\SecurityBundle\Security\FirewallMap; +use Symfony\Component\DependencyInjection\Container; +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\RequestMatcherInterface; + +class FirewallMapTest extends TestCase +{ + const ATTRIBUTE_FIREWALL_CONTEXT = '_firewall_context'; + + public function testGetListenersWithEmptyMap() + { + $request = new Request(); + + $map = array(); + $container = $this->getMockBuilder(Container::class)->getMock(); + $container->expects($this->never())->method('get'); + + $firewallMap = new FirewallMap($container, $map); + + $this->assertEquals(array(array(), null), $firewallMap->getListeners($request)); + $this->assertNull($firewallMap->getFirewallConfig($request)); + $this->assertFalse($request->attributes->has(self::ATTRIBUTE_FIREWALL_CONTEXT)); + } + + public function testGetListenersWithInvalidParameter() + { + $request = new Request(); + $request->attributes->set(self::ATTRIBUTE_FIREWALL_CONTEXT, 'foo'); + + $map = array(); + $container = $this->getMockBuilder(Container::class)->getMock(); + $container->expects($this->never())->method('get'); + + $firewallMap = new FirewallMap($container, $map); + + $this->assertEquals(array(array(), null), $firewallMap->getListeners($request)); + $this->assertNull($firewallMap->getFirewallConfig($request)); + $this->assertFalse($request->attributes->has(self::ATTRIBUTE_FIREWALL_CONTEXT)); + } + + public function testGetListeners() + { + $request = new Request(); + + $firewallContext = $this->getMockBuilder(FirewallContext::class)->disableOriginalConstructor()->getMock(); + $firewallContext->expects($this->once())->method('getConfig')->willReturn('CONFIG'); + $firewallContext->expects($this->once())->method('getContext')->willReturn(array('LISTENERS', 'EXCEPTION LISTENER')); + + $matcher = $this->getMockBuilder(RequestMatcherInterface::class)->getMock(); + $matcher->expects($this->once()) + ->method('matches') + ->with($request) + ->willReturn(true); + + $container = $this->getMockBuilder(Container::class)->getMock(); + $container->expects($this->exactly(2))->method('get')->willReturn($firewallContext); + + $firewallMap = new FirewallMap($container, array('security.firewall.map.context.foo' => $matcher)); + + $this->assertEquals(array('LISTENERS', 'EXCEPTION LISTENER'), $firewallMap->getListeners($request)); + $this->assertEquals('CONFIG', $firewallMap->getFirewallConfig($request)); + $this->assertEquals('security.firewall.map.context.foo', $request->attributes->get(self::ATTRIBUTE_FIREWALL_CONTEXT)); + } +} From 01057875ddd468cc26801ca94a80c958cfe0fe99 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Wed, 14 Jun 2017 13:33:13 -0700 Subject: [PATCH 0217/1099] fixed tests --- .../Bundle/SecurityBundle/Tests/Security/FirewallMapTest.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Security/FirewallMapTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/Security/FirewallMapTest.php index a94d8c2026d8f..da7800cce3037 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/Security/FirewallMapTest.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/Security/FirewallMapTest.php @@ -59,7 +59,8 @@ public function testGetListeners() $firewallContext = $this->getMockBuilder(FirewallContext::class)->disableOriginalConstructor()->getMock(); $firewallContext->expects($this->once())->method('getConfig')->willReturn('CONFIG'); - $firewallContext->expects($this->once())->method('getContext')->willReturn(array('LISTENERS', 'EXCEPTION LISTENER')); + $firewallContext->expects($this->once())->method('getListeners')->willReturn('LISTENERS'); + $firewallContext->expects($this->once())->method('getExceptionListener')->willReturn('EXCEPTION LISTENER'); $matcher = $this->getMockBuilder(RequestMatcherInterface::class)->getMock(); $matcher->expects($this->once()) From 016e97669118ac1045858a36e07ff4da8521d47a Mon Sep 17 00:00:00 2001 From: Roland Franssen Date: Thu, 4 May 2017 19:29:31 +0200 Subject: [PATCH 0218/1099] [Routing] Expose request in route conditions, if needed and possible --- .../Routing/Matcher/RedirectableUrlMatcher.php | 2 +- .../Routing/Matcher/TraceableUrlMatcher.php | 2 +- .../Component/Routing/Matcher/UrlMatcher.php | 17 ++++++++++++++++- .../Routing/Tests/Matcher/UrlMatcherTest.php | 10 ++++++++++ 4 files changed, 28 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Component/Routing/Matcher/RedirectableUrlMatcher.php b/src/Symfony/Component/Routing/Matcher/RedirectableUrlMatcher.php index 463bc0d056809..900c59fa37392 100644 --- a/src/Symfony/Component/Routing/Matcher/RedirectableUrlMatcher.php +++ b/src/Symfony/Component/Routing/Matcher/RedirectableUrlMatcher.php @@ -49,7 +49,7 @@ public function match($pathinfo) protected function handleRouteRequirements($pathinfo, $name, Route $route) { // expression condition - if ($route->getCondition() && !$this->getExpressionLanguage()->evaluate($route->getCondition(), array('context' => $this->context, 'request' => $this->request))) { + if ($route->getCondition() && !$this->getExpressionLanguage()->evaluate($route->getCondition(), array('context' => $this->context, 'request' => $this->request ?: $this->createRequest($pathinfo)))) { return array(self::REQUIREMENT_MISMATCH, null); } diff --git a/src/Symfony/Component/Routing/Matcher/TraceableUrlMatcher.php b/src/Symfony/Component/Routing/Matcher/TraceableUrlMatcher.php index cb1a35f4d3023..9085be0424886 100644 --- a/src/Symfony/Component/Routing/Matcher/TraceableUrlMatcher.php +++ b/src/Symfony/Component/Routing/Matcher/TraceableUrlMatcher.php @@ -105,7 +105,7 @@ protected function matchCollection($pathinfo, RouteCollection $routes) // check condition if ($condition = $route->getCondition()) { - if (!$this->getExpressionLanguage()->evaluate($condition, array('context' => $this->context, 'request' => $this->request))) { + if (!$this->getExpressionLanguage()->evaluate($condition, array('context' => $this->context, 'request' => $this->request ?: $this->createRequest($pathinfo)))) { $this->addTrace(sprintf('Condition "%s" does not evaluate to "true"', $condition), self::ROUTE_ALMOST_MATCHES, $name, $route); continue; diff --git a/src/Symfony/Component/Routing/Matcher/UrlMatcher.php b/src/Symfony/Component/Routing/Matcher/UrlMatcher.php index 9786a9b42cc60..c646723b3ab08 100644 --- a/src/Symfony/Component/Routing/Matcher/UrlMatcher.php +++ b/src/Symfony/Component/Routing/Matcher/UrlMatcher.php @@ -207,7 +207,7 @@ protected function getAttributes(Route $route, $name, array $attributes) protected function handleRouteRequirements($pathinfo, $name, Route $route) { // expression condition - if ($route->getCondition() && !$this->getExpressionLanguage()->evaluate($route->getCondition(), array('context' => $this->context, 'request' => $this->request))) { + if ($route->getCondition() && !$this->getExpressionLanguage()->evaluate($route->getCondition(), array('context' => $this->context, 'request' => $this->request ?: $this->createRequest($pathinfo)))) { return array(self::REQUIREMENT_MISMATCH, null); } @@ -248,4 +248,19 @@ protected function getExpressionLanguage() return $this->expressionLanguage; } + + /** + * @internal + */ + protected function createRequest($pathinfo) + { + if (!class_exists('Symfony\Component\HttpFoundation\Request')) { + return null; + } + + return Request::create($this->context->getScheme().'://'.$this->context->getHost().$this->context->getBaseUrl().$pathinfo, $this->context->getMethod(), $this->context->getParameters(), array(), array(), array( + 'SCRIPT_FILENAME' => $this->context->getBaseUrl(), + 'SCRIPT_NAME' => $this->context->getBaseUrl(), + )); + } } diff --git a/src/Symfony/Component/Routing/Tests/Matcher/UrlMatcherTest.php b/src/Symfony/Component/Routing/Tests/Matcher/UrlMatcherTest.php index 6d59855d2d8f3..9fd53e9814496 100644 --- a/src/Symfony/Component/Routing/Tests/Matcher/UrlMatcherTest.php +++ b/src/Symfony/Component/Routing/Tests/Matcher/UrlMatcherTest.php @@ -337,6 +337,16 @@ public function testCondition() $matcher->match('/foo'); } + public function testRequestCondition() + { + $coll = new RouteCollection(); + $route = new Route('/foo/{bar}'); + $route->setCondition('request.getBaseUrl() == "/sub/front.php" and request.getPathInfo() == "/foo/bar"'); + $coll->add('foo', $route); + $matcher = new UrlMatcher($coll, new RequestContext('/sub/front.php')); + $this->assertEquals(array('bar' => 'bar', '_route' => 'foo'), $matcher->match('/foo/bar')); + } + public function testDecodeOnce() { $coll = new RouteCollection(); From 94371d052b8474d2dafa170d9c181ee8459ad4bd Mon Sep 17 00:00:00 2001 From: Roland Franssen Date: Thu, 4 May 2017 19:29:31 +0200 Subject: [PATCH 0219/1099] [Routing] Expose request in route conditions, if needed and possible --- .../Routing/Matcher/RedirectableUrlMatcher.php | 2 +- .../Routing/Matcher/TraceableUrlMatcher.php | 2 +- .../Component/Routing/Matcher/UrlMatcher.php | 17 ++++++++++++++++- .../Routing/Tests/Matcher/UrlMatcherTest.php | 10 ++++++++++ 4 files changed, 28 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Component/Routing/Matcher/RedirectableUrlMatcher.php b/src/Symfony/Component/Routing/Matcher/RedirectableUrlMatcher.php index 463bc0d056809..900c59fa37392 100644 --- a/src/Symfony/Component/Routing/Matcher/RedirectableUrlMatcher.php +++ b/src/Symfony/Component/Routing/Matcher/RedirectableUrlMatcher.php @@ -49,7 +49,7 @@ public function match($pathinfo) protected function handleRouteRequirements($pathinfo, $name, Route $route) { // expression condition - if ($route->getCondition() && !$this->getExpressionLanguage()->evaluate($route->getCondition(), array('context' => $this->context, 'request' => $this->request))) { + if ($route->getCondition() && !$this->getExpressionLanguage()->evaluate($route->getCondition(), array('context' => $this->context, 'request' => $this->request ?: $this->createRequest($pathinfo)))) { return array(self::REQUIREMENT_MISMATCH, null); } diff --git a/src/Symfony/Component/Routing/Matcher/TraceableUrlMatcher.php b/src/Symfony/Component/Routing/Matcher/TraceableUrlMatcher.php index cb1a35f4d3023..9085be0424886 100644 --- a/src/Symfony/Component/Routing/Matcher/TraceableUrlMatcher.php +++ b/src/Symfony/Component/Routing/Matcher/TraceableUrlMatcher.php @@ -105,7 +105,7 @@ protected function matchCollection($pathinfo, RouteCollection $routes) // check condition if ($condition = $route->getCondition()) { - if (!$this->getExpressionLanguage()->evaluate($condition, array('context' => $this->context, 'request' => $this->request))) { + if (!$this->getExpressionLanguage()->evaluate($condition, array('context' => $this->context, 'request' => $this->request ?: $this->createRequest($pathinfo)))) { $this->addTrace(sprintf('Condition "%s" does not evaluate to "true"', $condition), self::ROUTE_ALMOST_MATCHES, $name, $route); continue; diff --git a/src/Symfony/Component/Routing/Matcher/UrlMatcher.php b/src/Symfony/Component/Routing/Matcher/UrlMatcher.php index 9786a9b42cc60..c646723b3ab08 100644 --- a/src/Symfony/Component/Routing/Matcher/UrlMatcher.php +++ b/src/Symfony/Component/Routing/Matcher/UrlMatcher.php @@ -207,7 +207,7 @@ protected function getAttributes(Route $route, $name, array $attributes) protected function handleRouteRequirements($pathinfo, $name, Route $route) { // expression condition - if ($route->getCondition() && !$this->getExpressionLanguage()->evaluate($route->getCondition(), array('context' => $this->context, 'request' => $this->request))) { + if ($route->getCondition() && !$this->getExpressionLanguage()->evaluate($route->getCondition(), array('context' => $this->context, 'request' => $this->request ?: $this->createRequest($pathinfo)))) { return array(self::REQUIREMENT_MISMATCH, null); } @@ -248,4 +248,19 @@ protected function getExpressionLanguage() return $this->expressionLanguage; } + + /** + * @internal + */ + protected function createRequest($pathinfo) + { + if (!class_exists('Symfony\Component\HttpFoundation\Request')) { + return null; + } + + return Request::create($this->context->getScheme().'://'.$this->context->getHost().$this->context->getBaseUrl().$pathinfo, $this->context->getMethod(), $this->context->getParameters(), array(), array(), array( + 'SCRIPT_FILENAME' => $this->context->getBaseUrl(), + 'SCRIPT_NAME' => $this->context->getBaseUrl(), + )); + } } diff --git a/src/Symfony/Component/Routing/Tests/Matcher/UrlMatcherTest.php b/src/Symfony/Component/Routing/Tests/Matcher/UrlMatcherTest.php index 6d59855d2d8f3..9fd53e9814496 100644 --- a/src/Symfony/Component/Routing/Tests/Matcher/UrlMatcherTest.php +++ b/src/Symfony/Component/Routing/Tests/Matcher/UrlMatcherTest.php @@ -337,6 +337,16 @@ public function testCondition() $matcher->match('/foo'); } + public function testRequestCondition() + { + $coll = new RouteCollection(); + $route = new Route('/foo/{bar}'); + $route->setCondition('request.getBaseUrl() == "/sub/front.php" and request.getPathInfo() == "/foo/bar"'); + $coll->add('foo', $route); + $matcher = new UrlMatcher($coll, new RequestContext('/sub/front.php')); + $this->assertEquals(array('bar' => 'bar', '_route' => 'foo'), $matcher->match('/foo/bar')); + } + public function testDecodeOnce() { $coll = new RouteCollection(); From c6e8c07e4df22bdf950954266a255dabefaee69a Mon Sep 17 00:00:00 2001 From: Matthias Pigulla Date: Sun, 11 Jun 2017 00:34:20 +0200 Subject: [PATCH 0220/1099] Fix two edge cases in ResponseCacheStrategy --- .../HttpCache/ResponseCacheStrategy.php | 2 +- .../HttpCache/ResponseCacheStrategyTest.php | 41 +++++++++++++++++++ 2 files changed, 42 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/HttpKernel/HttpCache/ResponseCacheStrategy.php b/src/Symfony/Component/HttpKernel/HttpCache/ResponseCacheStrategy.php index 39a99e6966c22..6e24016340ed6 100644 --- a/src/Symfony/Component/HttpKernel/HttpCache/ResponseCacheStrategy.php +++ b/src/Symfony/Component/HttpKernel/HttpCache/ResponseCacheStrategy.php @@ -39,7 +39,7 @@ class ResponseCacheStrategy implements ResponseCacheStrategyInterface */ public function add(Response $response) { - if ($response->isValidateable()) { + if ($response->isValidateable() || !$response->isCacheable()) { $this->cacheable = false; } else { $maxAge = $response->getMaxAge(); diff --git a/src/Symfony/Component/HttpKernel/Tests/HttpCache/ResponseCacheStrategyTest.php b/src/Symfony/Component/HttpKernel/Tests/HttpCache/ResponseCacheStrategyTest.php index a37a85bc436a9..4188bb37f243c 100644 --- a/src/Symfony/Component/HttpKernel/Tests/HttpCache/ResponseCacheStrategyTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/HttpCache/ResponseCacheStrategyTest.php @@ -137,4 +137,45 @@ public function testMasterResponseWithExpirationIsUnchangedWhenThereIsNoEmbedded $this->assertTrue($masterResponse->isFresh()); } + + public function testMasterResponseIsNotCacheableWhenEmbeddedResponseIsNotCacheable() + { + $cacheStrategy = new ResponseCacheStrategy(); + + $masterResponse = new Response(); + $masterResponse->setSharedMaxAge(3600); // Public, cacheable + + /* This response has no validation or expiration information. + That makes it uncacheable, it is always stale. + (It does *not* make this private, though.) */ + $embeddedResponse = new Response(); + $this->assertFalse($embeddedResponse->isFresh()); // not fresh, as no lifetime is provided + + $cacheStrategy->add($embeddedResponse); + $cacheStrategy->update($masterResponse); + + $this->assertTrue($masterResponse->headers->hasCacheControlDirective('no-cache')); + $this->assertTrue($masterResponse->headers->hasCacheControlDirective('must-revalidate')); + $this->assertFalse($masterResponse->isFresh()); + } + + public function testEmbeddingPrivateResponseMakesMainResponsePrivate() + { + $cacheStrategy = new ResponseCacheStrategy(); + + $masterResponse = new Response(); + $masterResponse->setSharedMaxAge(3600); // public, cacheable + + // The embedded response might for example contain per-user data that remains valid for 60 seconds + $embeddedResponse = new Response(); + $embeddedResponse->setPrivate(); + $embeddedResponse->setMaxAge(60); // this would implicitly set "private" as well, but let's be explicit + + $cacheStrategy->add($embeddedResponse); + $cacheStrategy->update($masterResponse); + + $this->assertTrue($masterResponse->headers->hasCacheControlDirective('private')); + // Not sure if we should pass "max-age: 60" in this case, as long as the response is private and + // that's the more conservative of both the master and embedded response...? + } } From 8dc00bbe8d901d80c2916295607a82b0e0233ed9 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Wed, 14 Jun 2017 14:54:47 -0700 Subject: [PATCH 0221/1099] fixed bad merge --- .../Component/PropertyAccess/Tests/PropertyAccessorTest.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Symfony/Component/PropertyAccess/Tests/PropertyAccessorTest.php b/src/Symfony/Component/PropertyAccess/Tests/PropertyAccessorTest.php index 61100c0d68944..275c76e0f3b50 100644 --- a/src/Symfony/Component/PropertyAccess/Tests/PropertyAccessorTest.php +++ b/src/Symfony/Component/PropertyAccess/Tests/PropertyAccessorTest.php @@ -641,6 +641,7 @@ public function setFoo($foo) } /** + * @requires PHP 7.0 * @expectedException \TypeError */ public function testThrowTypeErrorInsideSetterCall() From 09bcbc70e7c7cd9f57d2af10d2e8cd806b87ccc3 Mon Sep 17 00:00:00 2001 From: Matthias Pigulla Date: Sun, 11 Jun 2017 00:58:50 +0200 Subject: [PATCH 0222/1099] Embedding a response that combines expiration and validation, that should not defeat expiration on the combined response --- .../HttpCache/ResponseCacheStrategy.php | 5 ++- .../HttpCache/ResponseCacheStrategyTest.php | 41 +++++++++++++++++++ 2 files changed, 45 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/HttpKernel/HttpCache/ResponseCacheStrategy.php b/src/Symfony/Component/HttpKernel/HttpCache/ResponseCacheStrategy.php index 6e24016340ed6..027b2b1761334 100644 --- a/src/Symfony/Component/HttpKernel/HttpCache/ResponseCacheStrategy.php +++ b/src/Symfony/Component/HttpKernel/HttpCache/ResponseCacheStrategy.php @@ -39,7 +39,7 @@ class ResponseCacheStrategy implements ResponseCacheStrategyInterface */ public function add(Response $response) { - if ($response->isValidateable() || !$response->isCacheable()) { + if (!$response->isFresh() || !$response->isCacheable()) { $this->cacheable = false; } else { $maxAge = $response->getMaxAge(); @@ -70,6 +70,9 @@ public function update(Response $response) if ($response->isValidateable()) { $response->setEtag(null); $response->setLastModified(null); + } + + if (!$response->isFresh()) { $this->cacheable = false; } diff --git a/src/Symfony/Component/HttpKernel/Tests/HttpCache/ResponseCacheStrategyTest.php b/src/Symfony/Component/HttpKernel/Tests/HttpCache/ResponseCacheStrategyTest.php index 4188bb37f243c..5e4c322223eb3 100644 --- a/src/Symfony/Component/HttpKernel/Tests/HttpCache/ResponseCacheStrategyTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/HttpCache/ResponseCacheStrategyTest.php @@ -178,4 +178,45 @@ public function testEmbeddingPrivateResponseMakesMainResponsePrivate() // Not sure if we should pass "max-age: 60" in this case, as long as the response is private and // that's the more conservative of both the master and embedded response...? } + + public function testResponseIsExiprableWhenEmbeddedResponseCombinesExpiryAndValidation() + { + /* When "expiration wins over validation" (https://symfony.com/doc/current/http_cache/validation.html) + * and both the main and embedded response provide s-maxage, then the more restricting value of both + * should be fine, regardless of whether the embedded response can be validated later on or must be + * completely regenerated. + */ + $cacheStrategy = new ResponseCacheStrategy(); + + $masterResponse = new Response(); + $masterResponse->setSharedMaxAge(3600); + + $embeddedResponse = new Response(); + $embeddedResponse->setSharedMaxAge(60); + $embeddedResponse->setEtag('foo'); + + $cacheStrategy->add($embeddedResponse); + $cacheStrategy->update($masterResponse); + + $this->assertSame('60', $masterResponse->headers->getCacheControlDirective('s-maxage')); + } + + public function testResponseIsExpirableButNotValidateableWhenMasterResponseCombinesExpirationAndValidation() + { + $cacheStrategy = new ResponseCacheStrategy(); + + $masterResponse = new Response(); + $masterResponse->setSharedMaxAge(3600); + $masterResponse->setEtag('foo'); + $masterResponse->setLastModified(new \DateTime()); + + $embeddedResponse = new Response(); + $embeddedResponse->setSharedMaxAge(60); + + $cacheStrategy->add($embeddedResponse); + $cacheStrategy->update($masterResponse); + + $this->assertSame('60', $masterResponse->headers->getCacheControlDirective('s-maxage')); + $this->assertFalse($masterResponse->isValidateable()); + } } From e66d8f1bef18c3f84c2ec696946c785f9606e758 Mon Sep 17 00:00:00 2001 From: "Israel J. Carberry" Date: Mon, 5 Jun 2017 15:57:58 -0500 Subject: [PATCH 0223/1099] [Validator] Adds support to check specific DNS record type for URL --- src/Symfony/Component/Validator/CHANGELOG.md | 1 + .../Component/Validator/Constraints/Url.php | 16 ++++- .../Validator/Constraints/UrlValidator.php | 26 ++++++- .../Tests/Constraints/UrlValidatorTest.php | 71 ++++++++++++++++++- 4 files changed, 111 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Component/Validator/CHANGELOG.md b/src/Symfony/Component/Validator/CHANGELOG.md index b35a4824104cc..f886b1133a7b9 100644 --- a/src/Symfony/Component/Validator/CHANGELOG.md +++ b/src/Symfony/Component/Validator/CHANGELOG.md @@ -6,6 +6,7 @@ CHANGELOG * not setting the `strict` option of the `Choice` constraint to `true` is deprecated and will throw an exception in Symfony 4.0 + * setting the `checkDNS` option of the `Url` constraint to `true` is deprecated in favor of constant values and will throw an exception in Symfony 4.0 3.3.0 ----- diff --git a/src/Symfony/Component/Validator/Constraints/Url.php b/src/Symfony/Component/Validator/Constraints/Url.php index 8453a902081b2..988dd19136da6 100644 --- a/src/Symfony/Component/Validator/Constraints/Url.php +++ b/src/Symfony/Component/Validator/Constraints/Url.php @@ -21,6 +21,20 @@ */ class Url extends Constraint { + const CHECK_DNS_TYPE_ANY = 'ANY'; + const CHECK_DNS_TYPE_NONE = false; + const CHECK_DNS_TYPE_A = 'A'; + const CHECK_DNS_TYPE_A6 = 'A6'; + const CHECK_DNS_TYPE_AAAA = 'AAAA'; + const CHECK_DNS_TYPE_CNAME = 'CNAME'; + const CHECK_DNS_TYPE_MX = 'MX'; + const CHECK_DNS_TYPE_NAPTR = 'NAPTR'; + const CHECK_DNS_TYPE_NS = 'NS'; + const CHECK_DNS_TYPE_PTR = 'PTR'; + const CHECK_DNS_TYPE_SOA = 'SOA'; + const CHECK_DNS_TYPE_SRV = 'SRV'; + const CHECK_DNS_TYPE_TXT = 'TXT'; + const INVALID_URL_ERROR = '57c2f299-1154-4870-89bb-ef3b1f5ad229'; protected static $errorNames = array( @@ -30,5 +44,5 @@ class Url extends Constraint public $message = 'This value is not a valid URL.'; public $dnsMessage = 'The host could not be resolved.'; public $protocols = array('http', 'https'); - public $checkDNS = false; + public $checkDNS = self::CHECK_DNS_TYPE_NONE; } diff --git a/src/Symfony/Component/Validator/Constraints/UrlValidator.php b/src/Symfony/Component/Validator/Constraints/UrlValidator.php index 118a8defc1468..e011239d56f28 100644 --- a/src/Symfony/Component/Validator/Constraints/UrlValidator.php +++ b/src/Symfony/Component/Validator/Constraints/UrlValidator.php @@ -13,6 +13,7 @@ use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\ConstraintValidator; +use Symfony\Component\Validator\Exception\InvalidOptionsException; use Symfony\Component\Validator\Exception\UnexpectedTypeException; /** @@ -72,9 +73,32 @@ public function validate($value, Constraint $constraint) } if ($constraint->checkDNS) { + // backwards compatibility + if ($constraint->checkDNS === true) { + $constraint->checkDNS = Url::CHECK_DNS_TYPE_ANY; + @trigger_error(sprintf('Use of the boolean TRUE for the "checkDNS" option in %s is deprecated. Use Url::CHECK_DNS_TYPE_ANY instead.', Url::class), E_USER_DEPRECATED); + } + + if (!in_array($constraint->checkDNS, array( + Url::CHECK_DNS_TYPE_ANY, + Url::CHECK_DNS_TYPE_A, + Url::CHECK_DNS_TYPE_A6, + Url::CHECK_DNS_TYPE_AAAA, + Url::CHECK_DNS_TYPE_CNAME, + Url::CHECK_DNS_TYPE_MX, + Url::CHECK_DNS_TYPE_NAPTR, + Url::CHECK_DNS_TYPE_NS, + Url::CHECK_DNS_TYPE_PTR, + Url::CHECK_DNS_TYPE_SOA, + Url::CHECK_DNS_TYPE_SRV, + Url::CHECK_DNS_TYPE_TXT, + ))) { + throw new InvalidOptionsException(sprintf('Invalid value for option "checkDNS" in constraint %s', get_class($constraint)), array('checkDNS')); + } + $host = parse_url($value, PHP_URL_HOST); - if (!is_string($host) || !checkdnsrr($host, 'ANY')) { + if (!is_string($host) || !checkdnsrr($host, $constraint->checkDNS)) { $this->context->buildViolation($constraint->dnsMessage) ->setParameter('{{ value }}', $this->formatValue($host)) ->setCode(Url::INVALID_URL_ERROR) diff --git a/src/Symfony/Component/Validator/Tests/Constraints/UrlValidatorTest.php b/src/Symfony/Component/Validator/Tests/Constraints/UrlValidatorTest.php index 0459dd02201ed..633dcf6d571b2 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/UrlValidatorTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/UrlValidatorTest.php @@ -203,7 +203,7 @@ public function testCheckDns($violation) DnsMock::withMockedHosts(array('example.com' => array(array('type' => $violation ? '' : 'A')))); $constraint = new Url(array( - 'checkDNS' => true, + 'checkDNS' => 'ANY', 'dnsMessage' => 'myMessage', )); @@ -223,6 +223,75 @@ public function getCheckDns() { return array(array(true), array(false)); } + + /** + * @dataProvider getCheckDnsTypes + * @requires function Symfony\Bridge\PhpUnit\DnsMock::withMockedHosts + */ + public function testCheckDnsByType($type) + { + DnsMock::withMockedHosts(array('example.com' => array(array('type' => $type)))); + + $constraint = new Url(array( + 'checkDNS' => $type, + 'dnsMessage' => 'myMessage', + )); + + $this->validator->validate('http://example.com', $constraint); + + $this->assertNoViolation(); + } + + public function getCheckDnsTypes() + { + return array( + array('ANY'), + array('A'), + array('A6'), + array('AAAA'), + array('CNAME'), + array('MX'), + array('NAPTR'), + array('NS'), + array('PTR'), + array('SOA'), + array('SRV'), + array('TXT'), + ); + } + + /** + * @group legacy + */ + public function testCheckDnsWithBoolean() + { + DnsMock::withMockedHosts(array('example.com' => array(array('type' => 'A')))); + + $constraint = new Url(array( + 'checkDNS' => true, + 'dnsMessage' => 'myMessage', + )); + + $this->validator->validate('http://example.com', $constraint); + + $this->assertNoViolation(); + } + + /** + * @expectedException \Symfony\Component\Validator\Exception\InvalidOptionsException + * @requires function Symfony\Bridge\PhpUnit\DnsMock::withMockedHosts + */ + public function testCheckDnsWithInvalidType() + { + DnsMock::withMockedHosts(array('example.com' => array(array('type' => 'A')))); + + $constraint = new Url(array( + 'checkDNS' => 'BOGUS', + 'dnsMessage' => 'myMessage', + )); + + $this->validator->validate('http://example.com', $constraint); + } } class EmailProvider From 9e2b408f255ffac5cc494cdb11ebe503612dea8f Mon Sep 17 00:00:00 2001 From: rchoquet Date: Thu, 15 Jun 2017 11:46:38 +0200 Subject: [PATCH 0224/1099] add content-type header on exception response --- .../Controller/ExceptionController.php | 2 +- .../Controller/ExceptionControllerTest.php | 51 ++++++++++++------- 2 files changed, 35 insertions(+), 18 deletions(-) diff --git a/src/Symfony/Bundle/TwigBundle/Controller/ExceptionController.php b/src/Symfony/Bundle/TwigBundle/Controller/ExceptionController.php index 0eab87de26e2b..1878204003b62 100644 --- a/src/Symfony/Bundle/TwigBundle/Controller/ExceptionController.php +++ b/src/Symfony/Bundle/TwigBundle/Controller/ExceptionController.php @@ -74,7 +74,7 @@ public function showAction(Request $request, FlattenException $exception, DebugL 'logger' => $logger, 'currentContent' => $currentContent, ) - )); + ), 200, array('Content-Type' => $request->getMimeType($request->getRequestFormat()) ?: 'text/html')); } /** diff --git a/src/Symfony/Bundle/TwigBundle/Tests/Controller/ExceptionControllerTest.php b/src/Symfony/Bundle/TwigBundle/Tests/Controller/ExceptionControllerTest.php index 17f3ac17c87f2..7b85d86508273 100644 --- a/src/Symfony/Bundle/TwigBundle/Tests/Controller/ExceptionControllerTest.php +++ b/src/Symfony/Bundle/TwigBundle/Tests/Controller/ExceptionControllerTest.php @@ -22,14 +22,9 @@ class ExceptionControllerTest extends TestCase { public function testShowActionCanBeForcedToShowErrorPage() { - $twig = new Environment( - new ArrayLoader(array( - 'TwigBundle:Exception:error404.html.twig' => 'ok', - )) - ); + $twig = $this->createTwigEnv(array('TwigBundle:Exception:error404.html.twig' => 'not found')); - $request = Request::create('whatever', 'GET'); - $request->headers->set('X-Php-Ob-Level', 1); + $request = $this->createRequest('html'); $request->attributes->set('showException', false); $exception = FlattenException::create(new \Exception(), 404); $controller = new ExceptionController($twig, /* "showException" defaults to --> */ true); @@ -37,25 +32,47 @@ public function testShowActionCanBeForcedToShowErrorPage() $response = $controller->showAction($request, $exception, null); $this->assertEquals(200, $response->getStatusCode()); // successful request - $this->assertEquals('ok', $response->getContent()); // content of the error404.html template + $this->assertEquals('not found', $response->getContent()); } public function testFallbackToHtmlIfNoTemplateForRequestedFormat() { - $twig = new Environment( - new ArrayLoader(array( - 'TwigBundle:Exception:error.html.twig' => 'html', - )) - ); + $twig = $this->createTwigEnv(array('TwigBundle:Exception:error.html.twig' => '')); - $request = Request::create('whatever'); - $request->headers->set('X-Php-Ob-Level', 1); - $request->setRequestFormat('txt'); + $request = $this->createRequest('txt'); $exception = FlattenException::create(new \Exception()); $controller = new ExceptionController($twig, false); - $response = $controller->showAction($request, $exception); + $controller->showAction($request, $exception); $this->assertEquals('html', $request->getRequestFormat()); } + + public function testResponseHasRequestedMimeType() + { + $twig = $this->createTwigEnv(array('TwigBundle:Exception:error.json.twig' => '{}')); + + $request = $this->createRequest('json'); + $exception = FlattenException::create(new \Exception()); + $controller = new ExceptionController($twig, false); + + $response = $controller->showAction($request, $exception); + + $this->assertEquals('json', $request->getRequestFormat()); + $this->assertEquals($request->getMimeType('json'), $response->headers->get('Content-Type')); + } + + private function createRequest($requestFormat) + { + $request = Request::create('whatever'); + $request->headers->set('X-Php-Ob-Level', 1); + $request->setRequestFormat($requestFormat); + + return $request; + } + + private function createTwigEnv(array $templates) + { + return new Environment(new ArrayLoader($templates)); + } } From 6ac0de8c2f3792a03854932eaef6906a05949042 Mon Sep 17 00:00:00 2001 From: Maxime Steinhausser Date: Thu, 15 Jun 2017 13:47:35 +0200 Subject: [PATCH 0225/1099] [TwigBundle] Remove template.xml services when templating is disabled --- .../TwigBundle/DependencyInjection/Compiler/ExtensionPass.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Symfony/Bundle/TwigBundle/DependencyInjection/Compiler/ExtensionPass.php b/src/Symfony/Bundle/TwigBundle/DependencyInjection/Compiler/ExtensionPass.php index ab9479e46166a..c829cfa4377fb 100644 --- a/src/Symfony/Bundle/TwigBundle/DependencyInjection/Compiler/ExtensionPass.php +++ b/src/Symfony/Bundle/TwigBundle/DependencyInjection/Compiler/ExtensionPass.php @@ -96,6 +96,7 @@ public function process(ContainerBuilder $container) $twigLoader->clearTag('twig.loader'); } else { $container->setAlias('twig.loader.filesystem', new Alias('twig.loader.native_filesystem', false)); + $container->removeDefinition('templating.engine.twig'); } if ($container->has('assets.packages')) { From ee17131fcac065ca45742de629d446f888a325ef Mon Sep 17 00:00:00 2001 From: Ben Scott Date: Wed, 14 Jun 2017 17:24:40 +0100 Subject: [PATCH 0226/1099] Expose the AbstractController's container to its subclasses Useful if an application provides their own base Controller that references items in the container. It also makes it simpler for that base controller to add additional optional dependencies by only overriding getSubscribedServices instead of having to reimplement setContainer and use ControllerTrait. --- .../Bundle/FrameworkBundle/Controller/AbstractController.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/Controller/AbstractController.php b/src/Symfony/Bundle/FrameworkBundle/Controller/AbstractController.php index def76d9defba2..3ba3b8471edc4 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Controller/AbstractController.php +++ b/src/Symfony/Bundle/FrameworkBundle/Controller/AbstractController.php @@ -35,7 +35,10 @@ abstract class AbstractController implements ServiceSubscriberInterface { use ControllerTrait; - private $container; + /** + * @var ContainerInterface + */ + protected $container; /** * @internal From f927ebadadedb89d255d76e179e0ec992e7612c9 Mon Sep 17 00:00:00 2001 From: meyerbaptiste Date: Thu, 15 Jun 2017 14:58:50 +0200 Subject: [PATCH 0227/1099] [Yaml] Fix typo: PARSE_KEYS_AS_STRING -> PARSE_KEYS_AS_STRINGS --- src/Symfony/Component/Yaml/Inline.php | 2 +- src/Symfony/Component/Yaml/Parser.php | 2 +- src/Symfony/Component/Yaml/Tests/InlineTest.php | 2 +- src/Symfony/Component/Yaml/Tests/ParserTest.php | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Symfony/Component/Yaml/Inline.php b/src/Symfony/Component/Yaml/Inline.php index 6789f79efb6cf..5aac7cb89490a 100644 --- a/src/Symfony/Component/Yaml/Inline.php +++ b/src/Symfony/Component/Yaml/Inline.php @@ -494,7 +494,7 @@ private static function parseMapping($mapping, $flags, &$i = 0, $references = ar $evaluatedKey = self::evaluateScalar($key, $flags, $references); if ('' !== $key && $evaluatedKey !== $key && !is_string($evaluatedKey) && !is_int($evaluatedKey)) { - @trigger_error('Implicit casting of incompatible mapping keys to strings is deprecated since version 3.3 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0. Pass the PARSE_KEYS_AS_STRING flag to explicitly enable the type casts.', E_USER_DEPRECATED); + @trigger_error('Implicit casting of incompatible mapping keys to strings is deprecated since version 3.3 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0. Pass the PARSE_KEYS_AS_STRINGS flag to explicitly enable the type casts.', E_USER_DEPRECATED); } } diff --git a/src/Symfony/Component/Yaml/Parser.php b/src/Symfony/Component/Yaml/Parser.php index 29fcf8da5cec8..887e2184a0efb 100644 --- a/src/Symfony/Component/Yaml/Parser.php +++ b/src/Symfony/Component/Yaml/Parser.php @@ -238,7 +238,7 @@ private function doParse($value, $flags) if (!(Yaml::PARSE_KEYS_AS_STRINGS & $flags) && !is_string($key) && !is_int($key)) { $keyType = is_numeric($key) ? 'numeric key' : 'non-string key'; - @trigger_error(sprintf('Implicit casting of %s to string is deprecated since version 3.3 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0. Pass the PARSE_KEYS_AS_STRING flag to explicitly enable the type casts.', $keyType), E_USER_DEPRECATED); + @trigger_error(sprintf('Implicit casting of %s to string is deprecated since version 3.3 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0. Pass the PARSE_KEYS_AS_STRINGS flag to explicitly enable the type casts.', $keyType), E_USER_DEPRECATED); } // Convert float keys to strings, to avoid being converted to integers by PHP diff --git a/src/Symfony/Component/Yaml/Tests/InlineTest.php b/src/Symfony/Component/Yaml/Tests/InlineTest.php index 647904a91632b..89950251cb242 100644 --- a/src/Symfony/Component/Yaml/Tests/InlineTest.php +++ b/src/Symfony/Component/Yaml/Tests/InlineTest.php @@ -730,7 +730,7 @@ public function testTheEmptyStringIsAValidMappingKey() /** * @group legacy - * @expectedDeprecation Implicit casting of incompatible mapping keys to strings is deprecated since version 3.3 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0. Pass the PARSE_KEYS_AS_STRING flag to explicitly enable the type casts. + * @expectedDeprecation Implicit casting of incompatible mapping keys to strings is deprecated since version 3.3 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0. Pass the PARSE_KEYS_AS_STRINGS flag to explicitly enable the type casts. * @dataProvider getNotPhpCompatibleMappingKeyData */ public function testImplicitStringCastingOfMappingKeysIsDeprecated($yaml, $expected) diff --git a/src/Symfony/Component/Yaml/Tests/ParserTest.php b/src/Symfony/Component/Yaml/Tests/ParserTest.php index a296a3300125d..c1ce9a161fdab 100644 --- a/src/Symfony/Component/Yaml/Tests/ParserTest.php +++ b/src/Symfony/Component/Yaml/Tests/ParserTest.php @@ -1081,7 +1081,7 @@ public function testYamlDirective() /** * @group legacy - * @expectedDeprecation Implicit casting of numeric key to string is deprecated since version 3.3 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0. Pass the PARSE_KEYS_AS_STRING flag to explicitly enable the type casts. + * @expectedDeprecation Implicit casting of numeric key to string is deprecated since version 3.3 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0. Pass the PARSE_KEYS_AS_STRINGS flag to explicitly enable the type casts. */ public function testFloatKeys() { @@ -1103,7 +1103,7 @@ public function testFloatKeys() /** * @group legacy - * @expectedDeprecation Implicit casting of non-string key to string is deprecated since version 3.3 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0. Pass the PARSE_KEYS_AS_STRING flag to explicitly enable the type casts. + * @expectedDeprecation Implicit casting of non-string key to string is deprecated since version 3.3 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0. Pass the PARSE_KEYS_AS_STRINGS flag to explicitly enable the type casts. */ public function testBooleanKeys() { From 83fd578f9637419698e728515966aa7d308f046d Mon Sep 17 00:00:00 2001 From: Henne Van Och Date: Thu, 15 Jun 2017 15:33:54 +0200 Subject: [PATCH 0228/1099] Reset redirectCount when throwing exception --- src/Symfony/Component/BrowserKit/Client.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Symfony/Component/BrowserKit/Client.php b/src/Symfony/Component/BrowserKit/Client.php index c69599083802d..b5b2dab50d4cc 100644 --- a/src/Symfony/Component/BrowserKit/Client.php +++ b/src/Symfony/Component/BrowserKit/Client.php @@ -448,6 +448,7 @@ public function followRedirect() if (-1 !== $this->maxRedirects) { if ($this->redirectCount > $this->maxRedirects) { + $this->redirectCount = 0; throw new \LogicException(sprintf('The maximum number (%d) of redirections was reached.', $this->maxRedirects)); } } From 9c253e1ff67e9906ca8ed0831a508a1f63670995 Mon Sep 17 00:00:00 2001 From: Iltar van der Berg Date: Thu, 4 May 2017 09:35:02 +0200 Subject: [PATCH 0229/1099] [Security] Trigger a deprecation when a voter is missing the VoterInterface --- UPGRADE-3.4.md | 8 +++ .../Bundle/SecurityBundle/CHANGELOG.md | 6 ++ .../Compiler/AddSecurityVotersPass.php | 14 ++++ .../Compiler/AddSecurityVotersPassTest.php | 68 +++++++++++++++++-- src/Symfony/Component/Security/CHANGELOG.md | 6 ++ .../Authorization/AccessDecisionManager.php | 30 +++++++- .../Core/Exception/LogicException.php | 21 ++++++ .../AccessDecisionManagerTest.php | 33 +++++++++ .../Stub/VoterWithoutInterface.php | 22 ++++++ 9 files changed, 199 insertions(+), 9 deletions(-) create mode 100644 UPGRADE-3.4.md create mode 100644 src/Symfony/Component/Security/Core/Exception/LogicException.php create mode 100644 src/Symfony/Component/Security/Core/Tests/Authorization/Stub/VoterWithoutInterface.php diff --git a/UPGRADE-3.4.md b/UPGRADE-3.4.md new file mode 100644 index 0000000000000..28135e44cf15b --- /dev/null +++ b/UPGRADE-3.4.md @@ -0,0 +1,8 @@ +UPGRADE FROM 3.3 to 3.4 +======================= + +Security +-------- + + * Using voters that do not implement the `VoterInterface`is now deprecated in + the `AccessDecisionManager` and this functionality will be removed in 4.0. diff --git a/src/Symfony/Bundle/SecurityBundle/CHANGELOG.md b/src/Symfony/Bundle/SecurityBundle/CHANGELOG.md index 9691e5af03c16..715691a8e1b1e 100644 --- a/src/Symfony/Bundle/SecurityBundle/CHANGELOG.md +++ b/src/Symfony/Bundle/SecurityBundle/CHANGELOG.md @@ -1,6 +1,12 @@ CHANGELOG ========= +3.4.0 +----- + + * Tagging voters with the `security.voter` tag without implementing the + `VoterInterface` on the class is now deprecated and will be removed in 4.0. + 3.3.0 ----- diff --git a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Compiler/AddSecurityVotersPass.php b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Compiler/AddSecurityVotersPass.php index e907b7d56792f..67d0785b475fa 100644 --- a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Compiler/AddSecurityVotersPass.php +++ b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Compiler/AddSecurityVotersPass.php @@ -16,6 +16,7 @@ use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; use Symfony\Component\DependencyInjection\Compiler\PriorityTaggedServiceTrait; use Symfony\Component\DependencyInjection\Exception\LogicException; +use Symfony\Component\Security\Core\Authorization\Voter\VoterInterface; /** * Adds all configured security voters to the access decision manager. @@ -40,6 +41,19 @@ public function process(ContainerBuilder $container) throw new LogicException('No security voters found. You need to tag at least one with "security.voter"'); } + foreach ($voters as $voter) { + $class = $container->getDefinition((string) $voter)->getClass(); + + if (!is_a($class, VoterInterface::class, true)) { + @trigger_error(sprintf('Using a security.voter tag on a class without implementing the %1$s is deprecated as of 3.4 and will be removed in 4.0. Implement the %1$s instead.', VoterInterface::class), E_USER_DEPRECATED); + } + + if (!method_exists($class, 'vote')) { + // in case the vote method is completely missing, to prevent exceptions when voting + throw new LogicException(sprintf('%s should implement the %s interface when used as voter.', $class, VoterInterface::class)); + } + } + $adm = $container->getDefinition('security.access.decision_manager'); $adm->replaceArgument(0, new IteratorArgument($voters)); } diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Compiler/AddSecurityVotersPassTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Compiler/AddSecurityVotersPassTest.php index 66d6bde205975..a20b39cee8ae7 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Compiler/AddSecurityVotersPassTest.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Compiler/AddSecurityVotersPassTest.php @@ -14,7 +14,11 @@ use PHPUnit\Framework\TestCase; use Symfony\Bundle\SecurityBundle\DependencyInjection\Compiler\AddSecurityVotersPass; use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Exception\LogicException; use Symfony\Component\DependencyInjection\Reference; +use Symfony\Component\Security\Core\Authorization\AccessDecisionManager; +use Symfony\Component\Security\Core\Authorization\Voter\Voter; +use Symfony\Component\Security\Core\Tests\Authorization\Stub\VoterWithoutInterface; class AddSecurityVotersPassTest extends TestCase { @@ -25,7 +29,7 @@ public function testNoVoters() { $container = new ContainerBuilder(); $container - ->register('security.access.decision_manager', 'Symfony\Component\Security\Core\Authorization\AccessDecisionManager') + ->register('security.access.decision_manager', AccessDecisionManager::class) ->addArgument(array()) ; @@ -37,23 +41,23 @@ public function testThatSecurityVotersAreProcessedInPriorityOrder() { $container = new ContainerBuilder(); $container - ->register('security.access.decision_manager', 'Symfony\Component\Security\Core\Authorization\AccessDecisionManager') + ->register('security.access.decision_manager', AccessDecisionManager::class) ->addArgument(array()) ; $container - ->register('no_prio_service') + ->register('no_prio_service', Voter::class) ->addTag('security.voter') ; $container - ->register('lowest_prio_service') + ->register('lowest_prio_service', Voter::class) ->addTag('security.voter', array('priority' => 100)) ; $container - ->register('highest_prio_service') + ->register('highest_prio_service', Voter::class) ->addTag('security.voter', array('priority' => 200)) ; $container - ->register('zero_prio_service') + ->register('zero_prio_service', Voter::class) ->addTag('security.voter', array('priority' => 0)) ; $compilerPass = new AddSecurityVotersPass(); @@ -65,4 +69,56 @@ public function testThatSecurityVotersAreProcessedInPriorityOrder() $this->assertEquals(new Reference('lowest_prio_service'), $refs[1]); $this->assertCount(4, $refs); } + + /** + * @group legacy + * @expectedDeprecation Using a security.voter tag on a class without implementing the Symfony\Component\Security\Core\Authorization\Voter\VoterInterface is deprecated as of 3.4 and will be removed in 4.0. Implement the Symfony\Component\Security\Core\Authorization\Voter\VoterInterface instead. + */ + public function testVoterMissingInterface() + { + $container = new ContainerBuilder(); + $container + ->register('security.access.decision_manager', AccessDecisionManager::class) + ->addArgument(array()) + ; + $container + ->register('without_interface', VoterWithoutInterface::class) + ->addTag('security.voter') + ; + $compilerPass = new AddSecurityVotersPass(); + $compilerPass->process($container); + + $argument = $container->getDefinition('security.access.decision_manager')->getArgument(0); + $refs = $argument->getValues(); + $this->assertEquals(new Reference('without_interface'), $refs[0]); + $this->assertCount(1, $refs); + } + + /** + * @group legacy + */ + public function testVoterMissingInterfaceAndMethod() + { + $exception = LogicException::class; + $message = 'stdClass should implement the Symfony\Component\Security\Core\Authorization\Voter\VoterInterface interface when used as voter.'; + + if (method_exists($this, 'expectException')) { + $this->expectException($exception); + $this->expectExceptionMessage($message); + } else { + $this->setExpectedException($exception, $message); + } + + $container = new ContainerBuilder(); + $container + ->register('security.access.decision_manager', AccessDecisionManager::class) + ->addArgument(array()) + ; + $container + ->register('without_method', 'stdClass') + ->addTag('security.voter') + ; + $compilerPass = new AddSecurityVotersPass(); + $compilerPass->process($container); + } } diff --git a/src/Symfony/Component/Security/CHANGELOG.md b/src/Symfony/Component/Security/CHANGELOG.md index 69cdd285282fa..292c304fc68c7 100644 --- a/src/Symfony/Component/Security/CHANGELOG.md +++ b/src/Symfony/Component/Security/CHANGELOG.md @@ -1,6 +1,12 @@ CHANGELOG ========= +3.4.0 +----- + + * Using voters that do not implement the `VoterInterface`is now deprecated in + the `AccessDecisionManager` and this functionality will be removed in 4.0. + 3.3.0 ----- diff --git a/src/Symfony/Component/Security/Core/Authorization/AccessDecisionManager.php b/src/Symfony/Component/Security/Core/Authorization/AccessDecisionManager.php index 431597940dd9a..f50caf8cfe8b1 100644 --- a/src/Symfony/Component/Security/Core/Authorization/AccessDecisionManager.php +++ b/src/Symfony/Component/Security/Core/Authorization/AccessDecisionManager.php @@ -13,6 +13,7 @@ use Symfony\Component\Security\Core\Authorization\Voter\VoterInterface; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; +use Symfony\Component\Security\Core\Exception\LogicException; /** * AccessDecisionManager is the base class for all access decision managers @@ -84,7 +85,7 @@ private function decideAffirmative(TokenInterface $token, array $attributes, $ob { $deny = 0; foreach ($this->voters as $voter) { - $result = $voter->vote($token, $object, $attributes); + $result = $this->vote($voter, $token, $object, $attributes); switch ($result) { case VoterInterface::ACCESS_GRANTED: return true; @@ -125,7 +126,7 @@ private function decideConsensus(TokenInterface $token, array $attributes, $obje $grant = 0; $deny = 0; foreach ($this->voters as $voter) { - $result = $voter->vote($token, $object, $attributes); + $result = $this->vote($voter, $token, $object, $attributes); switch ($result) { case VoterInterface::ACCESS_GRANTED: @@ -166,7 +167,7 @@ private function decideUnanimous(TokenInterface $token, array $attributes, $obje $grant = 0; foreach ($this->voters as $voter) { foreach ($attributes as $attribute) { - $result = $voter->vote($token, $object, array($attribute)); + $result = $this->vote($voter, $token, $object, array($attribute)); switch ($result) { case VoterInterface::ACCESS_GRANTED: @@ -190,4 +191,27 @@ private function decideUnanimous(TokenInterface $token, array $attributes, $obje return $this->allowIfAllAbstainDecisions; } + + /** + * TokenInterface vote proxy method. + * + * Acts as a BC layer when the VoterInterface is not implemented on the voter. + * + * @deprecated as of 3.4 and will be removed in 4.0. Call the voter directly as the instance will always be a VoterInterface + */ + private function vote($voter, TokenInterface $token, $subject, $attributes) + { + if ($voter instanceof VoterInterface) { + return $voter->vote($token, $subject, $attributes); + } + + if (method_exists($voter, 'vote')) { + @trigger_error(sprintf('Calling vote() on an voter without %1$s is deprecated as of 3.4 and will be removed in 4.0. Implement the %1$s on your voter.', VoterInterface::class), E_USER_DEPRECATED); + + // making the assumption that the signature matches + return $voter->vote($token, $subject, $attributes); + } + + throw new LogicException(sprintf('%s should implement the %s interface when used as voter.', get_class($voter), VoterInterface::class)); + } } diff --git a/src/Symfony/Component/Security/Core/Exception/LogicException.php b/src/Symfony/Component/Security/Core/Exception/LogicException.php new file mode 100644 index 0000000000000..b9c63e941fca7 --- /dev/null +++ b/src/Symfony/Component/Security/Core/Exception/LogicException.php @@ -0,0 +1,21 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Security\Core\Exception; + +/** + * Base LogicException for the Security component. + * + * @author Iltar van der Berg + */ +class LogicException extends \LogicException implements ExceptionInterface +{ +} diff --git a/src/Symfony/Component/Security/Core/Tests/Authorization/AccessDecisionManagerTest.php b/src/Symfony/Component/Security/Core/Tests/Authorization/AccessDecisionManagerTest.php index 192fe87e2ad93..61d85274fc383 100644 --- a/src/Symfony/Component/Security/Core/Tests/Authorization/AccessDecisionManagerTest.php +++ b/src/Symfony/Component/Security/Core/Tests/Authorization/AccessDecisionManagerTest.php @@ -12,8 +12,11 @@ namespace Symfony\Component\Security\Core\Tests\Authorization; use PHPUnit\Framework\TestCase; +use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; use Symfony\Component\Security\Core\Authorization\AccessDecisionManager; use Symfony\Component\Security\Core\Authorization\Voter\VoterInterface; +use Symfony\Component\Security\Core\Exception\LogicException; +use Symfony\Component\Security\Core\Tests\Authorization\Stub\VoterWithoutInterface; class AccessDecisionManagerTest extends TestCase { @@ -138,4 +141,34 @@ protected function getVoter($vote) return $voter; } + + public function testVotingWrongTypeNoVoteMethod() + { + $exception = LogicException::class; + $message = sprintf('stdClass should implement the %s interface when used as voter.', VoterInterface::class); + + if (method_exists($this, 'expectException')) { + $this->expectException($exception); + $this->expectExceptionMessage($message); + } else { + $this->setExpectedException($exception, $message); + } + + $adm = new AccessDecisionManager(array(new \stdClass())); + $token = $this->getMockBuilder(TokenInterface::class)->getMock(); + + $adm->decide($token, array('TEST')); + } + + /** + * @group legacy + * @expectedDeprecation Calling vote() on an voter without Symfony\Component\Security\Core\Authorization\Voter\VoterInterface is deprecated as of 3.4 and will be removed in 4.0. Implement the Symfony\Component\Security\Core\Authorization\Voter\VoterInterface on your voter. + */ + public function testVotingWrongTypeWithVote() + { + $adm = new AccessDecisionManager(array(new VoterWithoutInterface())); + $token = $this->getMockBuilder(TokenInterface::class)->getMock(); + + $adm->decide($token, array('TEST')); + } } diff --git a/src/Symfony/Component/Security/Core/Tests/Authorization/Stub/VoterWithoutInterface.php b/src/Symfony/Component/Security/Core/Tests/Authorization/Stub/VoterWithoutInterface.php new file mode 100644 index 0000000000000..09c284d3c67fc --- /dev/null +++ b/src/Symfony/Component/Security/Core/Tests/Authorization/Stub/VoterWithoutInterface.php @@ -0,0 +1,22 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Security\Core\Tests\Authorization\Stub; + +/** + * @author Iltar van der Berg + */ +class VoterWithoutInterface +{ + public function vote() + { + } +} From 2940bb0d2cc218f18afd78f1ccab1d4436b14c42 Mon Sep 17 00:00:00 2001 From: Maxime Steinhausser Date: Fri, 16 Jun 2017 11:22:14 +0200 Subject: [PATCH 0230/1099] [FrameworkBundle] Allow .yaml file extension everywhere --- .../DependencyInjection/FrameworkExtension.php | 10 ++++++++-- .../FrameworkBundle/Resources/config/translation.xml | 7 ++++++- .../Component/Translation/Dumper/YamlFileDumper.php | 9 ++++++++- 3 files changed, 22 insertions(+), 4 deletions(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php index 6ad4cb5b9d01c..8537497d6a4b7 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php @@ -1177,7 +1177,10 @@ private function registerValidatorMapping(ContainerBuilder $container, array $co foreach ($container->getParameter('kernel.bundles_metadata') as $bundle) { $dirname = $bundle['path']; - if ($container->fileExists($file = $dirname.'/Resources/config/validation.yml', false)) { + if ( + $container->fileExists($file = $dirname.'/Resources/config/validation.yaml', false) || + $container->fileExists($file = $dirname.'/Resources/config/validation.yml', false) + ) { $fileRecorder('yml', $file); } @@ -1385,7 +1388,10 @@ private function registerSerializerConfiguration(array $config, ContainerBuilder $fileRecorder('xml', $file); } - if ($container->fileExists($file = $dirname.'/Resources/config/serialization.yml', false)) { + if ( + $container->fileExists($file = $dirname.'/Resources/config/serialization.yaml', false) || + $container->fileExists($file = $dirname.'/Resources/config/serialization.yml', false) + ) { $fileRecorder('yml', $file); } diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/translation.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/translation.xml index 4f8999d0cb647..cd0a983010c8a 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/translation.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/translation.xml @@ -33,7 +33,7 @@ - + @@ -92,6 +92,11 @@ + + yaml + + + diff --git a/src/Symfony/Component/Translation/Dumper/YamlFileDumper.php b/src/Symfony/Component/Translation/Dumper/YamlFileDumper.php index fdd113b103654..ecf00fa64ba92 100644 --- a/src/Symfony/Component/Translation/Dumper/YamlFileDumper.php +++ b/src/Symfony/Component/Translation/Dumper/YamlFileDumper.php @@ -23,6 +23,13 @@ */ class YamlFileDumper extends FileDumper { + private $extension; + + public function __construct(/**string */$extension = 'yml') + { + $this->extension = $extension; + } + /** * {@inheritdoc} */ @@ -50,6 +57,6 @@ public function formatCatalogue(MessageCatalogue $messages, $domain, array $opti */ protected function getExtension() { - return 'yml'; + return $this->extension; } } From 9e047122f1651b1bad1eec221bcdd768de28c24f Mon Sep 17 00:00:00 2001 From: Iltar van der Berg Date: Fri, 16 Jun 2017 14:40:34 +0200 Subject: [PATCH 0231/1099] Fixed composer resources between web/cli --- .../Config/Resource/ComposerResource.php | 20 ++----------------- 1 file changed, 2 insertions(+), 18 deletions(-) diff --git a/src/Symfony/Component/Config/Resource/ComposerResource.php b/src/Symfony/Component/Config/Resource/ComposerResource.php index 56224d16c01d8..64288ea1db2d6 100644 --- a/src/Symfony/Component/Config/Resource/ComposerResource.php +++ b/src/Symfony/Component/Config/Resource/ComposerResource.php @@ -18,16 +18,13 @@ */ class ComposerResource implements SelfCheckingResourceInterface, \Serializable { - private $versions; private $vendors; - private static $runtimeVersion; private static $runtimeVendors; public function __construct() { self::refresh(); - $this->versions = self::$runtimeVersion; $this->vendors = self::$runtimeVendors; } @@ -51,36 +48,23 @@ public function isFresh($timestamp) { self::refresh(); - if (self::$runtimeVersion !== $this->versions) { - return false; - } - return self::$runtimeVendors === $this->vendors; } public function serialize() { - return serialize(array($this->versions, $this->vendors)); + return serialize($this->vendors); } public function unserialize($serialized) { - list($this->versions, $this->vendors) = unserialize($serialized); + $this->vendors = unserialize($serialized); } private static function refresh() { - if (null !== self::$runtimeVersion) { - return; - } - - self::$runtimeVersion = array(); self::$runtimeVendors = array(); - foreach (get_loaded_extensions() as $ext) { - self::$runtimeVersion[$ext] = phpversion($ext); - } - foreach (get_declared_classes() as $class) { if ('C' === $class[0] && 0 === strpos($class, 'ComposerAutoloaderInit')) { $r = new \ReflectionClass($class); From aeab2fe1f717f5d45dbfe7744412bdfa232b9a8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A1bor=20Egyed?= Date: Wed, 14 Jun 2017 13:38:13 +0200 Subject: [PATCH 0232/1099] [WebServerBundle] Fix router script path and check existence --- .../Bundle/WebServerBundle/WebServerConfig.php | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Bundle/WebServerBundle/WebServerConfig.php b/src/Symfony/Bundle/WebServerBundle/WebServerConfig.php index 3c639f2034c75..88ed375dd15e8 100644 --- a/src/Symfony/Bundle/WebServerBundle/WebServerConfig.php +++ b/src/Symfony/Bundle/WebServerBundle/WebServerConfig.php @@ -36,7 +36,18 @@ public function __construct($documentRoot, $env, $address = null, $router = null $this->documentRoot = $documentRoot; $this->env = $env; - $this->router = $router ?: __DIR__.'/Resources/router.php'; + + if (null !== $router) { + $absoluteRouterPath = realpath($router); + + if (false === $absoluteRouterPath) { + throw new \InvalidArgumentException(sprintf('Router script "%s" does not exist.', $router)); + } + + $this->router = $absoluteRouterPath; + } else { + $this->router = __DIR__.'/Resources/router.php'; + } if (null === $address) { $this->hostname = '127.0.0.1'; From 50c1d478cee0a0544b68133d3999169dd7d0bbd1 Mon Sep 17 00:00:00 2001 From: Javier Eguiluz Date: Tue, 13 Jun 2017 12:17:26 +0200 Subject: [PATCH 0233/1099] [WebProfilerBundle] Fix the icon for the Cache panel --- .../Resources/views/Icon/cache.svg | 4 +-- .../Resources/views/Icon/forward.svg | 2 +- .../Resources/views/Icon/menu.svg | 2 +- .../Resources/views/Icon/redirect.svg | 2 +- .../Tests/Resources/IconTest.php | 33 +++++++++++++++++++ 5 files changed, 38 insertions(+), 5 deletions(-) create mode 100644 src/Symfony/Bundle/WebProfilerBundle/Tests/Resources/IconTest.php diff --git a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Icon/cache.svg b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Icon/cache.svg index 984a4efd4a475..5b36ae37e0158 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Icon/cache.svg +++ b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Icon/cache.svg @@ -1,3 +1,3 @@ - - + + diff --git a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Icon/forward.svg b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Icon/forward.svg index acb128509a9f5..96a5bd7d22e02 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Icon/forward.svg +++ b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Icon/forward.svg @@ -1,4 +1,4 @@ - + diff --git a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Icon/menu.svg b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Icon/menu.svg index 51870801cf284..3c863393bc1ab 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Icon/menu.svg +++ b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Icon/menu.svg @@ -1,3 +1,3 @@ - + diff --git a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Icon/redirect.svg b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Icon/redirect.svg index 9cb3b89bcfbdd..54ff4187a4c81 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Icon/redirect.svg +++ b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Icon/redirect.svg @@ -1,4 +1,4 @@ - + .*~s', file_get_contents($iconFilePath), sprintf('The SVG metadata of the %s icon is different than expected (use the same as the other icons).', $iconFilePath)); + } + + public function provideIconFilePaths() + { + return array_map( + function ($filePath) { return (array) $filePath; }, + glob(__DIR__.'/../../Resources/views/Icon/*.svg') + ); + } +} From 1d304d2c9ba7689b46e0e82ac56b2a009fc38e85 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Fri, 16 Jun 2017 10:45:26 -0700 Subject: [PATCH 0234/1099] fixed CS --- .../Bundle/WebProfilerBundle/Tests/Resources/IconTest.php | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/Symfony/Bundle/WebProfilerBundle/Tests/Resources/IconTest.php b/src/Symfony/Bundle/WebProfilerBundle/Tests/Resources/IconTest.php index 7ac2564c5856e..040d4003f5c54 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Tests/Resources/IconTest.php +++ b/src/Symfony/Bundle/WebProfilerBundle/Tests/Resources/IconTest.php @@ -25,9 +25,6 @@ public function testIconFileContents($iconFilePath) public function provideIconFilePaths() { - return array_map( - function ($filePath) { return (array) $filePath; }, - glob(__DIR__.'/../../Resources/views/Icon/*.svg') - ); + return array_map(function ($filePath) { return (array) $filePath; }, glob(__DIR__.'/../../Resources/views/Icon/*.svg')); } } From 180f178f43571327f34ff319580e77530eafa1f7 Mon Sep 17 00:00:00 2001 From: Nicolas Pion Date: Thu, 15 Jun 2017 14:05:42 +0200 Subject: [PATCH 0235/1099] [FrameworkBundle] [Command] Clean bundle directory, fixes #23177 --- .../FrameworkBundle/Command/AssetsInstallCommand.php | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/AssetsInstallCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/AssetsInstallCommand.php index 94daa82cc9a26..0a3ea2871deb3 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/AssetsInstallCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/AssetsInstallCommand.php @@ -89,6 +89,7 @@ protected function execute(InputInterface $input, OutputInterface $output) $output->writeln('Installing assets as hard copies.'); } + $validAssetDirs = array(); foreach ($this->getContainer()->get('kernel')->getBundles() as $bundle) { if (is_dir($originDir = $bundle->getPath().'/Resources/public')) { $targetDir = $bundlesDir.preg_replace('/bundle$/', '', strtolower($bundle->getName())); @@ -131,6 +132,13 @@ protected function execute(InputInterface $input, OutputInterface $output) } else { $this->hardCopy($originDir, $targetDir); } + $validAssetDirs[] = $targetDir; + } + } + // remove the assets of the bundles that no longer exist + foreach (new \FilesystemIterator($bundlesDir) as $dir) { + if (!in_array($dir, $validAssetDirs)) { + $filesystem->remove($dir); } } } From 8f6e67d3199453bc8b7fbdbe92e9e02fb4d0bf00 Mon Sep 17 00:00:00 2001 From: RJ Garcia Date: Fri, 9 Jun 2017 14:01:58 -0700 Subject: [PATCH 0236/1099] XML Encoder Optional Type Cast - This provides the ability to forgo the attribute type casting - Updated the CHANGELOG Signed-off-by: RJ Garcia --- src/Symfony/Component/Serializer/CHANGELOG.md | 2 ++ .../Serializer/Encoder/XmlEncoder.php | 33 ++++++++++++++----- .../Tests/Encoder/XmlEncoderTest.php | 22 +++++++++++++ 3 files changed, 48 insertions(+), 9 deletions(-) diff --git a/src/Symfony/Component/Serializer/CHANGELOG.md b/src/Symfony/Component/Serializer/CHANGELOG.md index 01c16d00cf2d9..ef5ed79538072 100644 --- a/src/Symfony/Component/Serializer/CHANGELOG.md +++ b/src/Symfony/Component/Serializer/CHANGELOG.md @@ -39,6 +39,8 @@ CHANGELOG * [DEPRECATION] the `Exception` interface has been renamed to `ExceptionInterface` * added `ObjectNormalizer` leveraging the `PropertyAccess` component to normalize objects containing both properties and getters / setters / issers / hassers methods. + * added `xml_type_cast_attributes` context option for allowing users to opt-out of typecasting + xml attributes. 2.6.0 ----- diff --git a/src/Symfony/Component/Serializer/Encoder/XmlEncoder.php b/src/Symfony/Component/Serializer/Encoder/XmlEncoder.php index f52c609d7e77b..acc08597ddcd5 100644 --- a/src/Symfony/Component/Serializer/Encoder/XmlEncoder.php +++ b/src/Symfony/Component/Serializer/Encoder/XmlEncoder.php @@ -119,10 +119,10 @@ public function decode($data, $format, array $context = array()) unset($data['@xmlns:xml']); if (empty($data)) { - return $this->parseXml($rootNode); + return $this->parseXml($rootNode, $context); } - return array_merge($data, (array) $this->parseXml($rootNode)); + return array_merge($data, (array) $this->parseXml($rootNode, $context)); } if (!$rootNode->hasAttributes()) { @@ -261,11 +261,11 @@ final protected function isElementNameValid($name) * * @return array|string */ - private function parseXml(\DOMNode $node) + private function parseXml(\DOMNode $node, array $context = array()) { - $data = $this->parseXmlAttributes($node); + $data = $this->parseXmlAttributes($node, $context); - $value = $this->parseXmlValue($node); + $value = $this->parseXmlValue($node, $context); if (!count($data)) { return $value; @@ -297,16 +297,17 @@ private function parseXml(\DOMNode $node) * * @return array */ - private function parseXmlAttributes(\DOMNode $node) + private function parseXmlAttributes(\DOMNode $node, array $context = array()) { if (!$node->hasAttributes()) { return array(); } $data = array(); + $typeCastAttributes = $this->resolveXmlTypeCastAttributes($context); foreach ($node->attributes as $attr) { - if (!is_numeric($attr->nodeValue)) { + if (!is_numeric($attr->nodeValue) || !$typeCastAttributes) { $data['@'.$attr->nodeName] = $attr->nodeValue; continue; @@ -331,7 +332,7 @@ private function parseXmlAttributes(\DOMNode $node) * * @return array|string */ - private function parseXmlValue(\DOMNode $node) + private function parseXmlValue(\DOMNode $node, array $context = array()) { if (!$node->hasChildNodes()) { return $node->nodeValue; @@ -348,7 +349,7 @@ private function parseXmlValue(\DOMNode $node) continue; } - $val = $this->parseXml($subnode); + $val = $this->parseXml($subnode, $context); if ('item' === $subnode->nodeName && isset($val['@key'])) { if (isset($val['#'])) { @@ -527,6 +528,20 @@ private function resolveXmlRootName(array $context = array()) : $this->rootNodeName; } + /** + * Get XML option for type casting attributes Defaults to true. + * + * @param array $context + * + * @return bool + */ + private function resolveXmlTypeCastAttributes(array $context = array()) + { + return isset($context['xml_type_cast_attributes']) + ? (bool) $context['xml_type_cast_attributes'] + : true; + } + /** * Create a DOM document, taking serializer options into account. * diff --git a/src/Symfony/Component/Serializer/Tests/Encoder/XmlEncoderTest.php b/src/Symfony/Component/Serializer/Tests/Encoder/XmlEncoderTest.php index b1c810e9550f6..e8178ad0c4c8b 100644 --- a/src/Symfony/Component/Serializer/Tests/Encoder/XmlEncoderTest.php +++ b/src/Symfony/Component/Serializer/Tests/Encoder/XmlEncoderTest.php @@ -284,6 +284,28 @@ public function testDecodeNegativeFloatAttribute() $this->assertSame(array('@index' => -12.11, '#' => 'Name'), $this->encoder->decode($source, 'xml')); } + public function testNoTypeCastAttribute() + { + $source = << + + + +XML; + + $data = $this->encoder->decode($source, 'xml', array('xml_type_cast_attributes' => false)); + $expected = array( + '@a' => '018', + '@b' => '-12.11', + 'node' => array( + '@a' => '018', + '@b' => '-12.11', + '#' => '', + ), + ); + $this->assertSame($expected, $data); + } + public function testEncode() { $source = $this->getXmlSource(); From 90e192e8249d447676ef5bda949e9e63f77b461d Mon Sep 17 00:00:00 2001 From: Dawid Nowak Date: Wed, 17 May 2017 18:18:47 +0200 Subject: [PATCH 0237/1099] Sessions: configurable "use_strict_mode" option for NativeSessionStorage https://github.com/symfony/symfony/pull/22352#issuecomment-302113533 --- .../FrameworkBundle/DependencyInjection/Configuration.php | 1 + .../FrameworkBundle/DependencyInjection/FrameworkExtension.php | 2 +- .../FrameworkBundle/Resources/config/schema/symfony-1.0.xsd | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php index b21b3ee8df769..404bd60ced98d 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php @@ -348,6 +348,7 @@ private function addSessionSection(ArrayNodeDefinition $rootNode) ->scalarNode('gc_divisor')->end() ->scalarNode('gc_probability')->defaultValue(1)->end() ->scalarNode('gc_maxlifetime')->end() + ->booleanNode('use_strict_mode')->end() ->scalarNode('save_path')->defaultValue('%kernel.cache_dir%/sessions')->end() ->integerNode('metadata_update_threshold') ->defaultValue('0') diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php index 3d125d616d393..85a1a9ba208f3 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php @@ -402,7 +402,7 @@ private function registerSessionConfiguration(array $config, ContainerBuilder $c // session storage $container->setAlias('session.storage', $config['storage_id']); $options = array(); - foreach (array('name', 'cookie_lifetime', 'cookie_path', 'cookie_domain', 'cookie_secure', 'cookie_httponly', 'gc_maxlifetime', 'gc_probability', 'gc_divisor') as $key) { + foreach (array('name', 'cookie_lifetime', 'cookie_path', 'cookie_domain', 'cookie_secure', 'cookie_httponly', 'gc_maxlifetime', 'gc_probability', 'gc_divisor', 'use_strict_mode') as $key) { if (isset($config[$key])) { $options[$key] = $config[$key]; } 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 fa7aa2b2bd808..0f0874829bcdb 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 @@ -111,6 +111,7 @@ + From 5d838360f324ccb310060837f9c410b5b78d5072 Mon Sep 17 00:00:00 2001 From: Matthias Pigulla Date: Thu, 23 Mar 2017 10:24:24 +0100 Subject: [PATCH 0238/1099] Shift responsibility for keeping Date header to ResponseHeaderBag --- .../Component/HttpFoundation/Response.php | 19 ---- .../HttpFoundation/ResponseHeaderBag.php | 20 ++++ .../Tests/ResponseHeaderBagTest.php | 91 +++++++++++-------- 3 files changed, 72 insertions(+), 58 deletions(-) diff --git a/src/Symfony/Component/HttpFoundation/Response.php b/src/Symfony/Component/HttpFoundation/Response.php index 4af1e0bae2ecf..3ea4cb6170452 100644 --- a/src/Symfony/Component/HttpFoundation/Response.php +++ b/src/Symfony/Component/HttpFoundation/Response.php @@ -201,11 +201,6 @@ public function __construct($content = '', $status = 200, $headers = array()) $this->setContent($content); $this->setStatusCode($status); $this->setProtocolVersion('1.0'); - - /* RFC2616 - 14.18 says all Responses need to have a Date */ - if (!$this->headers->has('Date')) { - $this->setDate(\DateTime::createFromFormat('U', time())); - } } /** @@ -334,11 +329,6 @@ public function sendHeaders() return $this; } - /* RFC2616 - 14.18 says all Responses need to have a Date */ - if (!$this->headers->has('Date')) { - $this->setDate(\DateTime::createFromFormat('U', time())); - } - // headers foreach ($this->headers->allPreserveCaseWithoutCookies() as $name => $values) { foreach ($values as $value) { @@ -648,15 +638,6 @@ public function mustRevalidate() */ public function getDate() { - /* - RFC2616 - 14.18 says all Responses need to have a Date. - Make sure we provide one even if it the header - has been removed in the meantime. - */ - if (!$this->headers->has('Date')) { - $this->setDate(\DateTime::createFromFormat('U', time())); - } - return $this->headers->getDate('Date'); } diff --git a/src/Symfony/Component/HttpFoundation/ResponseHeaderBag.php b/src/Symfony/Component/HttpFoundation/ResponseHeaderBag.php index df2931be05a2e..236528de21fe8 100644 --- a/src/Symfony/Component/HttpFoundation/ResponseHeaderBag.php +++ b/src/Symfony/Component/HttpFoundation/ResponseHeaderBag.php @@ -51,6 +51,11 @@ public function __construct(array $headers = array()) if (!isset($this->headers['cache-control'])) { $this->set('Cache-Control', ''); } + + /* RFC2616 - 14.18 says all Responses need to have a Date */ + if (!isset($this->headers['date'])) { + $this->initDate(); + } } /** @@ -90,6 +95,10 @@ public function replace(array $headers = array()) if (!isset($this->headers['cache-control'])) { $this->set('Cache-Control', ''); } + + if (!isset($this->headers['date'])) { + $this->initDate(); + } } /** @@ -156,6 +165,10 @@ public function remove($key) if ('cache-control' === $uniqueKey) { $this->computedCacheControl = array(); } + + if ('date' === $uniqueKey) { + $this->initDate(); + } } /** @@ -338,4 +351,11 @@ protected function computeCacheControlValue() return $header; } + + private function initDate() + { + $now = \DateTime::createFromFormat('U', time()); + $now->setTimezone(new \DateTimeZone('UTC')); + $this->set('Date', $now->format('D, d M Y H:i:s').' GMT'); + } } diff --git a/src/Symfony/Component/HttpFoundation/Tests/ResponseHeaderBagTest.php b/src/Symfony/Component/HttpFoundation/Tests/ResponseHeaderBagTest.php index 724328ae850e4..1d7341f335a93 100644 --- a/src/Symfony/Component/HttpFoundation/Tests/ResponseHeaderBagTest.php +++ b/src/Symfony/Component/HttpFoundation/Tests/ResponseHeaderBagTest.php @@ -20,48 +20,24 @@ */ class ResponseHeaderBagTest extends TestCase { - /** - * @dataProvider provideAllPreserveCase - */ - public function testAllPreserveCase($headers, $expected) + public function testAllPreserveCase() { + $headers = array( + 'fOo' => 'BAR', + 'ETag' => 'xyzzy', + 'Content-MD5' => 'Q2hlY2sgSW50ZWdyaXR5IQ==', + 'P3P' => 'CP="CAO PSA OUR"', + 'WWW-Authenticate' => 'Basic realm="WallyWorld"', + 'X-UA-Compatible' => 'IE=edge,chrome=1', + 'X-XSS-Protection' => '1; mode=block', + ); + $bag = new ResponseHeaderBag($headers); + $allPreservedCase = $bag->allPreserveCase(); - $this->assertEquals($expected, $bag->allPreserveCase(), '->allPreserveCase() gets all input keys in original case'); - } - - public function provideAllPreserveCase() - { - return array( - array( - array('fOo' => 'BAR'), - array('fOo' => array('BAR'), 'Cache-Control' => array('no-cache, private')), - ), - array( - array('ETag' => 'xyzzy'), - array('ETag' => array('xyzzy'), 'Cache-Control' => array('private, must-revalidate')), - ), - array( - array('Content-MD5' => 'Q2hlY2sgSW50ZWdyaXR5IQ=='), - array('Content-MD5' => array('Q2hlY2sgSW50ZWdyaXR5IQ=='), 'Cache-Control' => array('no-cache, private')), - ), - array( - array('P3P' => 'CP="CAO PSA OUR"'), - array('P3P' => array('CP="CAO PSA OUR"'), 'Cache-Control' => array('no-cache, private')), - ), - array( - array('WWW-Authenticate' => 'Basic realm="WallyWorld"'), - array('WWW-Authenticate' => array('Basic realm="WallyWorld"'), 'Cache-Control' => array('no-cache, private')), - ), - array( - array('X-UA-Compatible' => 'IE=edge,chrome=1'), - array('X-UA-Compatible' => array('IE=edge,chrome=1'), 'Cache-Control' => array('no-cache, private')), - ), - array( - array('X-XSS-Protection' => '1; mode=block'), - array('X-XSS-Protection' => array('1; mode=block'), 'Cache-Control' => array('no-cache, private')), - ), - ); + foreach (array_keys($headers) as $headerName) { + $this->assertArrayHasKey($headerName, $allPreservedCase, '->allPreserveCase() gets all input keys in original case'); + } } public function testCacheControlHeader() @@ -332,6 +308,43 @@ public function provideMakeDispositionFail() ); } + public function testDateHeaderAddedOnCreation() + { + $now = time(); + + $bag = new ResponseHeaderBag(); + $this->assertTrue($bag->has('Date')); + + $this->assertEquals($now, $bag->getDate('Date')->getTimestamp()); + } + + public function testDateHeaderCanBeSetOnCreation() + { + $someDate = 'Thu, 23 Mar 2017 09:15:12 GMT'; + $bag = new ResponseHeaderBag(array('Date' => $someDate)); + + $this->assertEquals($someDate, $bag->get('Date')); + } + + public function testDateHeaderWillBeRecreatedWhenRemoved() + { + $someDate = 'Thu, 23 Mar 2017 09:15:12 GMT'; + $bag = new ResponseHeaderBag(array('Date' => $someDate)); + $bag->remove('Date'); + + // a (new) Date header is still present + $this->assertTrue($bag->has('Date')); + $this->assertNotEquals($someDate, $bag->get('Date')); + } + + public function testDateHeaderWillBeRecreatedWhenHeadersAreReplaced() + { + $bag = new ResponseHeaderBag(); + $bag->replace(array()); + + $this->assertTrue($bag->has('Date')); + } + private function assertSetCookieHeader($expected, ResponseHeaderBag $actual) { $this->assertRegExp('#^Set-Cookie:\s+'.preg_quote($expected, '#').'$#m', str_replace("\r\n", "\n", (string) $actual)); From 33573c6eb17bead47b42e53c8d0c863231c5857c Mon Sep 17 00:00:00 2001 From: Jaroslav Kuba Date: Sun, 28 May 2017 21:03:49 +0200 Subject: [PATCH 0239/1099] Added support for the immutable directive in the cache-control header --- .../Component/HttpFoundation/Response.php | 34 ++++++++++++++++++- .../HttpFoundation/Tests/ResponseTest.php | 22 ++++++++++++ 2 files changed, 55 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/HttpFoundation/Response.php b/src/Symfony/Component/HttpFoundation/Response.php index 3ea4cb6170452..8b237d7587af5 100644 --- a/src/Symfony/Component/HttpFoundation/Response.php +++ b/src/Symfony/Component/HttpFoundation/Response.php @@ -610,6 +610,34 @@ public function setPublic() return $this; } + /** + * Marks the response as "immutable". + * + * @param bool $immutable Enables or disables the immutable directive. + * + * @return $this + */ + public function setImmutable($immutable = true) + { + if ($immutable) { + $this->headers->addCacheControlDirective('immutable'); + } else { + $this->headers->removeCacheControlDirective('immutable'); + } + + return $this; + } + + /** + * Returns true if the response is marked as "immutable". + * + * @return bool Returns true if the response is marked as "immutable"; otherwise false. + */ + public function isImmutable() + { + return $this->headers->hasCacheControlDirective('immutable'); + } + /** * Returns true if the response must be revalidated by caches. * @@ -937,7 +965,7 @@ public function setEtag($etag = null, $weak = false) */ public function setCache(array $options) { - if ($diff = array_diff(array_keys($options), array('etag', 'last_modified', 'max_age', 's_maxage', 'private', 'public'))) { + if ($diff = array_diff(array_keys($options), array('etag', 'last_modified', 'max_age', 's_maxage', 'private', 'public', 'immutable'))) { throw new \InvalidArgumentException(sprintf('Response does not support the following options: "%s".', implode('", "', array_values($diff)))); } @@ -973,6 +1001,10 @@ public function setCache(array $options) } } + if (isset($options['immutable'])) { + $this->setImmutable((bool) $options['immutable']); + } + return $this; } diff --git a/src/Symfony/Component/HttpFoundation/Tests/ResponseTest.php b/src/Symfony/Component/HttpFoundation/Tests/ResponseTest.php index 62b8c652597ea..9c5b34febfa30 100644 --- a/src/Symfony/Component/HttpFoundation/Tests/ResponseTest.php +++ b/src/Symfony/Component/HttpFoundation/Tests/ResponseTest.php @@ -610,6 +610,12 @@ public function testSetCache() $response->setCache(array('private' => false)); $this->assertTrue($response->headers->hasCacheControlDirective('public')); $this->assertFalse($response->headers->hasCacheControlDirective('private')); + + $response->setCache(array('immutable' => true)); + $this->assertTrue($response->headers->hasCacheControlDirective('immutable')); + + $response->setCache(array('immutable' => false)); + $this->assertFalse($response->headers->hasCacheControlDirective('immutable')); } public function testSendContent() @@ -631,6 +637,22 @@ public function testSetPublic() $this->assertFalse($response->headers->hasCacheControlDirective('private')); } + public function testSetImmutable() + { + $response = new Response(); + $response->setImmutable(); + + $this->assertTrue($response->headers->hasCacheControlDirective('immutable')); + } + + public function testIsImmutable() + { + $response = new Response(); + $response->setImmutable(); + + $this->assertTrue($response->isImmutable()); + } + public function testSetExpires() { $response = new Response(); From 74db2e61bc1764840a1ced7366ffaf2dd6264f84 Mon Sep 17 00:00:00 2001 From: Maxime Steinhausser Date: Sat, 17 Jun 2017 20:11:33 +0200 Subject: [PATCH 0240/1099] [Serializer] Fix workaround min php version --- .../Component/Serializer/Normalizer/DateTimeNormalizer.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/Serializer/Normalizer/DateTimeNormalizer.php b/src/Symfony/Component/Serializer/Normalizer/DateTimeNormalizer.php index 960782bc465b4..35b0b5f0e5cd6 100644 --- a/src/Symfony/Component/Serializer/Normalizer/DateTimeNormalizer.php +++ b/src/Symfony/Component/Serializer/Normalizer/DateTimeNormalizer.php @@ -81,7 +81,7 @@ public function denormalize($data, $class, $format = null, array $context = arra $timezone = $this->getTimezone($context); if (null !== $dateTimeFormat) { - if (null === $timezone && PHP_VERSION_ID < 50600) { + if (null === $timezone && PHP_VERSION_ID < 70000) { // https://bugs.php.net/bug.php?id=68669 $object = \DateTime::class === $class ? \DateTime::createFromFormat($dateTimeFormat, $data) : \DateTimeImmutable::createFromFormat($dateTimeFormat, $data); } else { From e76ee7a542a72f2593980a7dbf61efe8ddd436af Mon Sep 17 00:00:00 2001 From: Maxime Steinhausser Date: Sat, 17 Jun 2017 21:00:18 +0200 Subject: [PATCH 0241/1099] [Translation] Fix FileLoader::loadResource() php doc --- src/Symfony/Component/Translation/Loader/FileLoader.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/Translation/Loader/FileLoader.php b/src/Symfony/Component/Translation/Loader/FileLoader.php index a7f24f41a6535..1885963a99550 100644 --- a/src/Symfony/Component/Translation/Loader/FileLoader.php +++ b/src/Symfony/Component/Translation/Loader/FileLoader.php @@ -54,7 +54,7 @@ public function load($resource, $locale, $domain = 'messages') return $catalogue; } - /* + /** * @param string $resource * * @return array From 9f877efb3918f919f593d90ec56c70b498295eed Mon Sep 17 00:00:00 2001 From: Maxime Steinhausser Date: Sat, 17 Jun 2017 20:39:10 +0200 Subject: [PATCH 0242/1099] [DI] Dedup tags when using instanceof/autoconfigure --- .../ResolveInstanceofConditionalsPass.php | 3 +++ .../ResolveInstanceofConditionalsPassTest.php | 23 +++++++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/src/Symfony/Component/DependencyInjection/Compiler/ResolveInstanceofConditionalsPass.php b/src/Symfony/Component/DependencyInjection/Compiler/ResolveInstanceofConditionalsPass.php index a2e62f4e536a5..82f13ed2d0e17 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/ResolveInstanceofConditionalsPass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/ResolveInstanceofConditionalsPass.php @@ -107,6 +107,9 @@ private function processDefinition(ContainerBuilder $container, $id, Definition while (0 <= --$i) { foreach ($instanceofTags[$i] as $k => $v) { foreach ($v as $v) { + if ($definition->hasTag($k) && in_array($v, $definition->getTag($k))) { + continue; + } $definition->addTag($k, $v); } } diff --git a/src/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveInstanceofConditionalsPassTest.php b/src/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveInstanceofConditionalsPassTest.php index c6c3681025606..164ab25941d64 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveInstanceofConditionalsPassTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveInstanceofConditionalsPassTest.php @@ -130,6 +130,29 @@ public function testProcessUsesAutoconfiguredInstanceof() $this->assertSame(array('local_instanceof_tag' => array(array()), 'autoconfigured_tag' => array(array())), $def->getTags()); } + public function testAutoconfigureInstanceofDoesNotDuplicateTags() + { + $container = new ContainerBuilder(); + $def = $container->register('normal_service', self::class); + $def + ->addTag('duplicated_tag') + ->addTag('duplicated_tag', array('and_attributes' => 1)) + ; + $def->setInstanceofConditionals(array( + parent::class => (new ChildDefinition(''))->addTag('duplicated_tag'), + )); + $def->setAutoconfigured(true); + $container->registerForAutoconfiguration(parent::class) + ->addTag('duplicated_tag', array('and_attributes' => 1)) + ; + + (new ResolveInstanceofConditionalsPass())->process($container); + (new ResolveDefinitionTemplatesPass())->process($container); + + $def = $container->getDefinition('normal_service'); + $this->assertSame(array('duplicated_tag' => array(array(), array('and_attributes' => 1))), $def->getTags()); + } + public function testProcessDoesNotUseAutoconfiguredInstanceofIfNotEnabled() { $container = new ContainerBuilder(); From 93e6e95dae200ddced4ab3f6ab07b70185ee3036 Mon Sep 17 00:00:00 2001 From: Jacob Dreesen Date: Sun, 18 Jun 2017 13:44:42 +0200 Subject: [PATCH 0243/1099] Remove duplicate changelog entries --- src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md b/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md index 228500fbabfb2..c089a8b40a743 100644 --- a/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md +++ b/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md @@ -6,8 +6,6 @@ CHANGELOG * Removed `doctrine/cache` from the list of required dependencies in `composer.json` * Deprecated `validator.mapping.cache.doctrine.apc` service - * Deprecated using the `KERNEL_DIR` environment variable with `KernelTestCase::getKernelClass()`. - * Deprecated the `KernelTestCase::getPhpUnitXmlDir()` and `KernelTestCase::getPhpUnitCliConfigArgument()` methods. * The `symfony/stopwatch` dependency has been removed, require it via `composer require symfony/stopwatch` in your `dev` environment. * Deprecated using the `KERNEL_DIR` environment variable with `KernelTestCase::getKernelClass()`. From f6a94cb56fc544f66e39e0658143976c852a14bb Mon Sep 17 00:00:00 2001 From: Oleg Voronkovich Date: Sun, 18 Jun 2017 21:08:05 +0300 Subject: [PATCH 0244/1099] [Routing] Fix XmlFileLoader exception message --- src/Symfony/Component/Routing/Loader/XmlFileLoader.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/Routing/Loader/XmlFileLoader.php b/src/Symfony/Component/Routing/Loader/XmlFileLoader.php index b5c24f9871c2f..9e219ad37ecca 100644 --- a/src/Symfony/Component/Routing/Loader/XmlFileLoader.php +++ b/src/Symfony/Component/Routing/Loader/XmlFileLoader.php @@ -250,7 +250,7 @@ private function parseConfigs(\DOMElement $node, $path) $condition = trim($n->textContent); break; default: - throw new \InvalidArgumentException(sprintf('Unknown tag "%s" used in file "%s". Expected "default", "requirement" or "option".', $n->localName, $path)); + throw new \InvalidArgumentException(sprintf('Unknown tag "%s" used in file "%s". Expected "default", "requirement", "option" or "condition".', $n->localName, $path)); } } From 44ff4b1a49ef1c450c10a3597309546bf8e06386 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Mon, 19 Jun 2017 16:33:26 +0200 Subject: [PATCH 0245/1099] [Validator] replace hardcoded service id --- .../DependencyInjection/AddConstraintValidatorsPass.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/Validator/DependencyInjection/AddConstraintValidatorsPass.php b/src/Symfony/Component/Validator/DependencyInjection/AddConstraintValidatorsPass.php index ec68bc0a8c828..207a1ad49d487 100644 --- a/src/Symfony/Component/Validator/DependencyInjection/AddConstraintValidatorsPass.php +++ b/src/Symfony/Component/Validator/DependencyInjection/AddConstraintValidatorsPass.php @@ -49,7 +49,7 @@ public function process(ContainerBuilder $container) } $container - ->getDefinition('validator.validator_factory') + ->getDefinition($this->validatorFactoryServiceId) ->replaceArgument(0, ServiceLocatorTagPass::register($container, $validators)) ; } From ac5e884f36636620a176e97b2053e42a8d6e16cc Mon Sep 17 00:00:00 2001 From: Maxime Steinhausser Date: Thu, 27 Apr 2017 17:08:18 +0200 Subject: [PATCH 0246/1099] [Profiler][Validator] Add a validator panel in profiler --- .../FrameworkExtension.php | 7 +- .../Resources/config/validator_debug.xml | 20 +++ .../Bundle/FrameworkBundle/composer.json | 4 +- .../views/Collector/validator.html.twig | 98 +++++++++++++ .../Resources/views/Icon/validator.svg | 1 + .../views/Profiler/profiler.css.twig | 25 ++++ .../DataCollector/ValidatorDataCollector.php | 105 ++++++++++++++ .../ValidatorDataCollectorTest.php | 57 ++++++++ .../Validator/TraceableValidatorTest.php | 104 ++++++++++++++ .../Validator/TraceableValidator.php | 131 ++++++++++++++++++ src/Symfony/Component/Validator/composer.json | 2 + 11 files changed, 551 insertions(+), 3 deletions(-) create mode 100644 src/Symfony/Bundle/FrameworkBundle/Resources/config/validator_debug.xml create mode 100644 src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/validator.html.twig create mode 100644 src/Symfony/Bundle/WebProfilerBundle/Resources/views/Icon/validator.svg create mode 100644 src/Symfony/Component/Validator/DataCollector/ValidatorDataCollector.php create mode 100644 src/Symfony/Component/Validator/Tests/DataCollector/ValidatorDataCollectorTest.php create mode 100644 src/Symfony/Component/Validator/Tests/Validator/TraceableValidatorTest.php create mode 100644 src/Symfony/Component/Validator/Validator/TraceableValidator.php diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php index 8537497d6a4b7..1769258215475 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php @@ -81,6 +81,7 @@ class FrameworkExtension extends Extension private $translationConfigEnabled = false; private $sessionConfigEnabled = false; private $annotationsConfigEnabled = false; + private $validatorConfigEnabled = false; /** * @var string|null @@ -456,6 +457,10 @@ private function registerProfilerConfiguration(array $config, ContainerBuilder $ $loader->load('form_debug.xml'); } + if ($this->validatorConfigEnabled) { + $loader->load('validator_debug.xml'); + } + if ($this->translationConfigEnabled) { $loader->load('translation_debug.xml'); $container->getDefinition('translator.data_collector')->setDecoratedService('translator'); @@ -1107,7 +1112,7 @@ private function registerTranslatorConfiguration(array $config, ContainerBuilder */ private function registerValidationConfiguration(array $config, ContainerBuilder $container, XmlFileLoader $loader) { - if (!$this->isConfigEnabled($container, $config)) { + if (!$this->validatorConfigEnabled = $this->isConfigEnabled($container, $config)) { return; } diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/validator_debug.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/validator_debug.xml new file mode 100644 index 0000000000000..ac4724580a53e --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/validator_debug.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + diff --git a/src/Symfony/Bundle/FrameworkBundle/composer.json b/src/Symfony/Bundle/FrameworkBundle/composer.json index d46d5e128bea4..9699ae85d6d6f 100644 --- a/src/Symfony/Bundle/FrameworkBundle/composer.json +++ b/src/Symfony/Bundle/FrameworkBundle/composer.json @@ -49,7 +49,7 @@ "symfony/stopwatch": "~2.8|~3.0|~4.0", "symfony/translation": "~3.2|~4.0", "symfony/templating": "~2.8|~3.0|~4.0", - "symfony/validator": "~3.3|~4.0", + "symfony/validator": "~3.4|~4.0", "symfony/var-dumper": "~3.3|~4.0", "symfony/workflow": "~3.3|~4.0", "symfony/yaml": "~3.2|~4.0", @@ -69,7 +69,7 @@ "symfony/property-info": "<3.3", "symfony/serializer": "<3.3", "symfony/translation": "<3.2", - "symfony/validator": "<3.3", + "symfony/validator": "<3.4", "symfony/workflow": "<3.3" }, "suggest": { diff --git a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/validator.html.twig b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/validator.html.twig new file mode 100644 index 0000000000000..6b8ba44dac940 --- /dev/null +++ b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/validator.html.twig @@ -0,0 +1,98 @@ +{% extends '@WebProfiler/Profiler/layout.html.twig' %} + +{% block toolbar %} + {% if collector.violationsCount > 0 or collector.calls|length %} + {% set status_color = collector.violationsCount ? 'red' : '' %} + {% set icon %} + {{ include('@WebProfiler/Icon/validator.svg') }} + + {{ collector.violationsCount }} + + {% endset %} + + {% set text %} +
+ Validator calls + {{ collector.calls|length }} +
+
+ Number of violations + {{ collector.violationsCount }} +
+ {% endset %} + + {{ include('@WebProfiler/Profiler/toolbar_item.html.twig', { link: profiler_url, status: status_color }) }} + {% endif %} +{% endblock %} + +{% block menu %} + + {{ include('@WebProfiler/Icon/validator.svg') }} + Validator + {% if collector.violationsCount > 0 %} + + {{ collector.violationsCount }} + + {% endif %} + +{% endblock %} + +{% block panel %} +

Validator calls

+ + {% for call in collector.calls %} +
+ + + + + + + {% if call.violations|length %} + + + + + + + + + + {% for violation in call.violations %} + + + + + + + {% endfor %} +
PathMessageInvalid valueViolation
{{ violation.propertyPath }}{{ violation.message }}{{ profiler_dump(violation.seek('invalidValue')) }}{{ profiler_dump(violation) }}
+ {% else %} + No violations + {% endif %} +
+ {% else %} +
+

No calls to the validator were collected during this request.

+
+ {% endfor %} +{% endblock %} diff --git a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Icon/validator.svg b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Icon/validator.svg new file mode 100644 index 0000000000000..b501fe5486807 --- /dev/null +++ b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Icon/validator.svg @@ -0,0 +1 @@ + diff --git a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/profiler.css.twig b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/profiler.css.twig index 5b6647df8866a..94ac2abd2548e 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/profiler.css.twig +++ b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/profiler.css.twig @@ -880,6 +880,31 @@ table.logs .metadata { white-space: pre-wrap; } +{# Validator panel + ========================================================================= #} + +#collector-content .sf-validator { + margin-bottom: 2em; +} + +#collector-content .sf-validator .sf-validator-context, +#collector-content .sf-validator .trace { + border: 1px solid #DDD; + background: #FFF; + padding: 10px; + margin: 0.5em 0; +} +#collector-content .sf-validator .trace { + font-size: 12px; +} +#collector-content .sf-validator .trace li { + margin-bottom: 0; + padding: 0; +} +#collector-content .sf-validator .trace li.selected { + background: rgba(255, 255, 153, 0.5); +} + {# Dump panel ========================================================================= #} #collector-content .sf-dump { diff --git a/src/Symfony/Component/Validator/DataCollector/ValidatorDataCollector.php b/src/Symfony/Component/Validator/DataCollector/ValidatorDataCollector.php new file mode 100644 index 0000000000000..02c672191e968 --- /dev/null +++ b/src/Symfony/Component/Validator/DataCollector/ValidatorDataCollector.php @@ -0,0 +1,105 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Validator\DataCollector; + +use Symfony\Component\Form\FormInterface; +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\HttpKernel\DataCollector\DataCollector; +use Symfony\Component\HttpKernel\DataCollector\LateDataCollectorInterface; +use Symfony\Component\Validator\Validator\TraceableValidator; +use Symfony\Component\VarDumper\Caster\Caster; +use Symfony\Component\VarDumper\Caster\ClassStub; +use Symfony\Component\VarDumper\Cloner\Data; +use Symfony\Component\VarDumper\Cloner\VarCloner; + +/** + * @author Maxime Steinhausser + */ +class ValidatorDataCollector extends DataCollector implements LateDataCollectorInterface +{ + private $validator; + private $cloner; + + public function __construct(TraceableValidator $validator) + { + $this->validator = $validator; + $this->data = array( + 'calls' => array(), + 'violations_count' => 0, + ); + } + + /** + * {@inheritdoc} + */ + public function collect(Request $request, Response $response, \Exception $exception = null) + { + // Everything is collected once, on kernel terminate. + } + + /** + * {@inheritdoc} + */ + public function lateCollect() + { + $collected = $this->validator->getCollectedData(); + $this->data['calls'] = $this->cloneVar($collected); + $this->data['violations_count'] += array_reduce($collected, function ($previous, $item) { + return $previous += count($item['violations']); + }, 0); + } + + public function getCalls() + { + return $this->data['calls']; + } + + public function getViolationsCount() + { + return $this->data['violations_count']; + } + + /** + * {@inheritdoc} + */ + public function getName() + { + return 'validator'; + } + + /** + * {@inheritdoc} + */ + protected function cloneVar($var) + { + if ($var instanceof Data) { + return $var; + } + + if (null === $this->cloner) { + $this->cloner = new VarCloner(); + $this->cloner->setMaxItems(-1); + $this->cloner->addCasters(array( + FormInterface::class => function (FormInterface $f, array $a) { + return array( + Caster::PREFIX_VIRTUAL.'name' => $f->getName(), + Caster::PREFIX_VIRTUAL.'type_class' => new ClassStub(get_class($f->getConfig()->getType()->getInnerType())), + Caster::PREFIX_VIRTUAL.'data' => $f->getData(), + ); + }, + )); + } + + return $this->cloner->cloneVar($var, Caster::EXCLUDE_VERBOSE); + } +} diff --git a/src/Symfony/Component/Validator/Tests/DataCollector/ValidatorDataCollectorTest.php b/src/Symfony/Component/Validator/Tests/DataCollector/ValidatorDataCollectorTest.php new file mode 100644 index 0000000000000..811a55829a479 --- /dev/null +++ b/src/Symfony/Component/Validator/Tests/DataCollector/ValidatorDataCollectorTest.php @@ -0,0 +1,57 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Validator\Tests\DataCollector; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\Validator\ConstraintViolation; +use Symfony\Component\Validator\ConstraintViolationList; +use Symfony\Component\Validator\DataCollector\ValidatorDataCollector; +use Symfony\Component\Validator\Validator\TraceableValidator; +use Symfony\Component\Validator\Validator\ValidatorInterface; + +class ValidatorDataCollectorTest extends TestCase +{ + public function testCollectsValidatorCalls() + { + $originalValidator = $this->createMock(ValidatorInterface::class); + $validator = new TraceableValidator($originalValidator); + + $collector = new ValidatorDataCollector($validator); + + $violations = new ConstraintViolationList(array( + $this->createMock(ConstraintViolation::class), + $this->createMock(ConstraintViolation::class), + )); + $originalValidator->method('validate')->willReturn($violations); + + $validator->validate(new \stdClass()); + + $collector->lateCollect(); + + $calls = $collector->getCalls(); + + $this->assertCount(1, $calls); + $this->assertSame(2, $collector->getViolationsCount()); + + $call = $calls[0]; + + $this->assertArrayHasKey('caller', $call); + $this->assertArrayHasKey('context', $call); + $this->assertArrayHasKey('violations', $call); + $this->assertCount(2, $call['violations']); + } + + protected function createMock($classname) + { + return $this->getMockBuilder($classname)->disableOriginalConstructor()->getMock(); + } +} diff --git a/src/Symfony/Component/Validator/Tests/Validator/TraceableValidatorTest.php b/src/Symfony/Component/Validator/Tests/Validator/TraceableValidatorTest.php new file mode 100644 index 0000000000000..b2eef769ecf3c --- /dev/null +++ b/src/Symfony/Component/Validator/Tests/Validator/TraceableValidatorTest.php @@ -0,0 +1,104 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Validator\Tests\Validator; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\Validator\Constraint; +use Symfony\Component\Validator\ConstraintViolation; +use Symfony\Component\Validator\ConstraintViolationList; +use Symfony\Component\Validator\ConstraintViolationListInterface; +use Symfony\Component\Validator\Context\ExecutionContextInterface; +use Symfony\Component\Validator\Mapping\MetadataInterface; +use Symfony\Component\Validator\Validator\ContextualValidatorInterface; +use Symfony\Component\Validator\Validator\TraceableValidator; +use Symfony\Component\Validator\Validator\ValidatorInterface; + +class TraceableValidatorTest extends TestCase +{ + public function testValidate() + { + $originalValidator = $this->createMock(ValidatorInterface::class); + $violations = new ConstraintViolationList(array( + $this->createMock(ConstraintViolation::class), + $this->createMock(ConstraintViolation::class), + )); + $originalValidator->expects($this->exactly(2))->method('validate')->willReturn($violations); + + $validator = new TraceableValidator($originalValidator); + + $object = new \stdClass(); + $constraints = array($this->createMock(Constraint::class)); + $groups = array('Default', 'Create'); + + $validator->validate($object, $constraints, $groups); + $line = __LINE__ - 1; + + $collectedData = $validator->getCollectedData(); + + $this->assertCount(1, $collectedData); + + $callData = $collectedData[0]; + + $this->assertSame(iterator_to_array($violations), $callData['violations']); + + $this->assertSame(array( + 'value' => $object, + 'constraints' => $constraints, + 'groups' => $groups, + ), $callData['context']); + + $this->assertEquals(array( + 'name' => 'TraceableValidatorTest.php', + 'file' => __FILE__, + 'line' => $line, + ), $callData['caller']); + + $validator->validate($object, $constraints, $groups); + $collectedData = $validator->getCollectedData(); + + $this->assertCount(2, $collectedData); + } + + public function testForwardsToOriginalValidator() + { + $originalValidator = $this->createMock(ValidatorInterface::class); + $validator = new TraceableValidator($originalValidator); + + $expects = function ($method) use ($originalValidator) { return $originalValidator->expects($this->once())->method($method); }; + + $expects('getMetadataFor')->willReturn($expected = $this->createMock(MetadataInterface::class)); + $this->assertSame($expected, $validator->getMetadataFor('value'), 'returns original validator getMetadataFor() result'); + + $expects('hasMetadataFor')->willReturn($expected = false); + $this->assertSame($expected, $validator->hasMetadataFor('value'), 'returns original validator hasMetadataFor() result'); + + $expects('inContext')->willReturn($expected = $this->createMock(ContextualValidatorInterface::class)); + $this->assertSame($expected, $validator->inContext($this->createMock(ExecutionContextInterface::class)), 'returns original validator inContext() result'); + + $expects('startContext')->willReturn($expected = $this->createMock(ContextualValidatorInterface::class)); + $this->assertSame($expected, $validator->startContext(), 'returns original validator startContext() result'); + + $expects('validate')->willReturn($expected = $this->createMock(ConstraintViolationListInterface::class)); + $this->assertSame($expected, $validator->validate('value'), 'returns original validator validate() result'); + + $expects('validateProperty')->willReturn($expected = $this->createMock(ConstraintViolationListInterface::class)); + $this->assertSame($expected, $validator->validateProperty(new \stdClass(), 'property'), 'returns original validator validateProperty() result'); + + $expects('validatePropertyValue')->willReturn($expected = $this->createMock(ConstraintViolationListInterface::class)); + $this->assertSame($expected, $validator->validatePropertyValue(new \stdClass(), 'property', 'value'), 'returns original validator validatePropertyValue() result'); + } + + protected function createMock($classname) + { + return $this->getMockBuilder($classname)->disableOriginalConstructor()->getMock(); + } +} diff --git a/src/Symfony/Component/Validator/Validator/TraceableValidator.php b/src/Symfony/Component/Validator/Validator/TraceableValidator.php new file mode 100644 index 0000000000000..019559ae0023d --- /dev/null +++ b/src/Symfony/Component/Validator/Validator/TraceableValidator.php @@ -0,0 +1,131 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Validator\Validator; + +use Symfony\Component\Validator\ConstraintViolationList; +use Symfony\Component\Validator\Context\ExecutionContextInterface; + +/** + * Collects some data about validator calls. + * + * @author Maxime Steinhausser + */ +class TraceableValidator implements ValidatorInterface +{ + private $validator; + private $collectedData = array(); + + public function __construct(ValidatorInterface $validator) + { + $this->validator = $validator; + } + + /** + * @return ConstraintViolationList[] + */ + public function getCollectedData() + { + return $this->collectedData; + } + + /** + * {@inheritdoc} + */ + public function getMetadataFor($value) + { + return $this->validator->getMetadataFor($value); + } + + /** + * {@inheritdoc} + */ + public function hasMetadataFor($value) + { + return $this->validator->hasMetadataFor($value); + } + + /** + * {@inheritdoc} + */ + public function validate($value, $constraints = null, $groups = null) + { + $violations = $this->validator->validate($value, $constraints, $groups); + + $trace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 7); + + $file = $trace[0]['file']; + $line = $trace[0]['line']; + + for ($i = 1; $i < 7; ++$i) { + if (isset($trace[$i]['class'], $trace[$i]['function']) + && 'validate' === $trace[$i]['function'] + && is_a($trace[$i]['class'], ValidatorInterface::class, true) + ) { + $file = $trace[$i]['file']; + $line = $trace[$i]['line']; + + while (++$i < 7) { + if (isset($trace[$i]['function'], $trace[$i]['file']) && empty($trace[$i]['class']) && 0 !== strpos($trace[$i]['function'], 'call_user_func')) { + $file = $trace[$i]['file']; + $line = $trace[$i]['line']; + + break; + } + } + break; + } + } + + $name = str_replace('\\', '/', $file); + $name = substr($name, strrpos($name, '/') + 1); + + $this->collectedData[] = array( + 'caller' => compact('name', 'file', 'line'), + 'context' => compact('value', 'constraints', 'groups'), + 'violations' => iterator_to_array($violations), + ); + + return $violations; + } + + /** + * {@inheritdoc} + */ + public function validateProperty($object, $propertyName, $groups = null) + { + return $this->validator->validateProperty($object, $propertyName, $groups); + } + + /** + * {@inheritdoc} + */ + public function validatePropertyValue($objectOrClass, $propertyName, $value, $groups = null) + { + return $this->validator->validatePropertyValue($objectOrClass, $propertyName, $value, $groups); + } + + /** + * {@inheritdoc} + */ + public function startContext() + { + return $this->validator->startContext(); + } + + /** + * {@inheritdoc} + */ + public function inContext(ExecutionContextInterface $context) + { + return $this->validator->inContext($context); + } +} diff --git a/src/Symfony/Component/Validator/composer.json b/src/Symfony/Component/Validator/composer.json index 21c0a8a7cd022..2b0a0cab2971f 100644 --- a/src/Symfony/Component/Validator/composer.json +++ b/src/Symfony/Component/Validator/composer.json @@ -22,6 +22,8 @@ }, "require-dev": { "symfony/http-foundation": "~2.8|~3.0|~4.0", + "symfony/http-kernel": "~2.8|~3.0|~4.0.0", + "symfony/var-dumper": "~3.3|~4.0.0", "symfony/intl": "^2.8.18|^3.2.5|~4.0", "symfony/yaml": "~3.3|~4.0", "symfony/config": "~2.8|~3.0|~4.0", From b30fd4f36fbc57e206145570b326cf07e68051b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Vasseur?= Date: Thu, 11 May 2017 14:27:21 +0200 Subject: [PATCH 0247/1099] Add support for doctrin/dbal 2.6 types --- src/Symfony/Bridge/Doctrine/CHANGELOG.md | 4 ++++ .../Bridge/Doctrine/Form/DoctrineOrmTypeGuesser.php | 2 ++ .../Bridge/Doctrine/PropertyInfo/DoctrineExtractor.php | 9 +++++++++ .../Tests/PropertyInfo/DoctrineExtractorTest.php | 5 +++++ .../Tests/PropertyInfo/Fixtures/DoctrineDummy.php | 10 ++++++++++ 5 files changed, 30 insertions(+) diff --git a/src/Symfony/Bridge/Doctrine/CHANGELOG.md b/src/Symfony/Bridge/Doctrine/CHANGELOG.md index 3dcb8770ec8cc..5e24a8794f972 100644 --- a/src/Symfony/Bridge/Doctrine/CHANGELOG.md +++ b/src/Symfony/Bridge/Doctrine/CHANGELOG.md @@ -1,6 +1,10 @@ CHANGELOG ========= +3.4.0 +----- + * added support for doctrine/dbal v2.6 types + 3.1.0 ----- diff --git a/src/Symfony/Bridge/Doctrine/Form/DoctrineOrmTypeGuesser.php b/src/Symfony/Bridge/Doctrine/Form/DoctrineOrmTypeGuesser.php index 2e6af7a0d6a45..5721528f4d5ff 100644 --- a/src/Symfony/Bridge/Doctrine/Form/DoctrineOrmTypeGuesser.php +++ b/src/Symfony/Bridge/Doctrine/Form/DoctrineOrmTypeGuesser.php @@ -60,6 +60,8 @@ public function guessType($class, $property) case Type::DATETIMETZ: case 'vardatetime': return new TypeGuess('Symfony\Component\Form\Extension\Core\Type\DateTimeType', array(), Guess::HIGH_CONFIDENCE); + case 'dateinterval': + return new TypeGuess('Symfony\Component\Form\Extension\Core\Type\DateIntervalType', array(), Guess::HIGH_CONFIDENCE); case Type::DATE: return new TypeGuess('Symfony\Component\Form\Extension\Core\Type\DateType', array(), Guess::HIGH_CONFIDENCE); case Type::TIME: diff --git a/src/Symfony/Bridge/Doctrine/PropertyInfo/DoctrineExtractor.php b/src/Symfony/Bridge/Doctrine/PropertyInfo/DoctrineExtractor.php index e07c7b0bc2cba..ddc06806aa559 100644 --- a/src/Symfony/Bridge/Doctrine/PropertyInfo/DoctrineExtractor.php +++ b/src/Symfony/Bridge/Doctrine/PropertyInfo/DoctrineExtractor.php @@ -117,6 +117,15 @@ public function getTypes($class, $property, array $context = array()) case DBALType::TIME: return array(new Type(Type::BUILTIN_TYPE_OBJECT, $nullable, 'DateTime')); + case 'date_immutable': + case 'datetime_immutable': + case 'datetimetz_immutable': + case 'time_immutable': + return array(new Type(Type::BUILTIN_TYPE_OBJECT, $nullable, 'DateTimeImmutable')); + + case 'dateinterval': + return array(new Type(Type::BUILTIN_TYPE_OBJECT, $nullable, 'DateInterval')); + case DBALType::TARRAY: return array(new Type(Type::BUILTIN_TYPE_ARRAY, $nullable, null, true)); diff --git a/src/Symfony/Bridge/Doctrine/Tests/PropertyInfo/DoctrineExtractorTest.php b/src/Symfony/Bridge/Doctrine/Tests/PropertyInfo/DoctrineExtractorTest.php index 48822d5888fbc..5d09ede2d9ad4 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/PropertyInfo/DoctrineExtractorTest.php +++ b/src/Symfony/Bridge/Doctrine/Tests/PropertyInfo/DoctrineExtractorTest.php @@ -48,6 +48,8 @@ public function testGetProperties() 'id', 'guid', 'time', + 'timeImmutable', + 'dateInterval', 'json', 'simpleArray', 'float', @@ -78,6 +80,9 @@ public function typesProvider() array('id', array(new Type(Type::BUILTIN_TYPE_INT))), array('guid', array(new Type(Type::BUILTIN_TYPE_STRING))), array('bigint', array(new Type(Type::BUILTIN_TYPE_STRING))), + array('time', array(new Type(Type::BUILTIN_TYPE_OBJECT, false, 'DateTime'))), + array('timeImmutable', array(new Type(Type::BUILTIN_TYPE_OBJECT, false, 'DateTimeImmutable'))), + array('dateInterval', array(new Type(Type::BUILTIN_TYPE_OBJECT, false, 'DateInterval'))), array('float', array(new Type(Type::BUILTIN_TYPE_FLOAT))), array('decimal', array(new Type(Type::BUILTIN_TYPE_STRING))), array('bool', array(new Type(Type::BUILTIN_TYPE_BOOL))), diff --git a/src/Symfony/Bridge/Doctrine/Tests/PropertyInfo/Fixtures/DoctrineDummy.php b/src/Symfony/Bridge/Doctrine/Tests/PropertyInfo/Fixtures/DoctrineDummy.php index 580e75803db8f..793be8f9aae8b 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/PropertyInfo/Fixtures/DoctrineDummy.php +++ b/src/Symfony/Bridge/Doctrine/Tests/PropertyInfo/Fixtures/DoctrineDummy.php @@ -55,6 +55,16 @@ class DoctrineDummy */ private $time; + /** + * @Column(type="time_immutable") + */ + private $timeImmutable; + + /** + * @Column(type="dateinterval") + */ + private $dateInterval; + /** * @Column(type="json_array") */ From 78f1fdeb1cc74985b2da91ce6824afb2abf97bc9 Mon Sep 17 00:00:00 2001 From: Nikolay Labinskiy Date: Tue, 20 Jun 2017 10:52:59 +0300 Subject: [PATCH 0248/1099] [WebProfilerBundle] Eliminate line wrap on count columnt (routing) --- .../WebProfilerBundle/Resources/views/Router/panel.html.twig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Router/panel.html.twig b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Router/panel.html.twig index 8a6929c4df916..3da1cee28785d 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Router/panel.html.twig +++ b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Router/panel.html.twig @@ -54,7 +54,7 @@ {% for trace in traces %} - {{ loop.index }} + {{ loop.index }} {{ trace.name }} {{ trace.path }} From 5a18553bf125452644d961ebeebb079a51cc0b30 Mon Sep 17 00:00:00 2001 From: Javier Eguiluz Date: Tue, 20 Jun 2017 13:28:19 +0200 Subject: [PATCH 0249/1099] Improved the exception page when there is no message --- .../TwigBundle/Resources/views/Exception/exception.html.twig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Symfony/Bundle/TwigBundle/Resources/views/Exception/exception.html.twig b/src/Symfony/Bundle/TwigBundle/Resources/views/Exception/exception.html.twig index 4b35e4fad77db..8ed5226ad5ffa 100644 --- a/src/Symfony/Bundle/TwigBundle/Resources/views/Exception/exception.html.twig +++ b/src/Symfony/Bundle/TwigBundle/Resources/views/Exception/exception.html.twig @@ -13,6 +13,7 @@
+ {% if exception.message is not empty %}

@@ -24,6 +25,7 @@

+ {% endif %}
From 1c091eb7036c69a18c4c9220dc37b972220796cd Mon Sep 17 00:00:00 2001 From: Oleg Voronkovich Date: Tue, 20 Jun 2017 23:21:43 +0300 Subject: [PATCH 0250/1099] [Console] Fix catching exception type in QuestionHelper --- src/Symfony/Component/Console/Helper/QuestionHelper.php | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Component/Console/Helper/QuestionHelper.php b/src/Symfony/Component/Console/Helper/QuestionHelper.php index 3707ffee08f76..f0ca9e545322f 100644 --- a/src/Symfony/Component/Console/Helper/QuestionHelper.php +++ b/src/Symfony/Component/Console/Helper/QuestionHelper.php @@ -111,8 +111,7 @@ public function getName() * * @return bool|mixed|null|string * - * @throws \Exception - * @throws \RuntimeException + * @throws RuntimeException In case the fallback is deactivated and the response cannot be hidden */ public function doAsk(OutputInterface $output, Question $question) { @@ -126,7 +125,7 @@ public function doAsk(OutputInterface $output, Question $question) if ($question->isHidden()) { try { $ret = trim($this->getHiddenResponse($output, $inputStream)); - } catch (\RuntimeException $e) { + } catch (RuntimeException $e) { if (!$question->isHiddenFallback()) { throw $e; } From 61d796a2ead3d3d09b859e6f51ddffc711f50b54 Mon Sep 17 00:00:00 2001 From: Robin Chalas Date: Tue, 20 Jun 2017 23:04:29 +0200 Subject: [PATCH 0251/1099] [Serializer] Implement missing context aware interfaces --- .../Component/Serializer/Encoder/ChainDecoder.php | 6 ++---- .../Component/Serializer/Encoder/ChainEncoder.php | 9 +++------ .../Serializer/Normalizer/ArrayDenormalizer.php | 6 ++---- src/Symfony/Component/Serializer/Serializer.php | 6 +++++- 4 files changed, 12 insertions(+), 15 deletions(-) diff --git a/src/Symfony/Component/Serializer/Encoder/ChainDecoder.php b/src/Symfony/Component/Serializer/Encoder/ChainDecoder.php index a4cc9f67957ea..930c419552d74 100644 --- a/src/Symfony/Component/Serializer/Encoder/ChainDecoder.php +++ b/src/Symfony/Component/Serializer/Encoder/ChainDecoder.php @@ -22,7 +22,7 @@ * * @final since version 3.3. */ -class ChainDecoder implements DecoderInterface /*, ContextAwareDecoderInterface*/ +class ChainDecoder implements ContextAwareDecoderInterface { protected $decoders = array(); protected $decoderByFormat = array(); @@ -43,10 +43,8 @@ final public function decode($data, $format, array $context = array()) /** * {@inheritdoc} */ - public function supportsDecoding($format/*, array $context = array()*/) + public function supportsDecoding($format, array $context = array()) { - $context = func_num_args() > 1 ? func_get_arg(1) : array(); - try { $this->getDecoder($format, $context); } catch (RuntimeException $e) { diff --git a/src/Symfony/Component/Serializer/Encoder/ChainEncoder.php b/src/Symfony/Component/Serializer/Encoder/ChainEncoder.php index cfd8855bb8150..ae12cc9f29166 100644 --- a/src/Symfony/Component/Serializer/Encoder/ChainEncoder.php +++ b/src/Symfony/Component/Serializer/Encoder/ChainEncoder.php @@ -22,7 +22,7 @@ * * @final since version 3.3. */ -class ChainEncoder implements EncoderInterface /*, ContextAwareEncoderInterface*/ +class ChainEncoder implements ContextAwareEncoderInterface { protected $encoders = array(); protected $encoderByFormat = array(); @@ -43,10 +43,8 @@ final public function encode($data, $format, array $context = array()) /** * {@inheritdoc} */ - public function supportsEncoding($format/*, array $context = array()*/) + public function supportsEncoding($format, array $context = array()) { - $context = func_num_args() > 1 ? func_get_arg(1) : array(); - try { $this->getEncoder($format, $context); } catch (RuntimeException $e) { @@ -64,9 +62,8 @@ public function supportsEncoding($format/*, array $context = array()*/) * * @return bool */ - public function needsNormalization($format/*, array $context = array()*/) + public function needsNormalization($format, array $context = array()) { - $context = func_num_args() > 1 ? func_get_arg(1) : array(); $encoder = $this->getEncoder($format, $context); if (!$encoder instanceof NormalizationAwareInterface) { diff --git a/src/Symfony/Component/Serializer/Normalizer/ArrayDenormalizer.php b/src/Symfony/Component/Serializer/Normalizer/ArrayDenormalizer.php index 56d27eb7bf20f..817fe5111a9c5 100644 --- a/src/Symfony/Component/Serializer/Normalizer/ArrayDenormalizer.php +++ b/src/Symfony/Component/Serializer/Normalizer/ArrayDenormalizer.php @@ -24,7 +24,7 @@ * * @final since version 3.3. */ -class ArrayDenormalizer implements DenormalizerInterface, SerializerAwareInterface +class ArrayDenormalizer implements ContextAwareDenormalizerInterface, SerializerAwareInterface { /** * @var SerializerInterface|DenormalizerInterface @@ -66,10 +66,8 @@ public function denormalize($data, $class, $format = null, array $context = arra /** * {@inheritdoc} */ - public function supportsDenormalization($data, $type, $format = null/*, array $context = array()*/) + public function supportsDenormalization($data, $type, $format = null, array $context = array()) { - $context = func_num_args() > 3 ? func_get_arg(3) : array(); - return substr($type, -2) === '[]' && $this->serializer->supportsDenormalization($data, substr($type, 0, -2), $format, $context); } diff --git a/src/Symfony/Component/Serializer/Serializer.php b/src/Symfony/Component/Serializer/Serializer.php index f63c7d5c88e62..0911c67108d64 100644 --- a/src/Symfony/Component/Serializer/Serializer.php +++ b/src/Symfony/Component/Serializer/Serializer.php @@ -13,8 +13,12 @@ use Symfony\Component\Serializer\Encoder\ChainDecoder; use Symfony\Component\Serializer\Encoder\ChainEncoder; +use Symfony\Component\Serializer\Encoder\ContextAwareDecoderInterface; +use Symfony\Component\Serializer\Encoder\ContextAwareEncoderInterface; use Symfony\Component\Serializer\Encoder\EncoderInterface; use Symfony\Component\Serializer\Encoder\DecoderInterface; +use Symfony\Component\Serializer\Normalizer\ContextAwareDenormalizerInterface; +use Symfony\Component\Serializer\Normalizer\ContextAwareNormalizerInterface; use Symfony\Component\Serializer\Normalizer\DenormalizerAwareInterface; use Symfony\Component\Serializer\Normalizer\NormalizerAwareInterface; use Symfony\Component\Serializer\Normalizer\NormalizerInterface; @@ -37,7 +41,7 @@ * @author Lukas Kahwe Smith * @author Kévin Dunglas */ -class Serializer implements SerializerInterface, NormalizerInterface, DenormalizerInterface, EncoderInterface, DecoderInterface +class Serializer implements SerializerInterface, ContextAwareNormalizerInterface, ContextAwareDenormalizerInterface, ContextAwareEncoderInterface, ContextAwareDecoderInterface { /** * @var Encoder\ChainEncoder From dabecdee9973a0a3b42c2bd45b8718bd30ce6bc1 Mon Sep 17 00:00:00 2001 From: Robin Chalas Date: Wed, 21 Jun 2017 09:43:17 +0200 Subject: [PATCH 0252/1099] [Dotenv] Test load() with multiple paths --- .../Component/Dotenv/Tests/DotenvTest.php | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/src/Symfony/Component/Dotenv/Tests/DotenvTest.php b/src/Symfony/Component/Dotenv/Tests/DotenvTest.php index 85204e5c476ac..fd0398f318a28 100644 --- a/src/Symfony/Component/Dotenv/Tests/DotenvTest.php +++ b/src/Symfony/Component/Dotenv/Tests/DotenvTest.php @@ -146,6 +146,28 @@ public function getEnvData() return $tests; } + public function testLoad() + { + @mkdir($tmpdir = sys_get_temp_dir().'/dotenv'); + + $path1 = tempnam($tmpdir, 'sf-'); + $path2 = tempnam($tmpdir, 'sf-'); + + file_put_contents($path1, 'FOO=BAR'); + file_put_contents($path2, 'BAR=BAZ'); + + (new DotEnv())->load($path1, $path2); + + $this->assertSame('BAR', getenv('FOO')); + $this->assertSame('BAZ', getenv('BAR')); + + putenv('FOO'); + putenv('BAR'); + unlink($path1); + unlink($path2); + rmdir($tmpdir); + } + /** * @expectedException \Symfony\Component\Dotenv\Exception\PathException */ From 03f33b592a63846dd5f5f94be69d719fafff1c3a Mon Sep 17 00:00:00 2001 From: Maxime Steinhausser Date: Tue, 20 Jun 2017 20:51:06 +0200 Subject: [PATCH 0253/1099] [DI] Uncomment code --- .../DependencyInjection/Compiler/Compiler.php | 15 +--------- .../Compiler/PassConfig.php | 15 +--------- .../Compiler/ServiceReferenceGraph.php | 13 +-------- .../DependencyInjection/ContainerBuilder.php | 28 ++----------------- 4 files changed, 5 insertions(+), 66 deletions(-) diff --git a/src/Symfony/Component/DependencyInjection/Compiler/Compiler.php b/src/Symfony/Component/DependencyInjection/Compiler/Compiler.php index 43d65bdfd3c5b..8f7fc32b0b1b6 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/Compiler.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/Compiler.php @@ -77,21 +77,8 @@ public function getLoggingFormatter() * @param string $type The type of the pass * @param int $priority Used to sort the passes */ - public function addPass(CompilerPassInterface $pass, $type = PassConfig::TYPE_BEFORE_OPTIMIZATION/*, int $priority = 0*/) + public function addPass(CompilerPassInterface $pass, $type = PassConfig::TYPE_BEFORE_OPTIMIZATION, int $priority = 0) { - if (func_num_args() >= 3) { - $priority = func_get_arg(2); - } else { - if (__CLASS__ !== get_class($this)) { - $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 3.2.', __METHOD__), E_USER_DEPRECATED); - } - } - - $priority = 0; - } - $this->passConfig->addPass($pass, $type, $priority); } diff --git a/src/Symfony/Component/DependencyInjection/Compiler/PassConfig.php b/src/Symfony/Component/DependencyInjection/Compiler/PassConfig.php index 5ee8f98851438..baa1504d501d8 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/PassConfig.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/PassConfig.php @@ -108,21 +108,8 @@ public function getPasses() * * @throws InvalidArgumentException when a pass type doesn't exist */ - public function addPass(CompilerPassInterface $pass, $type = self::TYPE_BEFORE_OPTIMIZATION/*, int $priority = 0*/) + public function addPass(CompilerPassInterface $pass, $type = self::TYPE_BEFORE_OPTIMIZATION, int $priority = 0) { - if (func_num_args() >= 3) { - $priority = func_get_arg(2); - } else { - if (__CLASS__ !== get_class($this)) { - $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 3.2.', __METHOD__), E_USER_DEPRECATED); - } - } - - $priority = 0; - } - $property = $type.'Passes'; if (!isset($this->$property)) { throw new InvalidArgumentException(sprintf('Invalid type "%s".', $type)); diff --git a/src/Symfony/Component/DependencyInjection/Compiler/ServiceReferenceGraph.php b/src/Symfony/Component/DependencyInjection/Compiler/ServiceReferenceGraph.php index 193a37e20b0f6..f754067a0580c 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/ServiceReferenceGraph.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/ServiceReferenceGraph.php @@ -86,19 +86,8 @@ public function clear() * @param string $reference * @param bool $lazy */ - public function connect($sourceId, $sourceValue, $destId, $destValue = null, $reference = null/*, bool $lazy = false*/) + public function connect($sourceId, $sourceValue, $destId, $destValue = null, $reference = null, bool $lazy = false) { - if (func_num_args() >= 6) { - $lazy = func_get_arg(5); - } else { - if (__CLASS__ !== get_class($this)) { - $r = new \ReflectionMethod($this, __FUNCTION__); - if (__CLASS__ !== $r->getDeclaringClass()->getName()) { - @trigger_error(sprintf('Method %s() will have a 6th `bool $lazy = false` argument in version 4.0. Not defining it is deprecated since 3.3.', __METHOD__), E_USER_DEPRECATED); - } - } - $lazy = false; - } $sourceNode = $this->createNode($sourceId, $sourceValue); $destNode = $this->createNode($destId, $destValue); $edge = new ServiceReferenceGraphEdge($sourceNode, $destNode, $reference, $lazy); diff --git a/src/Symfony/Component/DependencyInjection/ContainerBuilder.php b/src/Symfony/Component/DependencyInjection/ContainerBuilder.php index b035bf3a2dacc..7e63452126bf0 100644 --- a/src/Symfony/Component/DependencyInjection/ContainerBuilder.php +++ b/src/Symfony/Component/DependencyInjection/ContainerBuilder.php @@ -442,21 +442,8 @@ public function loadFromExtension($extension, array $values = array()) * * @return $this */ - public function addCompilerPass(CompilerPassInterface $pass, $type = PassConfig::TYPE_BEFORE_OPTIMIZATION/*, int $priority = 0*/) + public function addCompilerPass(CompilerPassInterface $pass, $type = PassConfig::TYPE_BEFORE_OPTIMIZATION, int $priority = 0) { - if (func_num_args() >= 3) { - $priority = func_get_arg(2); - } else { - if (__CLASS__ !== get_class($this)) { - $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 3.2.', __METHOD__), E_USER_DEPRECATED); - } - } - - $priority = 0; - } - $this->getCompiler()->addPass($pass, $type, $priority); $this->addObjectResource($pass); @@ -699,19 +686,8 @@ public function prependExtensionConfig($name, array $config) * Set to "true" when you want to use the current ContainerBuilder * directly, keep to "false" when the container is dumped instead. */ - public function compile(/*$resolveEnvPlaceholders = false*/) + public function compile(bool $resolveEnvPlaceholders = false) { - if (1 <= func_num_args()) { - $resolveEnvPlaceholders = func_get_arg(0); - } else { - if (__CLASS__ !== static::class) { - $r = new \ReflectionMethod($this, __FUNCTION__); - if (__CLASS__ !== $r->getDeclaringClass()->getName() && (1 > $r->getNumberOfParameters() || 'resolveEnvPlaceholders' !== $r->getParameters()[0]->name)) { - @trigger_error(sprintf('The %s::compile() method expects a first "$resolveEnvPlaceholders" argument since version 3.3. It will be made mandatory in 4.0.', static::class), E_USER_DEPRECATED); - } - } - $resolveEnvPlaceholders = false; - } $compiler = $this->getCompiler(); if ($this->trackResources) { From a85d5b01f7a5a16d656de36877a19975b825d5a3 Mon Sep 17 00:00:00 2001 From: Florent Olivaud Date: Tue, 20 Jun 2017 17:06:22 +0200 Subject: [PATCH 0254/1099] Fix Predis client cluster with pipeline --- src/Symfony/Component/Cache/Traits/RedisTrait.php | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Component/Cache/Traits/RedisTrait.php b/src/Symfony/Component/Cache/Traits/RedisTrait.php index f28da39346627..b45d65adc8530 100644 --- a/src/Symfony/Component/Cache/Traits/RedisTrait.php +++ b/src/Symfony/Component/Cache/Traits/RedisTrait.php @@ -12,6 +12,7 @@ namespace Symfony\Component\Cache\Traits; use Predis\Connection\Factory; +use Predis\Connection\Aggregate\ClusterInterface; use Predis\Connection\Aggregate\PredisCluster; use Predis\Connection\Aggregate\RedisCluster; use Predis\Response\Status; @@ -284,7 +285,7 @@ private function pipeline(\Closure $generator) { $ids = array(); - if ($this->redis instanceof \Predis\Client) { + if ($this->redis instanceof \Predis\Client && !$this->redis->getConnection() instanceof ClusterInterface) { $results = $this->redis->pipeline(function ($redis) use ($generator, &$ids) { foreach ($generator() as $command => $args) { call_user_func_array(array($redis, $command), $args); @@ -308,9 +309,10 @@ private function pipeline(\Closure $generator) foreach ($results as $k => list($h, $c)) { $results[$k] = $connections[$h][$c]; } - } elseif ($this->redis instanceof \RedisCluster) { - // phpredis doesn't support pipelining with RedisCluster + } elseif ($this->redis instanceof \RedisCluster || ($this->redis instanceof \Predis\Client && $this->redis->getConnection() instanceof ClusterInterface)) { + // phpredis & predis don't support pipelining with RedisCluster // see https://github.com/phpredis/phpredis/blob/develop/cluster.markdown#pipelining + // see https://github.com/nrk/predis/issues/267#issuecomment-123781423 $results = array(); foreach ($generator() as $command => $args) { $results[] = call_user_func_array(array($this->redis, $command), $args); From 3c21650d9ec713c36ebbbc3667b8120646ebc6dc Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Wed, 21 Jun 2017 13:02:23 +0200 Subject: [PATCH 0255/1099] return fallback locales whenever possible --- src/Symfony/Component/Translation/DataCollectorTranslator.php | 2 +- src/Symfony/Component/Translation/LoggingTranslator.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/Translation/DataCollectorTranslator.php b/src/Symfony/Component/Translation/DataCollectorTranslator.php index b2049d47511ce..0243d8aa21596 100644 --- a/src/Symfony/Component/Translation/DataCollectorTranslator.php +++ b/src/Symfony/Component/Translation/DataCollectorTranslator.php @@ -95,7 +95,7 @@ public function getCatalogue($locale = null) */ public function getFallbackLocales() { - if ($this->translator instanceof Translator) { + if ($this->translator instanceof Translator || method_exists($this->translator, 'getFallbackLocales')) { return $this->translator->getFallbackLocales(); } diff --git a/src/Symfony/Component/Translation/LoggingTranslator.php b/src/Symfony/Component/Translation/LoggingTranslator.php index b259df5e0aa49..85ab3c47f55c8 100644 --- a/src/Symfony/Component/Translation/LoggingTranslator.php +++ b/src/Symfony/Component/Translation/LoggingTranslator.php @@ -95,7 +95,7 @@ public function getCatalogue($locale = null) */ public function getFallbackLocales() { - if ($this->translator instanceof Translator) { + if ($this->translator instanceof Translator || method_exists($this->translator, 'getFallbackLocales')) { return $this->translator->getFallbackLocales(); } From 2d8fdd9622e0c797ea6ef35e46aaf18e56f7ad13 Mon Sep 17 00:00:00 2001 From: "Alexander M. Turek" Date: Tue, 13 Jun 2017 17:15:58 +0200 Subject: [PATCH 0256/1099] Add Doctrine Cache to dev dependencies to fix failing unit tests. --- src/Symfony/Bundle/TwigBundle/composer.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Bundle/TwigBundle/composer.json b/src/Symfony/Bundle/TwigBundle/composer.json index 9b984f97ecdec..ef1a183e822d4 100644 --- a/src/Symfony/Bundle/TwigBundle/composer.json +++ b/src/Symfony/Bundle/TwigBundle/composer.json @@ -34,7 +34,8 @@ "symfony/templating": "~2.8|~3.0", "symfony/yaml": "~2.8|~3.0", "symfony/framework-bundle": "^3.2.2", - "doctrine/annotations": "~1.0" + "doctrine/annotations": "~1.0", + "doctrine/cache": "~1.0" }, "autoload": { "psr-4": { "Symfony\\Bundle\\TwigBundle\\": "" }, From 74c951fa042c279828ea19c0fea593eba8885d8a Mon Sep 17 00:00:00 2001 From: Thierry Thuon Date: Fri, 5 May 2017 12:35:04 +0200 Subject: [PATCH 0257/1099] [FrameworkBundle][Translation] Move translation compiler pass --- UPGRADE-3.4.md | 12 +++ UPGRADE-4.0.md | 12 +++ .../Bundle/FrameworkBundle/CHANGELOG.md | 6 ++ .../Compiler/TranslationDumperPass.php | 22 ++--- .../Compiler/TranslationExtractorPass.php | 29 ++---- .../Compiler/TranslatorPass.php | 45 ++------- .../FrameworkBundle/FrameworkBundle.php | 12 +-- .../Compiler/TranslatorPassTest.php | 3 + .../FrameworkExtensionTest.php | 2 +- .../Bundle/FrameworkBundle/composer.json | 4 +- .../Component/Translation/CHANGELOG.md | 7 ++ .../TranslationDumperPass.php | 44 +++++++++ .../TranslationExtractorPass.php | 49 +++++++++ .../DependencyInjection/TranslatorPass.php | 63 ++++++++++++ .../TranslationDumperPassTest.php | 66 +++++++++++++ .../TranslationExtractorPassTest.php | 99 +++++++++++++++++++ .../TranslationPassTest.php | 50 ++++++++++ .../Component/Translation/composer.json | 2 + 18 files changed, 444 insertions(+), 83 deletions(-) create mode 100644 src/Symfony/Component/Translation/DependencyInjection/TranslationDumperPass.php create mode 100644 src/Symfony/Component/Translation/DependencyInjection/TranslationExtractorPass.php create mode 100644 src/Symfony/Component/Translation/DependencyInjection/TranslatorPass.php create mode 100644 src/Symfony/Component/Translation/Tests/DependencyInjection/TranslationDumperPassTest.php create mode 100644 src/Symfony/Component/Translation/Tests/DependencyInjection/TranslationExtractorPassTest.php create mode 100644 src/Symfony/Component/Translation/Tests/DependencyInjection/TranslationPassTest.php diff --git a/UPGRADE-3.4.md b/UPGRADE-3.4.md index a609da081ccb8..cc015a7f3fb02 100644 --- a/UPGRADE-3.4.md +++ b/UPGRADE-3.4.md @@ -38,6 +38,18 @@ FrameworkBundle will be removed in 4.0. Use the `--prefix` option with an empty string as value instead (e.g. `--prefix=""`) + * The `Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\TranslationDumperPass` + class has been deprecated and will be removed in 4.0. Use the + `Symfony\Component\Translation\DependencyInjection\TranslationDumperPass` class instead. + + * The `Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\TranslationExtractorPass` + class has been deprecated and will be removed in 4.0. Use the + `Symfony\Component\Translation\DependencyInjection\TranslationExtractorPass` class instead. + + * The `Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\TranslatorPass` + class has been deprecated and will be removed in 4.0. Use the + `Symfony\Component\Translation\DependencyInjection\TranslatorPass` class instead. + Process ------- diff --git a/UPGRADE-4.0.md b/UPGRADE-4.0.md index b1027dc026fad..79ed0fad77dee 100644 --- a/UPGRADE-4.0.md +++ b/UPGRADE-4.0.md @@ -348,6 +348,18 @@ FrameworkBundle * The `--no-prefix` option of the `translation:update` command has been removed. + * The `Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\TranslationDumperPass` + class has been removed. Use the + `Symfony\Component\Translation\DependencyInjection\TranslationDumperPass` class instead. + + * The `Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\TranslationExtractorPass` + class has been removed. Use the + `Symfony\Component\Translation\DependencyInjection\TranslationExtractorPass` class instead. + + * The `Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\TranslatorPass` + class has been removed. Use the + `Symfony\Component\Translation\DependencyInjection\TranslatorPass` class instead. + HttpFoundation -------------- diff --git a/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md b/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md index c089a8b40a743..22fc00ade02bf 100644 --- a/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md +++ b/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md @@ -10,6 +10,12 @@ CHANGELOG require symfony/stopwatch` in your `dev` environment. * Deprecated using the `KERNEL_DIR` environment variable with `KernelTestCase::getKernelClass()`. * Deprecated the `KernelTestCase::getPhpUnitXmlDir()` and `KernelTestCase::getPhpUnitCliConfigArgument()` methods. + * Deprecated `TranslationDumperPass`, use + `Symfony\Component\Translation\DependencyInjection\TranslationDumperPass` instead + * Deprecated `TranslationExtractorPass`, use + `Symfony\Component\Translation\DependencyInjection\TranslationExtractorPass` instead + * Deprecated `TranslatorPass`, use + `Symfony\Component\Translation\DependencyInjection\TranslatorPass` instead 3.3.0 ----- diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/TranslationDumperPass.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/TranslationDumperPass.php index 541b06b31e254..38e52e8cd9c89 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/TranslationDumperPass.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/TranslationDumperPass.php @@ -11,25 +11,15 @@ namespace Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler; -use Symfony\Component\DependencyInjection\Reference; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; +@trigger_error(sprintf('The %s class is deprecated since version 3.4 and will be removed in 4.0. Use Symfony\Component\Translation\DependencyInjection\TranslationDumperPass instead.', TranslationDumperPass::class), E_USER_DEPRECATED); + +use Symfony\Component\Translation\DependencyInjection\TranslationDumperPass as BaseTranslationDumperPass; /** * Adds tagged translation.formatter services to translation writer. + * + * @deprecated since version 3.4, to be removed in 4.0. Use {@link BaseTranslationDumperPass instead}. */ -class TranslationDumperPass implements CompilerPassInterface +class TranslationDumperPass extends BaseTranslationDumperPass { - public function process(ContainerBuilder $container) - { - if (!$container->hasDefinition('translation.writer')) { - return; - } - - $definition = $container->getDefinition('translation.writer'); - - foreach ($container->findTaggedServiceIds('translation.dumper', true) as $id => $attributes) { - $definition->addMethodCall('addDumper', array($attributes[0]['alias'], new Reference($id))); - } - } } diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/TranslationExtractorPass.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/TranslationExtractorPass.php index 4dc8d3985ce68..985809eeb16ef 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/TranslationExtractorPass.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/TranslationExtractorPass.php @@ -11,30 +11,15 @@ namespace Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler; -use Symfony\Component\DependencyInjection\Reference; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; -use Symfony\Component\DependencyInjection\Exception\RuntimeException; +@trigger_error(sprintf('The %s class is deprecated since version 3.4 and will be removed in 4.0. Use Symfony\Component\Translation\DependencyInjection\TranslationExtractorPass instead.', TranslationExtractorPass::class), E_USER_DEPRECATED); + +use Symfony\Component\Translation\DependencyInjection\TranslationExtractorPass as BaseTranslationExtractorPass; /** - * Adds tagged translation.extractor services to translation extractor. + * Adds tagged translation.formatter services to translation writer. + * + * @deprecated since version 3.4, to be removed in 4.0. Use {@link BaseTranslationDumperPass instead}. */ -class TranslationExtractorPass implements CompilerPassInterface +class TranslationExtractorPass extends BaseTranslationExtractorPass { - public function process(ContainerBuilder $container) - { - if (!$container->hasDefinition('translation.extractor')) { - return; - } - - $definition = $container->getDefinition('translation.extractor'); - - foreach ($container->findTaggedServiceIds('translation.extractor', true) as $id => $attributes) { - if (!isset($attributes[0]['alias'])) { - throw new RuntimeException(sprintf('The alias for the tag "translation.extractor" of service "%s" must be set.', $id)); - } - - $definition->addMethodCall('addExtractor', array($attributes[0]['alias'], new Reference($id))); - } - } } diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/TranslatorPass.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/TranslatorPass.php index 29e251f274339..7bba4629371cb 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/TranslatorPass.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/TranslatorPass.php @@ -11,42 +11,15 @@ namespace Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler; -use Symfony\Component\DependencyInjection\Reference; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; -use Symfony\Component\DependencyInjection\Compiler\ServiceLocatorTagPass; +@trigger_error(sprintf('The %s class is deprecated since version 3.4 and will be removed in 4.0. Use Symfony\Component\Translation\DependencyInjection\TranslatorPass instead.', TranslatorPass::class), E_USER_DEPRECATED); -class TranslatorPass implements CompilerPassInterface -{ - public function process(ContainerBuilder $container) - { - if (!$container->hasDefinition('translator.default')) { - return; - } - - $loaders = array(); - $loaderRefs = array(); - foreach ($container->findTaggedServiceIds('translation.loader', true) as $id => $attributes) { - $loaderRefs[$id] = new Reference($id); - $loaders[$id][] = $attributes[0]['alias']; - if (isset($attributes[0]['legacy-alias'])) { - $loaders[$id][] = $attributes[0]['legacy-alias']; - } - } - - if ($container->hasDefinition('translation.loader')) { - $definition = $container->getDefinition('translation.loader'); - foreach ($loaders as $id => $formats) { - foreach ($formats as $format) { - $definition->addMethodCall('addLoader', array($format, $loaderRefs[$id])); - } - } - } +use Symfony\Component\Translation\DependencyInjection\TranslatorPass as BaseTranslatorPass; - $container - ->findDefinition('translator.default') - ->replaceArgument(0, ServiceLocatorTagPass::register($container, $loaderRefs)) - ->replaceArgument(3, $loaders) - ; - } +/** + * Adds tagged translation.formatter services to translation writer. + * + * @deprecated since version 3.4, to be removed in 4.0. Use {@link BaseTranslatorPass instead}. + */ +class TranslatorPass extends BaseTranslatorPass +{ } diff --git a/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php b/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php index 99ab06b337772..a9290c697c843 100644 --- a/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php +++ b/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php @@ -19,14 +19,11 @@ use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\DataCollectorTranslatorPass; use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\TemplatingPass; use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\ProfilerPass; -use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\TranslatorPass; use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\LoggingTranslatorPass; use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\AddCacheWarmerPass; use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\AddCacheClearerPass; use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\AddExpressionLanguageProvidersPass; use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\ContainerBuilderDebugDumpPass; -use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\TranslationExtractorPass; -use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\TranslationDumperPass; use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\UnusedTagsPass; use Symfony\Component\Config\DependencyInjection\ConfigCachePass; use Symfony\Component\Console\DependencyInjection\AddConsoleCommandPass; @@ -45,6 +42,9 @@ use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpKernel\Bundle\Bundle; use Symfony\Component\Config\Resource\ClassExistenceResource; +use Symfony\Component\Translation\DependencyInjection\TranslationDumperPass; +use Symfony\Component\Translation\DependencyInjection\TranslationExtractorPass; +use Symfony\Component\Translation\DependencyInjection\TranslatorPass; use Symfony\Component\Validator\DependencyInjection\AddConstraintValidatorsPass; use Symfony\Component\Validator\DependencyInjection\AddValidatorInitializersPass; use Symfony\Component\Workflow\DependencyInjection\ValidateWorkflowsPass; @@ -93,13 +93,13 @@ public function build(ContainerBuilder $container) $container->addCompilerPass(new AddAnnotationsCachedReaderPass(), PassConfig::TYPE_BEFORE_REMOVING); $this->addCompilerPassIfExists($container, AddValidatorInitializersPass::class); $this->addCompilerPassIfExists($container, AddConsoleCommandPass::class); - $container->addCompilerPass(new TranslatorPass()); + $this->addCompilerPassIfExists($container, TranslatorPass::class); $container->addCompilerPass(new LoggingTranslatorPass()); $container->addCompilerPass(new AddCacheWarmerPass()); $container->addCompilerPass(new AddCacheClearerPass()); $container->addCompilerPass(new AddExpressionLanguageProvidersPass()); - $container->addCompilerPass(new TranslationExtractorPass()); - $container->addCompilerPass(new TranslationDumperPass()); + $this->addCompilerPassIfExists($container, TranslationExtractorPass::class); + $this->addCompilerPassIfExists($container, TranslationDumperPass::class); $container->addCompilerPass(new FragmentRendererPass(), PassConfig::TYPE_AFTER_REMOVING); $this->addCompilerPassIfExists($container, SerializerPass::class); $this->addCompilerPassIfExists($container, PropertyInfoPass::class); diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/TranslatorPassTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/TranslatorPassTest.php index a92f734eccc0f..d31fb18a12864 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/TranslatorPassTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/TranslatorPassTest.php @@ -18,6 +18,9 @@ use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\DependencyInjection\Reference; +/** + * @group legacy + */ class TranslatorPassTest extends TestCase { public function testValidCollector() diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php index 4f86c85d4f8fb..b7f606e874175 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php @@ -12,7 +12,6 @@ namespace Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection; use Doctrine\Common\Annotations\Annotation; -use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\TranslatorPass; use Symfony\Bundle\FullStack; use Symfony\Bundle\FrameworkBundle\Tests\TestCase; use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\AddAnnotationsCachedReaderPass; @@ -41,6 +40,7 @@ use Symfony\Component\Serializer\Normalizer\DataUriNormalizer; use Symfony\Component\Serializer\Normalizer\DateTimeNormalizer; use Symfony\Component\Serializer\Normalizer\JsonSerializableNormalizer; +use Symfony\Component\Translation\DependencyInjection\TranslatorPass; use Symfony\Component\Validator\DependencyInjection\AddConstraintValidatorsPass; abstract class FrameworkExtensionTest extends TestCase diff --git a/src/Symfony/Bundle/FrameworkBundle/composer.json b/src/Symfony/Bundle/FrameworkBundle/composer.json index 9699ae85d6d6f..940a49a4de99d 100644 --- a/src/Symfony/Bundle/FrameworkBundle/composer.json +++ b/src/Symfony/Bundle/FrameworkBundle/composer.json @@ -47,7 +47,7 @@ "symfony/security-csrf": "~2.8|~3.0|~4.0", "symfony/serializer": "~3.3|~4.0", "symfony/stopwatch": "~2.8|~3.0|~4.0", - "symfony/translation": "~3.2|~4.0", + "symfony/translation": "~3.4|~4.0", "symfony/templating": "~2.8|~3.0|~4.0", "symfony/validator": "~3.4|~4.0", "symfony/var-dumper": "~3.3|~4.0", @@ -68,7 +68,7 @@ "symfony/form": "<3.3", "symfony/property-info": "<3.3", "symfony/serializer": "<3.3", - "symfony/translation": "<3.2", + "symfony/translation": "<3.4", "symfony/validator": "<3.4", "symfony/workflow": "<3.3" }, diff --git a/src/Symfony/Component/Translation/CHANGELOG.md b/src/Symfony/Component/Translation/CHANGELOG.md index 349faceb0c8f0..baa791b0ad174 100644 --- a/src/Symfony/Component/Translation/CHANGELOG.md +++ b/src/Symfony/Component/Translation/CHANGELOG.md @@ -1,6 +1,13 @@ CHANGELOG ========= +3.4.0 +----- + + * Added `TranslationDumperPass` + * Added `TranslationExtractorPass` + * Added `TranslatorPass` + 3.2.0 ----- diff --git a/src/Symfony/Component/Translation/DependencyInjection/TranslationDumperPass.php b/src/Symfony/Component/Translation/DependencyInjection/TranslationDumperPass.php new file mode 100644 index 0000000000000..1ca79cf00a5bd --- /dev/null +++ b/src/Symfony/Component/Translation/DependencyInjection/TranslationDumperPass.php @@ -0,0 +1,44 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\DependencyInjection; + +use Symfony\Component\DependencyInjection\Reference; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; + +/** + * Adds tagged translation.formatter services to translation writer. + */ +class TranslationDumperPass implements CompilerPassInterface +{ + private $writerServiceId; + private $dumperTag; + + public function __construct($writerServiceId = 'translation.writer', $dumperTag = 'translation.dumper') + { + $this->writerServiceId = $writerServiceId; + $this->dumperTag = $dumperTag; + } + + public function process(ContainerBuilder $container) + { + if (!$container->hasDefinition($this->writerServiceId)) { + return; + } + + $definition = $container->getDefinition($this->writerServiceId); + + foreach ($container->findTaggedServiceIds($this->dumperTag, true) as $id => $attributes) { + $definition->addMethodCall('addDumper', array($attributes[0]['alias'], new Reference($id))); + } + } +} diff --git a/src/Symfony/Component/Translation/DependencyInjection/TranslationExtractorPass.php b/src/Symfony/Component/Translation/DependencyInjection/TranslationExtractorPass.php new file mode 100644 index 0000000000000..06105187952c4 --- /dev/null +++ b/src/Symfony/Component/Translation/DependencyInjection/TranslationExtractorPass.php @@ -0,0 +1,49 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\DependencyInjection; + +use Symfony\Component\DependencyInjection\Reference; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; +use Symfony\Component\DependencyInjection\Exception\RuntimeException; + +/** + * Adds tagged translation.extractor services to translation extractor. + */ +class TranslationExtractorPass implements CompilerPassInterface +{ + private $extractorServiceId; + private $extractorTag; + + public function __construct($extractorServiceId = 'translation.extractor', $extractorTag = 'translation.extractor') + { + $this->extractorServiceId = $extractorServiceId; + $this->extractorTag = $extractorTag; + } + + public function process(ContainerBuilder $container) + { + if (!$container->hasDefinition($this->extractorServiceId)) { + return; + } + + $definition = $container->getDefinition($this->extractorServiceId); + + foreach ($container->findTaggedServiceIds($this->extractorTag, true) as $id => $attributes) { + if (!isset($attributes[0]['alias'])) { + throw new RuntimeException(sprintf('The alias for the tag "translation.extractor" of service "%s" must be set.', $id)); + } + + $definition->addMethodCall('addExtractor', array($attributes[0]['alias'], new Reference($id))); + } + } +} diff --git a/src/Symfony/Component/Translation/DependencyInjection/TranslatorPass.php b/src/Symfony/Component/Translation/DependencyInjection/TranslatorPass.php new file mode 100644 index 0000000000000..e144f6b74ef10 --- /dev/null +++ b/src/Symfony/Component/Translation/DependencyInjection/TranslatorPass.php @@ -0,0 +1,63 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\DependencyInjection; + +use Symfony\Component\DependencyInjection\Reference; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; +use Symfony\Component\DependencyInjection\Compiler\ServiceLocatorTagPass; + +class TranslatorPass implements CompilerPassInterface +{ + private $translatorServiceId; + private $loaderServiceId; + private $loaderTag; + + public function __construct($translatorServiceId = 'translator.default', $loaderServiceId = 'translation.loader', $loaderTag = 'translation.loader') + { + $this->translatorServiceId = $translatorServiceId; + $this->loaderServiceId = $loaderServiceId; + $this->loaderTag = $loaderTag; + } + + public function process(ContainerBuilder $container) + { + if (!$container->hasDefinition($this->translatorServiceId)) { + return; + } + + $loaders = array(); + $loaderRefs = array(); + foreach ($container->findTaggedServiceIds($this->loaderTag, true) as $id => $attributes) { + $loaderRefs[$id] = new Reference($id); + $loaders[$id][] = $attributes[0]['alias']; + if (isset($attributes[0]['legacy-alias'])) { + $loaders[$id][] = $attributes[0]['legacy-alias']; + } + } + + if ($container->hasDefinition($this->loaderServiceId)) { + $definition = $container->getDefinition($this->loaderServiceId); + foreach ($loaders as $id => $formats) { + foreach ($formats as $format) { + $definition->addMethodCall('addLoader', array($format, $loaderRefs[$id])); + } + } + } + + $container + ->findDefinition($this->translatorServiceId) + ->replaceArgument(0, ServiceLocatorTagPass::register($container, $loaderRefs)) + ->replaceArgument(3, $loaders) + ; + } +} diff --git a/src/Symfony/Component/Translation/Tests/DependencyInjection/TranslationDumperPassTest.php b/src/Symfony/Component/Translation/Tests/DependencyInjection/TranslationDumperPassTest.php new file mode 100644 index 0000000000000..845200e71251a --- /dev/null +++ b/src/Symfony/Component/Translation/Tests/DependencyInjection/TranslationDumperPassTest.php @@ -0,0 +1,66 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Tests\DependencyInjection; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\DependencyInjection\Reference; +use Symfony\Component\Translation\DependencyInjection\TranslationDumperPass; + +class TranslationDumperPassTest extends TestCase +{ + public function testProcess() + { + $definition = $this->getMockBuilder('Symfony\Component\DependencyInjection\Definition')->disableOriginalConstructor()->getMock(); + $container = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerBuilder')->disableOriginalConstructor()->getMock(); + + $container->expects($this->once()) + ->method('hasDefinition') + ->with('translation.writer') + ->will($this->returnValue(true)); + + $container->expects($this->once()) + ->method('getDefinition') + ->with('translation.writer') + ->will($this->returnValue($definition)); + + $valueTaggedServiceIdsFound = array( + 'foo.id' => array( + array('alias' => 'bar.alias'), + ), + ); + $container->expects($this->once()) + ->method('findTaggedServiceIds') + ->with('translation.dumper', true) + ->will($this->returnValue($valueTaggedServiceIdsFound)); + + $definition->expects($this->once())->method('addMethodCall')->with('addDumper', array('bar.alias', new Reference('foo.id'))); + + $translationDumperPass = new TranslationDumperPass(); + $translationDumperPass->process($container); + } + + public function testProcessNoDefinitionFound() + { + $container = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerBuilder')->disableOriginalConstructor()->getMock(); + + $container->expects($this->once()) + ->method('hasDefinition') + ->with('translation.writer') + ->will($this->returnValue(false)); + + $container->expects($this->never())->method('getDefinition'); + $container->expects($this->never())->method('findTaggedServiceIds'); + + $translationDumperPass = new TranslationDumperPass(); + $translationDumperPass->process($container); + } +} diff --git a/src/Symfony/Component/Translation/Tests/DependencyInjection/TranslationExtractorPassTest.php b/src/Symfony/Component/Translation/Tests/DependencyInjection/TranslationExtractorPassTest.php new file mode 100644 index 0000000000000..76d2b999cfd83 --- /dev/null +++ b/src/Symfony/Component/Translation/Tests/DependencyInjection/TranslationExtractorPassTest.php @@ -0,0 +1,99 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Tests\DependencyInjection; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\DependencyInjection\Reference; +use Symfony\Component\Translation\DependencyInjection\TranslationExtractorPass; + +class TranslationExtractorPassTest extends TestCase +{ + public function testProcess() + { + $definition = $this->getMockBuilder('Symfony\Component\DependencyInjection\Definition')->disableOriginalConstructor()->getMock(); + $container = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerBuilder')->disableOriginalConstructor()->getMock(); + + $container->expects($this->once()) + ->method('hasDefinition') + ->with('translation.extractor') + ->will($this->returnValue(true)); + + $container->expects($this->once()) + ->method('getDefinition') + ->with('translation.extractor') + ->will($this->returnValue($definition)); + + $valueTaggedServiceIdsFound = array( + 'foo.id' => array( + array('alias' => 'bar.alias'), + ), + ); + $container->expects($this->once()) + ->method('findTaggedServiceIds') + ->with('translation.extractor', true) + ->will($this->returnValue($valueTaggedServiceIdsFound)); + + $definition->expects($this->once())->method('addMethodCall')->with('addExtractor', array('bar.alias', new Reference('foo.id'))); + + $translationDumperPass = new TranslationExtractorPass(); + $translationDumperPass->process($container); + } + + public function testProcessNoDefinitionFound() + { + $container = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerBuilder')->disableOriginalConstructor()->getMock(); + + $container->expects($this->once()) + ->method('hasDefinition') + ->with('translation.extractor') + ->will($this->returnValue(false)); + + $container->expects($this->never())->method('getDefinition'); + $container->expects($this->never())->method('findTaggedServiceIds'); + + $translationDumperPass = new TranslationExtractorPass(); + $translationDumperPass->process($container); + } + + /** + * @expectedException \Symfony\Component\DependencyInjection\Exception\RuntimeException + * @expectedExceptionMessage The alias for the tag "translation.extractor" of service "foo.id" must be set. + */ + public function testProcessMissingAlias() + { + $definition = $this->getMockBuilder('Symfony\Component\DependencyInjection\Definition')->disableOriginalConstructor()->getMock(); + $container = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerBuilder')->disableOriginalConstructor()->getMock(); + + $container->expects($this->once()) + ->method('hasDefinition') + ->with('translation.extractor') + ->will($this->returnValue(true)); + + $container->expects($this->once()) + ->method('getDefinition') + ->with('translation.extractor') + ->will($this->returnValue($definition)); + + $valueTaggedServiceIdsFound = array( + 'foo.id' => array(), + ); + $container->expects($this->once()) + ->method('findTaggedServiceIds') + ->with('translation.extractor', true) + ->will($this->returnValue($valueTaggedServiceIdsFound)); + + $definition->expects($this->never())->method('addMethodCall'); + + $translationDumperPass = new TranslationExtractorPass(); + $translationDumperPass->process($container); + } +} diff --git a/src/Symfony/Component/Translation/Tests/DependencyInjection/TranslationPassTest.php b/src/Symfony/Component/Translation/Tests/DependencyInjection/TranslationPassTest.php new file mode 100644 index 0000000000000..8a4dff70a7946 --- /dev/null +++ b/src/Symfony/Component/Translation/Tests/DependencyInjection/TranslationPassTest.php @@ -0,0 +1,50 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Tests\DependencyInjection; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Definition; +use Symfony\Component\DependencyInjection\Reference; +use Symfony\Component\Translation\DependencyInjection\TranslatorPass; + +class TranslationPassTest extends TestCase +{ + public function testValidCollector() + { + $loader = (new Definition()) + ->addTag('translation.loader', array('alias' => 'xliff', 'legacy-alias' => 'xlf')); + + $translator = (new Definition()) + ->setArguments(array(null, null, null, null)); + + $container = new ContainerBuilder(); + $container->setDefinition('translator.default', $translator); + $container->setDefinition('translation.loader', $loader); + + $pass = new TranslatorPass(); + $pass->process($container); + + $expected = (new Definition()) + ->addTag('translation.loader', array('alias' => 'xliff', 'legacy-alias' => 'xlf')) + ->addMethodCall('addLoader', array('xliff', new Reference('translation.loader'))) + ->addMethodCall('addLoader', array('xlf', new Reference('translation.loader'))) + ; + $this->assertEquals($expected, $loader); + + $this->assertSame(array('translation.loader' => array('xliff', 'xlf')), $translator->getArgument(3)); + + $expected = array('translation.loader' => new ServiceClosureArgument(new Reference('translation.loader'))); + $this->assertEquals($expected, $container->getDefinition((string) $translator->getArgument(0))->getArgument(0)); + } +} diff --git a/src/Symfony/Component/Translation/composer.json b/src/Symfony/Component/Translation/composer.json index 4b4897e8e340e..3f59d4214f6c5 100644 --- a/src/Symfony/Component/Translation/composer.json +++ b/src/Symfony/Component/Translation/composer.json @@ -21,12 +21,14 @@ }, "require-dev": { "symfony/config": "~2.8|~3.0|~4.0", + "symfony/dependency-injection": "~3.4|~4.0", "symfony/intl": "^2.8.18|^3.2.5|~4.0", "symfony/yaml": "~3.3|~4.0", "psr/log": "~1.0" }, "conflict": { "symfony/config": "<2.8", + "symfony/dependency-injection": "<3.4", "symfony/yaml": "<3.3" }, "suggest": { From 17c7a2d8c7d0224619d46ba1d9e32d627fb9b308 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Tue, 23 May 2017 00:20:30 +0200 Subject: [PATCH 0258/1099] [HttpFoundation] remove deprecated features --- .../Component/HttpFoundation/CHANGELOG.md | 17 ++ .../Component/HttpFoundation/Request.php | 148 +++--------------- .../HttpFoundation/Tests/RequestTest.php | 127 +-------------- .../Fragment/InlineFragmentRenderer.php | 17 +- 4 files changed, 48 insertions(+), 261 deletions(-) diff --git a/src/Symfony/Component/HttpFoundation/CHANGELOG.md b/src/Symfony/Component/HttpFoundation/CHANGELOG.md index e1fdf77b9b8ae..aa2500f57a40c 100644 --- a/src/Symfony/Component/HttpFoundation/CHANGELOG.md +++ b/src/Symfony/Component/HttpFoundation/CHANGELOG.md @@ -1,6 +1,23 @@ CHANGELOG ========= +4.0.0 +----- + + * the `Request::setTrustedHeaderName()` and `Request::getTrustedHeaderName()` + methods have been removed + * the `Request::HEADER_CLIENT_IP` constant has been removed, use + `Request::HEADER_X_FORWARDED_FOR` instead + * the `Request::HEADER_CLIENT_HOST` constant has been removed, use + `Request::HEADER_X_FORWARDED_HOST` instead + * the `Request::HEADER_CLIENT_PROTO` constant has been removed, use + `Request::HEADER_X_FORWARDED_PROTO` instead + * the `Request::HEADER_CLIENT_PORT` constant has been removed, use + `Request::HEADER_X_FORWARDED_PORT` instead + * checking for cacheable HTTP methods using the `Request::isMethodSafe()` + method (by not passing `false` as its argument) is not supported anymore and + throws a `\BadMethodCallException` + 3.3.0 ----- diff --git a/src/Symfony/Component/HttpFoundation/Request.php b/src/Symfony/Component/HttpFoundation/Request.php index c15d7d3165559..35ac77d01e727 100644 --- a/src/Symfony/Component/HttpFoundation/Request.php +++ b/src/Symfony/Component/HttpFoundation/Request.php @@ -38,15 +38,6 @@ class Request const HEADER_X_FORWARDED_ALL = 0b11110; // All "X-Forwarded-*" headers const HEADER_X_FORWARDED_AWS_ELB = 0b11010; // AWS ELB doesn't send X-Forwarded-Host - /** @deprecated since version 3.3, to be removed in 4.0 */ - const HEADER_CLIENT_IP = self::HEADER_X_FORWARDED_FOR; - /** @deprecated since version 3.3, to be removed in 4.0 */ - const HEADER_CLIENT_HOST = self::HEADER_X_FORWARDED_HOST; - /** @deprecated since version 3.3, to be removed in 4.0 */ - const HEADER_CLIENT_PROTO = self::HEADER_X_FORWARDED_PROTO; - /** @deprecated since version 3.3, to be removed in 4.0 */ - const HEADER_CLIENT_PORT = self::HEADER_X_FORWARDED_PORT; - const METHOD_HEAD = 'HEAD'; const METHOD_GET = 'GET'; const METHOD_POST = 'POST'; @@ -73,25 +64,6 @@ class Request */ protected static $trustedHosts = array(); - /** - * Names for headers that can be trusted when - * using trusted proxies. - * - * The FORWARDED header is the standard as of rfc7239. - * - * The other headers are non-standard, but widely used - * by popular reverse proxies (like Apache mod_proxy or Amazon EC2). - * - * @deprecated since version 3.3, to be removed in 4.0 - */ - protected static $trustedHeaders = array( - self::HEADER_FORWARDED => 'FORWARDED', - self::HEADER_CLIENT_IP => 'X_FORWARDED_FOR', - self::HEADER_CLIENT_HOST => 'X_FORWARDED_HOST', - self::HEADER_CLIENT_PROTO => 'X_FORWARDED_PROTO', - self::HEADER_CLIENT_PORT => 'X_FORWARDED_PORT', - ); - protected static $httpMethodParameterOverride = false; /** @@ -226,15 +198,6 @@ class Request private static $trustedHeaderSet = -1; - /** @deprecated since version 3.3, to be removed in 4.0 */ - private static $trustedHeaderNames = array( - self::HEADER_FORWARDED => 'FORWARDED', - self::HEADER_CLIENT_IP => 'X_FORWARDED_FOR', - self::HEADER_CLIENT_HOST => 'X_FORWARDED_HOST', - self::HEADER_CLIENT_PROTO => 'X_FORWARDED_PROTO', - self::HEADER_CLIENT_PORT => 'X_FORWARDED_PORT', - ); - private static $forwardedParams = array( self::HEADER_X_FORWARDED_FOR => 'for', self::HEADER_X_FORWARDED_HOST => 'host', @@ -242,6 +205,23 @@ class Request self::HEADER_X_FORWARDED_PORT => 'host', ); + /** + * Names for headers that can be trusted when + * using trusted proxies. + * + * The FORWARDED header is the standard as of rfc7239. + * + * The other headers are non-standard, but widely used + * by popular reverse proxies (like Apache mod_proxy or Amazon EC2). + */ + private static $trustedHeaders = array( + self::HEADER_FORWARDED => 'FORWARDED', + self::HEADER_X_FORWARDED_FOR => 'X_FORWARDED_FOR', + self::HEADER_X_FORWARDED_HOST => 'X_FORWARDED_HOST', + self::HEADER_X_FORWARDED_PROTO => 'X_FORWARDED_PROTO', + self::HEADER_X_FORWARDED_PORT => 'X_FORWARDED_PORT', + ); + /** * Constructor. * @@ -572,20 +552,9 @@ public function overrideGlobals() * * @throws \InvalidArgumentException When $trustedHeaderSet is invalid */ - public static function setTrustedProxies(array $proxies/*, int $trustedHeaderSet*/) + public static function setTrustedProxies(array $proxies, int $trustedHeaderSet) { self::$trustedProxies = $proxies; - - if (2 > func_num_args()) { - @trigger_error(sprintf('The %s() method expects a bit field of Request::HEADER_* as second argument since version 3.3. Defining it will be required in 4.0. ', __METHOD__), E_USER_DEPRECATED); - - return; - } - $trustedHeaderSet = (int) func_get_arg(1); - - foreach (self::$trustedHeaderNames as $header => $name) { - self::$trustedHeaders[$header] = $header & $trustedHeaderSet ? $name : null; - } self::$trustedHeaderSet = $trustedHeaderSet; } @@ -635,68 +604,6 @@ public static function getTrustedHosts() return self::$trustedHostPatterns; } - /** - * Sets the name for trusted headers. - * - * The following header keys are supported: - * - * * Request::HEADER_CLIENT_IP: defaults to X-Forwarded-For (see getClientIp()) - * * Request::HEADER_CLIENT_HOST: defaults to X-Forwarded-Host (see getHost()) - * * Request::HEADER_CLIENT_PORT: defaults to X-Forwarded-Port (see getPort()) - * * Request::HEADER_CLIENT_PROTO: defaults to X-Forwarded-Proto (see getScheme() and isSecure()) - * * Request::HEADER_FORWARDED: defaults to Forwarded (see RFC 7239) - * - * Setting an empty value allows to disable the trusted header for the given key. - * - * @param string $key The header key - * @param string $value The header name - * - * @throws \InvalidArgumentException - * - * @deprecated since version 3.3, to be removed in 4.0. Use the $trustedHeaderSet argument of the Request::setTrustedProxies() method instead. - */ - public static function setTrustedHeaderName($key, $value) - { - @trigger_error(sprintf('The "%s()" method is deprecated since version 3.3 and will be removed in 4.0. Use the $trustedHeaderSet argument of the Request::setTrustedProxies() method instead.', __METHOD__), E_USER_DEPRECATED); - - if (!array_key_exists($key, self::$trustedHeaders)) { - throw new \InvalidArgumentException(sprintf('Unable to set the trusted header name for key "%s".', $key)); - } - - self::$trustedHeaders[$key] = $value; - - if (null !== $value) { - self::$trustedHeaderNames[$key] = $value; - self::$trustedHeaderSet |= $key; - } else { - self::$trustedHeaderSet &= ~$key; - } - } - - /** - * Gets the trusted proxy header name. - * - * @param string $key The header key - * - * @return string The header name - * - * @throws \InvalidArgumentException - * - * @deprecated since version 3.3, to be removed in 4.0. Use the Request::getTrustedHeaderSet() method instead. - */ - public static function getTrustedHeaderName($key) - { - if (2 > func_num_args() || func_get_arg(1)) { - @trigger_error(sprintf('The "%s()" method is deprecated since version 3.3 and will be removed in 4.0. Use the Request::getTrustedHeaderSet() method instead.', __METHOD__), E_USER_DEPRECATED); - } - - if (!array_key_exists($key, self::$trustedHeaders)) { - throw new \InvalidArgumentException(sprintf('Unable to get the trusted header name for key "%s".', $key)); - } - - return self::$trustedHeaders[$key]; - } - /** * Normalizes a query string. * @@ -864,7 +771,7 @@ public function getClientIps() return array($ip); } - return $this->getTrustedValues(self::HEADER_CLIENT_IP, $ip) ?: array($ip); + return $this->getTrustedValues(self::HEADER_X_FORWARDED_FOR, $ip) ?: array($ip); } /** @@ -991,9 +898,9 @@ public function getScheme() */ public function getPort() { - if ($this->isFromTrustedProxy() && $host = $this->getTrustedValues(self::HEADER_CLIENT_PORT)) { + if ($this->isFromTrustedProxy() && $host = $this->getTrustedValues(self::HEADER_X_FORWARDED_PORT)) { $host = $host[0]; - } elseif ($this->isFromTrustedProxy() && $host = $this->getTrustedValues(self::HEADER_CLIENT_HOST)) { + } elseif ($this->isFromTrustedProxy() && $host = $this->getTrustedValues(self::HEADER_X_FORWARDED_HOST)) { $host = $host[0]; } elseif (!$host = $this->headers->get('HOST')) { return $this->server->get('SERVER_PORT'); @@ -1209,7 +1116,7 @@ public function getQueryString() */ public function isSecure() { - if ($this->isFromTrustedProxy() && $proto = $this->getTrustedValues(self::HEADER_CLIENT_PROTO)) { + if ($this->isFromTrustedProxy() && $proto = $this->getTrustedValues(self::HEADER_X_FORWARDED_PROTO)) { return in_array(strtolower($proto[0]), array('https', 'on', 'ssl', '1'), true); } @@ -1236,7 +1143,7 @@ public function isSecure() */ public function getHost() { - if ($this->isFromTrustedProxy() && $host = $this->getTrustedValues(self::HEADER_CLIENT_HOST)) { + if ($this->isFromTrustedProxy() && $host = $this->getTrustedValues(self::HEADER_X_FORWARDED_HOST)) { $host = $host[0]; } elseif (!$host = $this->headers->get('HOST')) { if (!$host = $this->server->get('SERVER_NAME')) { @@ -1526,11 +1433,8 @@ public function isMethod($method) public function isMethodSafe(/* $andCacheable = true */) { if (!func_num_args() || func_get_arg(0)) { - // This deprecation should be turned into a BadMethodCallException in 4.0 (without adding the argument in the signature) - // then setting $andCacheable to false should be deprecated in 4.1 - @trigger_error('Checking only for cacheable HTTP methods with Symfony\Component\HttpFoundation\Request::isMethodSafe() is deprecated since version 3.2 and will throw an exception in 4.0. Disable checking only for cacheable methods by calling the method with `false` as first argument or use the Request::isMethodCacheable() instead.', E_USER_DEPRECATED); - - return in_array($this->getMethod(), array('GET', 'HEAD')); + // setting $andCacheable to false should be deprecated in 4.1 + throw new \BadMethodCallException('Checking only for cacheable HTTP methods with Symfony\Component\HttpFoundation\Request::isMethodSafe() is not supported.', E_USER_DEPRECATED); } return in_array($this->getMethod(), array('GET', 'HEAD', 'OPTIONS', 'TRACE')); @@ -2022,7 +1926,7 @@ private function getTrustedValues($type, $ip = null) if (self::$trustedHeaders[$type] && $this->headers->has(self::$trustedHeaders[$type])) { foreach (explode(',', $this->headers->get(self::$trustedHeaders[$type])) as $v) { - $clientValues[] = (self::HEADER_CLIENT_PORT === $type ? '0.0.0.0:' : '').trim($v); + $clientValues[] = (self::HEADER_X_FORWARDED_PORT === $type ? '0.0.0.0:' : '').trim($v); } } diff --git a/src/Symfony/Component/HttpFoundation/Tests/RequestTest.php b/src/Symfony/Component/HttpFoundation/Tests/RequestTest.php index 789fa7c8970ae..703857b00b81b 100644 --- a/src/Symfony/Component/HttpFoundation/Tests/RequestTest.php +++ b/src/Symfony/Component/HttpFoundation/Tests/RequestTest.php @@ -1711,53 +1711,6 @@ public function testTrustedProxiesXForwardedFor() $this->assertTrue($request->isSecure()); } - /** - * @group legacy - * @expectedDeprecation The "Symfony\Component\HttpFoundation\Request::setTrustedHeaderName()" method is deprecated since version 3.3 and will be removed in 4.0. Use the $trustedHeaderSet argument of the Request::setTrustedProxies() method instead. - */ - public function testLegacyTrustedProxies() - { - $request = Request::create('http://example.com/'); - $request->server->set('REMOTE_ADDR', '3.3.3.3'); - $request->headers->set('X_FORWARDED_FOR', '1.1.1.1, 2.2.2.2'); - $request->headers->set('X_FORWARDED_HOST', 'foo.example.com, real.example.com:8080'); - $request->headers->set('X_FORWARDED_PROTO', 'https'); - $request->headers->set('X_FORWARDED_PORT', 443); - $request->headers->set('X_MY_FOR', '3.3.3.3, 4.4.4.4'); - $request->headers->set('X_MY_HOST', 'my.example.com'); - $request->headers->set('X_MY_PROTO', 'http'); - $request->headers->set('X_MY_PORT', 81); - - Request::setTrustedProxies(array('3.3.3.3', '2.2.2.2'), Request::HEADER_X_FORWARDED_ALL); - - // custom header names - Request::setTrustedHeaderName(Request::HEADER_CLIENT_IP, 'X_MY_FOR'); - Request::setTrustedHeaderName(Request::HEADER_CLIENT_HOST, 'X_MY_HOST'); - Request::setTrustedHeaderName(Request::HEADER_CLIENT_PORT, 'X_MY_PORT'); - Request::setTrustedHeaderName(Request::HEADER_CLIENT_PROTO, 'X_MY_PROTO'); - $this->assertEquals('4.4.4.4', $request->getClientIp()); - $this->assertEquals('my.example.com', $request->getHost()); - $this->assertEquals(81, $request->getPort()); - $this->assertFalse($request->isSecure()); - - // disabling via empty header names - Request::setTrustedHeaderName(Request::HEADER_CLIENT_IP, null); - Request::setTrustedHeaderName(Request::HEADER_CLIENT_HOST, null); - Request::setTrustedHeaderName(Request::HEADER_CLIENT_PORT, null); - Request::setTrustedHeaderName(Request::HEADER_CLIENT_PROTO, null); - $this->assertEquals('3.3.3.3', $request->getClientIp()); - $this->assertEquals('example.com', $request->getHost()); - $this->assertEquals(80, $request->getPort()); - $this->assertFalse($request->isSecure()); - - //reset - Request::setTrustedHeaderName(Request::HEADER_FORWARDED, 'FORWARDED'); - Request::setTrustedHeaderName(Request::HEADER_CLIENT_IP, 'X_FORWARDED_FOR'); - Request::setTrustedHeaderName(Request::HEADER_CLIENT_HOST, 'X_FORWARDED_HOST'); - Request::setTrustedHeaderName(Request::HEADER_CLIENT_PORT, 'X_FORWARDED_PORT'); - Request::setTrustedHeaderName(Request::HEADER_CLIENT_PROTO, 'X_FORWARDED_PROTO'); - } - public function testTrustedProxiesForwarded() { $request = Request::create('http://example.com/'); @@ -1807,26 +1760,6 @@ public function testTrustedProxiesForwarded() $this->assertTrue($request->isSecure()); } - /** - * @group legacy - * @expectedException \InvalidArgumentException - */ - public function testSetTrustedProxiesInvalidHeaderName() - { - Request::create('http://example.com/'); - Request::setTrustedHeaderName('bogus name', 'X_MY_FOR'); - } - - /** - * @group legacy - * @expectedException \InvalidArgumentException - */ - public function testGetTrustedProxiesInvalidHeaderName() - { - Request::create('http://example.com/'); - Request::getTrustedHeaderName('bogus name'); - } - /** * @dataProvider iisRequestUriProvider */ @@ -2082,14 +2015,13 @@ public function methodSafeProvider() } /** - * @group legacy - * @expectedDeprecation Checking only for cacheable HTTP methods with Symfony\Component\HttpFoundation\Request::isMethodSafe() is deprecated since version 3.2 and will throw an exception in 4.0. Disable checking only for cacheable methods by calling the method with `false` as first argument or use the Request::isMethodCacheable() instead. + * @expectedException \BadMethodCallException */ public function testMethodSafeChecksCacheable() { $request = new Request(); $request->setMethod('OPTIONS'); - $this->assertFalse($request->isMethodSafe()); + $request->isMethodSafe(); } /** @@ -2117,61 +2049,6 @@ public function methodCacheableProvider() array('CONNECT', false), ); } - - /** - * @group legacy - */ - public function testGetTrustedHeaderName() - { - Request::setTrustedProxies(array('8.8.8.8'), Request::HEADER_X_FORWARDED_ALL); - - $this->assertNull(Request::getTrustedHeaderName(Request::HEADER_FORWARDED)); - $this->assertSame('X_FORWARDED_FOR', Request::getTrustedHeaderName(Request::HEADER_CLIENT_IP)); - $this->assertSame('X_FORWARDED_HOST', Request::getTrustedHeaderName(Request::HEADER_CLIENT_HOST)); - $this->assertSame('X_FORWARDED_PORT', Request::getTrustedHeaderName(Request::HEADER_CLIENT_PORT)); - $this->assertSame('X_FORWARDED_PROTO', Request::getTrustedHeaderName(Request::HEADER_CLIENT_PROTO)); - - Request::setTrustedProxies(array('8.8.8.8'), Request::HEADER_FORWARDED); - - $this->assertSame('FORWARDED', Request::getTrustedHeaderName(Request::HEADER_FORWARDED)); - $this->assertNull(Request::getTrustedHeaderName(Request::HEADER_CLIENT_IP)); - $this->assertNull(Request::getTrustedHeaderName(Request::HEADER_CLIENT_HOST)); - $this->assertNull(Request::getTrustedHeaderName(Request::HEADER_CLIENT_PORT)); - $this->assertNull(Request::getTrustedHeaderName(Request::HEADER_CLIENT_PROTO)); - - Request::setTrustedHeaderName(Request::HEADER_FORWARDED, 'A'); - Request::setTrustedHeaderName(Request::HEADER_CLIENT_IP, 'B'); - Request::setTrustedHeaderName(Request::HEADER_CLIENT_HOST, 'C'); - Request::setTrustedHeaderName(Request::HEADER_CLIENT_PORT, 'D'); - Request::setTrustedHeaderName(Request::HEADER_CLIENT_PROTO, 'E'); - - Request::setTrustedProxies(array('8.8.8.8'), Request::HEADER_FORWARDED); - - $this->assertSame('A', Request::getTrustedHeaderName(Request::HEADER_FORWARDED)); - $this->assertNull(Request::getTrustedHeaderName(Request::HEADER_CLIENT_IP)); - $this->assertNull(Request::getTrustedHeaderName(Request::HEADER_CLIENT_HOST)); - $this->assertNull(Request::getTrustedHeaderName(Request::HEADER_CLIENT_PORT)); - $this->assertNull(Request::getTrustedHeaderName(Request::HEADER_CLIENT_PROTO)); - - Request::setTrustedProxies(array('8.8.8.8'), Request::HEADER_X_FORWARDED_ALL); - - $this->assertNull(Request::getTrustedHeaderName(Request::HEADER_FORWARDED)); - $this->assertSame('B', Request::getTrustedHeaderName(Request::HEADER_CLIENT_IP)); - $this->assertSame('C', Request::getTrustedHeaderName(Request::HEADER_CLIENT_HOST)); - $this->assertSame('D', Request::getTrustedHeaderName(Request::HEADER_CLIENT_PORT)); - $this->assertSame('E', Request::getTrustedHeaderName(Request::HEADER_CLIENT_PROTO)); - - Request::setTrustedProxies(array('8.8.8.8'), Request::HEADER_FORWARDED); - - $this->assertSame('A', Request::getTrustedHeaderName(Request::HEADER_FORWARDED)); - - //reset - Request::setTrustedHeaderName(Request::HEADER_FORWARDED, 'FORWARDED'); - Request::setTrustedHeaderName(Request::HEADER_CLIENT_IP, 'X_FORWARDED_FOR'); - Request::setTrustedHeaderName(Request::HEADER_CLIENT_HOST, 'X_FORWARDED_HOST'); - Request::setTrustedHeaderName(Request::HEADER_CLIENT_PORT, 'X_FORWARDED_PORT'); - Request::setTrustedHeaderName(Request::HEADER_CLIENT_PROTO, 'X_FORWARDED_PROTO'); - } } class RequestContentProxy extends Request diff --git a/src/Symfony/Component/HttpKernel/Fragment/InlineFragmentRenderer.php b/src/Symfony/Component/HttpKernel/Fragment/InlineFragmentRenderer.php index 437b40bf95953..2365f922ee696 100644 --- a/src/Symfony/Component/HttpKernel/Fragment/InlineFragmentRenderer.php +++ b/src/Symfony/Component/HttpKernel/Fragment/InlineFragmentRenderer.php @@ -115,21 +115,10 @@ protected function createSubRequest($uri, Request $request) $cookies = $request->cookies->all(); $server = $request->server->all(); - // Override the arguments to emulate a sub-request. - // Sub-request object will point to localhost as client ip and real client ip - // will be included into trusted header for client ip - try { - if (Request::HEADER_X_FORWARDED_FOR & Request::getTrustedHeaderSet()) { - $currentXForwardedFor = $request->headers->get('X_FORWARDED_FOR', ''); - - $server['HTTP_X_FORWARDED_FOR'] = ($currentXForwardedFor ? $currentXForwardedFor.', ' : '').$request->getClientIp(); - } elseif (method_exists(Request::class, 'getTrustedHeaderName') && $trustedHeaderName = Request::getTrustedHeaderName(Request::HEADER_CLIENT_IP, false)) { - $currentXForwardedFor = $request->headers->get($trustedHeaderName, ''); + if (Request::HEADER_X_FORWARDED_FOR & Request::getTrustedHeaderSet()) { + $currentXForwardedFor = $request->headers->get('X_FORWARDED_FOR', ''); - $server['HTTP_'.$trustedHeaderName] = ($currentXForwardedFor ? $currentXForwardedFor.', ' : '').$request->getClientIp(); - } - } catch (\InvalidArgumentException $e) { - // Do nothing + $server['HTTP_X_FORWARDED_FOR'] = ($currentXForwardedFor ? $currentXForwardedFor.', ' : '').$request->getClientIp(); } $server['REMOTE_ADDR'] = '127.0.0.1'; From 408a33e99b285ee50d78cbf55f131d0198e48dca Mon Sep 17 00:00:00 2001 From: Robin Chalas Date: Tue, 20 Jun 2017 22:35:44 +0200 Subject: [PATCH 0259/1099] [Dotenv] Make load() variadic --- src/Symfony/Component/Dotenv/Dotenv.php | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Component/Dotenv/Dotenv.php b/src/Symfony/Component/Dotenv/Dotenv.php index 1e665fb537a70..1c4c2fd2128dd 100644 --- a/src/Symfony/Component/Dotenv/Dotenv.php +++ b/src/Symfony/Component/Dotenv/Dotenv.php @@ -45,10 +45,11 @@ final class Dotenv * @throws FormatException when a file has a syntax error * @throws PathException when a file does not exist or is not readable */ - public function load($path/*, ...$paths*/) + public function load($path, ...$paths) { - // func_get_args() to be replaced by a variadic argument for Symfony 4.0 - foreach (func_get_args() as $path) { + array_unshift($paths, $path); + + foreach ($paths as $path) { if (!is_readable($path) || is_dir($path)) { throw new PathException($path); } From 0ee3f57533aededf488e326bc0b30ca54d8dd1e2 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Wed, 21 Jun 2017 18:08:25 +0200 Subject: [PATCH 0260/1099] render hidden _method field in form_rest() --- .../views/Form/form_div_layout.html.twig | 15 +++++++++++++++ src/Symfony/Bridge/Twig/composer.json | 5 ++++- src/Symfony/Component/Form/FormView.php | 15 +++++++++++++++ 3 files changed, 34 insertions(+), 1 deletion(-) 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 04988d1539b24..0a52cc5110c82 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 @@ -262,6 +262,7 @@ {%- endblock form -%} {%- block form_start -%} + {%- do form.setMethodRendered() -%} {% set method = method|upper %} {%- if method in ["GET", "POST"] -%} {% set form_method = method %} @@ -301,6 +302,20 @@ {{- form_row(child) -}} {% endif %} {%- endfor %} + + {% if not form.methodRendered %} + {%- do form.setMethodRendered() -%} + {% set method = method|upper %} + {%- if method in ["GET", "POST"] -%} + {% set form_method = method %} + {%- else -%} + {% set form_method = "POST" %} + {%- endif -%} + + {%- if form_method != method -%} + + {%- endif -%} + {% endif %} {% endblock form_rest %} {# Support #} diff --git a/src/Symfony/Bridge/Twig/composer.json b/src/Symfony/Bridge/Twig/composer.json index 3b6c4356e14ba..9610edc8085b5 100644 --- a/src/Symfony/Bridge/Twig/composer.json +++ b/src/Symfony/Bridge/Twig/composer.json @@ -22,7 +22,7 @@ "require-dev": { "symfony/asset": "~2.7", "symfony/finder": "~2.3", - "symfony/form": "~2.7.26|^2.8.19", + "symfony/form": "~2.7.30|^2.8.23", "symfony/http-kernel": "~2.3", "symfony/intl": "~2.3", "symfony/routing": "~2.2", @@ -36,6 +36,9 @@ "symfony/var-dumper": "~2.7.16|^2.8.9", "symfony/expression-language": "~2.4" }, + "conflict": { + "symfony/form": "<2.7.30|~2.8,<2.8.23" + }, "suggest": { "symfony/finder": "", "symfony/asset": "For using the AssetExtension", diff --git a/src/Symfony/Component/Form/FormView.php b/src/Symfony/Component/Form/FormView.php index c1da5f8fc9bb1..8655bedf6e135 100644 --- a/src/Symfony/Component/Form/FormView.php +++ b/src/Symfony/Component/Form/FormView.php @@ -53,6 +53,8 @@ class FormView implements \ArrayAccess, \IteratorAggregate, \Countable */ private $rendered = false; + private $methodRendered = false; + public function __construct(FormView $parent = null) { $this->parent = $parent; @@ -90,6 +92,19 @@ public function setRendered() return $this; } + /** + * @return bool + */ + public function isMethodRendered() + { + return $this->methodRendered; + } + + public function setMethodRendered() + { + $this->methodRendered = true; + } + /** * Returns a child by name (implements \ArrayAccess). * From a3253f6db686adbaca39e0e034af49e7ab293ab2 Mon Sep 17 00:00:00 2001 From: Yonel Ceruto Date: Thu, 1 Jun 2017 20:08:36 -0400 Subject: [PATCH 0261/1099] [SecurityBundle] Add user impersonation info and exit action to the profiler --- .../DataCollector/SecurityDataCollector.php | 43 ++++++++++ .../DependencyInjection/SecurityExtension.php | 1 + .../Resources/config/security.xml | 1 + .../views/Collector/security.html.twig | 80 +++++++++++-------- .../Security/FirewallConfig.php | 13 ++- .../SecurityDataCollectorTest.php | 37 +++++++++ .../CompleteConfigurationTest.php | 6 ++ .../Tests/Functional/SwitchUserTest.php | 4 +- .../Tests/Security/FirewallConfigTest.php | 5 +- .../Http/Firewall/SwitchUserListener.php | 4 +- .../Tests/Firewall/SwitchUserListenerTest.php | 8 +- 11 files changed, 162 insertions(+), 40 deletions(-) diff --git a/src/Symfony/Bundle/SecurityBundle/DataCollector/SecurityDataCollector.php b/src/Symfony/Bundle/SecurityBundle/DataCollector/SecurityDataCollector.php index d25a5be606ec9..7549c718f6204 100644 --- a/src/Symfony/Bundle/SecurityBundle/DataCollector/SecurityDataCollector.php +++ b/src/Symfony/Bundle/SecurityBundle/DataCollector/SecurityDataCollector.php @@ -20,6 +20,8 @@ use Symfony\Component\HttpKernel\DataCollector\LateDataCollectorInterface; use Symfony\Component\Security\Core\Role\RoleInterface; use Symfony\Bundle\SecurityBundle\Debug\TraceableFirewallListener; +use Symfony\Component\Security\Core\Role\SwitchUserRole; +use Symfony\Component\Security\Http\Firewall\SwitchUserListener; use Symfony\Component\Security\Http\Logout\LogoutUrlGenerator; use Symfony\Component\Security\Core\Authorization\AccessDecisionManagerInterface; use Symfony\Component\Security\Core\Authorization\TraceableAccessDecisionManager; @@ -73,6 +75,9 @@ public function collect(Request $request, Response $response, \Exception $except $this->data = array( 'enabled' => false, 'authenticated' => false, + 'impersonated' => false, + 'impersonator_user' => null, + 'impersonation_exit_path' => null, 'token' => null, 'token_class' => null, 'logout_url' => null, @@ -85,6 +90,9 @@ public function collect(Request $request, Response $response, \Exception $except $this->data = array( 'enabled' => true, 'authenticated' => false, + 'impersonated' => false, + 'impersonator_user' => null, + 'impersonation_exit_path' => null, 'token' => null, 'token_class' => null, 'logout_url' => null, @@ -97,6 +105,14 @@ public function collect(Request $request, Response $response, \Exception $except $inheritedRoles = array(); $assignedRoles = $token->getRoles(); + $impersonatorUser = null; + foreach ($assignedRoles as $role) { + if ($role instanceof SwitchUserRole) { + $impersonatorUser = $role->getSource()->getUsername(); + break; + } + } + if (null !== $this->roleHierarchy) { $allRoles = $this->roleHierarchy->getReachableRoles($assignedRoles); foreach ($allRoles as $role) { @@ -126,6 +142,9 @@ public function collect(Request $request, Response $response, \Exception $except $this->data = array( 'enabled' => true, 'authenticated' => $token->isAuthenticated(), + 'impersonated' => null !== $impersonatorUser, + 'impersonator_user' => $impersonatorUser, + 'impersonation_exit_path' => null, 'token' => $token, 'token_class' => $this->hasVarDumper ? new ClassStub(get_class($token)) : get_class($token), 'logout_url' => $logoutUrl, @@ -169,6 +188,15 @@ public function collect(Request $request, Response $response, \Exception $except 'user_checker' => $firewallConfig->getUserChecker(), 'listeners' => $firewallConfig->getListeners(), ); + + // generate exit impersonation path from current request + if ($this->data['impersonated'] && null !== $switchUserConfig = $firewallConfig->getSwitchUser()) { + $exitPath = $request->getRequestUri(); + $exitPath .= null === $request->getQueryString() ? '?' : '&'; + $exitPath .= sprintf('%s=%s', urlencode($switchUserConfig['parameter']), SwitchUserListener::EXIT_VALUE); + + $this->data['impersonation_exit_path'] = $exitPath; + } } } @@ -245,6 +273,21 @@ public function isAuthenticated() return $this->data['authenticated']; } + public function isImpersonated() + { + return $this->data['impersonated']; + } + + public function getImpersonatorUser() + { + return $this->data['impersonator_user']; + } + + public function getImpersonationExitPath() + { + return $this->data['impersonation_exit_path']; + } + /** * Get the class name of the security token. * diff --git a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php index 6209d763cd81a..82aa222a759f7 100644 --- a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php +++ b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php @@ -448,6 +448,7 @@ private function createFirewall(ContainerBuilder $container, $id, $firewall, &$a } $config->replaceArgument(10, $listenerKeys); + $config->replaceArgument(11, isset($firewall['switch_user']) ? $firewall['switch_user'] : null); return array($matcher, $listeners, $exceptionListener); } diff --git a/src/Symfony/Bundle/SecurityBundle/Resources/config/security.xml b/src/Symfony/Bundle/SecurityBundle/Resources/config/security.xml index 79435ff5d4619..9b31ae84439d7 100644 --- a/src/Symfony/Bundle/SecurityBundle/Resources/config/security.xml +++ b/src/Symfony/Bundle/SecurityBundle/Resources/config/security.xml @@ -136,6 +136,7 @@ + diff --git a/src/Symfony/Bundle/SecurityBundle/Resources/views/Collector/security.html.twig b/src/Symfony/Bundle/SecurityBundle/Resources/views/Collector/security.html.twig index 46804a4d2ed2e..eb40758489d02 100644 --- a/src/Symfony/Bundle/SecurityBundle/Resources/views/Collector/security.html.twig +++ b/src/Symfony/Bundle/SecurityBundle/Resources/views/Collector/security.html.twig @@ -16,47 +16,63 @@ {% endset %} {% set text %} - {% if collector.enabled %} - {% if collector.token %} + {% if collector.impersonated %} +
- Logged in as - {{ collector.user }} + Impersonator + {{ collector.impersonatorUser }}
+
+ {% endif %} -
- Authenticated - {{ is_authenticated ? 'Yes' : 'No' }} -
+
+ {% if collector.enabled %} + {% if collector.token %} +
+ Logged in as + {{ collector.user }} +
-
- Token class - {{ collector.tokenClass|abbr_class }} -
- {% else %} -
- Authenticated - No -
- {% endif %} +
+ Authenticated + {{ is_authenticated ? 'Yes' : 'No' }} +
- {% if collector.firewall %} -
- Firewall name - {{ collector.firewall.name }} -
- {% endif %} +
+ Token class + {{ collector.tokenClass|abbr_class }} +
+ {% else %} +
+ Authenticated + No +
+ {% endif %} + + {% if collector.firewall %} +
+ Firewall name + {{ collector.firewall.name }} +
+ {% endif %} - {% if collector.token and collector.logoutUrl %} + {% if collector.token and collector.logoutUrl %} +
+ Actions + + Logout + {% if collector.impersonated and collector.impersonationExitPath %} + | Exit impersonation + {% endif %} + +
+ {% endif %} + {% else %}
- Actions - Logout + The security is disabled.
{% endif %} - {% else %} -
- The security is disabled. -
- {% endif %} +
{% endset %} {{ include('@WebProfiler/Profiler/toolbar_item.html.twig', { link: profiler_url, status: color_code }) }} diff --git a/src/Symfony/Bundle/SecurityBundle/Security/FirewallConfig.php b/src/Symfony/Bundle/SecurityBundle/Security/FirewallConfig.php index 3cfb11404ccf8..62317f625c271 100644 --- a/src/Symfony/Bundle/SecurityBundle/Security/FirewallConfig.php +++ b/src/Symfony/Bundle/SecurityBundle/Security/FirewallConfig.php @@ -27,6 +27,7 @@ final class FirewallConfig private $accessDeniedHandler; private $accessDeniedUrl; private $listeners; + private $switchUser; /** * @param string $name @@ -40,8 +41,9 @@ final class FirewallConfig * @param string|null $accessDeniedHandler * @param string|null $accessDeniedUrl * @param string[] $listeners + * @param array|null $switchUser */ - public function __construct($name, $userChecker, $requestMatcher = null, $securityEnabled = true, $stateless = false, $provider = null, $context = null, $entryPoint = null, $accessDeniedHandler = null, $accessDeniedUrl = null, $listeners = array()) + public function __construct($name, $userChecker, $requestMatcher = null, $securityEnabled = true, $stateless = false, $provider = null, $context = null, $entryPoint = null, $accessDeniedHandler = null, $accessDeniedUrl = null, $listeners = array(), $switchUser = null) { $this->name = $name; $this->userChecker = $userChecker; @@ -54,6 +56,7 @@ public function __construct($name, $userChecker, $requestMatcher = null, $securi $this->accessDeniedHandler = $accessDeniedHandler; $this->accessDeniedUrl = $accessDeniedUrl; $this->listeners = $listeners; + $this->switchUser = $switchUser; } public function getName() @@ -140,4 +143,12 @@ public function getListeners() { return $this->listeners; } + + /** + * @return array|null The switch_user parameters if configured, null otherwise + */ + public function getSwitchUser() + { + return $this->switchUser; + } } diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DataCollector/SecurityDataCollectorTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/DataCollector/SecurityDataCollectorTest.php index 1c75641daf697..58809ef56f8da 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/DataCollector/SecurityDataCollectorTest.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DataCollector/SecurityDataCollectorTest.php @@ -24,6 +24,7 @@ use Symfony\Component\Security\Core\Role\Role; use Symfony\Component\Security\Core\Role\RoleHierarchy; use Symfony\Component\Security\Http\Firewall\ListenerInterface; +use Symfony\Component\Security\Core\Role\SwitchUserRole; use Symfony\Component\Security\Http\FirewallMapInterface; use Symfony\Component\Security\Http\Logout\LogoutUrlGenerator; @@ -37,6 +38,9 @@ public function testCollectWhenSecurityIsDisabled() $this->assertSame('security', $collector->getName()); $this->assertFalse($collector->isEnabled()); $this->assertFalse($collector->isAuthenticated()); + $this->assertFalse($collector->isImpersonated()); + $this->assertNull($collector->getImpersonatorUser()); + $this->assertNull($collector->getImpersonationExitPath()); $this->assertNull($collector->getTokenClass()); $this->assertFalse($collector->supportsRoleHierarchy()); $this->assertCount(0, $collector->getRoles()); @@ -53,6 +57,9 @@ public function testCollectWhenAuthenticationTokenIsNull() $this->assertTrue($collector->isEnabled()); $this->assertFalse($collector->isAuthenticated()); + $this->assertFalse($collector->isImpersonated()); + $this->assertNull($collector->getImpersonatorUser()); + $this->assertNull($collector->getImpersonationExitPath()); $this->assertNull($collector->getTokenClass()); $this->assertTrue($collector->supportsRoleHierarchy()); $this->assertCount(0, $collector->getRoles()); @@ -73,6 +80,9 @@ public function testCollectAuthenticationTokenAndRoles(array $roles, array $norm $this->assertTrue($collector->isEnabled()); $this->assertTrue($collector->isAuthenticated()); + $this->assertFalse($collector->isImpersonated()); + $this->assertNull($collector->getImpersonatorUser()); + $this->assertNull($collector->getImpersonationExitPath()); $this->assertSame('Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken', $collector->getTokenClass()->getValue()); $this->assertTrue($collector->supportsRoleHierarchy()); $this->assertSame($normalizedRoles, $collector->getRoles()->getValue(true)); @@ -80,6 +90,33 @@ public function testCollectAuthenticationTokenAndRoles(array $roles, array $norm $this->assertSame('hhamon', $collector->getUser()); } + public function testCollectImpersonatedToken() + { + $adminToken = new UsernamePasswordToken('yceruto', 'P4$$w0rD', 'provider', array('ROLE_ADMIN')); + + $userRoles = array( + 'ROLE_USER', + new SwitchUserRole('ROLE_PREVIOUS_ADMIN', $adminToken), + ); + + $tokenStorage = new TokenStorage(); + $tokenStorage->setToken(new UsernamePasswordToken('hhamon', 'P4$$w0rD', 'provider', $userRoles)); + + $collector = new SecurityDataCollector($tokenStorage, $this->getRoleHierarchy()); + $collector->collect($this->getRequest(), $this->getResponse()); + $collector->lateCollect(); + + $this->assertTrue($collector->isEnabled()); + $this->assertTrue($collector->isAuthenticated()); + $this->assertTrue($collector->isImpersonated()); + $this->assertSame('yceruto', $collector->getImpersonatorUser()); + $this->assertSame('Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken', $collector->getTokenClass()->getValue()); + $this->assertTrue($collector->supportsRoleHierarchy()); + $this->assertSame(array('ROLE_USER', 'ROLE_PREVIOUS_ADMIN'), $collector->getRoles()->getValue(true)); + $this->assertSame(array(), $collector->getInheritedRoles()->getValue(true)); + $this->assertSame('hhamon', $collector->getUser()); + } + public function testGetFirewall() { $firewallConfig = new FirewallConfig('dummy', 'security.request_matcher.dummy', 'security.user_checker.dummy'); diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/CompleteConfigurationTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/CompleteConfigurationTest.php index 220e39b09a723..c2598b51ff927 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/CompleteConfigurationTest.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/CompleteConfigurationTest.php @@ -107,6 +107,10 @@ public function testFirewalls() 'remember_me', 'anonymous', ), + array( + 'parameter' => '_switch_user', + 'role' => 'ROLE_ALLOWED_TO_SWITCH', + ), ), array( 'host', @@ -123,6 +127,7 @@ public function testFirewalls() 'http_basic', 'anonymous', ), + null, ), array( 'with_user_checker', @@ -139,6 +144,7 @@ public function testFirewalls() 'http_basic', 'anonymous', ), + null, ), ), $configs); diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/SwitchUserTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/SwitchUserTest.php index f12e95671be2c..697829b1cb75a 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/SwitchUserTest.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/SwitchUserTest.php @@ -11,6 +11,8 @@ namespace Symfony\Bundle\SecurityBundle\Tests\Functional; +use Symfony\Component\Security\Http\Firewall\SwitchUserListener; + class SwitchUserTest extends WebTestCase { /** @@ -42,7 +44,7 @@ public function testSwitchedUserExit() $client = $this->createAuthenticatedClient('user_can_switch'); $client->request('GET', '/profile?_switch_user=user_cannot_switch_1'); - $client->request('GET', '/profile?_switch_user=_exit'); + $client->request('GET', '/profile?_switch_user='.SwitchUserListener::EXIT_VALUE); $this->assertEquals(200, $client->getResponse()->getStatusCode()); $this->assertEquals('user_can_switch', $client->getProfile()->getCollector('security')->getUser()); diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Security/FirewallConfigTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/Security/FirewallConfigTest.php index a0b4a79c50cdc..4abf33e276694 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/Security/FirewallConfigTest.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/Security/FirewallConfigTest.php @@ -29,6 +29,7 @@ public function testGetters() 'access_denied_url' => 'foo_access_denied_url', 'access_denied_handler' => 'foo_access_denied_handler', 'user_checker' => 'foo_user_checker', + 'switch_user' => array('provider' => null, 'parameter' => '_switch_user', 'role' => 'ROLE_ALLOWED_TO_SWITCH'), ); $config = new FirewallConfig( @@ -42,7 +43,8 @@ public function testGetters() $options['entry_point'], $options['access_denied_handler'], $options['access_denied_url'], - $listeners + $listeners, + $options['switch_user'] ); $this->assertSame('foo_firewall', $config->getName()); @@ -57,5 +59,6 @@ public function testGetters() $this->assertSame($options['user_checker'], $config->getUserChecker()); $this->assertTrue($config->allowsAnonymous()); $this->assertSame($listeners, $config->getListeners()); + $this->assertSame($options['switch_user'], $config->getSwitchUser()); } } diff --git a/src/Symfony/Component/Security/Http/Firewall/SwitchUserListener.php b/src/Symfony/Component/Security/Http/Firewall/SwitchUserListener.php index e9c3e4068d530..b4f9b3e0782c0 100644 --- a/src/Symfony/Component/Security/Http/Firewall/SwitchUserListener.php +++ b/src/Symfony/Component/Security/Http/Firewall/SwitchUserListener.php @@ -38,6 +38,8 @@ */ class SwitchUserListener implements ListenerInterface { + const EXIT_VALUE = '_exit'; + private $tokenStorage; private $provider; private $userChecker; @@ -80,7 +82,7 @@ public function handle(GetResponseEvent $event) return; } - if ('_exit' === $request->get($this->usernameParameter)) { + if (self::EXIT_VALUE === $request->get($this->usernameParameter)) { $this->tokenStorage->setToken($this->attemptExitUser($request)); } else { try { diff --git a/src/Symfony/Component/Security/Http/Tests/Firewall/SwitchUserListenerTest.php b/src/Symfony/Component/Security/Http/Tests/Firewall/SwitchUserListenerTest.php index 43013520c36ba..3174265c08d08 100644 --- a/src/Symfony/Component/Security/Http/Tests/Firewall/SwitchUserListenerTest.php +++ b/src/Symfony/Component/Security/Http/Tests/Firewall/SwitchUserListenerTest.php @@ -73,7 +73,7 @@ public function testExitUserThrowsAuthenticationExceptionIfOriginalTokenCannotBe $token = new UsernamePasswordToken('username', '', 'key', array('ROLE_FOO')); $this->tokenStorage->setToken($token); - $this->request->query->set('_switch_user', '_exit'); + $this->request->query->set('_switch_user', SwitchUserListener::EXIT_VALUE); $listener = new SwitchUserListener($this->tokenStorage, $this->userProvider, $this->userChecker, 'provider123', $this->accessDecisionManager); $listener->handle($this->event); @@ -84,7 +84,7 @@ public function testExitUserUpdatesToken() $originalToken = new UsernamePasswordToken('username', '', 'key', array()); $this->tokenStorage->setToken(new UsernamePasswordToken('username', '', 'key', array(new SwitchUserRole('ROLE_PREVIOUS', $originalToken)))); - $this->request->query->set('_switch_user', '_exit'); + $this->request->query->set('_switch_user', SwitchUserListener::EXIT_VALUE); $listener = new SwitchUserListener($this->tokenStorage, $this->userProvider, $this->userChecker, 'provider123', $this->accessDecisionManager); $listener->handle($this->event); @@ -108,7 +108,7 @@ public function testExitUserDispatchesEventWithRefreshedUser() ->willReturn($refreshedUser); $originalToken = new UsernamePasswordToken($originalUser, '', 'key'); $this->tokenStorage->setToken(new UsernamePasswordToken('username', '', 'key', array(new SwitchUserRole('ROLE_PREVIOUS', $originalToken)))); - $this->request->query->set('_switch_user', '_exit'); + $this->request->query->set('_switch_user', SwitchUserListener::EXIT_VALUE); $dispatcher = $this->getMockBuilder('Symfony\Component\EventDispatcher\EventDispatcherInterface')->getMock(); $dispatcher @@ -132,7 +132,7 @@ public function testExitUserDoesNotDispatchEventWithStringUser() ->method('refreshUser'); $originalToken = new UsernamePasswordToken($originalUser, '', 'key'); $this->tokenStorage->setToken(new UsernamePasswordToken('username', '', 'key', array(new SwitchUserRole('ROLE_PREVIOUS', $originalToken)))); - $this->request->query->set('_switch_user', '_exit'); + $this->request->query->set('_switch_user', SwitchUserListener::EXIT_VALUE); $dispatcher = $this->getMockBuilder('Symfony\Component\EventDispatcher\EventDispatcherInterface')->getMock(); $dispatcher From 83727c7e3dc7c2929059025dbaa0b2dc4e05d101 Mon Sep 17 00:00:00 2001 From: Thierry Thuon Date: Wed, 3 May 2017 14:00:53 +0200 Subject: [PATCH 0262/1099] [FrameworkBundle][HttpKernel] Move addcachearmer, addcacheclearer compiler pass --- UPGRADE-3.4.md | 8 ++ UPGRADE-4.0.md | 6 ++ .../Bundle/FrameworkBundle/CHANGELOG.md | 2 + .../Compiler/AddCacheClearerPass.php | 26 ++----- .../Compiler/AddCacheWarmerPass.php | 29 ++----- .../FrameworkBundle/FrameworkBundle.php | 4 +- .../Compiler/AddCacheWarmerPassTest.php | 3 + .../Bundle/FrameworkBundle/composer.json | 3 +- src/Symfony/Component/HttpKernel/CHANGELOG.md | 6 ++ .../AddCacheClearerPass.php | 50 ++++++++++++ .../AddCacheWarmerPass.php | 53 +++++++++++++ .../AddCacheClearerPassTest.php | 53 +++++++++++++ .../AddCacheWarmerPassTest.php | 77 +++++++++++++++++++ 13 files changed, 274 insertions(+), 46 deletions(-) create mode 100644 src/Symfony/Component/HttpKernel/DependencyInjection/AddCacheClearerPass.php create mode 100644 src/Symfony/Component/HttpKernel/DependencyInjection/AddCacheWarmerPass.php create mode 100644 src/Symfony/Component/HttpKernel/Tests/DependencyInjection/AddCacheClearerPassTest.php create mode 100644 src/Symfony/Component/HttpKernel/Tests/DependencyInjection/AddCacheWarmerPassTest.php diff --git a/UPGRADE-3.4.md b/UPGRADE-3.4.md index a609da081ccb8..93ca903215d01 100644 --- a/UPGRADE-3.4.md +++ b/UPGRADE-3.4.md @@ -38,6 +38,14 @@ FrameworkBundle will be removed in 4.0. Use the `--prefix` option with an empty string as value instead (e.g. `--prefix=""`) + * The `Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\AddCacheClearerPass` + class has been deprecated and will be removed in 4.0. Use the + `Symfony\Component\HttpKernel\DependencyInjection\AddCacheClearerPass` class instead. + + * The `Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\AddCacheWarmerPass` + class has been deprecated and will be removed in 4.0. Use the + `Symfony\Component\HttpKernel\DependencyInjection\AddCacheWarmerPass` class instead. + Process ------- diff --git a/UPGRADE-4.0.md b/UPGRADE-4.0.md index b1027dc026fad..6bd0dde3aa55c 100644 --- a/UPGRADE-4.0.md +++ b/UPGRADE-4.0.md @@ -348,6 +348,12 @@ FrameworkBundle * The `--no-prefix` option of the `translation:update` command has been removed. + * The `Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\AddCacheClearerPass` class has been removed. + Use the `Symfony\Component\HttpKernel\DependencyInjection\AddCacheClearerPass` class instead. + + * The `Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\AddCacheWarmerPass` class has been removed. + Use the `Symfony\Component\HttpKernel\DependencyInjection\AddCacheWarmerPass` class instead. + HttpFoundation -------------- diff --git a/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md b/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md index c089a8b40a743..6c5c2fd1475fb 100644 --- a/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md +++ b/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md @@ -10,6 +10,8 @@ CHANGELOG require symfony/stopwatch` in your `dev` environment. * Deprecated using the `KERNEL_DIR` environment variable with `KernelTestCase::getKernelClass()`. * Deprecated the `KernelTestCase::getPhpUnitXmlDir()` and `KernelTestCase::getPhpUnitCliConfigArgument()` methods. + * Deprecated `AddCacheClearerPass`, use `Symfony\Component\HttpKernel\DependencyInjection\AddCacheClearerPass` instead. + * Deprecated `AddCacheWarmerPass`, use `Symfony\Component\HttpKernel\DependencyInjection\AddCacheWarmerPass` instead. 3.3.0 ----- diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/AddCacheClearerPass.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/AddCacheClearerPass.php index 88cfffd04f123..c58fd6843d3eb 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/AddCacheClearerPass.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/AddCacheClearerPass.php @@ -11,31 +11,17 @@ namespace Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; -use Symfony\Component\DependencyInjection\Reference; +@trigger_error(sprintf('The %s class is deprecated since version 3.4 and will be removed in 4.0. Use Symfony\Component\HttpKernel\DependencyInjection\AddCacheClearerPass instead.', AddCacheClearerPass::class), E_USER_DEPRECATED); + +use Symfony\Component\HttpKernel\DependencyInjection\AddCacheClearerPass as BaseAddCacheClearerPass; /** * Registers the cache clearers. * + * @deprecated since version 3.4, to be removed in 4.0. Use {@link BaseAddCacheClearerPass instead}. + * * @author Dustin Dobervich */ -class AddCacheClearerPass implements CompilerPassInterface +class AddCacheClearerPass extends BaseAddCacheClearerPass { - /** - * {@inheritdoc} - */ - public function process(ContainerBuilder $container) - { - if (!$container->hasDefinition('cache_clearer')) { - return; - } - - $clearers = array(); - foreach ($container->findTaggedServiceIds('kernel.cache_clearer', true) as $id => $attributes) { - $clearers[] = new Reference($id); - } - - $container->getDefinition('cache_clearer')->replaceArgument(0, $clearers); - } } diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/AddCacheWarmerPass.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/AddCacheWarmerPass.php index 8f5353121ce8b..4b427684a9ed3 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/AddCacheWarmerPass.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/AddCacheWarmerPass.php @@ -11,34 +11,17 @@ namespace Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler; -use Symfony\Component\DependencyInjection\Compiler\PriorityTaggedServiceTrait; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; +@trigger_error(sprintf('The %s class is deprecated since version 3.4 and will be removed in 4.0. Use Symfony\Component\HttpKernel\DependencyInjection\AddCacheWarmerPass instead.', AddCacheWarmerPass::class), E_USER_DEPRECATED); + +use Symfony\Component\HttpKernel\DependencyInjection\AddCacheWarmerPass as BaseAddCacheWarmerPass; /** * Registers the cache warmers. * + * @deprecated since version 3.4, to be removed in 4.0. Use {@link BaseAddCacheWarmerPass instead}. + * * @author Fabien Potencier */ -class AddCacheWarmerPass implements CompilerPassInterface +class AddCacheWarmerPass extends BaseAddCacheWarmerPass { - use PriorityTaggedServiceTrait; - - /** - * {@inheritdoc} - */ - public function process(ContainerBuilder $container) - { - if (!$container->hasDefinition('cache_warmer')) { - return; - } - - $warmers = $this->findAndSortTaggedServices('kernel.cache_warmer', $container); - - if (empty($warmers)) { - return; - } - - $container->getDefinition('cache_warmer')->replaceArgument(0, $warmers); - } } diff --git a/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php b/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php index 99ab06b337772..ccf59ee4f8f1b 100644 --- a/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php +++ b/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php @@ -21,8 +21,6 @@ use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\ProfilerPass; use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\TranslatorPass; use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\LoggingTranslatorPass; -use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\AddCacheWarmerPass; -use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\AddCacheClearerPass; use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\AddExpressionLanguageProvidersPass; use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\ContainerBuilderDebugDumpPass; use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\TranslationExtractorPass; @@ -30,6 +28,8 @@ use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\UnusedTagsPass; use Symfony\Component\Config\DependencyInjection\ConfigCachePass; use Symfony\Component\Console\DependencyInjection\AddConsoleCommandPass; +use Symfony\Component\HttpKernel\DependencyInjection\AddCacheClearerPass; +use Symfony\Component\HttpKernel\DependencyInjection\AddCacheWarmerPass; use Symfony\Component\HttpKernel\DependencyInjection\ControllerArgumentValueResolverPass; use Symfony\Component\HttpKernel\DependencyInjection\RegisterControllerArgumentLocatorsPass; use Symfony\Component\HttpKernel\DependencyInjection\RemoveEmptyControllerArgumentLocatorsPass; diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/AddCacheWarmerPassTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/AddCacheWarmerPassTest.php index 3516aa93608fc..1f49022f8d863 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/AddCacheWarmerPassTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/AddCacheWarmerPassTest.php @@ -16,6 +16,9 @@ use Symfony\Component\DependencyInjection\Reference; use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\AddCacheWarmerPass; +/** + * @group legacy + */ class AddCacheWarmerPassTest extends TestCase { public function testThatCacheWarmersAreProcessedInPriorityOrder() diff --git a/src/Symfony/Bundle/FrameworkBundle/composer.json b/src/Symfony/Bundle/FrameworkBundle/composer.json index 9699ae85d6d6f..e181b55d98a8b 100644 --- a/src/Symfony/Bundle/FrameworkBundle/composer.json +++ b/src/Symfony/Bundle/FrameworkBundle/composer.json @@ -24,7 +24,7 @@ "symfony/config": "~3.3|~4.0", "symfony/event-dispatcher": "^3.3.1|~4.0", "symfony/http-foundation": "~3.3|~4.0", - "symfony/http-kernel": "~3.3|~4.0", + "symfony/http-kernel": "~3.4|~4.0", "symfony/polyfill-mbstring": "~1.0", "symfony/filesystem": "~2.8|~3.0|~4.0", "symfony/finder": "~2.8|~3.0|~4.0", @@ -66,6 +66,7 @@ "symfony/asset": "<3.3", "symfony/console": "<3.3", "symfony/form": "<3.3", + "symfony/http-kernel": "<3.4", "symfony/property-info": "<3.3", "symfony/serializer": "<3.3", "symfony/translation": "<3.2", diff --git a/src/Symfony/Component/HttpKernel/CHANGELOG.md b/src/Symfony/Component/HttpKernel/CHANGELOG.md index 061f61d172e25..6c21cb722aec3 100644 --- a/src/Symfony/Component/HttpKernel/CHANGELOG.md +++ b/src/Symfony/Component/HttpKernel/CHANGELOG.md @@ -1,6 +1,12 @@ CHANGELOG ========= +3.4.0 +----- + + * added `AddCacheClearerPass` + * added `AddCacheWarmerPass` + 3.3.0 ----- diff --git a/src/Symfony/Component/HttpKernel/DependencyInjection/AddCacheClearerPass.php b/src/Symfony/Component/HttpKernel/DependencyInjection/AddCacheClearerPass.php new file mode 100644 index 0000000000000..2689440bd7253 --- /dev/null +++ b/src/Symfony/Component/HttpKernel/DependencyInjection/AddCacheClearerPass.php @@ -0,0 +1,50 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\DependencyInjection; + +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; +use Symfony\Component\DependencyInjection\Reference; + +/** + * Registers the cache clearers. + * + * @author Dustin Dobervich + */ +class AddCacheClearerPass implements CompilerPassInterface +{ + private $cacheClearerId; + private $cacheClearerTag; + + public function __construct($cacheClearerId = 'cache_clearer', $cacheClearerTag = 'kernel.cache_clearer') + { + $this->cacheClearerId = $cacheClearerId; + $this->cacheClearerTag = $cacheClearerTag; + } + + /** + * {@inheritdoc} + */ + public function process(ContainerBuilder $container) + { + if (!$container->hasDefinition($this->cacheClearerId)) { + return; + } + + $clearers = array(); + foreach ($container->findTaggedServiceIds($this->cacheClearerTag, true) as $id => $attributes) { + $clearers[] = new Reference($id); + } + + $container->getDefinition($this->cacheClearerId)->replaceArgument(0, $clearers); + } +} diff --git a/src/Symfony/Component/HttpKernel/DependencyInjection/AddCacheWarmerPass.php b/src/Symfony/Component/HttpKernel/DependencyInjection/AddCacheWarmerPass.php new file mode 100644 index 0000000000000..6d13e1cbcb536 --- /dev/null +++ b/src/Symfony/Component/HttpKernel/DependencyInjection/AddCacheWarmerPass.php @@ -0,0 +1,53 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\DependencyInjection; + +use Symfony\Component\DependencyInjection\Compiler\PriorityTaggedServiceTrait; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; + +/** + * Registers the cache warmers. + * + * @author Fabien Potencier + */ +class AddCacheWarmerPass implements CompilerPassInterface +{ + use PriorityTaggedServiceTrait; + + private $cacheWarmerId; + private $cacheWarmerTag; + + public function __construct($cacheWarmerId = 'cache_warmer', $cacheWarmerTag = 'kernel.cache_warmer') + { + $this->cacheWarmerId = $cacheWarmerId; + $this->cacheWarmerTag = $cacheWarmerTag; + } + + /** + * {@inheritdoc} + */ + public function process(ContainerBuilder $container) + { + if (!$container->hasDefinition($this->cacheWarmerId)) { + return; + } + + $warmers = $this->findAndSortTaggedServices($this->cacheWarmerTag, $container); + + if (empty($warmers)) { + return; + } + + $container->getDefinition($this->cacheWarmerId)->replaceArgument(0, $warmers); + } +} diff --git a/src/Symfony/Component/HttpKernel/Tests/DependencyInjection/AddCacheClearerPassTest.php b/src/Symfony/Component/HttpKernel/Tests/DependencyInjection/AddCacheClearerPassTest.php new file mode 100644 index 0000000000000..3bdb84ad10667 --- /dev/null +++ b/src/Symfony/Component/HttpKernel/Tests/DependencyInjection/AddCacheClearerPassTest.php @@ -0,0 +1,53 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Tests\DependencyInjection; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Reference; +use Symfony\Component\HttpKernel\DependencyInjection\AddCacheClearerPass; + +class AddCacheClearerPassTest extends TestCase +{ + public function testThatCacheClearer() + { + $container = new ContainerBuilder(); + + $definition = $container->register('cache_clearer')->addArgument(null); + $container->register('my_cache_clearer_service1')->addTag('kernel.cache_clearer'); + + $addCacheWarmerPass = new AddCacheClearerPass(); + $addCacheWarmerPass->process($container); + + $expected = array( + new Reference('my_cache_clearer_service1'), + ); + $this->assertEquals($expected, $definition->getArgument(0)); + } + + public function testThatCompilerPassIsIgnoredIfThereIsNoCacheClearerDefinition() + { + $definition = $this->getMockBuilder('Symfony\Component\DependencyInjection\Definition')->getMock(); + $container = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerBuilder')->setMethods(array('hasDefinition', 'findTaggedServiceIds', 'getDefinition'))->getMock(); + + $container->expects($this->never())->method('findTaggedServiceIds'); + $container->expects($this->never())->method('getDefinition'); + $container->expects($this->atLeastOnce()) + ->method('hasDefinition') + ->with('cache_clearer') + ->will($this->returnValue(false)); + $definition->expects($this->never())->method('replaceArgument'); + + $addCacheWarmerPass = new AddCacheClearerPass(); + $addCacheWarmerPass->process($container); + } +} diff --git a/src/Symfony/Component/HttpKernel/Tests/DependencyInjection/AddCacheWarmerPassTest.php b/src/Symfony/Component/HttpKernel/Tests/DependencyInjection/AddCacheWarmerPassTest.php new file mode 100644 index 0000000000000..3f7bc6e65ebef --- /dev/null +++ b/src/Symfony/Component/HttpKernel/Tests/DependencyInjection/AddCacheWarmerPassTest.php @@ -0,0 +1,77 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Tests\DependencyInjection; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Reference; +use Symfony\Component\HttpKernel\DependencyInjection\AddCacheWarmerPass; + +class AddCacheWarmerPassTest extends TestCase +{ + public function testThatCacheWarmersAreProcessedInPriorityOrder() + { + $container = new ContainerBuilder(); + + $definition = $container->register('cache_warmer')->addArgument(null); + $container->register('my_cache_warmer_service1')->addTag('kernel.cache_warmer', array('priority' => 100)); + $container->register('my_cache_warmer_service2')->addTag('kernel.cache_warmer', array('priority' => 200)); + $container->register('my_cache_warmer_service3')->addTag('kernel.cache_warmer'); + + $addCacheWarmerPass = new AddCacheWarmerPass(); + $addCacheWarmerPass->process($container); + + $expected = array( + new Reference('my_cache_warmer_service2'), + new Reference('my_cache_warmer_service1'), + new Reference('my_cache_warmer_service3'), + ); + $this->assertEquals($expected, $definition->getArgument(0)); + } + + public function testThatCompilerPassIsIgnoredIfThereIsNoCacheWarmerDefinition() + { + $definition = $this->getMockBuilder('Symfony\Component\DependencyInjection\Definition')->getMock(); + $container = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerBuilder')->setMethods(array('hasDefinition', 'findTaggedServiceIds', 'getDefinition'))->getMock(); + + $container->expects($this->never())->method('findTaggedServiceIds'); + $container->expects($this->never())->method('getDefinition'); + $container->expects($this->atLeastOnce()) + ->method('hasDefinition') + ->with('cache_warmer') + ->will($this->returnValue(false)); + $definition->expects($this->never())->method('replaceArgument'); + + $addCacheWarmerPass = new AddCacheWarmerPass(); + $addCacheWarmerPass->process($container); + } + + public function testThatCacheWarmersMightBeNotDefined() + { + $definition = $this->getMockBuilder('Symfony\Component\DependencyInjection\Definition')->getMock(); + $container = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerBuilder')->setMethods(array('hasDefinition', 'findTaggedServiceIds', 'getDefinition'))->getMock(); + + $container->expects($this->atLeastOnce()) + ->method('findTaggedServiceIds') + ->will($this->returnValue(array())); + $container->expects($this->never())->method('getDefinition'); + $container->expects($this->atLeastOnce()) + ->method('hasDefinition') + ->with('cache_warmer') + ->will($this->returnValue(true)); + + $definition->expects($this->never())->method('replaceArgument'); + + $addCacheWarmerPass = new AddCacheWarmerPass(); + $addCacheWarmerPass->process($container); + } +} From cc7275bccce951d1d6a509f52723657b572d0083 Mon Sep 17 00:00:00 2001 From: Javier Eguiluz Date: Thu, 22 Jun 2017 18:11:34 +0200 Subject: [PATCH 0263/1099] Display a better error message when the toolbar cannot be displayed --- .../Resources/views/Profiler/toolbar_js.html.twig | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/toolbar_js.html.twig b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/toolbar_js.html.twig index 91ad9ad10ecf1..57537f61a3feb 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/toolbar_js.html.twig +++ b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/toolbar_js.html.twig @@ -57,8 +57,17 @@ } }, function(xhr) { + var errorToolbarHtml = ' + +
An error occurred while loading the web debug toolbar. Open the web profiler.
+ '; + if (xhr.status !== 0) { - confirm('An error occurred while loading the web debug toolbar (' + xhr.status + ': ' + xhr.statusText + ').\n\nDo you want to open the profiler?') && (window.location = '{{ path("_profiler", { "token": token }) }}'); + window.document.body.insertAdjacentHTML('beforeend', errorToolbarHtml); } }, {'maxTries': 5} From 99931a994b83a0ed35a1a8358c224a8117a18d5f Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Thu, 22 Jun 2017 21:48:55 +0200 Subject: [PATCH 0264/1099] allow SSI fragments configuration in XML files --- .../Resources/config/schema/symfony-1.0.xsd | 5 +++++ .../Tests/DependencyInjection/Fixtures/php/full.php | 3 +++ .../Tests/DependencyInjection/Fixtures/xml/full.xml | 1 + .../Tests/DependencyInjection/Fixtures/yml/full.yml | 2 ++ .../Tests/DependencyInjection/FrameworkExtensionTest.php | 7 +++++++ 5 files changed, 18 insertions(+) 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 0f0874829bcdb..2d866ff1b5cac 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 @@ -22,6 +22,7 @@ + @@ -64,6 +65,10 @@ + + + + diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/full.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/full.php index 5022aeaf9f207..6861844b49233 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/full.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/full.php @@ -16,6 +16,9 @@ 'esi' => array( 'enabled' => true, ), + 'ssi' => array( + 'enabled' => true, + ), 'profiler' => array( 'only_exceptions' => true, 'enabled' => false, diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/full.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/full.xml index 5b16a59796091..c0d8a85a1c5d7 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/full.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/full.xml @@ -12,6 +12,7 @@ + diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/full.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/full.yml index 47dcb575317e3..3e000ca9cc59c 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/full.yml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/full.yml @@ -10,6 +10,8 @@ framework: enabled: true esi: enabled: true + ssi: + enabled: true profiler: only_exceptions: true enabled: false diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php index a782a3f0748bb..5601e6a88b236 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php @@ -98,6 +98,13 @@ public function testEsi() $this->assertTrue($container->hasDefinition('esi'), '->registerEsiConfiguration() loads esi.xml'); } + public function testSsi() + { + $container = $this->createContainerFromFile('full'); + + $this->assertTrue($container->hasDefinition('ssi'), '->registerSsiConfiguration() loads ssi.xml'); + } + public function testEnabledProfiler() { $container = $this->createContainerFromFile('profiler'); From a433ceca4142aeebf14390c702f71839344f7db7 Mon Sep 17 00:00:00 2001 From: George Mponos Date: Thu, 22 Jun 2017 21:40:34 +0300 Subject: [PATCH 0265/1099] Show exception is checked twice in ExceptionController of twig --- .../Bundle/TwigBundle/Controller/ExceptionController.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Bundle/TwigBundle/Controller/ExceptionController.php b/src/Symfony/Bundle/TwigBundle/Controller/ExceptionController.php index 1878204003b62..0c31f9bd39f53 100644 --- a/src/Symfony/Bundle/TwigBundle/Controller/ExceptionController.php +++ b/src/Symfony/Bundle/TwigBundle/Controller/ExceptionController.php @@ -125,7 +125,7 @@ protected function findTemplate(Request $request, $format, $code, $showException // default to a generic HTML exception $request->setRequestFormat('html'); - return new TemplateReference('TwigBundle', 'Exception', $showException ? 'exception_full' : $name, 'html', 'twig'); + return new TemplateReference('TwigBundle', 'Exception', $name, 'html', 'twig'); } // to be removed when the minimum required version of Twig is >= 3.0 From 0724ebc5d2845ca64b6bfea7ed41c4f13eda7884 Mon Sep 17 00:00:00 2001 From: Nicolas Date: Fri, 23 Jun 2017 11:32:10 +0200 Subject: [PATCH 0266/1099] Fix undefined variable $filesystem --- .../Bundle/FrameworkBundle/Command/AssetsInstallCommand.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/AssetsInstallCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/AssetsInstallCommand.php index 0d87397b2e82f..395d3e6d335c1 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/AssetsInstallCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/AssetsInstallCommand.php @@ -154,7 +154,7 @@ protected function execute(InputInterface $input, OutputInterface $output) // remove the assets of the bundles that no longer exist foreach (new \FilesystemIterator($bundlesDir) as $dir) { if (!in_array($dir, $validAssetDirs)) { - $filesystem->remove($dir); + $this->filesystem->remove($dir); } } From 88fa75d27d8cc37bb90cec6b037769aa2691e6ea Mon Sep 17 00:00:00 2001 From: Ben Davies Date: Fri, 23 Jun 2017 11:09:44 +0100 Subject: [PATCH 0267/1099] swiftmailer bridge is gone --- composer.json | 1 - 1 file changed, 1 deletion(-) diff --git a/composer.json b/composer.json index 6c4347ccaab0a..698c283d149c9 100644 --- a/composer.json +++ b/composer.json @@ -111,7 +111,6 @@ "Symfony\\Bridge\\Doctrine\\": "src/Symfony/Bridge/Doctrine/", "Symfony\\Bridge\\Monolog\\": "src/Symfony/Bridge/Monolog/", "Symfony\\Bridge\\ProxyManager\\": "src/Symfony/Bridge/ProxyManager/", - "Symfony\\Bridge\\Swiftmailer\\": "src/Symfony/Bridge/Swiftmailer/", "Symfony\\Bridge\\Twig\\": "src/Symfony/Bridge/Twig/", "Symfony\\Bundle\\": "src/Symfony/Bundle/", "Symfony\\Component\\": "src/Symfony/Component/" From 635bccdf8f6b3272acd542aae11437807f122e05 Mon Sep 17 00:00:00 2001 From: Pierre du Plessis Date: Fri, 23 Jun 2017 12:52:30 +0200 Subject: [PATCH 0268/1099] Dont call count on non countable object --- .../Translation/Dumper/IcuResFileDumper.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Symfony/Component/Translation/Dumper/IcuResFileDumper.php b/src/Symfony/Component/Translation/Dumper/IcuResFileDumper.php index 0fd5b35ae333b..7d4db851fe23b 100644 --- a/src/Symfony/Component/Translation/Dumper/IcuResFileDumper.php +++ b/src/Symfony/Component/Translation/Dumper/IcuResFileDumper.php @@ -52,7 +52,7 @@ public function format(MessageCatalogue $messages, $domain = 'messages') $resOffset = $this->getPosition($data); - $data .= pack('v', count($messages)) + $data .= pack('v', count($messages->all($domain))) .$indexes .$this->writePadding($data) .$resources @@ -63,11 +63,11 @@ public function format(MessageCatalogue $messages, $domain = 'messages') $root = pack('V7', $resOffset + (2 << 28), // Resource Offset + Resource Type 6, // Index length - $keyTop, // Index keys top - $bundleTop, // Index resources top - $bundleTop, // Index bundle top - count($messages), // Index max table length - 0 // Index attributes + $keyTop, // Index keys top + $bundleTop, // Index resources top + $bundleTop, // Index bundle top + count($messages->all($domain)), // Index max table length + 0 // Index attributes ); $header = pack('vC2v4C12@32', From 6e88fef532f6348e1093b85bf35375ee790a61c5 Mon Sep 17 00:00:00 2001 From: Shude Date: Fri, 23 Jun 2017 18:11:58 +0300 Subject: [PATCH 0269/1099] Fix typo in docblock --- src/Symfony/Component/Routing/RouteCollectionBuilder.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/Routing/RouteCollectionBuilder.php b/src/Symfony/Component/Routing/RouteCollectionBuilder.php index 54bd86b7eaade..3998ce1ededd4 100644 --- a/src/Symfony/Component/Routing/RouteCollectionBuilder.php +++ b/src/Symfony/Component/Routing/RouteCollectionBuilder.php @@ -61,7 +61,7 @@ public function __construct(LoaderInterface $loader = null) */ public function import($resource, $prefix = '/', $type = null) { - /** @var RouteCollection[] $collection */ + /** @var RouteCollection[] $collections */ $collections = $this->load($resource, $type); // create a builder from the RouteCollection From 46c38df0fd82cc762c6fe27ec8b75cd69b1414f4 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Sat, 24 Jun 2017 11:40:57 +0200 Subject: [PATCH 0270/1099] [TwigBundle] add back exception check --- .../TwigBundle/Controller/ExceptionController.php | 2 +- .../Tests/Controller/ExceptionControllerTest.php | 14 ++++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Bundle/TwigBundle/Controller/ExceptionController.php b/src/Symfony/Bundle/TwigBundle/Controller/ExceptionController.php index 0c31f9bd39f53..1878204003b62 100644 --- a/src/Symfony/Bundle/TwigBundle/Controller/ExceptionController.php +++ b/src/Symfony/Bundle/TwigBundle/Controller/ExceptionController.php @@ -125,7 +125,7 @@ protected function findTemplate(Request $request, $format, $code, $showException // default to a generic HTML exception $request->setRequestFormat('html'); - return new TemplateReference('TwigBundle', 'Exception', $name, 'html', 'twig'); + return new TemplateReference('TwigBundle', 'Exception', $showException ? 'exception_full' : $name, 'html', 'twig'); } // to be removed when the minimum required version of Twig is >= 3.0 diff --git a/src/Symfony/Bundle/TwigBundle/Tests/Controller/ExceptionControllerTest.php b/src/Symfony/Bundle/TwigBundle/Tests/Controller/ExceptionControllerTest.php index 7b85d86508273..82f10c8296fd2 100644 --- a/src/Symfony/Bundle/TwigBundle/Tests/Controller/ExceptionControllerTest.php +++ b/src/Symfony/Bundle/TwigBundle/Tests/Controller/ExceptionControllerTest.php @@ -48,6 +48,20 @@ public function testFallbackToHtmlIfNoTemplateForRequestedFormat() $this->assertEquals('html', $request->getRequestFormat()); } + public function testFallbackToHtmlWithFullExceptionIfNoTemplateForRequestedFormatAndExceptionsShouldBeShown() + { + $twig = $this->createTwigEnv(array('TwigBundle:Exception:exception_full.html.twig' => '')); + + $request = $this->createRequest('txt'); + $request->attributes->set('showException', true); + $exception = FlattenException::create(new \Exception()); + $controller = new ExceptionController($twig, false); + + $controller->showAction($request, $exception); + + $this->assertEquals('html', $request->getRequestFormat()); + } + public function testResponseHasRequestedMimeType() { $twig = $this->createTwigEnv(array('TwigBundle:Exception:error.json.twig' => '{}')); From 265fc2a16a461cae7d904c90af9341403c391023 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Sat, 24 Jun 2017 13:17:41 +0200 Subject: [PATCH 0271/1099] add missing version attribute --- .../Bundle/WebProfilerBundle/Resources/views/Icon/validator.svg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Icon/validator.svg b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Icon/validator.svg index b501fe5486807..0b60184f9def5 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Icon/validator.svg +++ b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Icon/validator.svg @@ -1 +1 @@ - + From 7cda0996631e4d72998feb416c84715014bffe2f Mon Sep 17 00:00:00 2001 From: Jose Gonzalez Date: Sat, 24 Jun 2017 11:52:11 +0100 Subject: [PATCH 0272/1099] [Stopwatch] Add a reset method --- src/Symfony/Component/Stopwatch/Stopwatch.php | 10 +++++++++- .../Component/Stopwatch/Tests/StopwatchTest.php | 12 ++++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/Stopwatch/Stopwatch.php b/src/Symfony/Component/Stopwatch/Stopwatch.php index 8ad93165bfd74..562f220f673b1 100644 --- a/src/Symfony/Component/Stopwatch/Stopwatch.php +++ b/src/Symfony/Component/Stopwatch/Stopwatch.php @@ -30,7 +30,7 @@ class Stopwatch public function __construct() { - $this->sections = $this->activeSections = array('__root__' => new Section('__root__')); + $this->reset(); } /** @@ -156,4 +156,12 @@ public function getSectionEvents($id) { return isset($this->sections[$id]) ? $this->sections[$id]->getEvents() : array(); } + + /** + * Resets the stopwatch to its original state. + */ + public function reset() + { + $this->sections = $this->activeSections = array('__root__' => new Section('__root__')); + } } diff --git a/src/Symfony/Component/Stopwatch/Tests/StopwatchTest.php b/src/Symfony/Component/Stopwatch/Tests/StopwatchTest.php index f7d9171d8bc04..519803d9908d2 100644 --- a/src/Symfony/Component/Stopwatch/Tests/StopwatchTest.php +++ b/src/Symfony/Component/Stopwatch/Tests/StopwatchTest.php @@ -153,4 +153,16 @@ public function testReopenANewSectionShouldThrowAnException() $stopwatch = new Stopwatch(); $stopwatch->openSection('section'); } + + public function testReset() + { + $stopwatch = new Stopwatch(); + + $stopwatch->openSection(); + $stopwatch->start('foo', 'cat'); + + $stopwatch->reset(); + + $this->assertEquals(new Stopwatch(), $stopwatch); + } } From a12b8c37ff7c9cdc02c9f4afacffa2ee7f01ba88 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Sat, 24 Jun 2017 15:18:23 +0200 Subject: [PATCH 0273/1099] [Yaml] remove deprecated unspecific tag behavior --- src/Symfony/Component/Yaml/CHANGELOG.md | 2 ++ src/Symfony/Component/Yaml/Inline.php | 4 +--- .../Yaml/Tests/Fixtures/YtsSpecificationExamples.yml | 5 ++--- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/Symfony/Component/Yaml/CHANGELOG.md b/src/Symfony/Component/Yaml/CHANGELOG.md index 6c60a96166540..be65b535cdd6e 100644 --- a/src/Symfony/Component/Yaml/CHANGELOG.md +++ b/src/Symfony/Component/Yaml/CHANGELOG.md @@ -4,6 +4,8 @@ CHANGELOG 4.0.0 ----- + * The behavior of the non-specific tag `!` is changed and now forces + non-evaluating your values. * complex mappings will throw a `ParseException` * support for the comma as a group separator for floats has been dropped, use the underscore instead diff --git a/src/Symfony/Component/Yaml/Inline.php b/src/Symfony/Component/Yaml/Inline.php index 6ecbefd391627..45e173dd7211d 100644 --- a/src/Symfony/Component/Yaml/Inline.php +++ b/src/Symfony/Component/Yaml/Inline.php @@ -553,9 +553,7 @@ private static function evaluateScalar($scalar, $flags, $references = array()) case 0 === strpos($scalar, '!str'): return (string) substr($scalar, 5); case 0 === strpos($scalar, '! '): - @trigger_error('Using the non-specific tag "!" is deprecated since version 3.4 as its behavior will change in 4.0. It will force non-evaluating your values in 4.0. Use plain integers or !!float instead.', E_USER_DEPRECATED); - - return (int) self::parseScalar(substr($scalar, 2), $flags); + return substr($scalar, 2); case 0 === strpos($scalar, '!php/object:'): if (self::$objectSupport) { return unserialize(substr($scalar, 12)); diff --git a/src/Symfony/Component/Yaml/Tests/Fixtures/YtsSpecificationExamples.yml b/src/Symfony/Component/Yaml/Tests/Fixtures/YtsSpecificationExamples.yml index a9b6f8d8b5e18..4d64277675322 100644 --- a/src/Symfony/Component/Yaml/Tests/Fixtures/YtsSpecificationExamples.yml +++ b/src/Symfony/Component/Yaml/Tests/Fixtures/YtsSpecificationExamples.yml @@ -908,13 +908,12 @@ documents: 2 --- test: Explicit typing -deprecated: Using the non-specific tag "!" is deprecated since version 3.4 as its behavior will change in 4.0. yaml: | integer: 12 - also int: ! "12" + no int: ! 12 string: !str 12 php: | - array( 'integer' => 12, 'also int' => 12, 'string' => '12' ) + array( 'integer' => 12, 'no int' => '12', 'string' => '12' ) --- test: Private types todo: true From ddf43684442338229cc0f1e0742f0d6b1af6c241 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Sat, 24 Jun 2017 15:27:17 +0200 Subject: [PATCH 0274/1099] respect the API in FirewallContext map When being merged up, this will make the SecurityBundle tests on master green again. --- .../Tests/Security/FirewallMapTest.php | 20 ++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Security/FirewallMapTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/Security/FirewallMapTest.php index da7800cce3037..f9047cfdd233e 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/Security/FirewallMapTest.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/Security/FirewallMapTest.php @@ -12,11 +12,15 @@ namespace Symfony\Bundle\SecurityBundle\Tests\Security; use PHPUnit\Framework\TestCase; +use Symfony\Bundle\SecurityBundle\Security\FirewallConfig; use Symfony\Bundle\SecurityBundle\Security\FirewallContext; use Symfony\Bundle\SecurityBundle\Security\FirewallMap; use Symfony\Component\DependencyInjection\Container; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\RequestMatcherInterface; +use Symfony\Component\Security\Core\User\UserCheckerInterface; +use Symfony\Component\Security\Http\Firewall\ExceptionListener; +use Symfony\Component\Security\Http\Firewall\ListenerInterface; class FirewallMapTest extends TestCase { @@ -58,9 +62,15 @@ public function testGetListeners() $request = new Request(); $firewallContext = $this->getMockBuilder(FirewallContext::class)->disableOriginalConstructor()->getMock(); - $firewallContext->expects($this->once())->method('getConfig')->willReturn('CONFIG'); - $firewallContext->expects($this->once())->method('getListeners')->willReturn('LISTENERS'); - $firewallContext->expects($this->once())->method('getExceptionListener')->willReturn('EXCEPTION LISTENER'); + + $firewallConfig = new FirewallConfig('main', $this->getMockBuilder(UserCheckerInterface::class)->getMock()); + $firewallContext->expects($this->once())->method('getConfig')->willReturn($firewallConfig); + + $listener = $this->getMockBuilder(ListenerInterface::class)->getMock(); + $firewallContext->expects($this->once())->method('getListeners')->willReturn(array($listener)); + + $exceptionListener = $this->getMockBuilder(ExceptionListener::class)->disableOriginalConstructor()->getMock(); + $firewallContext->expects($this->once())->method('getExceptionListener')->willReturn($exceptionListener); $matcher = $this->getMockBuilder(RequestMatcherInterface::class)->getMock(); $matcher->expects($this->once()) @@ -73,8 +83,8 @@ public function testGetListeners() $firewallMap = new FirewallMap($container, array('security.firewall.map.context.foo' => $matcher)); - $this->assertEquals(array('LISTENERS', 'EXCEPTION LISTENER'), $firewallMap->getListeners($request)); - $this->assertEquals('CONFIG', $firewallMap->getFirewallConfig($request)); + $this->assertEquals(array(array($listener), $exceptionListener), $firewallMap->getListeners($request)); + $this->assertEquals($firewallConfig, $firewallMap->getFirewallConfig($request)); $this->assertEquals('security.firewall.map.context.foo', $request->attributes->get(self::ATTRIBUTE_FIREWALL_CONTEXT)); } } From 2b3d7f021d614f78ec19e404b3cbe11c444c739f Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Thu, 22 Jun 2017 21:48:55 +0200 Subject: [PATCH 0275/1099] disable unusable fragment renderers --- .../FrameworkExtension.php | 6 +++++ .../php/esi_and_ssi_without_fragments.php | 13 ++++++++++ .../Fixtures/php/esi_disabled.php | 7 ++++++ .../Fixtures/php/ssi_disabled.php | 7 ++++++ .../xml/esi_and_ssi_without_fragments.xml | 13 ++++++++++ .../Fixtures/xml/esi_disabled.xml | 11 ++++++++ .../Fixtures/xml/ssi_disabled.xml | 11 ++++++++ .../yml/esi_and_ssi_without_fragments.yml | 7 ++++++ .../Fixtures/yml/esi_disabled.yml | 3 +++ .../Fixtures/yml/ssi_disabled.yml | 3 +++ .../FrameworkExtensionTest.php | 25 +++++++++++++++++++ .../Compiler/ExtensionPass.php | 5 +--- 12 files changed, 107 insertions(+), 4 deletions(-) create mode 100644 src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/esi_and_ssi_without_fragments.php create mode 100644 src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/esi_disabled.php create mode 100644 src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/ssi_disabled.php create mode 100644 src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/esi_and_ssi_without_fragments.xml create mode 100644 src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/esi_disabled.xml create mode 100644 src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/ssi_disabled.xml create mode 100644 src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/esi_and_ssi_without_fragments.yml create mode 100644 src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/esi_disabled.yml create mode 100644 src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/ssi_disabled.yml diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php index ee22c1b0b8289..f3b77f0a12409 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php @@ -392,6 +392,8 @@ private function registerFormConfiguration($config, ContainerBuilder $container, private function registerEsiConfiguration(array $config, ContainerBuilder $container, XmlFileLoader $loader) { if (!$this->isConfigEnabled($container, $config)) { + $container->removeDefinition('fragment.renderer.esi'); + return; } @@ -408,6 +410,8 @@ private function registerEsiConfiguration(array $config, ContainerBuilder $conta private function registerSsiConfiguration(array $config, ContainerBuilder $container, XmlFileLoader $loader) { if (!$this->isConfigEnabled($container, $config)) { + $container->removeDefinition('fragment.renderer.ssi'); + return; } @@ -424,6 +428,8 @@ private function registerSsiConfiguration(array $config, ContainerBuilder $conta private function registerFragmentsConfiguration(array $config, ContainerBuilder $container, XmlFileLoader $loader) { if (!$this->isConfigEnabled($container, $config)) { + $container->removeDefinition('fragment.renderer.hinclude'); + return; } diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/esi_and_ssi_without_fragments.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/esi_and_ssi_without_fragments.php new file mode 100644 index 0000000000000..b8f3aa0441ac4 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/esi_and_ssi_without_fragments.php @@ -0,0 +1,13 @@ +loadFromExtension('framework', array( + 'fragments' => array( + 'enabled' => false, + ), + 'esi' => array( + 'enabled' => true, + ), + 'ssi' => array( + 'enabled' => true, + ), +)); diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/esi_disabled.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/esi_disabled.php new file mode 100644 index 0000000000000..1fb5936fdec11 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/esi_disabled.php @@ -0,0 +1,7 @@ +loadFromExtension('framework', array( + 'esi' => array( + 'enabled' => false, + ), +)); diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/ssi_disabled.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/ssi_disabled.php new file mode 100644 index 0000000000000..4d61d821660f8 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/ssi_disabled.php @@ -0,0 +1,7 @@ +loadFromExtension('framework', array( + 'ssi' => array( + 'enabled' => false, + ), +)); diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/esi_and_ssi_without_fragments.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/esi_and_ssi_without_fragments.xml new file mode 100644 index 0000000000000..7742141035d1a --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/esi_and_ssi_without_fragments.xml @@ -0,0 +1,13 @@ + + + + + + + + + diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/esi_disabled.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/esi_disabled.xml new file mode 100644 index 0000000000000..c358feda807da --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/esi_disabled.xml @@ -0,0 +1,11 @@ + + + + + + + diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/ssi_disabled.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/ssi_disabled.xml new file mode 100644 index 0000000000000..e7e1880655c58 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/ssi_disabled.xml @@ -0,0 +1,11 @@ + + + + + + + diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/esi_and_ssi_without_fragments.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/esi_and_ssi_without_fragments.yml new file mode 100644 index 0000000000000..49d63c8d60a15 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/esi_and_ssi_without_fragments.yml @@ -0,0 +1,7 @@ +framework: + fragments: + enabled: false + esi: + enabled: true + ssi: + enabled: true diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/esi_disabled.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/esi_disabled.yml new file mode 100644 index 0000000000000..2a78e6da0e725 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/esi_disabled.yml @@ -0,0 +1,3 @@ +framework: + esi: + enabled: false diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/ssi_disabled.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/ssi_disabled.yml new file mode 100644 index 0000000000000..3a8a820c71438 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/ssi_disabled.yml @@ -0,0 +1,3 @@ +framework: + ssi: + enabled: false diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php index eee6169ae15da..411c6c0dce402 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php @@ -132,6 +132,14 @@ public function testEsi() $container = $this->createContainerFromFile('full'); $this->assertTrue($container->hasDefinition('esi'), '->registerEsiConfiguration() loads esi.xml'); + $this->assertTrue($container->hasDefinition('fragment.renderer.esi'), 'The ESI fragment renderer is registered'); + } + + public function testEsiDisabled() + { + $container = $this->createContainerFromFile('esi_disabled'); + + $this->assertFalse($container->hasDefinition('fragment.renderer.esi'), 'The ESI fragment renderer is not registered'); } public function testSsi() @@ -139,6 +147,23 @@ public function testSsi() $container = $this->createContainerFromFile('full'); $this->assertTrue($container->hasDefinition('ssi'), '->registerSsiConfiguration() loads ssi.xml'); + $this->assertTrue($container->hasDefinition('fragment.renderer.ssi'), 'The SSI fragment renderer is registered'); + } + + public function testSsiDisabled() + { + $container = $this->createContainerFromFile('ssi_disabled'); + + $this->assertFalse($container->hasDefinition('fragment.renderer.ssi'), 'The SSI fragment renderer is not registered'); + } + + public function testEsiAndSsiWithoutFragments() + { + $container = $this->createContainerFromFile('esi_and_ssi_without_fragments'); + + $this->assertFalse($container->hasDefinition('fragment.renderer.hinclude'), 'The HInclude fragment renderer is not registered'); + $this->assertTrue($container->hasDefinition('fragment.renderer.esi'), 'The ESI fragment renderer is registered'); + $this->assertTrue($container->hasDefinition('fragment.renderer.ssi'), 'The SSI fragment renderer is registered'); } public function testEnabledProfiler() diff --git a/src/Symfony/Bundle/TwigBundle/DependencyInjection/Compiler/ExtensionPass.php b/src/Symfony/Bundle/TwigBundle/DependencyInjection/Compiler/ExtensionPass.php index a9bd57e57d6a2..31d1b758eff56 100644 --- a/src/Symfony/Bundle/TwigBundle/DependencyInjection/Compiler/ExtensionPass.php +++ b/src/Symfony/Bundle/TwigBundle/DependencyInjection/Compiler/ExtensionPass.php @@ -61,10 +61,7 @@ public function process(ContainerBuilder $container) $container->getDefinition('twig.extension.httpkernel')->addTag('twig.extension'); // inject Twig in the hinclude service if Twig is the only registered templating engine - if ( - !$container->hasParameter('templating.engines') - || array('twig') == $container->getParameter('templating.engines') - ) { + if ((!$container->hasParameter('templating.engines') || array('twig') == $container->getParameter('templating.engines')) && $container->hasDefinition('fragment.renderer.hinclude')) { $container->getDefinition('fragment.renderer.hinclude') ->addTag('kernel.fragment_renderer', array('alias' => 'hinclude')) ->replaceArgument(0, new Reference('twig')) From 2e435228d143fae98bf4d6d1ccee74fd0036d03f Mon Sep 17 00:00:00 2001 From: Ben Davies Date: Fri, 23 Jun 2017 11:09:44 +0100 Subject: [PATCH 0276/1099] swiftmailer bridge is gone --- composer.json | 1 - 1 file changed, 1 deletion(-) diff --git a/composer.json b/composer.json index c7994e4db2b59..75e9c916370b2 100644 --- a/composer.json +++ b/composer.json @@ -106,7 +106,6 @@ "Symfony\\Bridge\\Doctrine\\": "src/Symfony/Bridge/Doctrine/", "Symfony\\Bridge\\Monolog\\": "src/Symfony/Bridge/Monolog/", "Symfony\\Bridge\\ProxyManager\\": "src/Symfony/Bridge/ProxyManager/", - "Symfony\\Bridge\\Swiftmailer\\": "src/Symfony/Bridge/Swiftmailer/", "Symfony\\Bridge\\Twig\\": "src/Symfony/Bridge/Twig/", "Symfony\\Bundle\\": "src/Symfony/Bundle/", "Symfony\\Component\\": "src/Symfony/Component/" From bf0063e3d3c43273f56970234b593ebcf70b781d Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Sat, 24 Jun 2017 09:45:07 -0700 Subject: [PATCH 0277/1099] fixed tests --- .../TwigBundle/Tests/Controller/ExceptionControllerTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Bundle/TwigBundle/Tests/Controller/ExceptionControllerTest.php b/src/Symfony/Bundle/TwigBundle/Tests/Controller/ExceptionControllerTest.php index 5b6dcb76fcc31..5d779c68c2a5e 100644 --- a/src/Symfony/Bundle/TwigBundle/Tests/Controller/ExceptionControllerTest.php +++ b/src/Symfony/Bundle/TwigBundle/Tests/Controller/ExceptionControllerTest.php @@ -50,7 +50,7 @@ public function testFallbackToHtmlIfNoTemplateForRequestedFormat() public function testFallbackToHtmlWithFullExceptionIfNoTemplateForRequestedFormatAndExceptionsShouldBeShown() { - $twig = $this->createTwigEnv(array('TwigBundle:Exception:exception_full.html.twig' => '')); + $twig = $this->createTwigEnv(array('@Twig/Exception/exception_full.html.twig' => '')); $request = $this->createRequest('txt'); $request->attributes->set('showException', true); From 976b93a04056c5e9fd437c47252c0039fafa062f Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Sat, 24 Jun 2017 16:09:41 +0200 Subject: [PATCH 0278/1099] [Yaml] deprecate the !str tag The tag specified in the YAML spec is actually !!str. --- UPGRADE-3.4.md | 2 ++ UPGRADE-4.0.md | 2 ++ src/Symfony/Component/Yaml/CHANGELOG.md | 2 ++ src/Symfony/Component/Yaml/Inline.php | 4 ++++ .../Yaml/Tests/Fixtures/YtsSpecificationExamples.yml | 10 +++++----- .../Component/Yaml/Tests/Fixtures/YtsTypeTransfers.yml | 6 +++--- src/Symfony/Component/Yaml/Tests/InlineTest.php | 9 +++++++++ 7 files changed, 27 insertions(+), 8 deletions(-) diff --git a/UPGRADE-3.4.md b/UPGRADE-3.4.md index a609da081ccb8..383abb72eb1ac 100644 --- a/UPGRADE-3.4.md +++ b/UPGRADE-3.4.md @@ -61,5 +61,7 @@ Validator Yaml ---- + * Support for the `!str` tag is deprecated, use the `!!str` tag instead. + * Using the non-specific tag `!` is deprecated and will have a different behavior in 4.0. Use a plain integer or `!!float` instead. diff --git a/UPGRADE-4.0.md b/UPGRADE-4.0.md index b1027dc026fad..3c65dc2a374e4 100644 --- a/UPGRADE-4.0.md +++ b/UPGRADE-4.0.md @@ -575,6 +575,8 @@ Workflow Yaml ---- + * Support for the `!str` tag was removed, use the `!!str` tag instead. + * Starting an unquoted string with a question mark followed by a space throws a `ParseException`. diff --git a/src/Symfony/Component/Yaml/CHANGELOG.md b/src/Symfony/Component/Yaml/CHANGELOG.md index 172544aa97a8b..89c1a83ae238a 100644 --- a/src/Symfony/Component/Yaml/CHANGELOG.md +++ b/src/Symfony/Component/Yaml/CHANGELOG.md @@ -4,6 +4,8 @@ CHANGELOG 3.4.0 ----- + * Support for the `!str` tag is deprecated, use the `!!str` tag instead. + * Deprecated using the non-specific tag `!` as its behavior will change in 4.0. It will force non-evaluating your values in 4.0. Use plain integers or `!!float` instead. diff --git a/src/Symfony/Component/Yaml/Inline.php b/src/Symfony/Component/Yaml/Inline.php index a519ca5546b67..78e442bb723f5 100644 --- a/src/Symfony/Component/Yaml/Inline.php +++ b/src/Symfony/Component/Yaml/Inline.php @@ -609,7 +609,11 @@ private static function evaluateScalar($scalar, $flags, $references = array()) case $scalar[0] === '!': switch (true) { case 0 === strpos($scalar, '!str'): + @trigger_error('Support for the !str tag is deprecated since version 3.4. Use the !!str tag instead.', E_USER_DEPRECATED); + return (string) substr($scalar, 5); + case 0 === strpos($scalar, '!!str '): + return (string) substr($scalar, 6); case 0 === strpos($scalar, '! '): @trigger_error('Using the non-specific tag "!" is deprecated since version 3.4 as its behavior will change in 4.0. It will force non-evaluating your values in 4.0. Use plain integers or !!float instead.', E_USER_DEPRECATED); diff --git a/src/Symfony/Component/Yaml/Tests/Fixtures/YtsSpecificationExamples.yml b/src/Symfony/Component/Yaml/Tests/Fixtures/YtsSpecificationExamples.yml index fbdfffcc690d5..a7bba5edbe522 100644 --- a/src/Symfony/Component/Yaml/Tests/Fixtures/YtsSpecificationExamples.yml +++ b/src/Symfony/Component/Yaml/Tests/Fixtures/YtsSpecificationExamples.yml @@ -592,7 +592,7 @@ test: Various explicit families todo: true spec: 2.23 yaml: | - not-date: !str 2002-04-28 + not-date: !!str 2002-04-28 picture: !binary | R0lGODlhDAAMAIQAAP//9/X 17unp5WZmZgAAAOfn515eXv @@ -932,7 +932,7 @@ deprecated: Using the non-specific tag "!" is deprecated since version 3.4 as it yaml: | integer: 12 also int: ! "12" - string: !str 12 + string: !!str 12 php: | array( 'integer' => 12, 'also int' => 12, 'string' => '12' ) --- @@ -964,7 +964,7 @@ documents: 2 test: Type family under yaml.org yaml: | # The URI is 'tag:yaml.org,2002:str' - - !str a Unicode string + - !!str a Unicode string php: | array( 'a Unicode string' ) --- @@ -1351,7 +1351,7 @@ yaml: | second: 12 ## This is an integer. - third: !str 12 ## This is a string. + third: !!str 12 ## This is a string. span: this contains six spaces @@ -1420,7 +1420,7 @@ yaml: | # The following scalars # are loaded to the # string value '1' '2'. - - !str 12 + - !!str 12 - '12' - "12" - "\ diff --git a/src/Symfony/Component/Yaml/Tests/Fixtures/YtsTypeTransfers.yml b/src/Symfony/Component/Yaml/Tests/Fixtures/YtsTypeTransfers.yml index 5b9df73be1572..dea0be010b58c 100644 --- a/src/Symfony/Component/Yaml/Tests/Fixtures/YtsTypeTransfers.yml +++ b/src/Symfony/Component/Yaml/Tests/Fixtures/YtsTypeTransfers.yml @@ -52,10 +52,10 @@ php: | test: Forcing Strings brief: > Any YAML type can be forced into a string using the - explicit !str method. + explicit !!str method. yaml: | - date string: !str 2001-08-01 - number string: !str 192 + date string: !!str 2001-08-01 + number string: !!str 192 php: | array( 'date string' => '2001-08-01', diff --git a/src/Symfony/Component/Yaml/Tests/InlineTest.php b/src/Symfony/Component/Yaml/Tests/InlineTest.php index 89950251cb242..3d76fbf5a7bf1 100644 --- a/src/Symfony/Component/Yaml/Tests/InlineTest.php +++ b/src/Symfony/Component/Yaml/Tests/InlineTest.php @@ -755,4 +755,13 @@ public function getNotPhpCompatibleMappingKeyData() 'float' => array('{0.25: "foo"}', array('0.25' => 'foo')), ); } + + /** + * @group legacy + * @expectedDeprecation Support for the !str tag is deprecated since version 3.4. Use the !!str tag instead. + */ + public function testDeprecatedStrTag() + { + $this->assertSame(array('foo' => 'bar'), Inline::parse('{ foo: !str bar }')); + } } From b1e8ebc6ac38635446b8bd98bdf318a23d1bbf3f Mon Sep 17 00:00:00 2001 From: Guilhem Niot Date: Thu, 18 May 2017 19:45:50 +0200 Subject: [PATCH 0279/1099] [Yaml] Support tagged scalars --- src/Symfony/Component/Yaml/CHANGELOG.md | 6 ++++ src/Symfony/Component/Yaml/Inline.php | 20 ++++++------ src/Symfony/Component/Yaml/Parser.php | 6 ++-- .../Component/Yaml/Tests/ParserTest.php | 32 +++++++++++++++++-- 4 files changed, 48 insertions(+), 16 deletions(-) diff --git a/src/Symfony/Component/Yaml/CHANGELOG.md b/src/Symfony/Component/Yaml/CHANGELOG.md index be65b535cdd6e..11d46f470d024 100644 --- a/src/Symfony/Component/Yaml/CHANGELOG.md +++ b/src/Symfony/Component/Yaml/CHANGELOG.md @@ -23,6 +23,12 @@ CHANGELOG the parser and dumper is no longer supported, pass bitmask flags instead * the constructor arguments of the `Parser` class have been removed * the `Inline` class is internal and no longer part of the BC promise + * added support for tagged scalars. + + ```yml + Yaml::parse('!foo bar', Yaml::PARSE_CUSTOM_TAGS); + // returns TaggedValue('foo', 'bar'); + ``` 3.4.0 ----- diff --git a/src/Symfony/Component/Yaml/Inline.php b/src/Symfony/Component/Yaml/Inline.php index 45e173dd7211d..73389d7a076cd 100644 --- a/src/Symfony/Component/Yaml/Inline.php +++ b/src/Symfony/Component/Yaml/Inline.php @@ -77,7 +77,7 @@ public static function parse($value, $flags = 0, $references = array()) $result = self::parseScalar($value, $flags, null, $i, null === $tag, $references); } - if (null !== $tag) { + if (null !== $tag && '' !== $tag) { return new TaggedValue($tag, $result); } @@ -379,7 +379,7 @@ private static function parseSequence($sequence, $flags, &$i = 0, $references = --$i; } - if (null !== $tag) { + if (null !== $tag && '' !== $tag) { $value = new TaggedValue($tag, $value); } @@ -489,7 +489,7 @@ private static function parseMapping($mapping, $flags, &$i = 0, $references = ar --$i; } - if (null !== $tag) { + if (null !== $tag && '' !== $tag) { $output[$key] = new TaggedValue($tag, $value); } else { $output[$key] = $value; @@ -582,7 +582,7 @@ private static function evaluateScalar($scalar, $flags, $references = array()) case 0 === strpos($scalar, '!!binary '): return self::evaluateBinaryScalar(substr($scalar, 9)); default: - @trigger_error(sprintf('Using the unquoted scalar value "%s" is deprecated since version 3.3 and will be considered as a tagged value in 4.0. You must quote it.', $scalar), E_USER_DEPRECATED); + throw new ParseException(sprintf('The string "%s" could not be parsed as it uses an unsupported built-in tag.', $scalar)); } // Optimize for returning strings. @@ -650,20 +650,20 @@ private static function parseTag($value, &$i, $flags) $nextOffset = $i + $tagLength + 1; $nextOffset += strspn($value, ' ', $nextOffset); - // Is followed by a scalar - if (!isset($value[$nextOffset]) || !in_array($value[$nextOffset], array('[', '{'), true)) { - // Manage scalars in {@link self::evaluateScalar()} + // Is followed by a scalar and is a built-in tag + if ($tag && (!isset($value[$nextOffset]) || !in_array($value[$nextOffset], array('[', '{'), true)) && ('!' === $tag[0] || 'str' === $tag || 0 === strpos($tag, 'php/const:') || 0 === strpos($tag, 'php/object:'))) { + // Manage in {@link self::evaluateScalar()} return; } + $i = $nextOffset; + // Built-in tags if ($tag && '!' === $tag[0]) { throw new ParseException(sprintf('The built-in tag "!%s" is not implemented.', $tag)); } - if (Yaml::PARSE_CUSTOM_TAGS & $flags) { - $i = $nextOffset; - + if ('' === $tag || Yaml::PARSE_CUSTOM_TAGS & $flags) { return $tag; } diff --git a/src/Symfony/Component/Yaml/Parser.php b/src/Symfony/Component/Yaml/Parser.php index d24179d134a0c..fbd5678454e90 100644 --- a/src/Symfony/Component/Yaml/Parser.php +++ b/src/Symfony/Component/Yaml/Parser.php @@ -609,12 +609,12 @@ private function parseValue($value, $flags, $context) $data = $this->parseBlockScalar($matches['separator'], preg_replace('#\d+#', '', $modifiers), (int) abs($modifiers)); - if ('' !== $matches['tag']) { + if ('' !== $matches['tag'] && '!' !== $matches['tag']) { if ('!!binary' === $matches['tag']) { return Inline::evaluateBinaryScalar($data); - } elseif ('!' !== $matches['tag']) { - @trigger_error(sprintf('Using the custom tag "%s" for the value "%s" is deprecated since version 3.3. It will be replaced by an instance of %s in 4.0.', $matches['tag'], $data, TaggedValue::class), E_USER_DEPRECATED); } + + return new TaggedValue(substr($matches['tag'], 1), $data); } return $data; diff --git a/src/Symfony/Component/Yaml/Tests/ParserTest.php b/src/Symfony/Component/Yaml/Tests/ParserTest.php index 761a145a1089d..570daf6a2a3cd 100644 --- a/src/Symfony/Component/Yaml/Tests/ParserTest.php +++ b/src/Symfony/Component/Yaml/Tests/ParserTest.php @@ -1542,6 +1542,18 @@ public function testCustomTagSupport($expected, $yaml) public function taggedValuesProvider() { return array( + 'scalars' => array( + array( + 'foo' => new TaggedValue('inline', 'bar'), + 'quz' => new TaggedValue('long', 'this is a long text'), + ), + << + this is a long + text +YAML + ), 'sequences' => array( array(new TaggedValue('foo', array('yaml')), new TaggedValue('quz', array('bar'))), <<assertSame('12', $this->parser->parse('! 12')); + } + /** * @expectedException \Symfony\Component\Yaml\Exception\ParseException * @expectedExceptionMessage Tags support is not enabled. Enable the `Yaml::PARSE_CUSTOM_TAGS` flag to use "!iterator" at line 1 (near "!iterator [foo]"). @@ -1579,12 +1596,21 @@ public function testCustomTagsDisabled() } /** - * @group legacy - * @expectedDeprecation Using the unquoted scalar value "!iterator foo" is deprecated since version 3.3 and will be considered as a tagged value in 4.0. You must quote it. + * @expectedException \Symfony\Component\Yaml\Exception\ParseException + * @expectedExceptionMessage Tags support is not enabled. Enable the `Yaml::PARSE_CUSTOM_TAGS` flag to use "!iterator" at line 1 (near "!iterator foo"). */ public function testUnsupportedTagWithScalar() { - $this->assertEquals('!iterator foo', $this->parser->parse('!iterator foo')); + $this->parser->parse('!iterator foo'); + } + + /** + * @expectedException \Symfony\Component\Yaml\Exception\ParseException + * @expectedExceptionMessage The string "!!iterator foo" could not be parsed as it uses an unsupported built-in tag at line 1 (near "!!iterator foo"). + */ + public function testUnsupportedBuiltInTagWithScalar() + { + $this->parser->parse('!!iterator foo'); } /** From abe34405bb3da64bce51e6fe42d40717c1d17ff7 Mon Sep 17 00:00:00 2001 From: Maxime Steinhausser Date: Sun, 25 Jun 2017 09:03:39 +0200 Subject: [PATCH 0280/1099] [Translation] Uncomment YamlFileDumper constructor arg typehint --- src/Symfony/Component/Translation/Dumper/YamlFileDumper.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/Translation/Dumper/YamlFileDumper.php b/src/Symfony/Component/Translation/Dumper/YamlFileDumper.php index ecf00fa64ba92..db9e4b3645a39 100644 --- a/src/Symfony/Component/Translation/Dumper/YamlFileDumper.php +++ b/src/Symfony/Component/Translation/Dumper/YamlFileDumper.php @@ -25,7 +25,7 @@ class YamlFileDumper extends FileDumper { private $extension; - public function __construct(/**string */$extension = 'yml') + public function __construct(string $extension = 'yml') { $this->extension = $extension; } From 9f9697a57d7e4dc07c1d58f621c40619c5777317 Mon Sep 17 00:00:00 2001 From: Maxime Steinhausser Date: Sun, 25 Jun 2017 18:11:24 +0200 Subject: [PATCH 0281/1099] [WebProfilerBundle] Fix css trick used for offsetting html anchor from fixed header --- .../WebProfilerBundle/Resources/views/Profiler/open.css.twig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/open.css.twig b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/open.css.twig index 02bc252f12007..7a0941c955a6d 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/open.css.twig +++ b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/open.css.twig @@ -64,7 +64,7 @@ a.doc:hover { .anchor { position: relative; - padding-top: 7em; - margin-top: -7em; + display: block; + top: -7em; visibility: hidden; } From e9e1534cde99b77188b64dd0db837e57db913aba Mon Sep 17 00:00:00 2001 From: Maxime Steinhausser Date: Sun, 25 Jun 2017 18:46:33 +0200 Subject: [PATCH 0282/1099] [Validator] Remove property path suggestion for using the Expression validator --- src/Symfony/Component/Validator/composer.json | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Symfony/Component/Validator/composer.json b/src/Symfony/Component/Validator/composer.json index f17085aa98c45..36e404ffe92e7 100644 --- a/src/Symfony/Component/Validator/composer.json +++ b/src/Symfony/Component/Validator/composer.json @@ -43,7 +43,6 @@ "symfony/yaml": "", "symfony/config": "", "egulias/email-validator": "Strict (RFC compliant) email validation", - "symfony/property-access": "For using the Expression validator", "symfony/expression-language": "For using the Expression validator" }, "autoload": { From e4ec8e9462fbedf8c802641861576bcda3bbdb7b Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Mon, 26 Jun 2017 09:22:52 +0200 Subject: [PATCH 0283/1099] [Process] remove deprecated features --- src/Symfony/Component/Process/CHANGELOG.md | 14 + src/Symfony/Component/Process/PhpProcess.php | 11 +- src/Symfony/Component/Process/Process.php | 100 +------ .../Component/Process/ProcessBuilder.php | 281 ------------------ .../Component/Process/ProcessUtils.php | 54 ---- .../Process/Tests/ProcessBuilderTest.php | 213 ------------- .../Component/Process/Tests/ProcessTest.php | 34 --- .../Process/Tests/ProcessUtilsTest.php | 53 ---- 8 files changed, 31 insertions(+), 729 deletions(-) delete mode 100644 src/Symfony/Component/Process/ProcessBuilder.php delete mode 100644 src/Symfony/Component/Process/Tests/ProcessBuilderTest.php delete mode 100644 src/Symfony/Component/Process/Tests/ProcessUtilsTest.php diff --git a/src/Symfony/Component/Process/CHANGELOG.md b/src/Symfony/Component/Process/CHANGELOG.md index 7193c498d4326..8cbd98f23f779 100644 --- a/src/Symfony/Component/Process/CHANGELOG.md +++ b/src/Symfony/Component/Process/CHANGELOG.md @@ -1,6 +1,20 @@ CHANGELOG ========= +4.0.0 +----- + + * environment variables will always be inherited + * added a second `array $env = array()` argument to the `start()`, `run()`, + `mustRun()`, and `restart()` methods of the `Process` class + * added a second `array $env = array()` argument to the `start()` method of the + `PhpProcess` class + * the `ProcessUtils::escapeArgument()` method has been removed + * the `areEnvironmentVariablesInherited()`, `getOptions()`, and `setOptions()` + methods of the `Process` class have been removed + * support for passing `proc_open()` options has been removed + * removed the `ProcessBuilder` class, use the `Process` class instead + 3.4.0 ----- diff --git a/src/Symfony/Component/Process/PhpProcess.php b/src/Symfony/Component/Process/PhpProcess.php index 7afd182f5afbb..e2359dfc02e2f 100644 --- a/src/Symfony/Component/Process/PhpProcess.php +++ b/src/Symfony/Component/Process/PhpProcess.php @@ -31,9 +31,8 @@ class PhpProcess extends Process * @param string|null $cwd The working directory or null to use the working dir of the current PHP process * @param array|null $env The environment variables or null to use the same environment as the current PHP process * @param int $timeout The timeout in seconds - * @param array $options An array of options for proc_open */ - public function __construct($script, $cwd = null, array $env = null, $timeout = 60, array $options = null) + public function __construct($script, $cwd = null, array $env = null, $timeout = 60) { $executableFinder = new PhpExecutableFinder(); if (false === $php = $executableFinder->find(false)) { @@ -48,11 +47,8 @@ public function __construct($script, $cwd = null, array $env = null, $timeout = $php[] = $file; $script = null; } - if (null !== $options) { - @trigger_error(sprintf('The $options parameter of the %s constructor is deprecated since version 3.3 and will be removed in 4.0.', __CLASS__), E_USER_DEPRECATED); - } - parent::__construct($php, $cwd, $env, $script, $timeout, $options); + parent::__construct($php, $cwd, $env, $script, $timeout); } /** @@ -66,12 +62,11 @@ public function setPhpBinary($php) /** * {@inheritdoc} */ - public function start(callable $callback = null/*, array $env = array()*/) + public function start(callable $callback = null, array $env = array()) { if (null === $this->getCommandLine()) { throw new RuntimeException('Unable to find the PHP executable.'); } - $env = 1 < func_num_args() ? func_get_arg(1) : null; parent::start($callback, $env); } diff --git a/src/Symfony/Component/Process/Process.php b/src/Symfony/Component/Process/Process.php index cf471ee592b8b..d74c38afe8850 100644 --- a/src/Symfony/Component/Process/Process.php +++ b/src/Symfony/Component/Process/Process.php @@ -58,7 +58,6 @@ class Process implements \IteratorAggregate private $lastOutputTime; private $timeout; private $idleTimeout; - private $options = array('suppress_errors' => true); private $exitcode; private $fallbackStatus = array(); private $processInformation; @@ -73,7 +72,6 @@ class Process implements \IteratorAggregate private $incrementalErrorOutputOffset = 0; private $tty; private $pty; - private $inheritEnv = false; private $useFileHandles = false; /** @var PipesInterface */ @@ -141,11 +139,10 @@ class Process implements \IteratorAggregate * @param array|null $env The environment variables or null to use the same environment as the current PHP process * @param mixed|null $input The input as stream resource, scalar or \Traversable, or null for no input * @param int|float|null $timeout The timeout in seconds or null to disable - * @param array $options An array of options for proc_open * * @throws RuntimeException When proc_open is not installed */ - public function __construct($commandline, $cwd = null, array $env = null, $input = null, $timeout = 60, array $options = null) + public function __construct($commandline, $cwd = null, array $env = null, $input = null, $timeout = 60) { if (!function_exists('proc_open')) { throw new RuntimeException('The Process class relies on proc_open, which is not available on your PHP installation.'); @@ -170,10 +167,6 @@ public function __construct($commandline, $cwd = null, array $env = null, $input $this->useFileHandles = '\\' === DIRECTORY_SEPARATOR; $this->pty = false; $this->enhanceSigchildCompatibility = '\\' !== DIRECTORY_SEPARATOR && $this->isSigchildEnabled(); - if (null !== $options) { - @trigger_error(sprintf('The $options parameter of the %s constructor is deprecated since version 3.3 and will be removed in 4.0.', __CLASS__), E_USER_DEPRECATED); - $this->options = array_replace($this->options, $options); - } } public function __destruct() @@ -208,9 +201,8 @@ public function __clone() * * @final since version 3.3 */ - public function run($callback = null/*, array $env = array()*/) + public function run($callback = null, array $env = array()) { - $env = 1 < func_num_args() ? func_get_arg(1) : null; $this->start($callback, $env); return $this->wait(); @@ -232,12 +224,11 @@ public function run($callback = null/*, array $env = array()*/) * * @final since version 3.3 */ - public function mustRun(callable $callback = null/*, array $env = array()*/) + public function mustRun(callable $callback = null, array $env = array()) { if (!$this->enhanceSigchildCompatibility && $this->isSigchildEnabled()) { throw new RuntimeException('This PHP has been compiled with --enable-sigchild. You must use setEnhanceSigchildCompatibility() to use this method.'); } - $env = 1 < func_num_args() ? func_get_arg(1) : null; if (0 !== $this->run($callback, $env)) { throw new ProcessFailedException($this); @@ -266,29 +257,17 @@ public function mustRun(callable $callback = null/*, array $env = array()*/) * @throws RuntimeException When process is already running * @throws LogicException In case a callback is provided and output has been disabled */ - public function start(callable $callback = null/*, array $env = array()*/) + public function start(callable $callback = null, array $env = array()) { if ($this->isRunning()) { throw new RuntimeException('Process is already running'); } - if (2 <= func_num_args()) { - $env = func_get_arg(1); - } else { - if (__CLASS__ !== static::class) { - $r = new \ReflectionMethod($this, __FUNCTION__); - if (__CLASS__ !== $r->getDeclaringClass()->getName() && (2 > $r->getNumberOfParameters() || 'env' !== $r->getParameters()[0]->name)) { - @trigger_error(sprintf('The %s::start() method expects a second "$env" argument since version 3.3. It will be made mandatory in 4.0.', static::class), E_USER_DEPRECATED); - } - } - $env = null; - } $this->resetProcessData(); $this->starttime = $this->lastOutputTime = microtime(true); $this->callback = $this->buildCallback($callback); $this->hasCallback = null !== $callback; $descriptors = $this->getDescriptors(); - $inheritEnv = $this->inheritEnv; if (is_array($commandline = $this->commandline)) { $commandline = implode(' ', array_map(array($this, 'escapeArgument'), $commandline)); @@ -301,25 +280,23 @@ public function start(callable $callback = null/*, array $env = array()*/) if (null === $env) { $env = $this->env; - } else { - if ($this->env) { - $env += $this->env; - } - $inheritEnv = true; + } elseif ($this->env) { + $env += $this->env; } $envBackup = array(); - if (null !== $env && $inheritEnv) { + if (null !== $env) { foreach ($env as $k => $v) { $envBackup[$k] = getenv($k); putenv(false === $v || null === $v ? $k : "$k=$v"); } $env = null; - } elseif (null !== $env) { - @trigger_error('Not inheriting environment variables is deprecated since Symfony 3.3 and will always happen in 4.0. Set "Process::inheritEnvironmentVariables()" to true instead.', E_USER_DEPRECATED); } + + $options = array('suppress_errors' => true); + if ('\\' === DIRECTORY_SEPARATOR && $this->enhanceWindowsCompatibility) { - $this->options['bypass_shell'] = true; + $options['bypass_shell'] = true; $commandline = $this->prepareWindowsCommandLine($commandline, $envBackup, $env); } elseif (!$this->useFileHandles && $this->enhanceSigchildCompatibility && $this->isSigchildEnabled()) { // last exit code is output on the fourth pipe and caught to work around --enable-sigchild @@ -334,7 +311,7 @@ public function start(callable $callback = null/*, array $env = array()*/) $ptsWorkaround = fopen(__FILE__, 'r'); } - $this->process = proc_open($commandline, $descriptors, $this->processPipes->pipes, $this->cwd, $env, $this->options); + $this->process = proc_open($commandline, $descriptors, $this->processPipes->pipes, $this->cwd, $env, $options); foreach ($envBackup as $k => $v) { putenv(false === $v ? $k : "$k=$v"); @@ -375,12 +352,11 @@ public function start(callable $callback = null/*, array $env = array()*/) * * @final since version 3.3 */ - public function restart(callable $callback = null/*, array $env = array()*/) + public function restart(callable $callback = null, array $env = array()) { if ($this->isRunning()) { throw new RuntimeException('Process is already running'); } - $env = 1 < func_num_args() ? func_get_arg(1) : null; $process = clone $this; $process->start($callback, $env); @@ -1178,38 +1154,6 @@ public function setInput($input) return $this; } - /** - * Gets the options for proc_open. - * - * @return array The current options - * - * @deprecated since version 3.3, to be removed in 4.0. - */ - public function getOptions() - { - @trigger_error(sprintf('The %s() method is deprecated since version 3.3 and will be removed in 4.0.', __METHOD__), E_USER_DEPRECATED); - - return $this->options; - } - - /** - * Sets the options for proc_open. - * - * @param array $options The new options - * - * @return self The current Process instance - * - * @deprecated since version 3.3, to be removed in 4.0. - */ - public function setOptions(array $options) - { - @trigger_error(sprintf('The %s() method is deprecated since version 3.3 and will be removed in 4.0.', __METHOD__), E_USER_DEPRECATED); - - $this->options = $options; - - return $this; - } - /** * Gets whether or not Windows compatibility is enabled. * @@ -1290,28 +1234,12 @@ public function setEnhanceSigchildCompatibility($enhance) public function inheritEnvironmentVariables($inheritEnv = true) { if (!$inheritEnv) { - @trigger_error('Not inheriting environment variables is deprecated since Symfony 3.3 and will always happen in 4.0. Set "Process::inheritEnvironmentVariables()" to true instead.', E_USER_DEPRECATED); + throw new InvalidArgumentException('Not inheriting environment variables is not supported.'); } - $this->inheritEnv = (bool) $inheritEnv; - return $this; } - /** - * Returns whether environment variables will be inherited or not. - * - * @return bool - * - * @deprecated since version 3.3, to be removed in 4.0. Environment variables will always be inherited. - */ - public function areEnvironmentVariablesInherited() - { - @trigger_error(sprintf('The %s() method is deprecated since version 3.3 and will be removed in 4.0. Environment variables will always be inherited.', __METHOD__), E_USER_DEPRECATED); - - return $this->inheritEnv; - } - /** * Performs a check between the timeout definition and the time the process started. * diff --git a/src/Symfony/Component/Process/ProcessBuilder.php b/src/Symfony/Component/Process/ProcessBuilder.php deleted file mode 100644 index 5a54689875d8e..0000000000000 --- a/src/Symfony/Component/Process/ProcessBuilder.php +++ /dev/null @@ -1,281 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Process; - -@trigger_error(sprintf('The %s class is deprecated since version 3.4 and will be removed in 4.0. Use the Process class instead.', ProcessBuilder::class), E_USER_DEPRECATED); - -use Symfony\Component\Process\Exception\InvalidArgumentException; -use Symfony\Component\Process\Exception\LogicException; - -/** - * Process builder. - * - * @author Kris Wallsmith - * - * @deprecated since version 3.4, to be removed in 4.0. Use the Process class instead. - */ -class ProcessBuilder -{ - private $arguments; - private $cwd; - private $env = array(); - private $input; - private $timeout = 60; - private $options; - private $inheritEnv = true; - private $prefix = array(); - private $outputDisabled = false; - - /** - * Constructor. - * - * @param string[] $arguments An array of arguments - */ - public function __construct(array $arguments = array()) - { - $this->arguments = $arguments; - } - - /** - * Creates a process builder instance. - * - * @param string[] $arguments An array of arguments - * - * @return static - */ - public static function create(array $arguments = array()) - { - return new static($arguments); - } - - /** - * Adds an unescaped argument to the command string. - * - * @param string $argument A command argument - * - * @return $this - */ - public function add($argument) - { - $this->arguments[] = $argument; - - return $this; - } - - /** - * Adds a prefix to the command string. - * - * The prefix is preserved when resetting arguments. - * - * @param string|array $prefix A command prefix or an array of command prefixes - * - * @return $this - */ - public function setPrefix($prefix) - { - $this->prefix = is_array($prefix) ? $prefix : array($prefix); - - return $this; - } - - /** - * Sets the arguments of the process. - * - * Arguments must not be escaped. - * Previous arguments are removed. - * - * @param string[] $arguments - * - * @return $this - */ - public function setArguments(array $arguments) - { - $this->arguments = $arguments; - - return $this; - } - - /** - * Sets the working directory. - * - * @param null|string $cwd The working directory - * - * @return $this - */ - public function setWorkingDirectory($cwd) - { - $this->cwd = $cwd; - - return $this; - } - - /** - * Sets whether environment variables will be inherited or not. - * - * @param bool $inheritEnv - * - * @return $this - */ - public function inheritEnvironmentVariables($inheritEnv = true) - { - $this->inheritEnv = $inheritEnv; - - return $this; - } - - /** - * Sets an environment variable. - * - * Setting a variable overrides its previous value. Use `null` to unset a - * defined environment variable. - * - * @param string $name The variable name - * @param null|string $value The variable value - * - * @return $this - */ - public function setEnv($name, $value) - { - $this->env[$name] = $value; - - return $this; - } - - /** - * Adds a set of environment variables. - * - * Already existing environment variables with the same name will be - * overridden by the new values passed to this method. Pass `null` to unset - * a variable. - * - * @param array $variables The variables - * - * @return $this - */ - public function addEnvironmentVariables(array $variables) - { - $this->env = array_replace($this->env, $variables); - - return $this; - } - - /** - * Sets the input of the process. - * - * @param resource|scalar|\Traversable|null $input The input content - * - * @return $this - * - * @throws InvalidArgumentException In case the argument is invalid - */ - public function setInput($input) - { - $this->input = ProcessUtils::validateInput(__METHOD__, $input); - - return $this; - } - - /** - * Sets the process timeout. - * - * To disable the timeout, set this value to null. - * - * @param float|null $timeout - * - * @return $this - * - * @throws InvalidArgumentException - */ - public function setTimeout($timeout) - { - if (null === $timeout) { - $this->timeout = null; - - return $this; - } - - $timeout = (float) $timeout; - - if ($timeout < 0) { - throw new InvalidArgumentException('The timeout value must be a valid positive integer or float number.'); - } - - $this->timeout = $timeout; - - return $this; - } - - /** - * Adds a proc_open option. - * - * @param string $name The option name - * @param string $value The option value - * - * @return $this - */ - public function setOption($name, $value) - { - $this->options[$name] = $value; - - return $this; - } - - /** - * Disables fetching output and error output from the underlying process. - * - * @return $this - */ - public function disableOutput() - { - $this->outputDisabled = true; - - return $this; - } - - /** - * Enables fetching output and error output from the underlying process. - * - * @return $this - */ - public function enableOutput() - { - $this->outputDisabled = false; - - return $this; - } - - /** - * Creates a Process instance and returns it. - * - * @return Process - * - * @throws LogicException In case no arguments have been provided - */ - public function getProcess() - { - if (0 === count($this->prefix) && 0 === count($this->arguments)) { - throw new LogicException('You must add() command arguments before calling getProcess().'); - } - - $arguments = array_merge($this->prefix, $this->arguments); - $process = new Process($arguments, $this->cwd, $this->env, $this->input, $this->timeout, $this->options); - - if ($this->inheritEnv) { - $process->inheritEnvironmentVariables(); - } - if ($this->outputDisabled) { - $process->disableOutput(); - } - - return $process; - } -} diff --git a/src/Symfony/Component/Process/ProcessUtils.php b/src/Symfony/Component/Process/ProcessUtils.php index 24438d985cad9..e0d9c08ab463f 100644 --- a/src/Symfony/Component/Process/ProcessUtils.php +++ b/src/Symfony/Component/Process/ProcessUtils.php @@ -29,55 +29,6 @@ private function __construct() { } - /** - * Escapes a string to be used as a shell argument. - * - * @param string $argument The argument that will be escaped - * - * @return string The escaped argument - * - * @deprecated since version 3.3, to be removed in 4.0. Use a command line array or give env vars to the `Process::start/run()` method instead. - */ - public static function escapeArgument($argument) - { - @trigger_error('The '.__METHOD__.'() method is deprecated since version 3.3 and will be removed in 4.0. Use a command line array or give env vars to the Process::start/run() method instead.', E_USER_DEPRECATED); - - //Fix for PHP bug #43784 escapeshellarg removes % from given string - //Fix for PHP bug #49446 escapeshellarg doesn't work on Windows - //@see https://bugs.php.net/bug.php?id=43784 - //@see https://bugs.php.net/bug.php?id=49446 - if ('\\' === DIRECTORY_SEPARATOR) { - if ('' === $argument) { - return escapeshellarg($argument); - } - - $escapedArgument = ''; - $quote = false; - foreach (preg_split('/(")/', $argument, -1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE) as $part) { - if ('"' === $part) { - $escapedArgument .= '\\"'; - } elseif (self::isSurroundedBy($part, '%')) { - // Avoid environment variable expansion - $escapedArgument .= '^%"'.substr($part, 1, -1).'"^%'; - } else { - // escape trailing backslash - if ('\\' === substr($part, -1)) { - $part .= '\\'; - } - $quote = true; - $escapedArgument .= $part; - } - } - if ($quote) { - $escapedArgument = '"'.$escapedArgument.'"'; - } - - return $escapedArgument; - } - - return "'".str_replace("'", "'\\''", $argument)."'"; - } - /** * Validates and normalizes a Process input. * @@ -115,9 +66,4 @@ public static function validateInput($caller, $input) return $input; } - - private static function isSurroundedBy($arg, $char) - { - return 2 < strlen($arg) && $char === $arg[0] && $char === $arg[strlen($arg) - 1]; - } } diff --git a/src/Symfony/Component/Process/Tests/ProcessBuilderTest.php b/src/Symfony/Component/Process/Tests/ProcessBuilderTest.php deleted file mode 100644 index c1a67afa18bbb..0000000000000 --- a/src/Symfony/Component/Process/Tests/ProcessBuilderTest.php +++ /dev/null @@ -1,213 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Process\Tests; - -use PHPUnit\Framework\TestCase; -use Symfony\Component\Process\ProcessBuilder; - -/** - * @group legacy - */ -class ProcessBuilderTest extends TestCase -{ - public function testInheritEnvironmentVars() - { - $proc = ProcessBuilder::create() - ->add('foo') - ->getProcess(); - - $this->assertTrue($proc->areEnvironmentVariablesInherited()); - - $proc = ProcessBuilder::create() - ->add('foo') - ->inheritEnvironmentVariables(false) - ->getProcess(); - - $this->assertFalse($proc->areEnvironmentVariablesInherited()); - } - - public function testAddEnvironmentVariables() - { - $pb = new ProcessBuilder(); - $env = array( - 'foo' => 'bar', - 'foo2' => 'bar2', - ); - $proc = $pb - ->add('command') - ->setEnv('foo', 'bar2') - ->addEnvironmentVariables($env) - ->getProcess() - ; - - $this->assertSame($env, $proc->getEnv()); - } - - /** - * @expectedException \Symfony\Component\Process\Exception\InvalidArgumentException - */ - public function testNegativeTimeoutFromSetter() - { - $pb = new ProcessBuilder(); - $pb->setTimeout(-1); - } - - public function testNullTimeout() - { - $pb = new ProcessBuilder(); - $pb->setTimeout(10); - $pb->setTimeout(null); - - $r = new \ReflectionObject($pb); - $p = $r->getProperty('timeout'); - $p->setAccessible(true); - - $this->assertNull($p->getValue($pb)); - } - - public function testShouldSetArguments() - { - $pb = new ProcessBuilder(array('initial')); - $pb->setArguments(array('second')); - - $proc = $pb->getProcess(); - - $this->assertContains('second', $proc->getCommandLine()); - } - - public function testPrefixIsPrependedToAllGeneratedProcess() - { - $pb = new ProcessBuilder(); - $pb->setPrefix('/usr/bin/php'); - - $proc = $pb->setArguments(array('-v'))->getProcess(); - if ('\\' === DIRECTORY_SEPARATOR) { - $this->assertEquals('"/usr/bin/php" -v', $proc->getCommandLine()); - } else { - $this->assertEquals("'/usr/bin/php' '-v'", $proc->getCommandLine()); - } - - $proc = $pb->setArguments(array('-i'))->getProcess(); - if ('\\' === DIRECTORY_SEPARATOR) { - $this->assertEquals('"/usr/bin/php" -i', $proc->getCommandLine()); - } else { - $this->assertEquals("'/usr/bin/php' '-i'", $proc->getCommandLine()); - } - } - - public function testArrayPrefixesArePrependedToAllGeneratedProcess() - { - $pb = new ProcessBuilder(); - $pb->setPrefix(array('/usr/bin/php', 'composer.phar')); - - $proc = $pb->setArguments(array('-v'))->getProcess(); - if ('\\' === DIRECTORY_SEPARATOR) { - $this->assertEquals('"/usr/bin/php" composer.phar -v', $proc->getCommandLine()); - } else { - $this->assertEquals("'/usr/bin/php' 'composer.phar' '-v'", $proc->getCommandLine()); - } - - $proc = $pb->setArguments(array('-i'))->getProcess(); - if ('\\' === DIRECTORY_SEPARATOR) { - $this->assertEquals('"/usr/bin/php" composer.phar -i', $proc->getCommandLine()); - } else { - $this->assertEquals("'/usr/bin/php' 'composer.phar' '-i'", $proc->getCommandLine()); - } - } - - public function testShouldEscapeArguments() - { - $pb = new ProcessBuilder(array('%path%', 'foo " bar', '%baz%baz')); - $proc = $pb->getProcess(); - - if ('\\' === DIRECTORY_SEPARATOR) { - $this->assertSame('""^%"path"^%"" "foo "" bar" ""^%"baz"^%"baz"', $proc->getCommandLine()); - } else { - $this->assertSame("'%path%' 'foo \" bar' '%baz%baz'", $proc->getCommandLine()); - } - } - - public function testShouldEscapeArgumentsAndPrefix() - { - $pb = new ProcessBuilder(array('arg')); - $pb->setPrefix('%prefix%'); - $proc = $pb->getProcess(); - - if ('\\' === DIRECTORY_SEPARATOR) { - $this->assertSame('""^%"prefix"^%"" arg', $proc->getCommandLine()); - } else { - $this->assertSame("'%prefix%' 'arg'", $proc->getCommandLine()); - } - } - - /** - * @expectedException \Symfony\Component\Process\Exception\LogicException - */ - public function testShouldThrowALogicExceptionIfNoPrefixAndNoArgument() - { - ProcessBuilder::create()->getProcess(); - } - - public function testShouldNotThrowALogicExceptionIfNoArgument() - { - $process = ProcessBuilder::create() - ->setPrefix('/usr/bin/php') - ->getProcess(); - - if ('\\' === DIRECTORY_SEPARATOR) { - $this->assertEquals('"/usr/bin/php"', $process->getCommandLine()); - } else { - $this->assertEquals("'/usr/bin/php'", $process->getCommandLine()); - } - } - - public function testShouldNotThrowALogicExceptionIfNoPrefix() - { - $process = ProcessBuilder::create(array('/usr/bin/php')) - ->getProcess(); - - if ('\\' === DIRECTORY_SEPARATOR) { - $this->assertEquals('"/usr/bin/php"', $process->getCommandLine()); - } else { - $this->assertEquals("'/usr/bin/php'", $process->getCommandLine()); - } - } - - public function testShouldReturnProcessWithDisabledOutput() - { - $process = ProcessBuilder::create(array('/usr/bin/php')) - ->disableOutput() - ->getProcess(); - - $this->assertTrue($process->isOutputDisabled()); - } - - public function testShouldReturnProcessWithEnabledOutput() - { - $process = ProcessBuilder::create(array('/usr/bin/php')) - ->disableOutput() - ->enableOutput() - ->getProcess(); - - $this->assertFalse($process->isOutputDisabled()); - } - - /** - * @expectedException \Symfony\Component\Process\Exception\InvalidArgumentException - * @expectedExceptionMessage Symfony\Component\Process\ProcessBuilder::setInput only accepts strings, Traversable objects or stream resources. - */ - public function testInvalidInput() - { - $builder = ProcessBuilder::create(); - $builder->setInput(array()); - } -} diff --git a/src/Symfony/Component/Process/Tests/ProcessTest.php b/src/Symfony/Component/Process/Tests/ProcessTest.php index ade11138e3b60..1297e82381b6f 100644 --- a/src/Symfony/Component/Process/Tests/ProcessTest.php +++ b/src/Symfony/Component/Process/Tests/ProcessTest.php @@ -1425,27 +1425,6 @@ public function testEnvIsInherited() $this->assertEquals($expected, $env); } - /** - * @group legacy - */ - public function testInheritEnvDisabled() - { - $process = $this->getProcessForCode('echo serialize($_SERVER);', null, array('BAR' => 'BAZ')); - - putenv('FOO=BAR'); - - $this->assertSame($process, $process->inheritEnvironmentVariables(false)); - $this->assertFalse($process->areEnvironmentVariablesInherited()); - - $process->run(); - - $expected = array('BAR' => 'BAZ', 'FOO' => 'BAR'); - $env = array_intersect_key(unserialize($process->getOutput()), $expected); - unset($expected['FOO']); - - $this->assertSame($expected, $env); - } - public function testGetCommandLine() { $p = new Process(array('/usr/bin/php')); @@ -1465,19 +1444,6 @@ public function testEscapeArgument($arg) $this->assertSame($arg, $p->getOutput()); } - /** - * @dataProvider provideEscapeArgument - * @group legacy - */ - public function testEscapeArgumentWhenInheritEnvDisabled($arg) - { - $p = new Process(array(self::$phpBin, '-r', 'echo $argv[1];', $arg), null, array('BAR' => 'BAZ')); - $p->inheritEnvironmentVariables(false); - $p->run(); - - $this->assertSame($arg, $p->getOutput()); - } - public function provideEscapeArgument() { yield array('a"b%c%'); diff --git a/src/Symfony/Component/Process/Tests/ProcessUtilsTest.php b/src/Symfony/Component/Process/Tests/ProcessUtilsTest.php deleted file mode 100644 index 82fd8cfa8c898..0000000000000 --- a/src/Symfony/Component/Process/Tests/ProcessUtilsTest.php +++ /dev/null @@ -1,53 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Process\Tests; - -use PHPUnit\Framework\TestCase; -use Symfony\Component\Process\ProcessUtils; - -/** - * @group legacy - */ -class ProcessUtilsTest extends TestCase -{ - /** - * @dataProvider dataArguments - */ - public function testEscapeArgument($result, $argument) - { - $this->assertSame($result, ProcessUtils::escapeArgument($argument)); - } - - public function dataArguments() - { - if ('\\' === DIRECTORY_SEPARATOR) { - return array( - array('"\"php\" \"-v\""', '"php" "-v"'), - array('"foo bar"', 'foo bar'), - array('^%"path"^%', '%path%'), - array('"<|>\\" \\"\'f"', '<|>" "\'f'), - array('""', ''), - array('"with\trailingbs\\\\"', 'with\trailingbs\\'), - ); - } - - return array( - array("'\"php\" \"-v\"'", '"php" "-v"'), - array("'foo bar'", 'foo bar'), - array("'%path%'", '%path%'), - array("'<|>\" \"'\\''f'", '<|>" "\'f'), - array("''", ''), - array("'with\\trailingbs\\'", 'with\trailingbs\\'), - array("'withNonAsciiAccentLikeéÉèÈàÀöä'", 'withNonAsciiAccentLikeéÉèÈàÀöä'), - ); - } -} From c5042f35e10288d8a6d40d17c2d7bd5e5075a45c Mon Sep 17 00:00:00 2001 From: Tobias Nyholm Date: Sun, 25 Jun 2017 20:04:17 +0200 Subject: [PATCH 0284/1099] [Workflow] Added more events to the announce function --- src/Symfony/Component/Workflow/Tests/WorkflowTest.php | 2 ++ src/Symfony/Component/Workflow/Workflow.php | 3 +++ 2 files changed, 5 insertions(+) diff --git a/src/Symfony/Component/Workflow/Tests/WorkflowTest.php b/src/Symfony/Component/Workflow/Tests/WorkflowTest.php index c1efb0182765a..bbc9323c154c4 100644 --- a/src/Symfony/Component/Workflow/Tests/WorkflowTest.php +++ b/src/Symfony/Component/Workflow/Tests/WorkflowTest.php @@ -259,6 +259,8 @@ public function testApplyWithEventDispatcher() 'workflow.workflow_name.enter.b', 'workflow.workflow_name.enter.c', // Following events are fired because of announce() method + 'workflow.announce', + 'workflow.workflow_name.announce', 'workflow.guard', 'workflow.workflow_name.guard', 'workflow.workflow_name.guard.t2', diff --git a/src/Symfony/Component/Workflow/Workflow.php b/src/Symfony/Component/Workflow/Workflow.php index ec49895a3c604..3c0b07be3fbaf 100644 --- a/src/Symfony/Component/Workflow/Workflow.php +++ b/src/Symfony/Component/Workflow/Workflow.php @@ -282,6 +282,9 @@ private function announce($subject, Transition $initialTransition, Marking $mark $event = new Event($subject, $marking, $initialTransition); + $this->dispatcher->dispatch('workflow.announce', $event); + $this->dispatcher->dispatch(sprintf('workflow.%s.announce', $this->name), $event); + foreach ($this->getEnabledTransitions($subject) as $transition) { $this->dispatcher->dispatch(sprintf('workflow.%s.announce.%s', $this->name, $transition->getName()), $event); } From 65d89ec2248cfff57d3a26a89433196988d68f1b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pedro=20Magalh=C3=A3es?= Date: Tue, 27 Jun 2017 18:14:10 +0200 Subject: [PATCH 0285/1099] Identify tty tests in Component/Process --- src/Symfony/Component/Process/Tests/ProcessTest.php | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/Symfony/Component/Process/Tests/ProcessTest.php b/src/Symfony/Component/Process/Tests/ProcessTest.php index e034aeb28a743..90689c88cb8e6 100644 --- a/src/Symfony/Component/Process/Tests/ProcessTest.php +++ b/src/Symfony/Component/Process/Tests/ProcessTest.php @@ -439,6 +439,9 @@ public function testExitCodeCommandFailed() $this->assertGreaterThan(0, $process->getExitCode()); } + /** + * @group tty + */ public function testTTYCommand() { if ('\\' === DIRECTORY_SEPARATOR) { @@ -454,6 +457,9 @@ public function testTTYCommand() $this->assertSame(Process::STATUS_TERMINATED, $process->getStatus()); } + /** + * @group tty + */ public function testTTYCommandExitCode() { if ('\\' === DIRECTORY_SEPARATOR) { From b31ebae4cb22233fffc88a7e74720ae7dd58ff16 Mon Sep 17 00:00:00 2001 From: Julien Pauli Date: Wed, 28 Jun 2017 11:49:32 +0200 Subject: [PATCH 0286/1099] Allow * to bind all interfaces (as INADDR_ANY) --- src/Symfony/Bundle/WebServerBundle/CHANGELOG.md | 5 +++++ src/Symfony/Bundle/WebServerBundle/WebServerConfig.php | 3 +++ 2 files changed, 8 insertions(+) diff --git a/src/Symfony/Bundle/WebServerBundle/CHANGELOG.md b/src/Symfony/Bundle/WebServerBundle/CHANGELOG.md index 5fb759ca9729b..5afcf66449e5d 100644 --- a/src/Symfony/Bundle/WebServerBundle/CHANGELOG.md +++ b/src/Symfony/Bundle/WebServerBundle/CHANGELOG.md @@ -1,6 +1,11 @@ CHANGELOG ========= +3.4.0 +----- + + * 'WebServer can now use '*' as a wildcard to bind to 0.0.0.0 (INADDR_ANY) + 3.3.0 ----- diff --git a/src/Symfony/Bundle/WebServerBundle/WebServerConfig.php b/src/Symfony/Bundle/WebServerBundle/WebServerConfig.php index 88ed375dd15e8..c8cd4f75fc2dd 100644 --- a/src/Symfony/Bundle/WebServerBundle/WebServerConfig.php +++ b/src/Symfony/Bundle/WebServerBundle/WebServerConfig.php @@ -54,6 +54,9 @@ public function __construct($documentRoot, $env, $address = null, $router = null $this->port = $this->findBestPort(); } elseif (false !== $pos = strrpos($address, ':')) { $this->hostname = substr($address, 0, $pos); + if ($this->hostname == '*') { + $this->hostname = '0.0.0.0'; + } $this->port = substr($address, $pos + 1); } elseif (ctype_digit($address)) { $this->hostname = '127.0.0.1'; From 8014b38055272ccfe0aaf68fd03c1ce187f236ae Mon Sep 17 00:00:00 2001 From: Robin Chalas Date: Sat, 24 Jun 2017 14:52:30 +0200 Subject: [PATCH 0287/1099] [Security] Fix Firewall ExceptionListener priority --- .../Component/Security/Http/Firewall/ExceptionListener.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/Security/Http/Firewall/ExceptionListener.php b/src/Symfony/Component/Security/Http/Firewall/ExceptionListener.php index 2819018a8c2ae..fc279c0b3ab96 100644 --- a/src/Symfony/Component/Security/Http/Firewall/ExceptionListener.php +++ b/src/Symfony/Component/Security/Http/Firewall/ExceptionListener.php @@ -72,7 +72,7 @@ public function __construct(TokenStorageInterface $tokenStorage, AuthenticationT */ public function register(EventDispatcherInterface $dispatcher) { - $dispatcher->addListener(KernelEvents::EXCEPTION, array($this, 'onKernelException')); + $dispatcher->addListener(KernelEvents::EXCEPTION, array($this, 'onKernelException'), 1); } /** From f527790080d1275d8611094e3a4731ef5e5d365b Mon Sep 17 00:00:00 2001 From: Hugo Hamon Date: Thu, 29 Jun 2017 00:18:27 +0200 Subject: [PATCH 0288/1099] [Security] remove support for defining voters that don't implement the VoterInterface interface. --- UPGRADE-4.0.md | 2 + .../Bundle/SecurityBundle/CHANGELOG.md | 1 + .../Compiler/AddSecurityVotersPass.php | 9 +--- .../Compiler/AddSecurityVotersPassTest.php | 42 ++----------------- src/Symfony/Component/Security/CHANGELOG.md | 3 +- .../Authorization/AccessDecisionManager.php | 32 ++------------ .../AccessDecisionManagerTest.php | 33 --------------- .../Stub/VoterWithoutInterface.php | 22 ---------- 8 files changed, 15 insertions(+), 129 deletions(-) delete mode 100644 src/Symfony/Component/Security/Core/Tests/Authorization/Stub/VoterWithoutInterface.php diff --git a/UPGRADE-4.0.md b/UPGRADE-4.0.md index b1027dc026fad..f026160f8f490 100644 --- a/UPGRADE-4.0.md +++ b/UPGRADE-4.0.md @@ -455,6 +455,8 @@ Security * The `AccessDecisionManager::setVoters()` method has been removed. Pass the voters to the constructor instead. + * Support for defining voters that don't implement the `VoterInterface` has been removed. + SecurityBundle -------------- diff --git a/src/Symfony/Bundle/SecurityBundle/CHANGELOG.md b/src/Symfony/Bundle/SecurityBundle/CHANGELOG.md index 64721afde8566..6ae6503383fab 100644 --- a/src/Symfony/Bundle/SecurityBundle/CHANGELOG.md +++ b/src/Symfony/Bundle/SecurityBundle/CHANGELOG.md @@ -8,6 +8,7 @@ CHANGELOG * made `FirewallMap::$container` and `::$map` private * made the first `UserPasswordEncoderCommand::_construct()` argument mandatory * `UserPasswordEncoderCommand` does not extend `ContainerAwareCommand` anymore + * removed support for voters that don't implement the `VoterInterface` 3.4.0 ----- diff --git a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Compiler/AddSecurityVotersPass.php b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Compiler/AddSecurityVotersPass.php index 67d0785b475fa..6913f555cf762 100644 --- a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Compiler/AddSecurityVotersPass.php +++ b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Compiler/AddSecurityVotersPass.php @@ -38,19 +38,14 @@ public function process(ContainerBuilder $container) $voters = $this->findAndSortTaggedServices('security.voter', $container); if (!$voters) { - throw new LogicException('No security voters found. You need to tag at least one with "security.voter"'); + throw new LogicException('No security voters found. You need to tag at least one with "security.voter".'); } foreach ($voters as $voter) { $class = $container->getDefinition((string) $voter)->getClass(); if (!is_a($class, VoterInterface::class, true)) { - @trigger_error(sprintf('Using a security.voter tag on a class without implementing the %1$s is deprecated as of 3.4 and will be removed in 4.0. Implement the %1$s instead.', VoterInterface::class), E_USER_DEPRECATED); - } - - if (!method_exists($class, 'vote')) { - // in case the vote method is completely missing, to prevent exceptions when voting - throw new LogicException(sprintf('%s should implement the %s interface when used as voter.', $class, VoterInterface::class)); + throw new LogicException(sprintf('%s must implement the %s when used as a voter.', $class, VoterInterface::class)); } } diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Compiler/AddSecurityVotersPassTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Compiler/AddSecurityVotersPassTest.php index a20b39cee8ae7..82205e5912969 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Compiler/AddSecurityVotersPassTest.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Compiler/AddSecurityVotersPassTest.php @@ -14,16 +14,15 @@ use PHPUnit\Framework\TestCase; use Symfony\Bundle\SecurityBundle\DependencyInjection\Compiler\AddSecurityVotersPass; use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Exception\LogicException; use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\Security\Core\Authorization\AccessDecisionManager; use Symfony\Component\Security\Core\Authorization\Voter\Voter; -use Symfony\Component\Security\Core\Tests\Authorization\Stub\VoterWithoutInterface; class AddSecurityVotersPassTest extends TestCase { /** * @expectedException \Symfony\Component\DependencyInjection\Exception\LogicException + * @expectedExceptionMessage No security voters found. You need to tag at least one with "security.voter". */ public function testNoVoters() { @@ -71,8 +70,8 @@ public function testThatSecurityVotersAreProcessedInPriorityOrder() } /** - * @group legacy - * @expectedDeprecation Using a security.voter tag on a class without implementing the Symfony\Component\Security\Core\Authorization\Voter\VoterInterface is deprecated as of 3.4 and will be removed in 4.0. Implement the Symfony\Component\Security\Core\Authorization\Voter\VoterInterface instead. + * @expectedException \Symfony\Component\DependencyInjection\Exception\LogicException + * @expectedExceptionMessage stdClass must implement the Symfony\Component\Security\Core\Authorization\Voter\VoterInterface when used as a voter. */ public function testVoterMissingInterface() { @@ -82,40 +81,7 @@ public function testVoterMissingInterface() ->addArgument(array()) ; $container - ->register('without_interface', VoterWithoutInterface::class) - ->addTag('security.voter') - ; - $compilerPass = new AddSecurityVotersPass(); - $compilerPass->process($container); - - $argument = $container->getDefinition('security.access.decision_manager')->getArgument(0); - $refs = $argument->getValues(); - $this->assertEquals(new Reference('without_interface'), $refs[0]); - $this->assertCount(1, $refs); - } - - /** - * @group legacy - */ - public function testVoterMissingInterfaceAndMethod() - { - $exception = LogicException::class; - $message = 'stdClass should implement the Symfony\Component\Security\Core\Authorization\Voter\VoterInterface interface when used as voter.'; - - if (method_exists($this, 'expectException')) { - $this->expectException($exception); - $this->expectExceptionMessage($message); - } else { - $this->setExpectedException($exception, $message); - } - - $container = new ContainerBuilder(); - $container - ->register('security.access.decision_manager', AccessDecisionManager::class) - ->addArgument(array()) - ; - $container - ->register('without_method', 'stdClass') + ->register('without_interface', 'stdClass') ->addTag('security.voter') ; $compilerPass = new AddSecurityVotersPass(); diff --git a/src/Symfony/Component/Security/CHANGELOG.md b/src/Symfony/Component/Security/CHANGELOG.md index c421f8750323e..d4b6551117aa1 100644 --- a/src/Symfony/Component/Security/CHANGELOG.md +++ b/src/Symfony/Component/Security/CHANGELOG.md @@ -8,7 +8,8 @@ CHANGELOG You should implement this method yourself in your concrete authenticator. * removed the `AccessDecisionManager::setVoters()` method * removed the `RoleInterface` - * added a sixth `string $context` argument to`LogoutUrlGenerator::registerListener()` + * removed support for voters that don't implement the `VoterInterface` + * added a sixth `string $context` argument to `LogoutUrlGenerator::registerListener()` 3.4.0 ----- diff --git a/src/Symfony/Component/Security/Core/Authorization/AccessDecisionManager.php b/src/Symfony/Component/Security/Core/Authorization/AccessDecisionManager.php index 4d6107e61f1b3..a86c6c8a3e6ad 100644 --- a/src/Symfony/Component/Security/Core/Authorization/AccessDecisionManager.php +++ b/src/Symfony/Component/Security/Core/Authorization/AccessDecisionManager.php @@ -13,7 +13,6 @@ use Symfony\Component\Security\Core\Authorization\Voter\VoterInterface; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; -use Symfony\Component\Security\Core\Exception\LogicException; /** * AccessDecisionManager is the base class for all access decision managers @@ -33,7 +32,7 @@ class AccessDecisionManager implements AccessDecisionManagerInterface private $allowIfEqualGrantedDeniedDecisions; /** - * @param iterable|VoterInterface[] $voters An iterator of VoterInterface instances + * @param iterable|VoterInterface[] $voters An array or an iterator of VoterInterface instances * @param string $strategy The vote strategy * @param bool $allowIfAllAbstainDecisions Whether to grant access if all voters abstained or not * @param bool $allowIfEqualGrantedDeniedDecisions Whether to grant access if result are equals @@ -71,7 +70,7 @@ private function decideAffirmative(TokenInterface $token, array $attributes, $ob { $deny = 0; foreach ($this->voters as $voter) { - $result = $this->vote($voter, $token, $object, $attributes); + $result = $voter->vote($token, $object, $attributes); switch ($result) { case VoterInterface::ACCESS_GRANTED: return true; @@ -112,7 +111,7 @@ private function decideConsensus(TokenInterface $token, array $attributes, $obje $grant = 0; $deny = 0; foreach ($this->voters as $voter) { - $result = $this->vote($voter, $token, $object, $attributes); + $result = $voter->vote($token, $object, $attributes); switch ($result) { case VoterInterface::ACCESS_GRANTED: @@ -153,7 +152,7 @@ private function decideUnanimous(TokenInterface $token, array $attributes, $obje $grant = 0; foreach ($this->voters as $voter) { foreach ($attributes as $attribute) { - $result = $this->vote($voter, $token, $object, array($attribute)); + $result = $voter->vote($token, $object, array($attribute)); switch ($result) { case VoterInterface::ACCESS_GRANTED: @@ -177,27 +176,4 @@ private function decideUnanimous(TokenInterface $token, array $attributes, $obje return $this->allowIfAllAbstainDecisions; } - - /** - * TokenInterface vote proxy method. - * - * Acts as a BC layer when the VoterInterface is not implemented on the voter. - * - * @deprecated as of 3.4 and will be removed in 4.0. Call the voter directly as the instance will always be a VoterInterface - */ - private function vote($voter, TokenInterface $token, $subject, $attributes) - { - if ($voter instanceof VoterInterface) { - return $voter->vote($token, $subject, $attributes); - } - - if (method_exists($voter, 'vote')) { - @trigger_error(sprintf('Calling vote() on an voter without %1$s is deprecated as of 3.4 and will be removed in 4.0. Implement the %1$s on your voter.', VoterInterface::class), E_USER_DEPRECATED); - - // making the assumption that the signature matches - return $voter->vote($token, $subject, $attributes); - } - - throw new LogicException(sprintf('%s should implement the %s interface when used as voter.', get_class($voter), VoterInterface::class)); - } } diff --git a/src/Symfony/Component/Security/Core/Tests/Authorization/AccessDecisionManagerTest.php b/src/Symfony/Component/Security/Core/Tests/Authorization/AccessDecisionManagerTest.php index 61d85274fc383..192fe87e2ad93 100644 --- a/src/Symfony/Component/Security/Core/Tests/Authorization/AccessDecisionManagerTest.php +++ b/src/Symfony/Component/Security/Core/Tests/Authorization/AccessDecisionManagerTest.php @@ -12,11 +12,8 @@ namespace Symfony\Component\Security\Core\Tests\Authorization; use PHPUnit\Framework\TestCase; -use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; use Symfony\Component\Security\Core\Authorization\AccessDecisionManager; use Symfony\Component\Security\Core\Authorization\Voter\VoterInterface; -use Symfony\Component\Security\Core\Exception\LogicException; -use Symfony\Component\Security\Core\Tests\Authorization\Stub\VoterWithoutInterface; class AccessDecisionManagerTest extends TestCase { @@ -141,34 +138,4 @@ protected function getVoter($vote) return $voter; } - - public function testVotingWrongTypeNoVoteMethod() - { - $exception = LogicException::class; - $message = sprintf('stdClass should implement the %s interface when used as voter.', VoterInterface::class); - - if (method_exists($this, 'expectException')) { - $this->expectException($exception); - $this->expectExceptionMessage($message); - } else { - $this->setExpectedException($exception, $message); - } - - $adm = new AccessDecisionManager(array(new \stdClass())); - $token = $this->getMockBuilder(TokenInterface::class)->getMock(); - - $adm->decide($token, array('TEST')); - } - - /** - * @group legacy - * @expectedDeprecation Calling vote() on an voter without Symfony\Component\Security\Core\Authorization\Voter\VoterInterface is deprecated as of 3.4 and will be removed in 4.0. Implement the Symfony\Component\Security\Core\Authorization\Voter\VoterInterface on your voter. - */ - public function testVotingWrongTypeWithVote() - { - $adm = new AccessDecisionManager(array(new VoterWithoutInterface())); - $token = $this->getMockBuilder(TokenInterface::class)->getMock(); - - $adm->decide($token, array('TEST')); - } } diff --git a/src/Symfony/Component/Security/Core/Tests/Authorization/Stub/VoterWithoutInterface.php b/src/Symfony/Component/Security/Core/Tests/Authorization/Stub/VoterWithoutInterface.php deleted file mode 100644 index 09c284d3c67fc..0000000000000 --- a/src/Symfony/Component/Security/Core/Tests/Authorization/Stub/VoterWithoutInterface.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Security\Core\Tests\Authorization\Stub; - -/** - * @author Iltar van der Berg - */ -class VoterWithoutInterface -{ - public function vote() - { - } -} From 6cd188bd726746e473ea106568863e187143d181 Mon Sep 17 00:00:00 2001 From: Maxime Steinhausser Date: Thu, 29 Jun 2017 20:05:44 +0200 Subject: [PATCH 0289/1099] [FrameworkBundle] Display a proper warning on cache:clear without the --no-warmup option --- .../Bundle/FrameworkBundle/Command/CacheClearCommand.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/CacheClearCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/CacheClearCommand.php index 8f740c63178b9..2331afecb4e84 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/CacheClearCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/CacheClearCommand.php @@ -77,7 +77,11 @@ protected function execute(InputInterface $input, OutputInterface $output) if ($input->getOption('no-warmup')) { $filesystem->rename($realCacheDir, $oldCacheDir); } else { - @trigger_error('Calling cache:clear without the --no-warmup option is deprecated since version 3.3. Cache warmup should be done with the cache:warmup command instead.', E_USER_DEPRECATED); + $warning = 'Calling cache:clear without the --no-warmup option is deprecated since version 3.3. Cache warmup should be done with the cache:warmup command instead.'; + + @trigger_error($warning, E_USER_DEPRECATED); + + $io->warning($warning); $this->warmupCache($input, $output, $realCacheDir, $oldCacheDir); } From 28930c59d3b985bc41a2125763b32e10c99bc3be Mon Sep 17 00:00:00 2001 From: Maxime Steinhausser Date: Thu, 29 Jun 2017 21:02:30 +0200 Subject: [PATCH 0290/1099] [WebProfilerBundle] Fix full sized dump hovering in toolbar --- .../Resources/views/Profiler/toolbar.css.twig | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/toolbar.css.twig b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/toolbar.css.twig index 7a2d92e134a5f..6cbda5fb3b6a5 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/toolbar.css.twig +++ b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/toolbar.css.twig @@ -350,13 +350,12 @@ 100% { background: #222; } } -.sf-toolbar-block.sf-toolbar-block-dump { - position: static; -} - .sf-toolbar-block.sf-toolbar-block-dump .sf-toolbar-info { max-width: none; - right: 0; + width: 100%; + position: fixed; + box-sizing: border-box; + left: 0; } .sf-toolbar-block-dump pre.sf-dump { From c6d19b197670cc3b3bf119d46af9fd43d33e064b Mon Sep 17 00:00:00 2001 From: Wybren Koelmans Date: Thu, 29 Jun 2017 22:55:41 +0200 Subject: [PATCH 0291/1099] [Yaml][Twig][Lint] Added line numbers to JSON output. --- src/Symfony/Bridge/Twig/Command/LintCommand.php | 2 +- src/Symfony/Component/Yaml/Command/LintCommand.php | 4 ++-- src/Symfony/Component/Yaml/Parser.php | 10 ++++++++++ 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Bridge/Twig/Command/LintCommand.php b/src/Symfony/Bridge/Twig/Command/LintCommand.php index d20b9cf1934ca..01857fc1af08d 100644 --- a/src/Symfony/Bridge/Twig/Command/LintCommand.php +++ b/src/Symfony/Bridge/Twig/Command/LintCommand.php @@ -145,7 +145,7 @@ private function validate(Environment $twig, $template, $file) } catch (Error $e) { $twig->setLoader($realLoader); - return array('template' => $template, 'file' => $file, 'valid' => false, 'exception' => $e); + return array('template' => $template, 'file' => $file, 'line' => $e->getTemplateLine(), 'valid' => false, 'exception' => $e); } return array('template' => $template, 'file' => $file, 'valid' => true); diff --git a/src/Symfony/Component/Yaml/Command/LintCommand.php b/src/Symfony/Component/Yaml/Command/LintCommand.php index 271f2d8474109..f51d4bb38323c 100644 --- a/src/Symfony/Component/Yaml/Command/LintCommand.php +++ b/src/Symfony/Component/Yaml/Command/LintCommand.php @@ -105,7 +105,7 @@ private function validate($content, $file = null) { $prevErrorHandler = set_error_handler(function ($level, $message, $file, $line) use (&$prevErrorHandler) { if (E_USER_DEPRECATED === $level) { - throw new ParseException($message); + throw new ParseException($message, $this->getParser()->getLastLineNumberBeforeDeprecation()); } return $prevErrorHandler ? $prevErrorHandler($level, $message, $file, $line) : false; @@ -114,7 +114,7 @@ private function validate($content, $file = null) try { $this->getParser()->parse($content, Yaml::PARSE_CONSTANT); } catch (ParseException $e) { - return array('file' => $file, 'valid' => false, 'message' => $e->getMessage()); + return array('file' => $file, 'line' => $e->getParsedLine(), 'valid' => false, 'message' => $e->getMessage()); } finally { restore_error_handler(); } diff --git a/src/Symfony/Component/Yaml/Parser.php b/src/Symfony/Component/Yaml/Parser.php index d24179d134a0c..820ed75ad10a7 100644 --- a/src/Symfony/Component/Yaml/Parser.php +++ b/src/Symfony/Component/Yaml/Parser.php @@ -75,6 +75,16 @@ public function parse($value, $flags = 0) return $data; } + /** + * @internal + * + * @return int + */ + public function getLastLineNumberBeforeDeprecation() + { + return $this->getRealCurrentLineNb(); + } + private function doParse($value, $flags) { $this->currentLineNb = -1; From 2de59a73810c6fb5cf9159a418e61d6fc077a098 Mon Sep 17 00:00:00 2001 From: Maxime Steinhausser Date: Thu, 29 Jun 2017 19:50:07 +0200 Subject: [PATCH 0292/1099] [Validator] Throw exception on Comparison constraints null options --- .../Constraints/AbstractComparison.php | 4 ++++ .../AbstractComparisonValidatorTestCase.php | 19 +++++++++++++------ .../Constraints/EqualToValidatorTest.php | 2 +- .../GreaterThanOrEqualValidatorTest.php | 2 +- .../Constraints/GreaterThanValidatorTest.php | 2 +- .../Constraints/IdenticalToValidatorTest.php | 2 +- .../LessThanOrEqualValidatorTest.php | 2 +- .../Constraints/LessThanValidatorTest.php | 2 +- .../Constraints/NotEqualToValidatorTest.php | 2 +- .../NotIdenticalToValidatorTest.php | 2 +- 10 files changed, 25 insertions(+), 14 deletions(-) diff --git a/src/Symfony/Component/Validator/Constraints/AbstractComparison.php b/src/Symfony/Component/Validator/Constraints/AbstractComparison.php index fb1f1f3ef7c75..34466c7cb3251 100644 --- a/src/Symfony/Component/Validator/Constraints/AbstractComparison.php +++ b/src/Symfony/Component/Validator/Constraints/AbstractComparison.php @@ -29,6 +29,10 @@ abstract class AbstractComparison extends Constraint */ public function __construct($options = null) { + if (null === $options) { + $options = array(); + } + if (is_array($options) && !isset($options['value'])) { throw new ConstraintDefinitionException(sprintf( 'The %s constraint requires the "value" option to be set.', diff --git a/src/Symfony/Component/Validator/Tests/Constraints/AbstractComparisonValidatorTestCase.php b/src/Symfony/Component/Validator/Tests/Constraints/AbstractComparisonValidatorTestCase.php index 9c8ce50fc3dd1..8843e6077f6d0 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/AbstractComparisonValidatorTestCase.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/AbstractComparisonValidatorTestCase.php @@ -68,14 +68,21 @@ protected static function addPhp5Dot5Comparisons(array $comparisons) return $result; } + public function provideInvalidConstraintOptions() + { + return array( + array(null), + array(array()), + ); + } + /** + * @dataProvider provideInvalidConstraintOptions * @expectedException \Symfony\Component\Validator\Exception\ConstraintDefinitionException */ - public function testThrowsConstraintExceptionIfNoValueOrProperty() + public function testThrowsConstraintExceptionIfNoValueOrProperty($options) { - $comparison = $this->createConstraint(array()); - - $this->validator->validate('some value', $comparison); + $this->createConstraint($options); } /** @@ -169,9 +176,9 @@ public function provideAllInvalidComparisons() abstract public function provideInvalidComparisons(); /** - * @param array $options Options for the constraint + * @param array|null $options Options for the constraint * * @return Constraint */ - abstract protected function createConstraint(array $options); + abstract protected function createConstraint(array $options = null); } diff --git a/src/Symfony/Component/Validator/Tests/Constraints/EqualToValidatorTest.php b/src/Symfony/Component/Validator/Tests/Constraints/EqualToValidatorTest.php index c20db1550ba27..b396601396429 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/EqualToValidatorTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/EqualToValidatorTest.php @@ -30,7 +30,7 @@ protected function createValidator() return new EqualToValidator(); } - protected function createConstraint(array $options) + protected function createConstraint(array $options = null) { return new EqualTo($options); } diff --git a/src/Symfony/Component/Validator/Tests/Constraints/GreaterThanOrEqualValidatorTest.php b/src/Symfony/Component/Validator/Tests/Constraints/GreaterThanOrEqualValidatorTest.php index 41708f65c966e..923c7e61a08aa 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/GreaterThanOrEqualValidatorTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/GreaterThanOrEqualValidatorTest.php @@ -30,7 +30,7 @@ protected function createValidator() return new GreaterThanOrEqualValidator(); } - protected function createConstraint(array $options) + protected function createConstraint(array $options = null) { return new GreaterThanOrEqual($options); } diff --git a/src/Symfony/Component/Validator/Tests/Constraints/GreaterThanValidatorTest.php b/src/Symfony/Component/Validator/Tests/Constraints/GreaterThanValidatorTest.php index 85a2b1dad18d5..094949d97dfb1 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/GreaterThanValidatorTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/GreaterThanValidatorTest.php @@ -30,7 +30,7 @@ protected function createValidator() return new GreaterThanValidator(); } - protected function createConstraint(array $options) + protected function createConstraint(array $options = null) { return new GreaterThan($options); } diff --git a/src/Symfony/Component/Validator/Tests/Constraints/IdenticalToValidatorTest.php b/src/Symfony/Component/Validator/Tests/Constraints/IdenticalToValidatorTest.php index 0b6a4e411af9f..d7db609e17499 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/IdenticalToValidatorTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/IdenticalToValidatorTest.php @@ -30,7 +30,7 @@ protected function createValidator() return new IdenticalToValidator(); } - protected function createConstraint(array $options) + protected function createConstraint(array $options = null) { return new IdenticalTo($options); } diff --git a/src/Symfony/Component/Validator/Tests/Constraints/LessThanOrEqualValidatorTest.php b/src/Symfony/Component/Validator/Tests/Constraints/LessThanOrEqualValidatorTest.php index 75181355109ff..8f1666ea81572 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/LessThanOrEqualValidatorTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/LessThanOrEqualValidatorTest.php @@ -30,7 +30,7 @@ protected function createValidator() return new LessThanOrEqualValidator(); } - protected function createConstraint(array $options) + protected function createConstraint(array $options = null) { return new LessThanOrEqual($options); } diff --git a/src/Symfony/Component/Validator/Tests/Constraints/LessThanValidatorTest.php b/src/Symfony/Component/Validator/Tests/Constraints/LessThanValidatorTest.php index d555870c120b1..6d216e31644b9 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/LessThanValidatorTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/LessThanValidatorTest.php @@ -30,7 +30,7 @@ protected function createValidator() return new LessThanValidator(); } - protected function createConstraint(array $options) + protected function createConstraint(array $options = null) { return new LessThan($options); } diff --git a/src/Symfony/Component/Validator/Tests/Constraints/NotEqualToValidatorTest.php b/src/Symfony/Component/Validator/Tests/Constraints/NotEqualToValidatorTest.php index bc2c348efade0..c969e2a2af099 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/NotEqualToValidatorTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/NotEqualToValidatorTest.php @@ -30,7 +30,7 @@ protected function createValidator() return new NotEqualToValidator(); } - protected function createConstraint(array $options) + protected function createConstraint(array $options = null) { return new NotEqualTo($options); } diff --git a/src/Symfony/Component/Validator/Tests/Constraints/NotIdenticalToValidatorTest.php b/src/Symfony/Component/Validator/Tests/Constraints/NotIdenticalToValidatorTest.php index 43149847b9c5a..3aed5b7bf60b8 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/NotIdenticalToValidatorTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/NotIdenticalToValidatorTest.php @@ -30,7 +30,7 @@ protected function createValidator() return new NotIdenticalToValidator(); } - protected function createConstraint(array $options) + protected function createConstraint(array $options = null) { return new NotIdenticalTo($options); } From 1baac5a74ff313342f3ca1b3b616b8592eeaa953 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Thu, 29 Jun 2017 23:22:16 +0200 Subject: [PATCH 0293/1099] feature #23294 [Yaml][Lint] Add line numbers to JSON output. (WybrenKoelmans) This PR was merged into the 4.0-dev branch. Discussion ---------- [Yaml][Lint] Add line numbers to JSON output. | Q | A | ------------- | --- | Branch? | 2.7? | Bug fix? | no? | New feature? | yes? | BC breaks? | no? | Deprecations? | no? | Tests pass? | Hopefully | Fixed tickets | n/a | License | MIT | Doc PR | TODO? - [ ] Run tests? - [ ] Check if it will break BC? - [ ] Update changelog? The JSON output is not very useful for me without the line number. I don't want to have to parse it from the message. Is this the right way of doing it? With PR: ``` [ { "file": "", "line": 13, "valid": false, "message": "Unable to parse at line 13 (near \"sdf \")." } ] ``` Before: ``` [ { "file": "", "valid": false, "message": "Unable to parse at line 13 (near \"sdf \")." } ] ``` Commits ------- c6d19b1976 [Yaml][Twig][Lint] Added line numbers to JSON output. --- src/Symfony/Bridge/Twig/Command/LintCommand.php | 2 +- src/Symfony/Component/Yaml/Command/LintCommand.php | 4 ++-- src/Symfony/Component/Yaml/Parser.php | 10 ++++++++++ 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Bridge/Twig/Command/LintCommand.php b/src/Symfony/Bridge/Twig/Command/LintCommand.php index d20b9cf1934ca..01857fc1af08d 100644 --- a/src/Symfony/Bridge/Twig/Command/LintCommand.php +++ b/src/Symfony/Bridge/Twig/Command/LintCommand.php @@ -145,7 +145,7 @@ private function validate(Environment $twig, $template, $file) } catch (Error $e) { $twig->setLoader($realLoader); - return array('template' => $template, 'file' => $file, 'valid' => false, 'exception' => $e); + return array('template' => $template, 'file' => $file, 'line' => $e->getTemplateLine(), 'valid' => false, 'exception' => $e); } return array('template' => $template, 'file' => $file, 'valid' => true); diff --git a/src/Symfony/Component/Yaml/Command/LintCommand.php b/src/Symfony/Component/Yaml/Command/LintCommand.php index 271f2d8474109..f51d4bb38323c 100644 --- a/src/Symfony/Component/Yaml/Command/LintCommand.php +++ b/src/Symfony/Component/Yaml/Command/LintCommand.php @@ -105,7 +105,7 @@ private function validate($content, $file = null) { $prevErrorHandler = set_error_handler(function ($level, $message, $file, $line) use (&$prevErrorHandler) { if (E_USER_DEPRECATED === $level) { - throw new ParseException($message); + throw new ParseException($message, $this->getParser()->getLastLineNumberBeforeDeprecation()); } return $prevErrorHandler ? $prevErrorHandler($level, $message, $file, $line) : false; @@ -114,7 +114,7 @@ private function validate($content, $file = null) try { $this->getParser()->parse($content, Yaml::PARSE_CONSTANT); } catch (ParseException $e) { - return array('file' => $file, 'valid' => false, 'message' => $e->getMessage()); + return array('file' => $file, 'line' => $e->getParsedLine(), 'valid' => false, 'message' => $e->getMessage()); } finally { restore_error_handler(); } diff --git a/src/Symfony/Component/Yaml/Parser.php b/src/Symfony/Component/Yaml/Parser.php index 887e2184a0efb..47471102aaf0d 100644 --- a/src/Symfony/Component/Yaml/Parser.php +++ b/src/Symfony/Component/Yaml/Parser.php @@ -124,6 +124,16 @@ public function parse($value, $flags = 0) return $data; } + /** + * @internal + * + * @return int + */ + public function getLastLineNumberBeforeDeprecation() + { + return $this->getRealCurrentLineNb(); + } + private function doParse($value, $flags) { $this->currentLineNb = -1; From a2ae6bf745f18936ed876cfd34967ffe6e507edd Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Fri, 30 Jun 2017 10:50:50 +0200 Subject: [PATCH 0294/1099] [Yaml] fix the displayed line number `getRealCurrentLineNb()` returns line numbers index by 0 (as they serve as array indexes internally). --- src/Symfony/Component/Yaml/Command/LintCommand.php | 2 +- src/Symfony/Component/Yaml/Parser.php | 14 +++----------- 2 files changed, 4 insertions(+), 12 deletions(-) diff --git a/src/Symfony/Component/Yaml/Command/LintCommand.php b/src/Symfony/Component/Yaml/Command/LintCommand.php index f51d4bb38323c..36025bdebb8b7 100644 --- a/src/Symfony/Component/Yaml/Command/LintCommand.php +++ b/src/Symfony/Component/Yaml/Command/LintCommand.php @@ -105,7 +105,7 @@ private function validate($content, $file = null) { $prevErrorHandler = set_error_handler(function ($level, $message, $file, $line) use (&$prevErrorHandler) { if (E_USER_DEPRECATED === $level) { - throw new ParseException($message, $this->getParser()->getLastLineNumberBeforeDeprecation()); + throw new ParseException($message, $this->getParser()->getRealCurrentLineNb() + 1); } return $prevErrorHandler ? $prevErrorHandler($level, $message, $file, $line) : false; diff --git a/src/Symfony/Component/Yaml/Parser.php b/src/Symfony/Component/Yaml/Parser.php index 47471102aaf0d..1c27af8182be2 100644 --- a/src/Symfony/Component/Yaml/Parser.php +++ b/src/Symfony/Component/Yaml/Parser.php @@ -124,16 +124,6 @@ public function parse($value, $flags = 0) return $data; } - /** - * @internal - * - * @return int - */ - public function getLastLineNumberBeforeDeprecation() - { - return $this->getRealCurrentLineNb(); - } - private function doParse($value, $flags) { $this->currentLineNb = -1; @@ -463,9 +453,11 @@ private function parseBlock($offset, $yaml, $flags) /** * Returns the current line number (takes the offset into account). * + * @internal + * * @return int The current line number */ - private function getRealCurrentLineNb() + public function getRealCurrentLineNb() { $realCurrentLineNumber = $this->currentLineNb + $this->offset; From e0c5040398ff7b26f71d8ad343850014f1c2424a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Fri, 30 Jun 2017 11:17:50 +0200 Subject: [PATCH 0295/1099] [PropertyAccess] Fix TypeError discard --- .../PropertyAccess/PropertyAccessor.php | 2 +- .../Tests/Fixtures/ReturnTyped.php | 31 +++++++++++++++++++ .../Tests/PropertyAccessorTest.php | 13 ++++++++ 3 files changed, 45 insertions(+), 1 deletion(-) create mode 100644 src/Symfony/Component/PropertyAccess/Tests/Fixtures/ReturnTyped.php diff --git a/src/Symfony/Component/PropertyAccess/PropertyAccessor.php b/src/Symfony/Component/PropertyAccess/PropertyAccessor.php index cdb075c84621f..a6615f11e7a5e 100644 --- a/src/Symfony/Component/PropertyAccess/PropertyAccessor.php +++ b/src/Symfony/Component/PropertyAccess/PropertyAccessor.php @@ -245,7 +245,7 @@ public static function handleError($type, $message, $file, $line, $context) private static function throwInvalidArgumentException($message, $trace, $i) { - if (isset($trace[$i]['file']) && __FILE__ === $trace[$i]['file']) { + if (isset($trace[$i]['file']) && __FILE__ === $trace[$i]['file'] && isset($trace[$i]['args'][0])) { $pos = strpos($message, $delim = 'must be of the type ') ?: (strpos($message, $delim = 'must be an instance of ') ?: strpos($message, $delim = 'must implement interface ')); $pos += strlen($delim); $type = $trace[$i]['args'][0]; diff --git a/src/Symfony/Component/PropertyAccess/Tests/Fixtures/ReturnTyped.php b/src/Symfony/Component/PropertyAccess/Tests/Fixtures/ReturnTyped.php new file mode 100644 index 0000000000000..b6a9852715d79 --- /dev/null +++ b/src/Symfony/Component/PropertyAccess/Tests/Fixtures/ReturnTyped.php @@ -0,0 +1,31 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\PropertyAccess\Tests\Fixtures; + +/** + * @author Kévin Dunglas + */ +class ReturnTyped +{ + public function getFoos(): array + { + return 'It doesn\'t respect the return type on purpose'; + } + + public function addFoo(\DateTime $dateTime) + { + } + + public function removeFoo(\DateTime $dateTime) + { + } +} diff --git a/src/Symfony/Component/PropertyAccess/Tests/PropertyAccessorTest.php b/src/Symfony/Component/PropertyAccess/Tests/PropertyAccessorTest.php index fc434adb45a0e..bff2c728f1ca2 100644 --- a/src/Symfony/Component/PropertyAccess/Tests/PropertyAccessorTest.php +++ b/src/Symfony/Component/PropertyAccess/Tests/PropertyAccessorTest.php @@ -14,6 +14,7 @@ use PHPUnit\Framework\TestCase; use Symfony\Component\PropertyAccess\Exception\NoSuchIndexException; use Symfony\Component\PropertyAccess\PropertyAccessor; +use Symfony\Component\PropertyAccess\Tests\Fixtures\ReturnTyped; use Symfony\Component\PropertyAccess\Tests\Fixtures\TestClass; use Symfony\Component\PropertyAccess\Tests\Fixtures\TestClassMagicCall; use Symfony\Component\PropertyAccess\Tests\Fixtures\TestClassMagicGet; @@ -566,4 +567,16 @@ public function testThrowTypeErrorWithInterface() $this->propertyAccessor->setValue($object, 'countable', 'This is a string, \Countable expected.'); } + + /** + * @requires PHP 7 + * + * @expectedException \TypeError + */ + public function testDoNotDiscardReturnTypeError() + { + $object = new ReturnTyped(); + + $this->propertyAccessor->setValue($object, 'foos', array(new \DateTime())); + } } From 1beee4193e7892562dbfd03a313380d35bf6527d Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Fri, 30 Jun 2017 14:56:16 +0200 Subject: [PATCH 0296/1099] remove no longer valid docblock description --- src/Symfony/Component/HttpFoundation/Request.php | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/src/Symfony/Component/HttpFoundation/Request.php b/src/Symfony/Component/HttpFoundation/Request.php index 35ac77d01e727..be749a115001b 100644 --- a/src/Symfony/Component/HttpFoundation/Request.php +++ b/src/Symfony/Component/HttpFoundation/Request.php @@ -783,10 +783,6 @@ public function getClientIps() * being the original client, and each successive proxy that passed the request * adding the IP address where it received the request from. * - * If your reverse proxy uses a different header name than "X-Forwarded-For", - * ("Client-Ip" for instance), configure it via the $trustedHeaderSet - * argument of the Request::setTrustedProxies() method instead. - * * @return string|null The client IP address * * @see getClientIps() @@ -890,10 +886,6 @@ public function getScheme() * * The "X-Forwarded-Port" header must contain the client port. * - * If your reverse proxy uses a different header name than "X-Forwarded-Port", - * configure it via via the $trustedHeaderSet argument of the - * Request::setTrustedProxies() method instead. - * * @return int|string can be a string if fetched from the server bag */ public function getPort() @@ -1108,10 +1100,6 @@ public function getQueryString() * * The "X-Forwarded-Proto" header must contain the protocol: "https" or "http". * - * If your reverse proxy uses a different header name than "X-Forwarded-Proto" - * ("SSL_HTTPS" for instance), configure it via the $trustedHeaderSet - * argument of the Request::setTrustedProxies() method instead. - * * @return bool */ public function isSecure() @@ -1133,10 +1121,6 @@ public function isSecure() * * The "X-Forwarded-Host" header must contain the client host name. * - * If your reverse proxy uses a different header name than "X-Forwarded-Host", - * configure it via the $trustedHeaderSet argument of the - * Request::setTrustedProxies() method instead. - * * @return string * * @throws SuspiciousOperationException when the host name is invalid or not trusted From 66a4fd749d0ffe317d6b8842d1e2dea0f7e31fca Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Fri, 30 Jun 2017 20:34:12 +0200 Subject: [PATCH 0297/1099] parse escaped quotes in unquoted env var values --- src/Symfony/Component/Dotenv/Dotenv.php | 4 ++++ src/Symfony/Component/Dotenv/Tests/DotenvTest.php | 3 +++ 2 files changed, 7 insertions(+) diff --git a/src/Symfony/Component/Dotenv/Dotenv.php b/src/Symfony/Component/Dotenv/Dotenv.php index 1e665fb537a70..3f8623437a473 100644 --- a/src/Symfony/Component/Dotenv/Dotenv.php +++ b/src/Symfony/Component/Dotenv/Dotenv.php @@ -215,6 +215,10 @@ private function lexValue() $notQuoted = true; $prevChr = $this->data[$this->cursor - 1]; while ($this->cursor < $this->end && "\n" !== $this->data[$this->cursor] && !((' ' === $prevChr || "\t" === $prevChr) && '#' === $this->data[$this->cursor])) { + if ('\\' === $this->data[$this->cursor] && isset($this->data[$this->cursor + 1]) && ('"' === $this->data[$this->cursor + 1] || "'" === $this->data[$this->cursor + 1])) { + ++$this->cursor; + } + $value .= $prevChr = $this->data[$this->cursor]; ++$this->cursor; } diff --git a/src/Symfony/Component/Dotenv/Tests/DotenvTest.php b/src/Symfony/Component/Dotenv/Tests/DotenvTest.php index fd0398f318a28..d0dccd7c75541 100644 --- a/src/Symfony/Component/Dotenv/Tests/DotenvTest.php +++ b/src/Symfony/Component/Dotenv/Tests/DotenvTest.php @@ -94,6 +94,9 @@ public function getEnvData() array('FOO=" "', array('FOO' => ' ')), array('PATH="c:\\\\"', array('PATH' => 'c:\\')), array("FOO=\"bar\nfoo\"", array('FOO' => "bar\nfoo")), + array('FOO=BAR\\"', array('FOO' => 'BAR"')), + array("FOO=BAR\\'BAZ", array('FOO' => "BAR'BAZ")), + array('FOO=\\"BAR', array('FOO' => '"BAR')), // concatenated values From d8ba440def44f76ebd7c91cd9e64af34915f3705 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Sat, 1 Jul 2017 09:48:47 +0200 Subject: [PATCH 0298/1099] [Console] fix description of INF default values --- .../Component/Console/Descriptor/JsonDescriptor.php | 4 ++-- .../Component/Console/Descriptor/TextDescriptor.php | 4 ++++ .../Console/Tests/Descriptor/ObjectsProvider.php | 2 ++ .../Fixtures/input_argument_with_default_inf_value.json | 7 +++++++ .../Fixtures/input_argument_with_default_inf_value.md | 7 +++++++ .../Fixtures/input_argument_with_default_inf_value.txt | 1 + .../Fixtures/input_argument_with_default_inf_value.xml | 7 +++++++ .../Fixtures/input_option_with_default_inf_value.json | 9 +++++++++ .../Fixtures/input_option_with_default_inf_value.md | 9 +++++++++ .../Fixtures/input_option_with_default_inf_value.txt | 1 + .../Fixtures/input_option_with_default_inf_value.xml | 7 +++++++ 11 files changed, 56 insertions(+), 2 deletions(-) create mode 100644 src/Symfony/Component/Console/Tests/Fixtures/input_argument_with_default_inf_value.json create mode 100644 src/Symfony/Component/Console/Tests/Fixtures/input_argument_with_default_inf_value.md create mode 100644 src/Symfony/Component/Console/Tests/Fixtures/input_argument_with_default_inf_value.txt create mode 100644 src/Symfony/Component/Console/Tests/Fixtures/input_argument_with_default_inf_value.xml create mode 100644 src/Symfony/Component/Console/Tests/Fixtures/input_option_with_default_inf_value.json create mode 100644 src/Symfony/Component/Console/Tests/Fixtures/input_option_with_default_inf_value.md create mode 100644 src/Symfony/Component/Console/Tests/Fixtures/input_option_with_default_inf_value.txt create mode 100644 src/Symfony/Component/Console/Tests/Fixtures/input_option_with_default_inf_value.xml diff --git a/src/Symfony/Component/Console/Descriptor/JsonDescriptor.php b/src/Symfony/Component/Console/Descriptor/JsonDescriptor.php index 87e38fdb89071..942fdc96226ac 100644 --- a/src/Symfony/Component/Console/Descriptor/JsonDescriptor.php +++ b/src/Symfony/Component/Console/Descriptor/JsonDescriptor.php @@ -103,7 +103,7 @@ private function getInputArgumentData(InputArgument $argument) 'is_required' => $argument->isRequired(), 'is_array' => $argument->isArray(), 'description' => preg_replace('/\s*[\r\n]\s*/', ' ', $argument->getDescription()), - 'default' => $argument->getDefault(), + 'default' => INF === $argument->getDefault() ? 'INF' : $argument->getDefault(), ); } @@ -121,7 +121,7 @@ private function getInputOptionData(InputOption $option) 'is_value_required' => $option->isValueRequired(), 'is_multiple' => $option->isArray(), 'description' => preg_replace('/\s*[\r\n]\s*/', ' ', $option->getDescription()), - 'default' => $option->getDefault(), + 'default' => INF === $option->getDefault() ? 'INF' : $option->getDefault(), ); } diff --git a/src/Symfony/Component/Console/Descriptor/TextDescriptor.php b/src/Symfony/Component/Console/Descriptor/TextDescriptor.php index c0dd4830c3d2d..5b82b3deefa8e 100644 --- a/src/Symfony/Component/Console/Descriptor/TextDescriptor.php +++ b/src/Symfony/Component/Console/Descriptor/TextDescriptor.php @@ -237,6 +237,10 @@ private function writeText($content, array $options = array()) */ private function formatDefaultValue($default) { + if (INF === $default) { + return 'INF'; + } + if (is_string($default)) { $default = OutputFormatter::escape($default); } elseif (is_array($default)) { diff --git a/src/Symfony/Component/Console/Tests/Descriptor/ObjectsProvider.php b/src/Symfony/Component/Console/Tests/Descriptor/ObjectsProvider.php index 8f825ecb68395..b4f34ada19ec6 100644 --- a/src/Symfony/Component/Console/Tests/Descriptor/ObjectsProvider.php +++ b/src/Symfony/Component/Console/Tests/Descriptor/ObjectsProvider.php @@ -32,6 +32,7 @@ public static function getInputArguments() 'input_argument_3' => new InputArgument('argument_name', InputArgument::OPTIONAL, 'argument description', 'default_value'), 'input_argument_4' => new InputArgument('argument_name', InputArgument::REQUIRED, "multiline\nargument description"), 'input_argument_with_style' => new InputArgument('argument_name', InputArgument::OPTIONAL, 'argument description', 'style'), + 'input_argument_with_default_inf_value' => new InputArgument('argument_name', InputArgument::OPTIONAL, 'argument description', INF), ); } @@ -46,6 +47,7 @@ public static function getInputOptions() 'input_option_6' => new InputOption('option_name', array('o', 'O'), InputOption::VALUE_REQUIRED, 'option with multiple shortcuts'), 'input_option_with_style' => new InputOption('option_name', 'o', InputOption::VALUE_REQUIRED, 'option description', 'style'), 'input_option_with_style_array' => new InputOption('option_name', 'o', InputOption::VALUE_IS_ARRAY | InputOption::VALUE_REQUIRED, 'option description', array('Hello', 'world')), + 'input_option_with_default_inf_value' => new InputOption('option_name', 'o', InputOption::VALUE_OPTIONAL, 'option description', INF), ); } diff --git a/src/Symfony/Component/Console/Tests/Fixtures/input_argument_with_default_inf_value.json b/src/Symfony/Component/Console/Tests/Fixtures/input_argument_with_default_inf_value.json new file mode 100644 index 0000000000000..b61ecf7b8c23c --- /dev/null +++ b/src/Symfony/Component/Console/Tests/Fixtures/input_argument_with_default_inf_value.json @@ -0,0 +1,7 @@ +{ + "name": "argument_name", + "is_required": false, + "is_array": false, + "description": "argument description", + "default": "INF" +} diff --git a/src/Symfony/Component/Console/Tests/Fixtures/input_argument_with_default_inf_value.md b/src/Symfony/Component/Console/Tests/Fixtures/input_argument_with_default_inf_value.md new file mode 100644 index 0000000000000..293d816201271 --- /dev/null +++ b/src/Symfony/Component/Console/Tests/Fixtures/input_argument_with_default_inf_value.md @@ -0,0 +1,7 @@ +**argument_name:** + +* Name: argument_name +* Is required: no +* Is array: no +* Description: argument description +* Default: `INF` diff --git a/src/Symfony/Component/Console/Tests/Fixtures/input_argument_with_default_inf_value.txt b/src/Symfony/Component/Console/Tests/Fixtures/input_argument_with_default_inf_value.txt new file mode 100644 index 0000000000000..c32d768c6f328 --- /dev/null +++ b/src/Symfony/Component/Console/Tests/Fixtures/input_argument_with_default_inf_value.txt @@ -0,0 +1 @@ + argument_name argument description [default: INF] diff --git a/src/Symfony/Component/Console/Tests/Fixtures/input_argument_with_default_inf_value.xml b/src/Symfony/Component/Console/Tests/Fixtures/input_argument_with_default_inf_value.xml new file mode 100644 index 0000000000000..d457260070be0 --- /dev/null +++ b/src/Symfony/Component/Console/Tests/Fixtures/input_argument_with_default_inf_value.xml @@ -0,0 +1,7 @@ + + + argument description + + INF + + diff --git a/src/Symfony/Component/Console/Tests/Fixtures/input_option_with_default_inf_value.json b/src/Symfony/Component/Console/Tests/Fixtures/input_option_with_default_inf_value.json new file mode 100644 index 0000000000000..7c96ad30405c6 --- /dev/null +++ b/src/Symfony/Component/Console/Tests/Fixtures/input_option_with_default_inf_value.json @@ -0,0 +1,9 @@ +{ + "name": "--option_name", + "shortcut": "-o", + "accept_value": true, + "is_value_required": false, + "is_multiple": false, + "description": "option description", + "default": "INF" +} diff --git a/src/Symfony/Component/Console/Tests/Fixtures/input_option_with_default_inf_value.md b/src/Symfony/Component/Console/Tests/Fixtures/input_option_with_default_inf_value.md new file mode 100644 index 0000000000000..b57bd04bf9993 --- /dev/null +++ b/src/Symfony/Component/Console/Tests/Fixtures/input_option_with_default_inf_value.md @@ -0,0 +1,9 @@ +**option_name:** + +* Name: `--option_name` +* Shortcut: `-o` +* Accept value: yes +* Is value required: no +* Is multiple: no +* Description: option description +* Default: `INF` diff --git a/src/Symfony/Component/Console/Tests/Fixtures/input_option_with_default_inf_value.txt b/src/Symfony/Component/Console/Tests/Fixtures/input_option_with_default_inf_value.txt new file mode 100644 index 0000000000000..d467dcf42327b --- /dev/null +++ b/src/Symfony/Component/Console/Tests/Fixtures/input_option_with_default_inf_value.txt @@ -0,0 +1 @@ + -o, --option_name[=OPTION_NAME] option description [default: INF] diff --git a/src/Symfony/Component/Console/Tests/Fixtures/input_option_with_default_inf_value.xml b/src/Symfony/Component/Console/Tests/Fixtures/input_option_with_default_inf_value.xml new file mode 100644 index 0000000000000..5d1d21753e9dc --- /dev/null +++ b/src/Symfony/Component/Console/Tests/Fixtures/input_option_with_default_inf_value.xml @@ -0,0 +1,7 @@ + + From baafc7b40921caac6affb4b9f1d5fc6c1fd8ca6c Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Sat, 1 Jul 2017 11:45:13 +0200 Subject: [PATCH 0299/1099] [Dotenv] clean up before running assertions If one of the assertions failed, the clean up part would never happen. --- src/Symfony/Component/Dotenv/Tests/DotenvTest.php | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/Dotenv/Tests/DotenvTest.php b/src/Symfony/Component/Dotenv/Tests/DotenvTest.php index fd0398f318a28..62aa94295e9b7 100644 --- a/src/Symfony/Component/Dotenv/Tests/DotenvTest.php +++ b/src/Symfony/Component/Dotenv/Tests/DotenvTest.php @@ -148,6 +148,13 @@ public function getEnvData() public function testLoad() { + unset($_ENV['FOO']); + unset($_ENV['BAR']); + unset($_SERVER['FOO']); + unset($_SERVER['BAR']); + putenv('FOO'); + putenv('BAR'); + @mkdir($tmpdir = sys_get_temp_dir().'/dotenv'); $path1 = tempnam($tmpdir, 'sf-'); @@ -158,14 +165,17 @@ public function testLoad() (new DotEnv())->load($path1, $path2); - $this->assertSame('BAR', getenv('FOO')); - $this->assertSame('BAZ', getenv('BAR')); + $foo = getenv('FOO'); + $bar = getenv('BAR'); putenv('FOO'); putenv('BAR'); unlink($path1); unlink($path2); rmdir($tmpdir); + + $this->assertSame('BAR', $foo); + $this->assertSame('BAZ', $bar); } /** From c183b0e06d1d7babcdaf27f069ec1f4f1e198163 Mon Sep 17 00:00:00 2001 From: David Maicher Date: Sat, 1 Jul 2017 12:17:16 +0200 Subject: [PATCH 0300/1099] [Cache] fix cleanup of expired items for PdoAdapter --- .../Component/Cache/Adapter/PdoAdapter.php | 2 +- .../Cache/Tests/Adapter/PdoAdapterTest.php | 26 +++++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/Cache/Adapter/PdoAdapter.php b/src/Symfony/Component/Cache/Adapter/PdoAdapter.php index 3fa3a40533d9e..4a462b35c451e 100644 --- a/src/Symfony/Component/Cache/Adapter/PdoAdapter.php +++ b/src/Symfony/Component/Cache/Adapter/PdoAdapter.php @@ -195,7 +195,7 @@ protected function doFetch(array $ids) foreach ($expired as $id) { $stmt->bindValue(++$i, $id); } - $stmt->execute($expired); + $stmt->execute(); } } diff --git a/src/Symfony/Component/Cache/Tests/Adapter/PdoAdapterTest.php b/src/Symfony/Component/Cache/Tests/Adapter/PdoAdapterTest.php index b0d2b9cb8a105..90c9ece8bcc9d 100644 --- a/src/Symfony/Component/Cache/Tests/Adapter/PdoAdapterTest.php +++ b/src/Symfony/Component/Cache/Tests/Adapter/PdoAdapterTest.php @@ -41,4 +41,30 @@ public function createCachePool($defaultLifetime = 0) { return new PdoAdapter('sqlite:'.self::$dbFile, 'ns', $defaultLifetime); } + + public function testCleanupExpiredItems() + { + $pdo = new \PDO('sqlite:'.self::$dbFile); + + $getCacheItemCount = function () use ($pdo) { + return (int) $pdo->query('SELECT COUNT(*) FROM cache_items')->fetch(\PDO::FETCH_COLUMN); + }; + + $this->assertSame(0, $getCacheItemCount()); + + $cache = $this->createCachePool(); + + $item = $cache->getItem('some_nice_key'); + $item->expiresAfter(1); + $item->set(1); + + $cache->save($item); + $this->assertSame(1, $getCacheItemCount()); + + sleep(2); + + $newItem = $cache->getItem($item->getKey()); + $this->assertFalse($newItem->isHit()); + $this->assertSame(0, $getCacheItemCount(), 'PDOAdapter must clean up expired items'); + } } From fd7ad234bc573519134fff1db5a602ebe0e04f71 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Fri, 30 Jun 2017 20:18:03 +0200 Subject: [PATCH 0301/1099] do not validate empty values --- .../Doctrine/Validator/Constraints/UniqueEntityValidator.php | 4 ++++ .../Core/Validator/Constraints/UserPasswordValidator.php | 4 ++++ src/Symfony/Component/Validator/Constraints/UrlValidator.php | 2 +- 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Bridge/Doctrine/Validator/Constraints/UniqueEntityValidator.php b/src/Symfony/Bridge/Doctrine/Validator/Constraints/UniqueEntityValidator.php index 51181b0714e47..b0d9534a0e98d 100644 --- a/src/Symfony/Bridge/Doctrine/Validator/Constraints/UniqueEntityValidator.php +++ b/src/Symfony/Bridge/Doctrine/Validator/Constraints/UniqueEntityValidator.php @@ -62,6 +62,10 @@ public function validate($entity, Constraint $constraint) throw new ConstraintDefinitionException('At least one field has to be specified.'); } + if (null === $entity) { + return; + } + if ($constraint->em) { $em = $this->registry->getManager($constraint->em); diff --git a/src/Symfony/Component/Security/Core/Validator/Constraints/UserPasswordValidator.php b/src/Symfony/Component/Security/Core/Validator/Constraints/UserPasswordValidator.php index 2dc7fee49992e..5f4c146cab469 100644 --- a/src/Symfony/Component/Security/Core/Validator/Constraints/UserPasswordValidator.php +++ b/src/Symfony/Component/Security/Core/Validator/Constraints/UserPasswordValidator.php @@ -39,6 +39,10 @@ public function validate($password, Constraint $constraint) throw new UnexpectedTypeException($constraint, __NAMESPACE__.'\UserPassword'); } + if (null === $password || '' === $password) { + return; + } + $user = $this->tokenStorage->getToken()->getUser(); if (!$user instanceof UserInterface) { diff --git a/src/Symfony/Component/Validator/Constraints/UrlValidator.php b/src/Symfony/Component/Validator/Constraints/UrlValidator.php index 5cb126d8fe2fe..26246fe6d2aad 100644 --- a/src/Symfony/Component/Validator/Constraints/UrlValidator.php +++ b/src/Symfony/Component/Validator/Constraints/UrlValidator.php @@ -48,7 +48,7 @@ public function validate($value, Constraint $constraint) throw new UnexpectedTypeException($constraint, __NAMESPACE__.'\Url'); } - if (null === $value) { + if (null === $value || '' === $value) { return; } From 1880bcfde2678f6f594490a62bd508b0356461fc Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Mon, 3 Jul 2017 09:51:50 +0300 Subject: [PATCH 0302/1099] fixed CS --- src/Symfony/Bundle/WebServerBundle/CHANGELOG.md | 2 +- src/Symfony/Bundle/WebServerBundle/WebServerConfig.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Bundle/WebServerBundle/CHANGELOG.md b/src/Symfony/Bundle/WebServerBundle/CHANGELOG.md index 5afcf66449e5d..af709a0ee45e3 100644 --- a/src/Symfony/Bundle/WebServerBundle/CHANGELOG.md +++ b/src/Symfony/Bundle/WebServerBundle/CHANGELOG.md @@ -4,7 +4,7 @@ CHANGELOG 3.4.0 ----- - * 'WebServer can now use '*' as a wildcard to bind to 0.0.0.0 (INADDR_ANY) + * WebServer can now use '*' as a wildcard to bind to 0.0.0.0 (INADDR_ANY) 3.3.0 ----- diff --git a/src/Symfony/Bundle/WebServerBundle/WebServerConfig.php b/src/Symfony/Bundle/WebServerBundle/WebServerConfig.php index c8cd4f75fc2dd..6c17d110feb01 100644 --- a/src/Symfony/Bundle/WebServerBundle/WebServerConfig.php +++ b/src/Symfony/Bundle/WebServerBundle/WebServerConfig.php @@ -54,7 +54,7 @@ public function __construct($documentRoot, $env, $address = null, $router = null $this->port = $this->findBestPort(); } elseif (false !== $pos = strrpos($address, ':')) { $this->hostname = substr($address, 0, $pos); - if ($this->hostname == '*') { + if ('*' === $this->hostname) { $this->hostname = '0.0.0.0'; } $this->port = substr($address, $pos + 1); From ed3e403b4bf8b183a1fe76559b9b7849c43a8a3e Mon Sep 17 00:00:00 2001 From: Yonel Ceruto Date: Fri, 23 Jun 2017 00:23:25 -0400 Subject: [PATCH 0303/1099] Display a better error design when the toolbar cannot be displayed --- .../Resources/views/Profiler/toolbar.css.twig | 30 +++++++++++++++++++ .../views/Profiler/toolbar_js.html.twig | 18 +++++------ 2 files changed, 38 insertions(+), 10 deletions(-) diff --git a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/toolbar.css.twig b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/toolbar.css.twig index a01a9017f4a49..2e05fb89abe71 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/toolbar.css.twig +++ b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/toolbar.css.twig @@ -440,3 +440,33 @@ visibility: hidden; } } + +/***** Error Toolbar *****/ +.sf-error-toolbar .sf-toolbarreset { + background: #222; + color: #f5f5f5; + font: 13px/36px Arial, sans-serif; + height: 36px; + padding: 0 15px; + text-align: left; +} + +.sf-error-toolbar .sf-toolbarreset svg { + height: auto; +} + +.sf-error-toolbar .sf-toolbarreset a { + color: #99cdd8; + margin-left: 5px; + text-decoration: underline; +} + +.sf-error-toolbar .sf-toolbarreset a:hover { + text-decoration: none; +} + +.sf-error-toolbar .sf-toolbarreset .sf-toolbar-icon { + float: left; + padding: 5px 0; + margin-right: 10px; +} diff --git a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/toolbar_js.html.twig b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/toolbar_js.html.twig index 57537f61a3feb..3bdd8ef1e843e 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/toolbar_js.html.twig +++ b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/toolbar_js.html.twig @@ -57,17 +57,15 @@ } }, function(xhr) { - var errorToolbarHtml = ' - -
An error occurred while loading the web debug toolbar. Open the web profiler.
- '; - if (xhr.status !== 0) { - window.document.body.insertAdjacentHTML('beforeend', errorToolbarHtml); + var sfwdt = document.getElementById('sfwdt{{ token }}'); + sfwdt.innerHTML = '\ +
\ +
\ + An error occurred while loading the web debug toolbar. Open the web profiler.\ +
\ + '; + sfwdt.setAttribute('class', 'sf-toolbar sf-error-toolbar'); } }, {'maxTries': 5} From aaaf64ddde2aa22cb90a1c60fd902865589f5b18 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Fri, 30 Jun 2017 20:34:12 +0200 Subject: [PATCH 0304/1099] [Dotenv] parse concatenated variable values --- src/Symfony/Component/Dotenv/Dotenv.php | 133 +++++++++++------- .../Component/Dotenv/Tests/DotenvTest.php | 5 +- 2 files changed, 89 insertions(+), 49 deletions(-) diff --git a/src/Symfony/Component/Dotenv/Dotenv.php b/src/Symfony/Component/Dotenv/Dotenv.php index 3f8623437a473..00f27bb7b3cdd 100644 --- a/src/Symfony/Component/Dotenv/Dotenv.php +++ b/src/Symfony/Component/Dotenv/Dotenv.php @@ -168,73 +168,110 @@ private function lexValue() throw $this->createFormatException('Whitespace are not supported before the value'); } - $value = ''; - $singleQuoted = false; - $notQuoted = false; - if ("'" === $this->data[$this->cursor]) { - $singleQuoted = true; - ++$this->cursor; - while ("\n" !== $this->data[$this->cursor]) { - if ("'" === $this->data[$this->cursor]) { - if ($this->cursor + 1 === $this->end) { - break; - } - if ("'" !== $this->data[$this->cursor + 1]) { + $v = ''; + + do { + if ("'" === $this->data[$this->cursor]) { + $value = ''; + ++$this->cursor; + + while ("\n" !== $this->data[$this->cursor]) { + if ("'" === $this->data[$this->cursor]) { break; } - + $value .= $this->data[$this->cursor]; ++$this->cursor; - } - $value .= $this->data[$this->cursor]; - ++$this->cursor; - if ($this->cursor === $this->end) { + if ($this->cursor === $this->end) { + throw $this->createFormatException('Missing quote to end the value'); + } + } + if ("\n" === $this->data[$this->cursor]) { throw $this->createFormatException('Missing quote to end the value'); } - } - if ("\n" === $this->data[$this->cursor]) { - throw $this->createFormatException('Missing quote to end the value'); - } - ++$this->cursor; - } elseif ('"' === $this->data[$this->cursor]) { - ++$this->cursor; - while ('"' !== $this->data[$this->cursor] || ('\\' === $this->data[$this->cursor - 1] && '\\' !== $this->data[$this->cursor - 2])) { - $value .= $this->data[$this->cursor]; ++$this->cursor; + $v .= $value; + } elseif ('"' === $this->data[$this->cursor]) { + $value = ''; + ++$this->cursor; + + while ('"' !== $this->data[$this->cursor] || ('\\' === $this->data[$this->cursor - 1] && '\\' !== $this->data[$this->cursor - 2])) { + $value .= $this->data[$this->cursor]; + ++$this->cursor; - if ($this->cursor === $this->end) { + if ($this->cursor === $this->end) { + throw $this->createFormatException('Missing quote to end the value'); + } + } + if ("\n" === $this->data[$this->cursor]) { throw $this->createFormatException('Missing quote to end the value'); } - } - if ("\n" === $this->data[$this->cursor]) { - throw $this->createFormatException('Missing quote to end the value'); - } - ++$this->cursor; - $value = str_replace(array('\\\\', '\\"', '\r', '\n'), array('\\', '"', "\r", "\n"), $value); - } else { - $notQuoted = true; - $prevChr = $this->data[$this->cursor - 1]; - while ($this->cursor < $this->end && "\n" !== $this->data[$this->cursor] && !((' ' === $prevChr || "\t" === $prevChr) && '#' === $this->data[$this->cursor])) { - if ('\\' === $this->data[$this->cursor] && isset($this->data[$this->cursor + 1]) && ('"' === $this->data[$this->cursor + 1] || "'" === $this->data[$this->cursor + 1])) { + ++$this->cursor; + $value = str_replace(array('\\\\', '\\"', '\r', '\n'), array('\\', '"', "\r", "\n"), $value); + $resolvedValue = $value; + $resolvedValue = $this->resolveVariables($resolvedValue); + $resolvedValue = $this->resolveCommands($resolvedValue); + $v .= $resolvedValue; + } else { + $value = ''; + $prevChr = $this->data[$this->cursor - 1]; + while ($this->cursor < $this->end && !in_array($this->data[$this->cursor], array("\n", '"', "'"), true) && !((' ' === $prevChr || "\t" === $prevChr) && '#' === $this->data[$this->cursor])) { + if ('\\' === $this->data[$this->cursor] && isset($this->data[$this->cursor + 1]) && ('"' === $this->data[$this->cursor + 1] || "'" === $this->data[$this->cursor + 1])) { + ++$this->cursor; + } + + $value .= $prevChr = $this->data[$this->cursor]; + + if ('$' === $this->data[$this->cursor] && isset($this->data[$this->cursor + 1]) && '(' === $this->data[$this->cursor + 1]) { + ++$this->cursor; + $value .= '('.$this->lexNestedExpression().')'; + } + ++$this->cursor; } + $value = rtrim($value); + $resolvedValue = $value; + $resolvedValue = $this->resolveVariables($resolvedValue); + $resolvedValue = $this->resolveCommands($resolvedValue); - $value .= $prevChr = $this->data[$this->cursor]; - ++$this->cursor; + if ($resolvedValue === $value && preg_match('/\s+/', $value)) { + throw $this->createFormatException('A value containing spaces must be surrounded by quotes'); + } + + $v .= $resolvedValue; + + if ($this->cursor < $this->end && '#' === $this->data[$this->cursor]) { + break; + } } - $value = rtrim($value); - } + } while ($this->cursor < $this->end && "\n" !== $this->data[$this->cursor]); $this->skipEmptyLines(); - $currentValue = $value; - if (!$singleQuoted) { - $value = $this->resolveVariables($value); - $value = $this->resolveCommands($value); + return $v; + } + + private function lexNestedExpression() + { + ++$this->cursor; + $value = ''; + + while ("\n" !== $this->data[$this->cursor] && ')' !== $this->data[$this->cursor]) { + $value .= $this->data[$this->cursor]; + + if ('(' === $this->data[$this->cursor]) { + $value .= $this->lexNestedExpression().')'; + } + + ++$this->cursor; + + if ($this->cursor === $this->end) { + throw $this->createFormatException('Missing closing parenthesis.'); + } } - if ($notQuoted && $currentValue == $value && preg_match('/\s+/', $value)) { - throw $this->createFormatException('A value containing spaces must be surrounded by quotes'); + if ("\n" === $this->data[$this->cursor]) { + throw $this->createFormatException('Missing closing parenthesis.'); } return $value; diff --git a/src/Symfony/Component/Dotenv/Tests/DotenvTest.php b/src/Symfony/Component/Dotenv/Tests/DotenvTest.php index c257b84f0f017..a7f211ecd6e37 100644 --- a/src/Symfony/Component/Dotenv/Tests/DotenvTest.php +++ b/src/Symfony/Component/Dotenv/Tests/DotenvTest.php @@ -85,7 +85,6 @@ public function getEnvData() array("FOO='bar'\n", array('FOO' => 'bar')), array("FOO='bar\"foo'\n", array('FOO' => 'bar"foo')), array("FOO=\"bar\\\"foo\"\n", array('FOO' => 'bar"foo')), - array("FOO='bar''foo'\n", array('FOO' => 'bar\'foo')), array('FOO="bar\nfoo"', array('FOO' => "bar\nfoo")), array('FOO="bar\rfoo"', array('FOO' => "bar\rfoo")), array('FOO=\'bar\nfoo\'', array('FOO' => 'bar\nfoo')), @@ -99,6 +98,10 @@ public function getEnvData() array('FOO=\\"BAR', array('FOO' => '"BAR')), // concatenated values + array("FOO='bar''foo'\n", array('FOO' => 'barfoo')), + array("FOO='bar '' baz'", array('FOO' => 'bar baz')), + array("FOO=bar\nBAR='baz'\"\$FOO\"", array('FOO' => 'bar', 'BAR' => 'bazbar')), + array("FOO='bar '\\'' baz'", array('FOO' => "bar ' baz")), // comments array("#FOO=bar\nBAR=foo", array('BAR' => 'foo')), From 471b84c1a2545c65c226c50aebcddf5c1c36a6c7 Mon Sep 17 00:00:00 2001 From: "Nek (Maxime Veber)" Date: Sat, 17 Jun 2017 18:01:46 +0200 Subject: [PATCH 0305/1099] Remove HHVM support (second edition) --- .../Cache/Adapter/PhpArrayAdapter.php | 2 +- .../Component/Cache/Simple/PhpArrayCache.php | 2 +- src/Symfony/Component/Debug/ErrorHandler.php | 33 +++++-------------- .../ArgumentMetadataFactory.php | 7 +--- .../Data/Bundle/Reader/IntlBundleReader.php | 1 - .../Extractor/ReflectionExtractor.php | 5 --- .../Translation/Loader/IcuDatFileLoader.php | 1 - .../Translation/Loader/IcuResFileLoader.php | 1 - 8 files changed, 11 insertions(+), 41 deletions(-) diff --git a/src/Symfony/Component/Cache/Adapter/PhpArrayAdapter.php b/src/Symfony/Component/Cache/Adapter/PhpArrayAdapter.php index 69b712dbb4f33..e62ed9b575f8f 100644 --- a/src/Symfony/Component/Cache/Adapter/PhpArrayAdapter.php +++ b/src/Symfony/Component/Cache/Adapter/PhpArrayAdapter.php @@ -62,7 +62,7 @@ function ($key, $value, $isHit) { */ public static function create($file, CacheItemPoolInterface $fallbackPool) { - // Shared memory is available in PHP 7.0+ with OPCache enabled and in HHVM + // Shared memory is available in PHP 7.0+ with OPCache enabled if (ini_get('opcache.enable')) { if (!$fallbackPool instanceof AdapterInterface) { $fallbackPool = new ProxyAdapter($fallbackPool); diff --git a/src/Symfony/Component/Cache/Simple/PhpArrayCache.php b/src/Symfony/Component/Cache/Simple/PhpArrayCache.php index 3dfc7767e6c92..1c1ea42e0bc20 100644 --- a/src/Symfony/Component/Cache/Simple/PhpArrayCache.php +++ b/src/Symfony/Component/Cache/Simple/PhpArrayCache.php @@ -45,7 +45,7 @@ public function __construct($file, CacheInterface $fallbackPool) */ public static function create($file, CacheInterface $fallbackPool) { - // Shared memory is available in PHP 7.0+ with OPCache enabled and in HHVM + // Shared memory is available in PHP 7.0+ with OPCache enabled if (ini_get('opcache.enable')) { return new static($file, $fallbackPool); } diff --git a/src/Symfony/Component/Debug/ErrorHandler.php b/src/Symfony/Component/Debug/ErrorHandler.php index 6389b1c8c24e0..ddcf193da66ee 100644 --- a/src/Symfony/Component/Debug/ErrorHandler.php +++ b/src/Symfony/Component/Debug/ErrorHandler.php @@ -382,10 +382,8 @@ public function handleError($type, $message, $file, $line) if (4 < $numArgs = func_num_args()) { $context = $scope ? (func_get_arg(4) ?: array()) : array(); - $backtrace = 5 < $numArgs ? func_get_arg(5) : null; // defined on HHVM } else { $context = array(); - $backtrace = null; } if (isset($context['GLOBALS']) && $scope) { @@ -394,15 +392,6 @@ public function handleError($type, $message, $file, $line) $context = $e; } - if (null !== $backtrace && $type & E_ERROR) { - // E_ERROR fatal errors are triggered on HHVM when - // hhvm.error_handling.call_user_handler_on_fatals=1 - // which is the way to get their backtrace. - $this->handleFatalError(compact('type', 'message', 'file', 'line', 'backtrace')); - - return true; - } - $logMessage = $this->levels[$type].': '.$message; if (null !== self::$toStringException) { @@ -436,11 +425,12 @@ public function handleError($type, $message, $file, $line) // Clean the trace by removing function arguments and the first frames added by the error handler itself. if ($throw || $this->tracedErrors & $type) { - $backtrace = $backtrace ?: $errorAsException->getTrace(); + $backtrace = $errorAsException->getTrace(); $lightTrace = $this->cleanTrace($backtrace, $type, $file, $line, $throw); $this->traceReflector->setValue($errorAsException, $lightTrace); } else { $this->traceReflector->setValue($errorAsException, array()); + $backtrace = array(); } } @@ -454,32 +444,25 @@ public function handleError($type, $message, $file, $line) && ('trigger_error' === $backtrace[$i - 1]['function'] || 'user_error' === $backtrace[$i - 1]['function']) ) { // Here, we know trigger_error() has been called from __toString(). - // HHVM is fine with throwing from __toString() but PHP triggers a fatal error instead. + // PHP triggers a fatal error when throwing from __toString(). // A small convention allows working around the limitation: // given a caught $e exception in __toString(), quitting the method with // `return trigger_error($e, E_USER_ERROR);` allows this error handler // to make $e get through the __toString() barrier. foreach ($context as $e) { - if (($e instanceof \Exception || $e instanceof \Throwable) && $e->__toString() === $message) { - if (1 === $i) { - // On HHVM - $errorAsException = $e; - break; - } + if ($e instanceof \Throwable && $e->__toString() === $message) { self::$toStringException = $e; return true; } } - if (1 < $i) { - // On PHP (not on HHVM), display the original error message instead of the default one. - $this->handleException($errorAsException); + // Display the original error message instead of the default one. + $this->handleException($errorAsException); - // Stop the process by giving back the error to the native handler. - return false; - } + // Stop the process by giving back the error to the native handler. + return false; } } } diff --git a/src/Symfony/Component/HttpKernel/ControllerMetadata/ArgumentMetadataFactory.php b/src/Symfony/Component/HttpKernel/ControllerMetadata/ArgumentMetadataFactory.php index 3208a2866727e..646adc074bf6a 100644 --- a/src/Symfony/Component/HttpKernel/ControllerMetadata/ArgumentMetadataFactory.php +++ b/src/Symfony/Component/HttpKernel/ControllerMetadata/ArgumentMetadataFactory.php @@ -52,12 +52,7 @@ private function getType(\ReflectionParameter $parameter) if (!$type = $parameter->getType()) { return; } - $typeName = $type->getName(); - if ('array' === $typeName && !$type->isBuiltin()) { - // Special case for HHVM with variadics - return; - } - return $typeName; + return $type->getName(); } } diff --git a/src/Symfony/Component/Intl/Data/Bundle/Reader/IntlBundleReader.php b/src/Symfony/Component/Intl/Data/Bundle/Reader/IntlBundleReader.php index 9f800ccace7ef..375d3fe84658a 100644 --- a/src/Symfony/Component/Intl/Data/Bundle/Reader/IntlBundleReader.php +++ b/src/Symfony/Component/Intl/Data/Bundle/Reader/IntlBundleReader.php @@ -34,7 +34,6 @@ public function read($path, $locale) // Never enable fallback. We want to know if a bundle cannot be found $bundle = new \ResourceBundle($locale, $path, false); } catch (\Exception $e) { - // HHVM compatibility: constructor throws on invalid resource $bundle = null; } diff --git a/src/Symfony/Component/PropertyInfo/Extractor/ReflectionExtractor.php b/src/Symfony/Component/PropertyInfo/Extractor/ReflectionExtractor.php index 45e82de1e72b9..838fb9c4177f4 100644 --- a/src/Symfony/Component/PropertyInfo/Extractor/ReflectionExtractor.php +++ b/src/Symfony/Component/PropertyInfo/Extractor/ReflectionExtractor.php @@ -177,11 +177,6 @@ private function extractFromMutator($class, $property) } $type = $this->extractFromReflectionType($reflectionType); - // HHVM reports variadics with "array" but not builtin type hints - if (!$reflectionType->isBuiltin() && Type::BUILTIN_TYPE_ARRAY === $type->getBuiltinType()) { - return; - } - if (in_array($prefix, $this->arrayMutatorPrefixes)) { $type = new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, new Type(Type::BUILTIN_TYPE_INT), $type); } diff --git a/src/Symfony/Component/Translation/Loader/IcuDatFileLoader.php b/src/Symfony/Component/Translation/Loader/IcuDatFileLoader.php index 71ba90a39d9cc..822bc362072a8 100644 --- a/src/Symfony/Component/Translation/Loader/IcuDatFileLoader.php +++ b/src/Symfony/Component/Translation/Loader/IcuDatFileLoader.php @@ -39,7 +39,6 @@ public function load($resource, $locale, $domain = 'messages') try { $rb = new \ResourceBundle($locale, $resource); } catch (\Exception $e) { - // HHVM compatibility: constructor throws on invalid resource $rb = null; } diff --git a/src/Symfony/Component/Translation/Loader/IcuResFileLoader.php b/src/Symfony/Component/Translation/Loader/IcuResFileLoader.php index 2f8037fb164d8..47fe28f73f534 100644 --- a/src/Symfony/Component/Translation/Loader/IcuResFileLoader.php +++ b/src/Symfony/Component/Translation/Loader/IcuResFileLoader.php @@ -39,7 +39,6 @@ public function load($resource, $locale, $domain = 'messages') try { $rb = new \ResourceBundle($locale, $resource); } catch (\Exception $e) { - // HHVM compatibility: constructor throws on invalid resource $rb = null; } From b576f46c26ea5801e889a04fac2fe181c40cee5c Mon Sep 17 00:00:00 2001 From: mcorteel Date: Mon, 3 Jul 2017 09:17:38 +0200 Subject: [PATCH 0306/1099] Misspelled word MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The French word "chaine" should be spelled "chaîne". --- .../Validator/Resources/translations/validators.fr.xlf | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.fr.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.fr.xlf index b50ecbc63a1b5..e28ea54b4512c 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.fr.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.fr.xlf @@ -76,7 +76,7 @@ This value is too long. It should have {{ limit }} character or less.|This value is too long. It should have {{ limit }} characters or less. - Cette chaine est trop longue. Elle doit avoir au maximum {{ limit }} caractère.|Cette chaine est trop longue. Elle doit avoir au maximum {{ limit }} caractères. + Cette chaîne est trop longue. Elle doit avoir au maximum {{ limit }} caractère.|Cette chaîne est trop longue. Elle doit avoir au maximum {{ limit }} caractères. This value should be {{ limit }} or more. @@ -84,7 +84,7 @@ This value is too short. It should have {{ limit }} character or more.|This value is too short. It should have {{ limit }} characters or more. - Cette chaine est trop courte. Elle doit avoir au minimum {{ limit }} caractère.|Cette chaine est trop courte. Elle doit avoir au minimum {{ limit }} caractères. + Cette chaîne est trop courte. Elle doit avoir au minimum {{ limit }} caractère.|Cette chaîne est trop courte. Elle doit avoir au minimum {{ limit }} caractères. This value should not be blank. @@ -180,7 +180,7 @@ This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters. - Cette chaine doit avoir exactement {{ limit }} caractère.|Cette chaine doit avoir exactement {{ limit }} caractères. + Cette chaîne doit avoir exactement {{ limit }} caractère.|Cette chaîne doit avoir exactement {{ limit }} caractères. The file was only partially uploaded. From 1dbdf1c864efa33af651de7451bec890f2c8acdb Mon Sep 17 00:00:00 2001 From: Dany Maillard Date: Fri, 14 Apr 2017 02:47:17 +0200 Subject: [PATCH 0307/1099] Add DateCaster --- .../Component/VarDumper/Caster/DateCaster.php | 41 +++++++++ .../VarDumper/Cloner/AbstractCloner.php | 2 + .../VarDumper/Tests/Caster/DateCasterTest.php | 87 +++++++++++++++++++ 3 files changed, 130 insertions(+) create mode 100644 src/Symfony/Component/VarDumper/Caster/DateCaster.php create mode 100644 src/Symfony/Component/VarDumper/Tests/Caster/DateCasterTest.php diff --git a/src/Symfony/Component/VarDumper/Caster/DateCaster.php b/src/Symfony/Component/VarDumper/Caster/DateCaster.php new file mode 100644 index 0000000000000..2fc57c190b7c3 --- /dev/null +++ b/src/Symfony/Component/VarDumper/Caster/DateCaster.php @@ -0,0 +1,41 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\VarDumper\Caster; + +use Symfony\Component\VarDumper\Cloner\Stub; + +/** + * Casts DateTimeInterface related classes to array representation. + * + * @author Dany Maillard + */ +class DateCaster +{ + public static function castDateTime(\DateTimeInterface $d, array $a, Stub $stub, $isNested, $filter) + { + $prefix = Caster::PREFIX_VIRTUAL; + $location = $d->getTimezone()->getLocation(); + $fromNow = (new \DateTime())->diff($d); + + $title = $d->format('l, F j, Y') + ."\n".$fromNow->format('%R').(ltrim($fromNow->format('%yy %mm %dd %H:%I:%Ss'), ' 0ymd:s') ?: '0s').' from now' + .($location ? ($d->format('I') ? "\nDST On" : "\nDST Off") : '') + ; + + $a = array(); + $a[$prefix.'date'] = new ConstStub($d->format('Y-m-d H:i:s.u '.($location ? 'e (P)' : 'P')), $title); + + $stub->class .= $d->format(' @U'); + + return $a; + } +} diff --git a/src/Symfony/Component/VarDumper/Cloner/AbstractCloner.php b/src/Symfony/Component/VarDumper/Cloner/AbstractCloner.php index c07ae491c5dc0..bb2a4b85078f4 100644 --- a/src/Symfony/Component/VarDumper/Cloner/AbstractCloner.php +++ b/src/Symfony/Component/VarDumper/Cloner/AbstractCloner.php @@ -109,6 +109,8 @@ abstract class AbstractCloner implements ClonerInterface 'Redis' => array('Symfony\Component\VarDumper\Caster\RedisCaster', 'castRedis'), 'RedisArray' => array('Symfony\Component\VarDumper\Caster\RedisCaster', 'castRedisArray'), + 'DateTimeInterface' => array('Symfony\Component\VarDumper\Caster\DateCaster', 'castDateTime'), + ':curl' => array('Symfony\Component\VarDumper\Caster\ResourceCaster', 'castCurl'), ':dba' => array('Symfony\Component\VarDumper\Caster\ResourceCaster', 'castDba'), ':dba persistent' => array('Symfony\Component\VarDumper\Caster\ResourceCaster', 'castDba'), diff --git a/src/Symfony/Component/VarDumper/Tests/Caster/DateCasterTest.php b/src/Symfony/Component/VarDumper/Tests/Caster/DateCasterTest.php new file mode 100644 index 0000000000000..10f7896aec8a3 --- /dev/null +++ b/src/Symfony/Component/VarDumper/Tests/Caster/DateCasterTest.php @@ -0,0 +1,87 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\VarDumper\Tests\Caster; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\VarDumper\Caster\DateCaster; +use Symfony\Component\VarDumper\Cloner\Stub; +use Symfony\Component\VarDumper\Test\VarDumperTestTrait; + +/** + * @author Dany Maillard + */ +class DateCasterTest extends TestCase +{ + use VarDumperTestTrait; + + /** + * @dataProvider provideDateTimes + */ + public function testDumpDateTime($time, $timezone, $expected) + { + if ((defined('HHVM_VERSION_ID') || PHP_VERSION_ID <= 50509) && preg_match('/[-+]\d{2}:\d{2}/', $timezone)) { + $this->markTestSkipped('DateTimeZone GMT offsets are supported since 5.5.10. See https://github.com/facebook/hhvm/issues/5875 for HHVM.'); + } + + $date = new \DateTime($time, new \DateTimeZone($timezone)); + + $xDump = <<assertDumpMatchesFormat($xDump, $date); + } + + public function testCastDateTime() + { + $stub = new Stub(); + $date = new \DateTime('2017-08-30 00:00:00.000000', new \DateTimeZone('Europe/Zurich')); + $cast = DateCaster::castDateTime($date, array('foo' => 'bar'), $stub, false, 0); + + $xDump = <<<'EODUMP' +array:1 [ + "\x00~\x00date" => 2017-08-30 00:00:00.000000 Europe/Zurich (+02:00) +] +EODUMP; + + $this->assertDumpMatchesFormat($xDump, $cast); + + $xDump = <<<'EODUMP' +Symfony\Component\VarDumper\Caster\ConstStub { + +type: "ref" + +class: "2017-08-30 00:00:00.000000 Europe/Zurich (+02:00)" + +value: """ + Wednesday, August 30, 2017\n + +%a from now\n + DST On + """ + +cut: 0 + +handle: 0 + +refCount: 0 + +position: 0 + +attr: [] +} +EODUMP; + + $this->assertDumpMatchesFormat($xDump, $cast["\0~\0date"]); + } + + public function provideDateTimes() + { + return array( + array('2017-04-30 00:00:00.000000', 'Europe/Zurich', '2017-04-30 00:00:00.000000 Europe/Zurich (+02:00)'), + array('2017-04-30 00:00:00.000000', '+02:00', '2017-04-30 00:00:00.000000 +02:00'), + ); + } +} From f3867e6c5417ca1b6ee69e8cf8b162b54032dd90 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Mon, 3 Jul 2017 10:16:04 +0200 Subject: [PATCH 0308/1099] add changelog entry for Stopwatch::reset() --- src/Symfony/Component/Stopwatch/CHANGELOG.md | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 src/Symfony/Component/Stopwatch/CHANGELOG.md diff --git a/src/Symfony/Component/Stopwatch/CHANGELOG.md b/src/Symfony/Component/Stopwatch/CHANGELOG.md new file mode 100644 index 0000000000000..2a03545ed1b82 --- /dev/null +++ b/src/Symfony/Component/Stopwatch/CHANGELOG.md @@ -0,0 +1,7 @@ +CHANGELOG +========= + +3.4.0 +----- + + * added the `Stopwatch::reset()` method From d261894c6eba1231a2f8b2bfeb53e961c32fe3f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9goire=20Paris?= Date: Thu, 15 Jun 2017 18:40:16 +0200 Subject: [PATCH 0309/1099] Change wording from object to subject The authorization checker has been changed to support any value recently. The naming should reflect that to avoid confusion. Refs https://github.com/sonata-project/SonataAdminBundle/issues/4518 --- .../Controller/ControllerTrait.php | 18 +++++++++--------- .../Authorization/AuthorizationChecker.php | 4 ++-- .../AuthorizationCheckerInterface.php | 6 +++--- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/Controller/ControllerTrait.php b/src/Symfony/Bundle/FrameworkBundle/Controller/ControllerTrait.php index 0737145b0bedf..4bf5335bd9a68 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Controller/ControllerTrait.php +++ b/src/Symfony/Bundle/FrameworkBundle/Controller/ControllerTrait.php @@ -159,40 +159,40 @@ protected function addFlash($type, $message) } /** - * Checks if the attributes are granted against the current authentication token and optionally supplied object. + * Checks if the attributes are granted against the current authentication token and optionally supplied subject. * * @param mixed $attributes The attributes - * @param mixed $object The object + * @param mixed $subject The subject * * @return bool * * @throws \LogicException */ - protected function isGranted($attributes, $object = null) + protected function isGranted($attributes, $subject = null) { if (!$this->container->has('security.authorization_checker')) { throw new \LogicException('The SecurityBundle is not registered in your application.'); } - return $this->container->get('security.authorization_checker')->isGranted($attributes, $object); + return $this->container->get('security.authorization_checker')->isGranted($attributes, $subject); } /** * Throws an exception unless the attributes are granted against the current authentication token and optionally - * supplied object. + * supplied subject. * * @param mixed $attributes The attributes - * @param mixed $object The object + * @param mixed $subject The subject * @param string $message The message passed to the exception * * @throws AccessDeniedException */ - protected function denyAccessUnlessGranted($attributes, $object = null, $message = 'Access Denied.') + protected function denyAccessUnlessGranted($attributes, $subject = null, $message = 'Access Denied.') { - if (!$this->isGranted($attributes, $object)) { + if (!$this->isGranted($attributes, $subject)) { $exception = $this->createAccessDeniedException($message); $exception->setAttributes($attributes); - $exception->setSubject($object); + $exception->setSubject($subject); throw $exception; } diff --git a/src/Symfony/Component/Security/Core/Authorization/AuthorizationChecker.php b/src/Symfony/Component/Security/Core/Authorization/AuthorizationChecker.php index 23c190cb563d0..07d21d999267e 100644 --- a/src/Symfony/Component/Security/Core/Authorization/AuthorizationChecker.php +++ b/src/Symfony/Component/Security/Core/Authorization/AuthorizationChecker.php @@ -51,7 +51,7 @@ public function __construct(TokenStorageInterface $tokenStorage, AuthenticationM * * @throws AuthenticationCredentialsNotFoundException when the token storage has no authentication token. */ - final public function isGranted($attributes, $object = null) + final public function isGranted($attributes, $subject = null) { if (null === ($token = $this->tokenStorage->getToken())) { throw new AuthenticationCredentialsNotFoundException('The token storage contains no authentication token. One possible reason may be that there is no firewall configured for this URL.'); @@ -65,6 +65,6 @@ final public function isGranted($attributes, $object = null) $attributes = array($attributes); } - return $this->accessDecisionManager->decide($token, $attributes, $object); + return $this->accessDecisionManager->decide($token, $attributes, $subject); } } diff --git a/src/Symfony/Component/Security/Core/Authorization/AuthorizationCheckerInterface.php b/src/Symfony/Component/Security/Core/Authorization/AuthorizationCheckerInterface.php index bd24d6f1c297d..54c1fcf5554bf 100644 --- a/src/Symfony/Component/Security/Core/Authorization/AuthorizationCheckerInterface.php +++ b/src/Symfony/Component/Security/Core/Authorization/AuthorizationCheckerInterface.php @@ -19,12 +19,12 @@ interface AuthorizationCheckerInterface { /** - * Checks if the attributes are granted against the current authentication token and optionally supplied object. + * Checks if the attributes are granted against the current authentication token and optionally supplied subject. * * @param mixed $attributes - * @param mixed $object + * @param mixed $subject * * @return bool */ - public function isGranted($attributes, $object = null); + public function isGranted($attributes, $subject = null); } From ebdbecfb8b0a8cd136e9a92f9a2f65fd4f32a70d Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Mon, 3 Jul 2017 11:21:33 +0200 Subject: [PATCH 0310/1099] gracefully handle missing hinclude renderer --- .../DependencyInjection/Compiler/ExtensionPass.php | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/Symfony/Bundle/TwigBundle/DependencyInjection/Compiler/ExtensionPass.php b/src/Symfony/Bundle/TwigBundle/DependencyInjection/Compiler/ExtensionPass.php index 65f36edf205ee..96278822bf069 100644 --- a/src/Symfony/Bundle/TwigBundle/DependencyInjection/Compiler/ExtensionPass.php +++ b/src/Symfony/Bundle/TwigBundle/DependencyInjection/Compiler/ExtensionPass.php @@ -65,10 +65,7 @@ public function process(ContainerBuilder $container) $container->getDefinition('twig.extension.httpkernel')->addTag('twig.extension'); // inject Twig in the hinclude service if Twig is the only registered templating engine - if ( - !$container->hasParameter('templating.engines') - || array('twig') == $container->getParameter('templating.engines') - ) { + if ((!$container->hasParameter('templating.engines') || array('twig') == $container->getParameter('templating.engines')) && $container->hasDefinition('fragment.renderer.hinclude')) { $container->getDefinition('fragment.renderer.hinclude') ->addTag('kernel.fragment_renderer', array('alias' => 'hinclude')) ->replaceArgument(0, new Reference('twig')) From 3a529e3391ab526ba9ea776fbd887573921b4eb1 Mon Sep 17 00:00:00 2001 From: Thomas Perez Date: Mon, 3 Jul 2017 15:09:40 +0200 Subject: [PATCH 0311/1099] Improve CircularReferenceException message --- .../Component/Serializer/Normalizer/AbstractNormalizer.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/Serializer/Normalizer/AbstractNormalizer.php b/src/Symfony/Component/Serializer/Normalizer/AbstractNormalizer.php index 63bfb871e819d..5149d0dbc7d97 100644 --- a/src/Symfony/Component/Serializer/Normalizer/AbstractNormalizer.php +++ b/src/Symfony/Component/Serializer/Normalizer/AbstractNormalizer.php @@ -228,7 +228,7 @@ protected function handleCircularReference($object) return call_user_func($this->circularReferenceHandler, $object); } - throw new CircularReferenceException(sprintf('A circular reference has been detected (configured limit: %d).', $this->circularReferenceLimit)); + throw new CircularReferenceException(sprintf('A circular reference has been detected when serializing the object of class "%s" (configured limit: %d)', get_class($object), $this->circularReferenceLimit)); } /** From 3ddb6e6aade5ae2086d72a83ddde60aa75511e3e Mon Sep 17 00:00:00 2001 From: Robin Chalas Date: Mon, 3 Jul 2017 15:19:36 +0200 Subject: [PATCH 0312/1099] [Console] Fix descriptor tests --- .../Fixtures/input_argument_with_default_inf_value.md | 6 +++--- .../Tests/Fixtures/input_option_with_default_inf_value.md | 7 +++---- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/src/Symfony/Component/Console/Tests/Fixtures/input_argument_with_default_inf_value.md b/src/Symfony/Component/Console/Tests/Fixtures/input_argument_with_default_inf_value.md index 293d816201271..4f4d9b164a775 100644 --- a/src/Symfony/Component/Console/Tests/Fixtures/input_argument_with_default_inf_value.md +++ b/src/Symfony/Component/Console/Tests/Fixtures/input_argument_with_default_inf_value.md @@ -1,7 +1,7 @@ -**argument_name:** +#### `argument_name` + +argument description -* Name: argument_name * Is required: no * Is array: no -* Description: argument description * Default: `INF` diff --git a/src/Symfony/Component/Console/Tests/Fixtures/input_option_with_default_inf_value.md b/src/Symfony/Component/Console/Tests/Fixtures/input_option_with_default_inf_value.md index b57bd04bf9993..c27e30a0a3291 100644 --- a/src/Symfony/Component/Console/Tests/Fixtures/input_option_with_default_inf_value.md +++ b/src/Symfony/Component/Console/Tests/Fixtures/input_option_with_default_inf_value.md @@ -1,9 +1,8 @@ -**option_name:** +#### `--option_name|-o` + +option description -* Name: `--option_name` -* Shortcut: `-o` * Accept value: yes * Is value required: no * Is multiple: no -* Description: option description * Default: `INF` From d7914a6a7d9d863937860e13e1723d2c12cb5bce Mon Sep 17 00:00:00 2001 From: Robin Chalas Date: Mon, 3 Jul 2017 14:22:20 +0200 Subject: [PATCH 0313/1099] [Security] Lazy load user providers --- .../DependencyInjection/SecurityExtension.php | 4 ++-- .../CompleteConfigurationTest.php | 5 +++-- .../Core/Tests/User/ChainUserProviderTest.php | 20 +++++++++++++++++++ .../Security/Core/User/ChainUserProvider.php | 9 ++++++++- .../Http/Firewall/ContextListener.php | 20 ++++++++++++------- .../Tests/Firewall/ContextListenerTest.php | 17 ++++++++++------ 6 files changed, 57 insertions(+), 18 deletions(-) diff --git a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php index 82aa222a759f7..ba8a5280088a2 100644 --- a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php +++ b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php @@ -245,7 +245,7 @@ private function createFirewalls($config, ContainerBuilder $container) foreach ($providerIds as $userProviderId) { $userProviders[] = new Reference($userProviderId); } - $arguments[1] = $userProviders; + $arguments[1] = new IteratorArgument($userProviders); $definition->setArguments($arguments); $customUserChecker = false; @@ -613,7 +613,7 @@ private function createUserDaoProvider($name, $provider, ContainerBuilder $conta $container ->setDefinition($name, new ChildDefinition('security.user.provider.chain')) - ->addArgument($providers); + ->addArgument(new IteratorArgument($providers)); return $name; } diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/CompleteConfigurationTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/CompleteConfigurationTest.php index c2598b51ff927..aa67377ce5676 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/CompleteConfigurationTest.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/CompleteConfigurationTest.php @@ -12,6 +12,7 @@ namespace Symfony\Bundle\SecurityBundle\Tests\DependencyInjection; use PHPUnit\Framework\TestCase; +use Symfony\Component\DependencyInjection\Argument\IteratorArgument; use Symfony\Component\DependencyInjection\Reference; use Symfony\Bundle\SecurityBundle\SecurityBundle; use Symfony\Bundle\SecurityBundle\DependencyInjection\SecurityExtension; @@ -57,10 +58,10 @@ public function testUserProviders() $this->assertEquals(array(), array_diff($providers, $expectedProviders)); // chain provider - $this->assertEquals(array(array( + $this->assertEquals(array(new IteratorArgument(array( new Reference('security.user.provider.concrete.service'), new Reference('security.user.provider.concrete.basic'), - )), $container->getDefinition('security.user.provider.concrete.chain')->getArguments()); + ))), $container->getDefinition('security.user.provider.concrete.chain')->getArguments()); } public function testFirewalls() diff --git a/src/Symfony/Component/Security/Core/Tests/User/ChainUserProviderTest.php b/src/Symfony/Component/Security/Core/Tests/User/ChainUserProviderTest.php index 2f53cf924ca0a..7f4d38f190bd7 100644 --- a/src/Symfony/Component/Security/Core/Tests/User/ChainUserProviderTest.php +++ b/src/Symfony/Component/Security/Core/Tests/User/ChainUserProviderTest.php @@ -172,6 +172,26 @@ public function testSupportsClassWhenNotSupported() $this->assertFalse($provider->supportsClass('foo')); } + public function testAcceptsTraversable() + { + $provider1 = $this->getProvider(); + $provider1 + ->expects($this->once()) + ->method('refreshUser') + ->will($this->throwException(new UnsupportedUserException('unsupported'))) + ; + + $provider2 = $this->getProvider(); + $provider2 + ->expects($this->once()) + ->method('refreshUser') + ->will($this->returnValue($account = $this->getAccount())) + ; + + $provider = new ChainUserProvider(new \ArrayObject(array($provider1, $provider2))); + $this->assertSame($account, $provider->refreshUser($this->getAccount())); + } + protected function getAccount() { return $this->getMockBuilder('Symfony\Component\Security\Core\User\UserInterface')->getMock(); diff --git a/src/Symfony/Component/Security/Core/User/ChainUserProvider.php b/src/Symfony/Component/Security/Core/User/ChainUserProvider.php index 8604ddc4a7391..e00aa303c5d14 100644 --- a/src/Symfony/Component/Security/Core/User/ChainUserProvider.php +++ b/src/Symfony/Component/Security/Core/User/ChainUserProvider.php @@ -26,7 +26,10 @@ class ChainUserProvider implements UserProviderInterface { private $providers; - public function __construct(array $providers) + /** + * @param iterable|UserProviderInterface[] $providers + */ + public function __construct($providers) { $this->providers = $providers; } @@ -36,6 +39,10 @@ public function __construct(array $providers) */ public function getProviders() { + if ($this->providers instanceof \Traversable) { + return iterator_to_array($this->providers); + } + return $this->providers; } diff --git a/src/Symfony/Component/Security/Http/Firewall/ContextListener.php b/src/Symfony/Component/Security/Http/Firewall/ContextListener.php index e1e5161a1d52b..97abd4dce5622 100644 --- a/src/Symfony/Component/Security/Http/Firewall/ContextListener.php +++ b/src/Symfony/Component/Security/Http/Firewall/ContextListener.php @@ -44,18 +44,20 @@ class ContextListener implements ListenerInterface private $registered; private $trustResolver; - public function __construct(TokenStorageInterface $tokenStorage, array $userProviders, $contextKey, LoggerInterface $logger = null, EventDispatcherInterface $dispatcher = null, AuthenticationTrustResolverInterface $trustResolver = null) + /** + * @param TokenStorageInterface $tokenStorage + * @param iterable|UserProviderInterface[] $userProviders + * @param string $contextKey + * @param LoggerInterface|null $logger + * @param EventDispatcherInterface|null $dispatcher + * @param AuthenticationTrustResolverInterface|null $trustResolver + */ + public function __construct(TokenStorageInterface $tokenStorage, $userProviders, $contextKey, LoggerInterface $logger = null, EventDispatcherInterface $dispatcher = null, AuthenticationTrustResolverInterface $trustResolver = null) { if (empty($contextKey)) { throw new \InvalidArgumentException('$contextKey must not be empty.'); } - foreach ($userProviders as $userProvider) { - if (!$userProvider instanceof UserProviderInterface) { - throw new \InvalidArgumentException(sprintf('User provider "%s" must implement "Symfony\Component\Security\Core\User\UserProviderInterface".', get_class($userProvider))); - } - } - $this->tokenStorage = $tokenStorage; $this->userProviders = $userProviders; $this->contextKey = $contextKey; @@ -158,6 +160,10 @@ protected function refreshUser(TokenInterface $token) $userNotFoundByProvider = false; foreach ($this->userProviders as $provider) { + if (!$provider instanceof UserProviderInterface) { + throw new \InvalidArgumentException(sprintf('User provider "%s" must implement "%s".', get_class($provider), UserProviderInterface::class)); + } + try { $refreshedUser = $provider->refreshUser($user); $token->setUser($refreshedUser); diff --git a/src/Symfony/Component/Security/Http/Tests/Firewall/ContextListenerTest.php b/src/Symfony/Component/Security/Http/Tests/Firewall/ContextListenerTest.php index 8a0a9361ad4e2..b58c272b374ce 100644 --- a/src/Symfony/Component/Security/Http/Tests/Firewall/ContextListenerTest.php +++ b/src/Symfony/Component/Security/Http/Tests/Firewall/ContextListenerTest.php @@ -53,11 +53,7 @@ public function testItRequiresContextKey() */ public function testUserProvidersNeedToImplementAnInterface() { - new ContextListener( - $this->getMockBuilder('Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface')->getMock(), - array(new \stdClass()), - 'key123' - ); + $this->handleEventWithPreviousSession(new TokenStorage(), array(new \stdClass())); } public function testOnKernelResponseWillAddSession() @@ -287,6 +283,15 @@ public function testRuntimeExceptionIsThrownIfNoSupportingUserProviderWasRegiste $this->handleEventWithPreviousSession(new TokenStorage(), array(new NotSupportingUserProvider(), new NotSupportingUserProvider())); } + public function testAcceptsProvidersAsTraversable() + { + $tokenStorage = new TokenStorage(); + $refreshedUser = new User('foobar', 'baz'); + $this->handleEventWithPreviousSession($tokenStorage, new \ArrayObject(array(new NotSupportingUserProvider(), new SupportingUserProvider($refreshedUser)))); + + $this->assertSame($refreshedUser, $tokenStorage->getToken()->getUser()); + } + protected function runSessionOnKernelResponse($newToken, $original = null) { $session = new Session(new MockArraySessionStorage()); @@ -315,7 +320,7 @@ protected function runSessionOnKernelResponse($newToken, $original = null) return $session; } - private function handleEventWithPreviousSession(TokenStorageInterface $tokenStorage, array $userProviders) + private function handleEventWithPreviousSession(TokenStorageInterface $tokenStorage, $userProviders) { $session = new Session(new MockArraySessionStorage()); $session->set('_security_context_key', serialize(new UsernamePasswordToken(new User('foo', 'bar'), '', 'context_key'))); From 1d07a28beda7b2e9f2c18e13502ba8b293780f21 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Tue, 20 Jun 2017 19:01:50 +0200 Subject: [PATCH 0314/1099] call setContainer() for autowired controllers --- .../Controller/ControllerResolver.php | 14 +++- .../Controller/ControllerResolverTest.php | 69 +++++++++++++++++++ 2 files changed, 82 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/Controller/ControllerResolver.php b/src/Symfony/Bundle/FrameworkBundle/Controller/ControllerResolver.php index 355f526fdc950..3de157bd4ff3e 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Controller/ControllerResolver.php +++ b/src/Symfony/Bundle/FrameworkBundle/Controller/ControllerResolver.php @@ -49,7 +49,19 @@ protected function createController($controller) $controller = $this->parser->parse($controller); } - return parent::createController($controller); + $resolvedController = parent::createController($controller); + + if (1 === substr_count($controller, ':') && is_array($resolvedController)) { + if ($resolvedController[0] instanceof ContainerAwareInterface) { + $resolvedController[0]->setContainer($this->container); + } + + if ($resolvedController[0] instanceof AbstractController && null !== $previousContainer = $resolvedController[0]->setContainer($this->container)) { + $resolvedController[0]->setContainer($previousContainer); + } + } + + return $resolvedController; } /** diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/ControllerResolverTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/ControllerResolverTest.php index 7946a96e8d2c0..5880ee0186a18 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/ControllerResolverTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/ControllerResolverTest.php @@ -13,6 +13,7 @@ use Psr\Container\ContainerInterface as Psr11ContainerInterface; use Psr\Log\LoggerInterface; +use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Bundle\FrameworkBundle\Controller\ControllerNameParser; use Symfony\Bundle\FrameworkBundle\Controller\ControllerResolver; use Symfony\Component\DependencyInjection\Container; @@ -68,6 +69,24 @@ public function testGetControllerWithBundleNotation() $this->assertSame('testAction', $controller[1]); } + public function testContainerAwareControllerGetsContainerWhenNotSet() + { + class_exists(AbstractControllerTest::class); + + $controller = new ContainerAwareController(); + + $container = new Container(); + $container->set(TestAbstractController::class, $controller); + + $resolver = $this->createControllerResolver(null, $container); + + $request = Request::create('/'); + $request->attributes->set('_controller', TestAbstractController::class.':testAction'); + + $this->assertSame(array($controller, 'testAction'), $resolver->getController($request)); + $this->assertSame($container, $controller->getContainer()); + } + public function testAbstractControllerGetsContainerWhenNotSet() { class_exists(AbstractControllerTest::class); @@ -86,6 +105,24 @@ class_exists(AbstractControllerTest::class); $this->assertSame($container, $controller->setContainer($container)); } + public function testAbstractControllerServiceWithFcqnIdGetsContainerWhenNotSet() + { + class_exists(AbstractControllerTest::class); + + $controller = new DummyController(); + + $container = new Container(); + $container->set(DummyController::class, $controller); + + $resolver = $this->createControllerResolver(null, $container); + + $request = Request::create('/'); + $request->attributes->set('_controller', DummyController::class.':fooAction'); + + $this->assertSame(array($controller, 'fooAction'), $resolver->getController($request)); + $this->assertSame($container, $controller->getContainer()); + } + public function testAbstractControllerGetsNoContainerWhenSet() { class_exists(AbstractControllerTest::class); @@ -106,6 +143,26 @@ class_exists(AbstractControllerTest::class); $this->assertSame($controllerContainer, $controller->setContainer($container)); } + public function testAbstractControllerServiceWithFcqnIdGetsNoContainerWhenSet() + { + class_exists(AbstractControllerTest::class); + + $controller = new DummyController(); + $controllerContainer = new Container(); + $controller->setContainer($controllerContainer); + + $container = new Container(); + $container->set(DummyController::class, $controller); + + $resolver = $this->createControllerResolver(null, $container); + + $request = Request::create('/'); + $request->attributes->set('_controller', DummyController::class.':fooAction'); + + $this->assertSame(array($controller, 'fooAction'), $resolver->getController($request)); + $this->assertSame($controllerContainer, $controller->getContainer()); + } + protected function createControllerResolver(LoggerInterface $logger = null, Psr11ContainerInterface $container = null, ControllerNameParser $parser = null) { if (!$parser) { @@ -152,3 +209,15 @@ public function __invoke() { } } + +class DummyController extends AbstractController +{ + public function getContainer() + { + return $this->container; + } + + public function fooAction() + { + } +} From 400e76706d08540b2aa7fe5b3738a0621572fae0 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Mon, 3 Jul 2017 17:21:42 +0300 Subject: [PATCH 0315/1099] updated CHANGELOG for 2.7.30 --- CHANGELOG-2.7.md | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/CHANGELOG-2.7.md b/CHANGELOG-2.7.md index c93959532d398..cf90bc2e50f34 100644 --- a/CHANGELOG-2.7.md +++ b/CHANGELOG-2.7.md @@ -7,6 +7,36 @@ in 2.7 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/v2.7.0...v2.7.1 +* 2.7.30 (2017-07-03) + + * bug #23341 [DoctrineBridge][Security][Validator] do not validate empty values (xabbuh) + * bug #23274 Display a better error design when the toolbar cannot be displayed (yceruto) + * bug #23333 [PropertyAccess] Fix TypeError discard (dunglas) + * bug #23345 [Console] fix description of INF default values (xabbuh) + * bug #23279 Don't call count on non countable object (pierredup) + * bug #23283 [TwigBundle] add back exception check (xabbuh) + * bug #23268 Show exception is checked twice in ExceptionController of twig (gmponos) + * bug #23266 Display a better error message when the toolbar cannot be displayed (javiereguiluz) + * bug #23271 [FrameworkBundle] allow SSI fragments configuration in XML files (xabbuh) + * bug #23254 [Form][TwigBridge] render hidden _method field in form_rest() (xabbuh) + * bug #23250 [Translation] return fallback locales whenever possible (xabbuh) + * bug #22732 [Security] fix switch user _exit without having current token (dmaicher) + * bug #22730 [FrameworkBundle] Sessions: configurable "use_strict_mode" option for NativeSessionStorage (MacDada) + * bug #23195 [FrameworkBundle] [Command] Clean bundle directory, fixes #23177 (NicolasPion) + * bug #23052 [TwigBundle] Add Content-Type header for exception response (rchoquet) + * bug #23199 Reset redirectCount when throwing exception (hvanoch) + * bug #23186 [TwigBundle] Move template.xml loading to a compiler pass (ogizanagi) + * bug #23130 Keep s-maxage when expiry and validation are used in combination (mpdude) + * bug #23129 Fix two edge cases in ResponseCacheStrategy (mpdude) + * feature #22636 [Routing] Expose request in route conditions, if needed and possible (ro0NL) + * bug #22636 [Routing] Expose request in route conditions, if needed and possible (ro0NL) + * bug #23057 [Translation][FrameworkBundle] Fix resource loading order inconsistency reported in #23034 (mpdude) + * bug #23092 [Filesystem] added workaround in Filesystem::rename for PHP bug (VolCh) + * bug #23128 [HttpFoundation] fix for Support for new 7.1 session options (vincentaubert) + * bug #23176 [VarDumper] fixes (nicolas-grekas) + * bug #23086 [FrameworkBundle] Fix perf issue in CacheClearCommand::warmup() (nicolas-grekas) + * bug #23098 Cache ipCheck (2.7) (gonzalovilaseca) + * 2.7.29 (2017-06-07) * bug #23069 [SecurityBundle] Show unique Inherited roles in profile panel (yceruto) From e688bdc811fe0506ba2a757633b318b05c9b32c8 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Mon, 3 Jul 2017 17:22:39 +0300 Subject: [PATCH 0316/1099] update CONTRIBUTORS for 2.7.30 --- CONTRIBUTORS.md | 59 +++++++++++++++++++++++++++++++------------------ 1 file changed, 38 insertions(+), 21 deletions(-) diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index 532b8a261c4f2..0b695308c528f 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -20,11 +20,11 @@ Symfony is the result of the work of many people who made the code better - Javier Eguiluz (javier.eguiluz) - Hugo Hamon (hhamon) - Abdellatif Ait boudad (aitboudad) + - Maxime Steinhausser (ogizanagi) + - Robin Chalas (chalas_r) - Romain Neutron (romain) - Pascal Borreli (pborreli) - Wouter De Jong (wouterj) - - Robin Chalas (chalas_r) - - Maxime Steinhausser (ogizanagi) - Grégoire Pineau (lyrixx) - Joseph Bielawski (stloyd) - Karma Dordrak (drak) @@ -38,8 +38,8 @@ Symfony is the result of the work of many people who made the code better - Jules Pietri (heah) - Roland Franssen (ro0) - Sarah Khalil (saro0h) - - Jonathan Wage (jwage) - Guilhem Niot (energetick) + - Jonathan Wage (jwage) - Diego Saint Esteben (dosten) - Alexandre Salomé (alexandresalome) - William Durand (couac) @@ -48,24 +48,24 @@ Symfony is the result of the work of many people who made the code better - stealth35 ‏ (stealth35) - Alexander Mols (asm89) - Bulat Shakirzyanov (avalanche123) - - Peter Rehm (rpet) - Iltar van der Berg (kjarli) + - Peter Rehm (rpet) - Saša Stamenković (umpirsky) - Henrik Bjørnskov (henrikbjorn) - Miha Vrhovnik - Diego Saint Esteben (dii3g0) - Konstantin Kudryashov (everzet) + - Matthias Pigulla (mpdude) - Bilal Amarni (bamarni) - Florin Patan (florinpatan) - - Matthias Pigulla (mpdude) + - Gábor Egyed (1ed) - Kevin Bond (kbond) - Andrej Hudec (pulzarraider) - - Gábor Egyed (1ed) + - Pierre du Plessis (pierredup) - Michel Weimerskirch (mweimerskirch) - Eric Clemmons (ericclemmons) - Charles Sarrazin (csarrazi) - Christian Raue - - Pierre du Plessis (pierredup) - Arnout Boks (aboks) - Deni - Henrik Westphal (snc) @@ -83,25 +83,27 @@ Symfony is the result of the work of many people who made the code better - Toni Uebernickel (havvg) - Bart van den Burg (burgov) - Jordan Alliot (jalliot) + - Jérôme Tamarelle (gromnan) - John Wards (johnwards) - Dariusz Ruminski - Fran Moreno (franmomu) - Antoine Hérault (herzult) - - Jérôme Tamarelle (gromnan) - Paráda József (paradajozsef) - Arnaud Le Blanc (arnaud-lb) - Maxime STEINHAUSSER + - Alexander M. Turek (derrabus) - Michal Piotrowski (eventhorizon) - Issei Murasawa (issei_m) - Tim Nagel (merk) - Brice BERNARD (brikou) - - Alexander M. Turek (derrabus) - Baptiste Clavié (talus) + - Vladimir Reznichenko (kalessil) - marc.weistroff - lenar - Włodzimierz Gajda (gajdaw) - - Vladimir Reznichenko (kalessil) + - Yonel Ceruto González (yonelceruto) - Alexander Schwenn (xelaris) + - Jacob Dreesen (jdreesen) - Florian Voutzinos (florianv) - Colin Frei - Adrien Brault (adrienbrault) @@ -109,10 +111,8 @@ Symfony is the result of the work of many people who made the code better - Peter Kokot (maastermedia) - David Buchmann (dbu) - excelwebzone - - Jacob Dreesen (jdreesen) - Tobias Nyholm (tobias) - Tomáš Votruba (tomas_votruba) - - Yonel Ceruto González (yonelceruto) - Fabien Pennequin (fabienpennequin) - Gordon Franke (gimler) - Eric GELOEN (gelo) @@ -124,13 +124,13 @@ Symfony is the result of the work of many people who made the code better - Sebastiaan Stok (sstok) - Stefano Sala (stefano.sala) - Evgeniy (ewgraf) + - Vincent AUBERT (vincent) - Juti Noppornpitak (shiroyuki) - Tigran Azatyan (tigranazatyan) - Sebastian Hörl (blogsh) - Daniel Gomes (danielcsgomes) - Hidenori Goto (hidenorigoto) - Guilherme Blanco (guilhermeblanco) - - Vincent AUBERT (vincent) - Pablo Godel (pgodel) - Jérémie Augustin (jaugustin) - Andréia Bohner (andreia) @@ -147,6 +147,7 @@ Symfony is the result of the work of many people who made the code better - Thomas Rabaix (rande) - Rouven Weßling (realityking) - Teoh Han Hui (teohhanhui) + - David Maicher (dmaicher) - Jérôme Vasseur (jvasseur) - Clemens Tolboom - Helmer Aaviksoo @@ -154,16 +155,16 @@ Symfony is the result of the work of many people who made the code better - Hiromi Hishida (77web) - Matthieu Ouellette-Vachon (maoueh) - Michał Pipa (michal.pipa) + - Dawid Nowak - Amal Raghav (kertz) - Jonathan Ingram (jonathaningram) - Artur Kotyrba - - David Maicher (dmaicher) - jeremyFreeAgent (Jérémy Romey) (jeremyfreeagent) - James Halsall (jaitsu) - Warnar Boekkooi (boekkooi) - Dmitrii Chekaliuk (lazyhammer) - Clément JOBEILI (dator) - - Dawid Nowak + - Lars Strojny (lstrojny) - Possum - Dorian Villet (gnutix) - Richard Miller (mr_r_miller) @@ -175,12 +176,12 @@ Symfony is the result of the work of many people who made the code better - Chris Wilkinson (thewilkybarkid) - Andreas Hucks (meandmymonkey) - Noel Guilbert (noel) - - Lars Strojny (lstrojny) - Stepan Anchugov (kix) - bronze1man - Daniel Espendiller - sun (sun) - Larry Garfield (crell) + - Oleg Voronkovich - Martin Schuhfuß (usefulthink) - apetitpa - Matthieu Bontemps (mbontemps) @@ -242,7 +243,6 @@ Symfony is the result of the work of many people who made the code better - Uwe Jäger (uwej711) - Eugene Leonovich (rybakit) - Filippo Tessarotto - - Oleg Voronkovich - Joseph Rouff (rouffj) - Félix Labrecque (woodspire) - GordonsLondon @@ -294,6 +294,7 @@ Symfony is the result of the work of many people who made the code better - Victor Bocharsky (bocharsky_bw) - Jan Decavele (jandc) - Gustavo Piltcher + - Nikolay Labinskiy (e-moe) - Stepan Tanasiychuk (stfalcon) - Tiago Ribeiro (fixe) - Hidde Boomsma (hboomsma) @@ -359,7 +360,6 @@ Symfony is the result of the work of many people who made the code better - Endre Fejes - Tobias Naumann (tna) - Daniel Beyer - - Nikolay Labinskiy (e-moe) - Shein Alexey - Romain Gautier (mykiwi) - Joe Lencioni @@ -609,6 +609,7 @@ Symfony is the result of the work of many people who made the code better - Kevin (oxfouzer) - Paweł Wacławczyk (pwc) - Oleg Zinchenko (cystbear) + - Baptiste Meyer (meyerbaptiste) - Johannes Klauss (cloppy) - Evan Villemez - fzerorubigd @@ -671,6 +672,7 @@ Symfony is the result of the work of many people who made the code better - Benoit Lévêque (benoit_leveque) - Jeroen Fiege (fieg) - Krzysiek Łabuś + - George Mponos (gmponos) - Xavier Lacot (xavier) - possum - Denis Zunke (donalberto) @@ -734,6 +736,7 @@ Symfony is the result of the work of many people who made the code better - Omar Yepez (oyepez003) - mwsaz - Jelle Kapitein + - Ben Scott - Benoît Bourgeois - mantulo - corphi @@ -815,6 +818,7 @@ Symfony is the result of the work of many people who made the code better - ttomor - Mei Gwilym (meigwilym) - Michael H. Arieli (excelwebzone) + - Tom Panier (neemzy) - Fred Cox - Luciano Mammino (loige) - fabios @@ -850,6 +854,7 @@ Symfony is the result of the work of many people who made the code better - Máximo Cuadros (mcuadros) - tamirvs - julien.galenski + - Israel J. Carberry - Bob van de Vijver - Christian Neff - Per Sandström (per) @@ -888,7 +893,6 @@ Symfony is the result of the work of many people who made the code better - Eddie Jaoude - Antanas Arvasevicius - Haritz Iturbe (hizai) - - Baptiste Meyer (meyerbaptiste) - Nerijus Arlauskas (nercury) - SPolischook - Diego Sapriza @@ -910,8 +914,10 @@ Symfony is the result of the work of many people who made the code better - Marcin Chwedziak - hjkl - Tony Cosentino (tony-co) + - Dan Wilga - Alexander Cheprasov - Rodrigo Díez Villamuera (rodrigodiez) + - Malte Blättermann - e-ivanov - Jochen Bayer (jocl) - Jeremy Bush @@ -923,12 +929,14 @@ Symfony is the result of the work of many people who made the code better - Péter Buri (burci) - Davide Borsatto (davide.borsatto) - kaiwa + - RJ Garcia - Charles Sanquer (csanquer) - Albert Ganiev (helios-ag) - Neil Katin - David Otton - Will Donohoe - peter + - Jaroslav Kuba - flip111 - Jérémy Jourdin (jjk801) - BRAMILLE Sébastien (oktapodia) @@ -936,6 +944,7 @@ Symfony is the result of the work of many people who made the code better - Gustavo Adrian - Yannick - spdionis + - rchoquet - Taras Girnyk - Eduardo García Sanz (coma) - James Gilliland @@ -965,6 +974,7 @@ Symfony is the result of the work of many people who made the code better - Paul Matthews - Juan Traverso - Tarjei Huse (tarjei) + - tsufeki - Philipp Strube - Christian Sciberras - Clement Herreman (clemherreman) @@ -1055,6 +1065,7 @@ Symfony is the result of the work of many people who made the code better - m.chwedziak - Philip Frank - Lance McNearney + - Gonzalo Vilaseca (gonzalovilaseca) - Giorgio Premi - Ian Carroll - caponica @@ -1065,7 +1076,6 @@ Symfony is the result of the work of many people who made the code better - adev - Luis Galeas - Martin Pärtel - - George Mponos (gmponos) - Patrick Daley (padrig) - Xavier Briand (xavierbriand) - Max Summe @@ -1146,6 +1156,7 @@ Symfony is the result of the work of many people who made the code better - Hoffmann András - Olivier - pscheit + - Wybren Koelmans - Zdeněk Drahoš - Dan Harper - moldcraft @@ -1233,6 +1244,7 @@ Symfony is the result of the work of many people who made the code better - Fabien LUCAS (flucas2) - Indra Gunawan (indragunawan) - Karim Cassam Chenaï (ka) + - Michal Kurzeja (mkurzeja) - Nicolas Bastien (nicolas_bastien) - Denis (yethee) - Andrew Zhilin (zhil) @@ -1251,9 +1263,11 @@ Symfony is the result of the work of many people who made the code better - Warwick - VJ - Chris + - Florent Olivaud - JakeFr - Simon Sargeant - efeen + - Nicolas Pion - Muhammed Akbulut - Michał Dąbrowski (defrag) - Simone Fumagalli (hpatoio) @@ -1270,6 +1284,7 @@ Symfony is the result of the work of many people who made the code better - Grinbergs Reinis (shima5) - Artem Lopata (bumz) - Nicole Cordes + - VolCh - Alexey Popkov - Gijs Kunze - Artyom Protaskin @@ -1375,6 +1390,7 @@ Symfony is the result of the work of many people who made the code better - Dane Powell - Gerrit Drost - Linnaea Von Lavia + - Javan Eskander - Lenar Lõhmus - Cristian Gonzalez - AlberT @@ -1423,7 +1439,6 @@ Symfony is the result of the work of many people who made the code better - Yanick Witschi - Ondrej Mirtes - akimsko - - Ben Scott - Youpie - srsbiz - Taylan Kasap @@ -1556,6 +1571,7 @@ Symfony is the result of the work of many people who made the code better - Dawid Nowak - Lesnykh Ilia - Karolis Daužickas + - Nicolas - Sergio Santoro - tirnanog06 - phc @@ -1689,6 +1705,7 @@ Symfony is the result of the work of many people who made the code better - Adam Elsodaney (archfizz) - Daniel Kolvik (dkvk) - Marc Lemay (flug) + - Henne Van Och (hennevo) - Jeroen De Dauw (jeroendedauw) - Maxime COLIN (maximecolin) - Muharrem Demirci (mdemirci) From 75443d232b0ebe6486c2ace29d8e63100d1f8857 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Mon, 3 Jul 2017 17:22:50 +0300 Subject: [PATCH 0317/1099] updated VERSION for 2.7.30 --- 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 6b540518fcbc4..93be7003c1b37 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -58,12 +58,12 @@ abstract class Kernel implements KernelInterface, TerminableInterface protected $startTime; protected $loadClassCache; - const VERSION = '2.7.30-DEV'; + const VERSION = '2.7.30'; const VERSION_ID = 20730; const MAJOR_VERSION = 2; const MINOR_VERSION = 7; const RELEASE_VERSION = 30; - const EXTRA_VERSION = 'DEV'; + const EXTRA_VERSION = ''; const END_OF_MAINTENANCE = '05/2018'; const END_OF_LIFE = '05/2019'; From fa6b45bc58936af8e07f5818d7a451ea104a8307 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Mon, 3 Jul 2017 18:37:36 +0300 Subject: [PATCH 0318/1099] bumped Symfony version to 2.7.31 --- 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 93be7003c1b37..fc6c87b9e0665 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -58,12 +58,12 @@ abstract class Kernel implements KernelInterface, TerminableInterface protected $startTime; protected $loadClassCache; - const VERSION = '2.7.30'; - const VERSION_ID = 20730; + const VERSION = '2.7.31-DEV'; + const VERSION_ID = 20731; const MAJOR_VERSION = 2; const MINOR_VERSION = 7; - const RELEASE_VERSION = 30; - const EXTRA_VERSION = ''; + const RELEASE_VERSION = 31; + const EXTRA_VERSION = 'DEV'; const END_OF_MAINTENANCE = '05/2018'; const END_OF_LIFE = '05/2019'; From 0ca27ccfdee584d3cee9aaa548dc04112ddaea66 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Tue, 27 Dec 2016 11:46:45 +0100 Subject: [PATCH 0319/1099] add groups support to the Valid constraint --- src/Symfony/Component/Validator/CHANGELOG.md | 1 + .../Component/Validator/Constraints/Valid.php | 23 ++++++++---- .../Validator/Constraints/ValidValidator.php | 37 +++++++++++++++++++ .../Validator/Mapping/GenericMetadata.php | 2 +- .../Validator/Tests/Constraints/ValidTest.php | 16 +++++--- .../Tests/Validator/AbstractTest.php | 35 ++++++++++++++++++ 6 files changed, 100 insertions(+), 14 deletions(-) create mode 100644 src/Symfony/Component/Validator/Constraints/ValidValidator.php diff --git a/src/Symfony/Component/Validator/CHANGELOG.md b/src/Symfony/Component/Validator/CHANGELOG.md index 782ee436e037c..8eff88c6bbfed 100644 --- a/src/Symfony/Component/Validator/CHANGELOG.md +++ b/src/Symfony/Component/Validator/CHANGELOG.md @@ -4,6 +4,7 @@ CHANGELOG 3.4.0 ----- + * added support for validation groups to the `Valid` constraint * not setting the `strict` option of the `Choice` constraint to `true` is deprecated and will throw an exception in Symfony 4.0 * setting the `checkDNS` option of the `Url` constraint to `true` is deprecated in favor of constant values and will throw an exception in Symfony 4.0 diff --git a/src/Symfony/Component/Validator/Constraints/Valid.php b/src/Symfony/Component/Validator/Constraints/Valid.php index 439da3ae0056a..893942377851f 100644 --- a/src/Symfony/Component/Validator/Constraints/Valid.php +++ b/src/Symfony/Component/Validator/Constraints/Valid.php @@ -12,7 +12,6 @@ namespace Symfony\Component\Validator\Constraints; use Symfony\Component\Validator\Constraint; -use Symfony\Component\Validator\Exception\ConstraintDefinitionException; /** * @Annotation @@ -24,15 +23,23 @@ class Valid extends Constraint { public $traverse = true; - public function __construct($options = null) + public function __get($option) { - if (is_array($options) && array_key_exists('groups', $options)) { - throw new ConstraintDefinitionException(sprintf( - 'The option "groups" is not supported by the constraint %s', - __CLASS__ - )); + if ('groups' === $option) { + // when this is reached, no groups have been configured + return null; } - parent::__construct($options); + return parent::__get($option); + } + + /** + * {@inheritdoc} + */ + public function addImplicitGroupName($group) + { + if (null !== $this->groups) { + parent::addImplicitGroupName($group); + } } } diff --git a/src/Symfony/Component/Validator/Constraints/ValidValidator.php b/src/Symfony/Component/Validator/Constraints/ValidValidator.php new file mode 100644 index 0000000000000..45ac69d91d196 --- /dev/null +++ b/src/Symfony/Component/Validator/Constraints/ValidValidator.php @@ -0,0 +1,37 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Validator\Constraints; + +use Symfony\Component\Validator\Constraint; +use Symfony\Component\Validator\ConstraintValidator; +use Symfony\Component\Validator\Exception\UnexpectedTypeException; + +/** + * @author Christian Flothmann + */ +class ValidValidator extends ConstraintValidator +{ + public function validate($value, Constraint $constraint) + { + if (!$constraint instanceof Valid) { + throw new UnexpectedTypeException($constraint, __NAMESPACE__.'\Valid'); + } + + $violations = $this->context->getValidator()->validate($value, null, array($this->context->getGroup())); + + foreach ($violations as $violation) { + $this->context->buildViolation($violation->getMessage(), $violation->getParameters()) + ->atPath($violation->getPropertyPath()) + ->addViolation(); + } + } +} diff --git a/src/Symfony/Component/Validator/Mapping/GenericMetadata.php b/src/Symfony/Component/Validator/Mapping/GenericMetadata.php index ff1cb6d37f89e..a14b6578e359c 100644 --- a/src/Symfony/Component/Validator/Mapping/GenericMetadata.php +++ b/src/Symfony/Component/Validator/Mapping/GenericMetadata.php @@ -131,7 +131,7 @@ public function addConstraint(Constraint $constraint) )); } - if ($constraint instanceof Valid) { + if ($constraint instanceof Valid && null === $constraint->groups) { $this->cascadingStrategy = CascadingStrategy::CASCADE; if ($constraint->traverse) { diff --git a/src/Symfony/Component/Validator/Tests/Constraints/ValidTest.php b/src/Symfony/Component/Validator/Tests/Constraints/ValidTest.php index 83722fd2df0e0..9928bd82d0225 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/ValidTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/ValidTest.php @@ -19,11 +19,17 @@ */ class ValidTest extends TestCase { - /** - * @expectedException \Symfony\Component\Validator\Exception\ConstraintDefinitionException - */ - public function testRejectGroupsOption() + public function testGroupsCanBeSet() { - new Valid(array('groups' => 'foo')); + $constraint = new Valid(array('groups' => 'foo')); + + $this->assertSame(array('foo'), $constraint->groups); + } + + public function testGroupsAreNullByDefault() + { + $constraint = new Valid(); + + $this->assertNull($constraint->groups); } } diff --git a/src/Symfony/Component/Validator/Tests/Validator/AbstractTest.php b/src/Symfony/Component/Validator/Tests/Validator/AbstractTest.php index 77a7cc6c2bdc6..90b384a3111bd 100644 --- a/src/Symfony/Component/Validator/Tests/Validator/AbstractTest.php +++ b/src/Symfony/Component/Validator/Tests/Validator/AbstractTest.php @@ -14,6 +14,7 @@ use Symfony\Component\Validator\Constraints\Callback; use Symfony\Component\Validator\Constraints\Collection; use Symfony\Component\Validator\Constraints\GroupSequence; +use Symfony\Component\Validator\Constraints\NotBlank; use Symfony\Component\Validator\Constraints\NotNull; use Symfony\Component\Validator\Constraints\Traverse; use Symfony\Component\Validator\Constraints\Valid; @@ -670,4 +671,38 @@ public function testCollectionConstraitViolationHasCorrectContext() $this->assertCount(1, $violations); $this->assertSame($constraint, $violations[0]->getConstraint()); } + + public function testNestedObjectIsNotValidatedIfGroupInValidConstraintIsNotValidated() + { + $entity = new Entity(); + $entity->firstName = ''; + $reference = new Reference(); + $reference->value = ''; + $entity->childA = $reference; + + $this->metadata->addPropertyConstraint('firstName', new NotBlank(array('groups' => 'group1'))); + $this->metadata->addPropertyConstraint('childA', new Valid(array('groups' => 'group1'))); + $this->referenceMetadata->addPropertyConstraint('value', new NotBlank()); + + $violations = $this->validator->validate($entity, null, array()); + + $this->assertCount(0, $violations); + } + + public function testNestedObjectIsValidatedIfGroupInValidConstraintIsValidated() + { + $entity = new Entity(); + $entity->firstName = ''; + $reference = new Reference(); + $reference->value = ''; + $entity->childA = $reference; + + $this->metadata->addPropertyConstraint('firstName', new NotBlank(array('groups' => 'group1'))); + $this->metadata->addPropertyConstraint('childA', new Valid(array('groups' => 'group1'))); + $this->referenceMetadata->addPropertyConstraint('value', new NotBlank(array('groups' => 'group1'))); + + $violations = $this->validator->validate($entity, null, array('Default', 'group1')); + + $this->assertCount(2, $violations); + } } From e0913a28084b0371faa90cab6e207bd875d937ea Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Fri, 15 Jan 2016 21:45:57 +0100 Subject: [PATCH 0320/1099] add option to define the access decision manager --- .../DependencyInjection/MainConfiguration.php | 26 ++++++++++++++++++- .../DependencyInjection/SecurityExtension.php | 17 +++++++----- .../CompleteConfigurationTest.php | 24 +++++++++++++++++ ...cess_decision_manager_default_strategy.php | 16 ++++++++++++ .../php/access_decision_manager_service.php | 19 ++++++++++++++ ..._decision_manager_service_and_strategy.php | 20 ++++++++++++++ ...cess_decision_manager_default_strategy.xml | 16 ++++++++++++ .../xml/access_decision_manager_service.xml | 18 +++++++++++++ ..._decision_manager_service_and_strategy.xml | 18 +++++++++++++ ...cess_decision_manager_default_strategy.yml | 8 ++++++ .../yml/access_decision_manager_service.yml | 10 +++++++ ..._decision_manager_service_and_strategy.yml | 11 ++++++++ 12 files changed, 196 insertions(+), 7 deletions(-) create mode 100644 src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/access_decision_manager_default_strategy.php create mode 100644 src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/access_decision_manager_service.php create mode 100644 src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/access_decision_manager_service_and_strategy.php create mode 100644 src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/access_decision_manager_default_strategy.xml create mode 100644 src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/access_decision_manager_service.xml create mode 100644 src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/access_decision_manager_service_and_strategy.xml create mode 100644 src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/access_decision_manager_default_strategy.yml create mode 100644 src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/access_decision_manager_service.yml create mode 100644 src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/access_decision_manager_service_and_strategy.yml diff --git a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/MainConfiguration.php b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/MainConfiguration.php index c2bcb7d0e3ef2..6b23e2995898c 100644 --- a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/MainConfiguration.php +++ b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/MainConfiguration.php @@ -59,6 +59,26 @@ public function getConfigTreeBuilder() $rootNode = $tb->root('security'); $rootNode + ->beforeNormalization() + ->ifTrue(function ($v) { + if (!isset($v['access_decision_manager'])) { + return true; + } + + if (!isset($v['access_decision_manager']['strategy']) && !isset($v['access_decision_manager']['service'])) { + return true; + } + + return false; + }) + ->then(function ($v) { + $v['access_decision_manager'] = array( + 'strategy' => AccessDecisionManager::STRATEGY_AFFIRMATIVE, + ); + + return $v; + }) + ->end() ->children() ->scalarNode('access_denied_url')->defaultNull()->example('/foo/error403')->end() ->enumNode('session_fixation_strategy') @@ -73,11 +93,15 @@ public function getConfigTreeBuilder() ->children() ->enumNode('strategy') ->values(array(AccessDecisionManager::STRATEGY_AFFIRMATIVE, AccessDecisionManager::STRATEGY_CONSENSUS, AccessDecisionManager::STRATEGY_UNANIMOUS)) - ->defaultValue(AccessDecisionManager::STRATEGY_AFFIRMATIVE) ->end() + ->scalarNode('service')->end() ->booleanNode('allow_if_all_abstain')->defaultFalse()->end() ->booleanNode('allow_if_equal_granted_denied')->defaultTrue()->end() ->end() + ->validate() + ->ifTrue(function ($v) { return isset($v['strategy']) && isset($v['service']); }) + ->thenInvalid('"strategy" and "service" cannot be used together.') + ->end() ->end() ->end() ; diff --git a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php index 82aa222a759f7..95c2d07d9d419 100644 --- a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php +++ b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php @@ -83,12 +83,17 @@ public function load(array $configs, ContainerBuilder $container) $container->setParameter('security.access.denied_url', $config['access_denied_url']); $container->setParameter('security.authentication.manager.erase_credentials', $config['erase_credentials']); $container->setParameter('security.authentication.session_strategy.strategy', $config['session_fixation_strategy']); - $container - ->getDefinition('security.access.decision_manager') - ->addArgument($config['access_decision_manager']['strategy']) - ->addArgument($config['access_decision_manager']['allow_if_all_abstain']) - ->addArgument($config['access_decision_manager']['allow_if_equal_granted_denied']) - ; + + if (isset($config['access_decision_manager']['service'])) { + $container->setAlias('security.access.decision_manager', $config['access_decision_manager']['service']); + } else { + $container + ->getDefinition('security.access.decision_manager') + ->addArgument($config['access_decision_manager']['strategy']) + ->addArgument($config['access_decision_manager']['allow_if_all_abstain']) + ->addArgument($config['access_decision_manager']['allow_if_equal_granted_denied']); + } + $container->setParameter('security.access.always_authenticate_before_granting', $config['always_authenticate_before_granting']); $container->setParameter('security.authentication.hide_user_not_found', $config['hide_user_not_found']); diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/CompleteConfigurationTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/CompleteConfigurationTest.php index c2598b51ff927..4034e1c3c38a4 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/CompleteConfigurationTest.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/CompleteConfigurationTest.php @@ -16,6 +16,7 @@ use Symfony\Bundle\SecurityBundle\SecurityBundle; use Symfony\Bundle\SecurityBundle\DependencyInjection\SecurityExtension; use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\Security\Core\Authorization\AccessDecisionManager; abstract class CompleteConfigurationTest extends TestCase { @@ -356,6 +357,29 @@ public function testUserPasswordEncoderCommandIsRegistered() $this->assertTrue($this->getContainer('remember_me_options')->has('security.console.user_password_encoder_command')); } + public function testDefaultAccessDecisionManagerStrategyIsAffirmative() + { + $container = $this->getContainer('access_decision_manager_default_strategy'); + + $this->assertSame(AccessDecisionManager::STRATEGY_AFFIRMATIVE, $container->getDefinition('security.access.decision_manager')->getArgument(1), 'Default vote strategy is affirmative'); + } + + public function testCustomAccessDecisionManagerService() + { + $container = $this->getContainer('access_decision_manager_service'); + + $this->assertSame('app.access_decision_manager', (string) $container->getAlias('security.access.decision_manager'), 'The custom access decision manager service is aliased'); + } + + /** + * @expectedException \Symfony\Component\Config\Definition\Exception\InvalidConfigurationException + * @expectedExceptionMessage "strategy" and "service" cannot be used together. + */ + public function testAccessDecisionManagerServiceAndStrategyCannotBeUsedAtTheSameTime() + { + $container = $this->getContainer('access_decision_manager_service_and_strategy'); + } + protected function getContainer($file) { $file = $file.'.'.$this->getFileExtension(); diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/access_decision_manager_default_strategy.php b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/access_decision_manager_default_strategy.php new file mode 100644 index 0000000000000..d06fc3e686af2 --- /dev/null +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/access_decision_manager_default_strategy.php @@ -0,0 +1,16 @@ +loadFromExtension('security', array( + 'providers' => array( + 'default' => array( + 'memory' => array( + 'users' => array( + 'foo' => array('password' => 'foo', 'roles' => 'ROLE_USER'), + ), + ), + ), + ), + 'firewalls' => array( + 'simple' => array('pattern' => '/login', 'security' => false), + ), +)); diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/access_decision_manager_service.php b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/access_decision_manager_service.php new file mode 100644 index 0000000000000..29db539362649 --- /dev/null +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/access_decision_manager_service.php @@ -0,0 +1,19 @@ +loadFromExtension('security', array( + 'access_decision_manager' => array( + 'service' => 'app.access_decision_manager', + ), + 'providers' => array( + 'default' => array( + 'memory' => array( + 'users' => array( + 'foo' => array('password' => 'foo', 'roles' => 'ROLE_USER'), + ), + ), + ), + ), + 'firewalls' => array( + 'simple' => array('pattern' => '/login', 'security' => false), + ), +)); diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/access_decision_manager_service_and_strategy.php b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/access_decision_manager_service_and_strategy.php new file mode 100644 index 0000000000000..f7175e21f6fc8 --- /dev/null +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/access_decision_manager_service_and_strategy.php @@ -0,0 +1,20 @@ +loadFromExtension('security', array( + 'access_decision_manager' => array( + 'service' => 'app.access_decision_manager', + 'strategy' => 'affirmative', + ), + 'providers' => array( + 'default' => array( + 'memory' => array( + 'users' => array( + 'foo' => array('password' => 'foo', 'roles' => 'ROLE_USER'), + ), + ), + ), + ), + 'firewalls' => array( + 'simple' => array('pattern' => '/login', 'security' => false), + ), +)); diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/access_decision_manager_default_strategy.xml b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/access_decision_manager_default_strategy.xml new file mode 100644 index 0000000000000..6c267a2e7781c --- /dev/null +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/access_decision_manager_default_strategy.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/access_decision_manager_service.xml b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/access_decision_manager_service.xml new file mode 100644 index 0000000000000..4e67e168c8482 --- /dev/null +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/access_decision_manager_service.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/access_decision_manager_service_and_strategy.xml b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/access_decision_manager_service_and_strategy.xml new file mode 100644 index 0000000000000..dbadce4fa740d --- /dev/null +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/access_decision_manager_service_and_strategy.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/access_decision_manager_default_strategy.yml b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/access_decision_manager_default_strategy.yml new file mode 100644 index 0000000000000..f7fb5adc2c5d4 --- /dev/null +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/access_decision_manager_default_strategy.yml @@ -0,0 +1,8 @@ +security: + providers: + default: + memory: + users: + foo: { password: foo, roles: ROLE_USER } + firewalls: + simple: { pattern: /login, security: false } diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/access_decision_manager_service.yml b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/access_decision_manager_service.yml new file mode 100644 index 0000000000000..7ef3d8d93c3ab --- /dev/null +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/access_decision_manager_service.yml @@ -0,0 +1,10 @@ +security: + access_decision_manager: + service: app.access_decision_manager + providers: + default: + memory: + users: + foo: { password: foo, roles: ROLE_USER } + firewalls: + simple: { pattern: /login, security: false } diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/access_decision_manager_service_and_strategy.yml b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/access_decision_manager_service_and_strategy.yml new file mode 100644 index 0000000000000..bd38b21ef3536 --- /dev/null +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/access_decision_manager_service_and_strategy.yml @@ -0,0 +1,11 @@ +security: + access_decision_manager: + service: app.access_decision_manager + strategy: affirmative + providers: + default: + memory: + users: + foo: { password: foo, roles: ROLE_USER } + firewalls: + simple: { pattern: /login, security: false } From 41feceed5d94c2c097f0654f1a28bf374d37923e Mon Sep 17 00:00:00 2001 From: Dany Maillard Date: Mon, 3 Jul 2017 20:03:20 +0200 Subject: [PATCH 0321/1099] Remove hhvm compat --- .../Component/VarDumper/Tests/Caster/DateCasterTest.php | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/Symfony/Component/VarDumper/Tests/Caster/DateCasterTest.php b/src/Symfony/Component/VarDumper/Tests/Caster/DateCasterTest.php index 10f7896aec8a3..4de1f39efecac 100644 --- a/src/Symfony/Component/VarDumper/Tests/Caster/DateCasterTest.php +++ b/src/Symfony/Component/VarDumper/Tests/Caster/DateCasterTest.php @@ -28,10 +28,6 @@ class DateCasterTest extends TestCase */ public function testDumpDateTime($time, $timezone, $expected) { - if ((defined('HHVM_VERSION_ID') || PHP_VERSION_ID <= 50509) && preg_match('/[-+]\d{2}:\d{2}/', $timezone)) { - $this->markTestSkipped('DateTimeZone GMT offsets are supported since 5.5.10. See https://github.com/facebook/hhvm/issues/5875 for HHVM.'); - } - $date = new \DateTime($time, new \DateTimeZone($timezone)); $xDump = << Date: Mon, 3 Jul 2017 20:12:11 +0200 Subject: [PATCH 0322/1099] Remove bc layer --- .../Component/VarDumper/Test/VarDumperTestTrait.php | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/src/Symfony/Component/VarDumper/Test/VarDumperTestTrait.php b/src/Symfony/Component/VarDumper/Test/VarDumperTestTrait.php index dad06a653c348..4b47a89ab91b2 100644 --- a/src/Symfony/Component/VarDumper/Test/VarDumperTestTrait.php +++ b/src/Symfony/Component/VarDumper/Test/VarDumperTestTrait.php @@ -21,23 +21,11 @@ trait VarDumperTestTrait { public function assertDumpEquals($dump, $data, $filter = 0, $message = '') { - if (is_string($filter)) { - @trigger_error(sprintf('The $message argument of the "%s()" method at 3rd position is deprecated since version 3.4 and will be moved at 4th position in 4.0.', __METHOD__), E_USER_DEPRECATED); - $message = $filter; - $filter = 0; - } - $this->assertSame(rtrim($dump), $this->getDump($data, null, $filter), $message); } public function assertDumpMatchesFormat($dump, $data, $filter = 0, $message = '') { - if (is_string($filter)) { - @trigger_error(sprintf('The $message argument of the "%s()" method at 3rd position is deprecated since version 3.4 and will be moved at 4th position in 4.0.', __METHOD__), E_USER_DEPRECATED); - $message = $filter; - $filter = 0; - } - $this->assertStringMatchesFormat(rtrim($dump), $this->getDump($data, null, $filter), $message); } From c73dae379ea6ab550efb0248a40feaec8b06da26 Mon Sep 17 00:00:00 2001 From: Maxime Steinhausser Date: Mon, 3 Jul 2017 21:08:50 +0200 Subject: [PATCH 0323/1099] [Serializer] Remove DateTimeNormalizer PHP < 7 bc layer --- .../Component/Serializer/Normalizer/DateTimeNormalizer.php | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/Symfony/Component/Serializer/Normalizer/DateTimeNormalizer.php b/src/Symfony/Component/Serializer/Normalizer/DateTimeNormalizer.php index 35b0b5f0e5cd6..08469b0db785f 100644 --- a/src/Symfony/Component/Serializer/Normalizer/DateTimeNormalizer.php +++ b/src/Symfony/Component/Serializer/Normalizer/DateTimeNormalizer.php @@ -81,12 +81,7 @@ public function denormalize($data, $class, $format = null, array $context = arra $timezone = $this->getTimezone($context); if (null !== $dateTimeFormat) { - if (null === $timezone && PHP_VERSION_ID < 70000) { - // https://bugs.php.net/bug.php?id=68669 - $object = \DateTime::class === $class ? \DateTime::createFromFormat($dateTimeFormat, $data) : \DateTimeImmutable::createFromFormat($dateTimeFormat, $data); - } else { - $object = \DateTime::class === $class ? \DateTime::createFromFormat($dateTimeFormat, $data, $timezone) : \DateTimeImmutable::createFromFormat($dateTimeFormat, $data, $timezone); - } + $object = \DateTime::class === $class ? \DateTime::createFromFormat($dateTimeFormat, $data, $timezone) : \DateTimeImmutable::createFromFormat($dateTimeFormat, $data, $timezone); if (false !== $object) { return $object; From e5bb2bcc73194180723557dc8ce0801176af2edc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Sun, 25 Jun 2017 22:41:41 +0200 Subject: [PATCH 0324/1099] [DI][DoctrineBridge] Remove unused underscoreMap properties --- src/Symfony/Bridge/Doctrine/ManagerRegistry.php | 2 +- src/Symfony/Component/DependencyInjection/Container.php | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Symfony/Bridge/Doctrine/ManagerRegistry.php b/src/Symfony/Bridge/Doctrine/ManagerRegistry.php index 40a39efc8882b..be54b85e7f5b7 100644 --- a/src/Symfony/Bridge/Doctrine/ManagerRegistry.php +++ b/src/Symfony/Bridge/Doctrine/ManagerRegistry.php @@ -52,7 +52,7 @@ function (&$wrappedInstance, LazyLoadingInterface $manager) use ($name) { if (isset($this->aliases[$name = strtolower($name)])) { $name = $this->aliases[$name]; } - $method = !isset($this->methodMap[$name]) ? 'get'.strtr($name, $this->underscoreMap).'Service' : $this->methodMap[$name]; + $method = $this->methodMap[$name] ?? 'get'.$name.'Service'; $wrappedInstance = $this->{$method}(false); $manager->setProxyInitializer(null); diff --git a/src/Symfony/Component/DependencyInjection/Container.php b/src/Symfony/Component/DependencyInjection/Container.php index b55449020c427..3df05883dfab5 100644 --- a/src/Symfony/Component/DependencyInjection/Container.php +++ b/src/Symfony/Component/DependencyInjection/Container.php @@ -75,7 +75,6 @@ class Container implements ResettableContainerInterface */ protected $normalizedIds = array(); - private $underscoreMap = array('_' => '', '.' => '_', '\\' => '_'); private $envCache = array(); private $compiled = false; From 08a6178e77e1fd5bc44a39215861dc4ffd48388b Mon Sep 17 00:00:00 2001 From: Robin Chalas Date: Tue, 4 Jul 2017 00:07:18 +0200 Subject: [PATCH 0325/1099] Don't access private services from container aware commands (deprecated) --- .../Command/RouterDebugCommand.php | 3 +- .../Tests/Command/RouterDebugCommandTest.php | 31 +++++++++----- .../Tests/Command/RouterMatchCommandTest.php | 42 +++++++++++-------- 3 files changed, 47 insertions(+), 29 deletions(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/RouterDebugCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/RouterDebugCommand.php index 97707e8798b59..a08c1a352197f 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/RouterDebugCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/RouterDebugCommand.php @@ -12,6 +12,7 @@ namespace Symfony\Bundle\FrameworkBundle\Command; use Symfony\Bundle\FrameworkBundle\Console\Helper\DescriptorHelper; +use Symfony\Bundle\FrameworkBundle\Controller\ControllerNameParser; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; @@ -109,7 +110,7 @@ protected function execute(InputInterface $input, OutputInterface $output) private function convertController(Route $route) { - $nameParser = $this->getContainer()->get('controller_name_converter'); + $nameParser = new ControllerNameParser($this->getApplication()->getKernel()); if ($route->hasDefault('_controller')) { try { $route->setDefault('_controller', $nameParser->build($route->getDefault('_controller'))); diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/RouterDebugCommandTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/RouterDebugCommandTest.php index 6d32a37fd0ec9..597082485a0b6 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/RouterDebugCommandTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/RouterDebugCommandTest.php @@ -12,9 +12,10 @@ namespace Symfony\Bundle\FrameworkBundle\Tests\Command; use PHPUnit\Framework\TestCase; -use Symfony\Component\Console\Application; +use Symfony\Bundle\FrameworkBundle\Console\Application; use Symfony\Component\Console\Tester\CommandTester; use Symfony\Bundle\FrameworkBundle\Command\RouterDebugCommand; +use Symfony\Component\HttpKernel\KernelInterface; use Symfony\Component\Routing\Route; use Symfony\Component\Routing\RouteCollection; @@ -51,16 +52,15 @@ public function testDebugInvalidRoute() */ private function createCommandTester() { - $application = new Application(); + $application = new Application($this->getKernel()); $command = new RouterDebugCommand(); - $command->setContainer($this->getContainer()); $application->add($command); return new CommandTester($application->find('debug:router')); } - private function getContainer() + private function getKernel() { $routeCollection = new RouteCollection(); $routeCollection->add('foo', new Route('foo')); @@ -82,14 +82,25 @@ private function getContainer() ->with('router') ->will($this->returnValue(true)) ; - $container + ->expects($this->any()) ->method('get') - ->will($this->returnValueMap(array( - array('router', 1, $router), - array('controller_name_converter', 1, $loader), - ))); + ->with('router') + ->willReturn($router) + ; + + $kernel = $this->getMockBuilder(KernelInterface::class)->getMock(); + $kernel + ->expects($this->any()) + ->method('getContainer') + ->willReturn($container) + ; + $kernel + ->expects($this->once()) + ->method('getBundles') + ->willReturn(array()) + ; - return $container; + return $kernel; } } diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/RouterMatchCommandTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/RouterMatchCommandTest.php index cd15b8c5e82fc..384bd7ca53079 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/RouterMatchCommandTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/RouterMatchCommandTest.php @@ -12,10 +12,11 @@ namespace Symfony\Bundle\FrameworkBundle\Tests\Command; use PHPUnit\Framework\TestCase; -use Symfony\Component\Console\Application; +use Symfony\Bundle\FrameworkBundle\Console\Application; use Symfony\Component\Console\Tester\CommandTester; use Symfony\Bundle\FrameworkBundle\Command\RouterMatchCommand; use Symfony\Bundle\FrameworkBundle\Command\RouterDebugCommand; +use Symfony\Component\HttpKernel\KernelInterface; use Symfony\Component\Routing\Route; use Symfony\Component\Routing\RouteCollection; use Symfony\Component\Routing\RequestContext; @@ -45,20 +46,14 @@ public function testWithNotMatchPath() */ private function createCommandTester() { - $application = new Application(); - - $command = new RouterMatchCommand(); - $command->setContainer($this->getContainer()); - $application->add($command); - - $command = new RouterDebugCommand(); - $command->setContainer($this->getContainer()); - $application->add($command); + $application = new Application($this->getKernel()); + $application->add(new RouterMatchCommand()); + $application->add(new RouterDebugCommand()); return new CommandTester($application->find('router:match')); } - private function getContainer() + private function getKernel() { $routeCollection = new RouteCollection(); $routeCollection->add('foo', new Route('foo')); @@ -81,16 +76,27 @@ private function getContainer() $container = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerInterface')->getMock(); $container - ->expects($this->once()) + ->expects($this->atLeastOnce()) ->method('has') ->with('router') ->will($this->returnValue(true)); - $container->method('get') - ->will($this->returnValueMap(array( - array('router', 1, $router), - array('controller_name_converter', 1, $loader), - ))); + $container + ->expects($this->any()) + ->method('get') + ->willReturn($router); + + $kernel = $this->getMockBuilder(KernelInterface::class)->getMock(); + $kernel + ->expects($this->any()) + ->method('getContainer') + ->willReturn($container) + ; + $kernel + ->expects($this->once()) + ->method('getBundles') + ->willReturn(array()) + ; - return $container; + return $kernel; } } From 22998645956f063fc20b13beee668d44ce96038e Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Tue, 4 Jul 2017 08:30:58 +0300 Subject: [PATCH 0326/1099] updated CHANGELOG for 2.8.23 --- CHANGELOG-2.8.md | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/CHANGELOG-2.8.md b/CHANGELOG-2.8.md index da6f2aeebb9fb..ce55fb16317b8 100644 --- a/CHANGELOG-2.8.md +++ b/CHANGELOG-2.8.md @@ -7,6 +7,40 @@ in 2.8 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/v2.8.0...v2.8.1 +* 2.8.23 (2017-07-04) + + * bug #23341 [DoctrineBridge][Security][Validator] do not validate empty values (xabbuh) + * bug #23274 Display a better error design when the toolbar cannot be displayed (yceruto) + * bug #23333 [PropertyAccess] Fix TypeError discard (dunglas) + * bug #23345 [Console] fix description of INF default values (xabbuh) + * bug #23279 Don't call count on non countable object (pierredup) + * bug #23283 [TwigBundle] add back exception check (xabbuh) + * bug #23268 Show exception is checked twice in ExceptionController of twig (gmponos) + * bug #23266 Display a better error message when the toolbar cannot be displayed (javiereguiluz) + * bug #23271 [FrameworkBundle] allow SSI fragments configuration in XML files (xabbuh) + * bug #23254 [Form][TwigBridge] render hidden _method field in form_rest() (xabbuh) + * bug #23250 [Translation] return fallback locales whenever possible (xabbuh) + * bug #23240 [Console] Fix catching exception type in QuestionHelper (voronkovich) + * bug #23229 [WebProfilerBundle] Eliminate line wrap on count column (routing) (e-moe) + * bug #22732 [Security] fix switch user _exit without having current token (dmaicher) + * bug #22730 [FrameworkBundle] Sessions: configurable "use_strict_mode" option for NativeSessionStorage (MacDada) + * bug #23195 [FrameworkBundle] [Command] Clean bundle directory, fixes #23177 (NicolasPion) + * bug #23052 [TwigBundle] Add Content-Type header for exception response (rchoquet) + * bug #23199 Reset redirectCount when throwing exception (hvanoch) + * bug #23186 [TwigBundle] Move template.xml loading to a compiler pass (ogizanagi) + * bug #23130 Keep s-maxage when expiry and validation are used in combination (mpdude) + * bug #23129 Fix two edge cases in ResponseCacheStrategy (mpdude) + * feature #22636 [Routing] Expose request in route conditions, if needed and possible (ro0NL) + * bug #22636 [Routing] Expose request in route conditions, if needed and possible (ro0NL) + * bug #23057 [Translation][FrameworkBundle] Fix resource loading order inconsistency reported in #23034 (mpdude) + * bug #23092 [Filesystem] added workaround in Filesystem::rename for PHP bug (VolCh) + * bug #23128 [HttpFoundation] fix for Support for new 7.1 session options (vincentaubert) + * bug #23176 [VarDumper] fixes (nicolas-grekas) + * bug #22953 #22839 - changed debug toolbar dump section to relative and use full window width (mkurzeja) + * bug #23086 [FrameworkBundle] Fix perf issue in CacheClearCommand::warmup() (nicolas-grekas) + * bug #23098 Cache ipCheck (2.7) (gonzalovilaseca) + * bug #23069 [SecurityBundle] Show unique Inherited roles in profile panel (yceruto) + * 2.8.22 (2017-06-07) * bug #23073 [TwigBridge] Fix namespaced classes (ogizanagi) From f9b42239904b4326a2a0a380ffa74f41084a6869 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Tue, 4 Jul 2017 08:31:02 +0300 Subject: [PATCH 0327/1099] updated VERSION for 2.8.23 --- 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 37e10de8c64c4..48cb62a602cbc 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -59,12 +59,12 @@ abstract class Kernel implements KernelInterface, TerminableInterface protected $startTime; protected $loadClassCache; - const VERSION = '2.8.23-DEV'; + const VERSION = '2.8.23'; const VERSION_ID = 20823; const MAJOR_VERSION = 2; const MINOR_VERSION = 8; const RELEASE_VERSION = 23; - const EXTRA_VERSION = 'DEV'; + const EXTRA_VERSION = ''; const END_OF_MAINTENANCE = '11/2018'; const END_OF_LIFE = '11/2019'; From d011d57f812a9be8e9bc04b8330bb90e5aec896c Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Tue, 4 Jul 2017 08:43:52 +0300 Subject: [PATCH 0328/1099] bumped Symfony version to 2.8.24 --- 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 48cb62a602cbc..67a02337b510c 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -59,12 +59,12 @@ abstract class Kernel implements KernelInterface, TerminableInterface protected $startTime; protected $loadClassCache; - const VERSION = '2.8.23'; - const VERSION_ID = 20823; + const VERSION = '2.8.24-DEV'; + const VERSION_ID = 20824; const MAJOR_VERSION = 2; const MINOR_VERSION = 8; - const RELEASE_VERSION = 23; - const EXTRA_VERSION = ''; + const RELEASE_VERSION = 24; + const EXTRA_VERSION = 'DEV'; const END_OF_MAINTENANCE = '11/2018'; const END_OF_LIFE = '11/2019'; From e87e64e5e1fe0f6f3aab40ec491fc50630281f71 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Tue, 4 Jul 2017 08:44:55 +0300 Subject: [PATCH 0329/1099] updated CHANGELOG for 3.2.10 --- CHANGELOG-3.2.md | 52 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/CHANGELOG-3.2.md b/CHANGELOG-3.2.md index de1e0fd980928..5542e4160d1c3 100644 --- a/CHANGELOG-3.2.md +++ b/CHANGELOG-3.2.md @@ -7,6 +7,58 @@ in 3.2 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.2.0...v3.2.1 +* 3.2.10 (2017-07-04) + + * bug #23366 [FrameworkBundle] Don't get() private services from debug:router (chalasr) + * bug #23341 [DoctrineBridge][Security][Validator] do not validate empty values (xabbuh) + * bug #23274 Display a better error design when the toolbar cannot be displayed (yceruto) + * bug #23296 [WebProfilerBundle] Fix css trick used for offsetting html anchor from fixed header (ogizanagi) + * bug #23333 [PropertyAccess] Fix TypeError discard (dunglas) + * bug #23326 [Cache] fix cleanup of expired items for PdoAdapter (dmaicher) + * bug #23345 [Console] fix description of INF default values (xabbuh) + * bug #23299 [Workflow] Added more events to the announce function (Nyholm) + * bug #23279 Don't call count on non countable object (pierredup) + * bug #23283 [TwigBundle] add back exception check (xabbuh) + * bug #23268 Show exception is checked twice in ExceptionController of twig (gmponos) + * bug #23266 Display a better error message when the toolbar cannot be displayed (javiereguiluz) + * bug #23271 [FrameworkBundle] allow SSI fragments configuration in XML files (xabbuh) + * bug #23254 [Form][TwigBridge] render hidden _method field in form_rest() (xabbuh) + * bug #23250 [Translation] return fallback locales whenever possible (xabbuh) + * bug #23240 [Console] Fix catching exception type in QuestionHelper (voronkovich) + * bug #23229 [WebProfilerBundle] Eliminate line wrap on count column (routing) (e-moe) + * bug #22732 [Security] fix switch user _exit without having current token (dmaicher) + * bug #22730 [FrameworkBundle] Sessions: configurable "use_strict_mode" option for NativeSessionStorage (MacDada) + * bug #23195 [FrameworkBundle] [Command] Clean bundle directory, fixes #23177 (NicolasPion) + * bug #23052 [TwigBundle] Add Content-Type header for exception response (rchoquet) + * bug #23199 Reset redirectCount when throwing exception (hvanoch) + * bug #23186 [TwigBundle] Move template.xml loading to a compiler pass (ogizanagi) + * bug #23130 Keep s-maxage when expiry and validation are used in combination (mpdude) + * bug #23129 Fix two edge cases in ResponseCacheStrategy (mpdude) + * feature #22636 [Routing] Expose request in route conditions, if needed and possible (ro0NL) + * bug #22636 [Routing] Expose request in route conditions, if needed and possible (ro0NL) + * bug #22943 [SecurityBundle] Move cache of the firewall context into the request parameters (GromNaN) + * bug #23057 [Translation][FrameworkBundle] Fix resource loading order inconsistency reported in #23034 (mpdude) + * bug #23092 [Filesystem] added workaround in Filesystem::rename for PHP bug (VolCh) + * bug #23128 [HttpFoundation] fix for Support for new 7.1 session options (vincentaubert) + * bug #23176 [VarDumper] fixes (nicolas-grekas) + * bug #23100 [PropertyAccess] Do not silence TypeErrors from client code. (tsufeki) + * bug #23156 [PropertyAccess] Fix Usage with anonymous classes (mablae) + * bug #23091 [Cache] ApcuAdapter::isSupported() should return true when apc.enable_cli=Off (nicolas-grekas) + * bug #22953 #22839 - changed debug toolbar dump section to relative and use full window width (mkurzeja) + * bug #23086 [FrameworkBundle] Fix perf issue in CacheClearCommand::warmup() (nicolas-grekas) + * bug #23098 Cache ipCheck (2.7) (gonzalovilaseca) + * bug #23069 [SecurityBundle] Show unique Inherited roles in profile panel (yceruto) + * bug #23073 [TwigBridge] Fix namespaced classes (ogizanagi) + * bug #23063 [Cache] Fix extensibility of TagAwareAdapter::TAGS_PREFIX (wucdbm) + * bug #22936 [Form] Mix attr option between guessed options and user options (yceruto) + * bug #22976 [DependencyInjection] Use more clear message when unused environment variables detected (voronkovich) + * bug #23045 [Cache] fix Redis scheme detection (xabbuh) + * bug #22988 [PropertyInfo][DoctrineBridge] The bigint Doctrine's type must be converted to string (dunglas) + * bug #23014 Fix optional cache warmers are always instantiated whereas they should be lazy-loaded (romainneutron) + * bug #23024 [EventDispatcher] Fix ContainerAwareEventDispatcher::hasListeners(null) (nicolas-grekas) + * bug #22996 [Form] Fix \IntlDateFormatter timezone parameter usage to bypass PHP bug #66323 (romainneutron) + * bug #22994 Harden the debugging of Twig filters and functions (stof) + * 3.2.9 (2017-05-29) * bug #22847 [Console] ChoiceQuestion must have choices (ro0NL) From af3fcc11ed9e594795bb93a32adf9a964aa34e82 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Tue, 4 Jul 2017 08:45:03 +0300 Subject: [PATCH 0330/1099] updated VERSION for 3.2.10 --- 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 30270f0714e0a..e36c621722565 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -58,12 +58,12 @@ abstract class Kernel implements KernelInterface, TerminableInterface protected $startTime; protected $loadClassCache; - const VERSION = '3.2.10-DEV'; + const VERSION = '3.2.10'; const VERSION_ID = 30210; const MAJOR_VERSION = 3; const MINOR_VERSION = 2; const RELEASE_VERSION = 10; - const EXTRA_VERSION = 'DEV'; + const EXTRA_VERSION = ''; const END_OF_MAINTENANCE = '07/2017'; const END_OF_LIFE = '01/2018'; From ddc9d2e31327633c2488575a8c5bfc707b01fa50 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Tue, 4 Jul 2017 09:01:46 +0300 Subject: [PATCH 0331/1099] bumped Symfony version to 3.2.11 --- 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 e36c621722565..599cf6da6f932 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -58,12 +58,12 @@ abstract class Kernel implements KernelInterface, TerminableInterface protected $startTime; protected $loadClassCache; - const VERSION = '3.2.10'; - const VERSION_ID = 30210; + const VERSION = '3.2.11-DEV'; + const VERSION_ID = 30211; const MAJOR_VERSION = 3; const MINOR_VERSION = 2; - const RELEASE_VERSION = 10; - const EXTRA_VERSION = ''; + const RELEASE_VERSION = 11; + const EXTRA_VERSION = 'DEV'; const END_OF_MAINTENANCE = '07/2017'; const END_OF_LIFE = '01/2018'; From fcb6171d9ef8161cb1dbd02eb0f98182848a2c5c Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Tue, 4 Jul 2017 09:02:47 +0300 Subject: [PATCH 0332/1099] updated CHANGELOG for 3.3.3 --- CHANGELOG-3.3.md | 66 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) diff --git a/CHANGELOG-3.3.md b/CHANGELOG-3.3.md index 6c3cb3540ff0c..1817eff60299e 100644 --- a/CHANGELOG-3.3.md +++ b/CHANGELOG-3.3.md @@ -7,6 +7,72 @@ in 3.3 minor versions. To get the diff for a specific change, go to https://github.com/symfony/symfony/commit/XXX where XXX is the change hash To get the diff between two versions, go to https://github.com/symfony/symfony/compare/v3.3.0...v3.3.1 +* 3.3.3 (2017-07-04) + + * bug #23366 [FrameworkBundle] Don't get() private services from debug:router (chalasr) + * bug #23239 [FrameworkBundle] call setContainer() for autowired controllers (xabbuh) + * bug #23351 [Dotenv] parse concatenated variable values (xabbuh) + * bug #23341 [DoctrineBridge][Security][Validator] do not validate empty values (xabbuh) + * bug #23274 Display a better error design when the toolbar cannot be displayed (yceruto) + * bug #23342 [Dotenv] parse escaped quotes in unquoted env var values (xabbuh) + * bug #23291 [Security] Fix Firewall ExceptionListener priority (chalasr) + * bug #23296 [WebProfilerBundle] Fix css trick used for offsetting html anchor from fixed header (ogizanagi) + * bug #23333 [PropertyAccess] Fix TypeError discard (dunglas) + * bug #23326 [Cache] fix cleanup of expired items for PdoAdapter (dmaicher) + * bug #23345 [Console] fix description of INF default values (xabbuh) + * bug #23328 [FrameworkBundle] Display a proper warning on cache:clear without the --no-warmup option (ogizanagi) + * bug #23299 [Workflow] Added more events to the announce function (Nyholm) + * bug #23279 Don't call count on non countable object (pierredup) + * bug #23283 [TwigBundle] add back exception check (xabbuh) + * bug #23268 Show exception is checked twice in ExceptionController of twig (gmponos) + * bug #23266 Display a better error message when the toolbar cannot be displayed (javiereguiluz) + * bug #23271 [FrameworkBundle] allow SSI fragments configuration in XML files (xabbuh) + * bug #23254 [Form][TwigBridge] render hidden _method field in form_rest() (xabbuh) + * bug #23250 [Translation] return fallback locales whenever possible (xabbuh) + * bug #23237 [Cache] Fix Predis client cluster with pipeline (flolivaud) + * bug #23240 [Console] Fix catching exception type in QuestionHelper (voronkovich) + * bug #23218 [DI] Dedup tags when using instanceof/autoconfigure (ogizanagi) + * bug #23231 Improved the exception page when there is no message (javiereguiluz) + * bug #23229 [WebProfilerBundle] Eliminate line wrap on count column (routing) (e-moe) + * bug #22732 [Security] fix switch user _exit without having current token (dmaicher) + * bug #23226 [Validator] replace hardcoded service id (xabbuh) + * bug #22730 [FrameworkBundle] Sessions: configurable "use_strict_mode" option for NativeSessionStorage (MacDada) + * bug #23195 [FrameworkBundle] [Command] Clean bundle directory, fixes #23177 (NicolasPion) + * bug #23213 Fixed composer resources between web/cli (iltar) + * bug #23160 [WebProfilerBundle] Fix the icon for the Cache panel (javiereguiluz) + * bug #23052 [TwigBundle] Add Content-Type header for exception response (rchoquet) + * bug #23173 [WebServerBundle] Fix router script option BC (1ed) + * bug #23199 Reset redirectCount when throwing exception (hvanoch) + * bug #23180 [FrameworkBundle] Expose the AbstractController's container to its subclasses (BPScott) + * bug #23186 [TwigBundle] Move template.xml loading to a compiler pass (ogizanagi) + * bug #23130 Keep s-maxage when expiry and validation are used in combination (mpdude) + * bug #23129 Fix two edge cases in ResponseCacheStrategy (mpdude) + * feature #22636 [Routing] Expose request in route conditions, if needed and possible (ro0NL) + * bug #22636 [Routing] Expose request in route conditions, if needed and possible (ro0NL) + * bug #22943 [SecurityBundle] Move cache of the firewall context into the request parameters (GromNaN) + * bug #23088 [FrameworkBundle] Dont set pre-defined esi/ssi services (ro0NL) + * bug #23057 [Translation][FrameworkBundle] Fix resource loading order inconsistency reported in #23034 (mpdude) + * bug #23092 [Filesystem] added workaround in Filesystem::rename for PHP bug (VolCh) + * bug #23074 [HttpFoundation] add back support for legacy constant values (xabbuh) + * bug #23128 [HttpFoundation] fix for Support for new 7.1 session options (vincentaubert) + * bug #23176 [VarDumper] fixes (nicolas-grekas) + * bug #23100 [PropertyAccess] Do not silence TypeErrors from client code. (tsufeki) + * bug #23156 [PropertyAccess] Fix Usage with anonymous classes (mablae) + * bug #23168 [Config] Fix ** GlobResource on Windows (nicolas-grekas) + * bug #23171 [Yaml] Fix linting yaml with constants as keys (chalasr) + * bug #23121 [Routing] Revert the change in [#b42018] with respect to Routing/Route.php (Dan Wilga) + * bug #23141 [DI] Fix keys resolution in ResolveParameterPlaceHoldersPass (nicolas-grekas) + * bug #23145 Fix the conditional definition of the SymfonyTestsListener (stof) + * bug #23091 [Cache] ApcuAdapter::isSupported() should return true when apc.enable_cli=Off (nicolas-grekas) + * bug #22953 #22839 - changed debug toolbar dump section to relative and use full window width (mkurzeja) + * bug #23086 [FrameworkBundle] Fix perf issue in CacheClearCommand::warmup() (nicolas-grekas) + * bug #23090 [SecurityBundle] Made 2 service aliases private (nicolas-grekas) + * bug #23108 [Yaml] Remove line number in deprecation notices (nicolas-grekas) + * bug #23098 Cache ipCheck (2.7) (gonzalovilaseca) + * bug #23082 [MonologBridge] Do not silence errors in ServerLogHandler::formatRecord (lyrixx) + * bug #23007 [HttpKernel][Debug] Fix missing trace on deprecations collected during bootstrapping & silenced errors (ogizanagi) + * bug #23069 [SecurityBundle] Show unique Inherited roles in profile panel (yceruto) + * 3.3.2 (2017-06-06) * bug #23073 [TwigBridge] Fix namespaced classes (ogizanagi) From 5d8d746a100d9eff0500a058fde8b06189155f11 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Tue, 4 Jul 2017 09:02:59 +0300 Subject: [PATCH 0333/1099] updated VERSION for 3.3.3 --- 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 a89e4d50bb866..955be15e9ea12 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -61,12 +61,12 @@ abstract class Kernel implements KernelInterface, TerminableInterface private $projectDir; - const VERSION = '3.3.3-DEV'; + const VERSION = '3.3.3'; const VERSION_ID = 30303; const MAJOR_VERSION = 3; const MINOR_VERSION = 3; const RELEASE_VERSION = 3; - const EXTRA_VERSION = 'DEV'; + const EXTRA_VERSION = ''; const END_OF_MAINTENANCE = '01/2018'; const END_OF_LIFE = '07/2018'; From 5de56eba9a59bfc53075c3a6443a8e747676425d Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Tue, 4 Jul 2017 09:15:40 +0300 Subject: [PATCH 0334/1099] bumped Symfony version to 3.3.4 --- 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 955be15e9ea12..1a0f2434dc60f 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -61,12 +61,12 @@ abstract class Kernel implements KernelInterface, TerminableInterface private $projectDir; - const VERSION = '3.3.3'; - const VERSION_ID = 30303; + const VERSION = '3.3.4-DEV'; + const VERSION_ID = 30304; const MAJOR_VERSION = 3; const MINOR_VERSION = 3; - const RELEASE_VERSION = 3; - const EXTRA_VERSION = ''; + const RELEASE_VERSION = 4; + const EXTRA_VERSION = 'DEV'; const END_OF_MAINTENANCE = '01/2018'; const END_OF_LIFE = '07/2018'; From a32cae5caaebff52872c9a5e8d375a7dd35d5104 Mon Sep 17 00:00:00 2001 From: Maxime Steinhausser Date: Mon, 3 Jul 2017 19:07:33 +0200 Subject: [PATCH 0335/1099] [FrameworkBundle] Wire inner translator --- .../Compiler/LoggingTranslatorPass.php | 12 ++++++++++-- .../Compiler/LoggingTranslatorPassTest.php | 16 ++++++++++++++++ 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/LoggingTranslatorPass.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/LoggingTranslatorPass.php index 7d47dd2f9b132..ed0e811e0a7f0 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/LoggingTranslatorPass.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/LoggingTranslatorPass.php @@ -14,7 +14,6 @@ use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; -use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\Translation\TranslatorInterface; use Symfony\Component\Translation\TranslatorBagInterface; @@ -39,7 +38,16 @@ public function process(ContainerBuilder $container) } if ($r->isSubclassOf(TranslatorInterface::class) && $r->isSubclassOf(TranslatorBagInterface::class)) { $container->getDefinition('translator.logging')->setDecoratedService('translator'); - $container->getDefinition('translation.warmer')->replaceArgument(0, new Reference('translator.logging.inner')); + $warmer = $container->getDefinition('translation.warmer'); + $subscriberAttributes = $warmer->getTag('container.service_subscriber'); + $warmer->clearTag('container.service_subscriber'); + + foreach ($subscriberAttributes as $k => $v) { + if ((!isset($v['id']) || 'translator' !== $v['id']) && (!isset($v['key']) || 'translator' !== $v['key'])) { + $warmer->addTag('container.service_subscriber', $v); + } + } + $warmer->addTag('container.service_subscriber', array('key' => 'translator', 'id' => 'translator.logging.inner')); } } } diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/LoggingTranslatorPassTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/LoggingTranslatorPassTest.php index eda507c621ebf..a93d8ca5d0015 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/LoggingTranslatorPassTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/LoggingTranslatorPassTest.php @@ -60,6 +60,22 @@ public function testProcess() ->with('Symfony\Bundle\FrameworkBundle\Translation\Translator') ->will($this->returnValue(new \ReflectionClass('Symfony\Bundle\FrameworkBundle\Translation\Translator'))); + $definition->expects($this->once()) + ->method('getTag') + ->with('container.service_subscriber') + ->willReturn(array(array('id' => 'translator'), array('id' => 'foo'))); + + $definition->expects($this->once()) + ->method('clearTag') + ->with('container.service_subscriber'); + + $definition->expects($this->any()) + ->method('addTag') + ->withConsecutive( + array('container.service_subscriber', array('id' => 'foo')), + array('container.service_subscriber', array('key' => 'translator', 'id' => 'translator.logging.inner')) + ); + $pass = new LoggingTranslatorPass(); $pass->process($container); } From c75e486413ad0a2aa54dff937a19e9d3fd7bc170 Mon Sep 17 00:00:00 2001 From: Maxime Steinhausser Date: Tue, 4 Jul 2017 09:43:54 +0200 Subject: [PATCH 0336/1099] [FrameworkBundle] 3.3: Don't get() private services from debug:router --- .../Bundle/FrameworkBundle/Command/RouterDebugCommand.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/RouterDebugCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/RouterDebugCommand.php index e7d6d80a57ac7..f26fddabb0a93 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/RouterDebugCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/RouterDebugCommand.php @@ -137,7 +137,7 @@ private function extractCallable(Route $route) } } - $nameParser = $this->getContainer()->get('controller_name_converter'); + $nameParser = new ControllerNameParser($this->getApplication()->getKernel()); try { $shortNotation = $nameParser->build($controller); $route->setDefault('_controller', $shortNotation); From 6033503b5b2302b15cb79b1fd345eb45ba145db3 Mon Sep 17 00:00:00 2001 From: Dany Maillard Date: Tue, 4 Jul 2017 11:20:25 +0200 Subject: [PATCH 0337/1099] Remove enhancement Windows compatibility --- src/Symfony/Component/Process/Process.php | 37 +---------------------- 1 file changed, 1 insertion(+), 36 deletions(-) diff --git a/src/Symfony/Component/Process/Process.php b/src/Symfony/Component/Process/Process.php index d74c38afe8850..a34db920ef545 100644 --- a/src/Symfony/Component/Process/Process.php +++ b/src/Symfony/Component/Process/Process.php @@ -64,7 +64,6 @@ class Process implements \IteratorAggregate private $outputDisabled = false; private $stdout; private $stderr; - private $enhanceWindowsCompatibility = true; private $enhanceSigchildCompatibility; private $process; private $status = self::STATUS_READY; @@ -295,7 +294,7 @@ public function start(callable $callback = null, array $env = array()) $options = array('suppress_errors' => true); - if ('\\' === DIRECTORY_SEPARATOR && $this->enhanceWindowsCompatibility) { + if ('\\' === DIRECTORY_SEPARATOR) { $options['bypass_shell'] = true; $commandline = $this->prepareWindowsCommandLine($commandline, $envBackup, $env); } elseif (!$this->useFileHandles && $this->enhanceSigchildCompatibility && $this->isSigchildEnabled()) { @@ -1154,40 +1153,6 @@ public function setInput($input) return $this; } - /** - * Gets whether or not Windows compatibility is enabled. - * - * This is true by default. - * - * @return bool - * - * @deprecated since version 3.3, to be removed in 4.0. Enhanced Windows compatibility will always be enabled. - */ - public function getEnhanceWindowsCompatibility() - { - @trigger_error(sprintf('The %s() method is deprecated since version 3.3 and will be removed in 4.0. Enhanced Windows compatibility will always be enabled.', __METHOD__), E_USER_DEPRECATED); - - return $this->enhanceWindowsCompatibility; - } - - /** - * Sets whether or not Windows compatibility is enabled. - * - * @param bool $enhance - * - * @return self The current Process instance - * - * @deprecated since version 3.3, to be removed in 4.0. Enhanced Windows compatibility will always be enabled. - */ - public function setEnhanceWindowsCompatibility($enhance) - { - @trigger_error(sprintf('The %s() method is deprecated since version 3.3 and will be removed in 4.0. Enhanced Windows compatibility will always be enabled.', __METHOD__), E_USER_DEPRECATED); - - $this->enhanceWindowsCompatibility = (bool) $enhance; - - return $this; - } - /** * Returns whether sigchild compatibility mode is activated or not. * From 6ed9c8d8c5af201caaa0be47b4a48ae950721891 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A1bor=20Egyed?= Date: Tue, 4 Jul 2017 11:39:25 +0200 Subject: [PATCH 0338/1099] [FrameworkBundle] Do not remove files from assets dir --- .../Command/AssetsInstallCommand.php | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/AssetsInstallCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/AssetsInstallCommand.php index 0a3ea2871deb3..27cccd869e9a0 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/AssetsInstallCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/AssetsInstallCommand.php @@ -92,7 +92,9 @@ protected function execute(InputInterface $input, OutputInterface $output) $validAssetDirs = array(); foreach ($this->getContainer()->get('kernel')->getBundles() as $bundle) { if (is_dir($originDir = $bundle->getPath().'/Resources/public')) { - $targetDir = $bundlesDir.preg_replace('/bundle$/', '', strtolower($bundle->getName())); + $assetDir = preg_replace('/bundle$/', '', strtolower($bundle->getName())); + $targetDir = $bundlesDir.$assetDir; + $validAssetDirs[] = $assetDir; $output->writeln(sprintf('Installing assets for %s into %s', $bundle->getNamespace(), $targetDir)); @@ -132,15 +134,12 @@ protected function execute(InputInterface $input, OutputInterface $output) } else { $this->hardCopy($originDir, $targetDir); } - $validAssetDirs[] = $targetDir; } } + // remove the assets of the bundles that no longer exist - foreach (new \FilesystemIterator($bundlesDir) as $dir) { - if (!in_array($dir, $validAssetDirs)) { - $filesystem->remove($dir); - } - } + $dirsToRemove = Finder::create()->depth(0)->directories()->exclude($validAssetDirs)->in($bundlesDir); + $filesystem->remove($dirsToRemove); } /** From 9737bcc02442f067411f18ae46dd48a9e25b9105 Mon Sep 17 00:00:00 2001 From: Robin Chalas Date: Tue, 4 Jul 2017 14:04:47 +0200 Subject: [PATCH 0339/1099] [DoctrineBridge] Use normalizedIds for resetting entity manager services --- src/Symfony/Bridge/Doctrine/ManagerRegistry.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Bridge/Doctrine/ManagerRegistry.php b/src/Symfony/Bridge/Doctrine/ManagerRegistry.php index d602bfc2acaad..b30fd0691b1a8 100644 --- a/src/Symfony/Bridge/Doctrine/ManagerRegistry.php +++ b/src/Symfony/Bridge/Doctrine/ManagerRegistry.php @@ -53,7 +53,10 @@ protected function resetService($name) } $manager->setProxyInitializer(\Closure::bind( function (&$wrappedInstance, LazyLoadingInterface $manager) use ($name) { - if (isset($this->aliases[$name = strtolower($name)])) { + if (isset($this->normalizedIds[$normalizedId = strtolower($name)])) { + $name = $this->normalizedIds[$normalizedId]; + } + if (isset($this->aliases[$name])) { $name = $this->aliases[$name]; } $method = !isset($this->methodMap[$name]) ? 'get'.strtr($name, $this->underscoreMap).'Service' : $this->methodMap[$name]; From 9011aa176491f593e5b4d2a2cf0950a1fcff310a Mon Sep 17 00:00:00 2001 From: Dany Maillard Date: Tue, 4 Jul 2017 16:13:47 +0200 Subject: [PATCH 0340/1099] Remove !str support --- src/Symfony/Component/Yaml/Inline.php | 4 ---- src/Symfony/Component/Yaml/Tests/InlineTest.php | 9 --------- 2 files changed, 13 deletions(-) diff --git a/src/Symfony/Component/Yaml/Inline.php b/src/Symfony/Component/Yaml/Inline.php index 29645fadf70be..f0ab6a37f5c34 100644 --- a/src/Symfony/Component/Yaml/Inline.php +++ b/src/Symfony/Component/Yaml/Inline.php @@ -550,10 +550,6 @@ private static function evaluateScalar($scalar, $flags, $references = array()) return false; case $scalar[0] === '!': switch (true) { - case 0 === strpos($scalar, '!str'): - @trigger_error('Support for the !str tag is deprecated since version 3.4. Use the !!str tag instead.', E_USER_DEPRECATED); - - return (string) substr($scalar, 5); case 0 === strpos($scalar, '!!str '): return (string) substr($scalar, 6); case 0 === strpos($scalar, '! '): diff --git a/src/Symfony/Component/Yaml/Tests/InlineTest.php b/src/Symfony/Component/Yaml/Tests/InlineTest.php index dd4bfd2ae5f10..23e96b38da508 100644 --- a/src/Symfony/Component/Yaml/Tests/InlineTest.php +++ b/src/Symfony/Component/Yaml/Tests/InlineTest.php @@ -703,13 +703,4 @@ public function getNotPhpCompatibleMappingKeyData() 'float' => array('{0.25: "foo"}', array('0.25' => 'foo')), ); } - - /** - * @group legacy - * @expectedDeprecation Support for the !str tag is deprecated since version 3.4. Use the !!str tag instead. - */ - public function testDeprecatedStrTag() - { - $this->assertSame(array('foo' => 'bar'), Inline::parse('{ foo: !str bar }')); - } } From 47020c4904d4d01d39b5166097efc1ea24d8945a Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Tue, 4 Jul 2017 17:41:55 +0300 Subject: [PATCH 0341/1099] [Cache] Handle APCu failures gracefully --- src/Symfony/Component/Cache/Adapter/AbstractAdapter.php | 5 ++++- src/Symfony/Component/Cache/Adapter/ApcuAdapter.php | 8 ++++++-- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Component/Cache/Adapter/AbstractAdapter.php b/src/Symfony/Component/Cache/Adapter/AbstractAdapter.php index b5f6a61b56b03..84bb841d85df2 100644 --- a/src/Symfony/Component/Cache/Adapter/AbstractAdapter.php +++ b/src/Symfony/Component/Cache/Adapter/AbstractAdapter.php @@ -15,6 +15,7 @@ use Psr\Log\LoggerAwareInterface; use Psr\Log\LoggerAwareTrait; use Psr\Log\LoggerInterface; +use Psr\Log\NullLogger; use Symfony\Component\Cache\CacheItem; use Symfony\Component\Cache\Exception\InvalidArgumentException; @@ -108,7 +109,9 @@ public static function createSystemCache($namespace, $defaultLifetime, $version, } $apcu = new ApcuAdapter($namespace, (int) $defaultLifetime / 5, $version); - if (null !== $logger) { + if ('cli' === PHP_SAPI && !ini_get('apc.enable_cli')) { + $apcu->setLogger(new NullLogger()); + } elseif (null !== $logger) { $apcu->setLogger($logger); } diff --git a/src/Symfony/Component/Cache/Adapter/ApcuAdapter.php b/src/Symfony/Component/Cache/Adapter/ApcuAdapter.php index 6687bd4272d1d..ad3aadf1a5257 100644 --- a/src/Symfony/Component/Cache/Adapter/ApcuAdapter.php +++ b/src/Symfony/Component/Cache/Adapter/ApcuAdapter.php @@ -50,7 +50,7 @@ public function __construct($namespace = '', $defaultLifetime = 0, $version = nu protected function doFetch(array $ids) { try { - return apcu_fetch($ids); + return apcu_fetch($ids) ?: array(); } catch (\Error $e) { throw new \ErrorException($e->getMessage(), $e->getCode(), E_ERROR, $e->getFile(), $e->getLine()); } @@ -92,7 +92,11 @@ protected function doDelete(array $ids) protected function doSave(array $values, $lifetime) { try { - return array_keys(apcu_store($values, null, $lifetime)); + if (false === $failures = apcu_store($values, null, $lifetime)) { + $failures = $values; + } + + return array_keys($failures); } catch (\Error $e) { } catch (\Exception $e) { } From 61e262f0f893290be5d67ef2e2dd5d4e32c05eed Mon Sep 17 00:00:00 2001 From: Dany Maillard Date: Tue, 4 Jul 2017 16:56:41 +0200 Subject: [PATCH 0342/1099] Remove of boolean value for the checkDNS option --- UPGRADE-4.0.md | 15 +++++++++++++++ src/Symfony/Component/Validator/CHANGELOG.md | 1 + .../Validator/Constraints/UrlValidator.php | 6 ------ .../Tests/Constraints/UrlValidatorTest.php | 17 ----------------- 4 files changed, 16 insertions(+), 23 deletions(-) diff --git a/UPGRADE-4.0.md b/UPGRADE-4.0.md index 86edf3f42e9e4..cb88b17b1f292 100644 --- a/UPGRADE-4.0.md +++ b/UPGRADE-4.0.md @@ -569,6 +569,21 @@ Validator changed to `true` as of 4.0. If you need the previous behaviour ensure to set the option to `false`. + * Setting the `checkDNS` option of the `Url` constraint to `true` is dropped + in favor of `Url::CHECK_DNS_TYPE_*` constants values. + + Before: + + ```php + $constraint = new Url(['checkDNS' => true]); + ``` + + After: + + ```php + $constraint = new Url(['checkDNS' => Url::CHECK_DNS_TYPE_ANY]); + ``` + VarDumper --------- diff --git a/src/Symfony/Component/Validator/CHANGELOG.md b/src/Symfony/Component/Validator/CHANGELOG.md index b1db5e6de9bc8..6e3758be2554c 100644 --- a/src/Symfony/Component/Validator/CHANGELOG.md +++ b/src/Symfony/Component/Validator/CHANGELOG.md @@ -8,6 +8,7 @@ CHANGELOG is not supported anymore. * removed the `DateTimeValidator::PATTERN` constant * removed the `AbstractConstraintValidatorTest` class + * removed support for setting the `checkDNS` option of the `Url` constraint to `true` 3.4.0 ----- diff --git a/src/Symfony/Component/Validator/Constraints/UrlValidator.php b/src/Symfony/Component/Validator/Constraints/UrlValidator.php index e0e8f5f80ef4a..f987698fb83db 100644 --- a/src/Symfony/Component/Validator/Constraints/UrlValidator.php +++ b/src/Symfony/Component/Validator/Constraints/UrlValidator.php @@ -73,12 +73,6 @@ public function validate($value, Constraint $constraint) } if ($constraint->checkDNS) { - // backwards compatibility - if ($constraint->checkDNS === true) { - $constraint->checkDNS = Url::CHECK_DNS_TYPE_ANY; - @trigger_error(sprintf('Use of the boolean TRUE for the "checkDNS" option in %s is deprecated. Use Url::CHECK_DNS_TYPE_ANY instead.', Url::class), E_USER_DEPRECATED); - } - if (!in_array($constraint->checkDNS, array( Url::CHECK_DNS_TYPE_ANY, Url::CHECK_DNS_TYPE_A, diff --git a/src/Symfony/Component/Validator/Tests/Constraints/UrlValidatorTest.php b/src/Symfony/Component/Validator/Tests/Constraints/UrlValidatorTest.php index 633dcf6d571b2..112404907b0e8 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/UrlValidatorTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/UrlValidatorTest.php @@ -260,23 +260,6 @@ public function getCheckDnsTypes() ); } - /** - * @group legacy - */ - public function testCheckDnsWithBoolean() - { - DnsMock::withMockedHosts(array('example.com' => array(array('type' => 'A')))); - - $constraint = new Url(array( - 'checkDNS' => true, - 'dnsMessage' => 'myMessage', - )); - - $this->validator->validate('http://example.com', $constraint); - - $this->assertNoViolation(); - } - /** * @expectedException \Symfony\Component\Validator\Exception\InvalidOptionsException * @requires function Symfony\Bridge\PhpUnit\DnsMock::withMockedHosts From 19c6a6f12d62fa03ed51d86b58f066fb60ad7b27 Mon Sep 17 00:00:00 2001 From: Dany Maillard Date: Tue, 4 Jul 2017 19:44:25 +0200 Subject: [PATCH 0343/1099] Add some meta infos --- UPGRADE-4.0.md | 2 ++ src/Symfony/Component/Process/CHANGELOG.md | 1 + src/Symfony/Component/VarDumper/CHANGELOG.md | 4 ++++ src/Symfony/Component/Yaml/CHANGELOG.md | 1 + 4 files changed, 8 insertions(+) diff --git a/UPGRADE-4.0.md b/UPGRADE-4.0.md index 86edf3f42e9e4..03527692321b9 100644 --- a/UPGRADE-4.0.md +++ b/UPGRADE-4.0.md @@ -438,6 +438,8 @@ Process * Extending `Process::run()`, `Process::mustRun()` and `Process::restart()` is not supported anymore. + + * The `getEnhanceWindowsCompatibility()` and `setEnhanceWindowsCompatibility()` methods of the `Process` class have been removed. ProxyManager ------------ diff --git a/src/Symfony/Component/Process/CHANGELOG.md b/src/Symfony/Component/Process/CHANGELOG.md index 8cbd98f23f779..ed563c2bfa0c9 100644 --- a/src/Symfony/Component/Process/CHANGELOG.md +++ b/src/Symfony/Component/Process/CHANGELOG.md @@ -14,6 +14,7 @@ CHANGELOG methods of the `Process` class have been removed * support for passing `proc_open()` options has been removed * removed the `ProcessBuilder` class, use the `Process` class instead + * removed the `getEnhanceWindowsCompatibility()` and `setEnhanceWindowsCompatibility()` methods of the `Process` class 3.4.0 ----- diff --git a/src/Symfony/Component/VarDumper/CHANGELOG.md b/src/Symfony/Component/VarDumper/CHANGELOG.md index b763756aed02d..123e282d6fbe9 100644 --- a/src/Symfony/Component/VarDumper/CHANGELOG.md +++ b/src/Symfony/Component/VarDumper/CHANGELOG.md @@ -7,6 +7,10 @@ CHANGELOG * support for passing `\ReflectionClass` instances to the `Caster::castObject()` method has been dropped, pass class names as strings instead * the `Data::getRawData()` method has been removed + * the `VarDumperTestTrait::assertDumpEquals()` method expects a 3rd `$context = null` + argument and moves `$message = ''` argument at 4th position. + * the `VarDumperTestTrait::assertDumpMatchesFormat()` method expects a 3rd `$context = null` + argument and moves `$message = ''` argument at 4th position. 2.7.0 ----- diff --git a/src/Symfony/Component/Yaml/CHANGELOG.md b/src/Symfony/Component/Yaml/CHANGELOG.md index 7e58a6fc1deb4..64e550db37625 100644 --- a/src/Symfony/Component/Yaml/CHANGELOG.md +++ b/src/Symfony/Component/Yaml/CHANGELOG.md @@ -23,6 +23,7 @@ CHANGELOG the parser and dumper is no longer supported, pass bitmask flags instead * the constructor arguments of the `Parser` class have been removed * the `Inline` class is internal and no longer part of the BC promise + * removed support for the `!str` tag, use the `!!str` tag instead 3.4.0 ----- From ac107ba6b253af9d217cf511ceb10f1d47d91ed8 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Tue, 4 Jul 2017 21:32:35 +0200 Subject: [PATCH 0344/1099] [Validator] improve the changelog --- src/Symfony/Component/Validator/CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/Validator/CHANGELOG.md b/src/Symfony/Component/Validator/CHANGELOG.md index 782ee436e037c..9d2f78b942ce9 100644 --- a/src/Symfony/Component/Validator/CHANGELOG.md +++ b/src/Symfony/Component/Validator/CHANGELOG.md @@ -6,7 +6,8 @@ CHANGELOG * not setting the `strict` option of the `Choice` constraint to `true` is deprecated and will throw an exception in Symfony 4.0 - * setting the `checkDNS` option of the `Url` constraint to `true` is deprecated in favor of constant values and will throw an exception in Symfony 4.0 + * setting the `checkDNS` option of the `Url` constraint to `true` is deprecated in favor of + the `Url::CHECK_DNS_TYPE_*` constants values and will throw an exception in Symfony 4.0 3.3.0 ----- From 58ba4818a67aabf4f1bc424982ed7914fd819b5e Mon Sep 17 00:00:00 2001 From: Dariusz Date: Tue, 4 Jul 2017 23:00:55 +0200 Subject: [PATCH 0345/1099] Fix indent of methods --- .../SecurityRoutingIntegrationTest.php | 42 ++++----- .../LegacyApcUniversalClassLoaderTest.php | 90 +++++++++---------- 2 files changed, 66 insertions(+), 66 deletions(-) diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/SecurityRoutingIntegrationTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/SecurityRoutingIntegrationTest.php index 3abfd9585f159..5996415e10a64 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/SecurityRoutingIntegrationTest.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/SecurityRoutingIntegrationTest.php @@ -78,27 +78,27 @@ public function testSecurityConfigurationForMultipleIPAddresses($config) $this->assertRestricted($barredClient, '/secured-by-two-ips'); } - /** - * @dataProvider getConfigs - */ - public function testSecurityConfigurationForExpression($config) - { - $allowedClient = $this->createClient(array('test_case' => 'StandardFormLogin', 'root_config' => $config), array('HTTP_USER_AGENT' => 'Firefox 1.0')); - $this->assertAllowed($allowedClient, '/protected-via-expression'); - - $barredClient = $this->createClient(array('test_case' => 'StandardFormLogin', 'root_config' => $config), array()); - $this->assertRestricted($barredClient, '/protected-via-expression'); - - $allowedClient = $this->createClient(array('test_case' => 'StandardFormLogin', 'root_config' => $config), array()); - - $allowedClient->request('GET', '/protected-via-expression'); - $form = $allowedClient->followRedirect()->selectButton('login')->form(); - $form['_username'] = 'johannes'; - $form['_password'] = 'test'; - $allowedClient->submit($form); - $this->assertRedirect($allowedClient->getResponse(), '/protected-via-expression'); - $this->assertAllowed($allowedClient, '/protected-via-expression'); - } + /** + * @dataProvider getConfigs + */ + public function testSecurityConfigurationForExpression($config) + { + $allowedClient = $this->createClient(array('test_case' => 'StandardFormLogin', 'root_config' => $config), array('HTTP_USER_AGENT' => 'Firefox 1.0')); + $this->assertAllowed($allowedClient, '/protected-via-expression'); + + $barredClient = $this->createClient(array('test_case' => 'StandardFormLogin', 'root_config' => $config), array()); + $this->assertRestricted($barredClient, '/protected-via-expression'); + + $allowedClient = $this->createClient(array('test_case' => 'StandardFormLogin', 'root_config' => $config), array()); + + $allowedClient->request('GET', '/protected-via-expression'); + $form = $allowedClient->followRedirect()->selectButton('login')->form(); + $form['_username'] = 'johannes'; + $form['_password'] = 'test'; + $allowedClient->submit($form); + $this->assertRedirect($allowedClient->getResponse(), '/protected-via-expression'); + $this->assertAllowed($allowedClient, '/protected-via-expression'); + } private function assertAllowed($client, $path) { diff --git a/src/Symfony/Component/ClassLoader/Tests/LegacyApcUniversalClassLoaderTest.php b/src/Symfony/Component/ClassLoader/Tests/LegacyApcUniversalClassLoaderTest.php index 6d4e57e984504..8ef97bfd58822 100644 --- a/src/Symfony/Component/ClassLoader/Tests/LegacyApcUniversalClassLoaderTest.php +++ b/src/Symfony/Component/ClassLoader/Tests/LegacyApcUniversalClassLoaderTest.php @@ -43,17 +43,17 @@ public function testConstructor() $this->assertEquals($loader->findFile('\LegacyApc\Namespaced\FooBar'), apcu_fetch('test.prefix.\LegacyApc\Namespaced\FooBar'), '__construct() takes a prefix as its first argument'); } - /** - * @dataProvider getLoadClassTests - */ - public function testLoadClass($className, $testClassName, $message) - { - $loader = new ApcUniversalClassLoader('test.prefix.'); - $loader->registerNamespace('LegacyApc\Namespaced', __DIR__.DIRECTORY_SEPARATOR.'Fixtures'); - $loader->registerPrefix('LegacyApc_Pearlike_', __DIR__.DIRECTORY_SEPARATOR.'Fixtures'); - $loader->loadClass($testClassName); - $this->assertTrue(class_exists($className), $message); - } + /** + * @dataProvider getLoadClassTests + */ + public function testLoadClass($className, $testClassName, $message) + { + $loader = new ApcUniversalClassLoader('test.prefix.'); + $loader->registerNamespace('LegacyApc\Namespaced', __DIR__.DIRECTORY_SEPARATOR.'Fixtures'); + $loader->registerPrefix('LegacyApc_Pearlike_', __DIR__.DIRECTORY_SEPARATOR.'Fixtures'); + $loader->loadClass($testClassName); + $this->assertTrue(class_exists($className), $message); + } public function getLoadClassTests() { @@ -63,19 +63,19 @@ public function getLoadClassTests() ); } - /** - * @dataProvider getLoadClassFromFallbackTests - */ - public function testLoadClassFromFallback($className, $testClassName, $message) - { - $loader = new ApcUniversalClassLoader('test.prefix.fallback'); - $loader->registerNamespace('LegacyApc\Namespaced', __DIR__.DIRECTORY_SEPARATOR.'Fixtures'); - $loader->registerPrefix('LegacyApc_Pearlike_', __DIR__.DIRECTORY_SEPARATOR.'Fixtures'); - $loader->registerNamespaceFallbacks(array(__DIR__.DIRECTORY_SEPARATOR.'Fixtures/LegacyApc/fallback')); - $loader->registerPrefixFallbacks(array(__DIR__.DIRECTORY_SEPARATOR.'Fixtures/LegacyApc/fallback')); - $loader->loadClass($testClassName); - $this->assertTrue(class_exists($className), $message); - } + /** + * @dataProvider getLoadClassFromFallbackTests + */ + public function testLoadClassFromFallback($className, $testClassName, $message) + { + $loader = new ApcUniversalClassLoader('test.prefix.fallback'); + $loader->registerNamespace('LegacyApc\Namespaced', __DIR__.DIRECTORY_SEPARATOR.'Fixtures'); + $loader->registerPrefix('LegacyApc_Pearlike_', __DIR__.DIRECTORY_SEPARATOR.'Fixtures'); + $loader->registerNamespaceFallbacks(array(__DIR__.DIRECTORY_SEPARATOR.'Fixtures/LegacyApc/fallback')); + $loader->registerPrefixFallbacks(array(__DIR__.DIRECTORY_SEPARATOR.'Fixtures/LegacyApc/fallback')); + $loader->loadClass($testClassName); + $this->assertTrue(class_exists($className), $message); + } public function getLoadClassFromFallbackTests() { @@ -87,18 +87,18 @@ public function getLoadClassFromFallbackTests() ); } - /** - * @dataProvider getLoadClassNamespaceCollisionTests - */ - public function testLoadClassNamespaceCollision($namespaces, $className, $message) - { - $loader = new ApcUniversalClassLoader('test.prefix.collision.'); - $loader->registerNamespaces($namespaces); + /** + * @dataProvider getLoadClassNamespaceCollisionTests + */ + public function testLoadClassNamespaceCollision($namespaces, $className, $message) + { + $loader = new ApcUniversalClassLoader('test.prefix.collision.'); + $loader->registerNamespaces($namespaces); - $loader->loadClass($className); + $loader->loadClass($className); - $this->assertTrue(class_exists($className), $message); - } + $this->assertTrue(class_exists($className), $message); + } public function getLoadClassNamespaceCollisionTests() { @@ -138,17 +138,17 @@ public function getLoadClassNamespaceCollisionTests() ); } - /** - * @dataProvider getLoadClassPrefixCollisionTests - */ - public function testLoadClassPrefixCollision($prefixes, $className, $message) - { - $loader = new ApcUniversalClassLoader('test.prefix.collision.'); - $loader->registerPrefixes($prefixes); - - $loader->loadClass($className); - $this->assertTrue(class_exists($className), $message); - } + /** + * @dataProvider getLoadClassPrefixCollisionTests + */ + public function testLoadClassPrefixCollision($prefixes, $className, $message) + { + $loader = new ApcUniversalClassLoader('test.prefix.collision.'); + $loader->registerPrefixes($prefixes); + + $loader->loadClass($className); + $this->assertTrue(class_exists($className), $message); + } public function getLoadClassPrefixCollisionTests() { From d879eed12aa9973ca0dbecf5769412723aeffb17 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Wed, 5 Jul 2017 09:33:38 +0300 Subject: [PATCH 0346/1099] fixed bad merge --- src/Symfony/Component/HttpKernel/Kernel.php | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/Symfony/Component/HttpKernel/Kernel.php b/src/Symfony/Component/HttpKernel/Kernel.php index 7fde926bb6bec..67a02337b510c 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -59,19 +59,11 @@ abstract class Kernel implements KernelInterface, TerminableInterface protected $startTime; protected $loadClassCache; -<<<<<<< HEAD const VERSION = '2.8.24-DEV'; const VERSION_ID = 20824; const MAJOR_VERSION = 2; const MINOR_VERSION = 8; const RELEASE_VERSION = 24; -======= - const VERSION = '2.7.31-DEV'; - const VERSION_ID = 20731; - const MAJOR_VERSION = 2; - const MINOR_VERSION = 7; - const RELEASE_VERSION = 31; ->>>>>>> 2.7 const EXTRA_VERSION = 'DEV'; const END_OF_MAINTENANCE = '11/2018'; From ab2703be77840e4b0e3229481f675653e45cad04 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Wed, 5 Jul 2017 10:15:57 +0300 Subject: [PATCH 0347/1099] updated CHANGELOG for 2.7.31 --- CHANGELOG-2.7.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG-2.7.md b/CHANGELOG-2.7.md index cf90bc2e50f34..f5471bf653f4b 100644 --- a/CHANGELOG-2.7.md +++ b/CHANGELOG-2.7.md @@ -7,6 +7,10 @@ in 2.7 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/v2.7.0...v2.7.1 +* 2.7.31 (2017-07-05) + + * bug #23378 [FrameworkBundle] Do not remove files from assets dir (1ed) + * 2.7.30 (2017-07-03) * bug #23341 [DoctrineBridge][Security][Validator] do not validate empty values (xabbuh) From 3d332e53d46905eabc2d1daef8639da20ac56993 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Wed, 5 Jul 2017 10:16:08 +0300 Subject: [PATCH 0348/1099] update CONTRIBUTORS for 2.7.31 --- CONTRIBUTORS.md | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index 0b695308c528f..3e670f8d67e90 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -70,9 +70,9 @@ Symfony is the result of the work of many people who made the code better - Deni - Henrik Westphal (snc) - Dariusz Górecki (canni) + - Jáchym Toušek (enumag) - Titouan Galopin (tgalopin) - Douglas Greenshields (shieldo) - - Jáchym Toušek (enumag) - Konstantin Myakshin (koc) - Lee McDermott - Brandon Turner @@ -99,11 +99,12 @@ Symfony is the result of the work of many people who made the code better - Baptiste Clavié (talus) - Vladimir Reznichenko (kalessil) - marc.weistroff + - Yonel Ceruto González (yonelceruto) - lenar - Włodzimierz Gajda (gajdaw) - - Yonel Ceruto González (yonelceruto) - Alexander Schwenn (xelaris) - Jacob Dreesen (jdreesen) + - Tobias Nyholm (tobias) - Florian Voutzinos (florianv) - Colin Frei - Adrien Brault (adrienbrault) @@ -111,7 +112,6 @@ Symfony is the result of the work of many people who made the code better - Peter Kokot (maastermedia) - David Buchmann (dbu) - excelwebzone - - Tobias Nyholm (tobias) - Tomáš Votruba (tomas_votruba) - Fabien Pennequin (fabienpennequin) - Gordon Franke (gimler) @@ -133,12 +133,15 @@ Symfony is the result of the work of many people who made the code better - Guilherme Blanco (guilhermeblanco) - Pablo Godel (pgodel) - Jérémie Augustin (jaugustin) + - Dany Maillard (maidmaid) - Andréia Bohner (andreia) - Rafael Dohms (rdohms) - Arnaud Kleinpeter (nanocom) - jwdeitch + - David Maicher (dmaicher) - Mikael Pajunen - Joel Wurtz (brouznouf) + - Grégoire Paris (greg0ire) - Philipp Wahala (hifi) - Vyacheslav Pavlov - Richard van Laak (rvanlaak) @@ -147,11 +150,9 @@ Symfony is the result of the work of many people who made the code better - Thomas Rabaix (rande) - Rouven Weßling (realityking) - Teoh Han Hui (teohhanhui) - - David Maicher (dmaicher) - Jérôme Vasseur (jvasseur) - Clemens Tolboom - Helmer Aaviksoo - - Grégoire Paris (greg0ire) - Hiromi Hishida (77web) - Matthieu Ouellette-Vachon (maoueh) - Michał Pipa (michal.pipa) @@ -234,7 +235,6 @@ Symfony is the result of the work of many people who made the code better - Arjen Brouwer (arjenjb) - Katsuhiro OGAWA - Patrick McDougle (patrick-mcdougle) - - Dany Maillard (maidmaid) - Alif Rachmawadi - Kristen Gilden (kgilden) - Pierre-Yves LEBECQ (pylebecq) @@ -620,6 +620,7 @@ Symfony is the result of the work of many people who made the code better - develop - ReenExe - Mark Sonnabaum + - Maxime Veber (nek-) - Richard Quadling - jochenvdv - Arturas Smorgun (asarturas) @@ -642,6 +643,7 @@ Symfony is the result of the work of many people who made the code better - Trent Steel (trsteel88) - Yuen-Chi Lian - Besnik Br + - Jose Gonzalez - Dariusz Ruminski - Joshua Nye - Claudio Zizza @@ -1081,7 +1083,6 @@ Symfony is the result of the work of many people who made the code better - Max Summe - WedgeSama - Felds Liscia - - Maxime Veber (nek-) - Sullivan SENECHAL - Tadcka - Beth Binkovitz @@ -1092,12 +1093,12 @@ Symfony is the result of the work of many people who made the code better - Tomaz Ahlin - Marcus Stöhr (dafish) - Emmanuel Vella (emmanuel.vella) + - Adam Szaraniec (mimol) - Carsten Nielsen (phreaknerd) - Mathieu Rochette - Jay Severson - René Kerner - Nathaniel Catchpole - - Jose Gonzalez - Adrien Samson (adriensamson) - Samuel Gordalina (gordalina) - Max Romanovsky (maxromanovsky) @@ -1258,6 +1259,7 @@ Symfony is the result of the work of many people who made the code better - Aarón Nieves Fernández - Mike Meier - Kirill Saksin + - Julien Pauli - Koalabaerchen - michalmarcinkowski - Warwick @@ -1305,6 +1307,7 @@ Symfony is the result of the work of many people who made the code better - klemens - dened - Dmitry Korotovsky + - mcorteel - Michael van Tricht - Sam Ward - Walther Lalk @@ -1335,6 +1338,7 @@ Symfony is the result of the work of many people who made the code better - Jan Marek (janmarek) - Mark de Haan (markdehaan) - Dan Patrick (mdpatrick) + - Pedro Magalhães (pmmaga) - Rares Vlaseanu (raresvla) - tante kinast (tante) - Vincent LEFORT (vlefort) @@ -1542,6 +1546,7 @@ Symfony is the result of the work of many people who made the code better - Abdulkadir N. A. - Yevgen Kovalienia - Lebnik + - Shude - Ondřej Führer - Sema - Elan Ruusamäe From beee4332a1ead444d4d04964e3e36fcddc03a3f1 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Wed, 5 Jul 2017 10:16:12 +0300 Subject: [PATCH 0349/1099] updated VERSION for 2.7.31 --- 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 fc6c87b9e0665..6233186a48e22 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -58,12 +58,12 @@ abstract class Kernel implements KernelInterface, TerminableInterface protected $startTime; protected $loadClassCache; - const VERSION = '2.7.31-DEV'; + const VERSION = '2.7.31'; const VERSION_ID = 20731; const MAJOR_VERSION = 2; const MINOR_VERSION = 7; const RELEASE_VERSION = 31; - const EXTRA_VERSION = 'DEV'; + const EXTRA_VERSION = ''; const END_OF_MAINTENANCE = '05/2018'; const END_OF_LIFE = '05/2019'; From 7b442211dc8ad4df4a8d65d2be0ab006082a1a6b Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Wed, 5 Jul 2017 10:25:28 +0300 Subject: [PATCH 0350/1099] [Filesystem] Dont copy perms when origin is remote --- src/Symfony/Component/Filesystem/Filesystem.php | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/Symfony/Component/Filesystem/Filesystem.php b/src/Symfony/Component/Filesystem/Filesystem.php index e60d4690738ad..bc2e3dcc2d897 100644 --- a/src/Symfony/Component/Filesystem/Filesystem.php +++ b/src/Symfony/Component/Filesystem/Filesystem.php @@ -37,7 +37,8 @@ class Filesystem */ public function copy($originFile, $targetFile, $overwriteNewerFiles = false) { - if (stream_is_local($originFile) && !is_file($originFile)) { + $originIsLocal = stream_is_local($originFile) || 0 === stripos($originFile, 'file://'); + if ($originIsLocal && !is_file($originFile)) { throw new FileNotFoundException(sprintf('Failed to copy "%s" because file does not exist.', $originFile), 0, null, $originFile); } @@ -68,11 +69,13 @@ public function copy($originFile, $targetFile, $overwriteNewerFiles = false) throw new IOException(sprintf('Failed to copy "%s" to "%s".', $originFile, $targetFile), 0, null, $originFile); } - // Like `cp`, preserve executable permission bits - @chmod($targetFile, fileperms($targetFile) | (fileperms($originFile) & 0111)); + if ($originIsLocal) { + // Like `cp`, preserve executable permission bits + @chmod($targetFile, fileperms($targetFile) | (fileperms($originFile) & 0111)); - if (stream_is_local($originFile) && $bytesCopied !== ($bytesOrigin = filesize($originFile))) { - throw new IOException(sprintf('Failed to copy the whole content of "%s" to "%s" (%g of %g bytes copied).', $originFile, $targetFile, $bytesCopied, $bytesOrigin), 0, null, $originFile); + if ($bytesCopied !== $bytesOrigin = filesize($originFile)) { + throw new IOException(sprintf('Failed to copy the whole content of "%s" to "%s" (%g of %g bytes copied).', $originFile, $targetFile, $bytesCopied, $bytesOrigin), 0, null, $originFile); + } } } } From 39fc4ddec79a56dd44e129b7b165b9e2cfe9cb79 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Wed, 5 Jul 2017 11:52:01 +0300 Subject: [PATCH 0351/1099] bumped Symfony version to 2.7.32 --- 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 6233186a48e22..00d9c8236590a 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -58,12 +58,12 @@ abstract class Kernel implements KernelInterface, TerminableInterface protected $startTime; protected $loadClassCache; - const VERSION = '2.7.31'; - const VERSION_ID = 20731; + const VERSION = '2.7.32-DEV'; + const VERSION_ID = 20732; const MAJOR_VERSION = 2; const MINOR_VERSION = 7; - const RELEASE_VERSION = 31; - const EXTRA_VERSION = ''; + const RELEASE_VERSION = 32; + const EXTRA_VERSION = 'DEV'; const END_OF_MAINTENANCE = '05/2018'; const END_OF_LIFE = '05/2019'; From 09797de7578b9ff71ffeeda52918397fd871e7cc Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Wed, 5 Jul 2017 11:52:53 +0300 Subject: [PATCH 0352/1099] updated CHANGELOG for 2.8.24 --- CHANGELOG-2.8.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG-2.8.md b/CHANGELOG-2.8.md index ce55fb16317b8..661863ef7ce54 100644 --- a/CHANGELOG-2.8.md +++ b/CHANGELOG-2.8.md @@ -7,6 +7,10 @@ in 2.8 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/v2.8.0...v2.8.1 +* 2.8.24 (2017-07-05) + + * bug #23378 [FrameworkBundle] Do not remove files from assets dir (1ed) + * 2.8.23 (2017-07-04) * bug #23341 [DoctrineBridge][Security][Validator] do not validate empty values (xabbuh) From bf1be0e08f4e3e2d0f76b66c12de20fd793e1060 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Wed, 5 Jul 2017 11:52:59 +0300 Subject: [PATCH 0353/1099] updated VERSION for 2.8.24 --- 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 67a02337b510c..056d2e2aad253 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -59,12 +59,12 @@ abstract class Kernel implements KernelInterface, TerminableInterface protected $startTime; protected $loadClassCache; - const VERSION = '2.8.24-DEV'; + const VERSION = '2.8.24'; const VERSION_ID = 20824; const MAJOR_VERSION = 2; const MINOR_VERSION = 8; const RELEASE_VERSION = 24; - const EXTRA_VERSION = 'DEV'; + const EXTRA_VERSION = ''; const END_OF_MAINTENANCE = '11/2018'; const END_OF_LIFE = '11/2019'; From 5d35184d7aec13a3cbc6bbbad9fdeba4c3591aca Mon Sep 17 00:00:00 2001 From: Dany Maillard Date: Wed, 5 Jul 2017 11:08:46 +0200 Subject: [PATCH 0354/1099] Remove the RenameEntryInterface interface --- .../Ldap/Adapter/EntryManagerInterface.php | 10 +++++++++ .../Ldap/Adapter/ExtLdap/EntryManager.php | 3 +-- .../Ldap/Adapter/RenameEntryInterface.php | 22 ------------------- src/Symfony/Component/Ldap/CHANGELOG.md | 1 + 4 files changed, 12 insertions(+), 24 deletions(-) delete mode 100644 src/Symfony/Component/Ldap/Adapter/RenameEntryInterface.php diff --git a/src/Symfony/Component/Ldap/Adapter/EntryManagerInterface.php b/src/Symfony/Component/Ldap/Adapter/EntryManagerInterface.php index 9538abfae2b25..82c023d5ec06d 100644 --- a/src/Symfony/Component/Ldap/Adapter/EntryManagerInterface.php +++ b/src/Symfony/Component/Ldap/Adapter/EntryManagerInterface.php @@ -20,6 +20,7 @@ * * @author Charles Sarrazin * @author Bob van de Vijver + * @author Kevin Schuurmans */ interface EntryManagerInterface { @@ -43,6 +44,15 @@ public function add(Entry $entry); */ public function update(Entry $entry); + /** + * Renames an entry on the Ldap server. + * + * @param Entry $entry + * @param string $newRdn + * @param bool $removeOldRdn + */ + public function rename(Entry $entry, $newRdn, $removeOldRdn = true); + /** * Removes an entry from the Ldap server. * diff --git a/src/Symfony/Component/Ldap/Adapter/ExtLdap/EntryManager.php b/src/Symfony/Component/Ldap/Adapter/ExtLdap/EntryManager.php index 225414884bea2..09c0567ec4979 100644 --- a/src/Symfony/Component/Ldap/Adapter/ExtLdap/EntryManager.php +++ b/src/Symfony/Component/Ldap/Adapter/ExtLdap/EntryManager.php @@ -12,7 +12,6 @@ namespace Symfony\Component\Ldap\Adapter\ExtLdap; use Symfony\Component\Ldap\Adapter\EntryManagerInterface; -use Symfony\Component\Ldap\Adapter\RenameEntryInterface; use Symfony\Component\Ldap\Entry; use Symfony\Component\Ldap\Exception\LdapException; use Symfony\Component\Ldap\Exception\NotBoundException; @@ -21,7 +20,7 @@ * @author Charles Sarrazin * @author Bob van de Vijver */ -class EntryManager implements EntryManagerInterface, RenameEntryInterface +class EntryManager implements EntryManagerInterface { private $connection; diff --git a/src/Symfony/Component/Ldap/Adapter/RenameEntryInterface.php b/src/Symfony/Component/Ldap/Adapter/RenameEntryInterface.php deleted file mode 100644 index 8bc70bda9637a..0000000000000 --- a/src/Symfony/Component/Ldap/Adapter/RenameEntryInterface.php +++ /dev/null @@ -1,22 +0,0 @@ - - */ -interface RenameEntryInterface -{ - /** - * Renames an entry on the Ldap server. - * - * @param Entry $entry - * @param string $newRdn - * @param bool $removeOldRdn - */ - public function rename(Entry $entry, $newRdn, $removeOldRdn = true); -} diff --git a/src/Symfony/Component/Ldap/CHANGELOG.md b/src/Symfony/Component/Ldap/CHANGELOG.md index e70e61c45ed85..84aa6265de295 100644 --- a/src/Symfony/Component/Ldap/CHANGELOG.md +++ b/src/Symfony/Component/Ldap/CHANGELOG.md @@ -5,6 +5,7 @@ CHANGELOG ----- * removed the `LdapClient` class and the `LdapClientInterface` + * removed the `RenameEntryInterface` interface and merged with `EntryManagerInterface` 3.1.0 ----- From 959ac2a6b2089aecc091cc9267f58ea9562cc2f8 Mon Sep 17 00:00:00 2001 From: Maxime Steinhausser Date: Wed, 5 Jul 2017 11:12:59 +0200 Subject: [PATCH 0355/1099] [Serializer] AbstractObjectNormalizer: Allow to disable type enforcement --- src/Symfony/Component/Serializer/CHANGELOG.md | 6 ++++++ .../Serializer/Normalizer/AbstractObjectNormalizer.php | 5 +++++ .../Tests/Normalizer/ObjectNormalizerTest.php | 10 ++++++++++ 3 files changed, 21 insertions(+) diff --git a/src/Symfony/Component/Serializer/CHANGELOG.md b/src/Symfony/Component/Serializer/CHANGELOG.md index ef5ed79538072..2e10bd469bab4 100644 --- a/src/Symfony/Component/Serializer/CHANGELOG.md +++ b/src/Symfony/Component/Serializer/CHANGELOG.md @@ -1,6 +1,12 @@ CHANGELOG ========= +3.4.0 +----- + + * added `AbstractObjectNormalizer::DISABLE_TYPE_ENFORCEMENT` context option + to disable throwing an `UnexpectedValueException` on a type mismatch + 3.3.0 ----- diff --git a/src/Symfony/Component/Serializer/Normalizer/AbstractObjectNormalizer.php b/src/Symfony/Component/Serializer/Normalizer/AbstractObjectNormalizer.php index 4e4b99245da3c..d9174b949b480 100644 --- a/src/Symfony/Component/Serializer/Normalizer/AbstractObjectNormalizer.php +++ b/src/Symfony/Component/Serializer/Normalizer/AbstractObjectNormalizer.php @@ -33,6 +33,7 @@ abstract class AbstractObjectNormalizer extends AbstractNormalizer const ENABLE_MAX_DEPTH = 'enable_max_depth'; const DEPTH_KEY_PATTERN = 'depth_%s::%s'; const ALLOW_EXTRA_ATTRIBUTES = 'allow_extra_attributes'; + const DISABLE_TYPE_ENFORCEMENT = 'disable_type_enforcement'; private $propertyTypeExtractor; private $attributesCache = array(); @@ -289,6 +290,10 @@ private function validateAndDenormalize($currentClass, $attribute, $data, $forma } } + if (isset($context[self::DISABLE_TYPE_ENFORCEMENT]) && $context[self::DISABLE_TYPE_ENFORCEMENT]) { + return $data; + } + throw new UnexpectedValueException(sprintf('The type of the "%s" attribute for class "%s" must be one of "%s" ("%s" given).', $attribute, $currentClass, implode('", "', array_keys($expectedTypes)), gettype($data))); } diff --git a/src/Symfony/Component/Serializer/Tests/Normalizer/ObjectNormalizerTest.php b/src/Symfony/Component/Serializer/Tests/Normalizer/ObjectNormalizerTest.php index b2d7b872f4d94..f10937bd9c3a2 100644 --- a/src/Symfony/Component/Serializer/Tests/Normalizer/ObjectNormalizerTest.php +++ b/src/Symfony/Component/Serializer/Tests/Normalizer/ObjectNormalizerTest.php @@ -628,6 +628,16 @@ public function testRejectInvalidKey() $serializer->denormalize(array('inners' => array('a' => array('foo' => 1))), ObjectOuter::class); } + public function testDoNotRejectInvalidTypeOnDisableTypeEnforcementContextOption() + { + $extractor = new PropertyInfoExtractor(array(), array(new PhpDocExtractor())); + $normalizer = new ObjectNormalizer(null, null, null, $extractor); + $serializer = new Serializer(array($normalizer)); + $context = array(ObjectNormalizer::DISABLE_TYPE_ENFORCEMENT => true); + + $this->assertSame('foo', $serializer->denormalize(array('number' => 'foo'), JsonNumber::class, null, $context)->number); + } + public function testExtractAttributesRespectsFormat() { $normalizer = new FormatAndContextAwareNormalizer(); From 15df829a83ffd22c7bf3aa45b4630dfb16d1518c Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Wed, 5 Jul 2017 12:39:23 +0300 Subject: [PATCH 0356/1099] bumped Symfony version to 2.8.25 --- 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 056d2e2aad253..150fc17cf1987 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -59,12 +59,12 @@ abstract class Kernel implements KernelInterface, TerminableInterface protected $startTime; protected $loadClassCache; - const VERSION = '2.8.24'; - const VERSION_ID = 20824; + const VERSION = '2.8.25-DEV'; + const VERSION_ID = 20825; const MAJOR_VERSION = 2; const MINOR_VERSION = 8; - const RELEASE_VERSION = 24; - const EXTRA_VERSION = ''; + const RELEASE_VERSION = 25; + const EXTRA_VERSION = 'DEV'; const END_OF_MAINTENANCE = '11/2018'; const END_OF_LIFE = '11/2019'; From 0cd605bdea66f91526644582ae02b1435974c8ad Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Wed, 5 Jul 2017 12:51:40 +0300 Subject: [PATCH 0357/1099] updated CHANGELOG for 3.2.11 --- CHANGELOG-3.2.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG-3.2.md b/CHANGELOG-3.2.md index 5542e4160d1c3..de3c3fd9977b5 100644 --- a/CHANGELOG-3.2.md +++ b/CHANGELOG-3.2.md @@ -7,6 +7,11 @@ in 3.2 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.2.0...v3.2.1 +* 3.2.11 (2017-07-05) + + * bug #23390 [Cache] Handle APCu failures gracefully (nicolas-grekas) + * bug #23378 [FrameworkBundle] Do not remove files from assets dir (1ed) + * 3.2.10 (2017-07-04) * bug #23366 [FrameworkBundle] Don't get() private services from debug:router (chalasr) From 99e70b8cc0d7d0c77fb8b17a7ff52862438bdaa1 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Wed, 5 Jul 2017 12:51:47 +0300 Subject: [PATCH 0358/1099] updated VERSION for 3.2.11 --- 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 599cf6da6f932..bdfd2b2d9c4e7 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -58,12 +58,12 @@ abstract class Kernel implements KernelInterface, TerminableInterface protected $startTime; protected $loadClassCache; - const VERSION = '3.2.11-DEV'; + const VERSION = '3.2.11'; const VERSION_ID = 30211; const MAJOR_VERSION = 3; const MINOR_VERSION = 2; const RELEASE_VERSION = 11; - const EXTRA_VERSION = 'DEV'; + const EXTRA_VERSION = ''; const END_OF_MAINTENANCE = '07/2017'; const END_OF_LIFE = '01/2018'; From 692acb4d64c1bb5e2b0cb261f546d21fb7ba6dd0 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Wed, 5 Jul 2017 13:46:19 +0300 Subject: [PATCH 0359/1099] bumped Symfony version to 3.2.12 --- 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 bdfd2b2d9c4e7..dd6568b9893b5 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -58,12 +58,12 @@ abstract class Kernel implements KernelInterface, TerminableInterface protected $startTime; protected $loadClassCache; - const VERSION = '3.2.11'; - const VERSION_ID = 30211; + const VERSION = '3.2.12-DEV'; + const VERSION_ID = 30212; const MAJOR_VERSION = 3; const MINOR_VERSION = 2; - const RELEASE_VERSION = 11; - const EXTRA_VERSION = ''; + const RELEASE_VERSION = 12; + const EXTRA_VERSION = 'DEV'; const END_OF_MAINTENANCE = '07/2017'; const END_OF_LIFE = '01/2018'; From 64c2efd8cbabdf88f72352b399676ef914f5e191 Mon Sep 17 00:00:00 2001 From: Robin Chalas Date: Thu, 22 Jun 2017 00:05:03 +0200 Subject: [PATCH 0360/1099] [Security] Fix authentication.failure event not dispatched on AccountStatusException --- .../AuthenticationProviderManager.php | 4 +- .../AuthenticationProviderManagerTest.php | 47 +++++++++++++++++++ 2 files changed, 49 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/Security/Core/Authentication/AuthenticationProviderManager.php b/src/Symfony/Component/Security/Core/Authentication/AuthenticationProviderManager.php index 16de8daaeda93..4c0a7459d070c 100644 --- a/src/Symfony/Component/Security/Core/Authentication/AuthenticationProviderManager.php +++ b/src/Symfony/Component/Security/Core/Authentication/AuthenticationProviderManager.php @@ -83,9 +83,9 @@ public function authenticate(TokenInterface $token) break; } } catch (AccountStatusException $e) { - $e->setToken($token); + $lastException = $e; - throw $e; + break; } catch (AuthenticationException $e) { $lastException = $e; } diff --git a/src/Symfony/Component/Security/Core/Tests/Authentication/AuthenticationProviderManagerTest.php b/src/Symfony/Component/Security/Core/Tests/Authentication/AuthenticationProviderManagerTest.php index 9b8105012c3d8..373369d455959 100644 --- a/src/Symfony/Component/Security/Core/Tests/Authentication/AuthenticationProviderManagerTest.php +++ b/src/Symfony/Component/Security/Core/Tests/Authentication/AuthenticationProviderManagerTest.php @@ -13,6 +13,9 @@ use PHPUnit\Framework\TestCase; use Symfony\Component\Security\Core\Authentication\AuthenticationProviderManager; +use Symfony\Component\Security\Core\AuthenticationEvents; +use Symfony\Component\Security\Core\Event\AuthenticationEvent; +use Symfony\Component\Security\Core\Event\AuthenticationFailureEvent; use Symfony\Component\Security\Core\Exception\ProviderNotFoundException; use Symfony\Component\Security\Core\Exception\AuthenticationException; use Symfony\Component\Security\Core\Exception\AccountStatusException; @@ -124,6 +127,50 @@ public function testEraseCredentialFlag() $this->assertEquals('bar', $token->getCredentials()); } + public function testAuthenticateDispatchesAuthenticationFailureEvent() + { + $token = new UsernamePasswordToken('foo', 'bar', 'key'); + $provider = $this->getMockBuilder('Symfony\Component\Security\Core\Authentication\Provider\AuthenticationProviderInterface')->getMock(); + $provider->expects($this->once())->method('supports')->willReturn(true); + $provider->expects($this->once())->method('authenticate')->willThrowException($exception = new AuthenticationException()); + + $dispatcher = $this->getMockBuilder('Symfony\Component\EventDispatcher\EventDispatcherInterface')->getMock(); + $dispatcher + ->expects($this->once()) + ->method('dispatch') + ->with(AuthenticationEvents::AUTHENTICATION_FAILURE, $this->equalTo(new AuthenticationFailureEvent($token, $exception))); + + $manager = new AuthenticationProviderManager(array($provider)); + $manager->setEventDispatcher($dispatcher); + + try { + $manager->authenticate($token); + $this->fail('->authenticate() should rethrow exceptions'); + } catch (AuthenticationException $e) { + $this->assertSame($token, $exception->getToken()); + } + } + + public function testAuthenticateDispatchesAuthenticationSuccessEvent() + { + $token = new UsernamePasswordToken('foo', 'bar', 'key'); + + $provider = $this->getMockBuilder('Symfony\Component\Security\Core\Authentication\Provider\AuthenticationProviderInterface')->getMock(); + $provider->expects($this->once())->method('supports')->willReturn(true); + $provider->expects($this->once())->method('authenticate')->willReturn($token); + + $dispatcher = $this->getMockBuilder('Symfony\Component\EventDispatcher\EventDispatcherInterface')->getMock(); + $dispatcher + ->expects($this->once()) + ->method('dispatch') + ->with(AuthenticationEvents::AUTHENTICATION_SUCCESS, $this->equalTo(new AuthenticationEvent($token))); + + $manager = new AuthenticationProviderManager(array($provider)); + $manager->setEventDispatcher($dispatcher); + + $this->assertSame($token, $manager->authenticate($token)); + } + protected function getAuthenticationProvider($supports, $token = null, $exception = null) { $provider = $this->getMockBuilder('Symfony\Component\Security\Core\Authentication\Provider\AuthenticationProviderInterface')->getMock(); From 70bd2bc41b5146af1f1e07c9159c6b246095d6de Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Wed, 5 Jul 2017 15:26:31 +0300 Subject: [PATCH 0361/1099] [VarDumper] Reduce size of serialized Data objects --- src/Symfony/Component/Debug/ErrorHandler.php | 2 +- .../DataCollector/LoggerDataCollector.php | 3 +- src/Symfony/Component/HttpKernel/Kernel.php | 2 +- .../DataCollector/DumpDataCollectorTest.php | 2 +- .../Component/VarDumper/Cloner/Data.php | 72 ++++++++++++++++++- 5 files changed, 76 insertions(+), 5 deletions(-) diff --git a/src/Symfony/Component/Debug/ErrorHandler.php b/src/Symfony/Component/Debug/ErrorHandler.php index e25b5a6dd8b2a..369ed26f125c4 100644 --- a/src/Symfony/Component/Debug/ErrorHandler.php +++ b/src/Symfony/Component/Debug/ErrorHandler.php @@ -414,7 +414,7 @@ public function handleError($type, $message, $file, $line) $errorAsException = self::$silencedErrorCache[$message]; ++$errorAsException->count; } else { - $lightTrace = $this->tracedErrors & $type ? $this->cleanTrace(debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS), $type, $file, $line, false) : array(); + $lightTrace = $this->tracedErrors & $type ? $this->cleanTrace(debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 3), $type, $file, $line, false) : array(); $errorAsException = new SilencedErrorContext($type, $file, $line, $lightTrace); } diff --git a/src/Symfony/Component/HttpKernel/DataCollector/LoggerDataCollector.php b/src/Symfony/Component/HttpKernel/DataCollector/LoggerDataCollector.php index f45f99718d318..92fd0da71e648 100644 --- a/src/Symfony/Component/HttpKernel/DataCollector/LoggerDataCollector.php +++ b/src/Symfony/Component/HttpKernel/DataCollector/LoggerDataCollector.php @@ -120,6 +120,7 @@ private function getContainerDeprecationLogs() $log['priorityName'] = 'DEBUG'; $log['channel'] = '-'; $log['scream'] = false; + unset($log['type'], $log['file'], $log['line'], $log['trace'], $log['trace'], $log['count']); $logs[] = $log; } @@ -251,7 +252,7 @@ private function computeErrorsCount(array $containerDeprecationLogs) } foreach ($containerDeprecationLogs as $deprecationLog) { - $count['deprecation_count'] += $deprecationLog['count']; + $count['deprecation_count'] += $deprecationLog['context']['exception']->count; } ksort($count['priorities']); diff --git a/src/Symfony/Component/HttpKernel/Kernel.php b/src/Symfony/Component/HttpKernel/Kernel.php index 1a0f2434dc60f..d6ea3e6f04c59 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -551,7 +551,7 @@ protected function initializeContainer() return; } - $backtrace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS); + $backtrace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 3); // Clean the trace by removing first frames added by the error handler itself. for ($i = 0; isset($backtrace[$i]); ++$i) { if (isset($backtrace[$i]['file'], $backtrace[$i]['line']) && $backtrace[$i]['line'] === $line && $backtrace[$i]['file'] === $file) { diff --git a/src/Symfony/Component/HttpKernel/Tests/DataCollector/DumpDataCollectorTest.php b/src/Symfony/Component/HttpKernel/Tests/DataCollector/DumpDataCollectorTest.php index 9a306e533e006..e642e3c33715f 100644 --- a/src/Symfony/Component/HttpKernel/Tests/DataCollector/DumpDataCollectorTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/DataCollector/DumpDataCollectorTest.php @@ -50,7 +50,7 @@ public function testDump() ); $this->assertEquals($xDump, $dump); - $this->assertStringMatchesFormat('a:3:{i:0;a:5:{s:4:"data";O:39:"Symfony\Component\VarDumper\Cloner\Data":%a', $collector->serialize()); + $this->assertStringMatchesFormat('a:3:{i:0;a:5:{s:4:"data";%c:39:"Symfony\Component\VarDumper\Cloner\Data":%a', $collector->serialize()); $this->assertSame(0, $collector->getDumpsCount()); $this->assertSame('a:2:{i:0;b:0;i:1;s:5:"UTF-8";}', $collector->serialize()); } diff --git a/src/Symfony/Component/VarDumper/Cloner/Data.php b/src/Symfony/Component/VarDumper/Cloner/Data.php index 5a6997cf251cb..655fae0ca6fe5 100644 --- a/src/Symfony/Component/VarDumper/Cloner/Data.php +++ b/src/Symfony/Component/VarDumper/Cloner/Data.php @@ -16,7 +16,7 @@ /** * @author Nicolas Grekas */ -class Data implements \ArrayAccess, \Countable, \IteratorAggregate +class Data implements \ArrayAccess, \Countable, \IteratorAggregate, \Serializable { private $data; private $position = 0; @@ -278,6 +278,57 @@ public function dump(DumperInterface $dumper) $this->dumpItem($dumper, new Cursor(), $refs, $this->data[$this->position][$this->key]); } + /** + * @internal + */ + public function serialize() + { + $data = $this->data; + + foreach ($data as $i => $values) { + foreach ($values as $k => $v) { + if ($v instanceof Stub) { + if (Stub::TYPE_ARRAY === $v->type) { + $v = self::mapStubConsts($v, false); + $data[$i][$k] = array($v->class, $v->position, $v->cut); + } else { + $v = self::mapStubConsts($v, false); + $data[$i][$k] = array($v->class, $v->position, $v->cut, $v->type, $v->value, $v->handle, $v->refCount, $v->attr); + } + } + } + } + + return serialize(array($data, $this->position, $this->key, $this->maxDepth, $this->maxItemsPerDepth, $this->useRefHandles)); + } + + /** + * @internal + */ + public function unserialize($serialized) + { + list($data, $this->position, $this->key, $this->maxDepth, $this->maxItemsPerDepth, $this->useRefHandles) = unserialize($serialized); + + foreach ($data as $i => $values) { + foreach ($values as $k => $v) { + if ($v && is_array($v)) { + $s = new Stub(); + if (3 === count($v)) { + $s->type = Stub::TYPE_ARRAY; + $s = self::mapStubConsts($s, false); + list($s->class, $s->position, $s->cut) = $v; + $s->value = $s->cut + count($data[$s->position]); + } else { + list($s->class, $s->position, $s->cut, $s->type, $s->value, $s->handle, $s->refCount, $s->attr) = $v; + } + $data[$i][$k] = self::mapStubConsts($s, true); + } + } + } + + $this->data = $data; + } + /** * Depth-first dumping of items. * @@ -406,4 +457,23 @@ private function dumpChildren($dumper, $parentCursor, &$refs, $children, $hashCu return $hashCut; } + + private static function mapStubConsts(Stub $stub, $resolve) + { + static $stubConstIndexes, $stubConstValues; + + if (null === $stubConstIndexes) { + $r = new \ReflectionClass(Stub::class); + $stubConstIndexes = array_flip(array_values($r->getConstants())); + $stubConstValues = array_flip($stubConstIndexes); + } + + $map = $resolve ? $stubConstValues : $stubConstIndexes; + + $stub = clone $stub; + $stub->type = $map[$stub->type]; + $stub->class = isset($map[$stub->class]) ? $map[$stub->class] : $stub->class; + + return $stub; + } } From a7c9d1aca075f593dba853a01b1de607f1626a4c Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Wed, 5 Jul 2017 16:28:05 +0300 Subject: [PATCH 0362/1099] updated CHANGELOG for 3.3.4 --- CHANGELOG-3.3.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CHANGELOG-3.3.md b/CHANGELOG-3.3.md index 1817eff60299e..b6113a82ad279 100644 --- a/CHANGELOG-3.3.md +++ b/CHANGELOG-3.3.md @@ -7,6 +7,14 @@ in 3.3 minor versions. To get the diff for a specific change, go to https://github.com/symfony/symfony/commit/XXX where XXX is the change hash To get the diff between two versions, go to https://github.com/symfony/symfony/compare/v3.3.0...v3.3.1 +* 3.3.4 (2017-07-05) + + * bug #23413 [VarDumper] Reduce size of serialized Data objects (nicolas-grekas) + * bug #23385 [DoctrineBridge] Fix resetting entity managers with case sensitive id (chalasr) + * bug #23390 [Cache] Handle APCu failures gracefully (nicolas-grekas) + * bug #23371 [FrameworkBundle] 3.3: Don't get() private services from debug:router (ogizanagi) + * bug #23378 [FrameworkBundle] Do not remove files from assets dir (1ed) + * 3.3.3 (2017-07-04) * bug #23366 [FrameworkBundle] Don't get() private services from debug:router (chalasr) From e81d5d17d64d4a5885ce2f35c963de2ab7fb02d0 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Wed, 5 Jul 2017 16:28:15 +0300 Subject: [PATCH 0363/1099] updated VERSION for 3.3.4 --- 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 d6ea3e6f04c59..0fc96a0acc71f 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -61,12 +61,12 @@ abstract class Kernel implements KernelInterface, TerminableInterface private $projectDir; - const VERSION = '3.3.4-DEV'; + const VERSION = '3.3.4'; const VERSION_ID = 30304; const MAJOR_VERSION = 3; const MINOR_VERSION = 3; const RELEASE_VERSION = 4; - const EXTRA_VERSION = 'DEV'; + const EXTRA_VERSION = ''; const END_OF_MAINTENANCE = '01/2018'; const END_OF_LIFE = '07/2018'; From 94b6ec309259b32db23e2c3f50fcdd2e49d4a982 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Wed, 5 Jul 2017 16:59:31 +0300 Subject: [PATCH 0364/1099] bumped Symfony version to 3.3.5 --- 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 0fc96a0acc71f..af60ef900a84b 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -61,12 +61,12 @@ abstract class Kernel implements KernelInterface, TerminableInterface private $projectDir; - const VERSION = '3.3.4'; - const VERSION_ID = 30304; + const VERSION = '3.3.5-DEV'; + const VERSION_ID = 30305; const MAJOR_VERSION = 3; const MINOR_VERSION = 3; - const RELEASE_VERSION = 4; - const EXTRA_VERSION = ''; + const RELEASE_VERSION = 5; + const EXTRA_VERSION = 'DEV'; const END_OF_MAINTENANCE = '01/2018'; const END_OF_LIFE = '07/2018'; From a15829d52425d51aa6c36cc44d9e885cb294cceb Mon Sep 17 00:00:00 2001 From: Jordan Samouh Date: Fri, 30 Jun 2017 10:33:54 -0400 Subject: [PATCH 0365/1099] [Component][Serializer][Normalizer] : Deal it with Has Method for the Normalizer/Denormalizer --- .../Normalizer/GetSetMethodNormalizer.php | 8 ++++- .../Normalizer/GetSetMethodNormalizerTest.php | 32 +++++++++++++++++++ 2 files changed, 39 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/Serializer/Normalizer/GetSetMethodNormalizer.php b/src/Symfony/Component/Serializer/Normalizer/GetSetMethodNormalizer.php index 2a15d46d63b10..3d2c0665be60f 100644 --- a/src/Symfony/Component/Serializer/Normalizer/GetSetMethodNormalizer.php +++ b/src/Symfony/Component/Serializer/Normalizer/GetSetMethodNormalizer.php @@ -87,7 +87,8 @@ private function isGetMethod(\ReflectionMethod $method) !$method->isStatic() && ( ((0 === strpos($method->name, 'get') && 3 < $methodLength) || - (0 === strpos($method->name, 'is') && 2 < $methodLength)) && + (0 === strpos($method->name, 'is') && 2 < $methodLength) || + (0 === strpos($method->name, 'has') && 3 < $methodLength)) && 0 === $method->getNumberOfRequiredParameters() ) ; @@ -133,6 +134,11 @@ protected function getAttributeValue($object, $attribute, $format = null, array if (is_callable(array($object, $isser))) { return $object->$isser(); } + + $haser = 'has'.$ucfirsted; + if (is_callable(array($object, $haser))) { + return $object->$haser(); + } } /** diff --git a/src/Symfony/Component/Serializer/Tests/Normalizer/GetSetMethodNormalizerTest.php b/src/Symfony/Component/Serializer/Tests/Normalizer/GetSetMethodNormalizerTest.php index ee0a159f06f8a..6358cd7a908e9 100644 --- a/src/Symfony/Component/Serializer/Tests/Normalizer/GetSetMethodNormalizerTest.php +++ b/src/Symfony/Component/Serializer/Tests/Normalizer/GetSetMethodNormalizerTest.php @@ -497,6 +497,23 @@ public function testPrivateSetter() $this->assertEquals('bar', $obj->getFoo()); } + public function testHasGetterDenormalize() + { + $obj = $this->normalizer->denormalize(array('foo' => true), ObjectWithHasGetterDummy::class); + $this->assertTrue($obj->hasFoo()); + } + + public function testHasGetterNormalize() + { + $obj = new ObjectWithHasGetterDummy(); + $obj->setFoo(true); + + $this->assertEquals( + array('foo' => true), + $this->normalizer->normalize($obj, 'any') + ); + } + public function testMaxDepth() { $classMetadataFactory = new ClassMetadataFactory(new AnnotationLoader(new AnnotationReader())); @@ -807,3 +824,18 @@ public static function setFoo($foo) self::$foo = $foo; } } + +class ObjectWithHasGetterDummy +{ + private $foo; + + public function setFoo($foo) + { + $this->foo = $foo; + } + + public function hasFoo() + { + return $this->foo; + } +} From 052b8c3a04e855bc21323403dc1575c8e4ea0545 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Wed, 5 Jul 2017 22:19:23 +0200 Subject: [PATCH 0366/1099] [DI][Security] Prevent unwanted deprecation notices when using Expression Languages --- .../Component/DependencyInjection/ExpressionLanguage.php | 6 ++++-- .../Security/Core/Authorization/ExpressionLanguage.php | 6 ++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/Symfony/Component/DependencyInjection/ExpressionLanguage.php b/src/Symfony/Component/DependencyInjection/ExpressionLanguage.php index acc97bcf4973d..d80985fa670e5 100644 --- a/src/Symfony/Component/DependencyInjection/ExpressionLanguage.php +++ b/src/Symfony/Component/DependencyInjection/ExpressionLanguage.php @@ -12,7 +12,6 @@ namespace Symfony\Component\DependencyInjection; use Symfony\Component\ExpressionLanguage\ExpressionLanguage as BaseExpressionLanguage; -use Symfony\Component\ExpressionLanguage\ParserCache\ParserCacheInterface; /** * Adds some function to the default ExpressionLanguage. @@ -23,7 +22,10 @@ */ class ExpressionLanguage extends BaseExpressionLanguage { - public function __construct(ParserCacheInterface $cache = null, array $providers = array()) + /** + * {@inheritdoc} + */ + public function __construct($cache = null, array $providers = array()) { // prepend the default provider to let users override it easily array_unshift($providers, new ExpressionLanguageProvider()); diff --git a/src/Symfony/Component/Security/Core/Authorization/ExpressionLanguage.php b/src/Symfony/Component/Security/Core/Authorization/ExpressionLanguage.php index c2925af87121a..d4c8f33e06491 100644 --- a/src/Symfony/Component/Security/Core/Authorization/ExpressionLanguage.php +++ b/src/Symfony/Component/Security/Core/Authorization/ExpressionLanguage.php @@ -12,7 +12,6 @@ namespace Symfony\Component\Security\Core\Authorization; use Symfony\Component\ExpressionLanguage\ExpressionLanguage as BaseExpressionLanguage; -use Symfony\Component\ExpressionLanguage\ParserCache\ParserCacheInterface; /** * Adds some function to the default ExpressionLanguage. @@ -23,7 +22,10 @@ */ class ExpressionLanguage extends BaseExpressionLanguage { - public function __construct(ParserCacheInterface $cache = null, array $providers = array()) + /** + * {@inheritdoc} + */ + public function __construct($cache = null, array $providers = array()) { // prepend the default provider to let users override it easily array_unshift($providers, new ExpressionLanguageProvider()); From 89ad27d54464bcf3c043c72a0629d3a0e90e30d1 Mon Sep 17 00:00:00 2001 From: Alexander Schranz Date: Thu, 22 Jun 2017 11:09:30 +0200 Subject: [PATCH 0367/1099] Fixed absolute url generation for query strings and hash urls --- .../Twig/Extension/HttpFoundationExtension.php | 13 +++++++++++++ .../Tests/Extension/HttpFoundationExtensionTest.php | 9 +++++++++ 2 files changed, 22 insertions(+) diff --git a/src/Symfony/Bridge/Twig/Extension/HttpFoundationExtension.php b/src/Symfony/Bridge/Twig/Extension/HttpFoundationExtension.php index 69d6d326f4d08..6e1f5753d28ad 100644 --- a/src/Symfony/Bridge/Twig/Extension/HttpFoundationExtension.php +++ b/src/Symfony/Bridge/Twig/Extension/HttpFoundationExtension.php @@ -70,6 +70,13 @@ public function generateAbsoluteUrl($path) $port = ':'.$this->requestContext->getHttpsPort(); } + if ('#' === $path[0]) { + $queryString = $this->requestContext->getQueryString(); + $path = $this->requestContext->getPathInfo().($queryString ? '?'.$queryString : '').$path; + } elseif ('?' === $path[0]) { + $path = $this->requestContext->getPathInfo().$path; + } + if ('/' !== $path[0]) { $path = rtrim($this->requestContext->getBaseUrl(), '/').'/'.$path; } @@ -80,6 +87,12 @@ public function generateAbsoluteUrl($path) return $path; } + if ('#' === $path[0]) { + $path = $request->getRequestUri().$path; + } elseif ('?' === $path[0]) { + $path = $request->getPathInfo().$path; + } + if (!$path || '/' !== $path[0]) { $prefix = $request->getPathInfo(); $last = strlen($prefix) - 1; diff --git a/src/Symfony/Bridge/Twig/Tests/Extension/HttpFoundationExtensionTest.php b/src/Symfony/Bridge/Twig/Tests/Extension/HttpFoundationExtensionTest.php index 339d43d7c6bd1..3d9e9e6abe7da 100644 --- a/src/Symfony/Bridge/Twig/Tests/Extension/HttpFoundationExtensionTest.php +++ b/src/Symfony/Bridge/Twig/Tests/Extension/HttpFoundationExtensionTest.php @@ -41,6 +41,15 @@ public function getGenerateAbsoluteUrlData() array('http://example.com/baz', 'http://example.com/baz', '/'), array('https://example.com/baz', 'https://example.com/baz', '/'), array('//example.com/baz', '//example.com/baz', '/'), + + array('http://localhost/foo/bar?baz', '?baz', '/foo/bar'), + array('http://localhost/foo/bar?baz=1', '?baz=1', '/foo/bar?foo=1'), + array('http://localhost/foo/baz?baz=1', 'baz?baz=1', '/foo/bar?foo=1'), + + array('http://localhost/foo/bar#baz', '#baz', '/foo/bar'), + array('http://localhost/foo/bar?0#baz', '#baz', '/foo/bar?0'), + array('http://localhost/foo/bar?baz=1#baz', '?baz=1#baz', '/foo/bar?foo=1'), + array('http://localhost/foo/baz?baz=1#baz', 'baz?baz=1#baz', '/foo/bar?foo=1'), ); } From 6aa66444bc66992bdc0129cf1bf551a1fc9262a1 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Thu, 6 Jul 2017 09:26:26 +0300 Subject: [PATCH 0368/1099] added missing type hints --- .../Component/DependencyInjection/ExpressionLanguage.php | 3 ++- .../Security/Core/Authorization/ExpressionLanguage.php | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/DependencyInjection/ExpressionLanguage.php b/src/Symfony/Component/DependencyInjection/ExpressionLanguage.php index d80985fa670e5..a0f107c084e2a 100644 --- a/src/Symfony/Component/DependencyInjection/ExpressionLanguage.php +++ b/src/Symfony/Component/DependencyInjection/ExpressionLanguage.php @@ -11,6 +11,7 @@ namespace Symfony\Component\DependencyInjection; +use Psr\Cache\CacheItemPoolInterface; use Symfony\Component\ExpressionLanguage\ExpressionLanguage as BaseExpressionLanguage; /** @@ -25,7 +26,7 @@ class ExpressionLanguage extends BaseExpressionLanguage /** * {@inheritdoc} */ - public function __construct($cache = null, array $providers = array()) + public function __construct(CacheItemPoolInterface $cache = null, array $providers = array()) { // prepend the default provider to let users override it easily array_unshift($providers, new ExpressionLanguageProvider()); diff --git a/src/Symfony/Component/Security/Core/Authorization/ExpressionLanguage.php b/src/Symfony/Component/Security/Core/Authorization/ExpressionLanguage.php index d4c8f33e06491..0291acbfb6ed8 100644 --- a/src/Symfony/Component/Security/Core/Authorization/ExpressionLanguage.php +++ b/src/Symfony/Component/Security/Core/Authorization/ExpressionLanguage.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Security\Core\Authorization; +use Psr\Cache\CacheItemPoolInterface; use Symfony\Component\ExpressionLanguage\ExpressionLanguage as BaseExpressionLanguage; /** @@ -25,7 +26,7 @@ class ExpressionLanguage extends BaseExpressionLanguage /** * {@inheritdoc} */ - public function __construct($cache = null, array $providers = array()) + public function __construct(CacheItemPoolInterface $cache = null, array $providers = array()) { // prepend the default provider to let users override it easily array_unshift($providers, new ExpressionLanguageProvider()); From bbd0c7f69f49aea44ce0c5aa63cc3cd1a6efc284 Mon Sep 17 00:00:00 2001 From: Dany Maillard Date: Thu, 6 Jul 2017 09:01:40 +0200 Subject: [PATCH 0369/1099] Fix deprecated message --- UPGRADE-4.0.md | 2 +- src/Symfony/Component/Ldap/Adapter/RenameEntryInterface.php | 4 ++-- src/Symfony/Component/Ldap/CHANGELOG.md | 5 +++++ 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/UPGRADE-4.0.md b/UPGRADE-4.0.md index b06145202e7cd..3ce678b866b4b 100644 --- a/UPGRADE-4.0.md +++ b/UPGRADE-4.0.md @@ -402,7 +402,7 @@ HttpKernel Ldap ---- - * The `RenameEntryInterface` has been deprecated, and merged with `EntryManagerInterface` + * The `RenameEntryInterface` has been removed, and merged with `EntryManagerInterface` Process ------- diff --git a/src/Symfony/Component/Ldap/Adapter/RenameEntryInterface.php b/src/Symfony/Component/Ldap/Adapter/RenameEntryInterface.php index 8bc70bda9637a..c15cb16e77e80 100644 --- a/src/Symfony/Component/Ldap/Adapter/RenameEntryInterface.php +++ b/src/Symfony/Component/Ldap/Adapter/RenameEntryInterface.php @@ -5,9 +5,9 @@ use Symfony\Component\Ldap\Entry; /** - * @deprecated This interface will be deprecated in 4.0, and merged with `EntryManagerInterface` - * * @author Kevin Schuurmans + * + * @deprecated since version 3.3, will be merged with {@link EntryManagerInterface} in 4.0. */ interface RenameEntryInterface { diff --git a/src/Symfony/Component/Ldap/CHANGELOG.md b/src/Symfony/Component/Ldap/CHANGELOG.md index 61af4adf151a2..5d90f278f567a 100644 --- a/src/Symfony/Component/Ldap/CHANGELOG.md +++ b/src/Symfony/Component/Ldap/CHANGELOG.md @@ -1,6 +1,11 @@ CHANGELOG ========= +3.3.0 +----- + +* The `RenameEntryInterface` inferface is deprecated, and will be merged with `EntryManagerInterface` in 4.0. + 3.1.0 ----- From 680da44789aa1612aa84f7b962a32b3461799b3b Mon Sep 17 00:00:00 2001 From: Nikolay Labinskiy Date: Fri, 7 Apr 2017 14:39:54 +0300 Subject: [PATCH 0370/1099] [BrowserKit] Emulate back/forward browser navigation --- src/Symfony/Component/BrowserKit/CHANGELOG.md | 3 +++ src/Symfony/Component/BrowserKit/Client.php | 15 +++++++++++++-- .../Component/BrowserKit/Tests/ClientTest.php | 19 +++++++++++++++++++ 3 files changed, 35 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/BrowserKit/CHANGELOG.md b/src/Symfony/Component/BrowserKit/CHANGELOG.md index 036595c9b458c..3ddc3d7c5238f 100644 --- a/src/Symfony/Component/BrowserKit/CHANGELOG.md +++ b/src/Symfony/Component/BrowserKit/CHANGELOG.md @@ -7,6 +7,9 @@ CHANGELOG * [BC BREAK] The request method is dropped from POST to GET when the response status code is 301. + * [BC BREAK] Client will skip redirects during history navigation + (back and forward calls) according to W3C Browsers recommendation + 3.2.0 ----- diff --git a/src/Symfony/Component/BrowserKit/Client.php b/src/Symfony/Component/BrowserKit/Client.php index 50bcca301a3e2..5ceabb569a254 100644 --- a/src/Symfony/Component/BrowserKit/Client.php +++ b/src/Symfony/Component/BrowserKit/Client.php @@ -42,6 +42,7 @@ abstract class Client private $maxRedirects = -1; private $redirectCount = 0; + private $redirects = array(); private $isMainRequest = true; /** @@ -328,6 +329,8 @@ public function request($method, $uri, array $parameters = array(), array $files } if ($this->followRedirects && $this->redirect) { + $this->redirects[serialize($this->history->current())] = true; + return $this->crawler = $this->followRedirect(); } @@ -430,7 +433,11 @@ protected function createCrawlerFromContent($uri, $content, $type) */ public function back() { - return $this->requestFromRequest($this->history->back(), false); + do { + $request = $this->history->back(); + } while (array_key_exists(serialize($request), $this->redirects)); + + return $this->requestFromRequest($request, false); } /** @@ -440,7 +447,11 @@ public function back() */ public function forward() { - return $this->requestFromRequest($this->history->forward(), false); + do { + $request = $this->history->forward(); + } while (array_key_exists(serialize($request), $this->redirects)); + + return $this->requestFromRequest($request, false); } /** diff --git a/src/Symfony/Component/BrowserKit/Tests/ClientTest.php b/src/Symfony/Component/BrowserKit/Tests/ClientTest.php index 5bd4dad7b6ecb..9c7267e83b721 100644 --- a/src/Symfony/Component/BrowserKit/Tests/ClientTest.php +++ b/src/Symfony/Component/BrowserKit/Tests/ClientTest.php @@ -573,6 +573,25 @@ public function testForward() $this->assertEquals($content, $client->getRequest()->getContent(), '->forward() keeps content'); } + public function testBackAndFrowardWithRedirects() + { + $client = new TestClient(); + + $client->request('GET', 'http://www.example.com/foo'); + $client->setNextResponse(new Response('', 301, array('Location' => 'http://www.example.com/redirected'))); + $client->request('GET', 'http://www.example.com/bar'); + + $this->assertEquals('http://www.example.com/redirected', $client->getRequest()->getUri(), 'client followed redirect'); + + $client->back(); + + $this->assertEquals('http://www.example.com/foo', $client->getRequest()->getUri(), '->back() goes back in the history skipping redirects'); + + $client->forward(); + + $this->assertEquals('http://www.example.com/redirected', $client->getRequest()->getUri(), '->forward() goes forward in the history skipping redirects'); + } + public function testReload() { $client = new TestClient(); From 43212b9a90b9af1ae14c6851dd98b48038049934 Mon Sep 17 00:00:00 2001 From: Miroslav Sustek Date: Fri, 14 Apr 2017 20:04:38 +0200 Subject: [PATCH 0371/1099] [DX] [TwigBundle] Enhance the new exception page design --- .../Resources/views/Exception/trace.html.twig | 41 +++++++-------- .../views/Exception/traces.html.twig | 50 +++++++++---------- .../Resources/views/exception.css.twig | 14 ++++-- 3 files changed, 53 insertions(+), 52 deletions(-) diff --git a/src/Symfony/Bundle/TwigBundle/Resources/views/Exception/trace.html.twig b/src/Symfony/Bundle/TwigBundle/Resources/views/Exception/trace.html.twig index a6af5d0532242..1d8125a38f84b 100644 --- a/src/Symfony/Bundle/TwigBundle/Resources/views/Exception/trace.html.twig +++ b/src/Symfony/Bundle/TwigBundle/Resources/views/Exception/trace.html.twig @@ -1,28 +1,29 @@ -{% if trace.file|default(false) %} - {{ include('@Twig/images/icon-minus-square.svg') }} - {{ include('@Twig/images/icon-plus-square.svg') }} -{% endif %} - -{% if trace.function %} - {{ trace.class|abbr_class }}{% if trace.type is not empty %}{{ trace.type }}{% endif %}{{ trace.function }}({{ trace.args|format_args }}) -{% endif %} +
+ {% if trace.file|default(false) %} + {{ include('@Twig/images/icon-minus-square.svg') }} + {{ include('@Twig/images/icon-plus-square.svg') }} + {% endif %} -{% if trace.file|default(false) %} - {% set line_number = trace.line|default(1) %} - {% set file_link = trace.file|file_link(line_number) %} - {% set file_path = trace.file|format_file(line_number)|striptags|replace({ (' at line ' ~ line_number): '' }) %} - {% set file_path_parts = file_path|split(constant('DIRECTORY_SEPARATOR')) %} + {% if trace.function %} + {{ trace.class|abbr_class }}{% if trace.type is not empty %}{{ trace.type }}{% endif %}{{ trace.function }}({{ trace.args|format_args }}) + {% endif %} - - in - {{ file_path_parts[:-1]|join(constant('DIRECTORY_SEPARATOR')) }}{{ constant('DIRECTORY_SEPARATOR') }}{{ file_path_parts|last }} - (line {{ line_number }}) - -{% endif %} + {% if trace.file|default(false) %} + {% set line_number = trace.line|default(1) %} + {% set file_link = trace.file|file_link(line_number) %} + {% set file_path = trace.file|format_file(line_number)|striptags|replace({ (' at line ' ~ line_number): '' }) %} + {% set file_path_parts = file_path|split(constant('DIRECTORY_SEPARATOR')) %} + + in + {{ file_path_parts[:-1]|join(constant('DIRECTORY_SEPARATOR')) }}{{ constant('DIRECTORY_SEPARATOR') }}{{ file_path_parts|last }} + (line {{ line_number }}) + + {% endif %} +
{% if trace.file|default(false) %}
- {{ trace.file|file_excerpt(trace.line)|replace({ + {{ trace.file|file_excerpt(trace.line, 5)|replace({ '#DD0000': '#183691', '#007700': '#a71d5d', '#0000BB': '#222222', diff --git a/src/Symfony/Bundle/TwigBundle/Resources/views/Exception/traces.html.twig b/src/Symfony/Bundle/TwigBundle/Resources/views/Exception/traces.html.twig index 948ee86fa6cc5..2bf3e7613aad4 100644 --- a/src/Symfony/Bundle/TwigBundle/Resources/views/Exception/traces.html.twig +++ b/src/Symfony/Bundle/TwigBundle/Resources/views/Exception/traces.html.twig @@ -1,37 +1,33 @@
- - - - - - + {% if exception.message is not empty and index > 1 %} +

{{ exception.message }}

+ {% endif %} + + - +
{% set _is_first_user_code = true %} {% for i, trace in exception.trace %} {% set _display_code_snippet = _is_first_user_code and ('/vendor/' not in trace.file) and ('/var/cache/' not in trace.file) and (trace.file is not empty) %} {% if _display_code_snippet %}{% set _is_first_user_code = false %}{% endif %} -
- - +
+ {{ include('@Twig/Exception/trace.html.twig', { prefix: index, i: i, trace: trace, _display_code_snippet: _display_code_snippet }, with_context = false) }} +
{% endfor %} - -
-

- - {{ exception.class|split('\\')|slice(0, -1)|join('\\') }} - {{- exception.class|split('\\')|length > 1 ? '\\' }} - - {{ exception.class|split('\\')|last }} +
+
+ +

+ + {{ exception.class|split('\\')|slice(0, -1)|join('\\') }} + {{- exception.class|split('\\')|length > 1 ? '\\' }} + + {{ exception.class|split('\\')|last }} - {{ include('@Twig/images/icon-minus-square-o.svg') }} - {{ include('@Twig/images/icon-plus-square-o.svg') }} -

+ {{ include('@Twig/images/icon-minus-square-o.svg') }} + {{ include('@Twig/images/icon-plus-square-o.svg') }} +

- {% if exception.message is not empty and index > 1 %} -

{{ exception.message }}

- {% endif %} -
- {{ include('@Twig/Exception/trace.html.twig', { prefix: index, i: i, trace: trace }, with_context = false) }} -
+
+
diff --git a/src/Symfony/Bundle/TwigBundle/Resources/views/exception.css.twig b/src/Symfony/Bundle/TwigBundle/Resources/views/exception.css.twig index cb455274eecf9..ba3dd9412e266 100644 --- a/src/Symfony/Bundle/TwigBundle/Resources/views/exception.css.twig +++ b/src/Symfony/Bundle/TwigBundle/Resources/views/exception.css.twig @@ -89,30 +89,34 @@ header .container { display: flex; justify-content: space-between; } .exception-illustration { flex-basis: 111px; flex-shrink: 0; height: 66px; margin-left: 15px; opacity: .7; } .trace + .trace { margin-top: 30px; } +.trace-head { background-color: #e0e0e0; padding: 10px; } .trace-head .trace-class { color: #222; font-size: 18px; font-weight: bold; line-height: 1.3; margin: 0; position: relative; } .trace-head .trace-namespace { color: #999; display: block; font-size: 13px; } .trace-head .icon { position: absolute; right: 0; top: 0; } .trace-head .icon svg { height: 24px; width: 24px; } +.trace-details { background: #FFF; border: 1px solid #E0E0E0; box-shadow: 0px 0px 1px rgba(128, 128, 128, .2); margin: 1em 0; } + .trace-message { font-size: 14px; font-weight: normal; margin: .5em 0 0; } .trace-details { table-layout: fixed; } -.trace-line { position: relative; padding-left: 36px; } -.trace-line.sf-toggle:hover { background: #F5F5F5; } +.trace-line { position: relative; padding-top: 8px; padding-bottom: 8px; } +.trace-line:hover { background: #F5F5F5; } .trace-line a { color: #222; } .trace-line .icon { opacity: .4; position: absolute; left: 10px; top: 11px; } .trace-line .icon svg { height: 16px; width: 16px; } +.trace-line-header { padding-left: 36px; } -.trace-file-path, .trace-file-path a { margin-top: 3px; color: #999; color: #795da3; color: #B0413E; color: #222; font-size: 13px; } +.trace-file-path, .trace-file-path a { color: #999; color: #795da3; color: #B0413E; color: #222; font-size: 13px; } .trace-class { color: #B0413E; } .trace-type { padding: 0 2px; } .trace-method { color: #B0413E; color: #222; font-weight: bold; color: #B0413E; } .trace-arguments { color: #222; color: #999; font-weight: normal; color: #795da3; color: #777; padding-left: 2px; } -.trace-code { background: #FFF; font-size: 12px; margin: 10px 0 2px; padding: 10px; overflow-x: auto; } +.trace-code { background: #FFF; font-size: 12px; margin: 10px 10px 2px 10px; padding: 10px; overflow-x: auto; white-space: nowrap; } .trace-code ol { margin: 0; float: left; } .trace-code li { color: #969896; margin: 0; padding-left: 10px; float: left; width: 100%; } .trace-code li + li { margin-top: 5px; } -.trace-code li.selected { background: #F8EEC7; padding: 3px 0 3px 10px; margin-top: 2px; } +.trace-code li.selected { background: #F7E5A1; margin-top: 2px; } .trace-code li code { color: #222; white-space: nowrap; } .trace-as-text .stacktrace { line-height: 1.8; margin: 0 0 15px; white-space: pre-wrap; } From ec3cc84656313179fd16e162174aa99ee3f28a8b Mon Sep 17 00:00:00 2001 From: Maxime Veber Date: Fri, 31 Mar 2017 11:20:07 +0200 Subject: [PATCH 0372/1099] Fix phpdoc for serializer normalizers exceptions The normalizers throw exceptions. They need to be documented for DX in the normalizer/denormalizer interfaces. [Serializer] fit Symfony phpdoc standard It also adds meaning of each exception throw. Fix grammary in phpdoc --- .../Normalizer/AbstractObjectNormalizer.php | 3 --- .../Serializer/Normalizer/ArrayDenormalizer.php | 2 -- .../Serializer/Normalizer/DataUriNormalizer.php | 3 --- .../Normalizer/DenormalizerInterface.php | 14 ++++++++++++++ .../Serializer/Normalizer/NormalizerInterface.php | 9 +++++++++ 5 files changed, 23 insertions(+), 8 deletions(-) diff --git a/src/Symfony/Component/Serializer/Normalizer/AbstractObjectNormalizer.php b/src/Symfony/Component/Serializer/Normalizer/AbstractObjectNormalizer.php index 2b3433c567d4a..188b79ade85ff 100644 --- a/src/Symfony/Component/Serializer/Normalizer/AbstractObjectNormalizer.php +++ b/src/Symfony/Component/Serializer/Normalizer/AbstractObjectNormalizer.php @@ -13,7 +13,6 @@ use Symfony\Component\PropertyAccess\Exception\InvalidArgumentException; use Symfony\Component\Serializer\Encoder\JsonEncoder; -use Symfony\Component\Serializer\Exception\CircularReferenceException; use Symfony\Component\Serializer\Exception\LogicException; use Symfony\Component\Serializer\Exception\UnexpectedValueException; use Symfony\Component\PropertyInfo\PropertyTypeExtractorInterface; @@ -52,8 +51,6 @@ public function supportsNormalization($data, $format = null) /** * {@inheritdoc} - * - * @throws CircularReferenceException */ public function normalize($object, $format = null, array $context = array()) { diff --git a/src/Symfony/Component/Serializer/Normalizer/ArrayDenormalizer.php b/src/Symfony/Component/Serializer/Normalizer/ArrayDenormalizer.php index 7d3d87c510c55..9217d51a95908 100644 --- a/src/Symfony/Component/Serializer/Normalizer/ArrayDenormalizer.php +++ b/src/Symfony/Component/Serializer/Normalizer/ArrayDenormalizer.php @@ -31,8 +31,6 @@ class ArrayDenormalizer implements DenormalizerInterface, SerializerAwareInterfa /** * {@inheritdoc} - * - * @throws UnexpectedValueException */ public function denormalize($data, $class, $format = null, array $context = array()) { diff --git a/src/Symfony/Component/Serializer/Normalizer/DataUriNormalizer.php b/src/Symfony/Component/Serializer/Normalizer/DataUriNormalizer.php index 988a491b7c800..9e5af130d03b7 100644 --- a/src/Symfony/Component/Serializer/Normalizer/DataUriNormalizer.php +++ b/src/Symfony/Component/Serializer/Normalizer/DataUriNormalizer.php @@ -79,9 +79,6 @@ public function supportsNormalization($data, $format = null) * Regex adapted from Brian Grinstead code. * * @see https://gist.github.com/bgrins/6194623 - * - * @throws InvalidArgumentException - * @throws UnexpectedValueException */ public function denormalize($data, $class, $format = null, array $context = array()) { diff --git a/src/Symfony/Component/Serializer/Normalizer/DenormalizerInterface.php b/src/Symfony/Component/Serializer/Normalizer/DenormalizerInterface.php index 23df4829a8cbd..2b3b206287373 100644 --- a/src/Symfony/Component/Serializer/Normalizer/DenormalizerInterface.php +++ b/src/Symfony/Component/Serializer/Normalizer/DenormalizerInterface.php @@ -11,6 +11,13 @@ namespace Symfony\Component\Serializer\Normalizer; +use Symfony\Component\Serializer\Exception\BadMethodCallException; +use Symfony\Component\Serializer\Exception\ExtraAttributesException; +use Symfony\Component\Serializer\Exception\InvalidArgumentException; +use Symfony\Component\Serializer\Exception\LogicException; +use Symfony\Component\Serializer\Exception\RuntimeException; +use Symfony\Component\Serializer\Exception\UnexpectedValueException; + /** * Defines the interface of denormalizers. * @@ -27,6 +34,13 @@ interface DenormalizerInterface * @param array $context options available to the denormalizer * * @return object + * + * @throws BadMethodCallException Occurs when the normalizer is not called in an expected context + * @throws InvalidArgumentException Occurs when the arguments are not coherent or not supported + * @throws UnexpectedValueException Occurs when the item cannot be hydrated with the given data + * @throws ExtraAttributesException Occurs when the item doesn't have attribute to receive given data + * @throws LogicException Occurs when the normalizer is not supposed to denormalize + * @throws RuntimeException Occurs if the class cannot be instantiated */ public function denormalize($data, $class, $format = null, array $context = array()); diff --git a/src/Symfony/Component/Serializer/Normalizer/NormalizerInterface.php b/src/Symfony/Component/Serializer/Normalizer/NormalizerInterface.php index f7007840da1f4..2779053f741e9 100644 --- a/src/Symfony/Component/Serializer/Normalizer/NormalizerInterface.php +++ b/src/Symfony/Component/Serializer/Normalizer/NormalizerInterface.php @@ -11,6 +11,10 @@ namespace Symfony\Component\Serializer\Normalizer; +use Symfony\Component\Serializer\Exception\CircularReferenceException; +use Symfony\Component\Serializer\Exception\InvalidArgumentException; +use Symfony\Component\Serializer\Exception\LogicException; + /** * Defines the interface of normalizers. * @@ -26,6 +30,11 @@ interface NormalizerInterface * @param array $context Context options for the normalizer * * @return array|scalar + * + * @throws InvalidArgumentException Occurs when the object given is not an attempted type for the normalizer + * @throws CircularReferenceException Occurs when the normalizer detects a circular reference when no circular + * reference handler can fix it + * @throws LogicException Occurs when the normalizer is not called in an expected context */ public function normalize($object, $format = null, array $context = array()); From fd01d7a1cfdb0896247488c966900426853bb791 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Thu, 6 Jul 2017 10:45:45 +0300 Subject: [PATCH 0373/1099] fixed CHANGELOG --- src/Symfony/Component/BrowserKit/CHANGELOG.md | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Component/BrowserKit/CHANGELOG.md b/src/Symfony/Component/BrowserKit/CHANGELOG.md index 3ddc3d7c5238f..47c847d0617e5 100644 --- a/src/Symfony/Component/BrowserKit/CHANGELOG.md +++ b/src/Symfony/Component/BrowserKit/CHANGELOG.md @@ -1,15 +1,18 @@ CHANGELOG ========= +3.4.0 +----- + + * [BC BREAK] Client will skip redirects during history navigation + (back and forward calls) according to W3C Browsers recommendation + 3.3.0 ----- * [BC BREAK] The request method is dropped from POST to GET when the response status code is 301. - * [BC BREAK] Client will skip redirects during history navigation - (back and forward calls) according to W3C Browsers recommendation - 3.2.0 ----- From 032e654acbe13e256d8ce6454200b8e5289c0bde Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Thu, 6 Jul 2017 09:10:09 +0200 Subject: [PATCH 0374/1099] require the XML PHP extension --- composer.json | 1 + src/Symfony/Bundle/DebugBundle/composer.json | 1 + src/Symfony/Bundle/SecurityBundle/composer.json | 1 + 3 files changed, 3 insertions(+) diff --git a/composer.json b/composer.json index 1770bc4f305af..a7f3bbf9078d9 100644 --- a/composer.json +++ b/composer.json @@ -17,6 +17,7 @@ ], "require": { "php": ">=5.3.9", + "ext-xml": "*", "doctrine/common": "~2.4", "paragonie/random_compat": "~1.0", "symfony/polyfill-apcu": "~1.1", diff --git a/src/Symfony/Bundle/DebugBundle/composer.json b/src/Symfony/Bundle/DebugBundle/composer.json index d4cba7fc2410b..3fde4a67247eb 100644 --- a/src/Symfony/Bundle/DebugBundle/composer.json +++ b/src/Symfony/Bundle/DebugBundle/composer.json @@ -17,6 +17,7 @@ ], "require": { "php": ">=5.3.9", + "ext-xml": "*", "symfony/http-kernel": "~2.6", "symfony/twig-bridge": "~2.6", "symfony/var-dumper": "~2.6" diff --git a/src/Symfony/Bundle/SecurityBundle/composer.json b/src/Symfony/Bundle/SecurityBundle/composer.json index 3da10d429d4bf..6d6073f7f0bc3 100644 --- a/src/Symfony/Bundle/SecurityBundle/composer.json +++ b/src/Symfony/Bundle/SecurityBundle/composer.json @@ -17,6 +17,7 @@ ], "require": { "php": ">=5.3.9", + "ext-xml": "*", "symfony/security": "~2.7", "symfony/security-acl": "~2.7", "symfony/http-kernel": "~2.7" From 9ab5263d712881f8aa24920631685d14acd3a19b Mon Sep 17 00:00:00 2001 From: Arjan Keeman Date: Wed, 5 Apr 2017 09:40:57 +0200 Subject: [PATCH 0375/1099] add minimum and maximum amount of pixels to Image validator --- src/Symfony/Component/Validator/CHANGELOG.md | 1 + .../Component/Validator/Constraints/Image.php | 8 +++ .../Validator/Constraints/ImageValidator.php | 35 +++++++++++ .../Tests/Constraints/ImageValidatorTest.php | 60 +++++++++++++++++++ 4 files changed, 104 insertions(+) diff --git a/src/Symfony/Component/Validator/CHANGELOG.md b/src/Symfony/Component/Validator/CHANGELOG.md index 9d2f78b942ce9..2c767cd2ca86a 100644 --- a/src/Symfony/Component/Validator/CHANGELOG.md +++ b/src/Symfony/Component/Validator/CHANGELOG.md @@ -8,6 +8,7 @@ CHANGELOG deprecated and will throw an exception in Symfony 4.0 * setting the `checkDNS` option of the `Url` constraint to `true` is deprecated in favor of the `Url::CHECK_DNS_TYPE_*` constants values and will throw an exception in Symfony 4.0 + * added min/max amount of pixels check to `Image` constraint via `minPixels` and `maxPixels` 3.3.0 ----- diff --git a/src/Symfony/Component/Validator/Constraints/Image.php b/src/Symfony/Component/Validator/Constraints/Image.php index a3957f2379567..c3c2c7a237a82 100644 --- a/src/Symfony/Component/Validator/Constraints/Image.php +++ b/src/Symfony/Component/Validator/Constraints/Image.php @@ -25,6 +25,8 @@ class Image extends File const TOO_NARROW_ERROR = '9afbd561-4f90-4a27-be62-1780fc43604a'; const TOO_HIGH_ERROR = '7efae81c-4877-47ba-aa65-d01ccb0d4645'; const TOO_LOW_ERROR = 'aef0cb6a-c07f-4894-bc08-1781420d7b4c'; + const TOO_FEW_PIXEL_ERROR = '1b06b97d-ae48-474e-978f-038a74854c43'; + const TOO_MANY_PIXEL_ERROR = 'ee0804e8-44db-4eac-9775-be91aaf72ce1'; const RATIO_TOO_BIG_ERROR = '70cafca6-168f-41c9-8c8c-4e47a52be643'; const RATIO_TOO_SMALL_ERROR = '59b8c6ef-bcf2-4ceb-afff-4642ed92f12e'; const SQUARE_NOT_ALLOWED_ERROR = '5d41425b-facb-47f7-a55a-de9fbe45cb46'; @@ -45,6 +47,8 @@ class Image extends File self::TOO_NARROW_ERROR => 'TOO_NARROW_ERROR', self::TOO_HIGH_ERROR => 'TOO_HIGH_ERROR', self::TOO_LOW_ERROR => 'TOO_LOW_ERROR', + self::TOO_FEW_PIXEL_ERROR => 'TOO_FEW_PIXEL_ERROR', + self::TOO_MANY_PIXEL_ERROR => 'TOO_MANY_PIXEL_ERROR', self::RATIO_TOO_BIG_ERROR => 'RATIO_TOO_BIG_ERROR', self::RATIO_TOO_SMALL_ERROR => 'RATIO_TOO_SMALL_ERROR', self::SQUARE_NOT_ALLOWED_ERROR => 'SQUARE_NOT_ALLOWED_ERROR', @@ -60,6 +64,8 @@ class Image extends File public $minHeight; public $maxRatio; public $minRatio; + public $minPixels; + public $maxPixels; public $allowSquare = true; public $allowLandscape = true; public $allowPortrait = true; @@ -72,6 +78,8 @@ class Image extends File public $minWidthMessage = 'The image width is too small ({{ width }}px). Minimum width expected is {{ min_width }}px.'; public $maxHeightMessage = 'The image height is too big ({{ height }}px). Allowed maximum height is {{ max_height }}px.'; public $minHeightMessage = 'The image height is too small ({{ height }}px). Minimum height expected is {{ min_height }}px.'; + public $minPixelsMessage = 'The image has too few pixels ({{ pixels }} pixels). Minimum amount expected is {{ min_pixels }} pixels.'; + public $maxPixelsMessage = 'The image has too many pixels ({{ pixels }} pixels). Maximum amount expected is {{ max_pixels }} pixels.'; public $maxRatioMessage = 'The image ratio is too big ({{ ratio }}). Allowed maximum ratio is {{ max_ratio }}.'; public $minRatioMessage = 'The image ratio is too small ({{ ratio }}). Minimum ratio expected is {{ min_ratio }}.'; public $allowSquareMessage = 'The image is square ({{ width }}x{{ height }}px). Square images are not allowed.'; diff --git a/src/Symfony/Component/Validator/Constraints/ImageValidator.php b/src/Symfony/Component/Validator/Constraints/ImageValidator.php index 0ed0d41782227..da8ec19b715e8 100644 --- a/src/Symfony/Component/Validator/Constraints/ImageValidator.php +++ b/src/Symfony/Component/Validator/Constraints/ImageValidator.php @@ -46,6 +46,7 @@ public function validate($value, Constraint $constraint) if (null === $constraint->minWidth && null === $constraint->maxWidth && null === $constraint->minHeight && null === $constraint->maxHeight + && null === $constraint->minPixels && null === $constraint->maxPixels && null === $constraint->minRatio && null === $constraint->maxRatio && $constraint->allowSquare && $constraint->allowLandscape && $constraint->allowPortrait && !$constraint->detectCorrupted) { @@ -127,6 +128,40 @@ public function validate($value, Constraint $constraint) } } + $pixels = $width * $height; + + if (null !== $constraint->minPixels) { + if (!ctype_digit((string) $constraint->minPixels)) { + throw new ConstraintDefinitionException(sprintf('"%s" is not a valid minimum amount of pixels', $constraint->minPixels)); + } + + if ($pixels < $constraint->minPixels) { + $this->context->buildViolation($constraint->minPixelsMessage) + ->setParameter('{{ pixels }}', $pixels) + ->setParameter('{{ min_pixels }}', $constraint->minPixels) + ->setParameter('{{ height }}', $height) + ->setParameter('{{ width }}', $width) + ->setCode(Image::TOO_FEW_PIXEL_ERROR) + ->addViolation(); + } + } + + if (null !== $constraint->maxPixels) { + if (!ctype_digit((string) $constraint->maxPixels)) { + throw new ConstraintDefinitionException(sprintf('"%s" is not a valid maximum amount of pixels', $constraint->maxPixels)); + } + + if ($pixels > $constraint->maxPixels) { + $this->context->buildViolation($constraint->maxPixelsMessage) + ->setParameter('{{ pixels }}', $pixels) + ->setParameter('{{ max_pixels }}', $constraint->maxPixels) + ->setParameter('{{ height }}', $height) + ->setParameter('{{ width }}', $width) + ->setCode(Image::TOO_MANY_PIXEL_ERROR) + ->addViolation(); + } + } + $ratio = round($width / $height, 2); if (null !== $constraint->minRatio) { diff --git a/src/Symfony/Component/Validator/Tests/Constraints/ImageValidatorTest.php b/src/Symfony/Component/Validator/Tests/Constraints/ImageValidatorTest.php index 93b1d05bab7b2..05ab7e2f88433 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/ImageValidatorTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/ImageValidatorTest.php @@ -164,6 +164,42 @@ public function testHeightTooBig() ->assertRaised(); } + public function testPixelsTooFew() + { + $constraint = new Image(array( + 'minPixels' => 5, + 'minPixelsMessage' => 'myMessage', + )); + + $this->validator->validate($this->image, $constraint); + + $this->buildViolation('myMessage') + ->setParameter('{{ pixels }}', '4') + ->setParameter('{{ min_pixels }}', '5') + ->setParameter('{{ height }}', '2') + ->setParameter('{{ width }}', '2') + ->setCode(Image::TOO_FEW_PIXEL_ERROR) + ->assertRaised(); + } + + public function testPixelsTooMany() + { + $constraint = new Image(array( + 'maxPixels' => 3, + 'maxPixelsMessage' => 'myMessage', + )); + + $this->validator->validate($this->image, $constraint); + + $this->buildViolation('myMessage') + ->setParameter('{{ pixels }}', '4') + ->setParameter('{{ max_pixels }}', '3') + ->setParameter('{{ height }}', '2') + ->setParameter('{{ width }}', '2') + ->setCode(Image::TOO_MANY_PIXEL_ERROR) + ->assertRaised(); + } + /** * @expectedException \Symfony\Component\Validator\Exception\ConstraintDefinitionException */ @@ -212,6 +248,30 @@ public function testInvalidMaxHeight() $this->validator->validate($this->image, $constraint); } + /** + * @expectedException \Symfony\Component\Validator\Exception\ConstraintDefinitionException + */ + public function testInvalidMinPixels() + { + $constraint = new Image(array( + 'minPixels' => '1abc', + )); + + $this->validator->validate($this->image, $constraint); + } + + /** + * @expectedException \Symfony\Component\Validator\Exception\ConstraintDefinitionException + */ + public function testInvalidMaxPixels() + { + $constraint = new Image(array( + 'maxPixels' => '1abc', + )); + + $this->validator->validate($this->image, $constraint); + } + public function testRatioTooSmall() { $constraint = new Image(array( From 73187d00034678158a3ccbd7015cc1509a2ab7fc Mon Sep 17 00:00:00 2001 From: Yanick Witschi Date: Thu, 6 Jul 2017 10:48:01 +0200 Subject: [PATCH 0376/1099] Preserve HttpOnly value when deserializing a header The specification states that the cookie should be considered http only if and only if the flag is present. See https://www.owasp.org/index.php/HttpOnly --- src/Symfony/Component/HttpFoundation/Cookie.php | 2 +- .../Component/HttpFoundation/Tests/CookieTest.php | 11 ++++++++++- .../HttpFoundation/Tests/ResponseHeaderBagTest.php | 6 +++--- 3 files changed, 14 insertions(+), 5 deletions(-) diff --git a/src/Symfony/Component/HttpFoundation/Cookie.php b/src/Symfony/Component/HttpFoundation/Cookie.php index 2ac902685d329..915bc11a5d867 100644 --- a/src/Symfony/Component/HttpFoundation/Cookie.php +++ b/src/Symfony/Component/HttpFoundation/Cookie.php @@ -46,7 +46,7 @@ public static function fromString($cookie, $decode = false) 'path' => '/', 'domain' => null, 'secure' => false, - 'httponly' => true, + 'httponly' => false, 'raw' => !$decode, 'samesite' => null, ); diff --git a/src/Symfony/Component/HttpFoundation/Tests/CookieTest.php b/src/Symfony/Component/HttpFoundation/Tests/CookieTest.php index edaed2533b1bd..a79776a2a9ddf 100644 --- a/src/Symfony/Component/HttpFoundation/Tests/CookieTest.php +++ b/src/Symfony/Component/HttpFoundation/Tests/CookieTest.php @@ -200,6 +200,15 @@ public function testFromString() $this->assertEquals(new Cookie('foo', 'bar', strtotime('Fri, 20-May-2011 15:25:52 GMT'), '/', '.myfoodomain.com', true, true, true), $cookie); $cookie = Cookie::fromString('foo=bar', true); - $this->assertEquals(new Cookie('foo', 'bar'), $cookie); + $this->assertEquals(new Cookie('foo', 'bar', 0, '/', null, false, false), $cookie); + } + + public function testFromStringWithHttpOnly() + { + $cookie = Cookie::fromString('foo=bar; expires=Fri, 20-May-2011 15:25:52 GMT; path=/; domain=.myfoodomain.com; secure; httponly'); + $this->assertTrue($cookie->isHttpOnly()); + + $cookie = Cookie::fromString('foo=bar; expires=Fri, 20-May-2011 15:25:52 GMT; path=/; domain=.myfoodomain.com; secure'); + $this->assertFalse($cookie->isHttpOnly()); } } diff --git a/src/Symfony/Component/HttpFoundation/Tests/ResponseHeaderBagTest.php b/src/Symfony/Component/HttpFoundation/Tests/ResponseHeaderBagTest.php index 724328ae850e4..41365672141aa 100644 --- a/src/Symfony/Component/HttpFoundation/Tests/ResponseHeaderBagTest.php +++ b/src/Symfony/Component/HttpFoundation/Tests/ResponseHeaderBagTest.php @@ -241,12 +241,12 @@ public function testSetCookieHeader() { $bag = new ResponseHeaderBag(); $bag->set('set-cookie', 'foo=bar'); - $this->assertEquals(array(new Cookie('foo', 'bar', 0, '/', null, false, true, true)), $bag->getCookies()); + $this->assertEquals(array(new Cookie('foo', 'bar', 0, '/', null, false, false, true)), $bag->getCookies()); $bag->set('set-cookie', 'foo2=bar2', false); $this->assertEquals(array( - new Cookie('foo', 'bar', 0, '/', null, false, true, true), - new Cookie('foo2', 'bar2', 0, '/', null, false, true, true), + new Cookie('foo', 'bar', 0, '/', null, false, false, true), + new Cookie('foo2', 'bar2', 0, '/', null, false, false, true), ), $bag->getCookies()); $bag->remove('set-cookie'); From 0db8d7fb6a5396f84f2907e5e595c114982772ff Mon Sep 17 00:00:00 2001 From: Javier Eguiluz Date: Mon, 19 Jun 2017 11:42:01 +0200 Subject: [PATCH 0377/1099] Add support for microseconds in Stopwatch --- .../FrameworkExtension.php | 2 +- src/Symfony/Component/Stopwatch/CHANGELOG.md | 2 + src/Symfony/Component/Stopwatch/Section.php | 15 +++-- src/Symfony/Component/Stopwatch/Stopwatch.php | 13 +++- .../Component/Stopwatch/StopwatchEvent.php | 17 +++-- .../Component/Stopwatch/StopwatchPeriod.php | 17 ++--- .../Stopwatch/Tests/StopwatchPeriodTest.php | 67 +++++++++++++++++++ 7 files changed, 113 insertions(+), 20 deletions(-) create mode 100644 src/Symfony/Component/Stopwatch/Tests/StopwatchPeriodTest.php diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php index f3b77f0a12409..a3c92a026be52 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php @@ -652,7 +652,7 @@ private function registerDebugConfiguration(array $config, ContainerBuilder $con $loader->load('debug_prod.xml'); if (class_exists(Stopwatch::class)) { - $container->register('debug.stopwatch', Stopwatch::class); + $container->register('debug.stopwatch', Stopwatch::class)->addArgument(true); $container->setAlias(Stopwatch::class, 'debug.stopwatch'); } diff --git a/src/Symfony/Component/Stopwatch/CHANGELOG.md b/src/Symfony/Component/Stopwatch/CHANGELOG.md index 2a03545ed1b82..36d0c25f1a9f7 100644 --- a/src/Symfony/Component/Stopwatch/CHANGELOG.md +++ b/src/Symfony/Component/Stopwatch/CHANGELOG.md @@ -5,3 +5,5 @@ CHANGELOG ----- * added the `Stopwatch::reset()` method + * allowed to measure sub-millisecond times by introducing an argument to the + constructor of `Stopwatch` diff --git a/src/Symfony/Component/Stopwatch/Section.php b/src/Symfony/Component/Stopwatch/Section.php index 2337e03140c7f..d4ff9928f83ac 100644 --- a/src/Symfony/Component/Stopwatch/Section.php +++ b/src/Symfony/Component/Stopwatch/Section.php @@ -28,6 +28,11 @@ class Section */ private $origin; + /** + * @var bool + */ + private $morePrecision; + /** * @var string */ @@ -41,11 +46,13 @@ class Section /** * Constructor. * - * @param float|null $origin Set the origin of the events in this section, use null to set their origin to their start time + * @param float|null $origin Set the origin of the events in this section, use null to set their origin to their start time + * @param bool $morePrecision If true, time is stored as float to keep the original microsecond precision */ - public function __construct($origin = null) + public function __construct($origin = null, $morePrecision = false) { $this->origin = is_numeric($origin) ? $origin : null; + $this->morePrecision = $morePrecision; } /** @@ -74,7 +81,7 @@ public function get($id) public function open($id) { if (null === $session = $this->get($id)) { - $session = $this->children[] = new self(microtime(true) * 1000); + $session = $this->children[] = new self(microtime(true) * 1000, $this->morePrecision); } return $session; @@ -113,7 +120,7 @@ public function setId($id) public function startEvent($name, $category) { if (!isset($this->events[$name])) { - $this->events[$name] = new StopwatchEvent($this->origin ?: microtime(true) * 1000, $category); + $this->events[$name] = new StopwatchEvent($this->origin ?: microtime(true) * 1000, $category, $this->morePrecision); } return $this->events[$name]->start(); diff --git a/src/Symfony/Component/Stopwatch/Stopwatch.php b/src/Symfony/Component/Stopwatch/Stopwatch.php index 562f220f673b1..cbe08cc7c1f0f 100644 --- a/src/Symfony/Component/Stopwatch/Stopwatch.php +++ b/src/Symfony/Component/Stopwatch/Stopwatch.php @@ -18,6 +18,11 @@ */ class Stopwatch { + /** + * @var bool + */ + private $morePrecision; + /** * @var Section[] */ @@ -28,9 +33,13 @@ class Stopwatch */ private $activeSections; - public function __construct() + /** + * @param bool $morePrecision If true, time is stored as float to keep the original microsecond precision + */ + public function __construct($morePrecision = false) { $this->reset(); + $this->morePrecision = $morePrecision; } /** @@ -162,6 +171,6 @@ public function getSectionEvents($id) */ public function reset() { - $this->sections = $this->activeSections = array('__root__' => new Section('__root__')); + $this->sections = $this->activeSections = array('__root__' => new Section('__root__', $this->morePrecision)); } } diff --git a/src/Symfony/Component/Stopwatch/StopwatchEvent.php b/src/Symfony/Component/Stopwatch/StopwatchEvent.php index 16a30db2aa50e..0d20f49b13f3f 100644 --- a/src/Symfony/Component/Stopwatch/StopwatchEvent.php +++ b/src/Symfony/Component/Stopwatch/StopwatchEvent.php @@ -33,6 +33,11 @@ class StopwatchEvent */ private $category; + /** + * @var bool + */ + private $morePrecision; + /** * @var float[] */ @@ -41,15 +46,17 @@ class StopwatchEvent /** * Constructor. * - * @param float $origin The origin time in milliseconds - * @param string|null $category The event category or null to use the default + * @param float $origin The origin time in milliseconds + * @param string|null $category The event category or null to use the default + * @param bool $morePrecision If true, time is stored as float to keep the original microsecond precision * * @throws \InvalidArgumentException When the raw time is not valid */ - public function __construct($origin, $category = null) + public function __construct($origin, $category = null, $morePrecision = false) { $this->origin = $this->formatTime($origin); $this->category = is_string($category) ? $category : 'default'; + $this->morePrecision = $morePrecision; } /** @@ -97,7 +104,7 @@ public function stop() throw new \LogicException('stop() called but start() has not been called before.'); } - $this->periods[] = new StopwatchPeriod(array_pop($this->started), $this->getNow()); + $this->periods[] = new StopwatchPeriod(array_pop($this->started), $this->getNow(), $this->morePrecision); return $this; } @@ -177,7 +184,7 @@ public function getDuration() for ($i = 0; $i < $left; ++$i) { $index = $stopped + $i; - $periods[] = new StopwatchPeriod($this->started[$index], $this->getNow()); + $periods[] = new StopwatchPeriod($this->started[$index], $this->getNow(), $this->morePrecision); } $total = 0; diff --git a/src/Symfony/Component/Stopwatch/StopwatchPeriod.php b/src/Symfony/Component/Stopwatch/StopwatchPeriod.php index 9876f179aadb6..c3ae266c9aecb 100644 --- a/src/Symfony/Component/Stopwatch/StopwatchPeriod.php +++ b/src/Symfony/Component/Stopwatch/StopwatchPeriod.php @@ -25,20 +25,21 @@ class StopwatchPeriod /** * Constructor. * - * @param int $start The relative time of the start of the period (in milliseconds) - * @param int $end The relative time of the end of the period (in milliseconds) + * @param int|float $start The relative time of the start of the period (in milliseconds) + * @param int|float $end The relative time of the end of the period (in milliseconds) + * @param bool $morePrecision If true, time is stored as float to keep the original microsecond precision */ - public function __construct($start, $end) + public function __construct($start, $end, $morePrecision = false) { - $this->start = (int) $start; - $this->end = (int) $end; + $this->start = $morePrecision ? (float) $start : (int) $start; + $this->end = $morePrecision ? (float) $end : (int) $end; $this->memory = memory_get_usage(true); } /** * Gets the relative time of the start of the period. * - * @return int The time (in milliseconds) + * @return int|float The time (in milliseconds) */ public function getStartTime() { @@ -48,7 +49,7 @@ public function getStartTime() /** * Gets the relative time of the end of the period. * - * @return int The time (in milliseconds) + * @return int|float The time (in milliseconds) */ public function getEndTime() { @@ -58,7 +59,7 @@ public function getEndTime() /** * Gets the time spent in this period. * - * @return int The period duration (in milliseconds) + * @return int|float The period duration (in milliseconds) */ public function getDuration() { diff --git a/src/Symfony/Component/Stopwatch/Tests/StopwatchPeriodTest.php b/src/Symfony/Component/Stopwatch/Tests/StopwatchPeriodTest.php new file mode 100644 index 0000000000000..f2387b8285bec --- /dev/null +++ b/src/Symfony/Component/Stopwatch/Tests/StopwatchPeriodTest.php @@ -0,0 +1,67 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Stopwatch\Tests; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\Stopwatch\StopwatchPeriod; + +class StopwatchPeriodTest extends TestCase +{ + /** + * @dataProvider provideTimeValues + */ + public function testGetStartTime($start, $useMorePrecision, $expected) + { + $period = new StopwatchPeriod($start, $start, $useMorePrecision); + $this->assertSame($expected, $period->getStartTime()); + } + + /** + * @dataProvider provideTimeValues + */ + public function testGetEndTime($end, $useMorePrecision, $expected) + { + $period = new StopwatchPeriod($end, $end, $useMorePrecision); + $this->assertSame($expected, $period->getEndTime()); + } + + /** + * @dataProvider provideDurationValues + */ + public function testGetDuration($start, $end, $useMorePrecision, $duration) + { + $period = new StopwatchPeriod($start, $end, $useMorePrecision); + $this->assertSame($duration, $period->getDuration()); + } + + public function provideTimeValues() + { + yield array(0, false, 0); + yield array(0, true, 0.0); + yield array(0.0, false, 0); + yield array(0.0, true, 0.0); + yield array(2.71, false, 2); + yield array(2.71, true, 2.71); + } + + public function provideDurationValues() + { + yield array(0, 0, false, 0); + yield array(0, 0, true, 0.0); + yield array(0.0, 0.0, false, 0); + yield array(0.0, 0.0, true, 0.0); + yield array(2, 3.14, false, 1); + yield array(2, 3.14, true, 1.14); + yield array(2.71, 3.14, false, 1); + yield array(2.71, 3.14, true, 0.43); + } +} From f8be69da5f6aa3a93ae153ec1e383ae11c913068 Mon Sep 17 00:00:00 2001 From: Dany Maillard Date: Thu, 6 Jul 2017 11:15:46 +0200 Subject: [PATCH 0378/1099] Remove TemplateManager::getTemplates() --- UPGRADE-4.0.md | 5 +++++ .../Bundle/WebProfilerBundle/CHANGELOG.md | 1 + .../Profiler/TemplateManager.php | 20 ----------------- .../Tests/Profiler/TemplateManagerTest.php | 22 ------------------- 4 files changed, 6 insertions(+), 42 deletions(-) diff --git a/UPGRADE-4.0.md b/UPGRADE-4.0.md index ba301f1aeaa2c..f0bfb588ec3c6 100644 --- a/UPGRADE-4.0.md +++ b/UPGRADE-4.0.md @@ -619,6 +619,11 @@ VarDumper VarDumperTestTrait::assertDumpMatchesFormat($dump, $data, $filter = 0, $message = ''); ``` +WebProfilerBundle +----------------- + + * Removed the `getTemplates()` method of the `TemplateManager` class in favor of the ``getNames()`` method. + Workflow -------- diff --git a/src/Symfony/Bundle/WebProfilerBundle/CHANGELOG.md b/src/Symfony/Bundle/WebProfilerBundle/CHANGELOG.md index 9c1a66132925f..260dbdae05c67 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/CHANGELOG.md +++ b/src/Symfony/Bundle/WebProfilerBundle/CHANGELOG.md @@ -5,6 +5,7 @@ CHANGELOG ----- * removed the `WebProfilerExtension::dumpValue()` method + * removed the `getTemplates()` method of the `TemplateManager` class in favor of the ``getNames()`` method 3.1.0 ----- diff --git a/src/Symfony/Bundle/WebProfilerBundle/Profiler/TemplateManager.php b/src/Symfony/Bundle/WebProfilerBundle/Profiler/TemplateManager.php index 29fe3a31c85d6..13590e33acd95 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Profiler/TemplateManager.php +++ b/src/Symfony/Bundle/WebProfilerBundle/Profiler/TemplateManager.php @@ -60,26 +60,6 @@ public function getName(Profile $profile, $panel) return $templates[$panel]; } - /** - * Gets the templates for a given profile. - * - * @param Profile $profile - * - * @return Template[] - * - * @deprecated not used anymore internally - */ - public function getTemplates(Profile $profile) - { - $templates = $this->getNames($profile); - - foreach ($templates as $name => $template) { - $templates[$name] = $this->twig->loadTemplate($template); - } - - return $templates; - } - /** * Gets template names of templates that are present in the viewed profile. * diff --git a/src/Symfony/Bundle/WebProfilerBundle/Tests/Profiler/TemplateManagerTest.php b/src/Symfony/Bundle/WebProfilerBundle/Tests/Profiler/TemplateManagerTest.php index 7b8f9a8df51c0..ee0ba44fa74d9 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Tests/Profiler/TemplateManagerTest.php +++ b/src/Symfony/Bundle/WebProfilerBundle/Tests/Profiler/TemplateManagerTest.php @@ -79,28 +79,6 @@ public function testGetNameValidTemplate() $this->assertEquals('FooBundle:Collector:foo.html.twig', $this->templateManager->getName($profile, 'foo')); } - /** - * template should be loaded for 'foo' because other collectors are - * missing in profile or in profiler. - */ - public function testGetTemplates() - { - $profile = $this->mockProfile(); - $profile->expects($this->any()) - ->method('hasCollector') - ->will($this->returnCallback(array($this, 'profilerHasCallback'))); - - $this->profiler->expects($this->any()) - ->method('has') - ->withAnyParameters() - ->will($this->returnCallback(array($this, 'profileHasCollectorCallback'))); - - $result = $this->templateManager->getTemplates($profile); - $this->assertArrayHasKey('foo', $result); - $this->assertArrayNotHasKey('bar', $result); - $this->assertArrayNotHasKey('baz', $result); - } - public function profilerHasCallback($panel) { switch ($panel) { From 76858808ad70ada0b833b438d143c6462d179ef8 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Thu, 6 Jul 2017 12:37:30 +0300 Subject: [PATCH 0379/1099] fixed CS --- .../Component/Validator/Constraints/ImageValidator.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/Validator/Constraints/ImageValidator.php b/src/Symfony/Component/Validator/Constraints/ImageValidator.php index da8ec19b715e8..faf59eba21c14 100644 --- a/src/Symfony/Component/Validator/Constraints/ImageValidator.php +++ b/src/Symfony/Component/Validator/Constraints/ImageValidator.php @@ -68,7 +68,7 @@ public function validate($value, Constraint $constraint) if ($constraint->minWidth) { if (!ctype_digit((string) $constraint->minWidth)) { - throw new ConstraintDefinitionException(sprintf('"%s" is not a valid minimum width', $constraint->minWidth)); + throw new ConstraintDefinitionException(sprintf('"%s" is not a valid minimum width.', $constraint->minWidth)); } if ($width < $constraint->minWidth) { @@ -84,7 +84,7 @@ public function validate($value, Constraint $constraint) if ($constraint->maxWidth) { if (!ctype_digit((string) $constraint->maxWidth)) { - throw new ConstraintDefinitionException(sprintf('"%s" is not a valid maximum width', $constraint->maxWidth)); + throw new ConstraintDefinitionException(sprintf('"%s" is not a valid maximum width.', $constraint->maxWidth)); } if ($width > $constraint->maxWidth) { From a20426ddede264e5b9d2dc994af9d2740dabd9f6 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Thu, 6 Jul 2017 12:41:12 +0300 Subject: [PATCH 0380/1099] fixed CS --- UPGRADE-4.0.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/UPGRADE-4.0.md b/UPGRADE-4.0.md index f0bfb588ec3c6..e0c90e2cbee1c 100644 --- a/UPGRADE-4.0.md +++ b/UPGRADE-4.0.md @@ -622,7 +622,8 @@ VarDumper WebProfilerBundle ----------------- - * Removed the `getTemplates()` method of the `TemplateManager` class in favor of the ``getNames()`` method. + * Removed the `getTemplates()` method of the `TemplateManager` class in favor + of the `getNames()` method Workflow -------- From 5a37f84713e3bc36b3400e3d85043b176bfdf6b3 Mon Sep 17 00:00:00 2001 From: Chris Wilkinson Date: Tue, 31 Jan 2017 08:56:27 +0000 Subject: [PATCH 0381/1099] [HttpFoundation] Find the original request protocol version --- .../Component/HttpFoundation/Request.php | 24 +++++++++++++++ .../HttpFoundation/Tests/RequestTest.php | 30 +++++++++++++++++++ 2 files changed, 54 insertions(+) diff --git a/src/Symfony/Component/HttpFoundation/Request.php b/src/Symfony/Component/HttpFoundation/Request.php index 6fd0707b059ff..6cfee8f4af688 100644 --- a/src/Symfony/Component/HttpFoundation/Request.php +++ b/src/Symfony/Component/HttpFoundation/Request.php @@ -1581,6 +1581,30 @@ public function isMethodCacheable() return in_array($this->getMethod(), array('GET', 'HEAD')); } + /** + * Returns the protocol version. + * + * If the application is behind a proxy, the protocol version used in the + * requests between the client and the proxy and between the proxy and the + * server might be different. This returns the former (from the "Via" header) + * if the proxy is trusted (see "setTrustedProxies()"), otherwise it returns + * the latter (from the "SERVER_PROTOCOL" server parameter). + * + * @return string + */ + public function getProtocolVersion() + { + if ($this->isFromTrustedProxy()) { + preg_match('~^(HTTP/)?([1-9]\.[0-9]) ~', $this->headers->get('Via'), $matches); + + if ($matches) { + return 'HTTP/'.$matches[2]; + } + } + + return $this->server->get('SERVER_PROTOCOL'); + } + /** * Returns the request body content. * diff --git a/src/Symfony/Component/HttpFoundation/Tests/RequestTest.php b/src/Symfony/Component/HttpFoundation/Tests/RequestTest.php index b36fbb7e96258..54c95c4315452 100644 --- a/src/Symfony/Component/HttpFoundation/Tests/RequestTest.php +++ b/src/Symfony/Component/HttpFoundation/Tests/RequestTest.php @@ -2188,6 +2188,36 @@ public function testGetTrustedHeaderName() Request::setTrustedHeaderName(Request::HEADER_CLIENT_PORT, 'X_FORWARDED_PORT'); Request::setTrustedHeaderName(Request::HEADER_CLIENT_PROTO, 'X_FORWARDED_PROTO'); } + + /** + * @dataProvider protocolVersionProvider + */ + public function testProtocolVersion($serverProtocol, $trustedProxy, $via, $expected) + { + if ($trustedProxy) { + Request::setTrustedProxies(array('1.1.1.1')); + } + + $request = new Request(); + $request->server->set('SERVER_PROTOCOL', $serverProtocol); + $request->server->set('REMOTE_ADDR', '1.1.1.1'); + $request->headers->set('Via', $via); + + $this->assertSame($expected, $request->getProtocolVersion()); + } + + public function protocolVersionProvider() + { + return array( + 'untrusted without via' => array('HTTP/2.0', false, '', 'HTTP/2.0'), + 'untrusted with via' => array('HTTP/2.0', false, '1.0 fred, 1.1 nowhere.com (Apache/1.1)', 'HTTP/2.0'), + 'trusted without via' => array('HTTP/2.0', true, '', 'HTTP/2.0'), + 'trusted with via' => array('HTTP/2.0', true, '1.0 fred, 1.1 nowhere.com (Apache/1.1)', 'HTTP/1.0'), + 'trusted with via and protocol name' => array('HTTP/2.0', true, 'HTTP/1.0 fred, HTTP/1.1 nowhere.com (Apache/1.1)', 'HTTP/1.0'), + 'trusted with broken via' => array('HTTP/2.0', true, 'HTTP/1^0 foo', 'HTTP/2.0'), + 'trusted with partially-broken via' => array('HTTP/2.0', true, '1.0 fred, foo', 'HTTP/1.0'), + ); + } } class RequestContentProxy extends Request From 26641bdf44039cc2c11713c5e4a59a55a614a84d Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Thu, 6 Jul 2017 12:58:45 +0300 Subject: [PATCH 0382/1099] fixed tests --- src/Symfony/Component/HttpFoundation/Tests/RequestTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/HttpFoundation/Tests/RequestTest.php b/src/Symfony/Component/HttpFoundation/Tests/RequestTest.php index 54c95c4315452..47459c79af966 100644 --- a/src/Symfony/Component/HttpFoundation/Tests/RequestTest.php +++ b/src/Symfony/Component/HttpFoundation/Tests/RequestTest.php @@ -2195,7 +2195,7 @@ public function testGetTrustedHeaderName() public function testProtocolVersion($serverProtocol, $trustedProxy, $via, $expected) { if ($trustedProxy) { - Request::setTrustedProxies(array('1.1.1.1')); + Request::setTrustedProxies(array('1.1.1.1'), -1); } $request = new Request(); From 04b8b8027c5bc8c17dc4aa3bc5499aa1da31aa48 Mon Sep 17 00:00:00 2001 From: Michael Babker Date: Sun, 21 May 2017 10:02:52 -0500 Subject: [PATCH 0383/1099] Deprecate support for stacked errors --- UPGRADE-3.4.md | 5 +++++ UPGRADE-4.0.md | 2 ++ src/Symfony/Component/Debug/CHANGELOG.md | 5 +++++ src/Symfony/Component/Debug/DebugClassLoader.php | 4 ++-- src/Symfony/Component/Debug/ErrorHandler.php | 8 ++++++++ src/Symfony/Component/Debug/Tests/ErrorHandlerTest.php | 3 +++ 6 files changed, 25 insertions(+), 2 deletions(-) diff --git a/UPGRADE-3.4.md b/UPGRADE-3.4.md index 383abb72eb1ac..b1d0239547e34 100644 --- a/UPGRADE-3.4.md +++ b/UPGRADE-3.4.md @@ -6,6 +6,11 @@ DependencyInjection * Top-level anonymous services in XML are deprecated and will throw an exception in Symfony 4.0. +Debug +----- + + * Support for stacked errors in the `ErrorHandler` is deprecated and will be removed in Symfony 4.0. + Finder ------ diff --git a/UPGRADE-4.0.md b/UPGRADE-4.0.md index 791fad5a0b578..8e522ca92b660 100644 --- a/UPGRADE-4.0.md +++ b/UPGRADE-4.0.md @@ -70,6 +70,8 @@ Debug * `FlattenException::getTrace()` now returns additional type descriptions `integer` and `float`. + * Support for stacked errors in the `ErrorHandler` has been removed + DependencyInjection ------------------- diff --git a/src/Symfony/Component/Debug/CHANGELOG.md b/src/Symfony/Component/Debug/CHANGELOG.md index a853b7a0a70a4..31c67eb60cce9 100644 --- a/src/Symfony/Component/Debug/CHANGELOG.md +++ b/src/Symfony/Component/Debug/CHANGELOG.md @@ -1,6 +1,11 @@ CHANGELOG ========= +3.4.0 +----- + +* deprecated `ErrorHandler::stackErrors()` and `ErrorHandler::unstackErrors()` + 3.3.0 ----- diff --git a/src/Symfony/Component/Debug/DebugClassLoader.php b/src/Symfony/Component/Debug/DebugClassLoader.php index 2e1d71808e132..2b13c02cf92c5 100644 --- a/src/Symfony/Component/Debug/DebugClassLoader.php +++ b/src/Symfony/Component/Debug/DebugClassLoader.php @@ -136,7 +136,7 @@ public static function disable() */ public function loadClass($class) { - ErrorHandler::stackErrors(); + $e = error_reporting(error_reporting() | E_PARSE | E_ERROR | E_CORE_ERROR | E_COMPILE_ERROR); try { if ($this->isFinder) { @@ -148,7 +148,7 @@ public function loadClass($class) $file = false; } } finally { - ErrorHandler::unstackErrors(); + error_reporting($e); } $exists = class_exists($class, false) || interface_exists($class, false) || trait_exists($class, false); diff --git a/src/Symfony/Component/Debug/ErrorHandler.php b/src/Symfony/Component/Debug/ErrorHandler.php index e25b5a6dd8b2a..9ebe7b0d0e7bd 100644 --- a/src/Symfony/Component/Debug/ErrorHandler.php +++ b/src/Symfony/Component/Debug/ErrorHandler.php @@ -648,17 +648,25 @@ public static function handleFatalError(array $error = null) * * The most important feature of this is to prevent * autoloading until unstackErrors() is called. + * + * @deprecated since version 3.4, to be removed in 4.0. */ public static function stackErrors() { + @trigger_error('Support for stacking errors is deprecated since Symfony 3.4 and will be removed in 4.0.', E_USER_DEPRECATED); + self::$stackedErrorLevels[] = error_reporting(error_reporting() | E_PARSE | E_ERROR | E_CORE_ERROR | E_COMPILE_ERROR); } /** * Unstacks stacked errors and forwards to the logger. + * + * @deprecated since version 3.4, to be removed in 4.0. */ public static function unstackErrors() { + @trigger_error('Support for unstacking errors is deprecated since Symfony 3.4 and will be removed in 4.0.', E_USER_DEPRECATED); + $level = array_pop(self::$stackedErrorLevels); if (null !== $level) { diff --git a/src/Symfony/Component/Debug/Tests/ErrorHandlerTest.php b/src/Symfony/Component/Debug/Tests/ErrorHandlerTest.php index a14accf3df9a0..41d1bea77e123 100644 --- a/src/Symfony/Component/Debug/Tests/ErrorHandlerTest.php +++ b/src/Symfony/Component/Debug/Tests/ErrorHandlerTest.php @@ -342,6 +342,9 @@ public function testHandleException() } } + /** + * @group legacy + */ public function testErrorStacking() { try { From 76dc317e03acfd7b863892fb03af5f94b8ec7fbd Mon Sep 17 00:00:00 2001 From: Michael Babker Date: Sat, 20 May 2017 10:47:15 -0500 Subject: [PATCH 0384/1099] Removed ContextErrorException --- src/Symfony/Component/Debug/CHANGELOG.md | 1 + src/Symfony/Component/Debug/ErrorHandler.php | 7 +--- .../Debug/Exception/ContextErrorException.php | 40 ------------------- .../Debug/Tests/DebugClassLoaderTest.php | 32 --------------- .../Session/Storage/NativeSessionStorage.php | 5 +-- 5 files changed, 4 insertions(+), 81 deletions(-) delete mode 100644 src/Symfony/Component/Debug/Exception/ContextErrorException.php diff --git a/src/Symfony/Component/Debug/CHANGELOG.md b/src/Symfony/Component/Debug/CHANGELOG.md index ab7ff7219e480..122af73174bf4 100644 --- a/src/Symfony/Component/Debug/CHANGELOG.md +++ b/src/Symfony/Component/Debug/CHANGELOG.md @@ -5,6 +5,7 @@ CHANGELOG ----- * removed the symfony_debug extension +* removed `ContextErrorException` 3.4.0 ----- diff --git a/src/Symfony/Component/Debug/ErrorHandler.php b/src/Symfony/Component/Debug/ErrorHandler.php index 33045e97aac4d..570f0d0c8cef9 100644 --- a/src/Symfony/Component/Debug/ErrorHandler.php +++ b/src/Symfony/Component/Debug/ErrorHandler.php @@ -13,7 +13,6 @@ use Psr\Log\LogLevel; use Psr\Log\LoggerInterface; -use Symfony\Component\Debug\Exception\ContextErrorException; use Symfony\Component\Debug\Exception\FatalErrorException; use Symfony\Component\Debug\Exception\FatalThrowableError; use Symfony\Component\Debug\Exception\OutOfMemoryException; @@ -415,11 +414,7 @@ public function handleError($type, $message, $file, $line) return; } } else { - if ($scope) { - $errorAsException = new ContextErrorException($logMessage, 0, $type, $file, $line, $context); - } else { - $errorAsException = new \ErrorException($logMessage, 0, $type, $file, $line); - } + $errorAsException = new \ErrorException($logMessage, 0, $type, $file, $line); // Clean the trace by removing function arguments and the first frames added by the error handler itself. if ($throw || $this->tracedErrors & $type) { diff --git a/src/Symfony/Component/Debug/Exception/ContextErrorException.php b/src/Symfony/Component/Debug/Exception/ContextErrorException.php deleted file mode 100644 index 6561d4df37287..0000000000000 --- a/src/Symfony/Component/Debug/Exception/ContextErrorException.php +++ /dev/null @@ -1,40 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Debug\Exception; - -/** - * Error Exception with Variable Context. - * - * @author Christian Sciberras - * - * @deprecated since version 3.3. Instead, \ErrorException will be used directly in 4.0. - */ -class ContextErrorException extends \ErrorException -{ - private $context = array(); - - public function __construct($message, $code, $severity, $filename, $lineno, $context = array()) - { - parent::__construct($message, $code, $severity, $filename, $lineno); - $this->context = $context; - } - - /** - * @return array Array of variables that existed when the exception occurred - */ - public function getContext() - { - @trigger_error(sprintf('The %s class is deprecated since version 3.3 and will be removed in 4.0.', __CLASS__), E_USER_DEPRECATED); - - return $this->context; - } -} diff --git a/src/Symfony/Component/Debug/Tests/DebugClassLoaderTest.php b/src/Symfony/Component/Debug/Tests/DebugClassLoaderTest.php index 034e6a3b2aec3..2de0dec574271 100644 --- a/src/Symfony/Component/Debug/Tests/DebugClassLoaderTest.php +++ b/src/Symfony/Component/Debug/Tests/DebugClassLoaderTest.php @@ -59,38 +59,6 @@ public function testIdempotence() $this->fail('DebugClassLoader did not register'); } - public function testStacking() - { - // the ContextErrorException must not be loaded to test the workaround - // for https://bugs.php.net/65322. - if (class_exists('Symfony\Component\Debug\Exception\ContextErrorException', false)) { - $this->markTestSkipped('The ContextErrorException class is already loaded.'); - } - - ErrorHandler::register(); - - try { - // Trigger autoloading + E_STRICT at compile time - // which in turn triggers $errorHandler->handle() - // that again triggers autoloading for ContextErrorException. - // Error stacking works around the bug above and everything is fine. - - eval(' - namespace '.__NAMESPACE__.'; - class ChildTestingStacking extends TestingStacking { function foo($bar) {} } - '); - $this->fail('ContextErrorException expected'); - } catch (\ErrorException $exception) { - // if an exception is thrown, the test passed - $this->assertStringStartsWith(__FILE__, $exception->getFile()); - $this->assertRegExp('/^Warning: Declaration/', $exception->getMessage()); - $this->assertEquals(E_WARNING, $exception->getSeverity()); - } finally { - restore_error_handler(); - restore_exception_handler(); - } - } - /** * @expectedException \RuntimeException */ diff --git a/src/Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.php b/src/Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.php index 8a6ffec12dd1a..2671cf481d8a5 100644 --- a/src/Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.php +++ b/src/Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.php @@ -11,7 +11,6 @@ namespace Symfony\Component\HttpFoundation\Session\Storage; -use Symfony\Component\Debug\Exception\ContextErrorException; use Symfony\Component\HttpFoundation\Session\SessionBagInterface; use Symfony\Component\HttpFoundation\Session\Storage\Handler\NativeSessionHandler; use Symfony\Component\HttpFoundation\Session\Storage\Proxy\AbstractProxy; @@ -213,13 +212,13 @@ public function save() { // Register custom error handler to catch a possible failure warning during session write set_error_handler(function ($errno, $errstr, $errfile, $errline, $errcontext) { - throw new ContextErrorException($errstr, $errno, E_WARNING, $errfile, $errline, $errcontext); + throw new \ErrorException($errstr, $errno, E_WARNING, $errfile, $errline, $errcontext); }, E_WARNING); try { session_write_close(); restore_error_handler(); - } catch (ContextErrorException $e) { + } catch (\ErrorException $e) { // The default PHP error message is not very helpful, as it does not give any information on the current save handler. // Therefore, we catch this error and trigger a warning with a better error message $handler = $this->getSaveHandler(); From 1dfcdc7000bd9acc8c29b617e2d884fa34c04a66 Mon Sep 17 00:00:00 2001 From: Brieuc Thomas Date: Thu, 6 Jul 2017 14:23:24 +0200 Subject: [PATCH 0385/1099] [DotEnv] Fix variable substitution --- src/Symfony/Component/Dotenv/Dotenv.php | 2 +- src/Symfony/Component/Dotenv/Tests/DotenvTest.php | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/Dotenv/Dotenv.php b/src/Symfony/Component/Dotenv/Dotenv.php index 00f27bb7b3cdd..2e907b8c980b8 100644 --- a/src/Symfony/Component/Dotenv/Dotenv.php +++ b/src/Symfony/Component/Dotenv/Dotenv.php @@ -351,7 +351,7 @@ private function resolveVariables($value) } $name = $matches[3]; - $value = isset($this->values[$name]) ? $this->values[$name] : (isset($_ENV[$name]) ? isset($_ENV[$name]) : (string) getenv($name)); + $value = isset($this->values[$name]) ? $this->values[$name] : (isset($_ENV[$name]) ? $_ENV[$name] : (string) getenv($name)); if (!$matches[2] && isset($matches[4])) { $value .= '}'; diff --git a/src/Symfony/Component/Dotenv/Tests/DotenvTest.php b/src/Symfony/Component/Dotenv/Tests/DotenvTest.php index a7f211ecd6e37..47598030a87f1 100644 --- a/src/Symfony/Component/Dotenv/Tests/DotenvTest.php +++ b/src/Symfony/Component/Dotenv/Tests/DotenvTest.php @@ -63,6 +63,7 @@ public function testParse($data, $expected) public function getEnvData() { putenv('LOCAL=local'); + $_ENV['REMOTE'] = 'remote'; $tests = array( // spaces @@ -134,6 +135,7 @@ public function getEnvData() array('FOO=" \\$ "', array('FOO' => ' $ ')), array('FOO=" $ "', array('FOO' => ' $ ')), array('BAR=$LOCAL', array('BAR' => 'local')), + array('BAR=$REMOTE', array('BAR' => 'remote')), array('FOO=$NOTDEFINED', array('FOO' => '')), ); From c7c5ba894600e9e859c33ee28ecd04626da241a3 Mon Sep 17 00:00:00 2001 From: Tobias Schultze Date: Thu, 6 Jul 2017 14:34:37 +0200 Subject: [PATCH 0386/1099] [TwigBridge] cleaner implementation of the TwigRenderer --- src/Symfony/Bridge/Twig/Form/TwigRenderer.php | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/src/Symfony/Bridge/Twig/Form/TwigRenderer.php b/src/Symfony/Bridge/Twig/Form/TwigRenderer.php index 2485c0a88c530..9f4d7c56ea886 100644 --- a/src/Symfony/Bridge/Twig/Form/TwigRenderer.php +++ b/src/Symfony/Bridge/Twig/Form/TwigRenderer.php @@ -19,16 +19,19 @@ */ class TwigRenderer extends FormRenderer implements TwigRendererInterface { - /** - * @var TwigRendererEngineInterface - */ - private $engine; - public function __construct(TwigRendererEngineInterface $engine, $csrfTokenManager = null) { parent::__construct($engine, $csrfTokenManager); + } - $this->engine = $engine; + /** + * Returns the engine used by this renderer. + * + * @return TwigRendererEngineInterface The renderer engine + */ + public function getEngine() + { + return parent::getEngine(); } /** @@ -36,6 +39,6 @@ public function __construct(TwigRendererEngineInterface $engine, $csrfTokenManag */ public function setEnvironment(Environment $environment) { - $this->engine->setEnvironment($environment); + $this->getEngine()->setEnvironment($environment); } } From 0bcc5afbda22e7b48056c2970e148c6dae7f647a Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Thu, 6 Jul 2017 16:36:30 +0300 Subject: [PATCH 0387/1099] Minor cleanups --- src/Symfony/Bundle/FrameworkBundle/composer.json | 1 - src/Symfony/Component/Debug/Tests/ErrorHandlerTest.php | 2 -- 2 files changed, 3 deletions(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/composer.json b/src/Symfony/Bundle/FrameworkBundle/composer.json index e6344094dd3c9..e17636e156175 100644 --- a/src/Symfony/Bundle/FrameworkBundle/composer.json +++ b/src/Symfony/Bundle/FrameworkBundle/composer.json @@ -66,7 +66,6 @@ "symfony/asset": "<3.3", "symfony/console": "<3.3", "symfony/form": "<3.3", - "symfony/http-kernel": "<3.4", "symfony/property-info": "<3.3", "symfony/serializer": "<3.3", "symfony/translation": "<3.4", diff --git a/src/Symfony/Component/Debug/Tests/ErrorHandlerTest.php b/src/Symfony/Component/Debug/Tests/ErrorHandlerTest.php index 41d1bea77e123..4cbe47f35c4d6 100644 --- a/src/Symfony/Component/Debug/Tests/ErrorHandlerTest.php +++ b/src/Symfony/Component/Debug/Tests/ErrorHandlerTest.php @@ -98,8 +98,6 @@ public function testNotice() // dummy function to test trace in error handler. private static function triggerNotice($that) { - // dummy variable to check for in error handler. - $foobar = 123; $that->assertSame('', $foo.$foo.$bar); } From dc3f7a9ebd465121dc73f2f1c9909cfd488422d2 Mon Sep 17 00:00:00 2001 From: Arturs Vonda Date: Fri, 11 Jul 2014 21:32:20 +0300 Subject: [PATCH 0388/1099] [Routing] Add matched and default parameters to redirect responses --- .../Matcher/Dumper/PhpMatcherDumper.php | 50 +++++++++++-------- .../Component/Routing/Matcher/UrlMatcher.php | 4 +- .../Tests/Fixtures/dumper/url_matcher2.php | 25 ++++++---- .../Tests/Fixtures/dumper/url_matcher5.php | 45 ++++++++++------- .../Tests/Fixtures/dumper/url_matcher7.php | 30 ++++++----- .../Matcher/RedirectableUrlMatcherTest.php | 16 +++++- 6 files changed, 107 insertions(+), 63 deletions(-) diff --git a/src/Symfony/Component/Routing/Matcher/Dumper/PhpMatcherDumper.php b/src/Symfony/Component/Routing/Matcher/Dumper/PhpMatcherDumper.php index 8eae68c4c280e..9a221e6c61cfe 100644 --- a/src/Symfony/Component/Routing/Matcher/Dumper/PhpMatcherDumper.php +++ b/src/Symfony/Component/Routing/Matcher/Dumper/PhpMatcherDumper.php @@ -333,10 +333,34 @@ private function compileRoute(Route $route, $name, $supportsRedirections, $paren } } + $retOffset = strlen($code); + + // optimize parameters array + if ($matches || $hostMatches) { + $vars = array(); + if ($hostMatches) { + $vars[] = '$hostMatches'; + } + if ($matches) { + $vars[] = '$matches'; + } + $vars[] = "array('_route' => '$name')"; + + $code .= sprintf( + " \$ret = \$this->mergeDefaults(array_replace(%s), %s);\n", + implode(', ', $vars), + str_replace("\n", '', var_export($route->getDefaults(), true)) + ); + } elseif ($route->getDefaults()) { + $code .= sprintf(" \$ret = %s;\n", str_replace("\n", '', var_export(array_replace($route->getDefaults(), array('_route' => $name)), true))); + } else { + $code .= sprintf(" \$ret = array('_route' => '%s');\n", $name); + } + if ($hasTrailingSlash) { $code .= <<redirect(\$pathinfo.'/', '$name'); + return array_replace(\$ret, \$this->redirect(\$pathinfo.'/', '$name')); } @@ -351,33 +375,17 @@ private function compileRoute(Route $route, $name, $supportsRedirections, $paren $code .= <<redirect(\$pathinfo, '$name', key(\$requiredSchemes)); + return array_replace(\$ret, \$this->redirect(\$pathinfo, '$name', key(\$requiredSchemes))); } EOF; } - // optimize parameters array - if ($matches || $hostMatches) { - $vars = array(); - if ($hostMatches) { - $vars[] = '$hostMatches'; - } - if ($matches) { - $vars[] = '$matches'; - } - $vars[] = "array('_route' => '$name')"; - - $code .= sprintf( - " return \$this->mergeDefaults(array_replace(%s), %s);\n", - implode(', ', $vars), - str_replace("\n", '', var_export($route->getDefaults(), true)) - ); - } elseif ($route->getDefaults()) { - $code .= sprintf(" return %s;\n", str_replace("\n", '', var_export(array_replace($route->getDefaults(), array('_route' => $name)), true))); + if ($hasTrailingSlash || $schemes) { + $code .= " return \$ret;\n"; } else { - $code .= sprintf(" return array('_route' => '%s');\n", $name); + $code = substr_replace($code, 'return', $retOffset + 12, 6); } $code .= " }\n"; diff --git a/src/Symfony/Component/Routing/Matcher/UrlMatcher.php b/src/Symfony/Component/Routing/Matcher/UrlMatcher.php index c646723b3ab08..f90555643a357 100644 --- a/src/Symfony/Component/Routing/Matcher/UrlMatcher.php +++ b/src/Symfony/Component/Routing/Matcher/UrlMatcher.php @@ -164,7 +164,9 @@ protected function matchCollection($pathinfo, RouteCollection $routes) $status = $this->handleRouteRequirements($pathinfo, $name, $route); if (self::ROUTE_MATCH === $status[0]) { - return $status[1]; + $attributes = array_replace($matches, $hostMatches, (array) $status[1]); + + return $this->mergeDefaults($attributes, $route->getDefaults()); } if (self::REQUIREMENT_MISMATCH === $status[0]) { diff --git a/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher2.php b/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher2.php index 91ec47899e4eb..efab3dba7e4aa 100644 --- a/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher2.php +++ b/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher2.php @@ -87,22 +87,24 @@ public function match($pathinfo) // baz3 if ('/test/baz3' === $trimmedPathinfo) { + $ret = array('_route' => 'baz3'); if (substr($pathinfo, -1) !== '/') { - return $this->redirect($pathinfo.'/', 'baz3'); + return array_replace($ret, $this->redirect($pathinfo.'/', 'baz3')); } - return array('_route' => 'baz3'); + return $ret; } } // baz4 if (preg_match('#^/test/(?P[^/]++)/?$#s', $pathinfo, $matches)) { + $ret = $this->mergeDefaults(array_replace($matches, array('_route' => 'baz4')), array ()); if (substr($pathinfo, -1) !== '/') { - return $this->redirect($pathinfo.'/', 'baz4'); + return array_replace($ret, $this->redirect($pathinfo.'/', 'baz4')); } - return $this->mergeDefaults(array_replace($matches, array('_route' => 'baz4')), array ()); + return $ret; } // baz5 @@ -181,11 +183,12 @@ public function match($pathinfo) // hey if ('/multi/hey' === $trimmedPathinfo) { + $ret = array('_route' => 'hey'); if (substr($pathinfo, -1) !== '/') { - return $this->redirect($pathinfo.'/', 'hey'); + return array_replace($ret, $this->redirect($pathinfo.'/', 'hey')); } - return array('_route' => 'hey'); + return $ret; } // overridden2 @@ -326,22 +329,24 @@ public function match($pathinfo) // secure if ('/secure' === $pathinfo) { + $ret = array('_route' => 'secure'); $requiredSchemes = array ( 'https' => 0,); if (!isset($requiredSchemes[$scheme])) { - return $this->redirect($pathinfo, 'secure', key($requiredSchemes)); + return array_replace($ret, $this->redirect($pathinfo, 'secure', key($requiredSchemes))); } - return array('_route' => 'secure'); + return $ret; } // nonsecure if ('/nonsecure' === $pathinfo) { + $ret = array('_route' => 'nonsecure'); $requiredSchemes = array ( 'http' => 0,); if (!isset($requiredSchemes[$scheme])) { - return $this->redirect($pathinfo, 'nonsecure', key($requiredSchemes)); + return array_replace($ret, $this->redirect($pathinfo, 'nonsecure', key($requiredSchemes))); } - return array('_route' => 'nonsecure'); + return $ret; } throw 0 < count($allow) ? new MethodNotAllowedException(array_unique($allow)) : new ResourceNotFoundException(); diff --git a/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher5.php b/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher5.php index 1e6824b341b7e..42258149f5f3f 100644 --- a/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher5.php +++ b/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher5.php @@ -61,29 +61,32 @@ public function match($pathinfo) if (0 === strpos($pathinfo, '/a')) { // a_fourth if ('/a/44' === $trimmedPathinfo) { + $ret = array('_route' => 'a_fourth'); if (substr($pathinfo, -1) !== '/') { - return $this->redirect($pathinfo.'/', 'a_fourth'); + return array_replace($ret, $this->redirect($pathinfo.'/', 'a_fourth')); } - return array('_route' => 'a_fourth'); + return $ret; } // a_fifth if ('/a/55' === $trimmedPathinfo) { + $ret = array('_route' => 'a_fifth'); if (substr($pathinfo, -1) !== '/') { - return $this->redirect($pathinfo.'/', 'a_fifth'); + return array_replace($ret, $this->redirect($pathinfo.'/', 'a_fifth')); } - return array('_route' => 'a_fifth'); + return $ret; } // a_sixth if ('/a/66' === $trimmedPathinfo) { + $ret = array('_route' => 'a_sixth'); if (substr($pathinfo, -1) !== '/') { - return $this->redirect($pathinfo.'/', 'a_sixth'); + return array_replace($ret, $this->redirect($pathinfo.'/', 'a_sixth')); } - return array('_route' => 'a_sixth'); + return $ret; } } @@ -96,29 +99,32 @@ public function match($pathinfo) if (0 === strpos($pathinfo, '/nested/group')) { // nested_a if ('/nested/group/a' === $trimmedPathinfo) { + $ret = array('_route' => 'nested_a'); if (substr($pathinfo, -1) !== '/') { - return $this->redirect($pathinfo.'/', 'nested_a'); + return array_replace($ret, $this->redirect($pathinfo.'/', 'nested_a')); } - return array('_route' => 'nested_a'); + return $ret; } // nested_b if ('/nested/group/b' === $trimmedPathinfo) { + $ret = array('_route' => 'nested_b'); if (substr($pathinfo, -1) !== '/') { - return $this->redirect($pathinfo.'/', 'nested_b'); + return array_replace($ret, $this->redirect($pathinfo.'/', 'nested_b')); } - return array('_route' => 'nested_b'); + return $ret; } // nested_c if ('/nested/group/c' === $trimmedPathinfo) { + $ret = array('_route' => 'nested_c'); if (substr($pathinfo, -1) !== '/') { - return $this->redirect($pathinfo.'/', 'nested_c'); + return array_replace($ret, $this->redirect($pathinfo.'/', 'nested_c')); } - return array('_route' => 'nested_c'); + return $ret; } } @@ -126,29 +132,32 @@ public function match($pathinfo) elseif (0 === strpos($pathinfo, '/slashed/group')) { // slashed_a if ('/slashed/group' === $trimmedPathinfo) { + $ret = array('_route' => 'slashed_a'); if (substr($pathinfo, -1) !== '/') { - return $this->redirect($pathinfo.'/', 'slashed_a'); + return array_replace($ret, $this->redirect($pathinfo.'/', 'slashed_a')); } - return array('_route' => 'slashed_a'); + return $ret; } // slashed_b if ('/slashed/group/b' === $trimmedPathinfo) { + $ret = array('_route' => 'slashed_b'); if (substr($pathinfo, -1) !== '/') { - return $this->redirect($pathinfo.'/', 'slashed_b'); + return array_replace($ret, $this->redirect($pathinfo.'/', 'slashed_b')); } - return array('_route' => 'slashed_b'); + return $ret; } // slashed_c if ('/slashed/group/c' === $trimmedPathinfo) { + $ret = array('_route' => 'slashed_c'); if (substr($pathinfo, -1) !== '/') { - return $this->redirect($pathinfo.'/', 'slashed_c'); + return array_replace($ret, $this->redirect($pathinfo.'/', 'slashed_c')); } - return array('_route' => 'slashed_c'); + return $ret; } } diff --git a/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher7.php b/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher7.php index 876a90f2da468..4548bcf52d2a7 100644 --- a/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher7.php +++ b/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher7.php @@ -38,11 +38,12 @@ public function match($pathinfo) if (0 === strpos($pathinfo, '/trailing/simple')) { // simple_trailing_slash_no_methods if ('/trailing/simple/no-methods' === $trimmedPathinfo) { + $ret = array('_route' => 'simple_trailing_slash_no_methods'); if (substr($pathinfo, -1) !== '/') { - return $this->redirect($pathinfo.'/', 'simple_trailing_slash_no_methods'); + return array_replace($ret, $this->redirect($pathinfo.'/', 'simple_trailing_slash_no_methods')); } - return array('_route' => 'simple_trailing_slash_no_methods'); + return $ret; } // simple_trailing_slash_GET_method @@ -52,11 +53,12 @@ public function match($pathinfo) goto not_simple_trailing_slash_GET_method; } + $ret = array('_route' => 'simple_trailing_slash_GET_method'); if (substr($pathinfo, -1) !== '/') { - return $this->redirect($pathinfo.'/', 'simple_trailing_slash_GET_method'); + return array_replace($ret, $this->redirect($pathinfo.'/', 'simple_trailing_slash_GET_method')); } - return array('_route' => 'simple_trailing_slash_GET_method'); + return $ret; } not_simple_trailing_slash_GET_method: @@ -67,11 +69,12 @@ public function match($pathinfo) goto not_simple_trailing_slash_HEAD_method; } + $ret = array('_route' => 'simple_trailing_slash_HEAD_method'); if (substr($pathinfo, -1) !== '/') { - return $this->redirect($pathinfo.'/', 'simple_trailing_slash_HEAD_method'); + return array_replace($ret, $this->redirect($pathinfo.'/', 'simple_trailing_slash_HEAD_method')); } - return array('_route' => 'simple_trailing_slash_HEAD_method'); + return $ret; } not_simple_trailing_slash_HEAD_method: @@ -91,11 +94,12 @@ public function match($pathinfo) elseif (0 === strpos($pathinfo, '/trailing/regex')) { // regex_trailing_slash_no_methods if (0 === strpos($pathinfo, '/trailing/regex/no-methods') && preg_match('#^/trailing/regex/no\\-methods/(?P[^/]++)/?$#s', $pathinfo, $matches)) { + $ret = $this->mergeDefaults(array_replace($matches, array('_route' => 'regex_trailing_slash_no_methods')), array ()); if (substr($pathinfo, -1) !== '/') { - return $this->redirect($pathinfo.'/', 'regex_trailing_slash_no_methods'); + return array_replace($ret, $this->redirect($pathinfo.'/', 'regex_trailing_slash_no_methods')); } - return $this->mergeDefaults(array_replace($matches, array('_route' => 'regex_trailing_slash_no_methods')), array ()); + return $ret; } // regex_trailing_slash_GET_method @@ -105,11 +109,12 @@ public function match($pathinfo) goto not_regex_trailing_slash_GET_method; } + $ret = $this->mergeDefaults(array_replace($matches, array('_route' => 'regex_trailing_slash_GET_method')), array ()); if (substr($pathinfo, -1) !== '/') { - return $this->redirect($pathinfo.'/', 'regex_trailing_slash_GET_method'); + return array_replace($ret, $this->redirect($pathinfo.'/', 'regex_trailing_slash_GET_method')); } - return $this->mergeDefaults(array_replace($matches, array('_route' => 'regex_trailing_slash_GET_method')), array ()); + return $ret; } not_regex_trailing_slash_GET_method: @@ -120,11 +125,12 @@ public function match($pathinfo) goto not_regex_trailing_slash_HEAD_method; } + $ret = $this->mergeDefaults(array_replace($matches, array('_route' => 'regex_trailing_slash_HEAD_method')), array ()); if (substr($pathinfo, -1) !== '/') { - return $this->redirect($pathinfo.'/', 'regex_trailing_slash_HEAD_method'); + return array_replace($ret, $this->redirect($pathinfo.'/', 'regex_trailing_slash_HEAD_method')); } - return $this->mergeDefaults(array_replace($matches, array('_route' => 'regex_trailing_slash_HEAD_method')), array ()); + return $ret; } not_regex_trailing_slash_HEAD_method: diff --git a/src/Symfony/Component/Routing/Tests/Matcher/RedirectableUrlMatcherTest.php b/src/Symfony/Component/Routing/Tests/Matcher/RedirectableUrlMatcherTest.php index ba4c6e972f19c..eb9a8492c3e90 100644 --- a/src/Symfony/Component/Routing/Tests/Matcher/RedirectableUrlMatcherTest.php +++ b/src/Symfony/Component/Routing/Tests/Matcher/RedirectableUrlMatcherTest.php @@ -65,8 +65,22 @@ public function testNoSchemaRedirectIfOnOfMultipleSchemesMatches() $matcher = $this->getMockForAbstractClass('Symfony\Component\Routing\Matcher\RedirectableUrlMatcher', array($coll, new RequestContext())); $matcher ->expects($this->never()) + ->method('redirect'); + $matcher->match('/foo'); + } + + public function testRedirectWithParams() + { + $coll = new RouteCollection(); + $coll->add('foo', new Route('/foo/{bar}', array(), array(), array(), '', array('https'))); + + $matcher = $this->getMockForAbstractClass('Symfony\Component\Routing\Matcher\RedirectableUrlMatcher', array($coll, new RequestContext())); + $matcher + ->expects($this->once()) ->method('redirect') + ->with('/foo/baz', 'foo', 'https') + ->will($this->returnValue(array('_route' => 'foo'))) ; - $matcher->match('/foo'); + $this->assertEquals(array('_route' => 'foo', 'bar' => 'baz'), $matcher->match('/foo/baz')); } } From 07c5aa6822286ac0d821e7c4d6378378c942483c Mon Sep 17 00:00:00 2001 From: Maxime Steinhausser Date: Tue, 4 Jul 2017 22:50:18 +0200 Subject: [PATCH 0389/1099] [Validator] Allow to use a property path to get value to compare in comparison constraints --- src/Symfony/Component/Validator/CHANGELOG.md | 1 + .../Constraints/AbstractComparison.php | 19 +++-- .../AbstractComparisonValidator.php | 34 +++++++- .../AbstractComparisonValidatorTestCase.php | 85 ++++++++++++++++++- .../Constraints/EqualToValidatorTest.php | 10 +++ .../GreaterThanOrEqualValidatorTest.php | 11 +++ .../Constraints/GreaterThanValidatorTest.php | 10 +++ .../Constraints/IdenticalToValidatorTest.php | 10 +++ .../LessThanOrEqualValidatorTest.php | 11 +++ .../Constraints/LessThanValidatorTest.php | 10 +++ .../Constraints/NotEqualToValidatorTest.php | 10 +++ .../NotIdenticalToValidatorTest.php | 10 +++ src/Symfony/Component/Validator/composer.json | 2 + 13 files changed, 216 insertions(+), 7 deletions(-) diff --git a/src/Symfony/Component/Validator/CHANGELOG.md b/src/Symfony/Component/Validator/CHANGELOG.md index 2c767cd2ca86a..adffe035fc6f5 100644 --- a/src/Symfony/Component/Validator/CHANGELOG.md +++ b/src/Symfony/Component/Validator/CHANGELOG.md @@ -9,6 +9,7 @@ CHANGELOG * setting the `checkDNS` option of the `Url` constraint to `true` is deprecated in favor of the `Url::CHECK_DNS_TYPE_*` constants values and will throw an exception in Symfony 4.0 * added min/max amount of pixels check to `Image` constraint via `minPixels` and `maxPixels` + * added a new "propertyPath" option to comparison constraints in order to get the value to compare from an array or object 3.3.0 ----- diff --git a/src/Symfony/Component/Validator/Constraints/AbstractComparison.php b/src/Symfony/Component/Validator/Constraints/AbstractComparison.php index e20a8f3fb7b05..c41f371e3ae3a 100644 --- a/src/Symfony/Component/Validator/Constraints/AbstractComparison.php +++ b/src/Symfony/Component/Validator/Constraints/AbstractComparison.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Validator\Constraints; +use Symfony\Component\PropertyAccess\PropertyAccess; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\Exception\ConstraintDefinitionException; @@ -24,6 +25,7 @@ abstract class AbstractComparison extends Constraint { public $message; public $value; + public $propertyPath; /** * {@inheritdoc} @@ -34,11 +36,18 @@ public function __construct($options = null) $options = array(); } - if (is_array($options) && !isset($options['value'])) { - throw new ConstraintDefinitionException(sprintf( - 'The %s constraint requires the "value" option to be set.', - get_class($this) - )); + 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))); + } + + 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))); + } + + 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))); + } } parent::__construct($options); diff --git a/src/Symfony/Component/Validator/Constraints/AbstractComparisonValidator.php b/src/Symfony/Component/Validator/Constraints/AbstractComparisonValidator.php index dbaa5cd0b22d0..95d584bce6873 100644 --- a/src/Symfony/Component/Validator/Constraints/AbstractComparisonValidator.php +++ b/src/Symfony/Component/Validator/Constraints/AbstractComparisonValidator.php @@ -11,8 +11,12 @@ namespace Symfony\Component\Validator\Constraints; +use Symfony\Component\PropertyAccess\Exception\NoSuchPropertyException; +use Symfony\Component\PropertyAccess\PropertyAccess; +use Symfony\Component\PropertyAccess\PropertyAccessor; use Symfony\Component\Validator\Constraint; use Symfony\Component\Validator\ConstraintValidator; +use Symfony\Component\Validator\Exception\ConstraintDefinitionException; use Symfony\Component\Validator\Exception\UnexpectedTypeException; /** @@ -23,6 +27,13 @@ */ abstract class AbstractComparisonValidator extends ConstraintValidator { + private $propertyAccessor; + + public function __construct(PropertyAccessor $propertyAccessor = null) + { + $this->propertyAccessor = $propertyAccessor; + } + /** * {@inheritdoc} */ @@ -36,7 +47,19 @@ public function validate($value, Constraint $constraint) return; } - $comparedValue = $constraint->value; + if ($path = $constraint->propertyPath) { + if (null === $object = $this->context->getObject()) { + return; + } + + try { + $comparedValue = $this->getPropertyAccessor()->getValue($object, $path); + } catch (NoSuchPropertyException $e) { + throw new ConstraintDefinitionException(sprintf('Invalid property path "%s" provided to "%s" constraint: %s', $path, get_class($constraint), $e->getMessage()), 0, $e); + } + } else { + $comparedValue = $constraint->value; + } // Convert strings to DateTimes if comparing another DateTime // This allows to compare with any date/time value supported by @@ -63,6 +86,15 @@ public function validate($value, Constraint $constraint) } } + private function getPropertyAccessor() + { + if (null === $this->propertyAccessor) { + $this->propertyAccessor = PropertyAccess::createPropertyAccessor(); + } + + return $this->propertyAccessor; + } + /** * Compares the two given values to find if their relationship is valid. * diff --git a/src/Symfony/Component/Validator/Tests/Constraints/AbstractComparisonValidatorTestCase.php b/src/Symfony/Component/Validator/Tests/Constraints/AbstractComparisonValidatorTestCase.php index a613d18ead3fb..93898bc6ec89f 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/AbstractComparisonValidatorTestCase.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/AbstractComparisonValidatorTestCase.php @@ -13,6 +13,7 @@ use Symfony\Component\Intl\Util\IntlTestHelper; use Symfony\Component\Validator\Constraint; +use Symfony\Component\Validator\Exception\ConstraintDefinitionException; use Symfony\Component\Validator\Test\ConstraintValidatorTestCase; class ComparisonTest_Class @@ -28,6 +29,11 @@ public function __toString() { return (string) $this->value; } + + public function getValue() + { + return $this->value; + } } /** @@ -76,12 +82,25 @@ public function provideInvalidConstraintOptions() /** * @dataProvider provideInvalidConstraintOptions * @expectedException \Symfony\Component\Validator\Exception\ConstraintDefinitionException + * @expectedExceptionMessage requires either the "value" or "propertyPath" option to be set. */ - public function testThrowsConstraintExceptionIfNoValueOrProperty($options) + public function testThrowsConstraintExceptionIfNoValueOrPropertyPath($options) { $this->createConstraint($options); } + /** + * @expectedException \Symfony\Component\Validator\Exception\ConstraintDefinitionException + * @expectedExceptionMessage requires only one of the "value" or "propertyPath" options to be set, not both. + */ + public function testThrowsConstraintExceptionIfBothValueAndPropertyPath() + { + $this->createConstraint((array( + 'value' => 'value', + 'propertyPath' => 'propertyPath', + ))); + } + /** * @dataProvider provideAllValidComparisons * @@ -113,11 +132,75 @@ public function provideAllValidComparisons() return $comparisons; } + /** + * @dataProvider provideValidComparisonsToPropertyPath + */ + public function testValidComparisonToPropertyPath($comparedValue) + { + $constraint = $this->createConstraint(array('propertyPath' => 'value')); + + $object = new ComparisonTest_Class(5); + + $this->setObject($object); + + $this->validator->validate($comparedValue, $constraint); + + $this->assertNoViolation(); + } + + /** + * @dataProvider provideValidComparisonsToPropertyPath + */ + public function testValidComparisonToPropertyPathOnArray($comparedValue) + { + $constraint = $this->createConstraint(array('propertyPath' => '[root][value]')); + + $this->setObject(array('root' => array('value' => 5))); + + $this->validator->validate($comparedValue, $constraint); + + $this->assertNoViolation(); + } + + public function testNoViolationOnNullObjectWithPropertyPath() + { + $constraint = $this->createConstraint(array('propertyPath' => 'propertyPath')); + + $this->setObject(null); + + $this->validator->validate('some data', $constraint); + + $this->assertNoViolation(); + } + + public function testInvalidValuePath() + { + $constraint = $this->createConstraint(array('propertyPath' => 'foo')); + + if (method_exists($this, 'expectException')) { + $this->expectException(ConstraintDefinitionException::class); + $this->expectExceptionMessage(sprintf('Invalid property path "foo" provided to "%s" constraint', get_class($constraint))); + } else { + $this->setExpectedException(ConstraintDefinitionException::class, sprintf('Invalid property path "foo" provided to "%s" constraint', get_class($constraint))); + } + + $object = new ComparisonTest_Class(5); + + $this->setObject($object); + + $this->validator->validate(5, $constraint); + } + /** * @return array */ abstract public function provideValidComparisons(); + /** + * @return array + */ + abstract public function provideValidComparisonsToPropertyPath(); + /** * @dataProvider provideAllInvalidComparisons * diff --git a/src/Symfony/Component/Validator/Tests/Constraints/EqualToValidatorTest.php b/src/Symfony/Component/Validator/Tests/Constraints/EqualToValidatorTest.php index 5e079ce525058..e47de8fce2e59 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/EqualToValidatorTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/EqualToValidatorTest.php @@ -51,6 +51,16 @@ public function provideValidComparisons() ); } + /** + * {@inheritdoc} + */ + public function provideValidComparisonsToPropertyPath() + { + return array( + array(5), + ); + } + /** * {@inheritdoc} */ diff --git a/src/Symfony/Component/Validator/Tests/Constraints/GreaterThanOrEqualValidatorTest.php b/src/Symfony/Component/Validator/Tests/Constraints/GreaterThanOrEqualValidatorTest.php index f13cbd9d396ac..22fb9b662bad7 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/GreaterThanOrEqualValidatorTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/GreaterThanOrEqualValidatorTest.php @@ -54,6 +54,17 @@ public function provideValidComparisons() ); } + /** + * {@inheritdoc} + */ + public function provideValidComparisonsToPropertyPath() + { + return array( + array(5), + array(6), + ); + } + /** * {@inheritdoc} */ diff --git a/src/Symfony/Component/Validator/Tests/Constraints/GreaterThanValidatorTest.php b/src/Symfony/Component/Validator/Tests/Constraints/GreaterThanValidatorTest.php index 4347473fe006e..08446ec847073 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/GreaterThanValidatorTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/GreaterThanValidatorTest.php @@ -50,6 +50,16 @@ public function provideValidComparisons() ); } + /** + * {@inheritdoc} + */ + public function provideValidComparisonsToPropertyPath() + { + return array( + array(6), + ); + } + /** * {@inheritdoc} */ diff --git a/src/Symfony/Component/Validator/Tests/Constraints/IdenticalToValidatorTest.php b/src/Symfony/Component/Validator/Tests/Constraints/IdenticalToValidatorTest.php index 100600d04bb3b..360eccabc7025 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/IdenticalToValidatorTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/IdenticalToValidatorTest.php @@ -69,6 +69,16 @@ public function provideValidComparisons() return $comparisons; } + /** + * {@inheritdoc} + */ + public function provideValidComparisonsToPropertyPath() + { + return array( + array(5), + ); + } + /** * {@inheritdoc} */ diff --git a/src/Symfony/Component/Validator/Tests/Constraints/LessThanOrEqualValidatorTest.php b/src/Symfony/Component/Validator/Tests/Constraints/LessThanOrEqualValidatorTest.php index bbd0604f84e1c..f31a50e673c8f 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/LessThanOrEqualValidatorTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/LessThanOrEqualValidatorTest.php @@ -56,6 +56,17 @@ public function provideValidComparisons() ); } + /** + * {@inheritdoc} + */ + public function provideValidComparisonsToPropertyPath() + { + return array( + array(4), + array(5), + ); + } + /** * {@inheritdoc} */ diff --git a/src/Symfony/Component/Validator/Tests/Constraints/LessThanValidatorTest.php b/src/Symfony/Component/Validator/Tests/Constraints/LessThanValidatorTest.php index d5a5c7378d8da..a5d69355d7e58 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/LessThanValidatorTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/LessThanValidatorTest.php @@ -50,6 +50,16 @@ public function provideValidComparisons() ); } + /** + * {@inheritdoc} + */ + public function provideValidComparisonsToPropertyPath() + { + return array( + array(4), + ); + } + /** * {@inheritdoc} */ diff --git a/src/Symfony/Component/Validator/Tests/Constraints/NotEqualToValidatorTest.php b/src/Symfony/Component/Validator/Tests/Constraints/NotEqualToValidatorTest.php index fb9aa9f6e8b86..e7031d4c4dfd8 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/NotEqualToValidatorTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/NotEqualToValidatorTest.php @@ -50,6 +50,16 @@ public function provideValidComparisons() ); } + /** + * {@inheritdoc} + */ + public function provideValidComparisonsToPropertyPath() + { + return array( + array(0), + ); + } + /** * {@inheritdoc} */ diff --git a/src/Symfony/Component/Validator/Tests/Constraints/NotIdenticalToValidatorTest.php b/src/Symfony/Component/Validator/Tests/Constraints/NotIdenticalToValidatorTest.php index 7938b0a7e3899..907f36c063290 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/NotIdenticalToValidatorTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/NotIdenticalToValidatorTest.php @@ -53,6 +53,16 @@ public function provideValidComparisons() ); } + /** + * {@inheritdoc} + */ + public function provideValidComparisonsToPropertyPath() + { + return array( + array(0), + ); + } + public function provideAllInvalidComparisons() { $this->setDefaultTimezone('UTC'); diff --git a/src/Symfony/Component/Validator/composer.json b/src/Symfony/Component/Validator/composer.json index f104f94c5fafc..69b39c9c821b0 100644 --- a/src/Symfony/Component/Validator/composer.json +++ b/src/Symfony/Component/Validator/composer.json @@ -30,6 +30,7 @@ "symfony/dependency-injection": "~3.3|~4.0", "symfony/expression-language": "~2.8|~3.0|~4.0", "symfony/cache": "~3.1|~4.0", + "symfony/property-access": "~2.8|~3.0|~4.0", "doctrine/annotations": "~1.0", "doctrine/cache": "~1.0", "egulias/email-validator": "^1.2.8|~2.0" @@ -48,6 +49,7 @@ "symfony/yaml": "", "symfony/config": "", "egulias/email-validator": "Strict (RFC compliant) email validation", + "symfony/property-access": "For accessing properties within comparison constraints", "symfony/expression-language": "For using the Expression validator" }, "autoload": { From 595a225a0f02577e47d2d98d51baf48d194d8b35 Mon Sep 17 00:00:00 2001 From: Roland Franssen Date: Sat, 8 Jul 2017 10:28:14 +0200 Subject: [PATCH 0390/1099] [DI] Remove irrelevant comment from container --- .../Component/DependencyInjection/Container.php | 10 ---------- .../DependencyInjection/Tests/ContainerTest.php | 4 ++-- 2 files changed, 2 insertions(+), 12 deletions(-) diff --git a/src/Symfony/Component/DependencyInjection/Container.php b/src/Symfony/Component/DependencyInjection/Container.php index f6c953f550993..7bf2e36ec2da2 100644 --- a/src/Symfony/Component/DependencyInjection/Container.php +++ b/src/Symfony/Component/DependencyInjection/Container.php @@ -29,16 +29,6 @@ * * Parameter and service keys are case insensitive. * - * A service id can contain lowercased letters, digits, underscores, and dots. - * Underscores are used to separate words, and dots to group services - * under namespaces: - * - *
    - *
  • request
  • - *
  • mysql_session_storage
  • - *
  • symfony.mysql_session_storage
  • - *
- * * A service can also be defined by creating a method named * getXXXService(), where XXX is the camelized version of the id: * diff --git a/src/Symfony/Component/DependencyInjection/Tests/ContainerTest.php b/src/Symfony/Component/DependencyInjection/Tests/ContainerTest.php index 02018c5a0a999..5ec0deed3d3a4 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/ContainerTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/ContainerTest.php @@ -134,8 +134,8 @@ public function testGetServiceIds() public function testSet() { $sc = new Container(); - $sc->set('foo', $foo = new \stdClass()); - $this->assertSame($foo, $sc->get('foo'), '->set() sets a service'); + $sc->set('._. \\o/', $foo = new \stdClass()); + $this->assertSame($foo, $sc->get('._. \\o/'), '->set() sets a service'); } public function testSetWithNullResetTheService() From 632e934cfa6e9b0d0927e113173943b193693f8a Mon Sep 17 00:00:00 2001 From: Roland Franssen Date: Mon, 27 Mar 2017 16:07:30 +0200 Subject: [PATCH 0391/1099] [DI] Allow imports in string format for YAML --- .../Component/DependencyInjection/Loader/YamlFileLoader.php | 5 ++++- .../DependencyInjection/Tests/Fixtures/yaml/bad_import.yml | 2 +- .../DependencyInjection/Tests/Fixtures/yaml/services4.yml | 2 +- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php b/src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php index 7a0123ba21bf5..8ac54173ec5f1 100644 --- a/src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php +++ b/src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php @@ -177,7 +177,10 @@ private function parseImports(array $content, $file) $defaultDirectory = dirname($file); foreach ($content['imports'] as $import) { if (!is_array($import)) { - throw new InvalidArgumentException(sprintf('The values in the "imports" key should be arrays in %s. Check your YAML syntax.', $file)); + $import = array('resource' => $import); + } + if (!isset($import['resource'])) { + throw new InvalidArgumentException(sprintf('An import should provide a resource in %s. Check your YAML syntax.', $file)); } $this->setCurrentDir($defaultDirectory); diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/bad_import.yml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/bad_import.yml index 0765dc8dd0856..2dbbcbf2653f3 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/bad_import.yml +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/bad_import.yml @@ -1,2 +1,2 @@ imports: - - foo.yml + - { resource: ~ } diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services4.yml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services4.yml index 92758190befaa..073f55547330e 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services4.yml +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services4.yml @@ -1,5 +1,5 @@ imports: - - { resource: services2.yml } + - services2.yml - { resource: services3.yml } - { resource: "../php/simple.php" } - { resource: "../ini/parameters.ini", class: Symfony\Component\DependencyInjection\Loader\IniFileLoader } From 8a197958cbd300091fce9dbe67852312341bb069 Mon Sep 17 00:00:00 2001 From: Roland Franssen Date: Sat, 8 Jul 2017 21:11:54 +0200 Subject: [PATCH 0392/1099] [WebProfilerBundle] Cleanup profiler leftover --- .../Controller/ProfilerController.php | 28 ------------------- .../Resources/config/routing/profiler.xml | 4 --- .../Resources/views/Profiler/info.html.twig | 15 ---------- 3 files changed, 47 deletions(-) diff --git a/src/Symfony/Bundle/WebProfilerBundle/Controller/ProfilerController.php b/src/Symfony/Bundle/WebProfilerBundle/Controller/ProfilerController.php index 37f47df6a6e40..7ebd04b574c22 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Controller/ProfilerController.php +++ b/src/Symfony/Bundle/WebProfilerBundle/Controller/ProfilerController.php @@ -128,34 +128,6 @@ public function panelAction(Request $request, $token) )), 200, array('Content-Type' => 'text/html')); } - /** - * Displays information page. - * - * @param Request $request The current HTTP Request - * @param string $about The about message - * - * @return Response A Response instance - * - * @throws NotFoundHttpException - */ - public function infoAction(Request $request, $about) - { - if (null === $this->profiler) { - throw new NotFoundHttpException('The profiler must be enabled.'); - } - - $this->profiler->disable(); - - if (null !== $this->cspHandler) { - $this->cspHandler->disableCsp(); - } - - return new Response($this->twig->render('@WebProfiler/Profiler/info.html.twig', array( - 'about' => $about, - 'request' => $request, - )), 200, array('Content-Type' => 'text/html')); - } - /** * Renders the Web Debug Toolbar. * diff --git a/src/Symfony/Bundle/WebProfilerBundle/Resources/config/routing/profiler.xml b/src/Symfony/Bundle/WebProfilerBundle/Resources/config/routing/profiler.xml index 1a4bd39c621a6..0be717b19d6e7 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Resources/config/routing/profiler.xml +++ b/src/Symfony/Bundle/WebProfilerBundle/Resources/config/routing/profiler.xml @@ -16,10 +16,6 @@ web_profiler.controller.profiler:searchBarAction - - web_profiler.controller.profiler:infoAction - - web_profiler.controller.profiler:phpinfoAction diff --git a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/info.html.twig b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/info.html.twig index ef381fe4a73a7..0227532e1208a 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/info.html.twig +++ b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/info.html.twig @@ -1,25 +1,10 @@ {% extends '@WebProfiler/Profiler/layout.html.twig' %} {% set messages = { - 'purge' : { - status: 'success', - title: 'The profiler database was purged successfully', - message: 'Now you need to browse some pages with the Symfony Profiler enabled to collect data.' - }, 'no_token' : { status: 'error', title: (token|default('') == 'latest') ? 'There are no profiles' : 'Token not found', message: (token|default('') == 'latest') ? 'No profiles found in the database.' : 'Token "' ~ token|default('') ~ '" was not found in the database.' - }, - 'upload_error' : { - status: 'error', - title: 'A problem occurred when uploading the data', - message: 'No file given or the file was not uploaded successfully.' - }, - 'already_exists' : { - status: 'error', - title: 'A problem occurred when uploading the data', - message: 'The token already exists in the database.' } } %} From b033e79211663be8e300b4f0635b25722266a798 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Sun, 9 Jul 2017 12:27:07 +0200 Subject: [PATCH 0393/1099] =?UTF-8?q?[FrameworkBundle]=C2=A0fix=20changelo?= =?UTF-8?q?g?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The `framework.serializer.cache` option was also deprecated in Symfony 3.1. This was documented in the upgrade file, but was not reflected in the bundle's changelog. --- src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md b/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md index efee66b41cecf..c1eb01d3284e3 100644 --- a/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md +++ b/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md @@ -21,7 +21,8 @@ CHANGELOG * Deprecated using core form types without dependencies as services * Added `Symfony\Component\HttpHernel\DataCollector\RequestDataCollector::onKernelResponse()` * Added `Symfony\Bundle\FrameworkBundle\DataCollector\RequestDataCollector` - * Deprecated service `serializer.mapping.cache.apc` (use `serializer.mapping.cache.doctrine.apc` instead) + * The `framework.serializer.cache` option and the service `serializer.mapping.cache.apc` have been + deprecated. APCu should now be automatically used when available. 3.0.0 ----- From 5dbee5b5bde64e8097da9037d3ac9f267024f320 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Sun, 9 Jul 2017 14:41:10 +0200 Subject: [PATCH 0394/1099] [HttpKernel] fix DumpDataCollector tests --- .../HttpKernel/Tests/DataCollector/DumpDataCollectorTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/HttpKernel/Tests/DataCollector/DumpDataCollectorTest.php b/src/Symfony/Component/HttpKernel/Tests/DataCollector/DumpDataCollectorTest.php index 9a306e533e006..e642e3c33715f 100644 --- a/src/Symfony/Component/HttpKernel/Tests/DataCollector/DumpDataCollectorTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/DataCollector/DumpDataCollectorTest.php @@ -50,7 +50,7 @@ public function testDump() ); $this->assertEquals($xDump, $dump); - $this->assertStringMatchesFormat('a:3:{i:0;a:5:{s:4:"data";O:39:"Symfony\Component\VarDumper\Cloner\Data":%a', $collector->serialize()); + $this->assertStringMatchesFormat('a:3:{i:0;a:5:{s:4:"data";%c:39:"Symfony\Component\VarDumper\Cloner\Data":%a', $collector->serialize()); $this->assertSame(0, $collector->getDumpsCount()); $this->assertSame('a:2:{i:0;b:0;i:1;s:5:"UTF-8";}', $collector->serialize()); } From 5a3a24b0ac74ad36ca380fad02ef6aed11909a65 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Sun, 9 Jul 2017 15:51:00 +0200 Subject: [PATCH 0395/1099] allow to configure custom formats in XML configs --- .../Resources/config/schema/twig-1.0.xsd | 15 ++++++++++++++ .../Fixtures/php/formats.php | 14 +++++++++++++ .../Fixtures/xml/formats.xml | 12 +++++++++++ .../Fixtures/yml/formats.yml | 9 +++++++++ .../DependencyInjection/TwigExtensionTest.php | 20 +++++++++++++++++++ 5 files changed, 70 insertions(+) create mode 100644 src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/Fixtures/php/formats.php create mode 100644 src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/Fixtures/xml/formats.xml create mode 100644 src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/Fixtures/yml/formats.yml diff --git a/src/Symfony/Bundle/TwigBundle/Resources/config/schema/twig-1.0.xsd b/src/Symfony/Bundle/TwigBundle/Resources/config/schema/twig-1.0.xsd index 474b6c9721e0c..70b6de5c38d5c 100644 --- a/src/Symfony/Bundle/TwigBundle/Resources/config/schema/twig-1.0.xsd +++ b/src/Symfony/Bundle/TwigBundle/Resources/config/schema/twig-1.0.xsd @@ -9,6 +9,9 @@ + + + @@ -28,6 +31,18 @@ + + + + + + + + + + + + diff --git a/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/Fixtures/php/formats.php b/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/Fixtures/php/formats.php new file mode 100644 index 0000000000000..630a9a9edc01a --- /dev/null +++ b/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/Fixtures/php/formats.php @@ -0,0 +1,14 @@ +loadFromExtension('twig', array( + 'date' => array( + 'format' => 'Y-m-d', + 'interval_format' => '%d', + 'timezone' => 'Europe/Berlin', + ), + 'number_format' => array( + 'decimals' => 2, + 'decimal_point' => ',', + 'thousands_separator' => '.', + ), +)); diff --git a/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/Fixtures/xml/formats.xml b/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/Fixtures/xml/formats.xml new file mode 100644 index 0000000000000..1ab39e49229cd --- /dev/null +++ b/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/Fixtures/xml/formats.xml @@ -0,0 +1,12 @@ + + + + + + + + diff --git a/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/Fixtures/yml/formats.yml b/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/Fixtures/yml/formats.yml new file mode 100644 index 0000000000000..290921630f9e6 --- /dev/null +++ b/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/Fixtures/yml/formats.yml @@ -0,0 +1,9 @@ +twig: + date: + format: Y-m-d + interval_format: '%d' + timezone: Europe/Berlin + number_format: + decimals: 2 + decimal_point: ',' + thousands_separator: . diff --git a/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/TwigExtensionTest.php b/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/TwigExtensionTest.php index f5809cc045c42..f385ec04fd28c 100644 --- a/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/TwigExtensionTest.php +++ b/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/TwigExtensionTest.php @@ -150,6 +150,26 @@ public function testLoadDefaultTemplateEscapingGuesserConfiguration($format) $this->assertEquals('name', $options['autoescape']); } + /** + * @dataProvider getFormats + */ + public function testLoadCustomDateFormats($fileFormat) + { + $container = $this->createContainer(); + $container->registerExtension(new TwigExtension()); + $this->loadFromFile($container, 'formats', $fileFormat); + $this->compileContainer($container); + + $environmentConfigurator = $container->getDefinition('twig.configurator.environment'); + + $this->assertSame('Y-m-d', $environmentConfigurator->getArgument(0)); + $this->assertSame('%d', $environmentConfigurator->getArgument(1)); + $this->assertSame('Europe/Berlin', $environmentConfigurator->getArgument(2)); + $this->assertSame(2, $environmentConfigurator->getArgument(3)); + $this->assertSame(',', $environmentConfigurator->getArgument(4)); + $this->assertSame('.', $environmentConfigurator->getArgument(5)); + } + public function testGlobalsWithDifferentTypesAndValues() { $globals = array( From 9b8d96b8450d420e7a39e42e4004aac10ca3ae1d Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Sun, 9 Jul 2017 20:26:31 +0200 Subject: [PATCH 0396/1099] [Validator] sync upgrade file with latest code changes --- UPGRADE-4.0.md | 4 ---- 1 file changed, 4 deletions(-) diff --git a/UPGRADE-4.0.md b/UPGRADE-4.0.md index e139d902164ca..f552c0806d208 100644 --- a/UPGRADE-4.0.md +++ b/UPGRADE-4.0.md @@ -583,10 +583,6 @@ Validator } ``` - * The default value of the strict option of the `Choice` Constraint has been - changed to `true` as of 4.0. If you need the previous behaviour ensure to - set the option to `false`. - VarDumper --------- From 754d3a7568b1df9aa8871eddc065cc1dcc025a56 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Mon, 10 Jul 2017 10:56:59 +0200 Subject: [PATCH 0397/1099] [HttpKernel][VarDumper] Truncate profiler data & optim perf --- .../DataCollector/FormDataCollector.php | 87 ++++++------------- src/Symfony/Component/Form/composer.json | 6 +- .../DataCollector/DataCollector.php | 43 +++++++-- .../Component/VarDumper/Caster/Caster.php | 13 ++- .../VarDumper/Caster/ExceptionCaster.php | 4 +- .../VarDumper/Cloner/AbstractCloner.php | 16 ++-- 6 files changed, 84 insertions(+), 85 deletions(-) diff --git a/src/Symfony/Component/Form/Extension/DataCollector/FormDataCollector.php b/src/Symfony/Component/Form/Extension/DataCollector/FormDataCollector.php index b088abc7962f6..7540449b96ec5 100644 --- a/src/Symfony/Component/Form/Extension/DataCollector/FormDataCollector.php +++ b/src/Symfony/Component/Form/Extension/DataCollector/FormDataCollector.php @@ -20,11 +20,7 @@ use Symfony\Component\Validator\ConstraintViolationInterface; use Symfony\Component\VarDumper\Caster\Caster; use Symfony\Component\VarDumper\Caster\ClassStub; -use Symfony\Component\VarDumper\Caster\CutStub; -use Symfony\Component\VarDumper\Cloner\ClonerInterface; -use Symfony\Component\VarDumper\Cloner\Data; use Symfony\Component\VarDumper\Cloner\Stub; -use Symfony\Component\VarDumper\Cloner\VarCloner; /** * Data collector for {@link FormInterface} instances. @@ -77,11 +73,6 @@ class FormDataCollector extends DataCollector implements FormDataCollectorInterf */ private $valueExporter; - /** - * @var ClonerInterface - */ - private $cloner; - private $hasVarDumper; public function __construct(FormDataExtractorInterface $dataExtractor) @@ -255,61 +246,33 @@ public function serialize() /** * {@inheritdoc} */ - protected function cloneVar($var, $isClass = false) + protected function getCasters() { - if ($var instanceof Data) { - return $var; - } - if (null === $this->cloner) { - if ($this->hasVarDumper) { - $this->cloner = new VarCloner(); - $this->cloner->setMaxItems(-1); - $this->cloner->addCasters(array( - '*' => function ($v, array $a, Stub $s, $isNested) { - foreach ($a as &$v) { - if (is_object($v) && !$v instanceof \DateTimeInterface) { - $v = new CutStub($v); - } - } - - return $a; - }, - \Exception::class => function (\Exception $e, array $a, Stub $s) { - if (isset($a[$k = "\0Exception\0previous"])) { - unset($a[$k]); - ++$s->cut; - } - - return $a; - }, - FormInterface::class => function (FormInterface $f, array $a) { - return array( - Caster::PREFIX_VIRTUAL.'name' => $f->getName(), - Caster::PREFIX_VIRTUAL.'type_class' => new ClassStub(get_class($f->getConfig()->getType()->getInnerType())), - ); - }, - ConstraintViolationInterface::class => function (ConstraintViolationInterface $v, array $a) { - return array( - Caster::PREFIX_VIRTUAL.'root' => $v->getRoot(), - Caster::PREFIX_VIRTUAL.'path' => $v->getPropertyPath(), - Caster::PREFIX_VIRTUAL.'value' => $v->getInvalidValue(), - ); - }, - )); - } else { - @trigger_error(sprintf('Using the %s() method without the VarDumper component is deprecated since version 3.2 and won\'t be supported in 4.0. Install symfony/var-dumper version 3.2 or above.', __METHOD__), E_USER_DEPRECATED); - $this->cloner = false; - } - } - if (false !== $this->cloner) { - return $this->cloner->cloneVar($var, Caster::EXCLUDE_VERBOSE); - } - - if (null === $this->valueExporter) { - $this->valueExporter = new ValueExporter(); - } + return parent::getCasters() + array( + \Exception::class => function (\Exception $e, array $a, Stub $s) { + foreach (array("\0Exception\0previous", "\0Exception\0trace") as $k) { + if (isset($a[$k])) { + unset($a[$k]); + ++$s->cut; + } + } - return $this->valueExporter->exportValue($var); + return $a; + }, + FormInterface::class => function (FormInterface $f, array $a) { + return array( + Caster::PREFIX_VIRTUAL.'name' => $f->getName(), + Caster::PREFIX_VIRTUAL.'type_class' => new ClassStub(get_class($f->getConfig()->getType()->getInnerType())), + ); + }, + ConstraintViolationInterface::class => function (ConstraintViolationInterface $v, array $a) { + return array( + Caster::PREFIX_VIRTUAL.'root' => $v->getRoot(), + Caster::PREFIX_VIRTUAL.'path' => $v->getPropertyPath(), + Caster::PREFIX_VIRTUAL.'value' => $v->getInvalidValue(), + ); + }, + ); } private function &recursiveBuildPreliminaryFormTree(FormInterface $form, array &$outputByHash) diff --git a/src/Symfony/Component/Form/composer.json b/src/Symfony/Component/Form/composer.json index 5a1d6ef9cba51..85250b87f357b 100644 --- a/src/Symfony/Component/Form/composer.json +++ b/src/Symfony/Component/Form/composer.json @@ -29,7 +29,7 @@ "symfony/dependency-injection": "~3.3", "symfony/config": "~2.7|~3.0", "symfony/http-foundation": "~2.8|~3.0", - "symfony/http-kernel": "~2.8|~3.0", + "symfony/http-kernel": "^3.3.5", "symfony/security-csrf": "~2.8|~3.0", "symfony/translation": "~2.8|~3.0", "symfony/var-dumper": "~3.3" @@ -39,8 +39,8 @@ "symfony/dependency-injection": "<3.3", "symfony/doctrine-bridge": "<2.7", "symfony/framework-bundle": "<2.7", - "symfony/twig-bridge": "<2.7", - "symfony/var-dumper": "<3.3" + "symfony/http-kernel": "<3.3.5", + "symfony/twig-bridge": "<2.7" }, "suggest": { "symfony/validator": "For form validation.", diff --git a/src/Symfony/Component/HttpKernel/DataCollector/DataCollector.php b/src/Symfony/Component/HttpKernel/DataCollector/DataCollector.php index 0d574eae3b3af..770c985637da6 100644 --- a/src/Symfony/Component/HttpKernel/DataCollector/DataCollector.php +++ b/src/Symfony/Component/HttpKernel/DataCollector/DataCollector.php @@ -12,9 +12,10 @@ namespace Symfony\Component\HttpKernel\DataCollector; use Symfony\Component\HttpKernel\DataCollector\Util\ValueExporter; -use Symfony\Component\VarDumper\Caster\ClassStub; +use Symfony\Component\VarDumper\Caster\CutStub; use Symfony\Component\VarDumper\Cloner\ClonerInterface; use Symfony\Component\VarDumper\Cloner\Data; +use Symfony\Component\VarDumper\Cloner\Stub; use Symfony\Component\VarDumper\Cloner\VarCloner; /** @@ -37,7 +38,7 @@ abstract class DataCollector implements DataCollectorInterface, \Serializable /** * @var ClonerInterface */ - private static $cloner; + private $cloner; public function serialize() { @@ -61,16 +62,20 @@ public function unserialize($data) */ protected function cloneVar($var) { - if (null === self::$cloner) { - if (class_exists(ClassStub::class)) { - self::$cloner = new VarCloner(); - self::$cloner->setMaxItems(-1); + if ($var instanceof Data) { + return $var; + } + if (null === $this->cloner) { + if (class_exists(CutStub::class)) { + $this->cloner = new VarCloner(); + $this->cloner->setMaxItems(-1); + $this->cloner->addCasters(self::getCasters()); } else { @trigger_error(sprintf('Using the %s() method without the VarDumper component is deprecated since version 3.2 and won\'t be supported in 4.0. Install symfony/var-dumper version 3.2 or above.', __METHOD__), E_USER_DEPRECATED); - self::$cloner = false; + $this->cloner = false; } } - if (false === self::$cloner) { + if (false === $this->cloner) { if (null === $this->valueExporter) { $this->valueExporter = new ValueExporter(); } @@ -78,7 +83,7 @@ protected function cloneVar($var) return $this->valueExporter->exportValue($var); } - return self::$cloner->cloneVar($var); + return $this->cloner->cloneVar($var); } /** @@ -100,4 +105,24 @@ protected function varToString($var) return $this->valueExporter->exportValue($var); } + + /** + * @return callable[] The casters to add to the cloner + */ + protected function getCasters() + { + return array( + '*' => function ($v, array $a, Stub $s, $isNested) { + if (!$v instanceof Stub) { + foreach ($a as $k => $v) { + if (is_object($v) && !$v instanceof \DateTimeInterface && !$v instanceof Stub) { + $a[$k] = new CutStub($v); + } + } + } + + return $a; + }, + ); + } } diff --git a/src/Symfony/Component/VarDumper/Caster/Caster.php b/src/Symfony/Component/VarDumper/Caster/Caster.php index a0efa651b9258..b1e67cb30a035 100644 --- a/src/Symfony/Component/VarDumper/Caster/Caster.php +++ b/src/Symfony/Component/VarDumper/Caster/Caster.php @@ -65,11 +65,20 @@ public static function castObject($obj, $class, $hasDebugInfo = false) } if ($a) { + static $publicProperties = array(); + $i = 0; $prefixedKeys = array(); foreach ($a as $k => $v) { - if (isset($k[0]) && "\0" !== $k[0] && !property_exists($class, $k)) { - $prefixedKeys[$i] = self::PREFIX_DYNAMIC.$k; + if (isset($k[0]) && "\0" !== $k[0]) { + if (!isset($publicProperties[$class])) { + foreach (get_class_vars($class) as $prop => $v) { + $publicProperties[$class][$prop] = true; + } + } + if (!isset($publicProperties[$class][$k])) { + $prefixedKeys[$i] = self::PREFIX_DYNAMIC.$k; + } } elseif (isset($k[16]) && "\0" === $k[16] && 0 === strpos($k, "\0class@anonymous\0")) { $prefixedKeys[$i] = "\0".get_parent_class($class).'@anonymous'.strrchr($k, "\0"); } diff --git a/src/Symfony/Component/VarDumper/Caster/ExceptionCaster.php b/src/Symfony/Component/VarDumper/Caster/ExceptionCaster.php index f1f58c0a87263..6786cf6a11803 100644 --- a/src/Symfony/Component/VarDumper/Caster/ExceptionCaster.php +++ b/src/Symfony/Component/VarDumper/Caster/ExceptionCaster.php @@ -102,7 +102,7 @@ public static function castSilencedErrorContext(SilencedErrorContext $e, array $ } unset($a[$sPrefix.'file'], $a[$sPrefix.'line'], $a[$sPrefix.'trace']); - $a[Caster::PREFIX_VIRTUAL.'trace'] = new TraceStub($trace); + $a[Caster::PREFIX_VIRTUAL.'trace'] = new TraceStub($trace, self::$traceArgs); return $a; } @@ -256,7 +256,7 @@ private static function filterExceptionArray($xClass, array $a, $xPrefix, $filte $trace = array(); } - if (!($filter & Caster::EXCLUDE_VERBOSE)) { + if (!($filter & Caster::EXCLUDE_VERBOSE) && $trace) { if (isset($a[Caster::PREFIX_PROTECTED.'file'], $a[Caster::PREFIX_PROTECTED.'line'])) { self::traceUnshift($trace, $xClass, $a[Caster::PREFIX_PROTECTED.'file'], $a[Caster::PREFIX_PROTECTED.'line']); } diff --git a/src/Symfony/Component/VarDumper/Cloner/AbstractCloner.php b/src/Symfony/Component/VarDumper/Cloner/AbstractCloner.php index c07ae491c5dc0..45e0b6ad771b1 100644 --- a/src/Symfony/Component/VarDumper/Cloner/AbstractCloner.php +++ b/src/Symfony/Component/VarDumper/Cloner/AbstractCloner.php @@ -209,15 +209,17 @@ public function cloneVar($var, $filter = 0) }); $this->filter = $filter; + if ($gc = gc_enabled()) { + gc_disable(); + } try { $data = $this->doClone($var); - } catch (\Exception $e) { - } - restore_error_handler(); - $this->prevErrorHandler = null; - - if (isset($e)) { - throw $e; + } finally { + if ($gc) { + gc_enable(); + } + restore_error_handler(); + $this->prevErrorHandler = null; } return new Data($data); From 64d196adaee02cfa747ac1c7870df295b4db1d48 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9goire=20Pineau?= Date: Fri, 7 Jul 2017 12:05:26 +0200 Subject: [PATCH 0398/1099] [Cache] Added test for ApcuAdapter when using in CLI --- .../Cache/Tests/Adapter/ApcuAdapterTest.php | 28 ++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/Cache/Tests/Adapter/ApcuAdapterTest.php b/src/Symfony/Component/Cache/Tests/Adapter/ApcuAdapterTest.php index 50206bb278b52..8c6eacf4bbec5 100644 --- a/src/Symfony/Component/Cache/Tests/Adapter/ApcuAdapterTest.php +++ b/src/Symfony/Component/Cache/Tests/Adapter/ApcuAdapterTest.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Cache\Tests\Adapter; +use Psr\Log\NullLogger; use Symfony\Component\Cache\Adapter\ApcuAdapter; class ApcuAdapterTest extends AdapterTestCase @@ -23,9 +24,14 @@ class ApcuAdapterTest extends AdapterTestCase public function createCachePool($defaultLifetime = 0) { - if (!function_exists('apcu_fetch') || !ini_get('apc.enabled') || ('cli' === PHP_SAPI && !ini_get('apc.enable_cli'))) { + if (!function_exists('apcu_fetch') || !ini_get('apc.enabled')) { $this->markTestSkipped('APCu extension is required.'); } + if ('cli' === PHP_SAPI && !ini_get('apc.enable_cli')) { + if ('testWithCliSapi' !== $this->getName()) { + $this->markTestSkipped('APCu extension is required.'); + } + } if ('\\' === DIRECTORY_SEPARATOR) { $this->markTestSkipped('Fails transiently on Windows.'); } @@ -70,4 +76,24 @@ public function testVersion() $this->assertFalse($item->isHit()); $this->assertNull($item->get()); } + + public function testWithCliSapi() + { + try { + // disable PHPUnit error handler to mimic a production environment + $isCalled = false; + set_error_handler(function () use (&$isCalled) { + $isCalled = true; + }); + $pool = new ApcuAdapter(str_replace('\\', '.', __CLASS__)); + $pool->setLogger(new NullLogger()); + + $item = $pool->getItem('foo'); + $item->isHit(); + $pool->save($item->set('bar')); + $this->assertFalse($isCalled); + } finally { + restore_error_handler(); + } + } } From 0b349aee18147e745f0b2be2fff3d2f8345f18c4 Mon Sep 17 00:00:00 2001 From: Alessandro Chitolina Date: Sun, 9 Jul 2017 01:59:34 +0200 Subject: [PATCH 0399/1099] check _controller attribute is a string before parsing it --- .../ResolveControllerNameSubscriber.php | 2 +- .../ResolveControllerNameSubscriberTest.php | 15 ++++++++++++--- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/EventListener/ResolveControllerNameSubscriber.php b/src/Symfony/Bundle/FrameworkBundle/EventListener/ResolveControllerNameSubscriber.php index b083bb7ba8723..6072061dbac04 100644 --- a/src/Symfony/Bundle/FrameworkBundle/EventListener/ResolveControllerNameSubscriber.php +++ b/src/Symfony/Bundle/FrameworkBundle/EventListener/ResolveControllerNameSubscriber.php @@ -33,7 +33,7 @@ public function __construct(ControllerNameParser $parser) public function onKernelRequest(GetResponseEvent $event) { $controller = $event->getRequest()->attributes->get('_controller'); - if ($controller && false === strpos($controller, '::') && 2 === substr_count($controller, ':')) { + if (is_string($controller) && false === strpos($controller, '::') && 2 === substr_count($controller, ':')) { // controller in the a:b:c notation then $event->getRequest()->attributes->set('_controller', $this->parser->parse($controller)); } diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/EventListener/ResolveControllerNameSubscriberTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/EventListener/ResolveControllerNameSubscriberTest.php index e5cc6d28a4e9d..338c1ec81a5c0 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/EventListener/ResolveControllerNameSubscriberTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/EventListener/ResolveControllerNameSubscriberTest.php @@ -37,7 +37,10 @@ public function testReplacesControllerAttribute() $this->assertEquals('App\\Final\\Format::methodName', $request->attributes->get('_controller')); } - public function testSkipsOtherControllerFormats() + /** + * @dataProvider provideSkippedControllers + */ + public function testSkipsOtherControllerFormats($controller) { $parser = $this->getMockBuilder(ControllerNameParser::class)->disableOriginalConstructor()->getMock(); $parser->expects($this->never()) @@ -45,10 +48,16 @@ public function testSkipsOtherControllerFormats() $httpKernel = $this->getMockBuilder(HttpKernelInterface::class)->getMock(); $request = new Request(); - $request->attributes->set('_controller', 'Other:format'); + $request->attributes->set('_controller', $controller); $subscriber = new ResolveControllerNameSubscriber($parser); $subscriber->onKernelRequest(new GetResponseEvent($httpKernel, $request, HttpKernelInterface::MASTER_REQUEST)); - $this->assertEquals('Other:format', $request->attributes->get('_controller')); + $this->assertEquals($controller, $request->attributes->get('_controller')); + } + + public function provideSkippedControllers() + { + yield array('Other:format'); + yield array(function () {}); } } From 9380614de9a7f7ef226e94d22611153070b14e83 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Mon, 10 Jul 2017 19:31:39 +0200 Subject: [PATCH 0400/1099] do not wire namespaces for the ArrayAdapter --- .../Compiler/CachePoolPass.php | 3 ++- .../Compiler/CachePoolPassTest.php | 19 +++++++++++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/CachePoolPass.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/CachePoolPass.php index db1430eb49b13..eda6f936bf7b5 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/CachePoolPass.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/CachePoolPass.php @@ -11,6 +11,7 @@ namespace Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler; +use Symfony\Component\Cache\Adapter\ArrayAdapter; use Symfony\Component\Cache\Adapter\RedisAdapter; use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; use Symfony\Component\DependencyInjection\ContainerBuilder; @@ -70,7 +71,7 @@ public function process(ContainerBuilder $container) } $i = 0; foreach ($attributes as $attr) { - if (isset($tags[0][$attr])) { + if (isset($tags[0][$attr]) && ('namespace' !== $attr || ArrayAdapter::class !== $adapter->getClass())) { $pool->replaceArgument($i++, $tags[0][$attr]); } unset($tags[0][$attr]); diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/CachePoolPassTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/CachePoolPassTest.php index 6fe6b30eb36c4..e9b9bbc778cac 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/CachePoolPassTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/CachePoolPassTest.php @@ -13,6 +13,7 @@ use PHPUnit\Framework\TestCase; use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\CachePoolPass; +use Symfony\Component\Cache\Adapter\ArrayAdapter; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\DependencyInjection\DefinitionDecorator; @@ -49,6 +50,24 @@ public function testNamespaceArgumentIsReplaced() $this->assertSame('D07rhFx97S', $cachePool->getArgument(0)); } + public function testNamespaceArgumentIsNotReplacedIfArrayAdapterIsUsed() + { + $container = new ContainerBuilder(); + $container->setParameter('kernel.environment', 'prod'); + $container->setParameter('kernel.name', 'app'); + $container->setParameter('kernel.root_dir', 'foo'); + + $container->register('cache.adapter.array', ArrayAdapter::class)->addArgument(0); + + $cachePool = new DefinitionDecorator('cache.adapter.array'); + $cachePool->addTag('cache.pool'); + $container->setDefinition('app.cache_pool', $cachePool); + + $this->cachePoolPass->process($container); + + $this->assertCount(0, $container->getDefinition('app.cache_pool')->getArguments()); + } + public function testArgsAreReplaced() { $container = new ContainerBuilder(); From 85766c9b5e12b945067a840b0ddb9491194fe3dc Mon Sep 17 00:00:00 2001 From: Dany Maillard Date: Mon, 10 Jul 2017 23:04:06 +0200 Subject: [PATCH 0401/1099] Add exculde verbosity test --- .../Tests/Caster/ExceptionCasterTest.php | 35 ++++++++++++++----- 1 file changed, 26 insertions(+), 9 deletions(-) diff --git a/src/Symfony/Component/VarDumper/Tests/Caster/ExceptionCasterTest.php b/src/Symfony/Component/VarDumper/Tests/Caster/ExceptionCasterTest.php index 3f6a2e8ec3ff1..4e1e3682dc9f3 100644 --- a/src/Symfony/Component/VarDumper/Tests/Caster/ExceptionCasterTest.php +++ b/src/Symfony/Component/VarDumper/Tests/Caster/ExceptionCasterTest.php @@ -12,6 +12,7 @@ namespace Symfony\Component\VarDumper\Tests\Caster; use PHPUnit\Framework\TestCase; +use Symfony\Component\VarDumper\Caster\Caster; use Symfony\Component\VarDumper\Caster\ExceptionCaster; use Symfony\Component\VarDumper\Caster\FrameStub; use Symfony\Component\VarDumper\Cloner\VarCloner; @@ -43,9 +44,9 @@ public function testDefaultSettings() #message: "foo" #code: 0 #file: "%sExceptionCasterTest.php" - #line: 27 + #line: 28 trace: { - %sExceptionCasterTest.php:27: { + %sExceptionCasterTest.php:28: { : { : return new \Exception(''.$msg); : } @@ -72,7 +73,7 @@ public function testSeek() $expectedDump = <<<'EODUMP' { - %sExceptionCasterTest.php:27: { + %sExceptionCasterTest.php:28: { : { : return new \Exception(''.$msg); : } @@ -101,9 +102,9 @@ public function testNoArgs() #message: "1" #code: 0 #file: "%sExceptionCasterTest.php" - #line: 27 + #line: 28 trace: { - %sExceptionCasterTest.php:27: { + %sExceptionCasterTest.php:28: { : { : return new \Exception(''.$msg); : } @@ -129,9 +130,9 @@ public function testNoSrcContext() #message: "1" #code: 0 #file: "%sExceptionCasterTest.php" - #line: 27 + #line: 28 trace: { - %sExceptionCasterTest.php: 27 + %sExceptionCasterTest.php: 28 %sExceptionCasterTest.php: %d %A EODUMP; @@ -157,10 +158,10 @@ public function testHtmlDump() #code: 0 #file: "%s%eVarDumper%eTests%eCaster%eExceptionCasterTest.php" - #line: 27 + #line: 28 trace: { %s%eVarDumper%eTests%eCaster%eExceptionCasterTest.php: 27 +Stack level %d.">%s%eVarDumper%eTests%eCaster%eExceptionCasterTest.php: 28 …%d } } @@ -222,4 +223,20 @@ class: "__TwigTemplate_VarDumperFixture_u75a09" $this->assertDumpMatchesFormat($expectedDump, $f); } + + public function testExcludeVerbosity() + { + $e = $this->getTestException('foo'); + + $expectedDump = <<<'EODUMP' +Exception { + #message: "foo" + #code: 0 + #file: "%sExceptionCasterTest.php" + #line: 28 +} +EODUMP; + + $this->assertDumpMatchesFormat($expectedDump, $e, Caster::EXCLUDE_VERBOSE); + } } From 4c1fdd4edfca4523837e49a390b8a682bab7de50 Mon Sep 17 00:00:00 2001 From: Tobias Schultze Date: Sun, 12 Jun 2016 18:04:21 +0200 Subject: [PATCH 0402/1099] [Routing] also add matched params for redirect due to trailing slash --- .../Routing/RedirectableUrlMatcherTest.php | 2 +- src/Symfony/Component/Routing/CHANGELOG.md | 1 + .../Matcher/Dumper/PhpMatcherDumper.php | 5 ++-- .../Matcher/RedirectableUrlMatcher.php | 4 ++-- .../Component/Routing/Matcher/UrlMatcher.php | 8 +------ .../Matcher/RedirectableUrlMatcherTest.php | 23 +++++++++++++++---- 6 files changed, 27 insertions(+), 16 deletions(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Routing/RedirectableUrlMatcherTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Routing/RedirectableUrlMatcherTest.php index fb5395ea6d26d..438ca2538df8e 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Routing/RedirectableUrlMatcherTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Routing/RedirectableUrlMatcherTest.php @@ -33,7 +33,7 @@ public function testRedirectWhenNoSlash() 'scheme' => null, 'httpPort' => $context->getHttpPort(), 'httpsPort' => $context->getHttpsPort(), - '_route' => null, + '_route' => 'foo', ), $matcher->match('/foo') ); diff --git a/src/Symfony/Component/Routing/CHANGELOG.md b/src/Symfony/Component/Routing/CHANGELOG.md index 07f8280fe51ed..b79318e29a261 100644 --- a/src/Symfony/Component/Routing/CHANGELOG.md +++ b/src/Symfony/Component/Routing/CHANGELOG.md @@ -5,6 +5,7 @@ CHANGELOG ----- * Added support for prioritized routing loaders. + * Add matched and default parameters to redirect responses 3.3.0 ----- diff --git a/src/Symfony/Component/Routing/Matcher/Dumper/PhpMatcherDumper.php b/src/Symfony/Component/Routing/Matcher/Dumper/PhpMatcherDumper.php index 9a221e6c61cfe..cfe8459f4a425 100644 --- a/src/Symfony/Component/Routing/Matcher/Dumper/PhpMatcherDumper.php +++ b/src/Symfony/Component/Routing/Matcher/Dumper/PhpMatcherDumper.php @@ -333,7 +333,8 @@ private function compileRoute(Route $route, $name, $supportsRedirections, $paren } } - $retOffset = strlen($code); + // the offset where the return value is appended below, with indendation + $retOffset = 12 + strlen($code); // optimize parameters array if ($matches || $hostMatches) { @@ -385,7 +386,7 @@ private function compileRoute(Route $route, $name, $supportsRedirections, $paren if ($hasTrailingSlash || $schemes) { $code .= " return \$ret;\n"; } else { - $code = substr_replace($code, 'return', $retOffset + 12, 6); + $code = substr_replace($code, 'return', $retOffset, 6); } $code .= " }\n"; diff --git a/src/Symfony/Component/Routing/Matcher/RedirectableUrlMatcher.php b/src/Symfony/Component/Routing/Matcher/RedirectableUrlMatcher.php index 900c59fa37392..3770a9c24c5e5 100644 --- a/src/Symfony/Component/Routing/Matcher/RedirectableUrlMatcher.php +++ b/src/Symfony/Component/Routing/Matcher/RedirectableUrlMatcher.php @@ -32,9 +32,9 @@ public function match($pathinfo) } try { - parent::match($pathinfo.'/'); + $parameters = parent::match($pathinfo.'/'); - return $this->redirect($pathinfo.'/', null); + return array_replace($parameters, $this->redirect($pathinfo.'/', isset($parameters['_route']) ? $parameters['_route'] : null)); } catch (ResourceNotFoundException $e2) { throw $e; } diff --git a/src/Symfony/Component/Routing/Matcher/UrlMatcher.php b/src/Symfony/Component/Routing/Matcher/UrlMatcher.php index f90555643a357..df80226cc4f94 100644 --- a/src/Symfony/Component/Routing/Matcher/UrlMatcher.php +++ b/src/Symfony/Component/Routing/Matcher/UrlMatcher.php @@ -163,17 +163,11 @@ protected function matchCollection($pathinfo, RouteCollection $routes) $status = $this->handleRouteRequirements($pathinfo, $name, $route); - if (self::ROUTE_MATCH === $status[0]) { - $attributes = array_replace($matches, $hostMatches, (array) $status[1]); - - return $this->mergeDefaults($attributes, $route->getDefaults()); - } - if (self::REQUIREMENT_MISMATCH === $status[0]) { continue; } - return $this->getAttributes($route, $name, array_replace($matches, $hostMatches)); + return $this->getAttributes($route, $name, array_replace($matches, $hostMatches, isset($status[1]) ? $status[1] : array())); } } diff --git a/src/Symfony/Component/Routing/Tests/Matcher/RedirectableUrlMatcherTest.php b/src/Symfony/Component/Routing/Tests/Matcher/RedirectableUrlMatcherTest.php index eb9a8492c3e90..ddd2133e9614e 100644 --- a/src/Symfony/Component/Routing/Tests/Matcher/RedirectableUrlMatcherTest.php +++ b/src/Symfony/Component/Routing/Tests/Matcher/RedirectableUrlMatcherTest.php @@ -24,7 +24,7 @@ public function testRedirectWhenNoSlash() $coll->add('foo', new Route('/foo/')); $matcher = $this->getMockForAbstractClass('Symfony\Component\Routing\Matcher\RedirectableUrlMatcher', array($coll, new RequestContext())); - $matcher->expects($this->once())->method('redirect'); + $matcher->expects($this->once())->method('redirect')->will($this->returnValue(array())); $matcher->match('/foo'); } @@ -69,7 +69,7 @@ public function testNoSchemaRedirectIfOnOfMultipleSchemesMatches() $matcher->match('/foo'); } - public function testRedirectWithParams() + public function testSchemeRedirectWithParams() { $coll = new RouteCollection(); $coll->add('foo', new Route('/foo/{bar}', array(), array(), array(), '', array('https'))); @@ -79,8 +79,23 @@ public function testRedirectWithParams() ->expects($this->once()) ->method('redirect') ->with('/foo/baz', 'foo', 'https') - ->will($this->returnValue(array('_route' => 'foo'))) + ->will($this->returnValue(array('redirect' => 'value'))) + ; + $this->assertEquals(array('_route' => 'foo', 'bar' => 'baz', 'redirect' => 'value'), $matcher->match('/foo/baz')); + } + + public function testSlashRedirectWithParams() + { + $coll = new RouteCollection(); + $coll->add('foo', new Route('/foo/{bar}/')); + + $matcher = $this->getMockForAbstractClass('Symfony\Component\Routing\Matcher\RedirectableUrlMatcher', array($coll, new RequestContext())); + $matcher + ->expects($this->once()) + ->method('redirect') + ->with('/foo/baz/', 'foo', null) + ->will($this->returnValue(array('redirect' => 'value'))) ; - $this->assertEquals(array('_route' => 'foo', 'bar' => 'baz'), $matcher->match('/foo/baz')); + $this->assertEquals(array('_route' => 'foo', 'bar' => 'baz', 'redirect' => 'value'), $matcher->match('/foo/baz')); } } From ca3ff88361cc64ca6f23a02418c3331014348cff Mon Sep 17 00:00:00 2001 From: Javier Eguiluz Date: Sun, 9 Jul 2017 19:50:49 +0200 Subject: [PATCH 0403/1099] Don't display the Symfony debug toolbar when printing the page --- .../Resources/views/Profiler/toolbar.css.twig | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/toolbar.css.twig b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/toolbar.css.twig index c148954f5a9c8..16a3310d77178 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/toolbar.css.twig +++ b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/toolbar.css.twig @@ -527,3 +527,10 @@ padding: 5px 0; margin-right: 10px; } + +/***** Media query print: Do not print the Toolbar. *****/ +@media print { + .sf-toolbar { + display: none; + } +} From e53508986a76dcda753b695ab9fff3e833937b35 Mon Sep 17 00:00:00 2001 From: Dany Maillard Date: Tue, 11 Jul 2017 00:31:46 +0200 Subject: [PATCH 0404/1099] Add exculde verbosity test --- .../Tests/Caster/ReflectionCasterTest.php | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/VarDumper/Tests/Caster/ReflectionCasterTest.php b/src/Symfony/Component/VarDumper/Tests/Caster/ReflectionCasterTest.php index 5495a78e40f34..b7080b73eda80 100644 --- a/src/Symfony/Component/VarDumper/Tests/Caster/ReflectionCasterTest.php +++ b/src/Symfony/Component/VarDumper/Tests/Caster/ReflectionCasterTest.php @@ -12,6 +12,7 @@ namespace Symfony\Component\VarDumper\Tests\Caster; use PHPUnit\Framework\TestCase; +use Symfony\Component\VarDumper\Caster\Caster; use Symfony\Component\VarDumper\Test\VarDumperTestTrait; use Symfony\Component\VarDumper\Tests\Fixtures\GeneratorDemo; use Symfony\Component\VarDumper\Tests\Fixtures\NotLoadableClass; @@ -77,13 +78,27 @@ public function testClosureCaster() \$b: & 123 } file: "%sReflectionCasterTest.php" - line: "67 to 67" + line: "68 to 68" } EOTXT , $var ); } + public function testClosureCasterExcludingVerbosity() + { + $var = function () {}; + + $expectedDump = <<assertDumpEquals($expectedDump, $var, Caster::EXCLUDE_VERBOSE); + } + public function testReflectionParameter() { $var = new \ReflectionParameter(__NAMESPACE__.'\reflectionParameterFixture', 0); From 8826da1c81caaae0780ea532bc01282538da8534 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Tue, 11 Jul 2017 15:19:03 +0200 Subject: [PATCH 0405/1099] [Process] Fix parsing args on Windows --- src/Symfony/Component/Process/Process.php | 7 +++++-- .../Component/Process/Tests/ProcessTest.php | 18 ++++++++++++++++++ 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/Process/Process.php b/src/Symfony/Component/Process/Process.php index fb12d393abad7..05f88d2d1b112 100644 --- a/src/Symfony/Component/Process/Process.php +++ b/src/Symfony/Component/Process/Process.php @@ -1633,14 +1633,17 @@ private function prepareWindowsCommandLine($cmd, array &$envBackup, array &$env $varCount = 0; $varCache = array(); $cmd = preg_replace_callback( - '/"( + '/"(?:( [^"%!^]*+ (?: (?: !LF! | "(?:\^[%!^])?+" ) [^"%!^]*+ )++ - )"/x', + ) | [^"]*+ )"/x', function ($m) use (&$envBackup, &$env, &$varCache, &$varCount, $uid) { + if (!isset($m[1])) { + return $m[0]; + } if (isset($varCache[$m[0]])) { return $varCache[$m[0]]; } diff --git a/src/Symfony/Component/Process/Tests/ProcessTest.php b/src/Symfony/Component/Process/Tests/ProcessTest.php index e4d084f44efdb..267257117d43d 100644 --- a/src/Symfony/Component/Process/Tests/ProcessTest.php +++ b/src/Symfony/Component/Process/Tests/ProcessTest.php @@ -1484,6 +1484,24 @@ public function testEscapeArgumentWhenInheritEnvDisabled($arg) $this->assertSame($arg, $p->getOutput()); } + public function testRawCommandLine() + { + $p = new Process(sprintf('"%s" -r %s "a" "" "b"', self::$phpBin, escapeshellarg('print_r($argv);'))); + $p->run(); + + $expected = << - + [1] => a + [2] => + [3] => b +) + +EOTXT; + $this->assertSame($expected, $p->getOutput()); + } + public function provideEscapeArgument() { yield array('a"b%c%'); From 63e26fcba6b9bf25e8ecf4561e02173d112bb5a5 Mon Sep 17 00:00:00 2001 From: Roland Franssen Date: Sat, 20 May 2017 22:54:17 +0200 Subject: [PATCH 0406/1099] [DI] Remove deprecated case insensitive service ids --- .../Bridge/Doctrine/ManagerRegistry.php | 3 - .../DependencyInjection/CHANGELOG.md | 1 + .../DependencyInjection/Container.php | 186 ++++++------------ .../DependencyInjection/ContainerBuilder.php | 44 +---- .../Dumper/GraphvizDumper.php | 2 +- .../DependencyInjection/Dumper/PhpDumper.php | 20 -- .../Tests/ContainerBuilderTest.php | 15 ++ .../Tests/ContainerTest.php | 25 +-- .../Tests/CrossCheckTest.php | 6 - .../Tests/Fixtures/containers/container9.php | 6 + .../Tests/Fixtures/graphviz/services9.dot | 4 + .../Tests/Fixtures/php/services33.php | 3 - .../Tests/Fixtures/php/services9.php | 54 ++++- .../Tests/Fixtures/php/services9_compiled.php | 50 ++++- .../Fixtures/php/services_subscriber.php | 4 - .../Tests/Fixtures/xml/services9.xml | 5 + .../Tests/Fixtures/xml/services_case.xml | 15 ++ .../Tests/Fixtures/yaml/services9.yml | 7 + .../Tests/Fixtures/yaml/services_case.yml | 10 + .../Tests/Loader/XmlFileLoaderTest.php | 15 ++ .../Tests/Loader/YamlFileLoaderTest.php | 15 ++ 21 files changed, 261 insertions(+), 229 deletions(-) create mode 100644 src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services_case.xml create mode 100644 src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services_case.yml diff --git a/src/Symfony/Bridge/Doctrine/ManagerRegistry.php b/src/Symfony/Bridge/Doctrine/ManagerRegistry.php index fec62f14e9ca6..6153166e79b8b 100644 --- a/src/Symfony/Bridge/Doctrine/ManagerRegistry.php +++ b/src/Symfony/Bridge/Doctrine/ManagerRegistry.php @@ -49,9 +49,6 @@ protected function resetService($name) } $manager->setProxyInitializer(\Closure::bind( function (&$wrappedInstance, LazyLoadingInterface $manager) use ($name) { - if (isset($this->normalizedIds[$normalizedId = strtolower($name)])) { - $name = $this->normalizedIds[$normalizedId]; - } if (isset($this->aliases[$name])) { $name = $this->aliases[$name]; } diff --git a/src/Symfony/Component/DependencyInjection/CHANGELOG.md b/src/Symfony/Component/DependencyInjection/CHANGELOG.md index f0887c29f099b..7c01c34021d7e 100644 --- a/src/Symfony/Component/DependencyInjection/CHANGELOG.md +++ b/src/Symfony/Component/DependencyInjection/CHANGELOG.md @@ -10,6 +10,7 @@ CHANGELOG * removed `Container::isFrozen` * removed support for dumping an ucompiled container in `PhpDumper` * removed support for generating a dumped `Container` without populating the method map + * removed support for case insensitive service identifiers 3.4.0 ----- diff --git a/src/Symfony/Component/DependencyInjection/Container.php b/src/Symfony/Component/DependencyInjection/Container.php index 3df05883dfab5..fc5dfe9d25a15 100644 --- a/src/Symfony/Component/DependencyInjection/Container.php +++ b/src/Symfony/Component/DependencyInjection/Container.php @@ -26,26 +26,7 @@ * * Services and parameters are simple key/pair stores. * - * Parameter and service keys are case insensitive. - * - * A service id can contain lowercased letters, digits, underscores, and dots. - * Underscores are used to separate words, and dots to group services - * under namespaces: - * - *
    - *
  • request
  • - *
  • mysql_session_storage
  • - *
  • symfony.mysql_session_storage
  • - *
- * - * A service can also be defined by creating a method named - * getXXXService(), where XXX is the camelized version of the id: - * - *
    - *
  • request -> getRequestService()
  • - *
  • mysql_session_storage -> getMysqlSessionStorageService()
  • - *
  • symfony.mysql_session_storage -> getSymfony_MysqlSessionStorageService()
  • - *
+ * Parameter keys are case insensitive. * * The container can have three possible behaviors when a service does not exist: * @@ -70,11 +51,6 @@ class Container implements ResettableContainerInterface protected $aliases = array(); protected $loading = array(); - /** - * @internal - */ - protected $normalizedIds = array(); - private $envCache = array(); private $compiled = false; @@ -171,8 +147,6 @@ public function setParameter($name, $value) */ public function set($id, $service) { - $id = $this->normalizeId($id); - if ('service_container' === $id) { throw new InvalidArgumentException('You cannot set service "service_container".'); } @@ -212,31 +186,24 @@ public function set($id, $service) */ public function has($id) { - for ($i = 2;;) { - if (isset($this->privates[$id])) { - @trigger_error(sprintf('Checking for the existence of the "%s" private service is deprecated since Symfony 3.2 and won\'t be supported anymore in Symfony 4.0.', $id), E_USER_DEPRECATED); - } - if ('service_container' === $id) { - return true; - } - if (isset($this->aliases[$id])) { - $id = $this->aliases[$id]; - } - if (isset($this->services[$id])) { - return true; - } - - if (isset($this->methodMap[$id])) { - return true; - } - - if (--$i && $id !== $normalizedId = $this->normalizeId($id)) { - $id = $normalizedId; - continue; - } + if (isset($this->privates[$id])) { + @trigger_error(sprintf('Checking for the existence of the "%s" private service is deprecated since Symfony 3.2 and won\'t be supported anymore in Symfony 4.0.', $id), E_USER_DEPRECATED); + } + if ('service_container' === $id) { + return true; + } + if (isset($this->aliases[$id])) { + $id = $this->aliases[$id]; + } + if (isset($this->services[$id])) { + return true; + } - return false; + if (isset($this->methodMap[$id])) { + return true; } + + return false; } /** @@ -258,69 +225,60 @@ public function has($id) */ public function get($id, $invalidBehavior = self::EXCEPTION_ON_INVALID_REFERENCE) { - // Attempt to retrieve the service by checking first aliases then - // available services. Service IDs are case insensitive, however since - // this method can be called thousands of times during a request, avoid - // calling $this->normalizeId($id) unless necessary. - for ($i = 2;;) { - if (isset($this->privates[$id])) { - @trigger_error(sprintf('Requesting the "%s" private service is deprecated since Symfony 3.2 and won\'t be supported anymore in Symfony 4.0.', $id), E_USER_DEPRECATED); - } - if ('service_container' === $id) { - return $this; - } - if (isset($this->aliases[$id])) { - $id = $this->aliases[$id]; - } + if (isset($this->privates[$id])) { + @trigger_error(sprintf('Requesting the "%s" private service is deprecated since Symfony 3.2 and won\'t be supported anymore in Symfony 4.0.', $id), E_USER_DEPRECATED); + } + if ('service_container' === $id) { + return $this; + } + if (isset($this->aliases[$id])) { + $id = $this->aliases[$id]; + } - // Re-use shared service instance if it exists. - if (isset($this->services[$id])) { - return $this->services[$id]; - } + // Re-use shared service instance if it exists. + if (isset($this->services[$id])) { + return $this->services[$id]; + } - if (isset($this->loading[$id])) { - throw new ServiceCircularReferenceException($id, array_keys($this->loading)); - } + if (isset($this->loading[$id])) { + throw new ServiceCircularReferenceException($id, array_keys($this->loading)); + } - if (isset($this->methodMap[$id])) { - $method = $this->methodMap[$id]; - } elseif (--$i && $id !== $normalizedId = $this->normalizeId($id)) { - $id = $normalizedId; - continue; - } else { - if (self::EXCEPTION_ON_INVALID_REFERENCE === $invalidBehavior) { - if (!$id) { - throw new ServiceNotFoundException($id); - } + if (isset($this->methodMap[$id])) { + $method = $this->methodMap[$id]; + } else { + if (self::EXCEPTION_ON_INVALID_REFERENCE === $invalidBehavior) { + if (!$id) { + throw new ServiceNotFoundException($id); + } - $alternatives = array(); - foreach ($this->getServiceIds() as $knownId) { - $lev = levenshtein($id, $knownId); - if ($lev <= strlen($id) / 3 || false !== strpos($knownId, $id)) { - $alternatives[] = $knownId; - } + $alternatives = array(); + foreach ($this->getServiceIds() as $knownId) { + $lev = levenshtein($id, $knownId); + if ($lev <= strlen($id) / 3 || false !== strpos($knownId, $id)) { + $alternatives[] = $knownId; } - - throw new ServiceNotFoundException($id, null, null, $alternatives); } - return; + throw new ServiceNotFoundException($id, null, null, $alternatives); } - $this->loading[$id] = true; + return; + } - try { - $service = $this->$method(); - } catch (\Exception $e) { - unset($this->services[$id]); + $this->loading[$id] = true; - throw $e; - } finally { - unset($this->loading[$id]); - } + try { + $service = $this->$method(); + } catch (\Exception $e) { + unset($this->services[$id]); - return $service; + throw $e; + } finally { + unset($this->loading[$id]); } + + return $service; } /** @@ -332,8 +290,6 @@ public function get($id, $invalidBehavior = self::EXCEPTION_ON_INVALID_REFERENCE */ public function initialized($id) { - $id = $this->normalizeId($id); - if ('service_container' === $id) { return false; } @@ -418,32 +374,6 @@ protected function getEnv($name) return $this->envCache[$name] = $this->getParameter("env($name)"); } - /** - * Returns the case sensitive id used at registration time. - * - * @param string $id - * - * @return string - * - * @internal - */ - public function normalizeId($id) - { - if (!is_string($id)) { - $id = (string) $id; - } - if (isset($this->normalizedIds[$normalizedId = strtolower($id)])) { - $normalizedId = $this->normalizedIds[$normalizedId]; - if ($id !== $normalizedId) { - @trigger_error(sprintf('Service identifiers will be made case sensitive in Symfony 4.0. Using "%s" instead of "%s" is deprecated since version 3.3.', $id, $normalizedId), E_USER_DEPRECATED); - } - } else { - $normalizedId = $this->normalizedIds[$normalizedId] = $id; - } - - return $normalizedId; - } - private function __clone() { } diff --git a/src/Symfony/Component/DependencyInjection/ContainerBuilder.php b/src/Symfony/Component/DependencyInjection/ContainerBuilder.php index 7e63452126bf0..a14c29d55d206 100644 --- a/src/Symfony/Component/DependencyInjection/ContainerBuilder.php +++ b/src/Symfony/Component/DependencyInjection/ContainerBuilder.php @@ -485,8 +485,6 @@ public function getCompiler() */ public function set($id, $service) { - $id = $this->normalizeId($id); - if ($this->isCompiled() && (isset($this->definitions[$id]) && !$this->definitions[$id]->isSynthetic())) { // setting a synthetic service on a compiled container is alright throw new BadMethodCallException(sprintf('Setting service "%s" for an unknown or non-synthetic service definition on a compiled container is not allowed.', $id)); @@ -504,7 +502,7 @@ public function set($id, $service) */ public function removeDefinition($id) { - unset($this->definitions[$this->normalizeId($id)]); + unset($this->definitions[$id]); } /** @@ -516,8 +514,6 @@ public function removeDefinition($id) */ public function has($id) { - $id = $this->normalizeId($id); - return isset($this->definitions[$id]) || isset($this->aliasDefinitions[$id]) || parent::has($id); } @@ -538,8 +534,6 @@ public function has($id) */ public function get($id, $invalidBehavior = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE) { - $id = $this->normalizeId($id); - if ($service = parent::get($id, ContainerInterface::NULL_ON_INVALID_REFERENCE)) { return $service; } @@ -762,10 +756,8 @@ public function setAliases(array $aliases) */ public function setAlias($alias, $id) { - $alias = $this->normalizeId($alias); - if (is_string($id)) { - $id = new Alias($this->normalizeId($id)); + $id = new Alias($id); } elseif (!$id instanceof Alias) { throw new InvalidArgumentException('$id must be a string, or an Alias object.'); } @@ -786,7 +778,7 @@ public function setAlias($alias, $id) */ public function removeAlias($alias) { - unset($this->aliasDefinitions[$this->normalizeId($alias)]); + unset($this->aliasDefinitions[$alias]); } /** @@ -798,7 +790,7 @@ public function removeAlias($alias) */ public function hasAlias($id) { - return isset($this->aliasDefinitions[$this->normalizeId($id)]); + return isset($this->aliasDefinitions[$id]); } /** @@ -822,8 +814,6 @@ public function getAliases() */ public function getAlias($id) { - $id = $this->normalizeId($id); - if (!isset($this->aliasDefinitions[$id])) { throw new InvalidArgumentException(sprintf('The service alias "%s" does not exist.', $id)); } @@ -912,8 +902,6 @@ public function setDefinition($id, Definition $definition) throw new BadMethodCallException('Adding definition to a compiled container is not allowed'); } - $id = $this->normalizeId($id); - unset($this->aliasDefinitions[$id]); return $this->definitions[$id] = $definition; @@ -928,7 +916,7 @@ public function setDefinition($id, Definition $definition) */ public function hasDefinition($id) { - return isset($this->definitions[$this->normalizeId($id)]); + return isset($this->definitions[$id]); } /** @@ -942,8 +930,6 @@ public function hasDefinition($id) */ public function getDefinition($id) { - $id = $this->normalizeId($id); - if (!isset($this->definitions[$id])) { throw new ServiceNotFoundException($id); } @@ -964,8 +950,6 @@ public function getDefinition($id) */ public function findDefinition($id) { - $id = $this->normalizeId($id); - while (isset($this->aliasDefinitions[$id])) { $id = (string) $this->aliasDefinitions[$id]; } @@ -1311,22 +1295,6 @@ public function getEnvCounters() return $this->envCounters; } - /** - * @internal - */ - public function getNormalizedIds() - { - $normalizedIds = array(); - - foreach ($this->normalizedIds as $k => $v) { - if ($v !== (string) $k) { - $normalizedIds[$k] = $v; - } - } - - return $normalizedIds; - } - /** * @final */ @@ -1394,7 +1362,7 @@ private function callMethod($service, $call) private function shareService(Definition $definition, $service, $id) { if (null !== $id && $definition->isShared()) { - $this->services[$this->normalizeId($id)] = $service; + $this->services[$id] = $service; } } diff --git a/src/Symfony/Component/DependencyInjection/Dumper/GraphvizDumper.php b/src/Symfony/Component/DependencyInjection/Dumper/GraphvizDumper.php index 25ab3078c9a2a..57a6e5c100b9a 100644 --- a/src/Symfony/Component/DependencyInjection/Dumper/GraphvizDumper.php +++ b/src/Symfony/Component/DependencyInjection/Dumper/GraphvizDumper.php @@ -281,7 +281,7 @@ private function addOptions(array $options) */ private function dotize($id) { - return strtolower(preg_replace('/\W/i', '_', $id)); + return preg_replace('/\W/i', '_', $id); } /** diff --git a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php index d77733ed884ee..61718c680d6d1 100644 --- a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php +++ b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php @@ -826,7 +826,6 @@ public function __construct() } $code .= "\n \$this->services = array();\n"; - $code .= $this->addNormalizedIds(); $code .= $this->addMethodMap(); $code .= $this->addPrivateServices(); $code .= $this->addAliases(); @@ -879,25 +878,6 @@ public function isCompiled() EOF; } - /** - * Adds the normalizedIds property definition. - * - * @return string - */ - private function addNormalizedIds() - { - $code = ''; - $normalizedIds = $this->container->getNormalizedIds(); - ksort($normalizedIds); - foreach ($normalizedIds as $id => $normalizedId) { - if ($this->container->has($normalizedId)) { - $code .= ' '.$this->export($id).' => '.$this->export($normalizedId).",\n"; - } - } - - return $code ? " \$this->normalizedIds = array(\n".$code." );\n" : ''; - } - /** * Adds the methodMap property definition. * diff --git a/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php b/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php index 51f7001491a19..a8b7f88313a6e 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php @@ -1082,6 +1082,21 @@ public function testRegisterForAutoconfiguration() // when called multiple times, the same instance is returned $this->assertSame($childDefA, $container->registerForAutoconfiguration('AInterface')); } + + public function testCaseSensitivity() + { + $container = new ContainerBuilder(); + $container->register('foo', 'stdClass'); + $container->register('Foo', 'stdClass')->setProperty('foo', new Reference('foo'))->setPublic(false); + $container->register('fOO', 'stdClass')->setProperty('Foo', new Reference('Foo')); + + $this->assertSame(array('service_container', 'foo', 'Foo', 'fOO', 'Psr\Container\ContainerInterface', 'Symfony\Component\DependencyInjection\ContainerInterface'), $container->getServiceIds()); + + $container->compile(); + + $this->assertNotSame($container->get('foo'), $container->get('fOO'), '->get() returns the service for the given id, case sensitively'); + $this->assertSame($container->get('fOO')->Foo->foo, $container->get('foo'), '->get() returns the service for the given id, case sensitively'); + } } class FooClass diff --git a/src/Symfony/Component/DependencyInjection/Tests/ContainerTest.php b/src/Symfony/Component/DependencyInjection/Tests/ContainerTest.php index 3cc9f384ed5c7..9b3db8af6d095 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/ContainerTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/ContainerTest.php @@ -193,26 +193,15 @@ public function testGet() $this->assertNull($sc->get('', ContainerInterface::NULL_ON_INVALID_REFERENCE), '->get() returns null if the service is empty'); } - /** - * @group legacy - * @expectedDeprecation Service identifiers will be made case sensitive in Symfony 4.0. Using "Foo" instead of "foo" is deprecated since version 3.3. - */ - public function testGetInsensitivity() + public function testCaseSensitivity() { - $sc = new ProjectServiceContainer(); - $sc->set('foo', $foo = new \stdClass()); - $this->assertSame($foo, $sc->get('Foo'), '->get() returns the service for the given id, and converts id to lowercase'); - } + $sc = new Container(); + $sc->set('foo', $foo1 = new \stdClass()); + $sc->set('Foo', $foo2 = new \stdClass()); - /** - * @group legacy - * @expectedDeprecation Service identifiers will be made case sensitive in Symfony 4.0. Using "foo" instead of "Foo" is deprecated since version 3.3. - */ - public function testNormalizeIdKeepsCase() - { - $sc = new ProjectServiceContainer(); - $sc->normalizeId('Foo', true); - $this->assertSame('Foo', $sc->normalizeId('foo')); + $this->assertSame(array('service_container', 'foo', 'Foo'), $sc->getServiceIds()); + $this->assertSame($foo1, $sc->get('foo'), '->get() returns the service for the given id, case sensitively'); + $this->assertSame($foo2, $sc->get('Foo'), '->get() returns the service for the given id, case sensitively'); } public function testGetThrowServiceNotFoundException() diff --git a/src/Symfony/Component/DependencyInjection/Tests/CrossCheckTest.php b/src/Symfony/Component/DependencyInjection/Tests/CrossCheckTest.php index bcfe88acc0ce4..dbdbb79542316 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/CrossCheckTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/CrossCheckTest.php @@ -55,12 +55,6 @@ public function testCrossCheck($fixture, $type) $this->assertEquals($container2->getAliases(), $container1->getAliases(), 'loading a dump from a previously loaded container returns the same container'); $this->assertEquals($container2->getDefinitions(), $container1->getDefinitions(), 'loading a dump from a previously loaded container returns the same container'); $this->assertEquals($container2->getParameterBag()->all(), $container1->getParameterBag()->all(), '->getParameterBag() returns the same value for both containers'); - - $r = new \ReflectionProperty(ContainerBuilder::class, 'normalizedIds'); - $r->setAccessible(true); - $r->setValue($container2, array()); - $r->setValue($container1, array()); - $this->assertEquals(serialize($container2), serialize($container1), 'loading a dump from a previously loaded container returns the same container'); $services1 = array(); diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container9.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container9.php index 13b45fda07a70..472a211537160 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container9.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container9.php @@ -139,5 +139,11 @@ ->register('lazy_context_ignore_invalid_ref', 'LazyContext') ->setArguments(array(new IteratorArgument(array(new Reference('foo.baz'), new Reference('invalid', ContainerInterface::IGNORE_ON_INVALID_REFERENCE))), new IteratorArgument(array()))) ; +$container + ->register('BAR', 'stdClass') + ->setProperty('bar', new Reference('bar')) +; +$container->register('bar2', 'stdClass'); +$container->register('BAR2', 'stdClass'); return $container; diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/graphviz/services9.dot b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/graphviz/services9.dot index b316b93c1576b..e6b4de7d85e83 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/graphviz/services9.dot +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/graphviz/services9.dot @@ -29,6 +29,9 @@ digraph sc { node_factory_service_simple [label="factory_service_simple\nBar\n", shape=record, fillcolor="#eeeeee", style="filled"]; node_lazy_context [label="lazy_context\nLazyContext\n", shape=record, fillcolor="#eeeeee", style="filled"]; node_lazy_context_ignore_invalid_ref [label="lazy_context_ignore_invalid_ref\nLazyContext\n", shape=record, fillcolor="#eeeeee", style="filled"]; + node_BAR [label="BAR\nstdClass\n", shape=record, fillcolor="#eeeeee", style="filled"]; + node_bar2 [label="bar2\nstdClass\n", shape=record, fillcolor="#eeeeee", style="filled"]; + node_BAR2 [label="BAR2\nstdClass\n", shape=record, fillcolor="#eeeeee", style="filled"]; node_foo2 [label="foo2\n\n", shape=record, fillcolor="#ff9999", style="filled"]; node_foo3 [label="foo3\n\n", shape=record, fillcolor="#ff9999", style="filled"]; node_foobaz [label="foobaz\n\n", shape=record, fillcolor="#ff9999", style="filled"]; @@ -50,4 +53,5 @@ digraph sc { node_lazy_context -> node_service_container [label="" style="filled" color="#9999ff"]; node_lazy_context_ignore_invalid_ref -> node_foo_baz [label="" style="filled" color="#9999ff"]; node_lazy_context_ignore_invalid_ref -> node_invalid [label="" style="filled" color="#9999ff"]; + node_BAR -> node_bar [label="" style="dashed"]; } diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services33.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services33.php index 76787db068b24..3c3ac43244249 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services33.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services33.php @@ -27,9 +27,6 @@ class ProjectServiceContainer extends Container public function __construct() { $this->services = array(); - $this->normalizedIds = array( - 'symfony\\component\\dependencyinjection\\tests\\fixtures\\container33\\foo' => 'Symfony\\Component\\DependencyInjection\\Tests\\Fixtures\\Container33\\Foo', - ); $this->methodMap = array( 'Symfony\\Component\\DependencyInjection\\Tests\\Fixtures\\Container33\\Foo' => 'getSymfony_Component_DependencyInjection_Tests_Fixtures_Container33_FooService', ); diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9.php index 5b6c16919c003..b8118504bea82 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9.php @@ -27,12 +27,11 @@ class ProjectServiceContainer extends Container public function __construct() { parent::__construct(new ParameterBag($this->getDefaultParameters())); - $this->normalizedIds = array( - 'psr\\container\\containerinterface' => 'Psr\\Container\\ContainerInterface', - 'symfony\\component\\dependencyinjection\\containerinterface' => 'Symfony\\Component\\DependencyInjection\\ContainerInterface', - ); $this->methodMap = array( - 'bar' => 'getBarService', + 'BAR' => 'getBARService', + 'BAR2' => 'getBAR2Service', + 'bar' => 'getBar3Service', + 'bar2' => 'getBar22Service', 'baz' => 'getBazService', 'configurator_service' => 'getConfiguratorServiceService', 'configurator_service_simple' => 'getConfiguratorServiceSimpleService', @@ -72,6 +71,36 @@ public function __construct() ); } + /** + * Gets the 'BAR' service. + * + * This service is shared. + * This method always returns the same instance of the service. + * + * @return \stdClass A stdClass instance + */ + protected function getBARService() + { + $this->services['BAR'] = $instance = new \stdClass(); + + $instance->bar = ($this->services['bar'] ?? $this->get('bar')); + + return $instance; + } + + /** + * Gets the 'BAR2' service. + * + * This service is shared. + * This method always returns the same instance of the service. + * + * @return \stdClass A stdClass instance + */ + protected function getBAR2Service() + { + return $this->services['BAR2'] = new \stdClass(); + } + /** * Gets the 'bar' service. * @@ -80,7 +109,7 @@ public function __construct() * * @return \Bar\FooClass A Bar\FooClass instance */ - protected function getBarService() + protected function getBar3Service() { $a = ($this->services['foo.baz'] ?? $this->get('foo.baz')); @@ -91,6 +120,19 @@ protected function getBarService() return $instance; } + /** + * Gets the 'bar2' service. + * + * This service is shared. + * This method always returns the same instance of the service. + * + * @return \stdClass A stdClass instance + */ + protected function getBar22Service() + { + return $this->services['bar2'] = new \stdClass(); + } + /** * Gets the 'baz' service. * diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_compiled.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_compiled.php index ac46b06a8cca9..8fb33d8cbd44c 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_compiled.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_compiled.php @@ -30,7 +30,10 @@ public function __construct() $this->services = array(); $this->methodMap = array( - 'bar' => 'getBarService', + 'BAR' => 'getBARService', + 'BAR2' => 'getBAR2Service', + 'bar' => 'getBar3Service', + 'bar2' => 'getBar22Service', 'baz' => 'getBazService', 'configured_service' => 'getConfiguredServiceService', 'configured_service_simple' => 'getConfiguredServiceSimpleService', @@ -72,6 +75,36 @@ public function isCompiled() return true; } + /** + * Gets the 'BAR' service. + * + * This service is shared. + * This method always returns the same instance of the service. + * + * @return \stdClass A stdClass instance + */ + protected function getBARService() + { + $this->services['BAR'] = $instance = new \stdClass(); + + $instance->bar = ($this->services['bar'] ?? $this->get('bar')); + + return $instance; + } + + /** + * Gets the 'BAR2' service. + * + * This service is shared. + * This method always returns the same instance of the service. + * + * @return \stdClass A stdClass instance + */ + protected function getBAR2Service() + { + return $this->services['BAR2'] = new \stdClass(); + } + /** * Gets the 'bar' service. * @@ -80,7 +113,7 @@ public function isCompiled() * * @return \Bar\FooClass A Bar\FooClass instance */ - protected function getBarService() + protected function getBar3Service() { $a = ($this->services['foo.baz'] ?? $this->get('foo.baz')); @@ -91,6 +124,19 @@ protected function getBarService() return $instance; } + /** + * Gets the 'bar2' service. + * + * This service is shared. + * This method always returns the same instance of the service. + * + * @return \stdClass A stdClass instance + */ + protected function getBar22Service() + { + return $this->services['bar2'] = new \stdClass(); + } + /** * Gets the 'baz' service. * diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_subscriber.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_subscriber.php index 81506dae44a0d..1d852fab35a58 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_subscriber.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_subscriber.php @@ -27,10 +27,6 @@ class ProjectServiceContainer extends Container public function __construct() { $this->services = array(); - $this->normalizedIds = array( - 'autowired.symfony\\component\\dependencyinjection\\tests\\fixtures\\customdefinition' => 'autowired.Symfony\\Component\\DependencyInjection\\Tests\\Fixtures\\CustomDefinition', - 'symfony\\component\\dependencyinjection\\tests\\fixtures\\testservicesubscriber' => 'Symfony\\Component\\DependencyInjection\\Tests\\Fixtures\\TestServiceSubscriber', - ); $this->methodMap = array( 'Symfony\\Component\\DependencyInjection\\Tests\\Fixtures\\TestServiceSubscriber' => 'getSymfony_Component_DependencyInjection_Tests_Fixtures_TestServiceSubscriberService', 'autowired.Symfony\\Component\\DependencyInjection\\Tests\\Fixtures\\CustomDefinition' => 'getAutowired_Symfony_Component_DependencyInjection_Tests_Fixtures_CustomDefinitionService', diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services9.xml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services9.xml index 100a23a9c5b7e..5f46821a0f90e 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services9.xml +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services9.xml @@ -130,6 +130,11 @@
+ + + + + diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services_case.xml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services_case.xml new file mode 100644 index 0000000000000..31fea2eb260ad --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services_case.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services9.yml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services9.yml index a7a9cc28fd61b..e91fbb208c1ae 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services9.yml +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services9.yml @@ -116,6 +116,13 @@ services: lazy_context_ignore_invalid_ref: class: LazyContext arguments: [!iterator ['@foo.baz', '@?invalid'], !iterator []] + BAR: + class: stdClass + properties: { bar: '@bar' } + bar2: + class: stdClass + BAR2: + class: stdClass alias_for_foo: '@foo' alias_for_alias: '@foo' Psr\Container\ContainerInterface: diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services_case.yml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services_case.yml new file mode 100644 index 0000000000000..cbf158659cfd7 --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services_case.yml @@ -0,0 +1,10 @@ +services: + bar: + class: stdClass + Bar: + class: stdClass + properties: { bar: '@bar' } + BAR: + class: Bar\FooClass + arguments: ['@Bar'] + calls: [[setBar, ['@bar']]] diff --git a/src/Symfony/Component/DependencyInjection/Tests/Loader/XmlFileLoaderTest.php b/src/Symfony/Component/DependencyInjection/Tests/Loader/XmlFileLoaderTest.php index a242898526537..e2ebd090ebefe 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Loader/XmlFileLoaderTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Loader/XmlFileLoaderTest.php @@ -756,6 +756,21 @@ public function testAutoConfigureInstanceof() $this->assertTrue($container->getDefinition('use_defaults_settings')->isAutoconfigured()); $this->assertFalse($container->getDefinition('override_defaults_settings_to_false')->isAutoconfigured()); } + + public function testCaseSensitivity() + { + $container = new ContainerBuilder(); + $loader = new XmlFileLoader($container, new FileLocator(self::$fixturesPath.'/xml')); + $loader->load('services_case.xml'); + $container->compile(); + + $this->assertTrue($container->has('bar')); + $this->assertTrue($container->has('BAR')); + $this->assertFalse($container->has('baR')); + $this->assertNotSame($container->get('BAR'), $container->get('bar')); + $this->assertSame($container->get('BAR')->arguments->bar, $container->get('bar')); + $this->assertSame($container->get('BAR')->bar, $container->get('bar')); + } } interface BarInterface diff --git a/src/Symfony/Component/DependencyInjection/Tests/Loader/YamlFileLoaderTest.php b/src/Symfony/Component/DependencyInjection/Tests/Loader/YamlFileLoaderTest.php index 622bacf6944db..98382e84dec4f 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Loader/YamlFileLoaderTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Loader/YamlFileLoaderTest.php @@ -624,6 +624,21 @@ public function testUnsupportedKeywordInServiceAliasThrowsException() $loader = new YamlFileLoader($container, new FileLocator(self::$fixturesPath.'/yaml')); $loader->load('bad_alias.yml'); } + + public function testCaseSensitivity() + { + $container = new ContainerBuilder(); + $loader = new YamlFileLoader($container, new FileLocator(self::$fixturesPath.'/yaml')); + $loader->load('services_case.yml'); + $container->compile(); + + $this->assertTrue($container->has('bar')); + $this->assertTrue($container->has('BAR')); + $this->assertFalse($container->has('baR')); + $this->assertNotSame($container->get('BAR'), $container->get('bar')); + $this->assertSame($container->get('BAR')->arguments->bar, $container->get('bar')); + $this->assertSame($container->get('BAR')->bar, $container->get('bar')); + } } interface FooInterface From ba8763b12e9a9c8a9bec21934093fb6be6aa8006 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9goire=20Pineau?= Date: Fri, 2 Jun 2017 16:36:46 +0200 Subject: [PATCH 0407/1099] [TwigBundle] Added a RuntimeExtensionInterface to take advantage of autoconfigure --- .../Bundle/TwigBundle/DependencyInjection/TwigExtension.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Symfony/Bundle/TwigBundle/DependencyInjection/TwigExtension.php b/src/Symfony/Bundle/TwigBundle/DependencyInjection/TwigExtension.php index e8c10786c457d..09daf1322f307 100644 --- a/src/Symfony/Bundle/TwigBundle/DependencyInjection/TwigExtension.php +++ b/src/Symfony/Bundle/TwigBundle/DependencyInjection/TwigExtension.php @@ -19,6 +19,7 @@ use Symfony\Component\HttpKernel\DependencyInjection\Extension; use Symfony\Component\WebLink\HttpHeaderSerializer; use Twig\Extension\ExtensionInterface; +use Twig\Extension\RuntimeExtensionInterface; use Twig\Loader\LoaderInterface; /** @@ -150,6 +151,7 @@ public function load(array $configs, ContainerBuilder $container) $container->registerForAutoconfiguration(\Twig_LoaderInterface::class)->addTag('twig.loader'); $container->registerForAutoconfiguration(ExtensionInterface::class)->addTag('twig.extension'); $container->registerForAutoconfiguration(LoaderInterface::class)->addTag('twig.loader'); + $container->registerForAutoconfiguration(RuntimeExtensionInterface::class)->addTag('twig.runtime'); if (\PHP_VERSION_ID < 70000) { $this->addClassesToCompile(array( From 025dfff675a5b4b266bd5d500e6baa6b519ff8a8 Mon Sep 17 00:00:00 2001 From: Javier Eguiluz Date: Sun, 9 Jul 2017 20:05:54 +0200 Subject: [PATCH 0408/1099] Use rawurlencode() to transform the Cookie into a string --- src/Symfony/Component/BrowserKit/Cookie.php | 2 +- .../Component/BrowserKit/Tests/CookieTest.php | 15 +++++++++++++++ src/Symfony/Component/HttpFoundation/Cookie.php | 2 +- .../Component/HttpFoundation/Tests/CookieTest.php | 3 +++ 4 files changed, 20 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/BrowserKit/Cookie.php b/src/Symfony/Component/BrowserKit/Cookie.php index 42f184d532e02..c042c6a525295 100644 --- a/src/Symfony/Component/BrowserKit/Cookie.php +++ b/src/Symfony/Component/BrowserKit/Cookie.php @@ -62,7 +62,7 @@ public function __construct($name, $value, $expires = null, $path = null, $domai $this->rawValue = $value; } else { $this->value = $value; - $this->rawValue = urlencode($value); + $this->rawValue = rawurlencode($value); } $this->name = $name; $this->path = empty($path) ? '/' : $path; diff --git a/src/Symfony/Component/BrowserKit/Tests/CookieTest.php b/src/Symfony/Component/BrowserKit/Tests/CookieTest.php index 38ea81220bb2c..2f5a08d104143 100644 --- a/src/Symfony/Component/BrowserKit/Tests/CookieTest.php +++ b/src/Symfony/Component/BrowserKit/Tests/CookieTest.php @@ -16,6 +16,21 @@ class CookieTest extends TestCase { + public function testToString() + { + $cookie = new Cookie('foo', 'bar', strtotime('Fri, 20-May-2011 15:25:52 GMT'), '/', '.myfoodomain.com', true); + $this->assertEquals('foo=bar; expires=Fri, 20 May 2011 15:25:52 GMT; domain=.myfoodomain.com; path=/; secure; httponly', (string) $cookie, '->__toString() returns string representation of the cookie'); + + $cookie = new Cookie('foo', 'bar with white spaces', strtotime('Fri, 20-May-2011 15:25:52 GMT'), '/', '.myfoodomain.com', true); + $this->assertEquals('foo=bar%20with%20white%20spaces; expires=Fri, 20 May 2011 15:25:52 GMT; domain=.myfoodomain.com; path=/; secure; httponly', (string) $cookie, '->__toString() encodes the value of the cookie according to RFC 3986 (white space = %20)'); + + $cookie = new Cookie('foo', null, 1, '/admin/', '.myfoodomain.com'); + $this->assertEquals('foo=; expires=Thu, 01 Jan 1970 00:00:01 GMT; domain=.myfoodomain.com; path=/admin/; httponly', (string) $cookie, '->__toString() returns string representation of a cleared cookie if value is NULL'); + + $cookie = new Cookie('foo', 'bar', 0, '/', ''); + $this->assertEquals('foo=bar; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/; httponly', (string) $cookie); + } + /** * @dataProvider getTestsForToFromString */ diff --git a/src/Symfony/Component/HttpFoundation/Cookie.php b/src/Symfony/Component/HttpFoundation/Cookie.php index 91783a6ad2b50..fb1e7dfd74ea4 100644 --- a/src/Symfony/Component/HttpFoundation/Cookie.php +++ b/src/Symfony/Component/HttpFoundation/Cookie.php @@ -82,7 +82,7 @@ public function __toString() if ('' === (string) $this->getValue()) { $str .= 'deleted; expires='.gmdate('D, d-M-Y H:i:s T', time() - 31536001); } else { - $str .= urlencode($this->getValue()); + $str .= rawurlencode($this->getValue()); if (0 !== $this->getExpiresTime()) { $str .= '; expires='.gmdate('D, d-M-Y H:i:s T', $this->getExpiresTime()); diff --git a/src/Symfony/Component/HttpFoundation/Tests/CookieTest.php b/src/Symfony/Component/HttpFoundation/Tests/CookieTest.php index f3f74f635eb40..2d9fb09d3d4b6 100644 --- a/src/Symfony/Component/HttpFoundation/Tests/CookieTest.php +++ b/src/Symfony/Component/HttpFoundation/Tests/CookieTest.php @@ -160,6 +160,9 @@ public function testToString() $cookie = new Cookie('foo', 'bar', strtotime('Fri, 20-May-2011 15:25:52 GMT'), '/', '.myfoodomain.com', true); $this->assertEquals('foo=bar; expires=Fri, 20-May-2011 15:25:52 GMT; path=/; domain=.myfoodomain.com; secure; httponly', (string) $cookie, '->__toString() returns string representation of the cookie'); + $cookie = new Cookie('foo', 'bar with white spaces', strtotime('Fri, 20-May-2011 15:25:52 GMT'), '/', '.myfoodomain.com', true); + $this->assertEquals('foo=bar%20with%20white%20spaces; expires=Fri, 20-May-2011 15:25:52 GMT; path=/; domain=.myfoodomain.com; secure; httponly', (string) $cookie, '->__toString() encodes the value of the cookie according to RFC 3986 (white space = %20)'); + $cookie = new Cookie('foo', null, 1, '/admin/', '.myfoodomain.com'); $this->assertEquals('foo=deleted; expires='.gmdate('D, d-M-Y H:i:s T', time() - 31536001).'; path=/admin/; domain=.myfoodomain.com; httponly', (string) $cookie, '->__toString() returns string representation of a cleared cookie if value is NULL'); From 7f97519624cb08c0d9c119eff0ebb911d7f13d97 Mon Sep 17 00:00:00 2001 From: Robin Chalas Date: Wed, 12 Jul 2017 11:59:19 +0200 Subject: [PATCH 0409/1099] Add support for command lazy-loading --- .../Bundle/FrameworkBundle/CHANGELOG.md | 2 + .../FrameworkBundle/Console/Application.php | 26 +++-- .../Tests/Command/RouterDebugCommandTest.php | 11 +- .../Tests/Command/RouterMatchCommandTest.php | 10 +- .../Bundle/FrameworkBundle/composer.json | 4 +- .../Resources/config/console.xml | 2 +- .../Resources/config/webserver.xml | 8 +- src/Symfony/Component/Console/Application.php | 57 ++++++++-- src/Symfony/Component/Console/CHANGELOG.md | 5 + .../Component/Console/Command/Command.php | 4 - .../CommandLoader/CommandLoaderInterface.php | 37 +++++++ .../CommandLoader/ContainerCommandLoader.php | 55 ++++++++++ .../AddConsoleCommandPass.php | 61 +++++++++-- .../Console/Tests/ApplicationTest.php | 100 ++++++++++++++++++ .../Console/Tests/Command/CommandTest.php | 2 +- .../ContainerCommandLoaderTest.php | 61 +++++++++++ .../AddConsoleCommandPassTest.php | 27 ++++- 17 files changed, 424 insertions(+), 48 deletions(-) create mode 100644 src/Symfony/Component/Console/CommandLoader/CommandLoaderInterface.php create mode 100644 src/Symfony/Component/Console/CommandLoader/ContainerCommandLoader.php create mode 100644 src/Symfony/Component/Console/Tests/CommandLoader/ContainerCommandLoaderTest.php diff --git a/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md b/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md index bae6cb0a5a3fd..2067942665051 100644 --- a/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md +++ b/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md @@ -18,6 +18,8 @@ CHANGELOG `Symfony\Component\Translation\DependencyInjection\TranslationExtractorPass` instead * Deprecated `TranslatorPass`, use `Symfony\Component\Translation\DependencyInjection\TranslatorPass` instead + * Added `command` attribute to the `console.command` tag which takes the command + name as value, using it makes the command lazy 3.3.0 ----- diff --git a/src/Symfony/Bundle/FrameworkBundle/Console/Application.php b/src/Symfony/Bundle/FrameworkBundle/Console/Application.php index af5eb25c5a2d6..b1c893ad0503d 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Console/Application.php +++ b/src/Symfony/Bundle/FrameworkBundle/Console/Application.php @@ -68,15 +68,7 @@ public function doRun(InputInterface $input, OutputInterface $output) { $this->kernel->boot(); - $container = $this->kernel->getContainer(); - - foreach ($this->all() as $command) { - if ($command instanceof ContainerAwareInterface) { - $command->setContainer($container); - } - } - - $this->setDispatcher($container->get('event_dispatcher')); + $this->setDispatcher($this->kernel->getContainer()->get('event_dispatcher')); return parent::doRun($input, $output); } @@ -98,7 +90,13 @@ public function get($name) { $this->registerCommands(); - return parent::get($name); + $command = parent::get($name); + + if ($command instanceof ContainerAwareInterface) { + $command->setContainer($this->kernel->getContainer()); + } + + return $command; } /** @@ -144,9 +142,15 @@ protected function registerCommands() } } + if ($container->has('console.command_loader')) { + $this->setCommandLoader($container->get('console.command_loader')); + } + if ($container->hasParameter('console.command.ids')) { foreach ($container->getParameter('console.command.ids') as $id) { - $this->add($container->get($id)); + if (false !== $id) { + $this->add($container->get($id)); + } } } } diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/RouterDebugCommandTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/RouterDebugCommandTest.php index 597082485a0b6..13901dd1734b5 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/RouterDebugCommandTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/RouterDebugCommandTest.php @@ -77,10 +77,15 @@ private function getKernel() $container = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerInterface')->getMock(); $container - ->expects($this->once()) + ->expects($this->atLeastOnce()) ->method('has') - ->with('router') - ->will($this->returnValue(true)) + ->will($this->returnCallback(function ($id) { + if ('console.command_loader' === $id) { + return false; + } + + return true; + })) ; $container ->expects($this->any()) diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/RouterMatchCommandTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/RouterMatchCommandTest.php index 384bd7ca53079..44749bbd71dbc 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/RouterMatchCommandTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/RouterMatchCommandTest.php @@ -78,8 +78,14 @@ private function getKernel() $container ->expects($this->atLeastOnce()) ->method('has') - ->with('router') - ->will($this->returnValue(true)); + ->will($this->returnCallback(function ($id) { + if ('console.command_loader' === $id) { + return false; + } + + return true; + })) + ; $container ->expects($this->any()) ->method('get') diff --git a/src/Symfony/Bundle/FrameworkBundle/composer.json b/src/Symfony/Bundle/FrameworkBundle/composer.json index e17636e156175..20686669ddaa4 100644 --- a/src/Symfony/Bundle/FrameworkBundle/composer.json +++ b/src/Symfony/Bundle/FrameworkBundle/composer.json @@ -35,7 +35,7 @@ "fig/link-util": "^1.0", "symfony/asset": "~3.3|~4.0", "symfony/browser-kit": "~2.8|~3.0|~4.0", - "symfony/console": "~3.3|~4.0", + "symfony/console": "~3.4|~4.0", "symfony/css-selector": "~2.8|~3.0|~4.0", "symfony/dom-crawler": "~2.8|~3.0|~4.0", "symfony/polyfill-intl-icu": "~1.0", @@ -64,7 +64,7 @@ "phpdocumentor/type-resolver": "<0.2.0", "phpunit/phpunit": "<4.8.35|<5.4.3,>=5.0", "symfony/asset": "<3.3", - "symfony/console": "<3.3", + "symfony/console": "<3.4", "symfony/form": "<3.3", "symfony/property-info": "<3.3", "symfony/serializer": "<3.3", diff --git a/src/Symfony/Bundle/SecurityBundle/Resources/config/console.xml b/src/Symfony/Bundle/SecurityBundle/Resources/config/console.xml index d8b818ff61051..c94c00f75488f 100644 --- a/src/Symfony/Bundle/SecurityBundle/Resources/config/console.xml +++ b/src/Symfony/Bundle/SecurityBundle/Resources/config/console.xml @@ -10,7 +10,7 @@ - + diff --git a/src/Symfony/Bundle/WebServerBundle/Resources/config/webserver.xml b/src/Symfony/Bundle/WebServerBundle/Resources/config/webserver.xml index 2815c6d2cfbf5..a3c8b50841532 100644 --- a/src/Symfony/Bundle/WebServerBundle/Resources/config/webserver.xml +++ b/src/Symfony/Bundle/WebServerBundle/Resources/config/webserver.xml @@ -10,21 +10,21 @@ %kernel.project_dir%/web %kernel.environment% - + %kernel.project_dir%/web %kernel.environment% - + - + - + diff --git a/src/Symfony/Component/Console/Application.php b/src/Symfony/Component/Console/Application.php index fd15fb4cb26aa..fff5d0a6e7b8c 100644 --- a/src/Symfony/Component/Console/Application.php +++ b/src/Symfony/Component/Console/Application.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Console; +use Symfony\Component\Console\CommandLoader\CommandLoaderInterface; use Symfony\Component\Console\Exception\ExceptionInterface; use Symfony\Component\Console\Formatter\OutputFormatter; use Symfony\Component\Console\Helper\DebugFormatterHelper; @@ -64,6 +65,7 @@ class Application private $runningCommand; private $name; private $version; + private $commandLoader; private $catchExceptions = true; private $autoExit = true; private $definition; @@ -96,6 +98,11 @@ public function setDispatcher(EventDispatcherInterface $dispatcher) $this->dispatcher = $dispatcher; } + public function setCommandLoader(CommandLoaderInterface $commandLoader) + { + $this->commandLoader = $commandLoader; + } + /** * Runs the current application. * @@ -431,6 +438,10 @@ public function add(Command $command) throw new LogicException(sprintf('Command class "%s" is not correctly initialized. You probably forgot to call the parent constructor.', get_class($command))); } + if (!$command->getName()) { + throw new LogicException(sprintf('The command defined in "%s" cannot have an empty name.', get_class($command))); + } + $this->commands[$command->getName()] = $command; foreach ($command->getAliases() as $alias) { @@ -451,12 +462,16 @@ public function add(Command $command) */ public function get($name) { - if (!isset($this->commands[$name])) { + if (isset($this->commands[$name])) { + $command = $this->commands[$name]; + } elseif ($this->commandLoader && $this->commandLoader->has($name)) { + $command = $this->commandLoader->get($name); + $command->setName($name); + $this->add($command); + } else { throw new CommandNotFoundException(sprintf('The command "%s" does not exist.', $name)); } - $command = $this->commands[$name]; - if ($this->wantHelps) { $this->wantHelps = false; @@ -478,7 +493,7 @@ public function get($name) */ public function has($name) { - return isset($this->commands[$name]); + return isset($this->commands[$name]) || ($this->commandLoader && $this->commandLoader->has($name)); } /** @@ -555,7 +570,7 @@ public function findNamespace($namespace) */ public function find($name) { - $allCommands = array_keys($this->commands); + $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); @@ -581,12 +596,12 @@ public function find($name) // filter out aliases for commands which are already on the list if (count($commands) > 1) { - $commandList = $this->commands; - $commands = array_filter($commands, function ($nameOrAlias) use ($commandList, $commands) { - $commandName = $commandList[$nameOrAlias]->getName(); + $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) { + $commandName = $commandList[$nameOrAlias] instanceof Command ? $commandList[$nameOrAlias]->getName() : $nameOrAlias; return $commandName === $nameOrAlias || !in_array($commandName, $commands); - }); + })); } $exact = in_array($name, $commands, true); @@ -598,6 +613,9 @@ public function find($name) $maxLen = max(Helper::strlen($abbrev), $maxLen); } $abbrevs = array_map(function ($cmd) use ($commandList, $usableWidth, $maxLen) { + if (!$commandList[$cmd] instanceof Command) { + return $cmd; + } $abbrev = str_pad($cmd, $maxLen, ' ').' '.$commandList[$cmd]->getDescription(); return Helper::strlen($abbrev) > $usableWidth ? Helper::substr($abbrev, 0, $usableWidth - 3).'...' : $abbrev; @@ -622,7 +640,18 @@ public function find($name) public function all($namespace = null) { if (null === $namespace) { - return $this->commands; + if (!$this->commandLoader) { + return $this->commands; + } + + $commands = $this->commands; + foreach ($this->commandLoader->getNames() as $name) { + if (!isset($commands[$name])) { + $commands[$name] = $this->commandLoader->get($name); + } + } + + return $commands; } $commands = array(); @@ -632,6 +661,14 @@ public function all($namespace = null) } } + if ($this->commandLoader) { + foreach ($this->commandLoader->getNames() as $name) { + if (!isset($commands[$name]) && $namespace === $this->extractNamespace($name, substr_count($namespace, ':') + 1)) { + $commands[$name] = $this->commandLoader->get($name); + } + } + } + return $commands; } diff --git a/src/Symfony/Component/Console/CHANGELOG.md b/src/Symfony/Component/Console/CHANGELOG.md index f8539491d264b..542d00623bebb 100644 --- a/src/Symfony/Component/Console/CHANGELOG.md +++ b/src/Symfony/Component/Console/CHANGELOG.md @@ -1,6 +1,11 @@ CHANGELOG ========= +3.4.0 +----- + + * added `CommandLoaderInterface` and PSR-11 `ContainerCommandLoader` + 3.3.0 ----- diff --git a/src/Symfony/Component/Console/Command/Command.php b/src/Symfony/Component/Console/Command/Command.php index 08a74c3b69a9a..6620ff5718c53 100644 --- a/src/Symfony/Component/Console/Command/Command.php +++ b/src/Symfony/Component/Console/Command/Command.php @@ -61,10 +61,6 @@ public function __construct($name = null) } $this->configure(); - - if (!$this->name) { - throw new LogicException(sprintf('The command defined in "%s" cannot have an empty name.', get_class($this))); - } } /** diff --git a/src/Symfony/Component/Console/CommandLoader/CommandLoaderInterface.php b/src/Symfony/Component/Console/CommandLoader/CommandLoaderInterface.php new file mode 100644 index 0000000000000..9462996f6d2af --- /dev/null +++ b/src/Symfony/Component/Console/CommandLoader/CommandLoaderInterface.php @@ -0,0 +1,37 @@ + + */ +interface CommandLoaderInterface +{ + /** + * Loads a command. + * + * @param string $name + * + * @return Command + * + * @throws CommandNotFoundException + */ + public function get($name); + + /** + * Checks if a command exists. + * + * @param string $name + * + * @return bool + */ + public function has($name); + + /** + * @return string[] All registered command names + */ + public function getNames(); +} diff --git a/src/Symfony/Component/Console/CommandLoader/ContainerCommandLoader.php b/src/Symfony/Component/Console/CommandLoader/ContainerCommandLoader.php new file mode 100644 index 0000000000000..753ad0fb705c2 --- /dev/null +++ b/src/Symfony/Component/Console/CommandLoader/ContainerCommandLoader.php @@ -0,0 +1,55 @@ + + */ +class ContainerCommandLoader implements CommandLoaderInterface +{ + private $container; + private $commandMap; + + /** + * @param ContainerInterface $container A container from which to load command services + * @param array $commandMap An array with command names as keys and service ids as values + */ + public function __construct(ContainerInterface $container, array $commandMap) + { + $this->container = $container; + $this->commandMap = $commandMap; + } + + /** + * {@inheritdoc} + */ + public function get($name) + { + if (!$this->has($name)) { + throw new CommandNotFoundException(sprintf('Command "%s" does not exist.', $name)); + } + + return $this->container->get($this->commandMap[$name]); + } + + /** + * {@inheritdoc} + */ + public function has($name) + { + return isset($this->commandMap[$name]) && $this->container->has($this->commandMap[$name]); + } + + /** + * {@inheritdoc} + */ + public function getNames() + { + return array_keys($this->commandMap); + } +} diff --git a/src/Symfony/Component/Console/DependencyInjection/AddConsoleCommandPass.php b/src/Symfony/Component/Console/DependencyInjection/AddConsoleCommandPass.php index d0626be16b2cf..5a323421b13e8 100644 --- a/src/Symfony/Component/Console/DependencyInjection/AddConsoleCommandPass.php +++ b/src/Symfony/Component/Console/DependencyInjection/AddConsoleCommandPass.php @@ -12,9 +12,12 @@ namespace Symfony\Component\Console\DependencyInjection; use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\CommandLoader\ContainerCommandLoader; use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; +use Symfony\Component\DependencyInjection\Compiler\ServiceLocatorTagPass; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; +use Symfony\Component\DependencyInjection\TypedReference; /** * Registers console commands. @@ -23,9 +26,20 @@ */ class AddConsoleCommandPass implements CompilerPassInterface { + private $commandLoaderServiceId; + private $commandTag; + + public function __construct($commandLoaderServiceId = 'console.command_loader', $commandTag = 'console.command') + { + $this->commandLoaderServiceId = $commandLoaderServiceId; + $this->commandTag = $commandTag; + } + public function process(ContainerBuilder $container) { - $commandServices = $container->findTaggedServiceIds('console.command', true); + $commandServices = $container->findTaggedServiceIds($this->commandTag, true); + $lazyCommandMap = array(); + $lazyCommandRefs = array(); $serviceIds = array(); foreach ($commandServices as $id => $tags) { @@ -36,21 +50,52 @@ public function process(ContainerBuilder $container) throw new InvalidArgumentException(sprintf('Class "%s" used for service "%s" cannot be found.', $class, $id)); } if (!$r->isSubclassOf(Command::class)) { - throw new InvalidArgumentException(sprintf('The service "%s" tagged "console.command" must be a subclass of "%s".', $id, Command::class)); + throw new InvalidArgumentException(sprintf('The service "%s" tagged "%s" must be a subclass of "%s".', $id, $this->commandTag, Command::class)); } $commandId = 'console.command.'.strtolower(str_replace('\\', '_', $class)); - if ($container->hasAlias($commandId) || isset($serviceIds[$commandId])) { - $commandId = $commandId.'_'.$id; + + if (!isset($tags[0]['command'])) { + if (isset($serviceIds[$commandId]) || $container->hasAlias($commandId)) { + $commandId = $commandId.'_'.$id; + } + if (!$definition->isPublic()) { + $container->setAlias($commandId, $id); + $id = $commandId; + } + $serviceIds[$commandId] = $id; + + continue; } - if (!$definition->isPublic()) { - $container->setAlias($commandId, $id); - $id = $commandId; + + $serviceIds[$commandId] = false; + $commandName = $tags[0]['command']; + $lazyCommandMap[$commandName] = $id; + $lazyCommandRefs[$id] = new TypedReference($id, $class); + $aliases = array(); + + foreach ($tags as $tag) { + if (!isset($tag['command'])) { + throw new InvalidArgumentException(sprintf('Missing "command" attribute on tag "%s" for service "%s".', $this->commandTag, $id)); + } + if ($commandName !== $tag['command']) { + throw new InvalidArgumentException(sprintf('The "command" attribute must be the same on each "%s" tag for service "%s".', $this->commandTag, $id)); + } + if (isset($tag['alias'])) { + $aliases[] = $tag['alias']; + $lazyCommandMap[$tag['alias']] = $id; + } } - $serviceIds[$commandId] = $id; + if ($aliases) { + $definition->addMethodCall('setAliases', array($aliases)); + } } + $container + ->register($this->commandLoaderServiceId, ContainerCommandLoader::class) + ->setArguments(array(ServiceLocatorTagPass::register($container, $lazyCommandRefs), $lazyCommandMap)); + $container->setParameter('console.command.ids', $serviceIds); } } diff --git a/src/Symfony/Component/Console/Tests/ApplicationTest.php b/src/Symfony/Component/Console/Tests/ApplicationTest.php index 34d9cb0c0d780..7bf76ddc8e83d 100644 --- a/src/Symfony/Component/Console/Tests/ApplicationTest.php +++ b/src/Symfony/Component/Console/Tests/ApplicationTest.php @@ -13,6 +13,9 @@ use PHPUnit\Framework\TestCase; use Symfony\Component\Console\Application; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\CommandLoader\ContainerCommandLoader; +use Symfony\Component\Console\DependencyInjection\AddConsoleCommandPass; use Symfony\Component\Console\Helper\HelperSet; use Symfony\Component\Console\Helper\FormatterHelper; use Symfony\Component\Console\Input\ArgvInput; @@ -31,6 +34,8 @@ use Symfony\Component\Console\Event\ConsoleExceptionEvent; use Symfony\Component\Console\Event\ConsoleTerminateEvent; use Symfony\Component\Console\Exception\CommandNotFoundException; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\ServiceLocator; use Symfony\Component\EventDispatcher\EventDispatcher; class ApplicationTest extends TestCase @@ -114,6 +119,26 @@ public function testAll() $this->assertCount(1, $commands, '->all() takes a namespace as its first argument'); } + public function testAllWithCommandLoader() + { + $application = new Application(); + $commands = $application->all(); + $this->assertInstanceOf('Symfony\\Component\\Console\\Command\\HelpCommand', $commands['help'], '->all() returns the registered commands'); + + $application->add(new \FooCommand()); + $commands = $application->all('foo'); + $this->assertCount(1, $commands, '->all() takes a namespace as its first argument'); + + $application->setCommandLoader(new ContainerCommandLoader( + new ServiceLocator(array('foo-bar' => function () { return new \Foo1Command(); })), + array('foo:bar1' => 'foo-bar') + )); + $commands = $application->all('foo'); + $this->assertCount(2, $commands, '->all() takes a namespace as its first argument'); + $this->assertInstanceOf(\FooCommand::class, $commands['foo:bar'], '->all() returns the registered commands'); + $this->assertInstanceOf(\Foo1Command::class, $commands['foo:bar1'], '->all() returns the registered commands'); + } + public function testRegister() { $application = new Application(); @@ -166,6 +191,30 @@ public function testHasGet() $this->assertInstanceOf('Symfony\Component\Console\Command\HelpCommand', $command, '->get() returns the help command if --help is provided as the input'); } + public function testHasGetWithCommandLoader() + { + $application = new Application(); + $this->assertTrue($application->has('list'), '->has() returns true if a named command is registered'); + $this->assertFalse($application->has('afoobar'), '->has() returns false if a named command is not registered'); + + $application->add($foo = new \FooCommand()); + $this->assertTrue($application->has('afoobar'), '->has() returns true if an alias is registered'); + $this->assertEquals($foo, $application->get('foo:bar'), '->get() returns a command by name'); + $this->assertEquals($foo, $application->get('afoobar'), '->get() returns a command by alias'); + + $application->setCommandLoader(new ContainerCommandLoader(new ServiceLocator(array( + 'foo-bar' => function () { return new \Foo1Command(); }, + )), array('foo:bar1' => 'foo-bar', 'afoobar1' => 'foo-bar'))); + + $this->assertTrue($application->has('afoobar'), '->has() returns true if an instance is registered for an alias even with command loader'); + $this->assertEquals($foo, $application->get('foo:bar'), '->get() returns an instance by name even with command loader'); + $this->assertEquals($foo, $application->get('afoobar'), '->get() returns an instance by alias even with command loader'); + $this->assertTrue($application->has('foo:bar1'), '->has() returns true for commands registered in the loader'); + $this->assertInstanceOf(\Foo1Command::class, $foo1 = $application->get('foo:bar1'), '->get() returns a command by name from the command loader'); + $this->assertTrue($application->has('afoobar1'), '->has() returns true for commands registered in the loader'); + $this->assertEquals($foo1, $application->get('afoobar1'), '->get() returns a command by name from the command loader'); + } + public function testSilentHelp() { $application = new Application(); @@ -269,6 +318,20 @@ public function testFind() $this->assertInstanceOf('FooCommand', $application->find('a'), '->find() returns a command if the abbreviation exists for an alias'); } + public function testFindWithCommandLoader() + { + $application = new Application(); + $application->setCommandLoader(new ContainerCommandLoader(new ServiceLocator(array( + 'foo-bar' => $f = function () { return new \FooCommand(); }, + )), array('foo:bar' => 'foo-bar'))); + + $this->assertInstanceOf('FooCommand', $application->find('foo:bar'), '->find() returns a command if its name exists'); + $this->assertInstanceOf('Symfony\Component\Console\Command\HelpCommand', $application->find('h'), '->find() returns a command if its name exists'); + $this->assertInstanceOf('FooCommand', $application->find('f:bar'), '->find() returns a command if the abbreviation for the namespace exists'); + $this->assertInstanceOf('FooCommand', $application->find('f:b'), '->find() returns a command if the abbreviation for the namespace and the command name exist'); + $this->assertInstanceOf('FooCommand', $application->find('a'), '->find() returns a command if the abbreviation exists for an alias'); + } + /** * @dataProvider provideAmbiguousAbbreviations */ @@ -1362,6 +1425,35 @@ public function testCanCheckIfTerminalIsInteractive() $this->assertEquals($tester->getInput()->isInteractive(), @posix_isatty($inputStream)); } + public function testRunLazyCommandService() + { + $container = new ContainerBuilder(); + $container->addCompilerPass(new AddConsoleCommandPass()); + $container + ->register('lazy-command', LazyCommand::class) + ->addTag('console.command', array('command' => 'lazy:command', 'alias' => 'lazy:alias')) + ->addTag('console.command', array('command' => 'lazy:command', 'alias' => 'lazy:alias2')); + $container->compile(); + + $application = new Application(); + $application->setCommandLoader($container->get('console.command_loader')); + $application->setAutoExit(false); + + $tester = new ApplicationTester($application); + + $tester->run(array('command' => 'lazy:command')); + $this->assertSame("lazy-command called\n", $tester->getDisplay(true)); + + $tester->run(array('command' => 'lazy:alias')); + $this->assertSame("lazy-command called\n", $tester->getDisplay(true)); + + $tester->run(array('command' => 'lazy:alias2')); + $this->assertSame("lazy-command called\n", $tester->getDisplay(true)); + + $command = $application->get('lazy:command'); + $this->assertSame(array('lazy:alias', 'lazy:alias2'), $command->getAliases()); + } + protected function getDispatcher($skipCommand = false) { $dispatcher = new EventDispatcher(); @@ -1449,3 +1541,11 @@ public function __construct() $this->setDefaultCommand($command->getName()); } } + +class LazyCommand extends Command +{ + public function execute(InputInterface $input, OutputInterface $output) + { + $output->writeln('lazy-command called'); + } +} diff --git a/src/Symfony/Component/Console/Tests/Command/CommandTest.php b/src/Symfony/Component/Console/Tests/Command/CommandTest.php index 93b4721c393dd..4fcbf95753bb8 100644 --- a/src/Symfony/Component/Console/Tests/Command/CommandTest.php +++ b/src/Symfony/Component/Console/Tests/Command/CommandTest.php @@ -46,7 +46,7 @@ public function testConstructor() */ public function testCommandNameCannotBeEmpty() { - new Command(); + (new Application())->add(new Command()); } public function testSetApplication() diff --git a/src/Symfony/Component/Console/Tests/CommandLoader/ContainerCommandLoaderTest.php b/src/Symfony/Component/Console/Tests/CommandLoader/ContainerCommandLoaderTest.php new file mode 100644 index 0000000000000..78eefd24f1b3d --- /dev/null +++ b/src/Symfony/Component/Console/Tests/CommandLoader/ContainerCommandLoaderTest.php @@ -0,0 +1,61 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Tests\CommandLoader; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\CommandLoader\ContainerCommandLoader; +use Symfony\Component\DependencyInjection\ServiceLocator; + +class ContainerCommandLoaderTest extends TestCase +{ + public function testHas() + { + $loader = new ContainerCommandLoader(new ServiceLocator(array( + 'foo-service' => function () { return new Command('foo'); }, + 'bar-service' => function () { return new Command('bar'); }, + )), array('foo' => 'foo-service', 'bar' => 'bar-service')); + + $this->assertTrue($loader->has('foo')); + $this->assertTrue($loader->has('bar')); + $this->assertFalse($loader->has('baz')); + } + + public function testGet() + { + $loader = new ContainerCommandLoader(new ServiceLocator(array( + 'foo-service' => function () { return new Command('foo'); }, + 'bar-service' => function () { return new Command('bar'); }, + )), array('foo' => 'foo-service', 'bar' => 'bar-service')); + + $this->assertInstanceOf(Command::class, $loader->get('foo')); + $this->assertInstanceOf(Command::class, $loader->get('bar')); + } + + /** + * @expectedException \Symfony\Component\Console\Exception\CommandNotFoundException + */ + public function testGetUnknownCommandThrows() + { + (new ContainerCommandLoader(new ServiceLocator(array()), array()))->get('unknown'); + } + + public function testGetCommandNames() + { + $loader = new ContainerCommandLoader(new ServiceLocator(array( + 'foo-service' => function () { return new Command('foo'); }, + 'bar-service' => function () { return new Command('bar'); }, + )), array('foo' => 'foo-service', 'bar' => 'bar-service')); + + $this->assertSame(array('foo', 'bar'), $loader->getNames()); + } +} diff --git a/src/Symfony/Component/Console/Tests/DependencyInjection/AddConsoleCommandPassTest.php b/src/Symfony/Component/Console/Tests/DependencyInjection/AddConsoleCommandPassTest.php index 0cf4631754522..6454dd63df8db 100644 --- a/src/Symfony/Component/Console/Tests/DependencyInjection/AddConsoleCommandPassTest.php +++ b/src/Symfony/Component/Console/Tests/DependencyInjection/AddConsoleCommandPassTest.php @@ -12,10 +12,13 @@ namespace Symfony\Component\Console\Tests\DependencyInjection; use PHPUnit\Framework\TestCase; +use Symfony\Component\Console\CommandLoader\ContainerCommandLoader; use Symfony\Component\Console\DependencyInjection\AddConsoleCommandPass; use Symfony\Component\Console\Command\Command; +use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Definition; +use Symfony\Component\DependencyInjection\TypedReference; use Symfony\Component\HttpKernel\Bundle\Bundle; class AddConsoleCommandPassTest extends TestCase @@ -53,6 +56,26 @@ public function testProcess($public) $this->assertSame(array($alias => $id), $container->getParameter('console.command.ids')); } + public function testProcessRegisterLazyCommands() + { + $container = new ContainerBuilder(); + $container + ->register('my-command', MyCommand::class) + ->setPublic(false) + ->addTag('console.command', array('command' => 'my:command', 'alias' => 'my:alias')) + ; + + (new AddConsoleCommandPass())->process($container); + + $commandLoader = $container->getDefinition('console.command_loader'); + $commandLocator = $container->getDefinition((string) $commandLoader->getArgument(0)); + + $this->assertSame(ContainerCommandLoader::class, $commandLoader->getClass()); + $this->assertSame(array('my:command' => 'my-command', 'my:alias' => 'my-command'), $commandLoader->getArgument(1)); + $this->assertEquals(array(array('my-command' => new ServiceClosureArgument(new TypedReference('my-command', MyCommand::class)))), $commandLocator->getArguments()); + $this->assertSame(array('console.command.symfony_component_console_tests_dependencyinjection_mycommand' => false), $container->getParameter('console.command.ids')); + } + public function visibilityProvider() { return array( @@ -72,7 +95,7 @@ public function testProcessThrowAnExceptionIfTheServiceIsAbstract() $container->addCompilerPass(new AddConsoleCommandPass()); $definition = new Definition('Symfony\Component\Console\Tests\DependencyInjection\MyCommand'); - $definition->addTag('console.command'); + $definition->addTag('console.command', array('command' => 'my:command')); $definition->setAbstract(true); $container->setDefinition('my-command', $definition); @@ -90,7 +113,7 @@ public function testProcessThrowAnExceptionIfTheServiceIsNotASubclassOfCommand() $container->addCompilerPass(new AddConsoleCommandPass()); $definition = new Definition('SplObjectStorage'); - $definition->addTag('console.command'); + $definition->addTag('console.command', array('command' => 'my:command')); $container->setDefinition('my-command', $definition); $container->compile(); From 4bd7b921f4047fa32478459a9b50e63001372aee Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Wed, 12 Jul 2017 12:01:37 +0200 Subject: [PATCH 0410/1099] [DI] Remove remaining deprecated features --- .../Bundle/FrameworkBundle/CHANGELOG.md | 1 + .../FrameworkExtension.php | 11 +- .../DependencyInjection/CHANGELOG.md | 8 ++ .../DependencyInjection/ChildDefinition.php | 2 - .../Compiler/AutowirePass.php | 68 +-------- .../DependencyInjection/Compiler/Compiler.php | 32 ----- .../Compiler/FactoryReturnTypePass.php | 108 -------------- .../Compiler/LoggingFormatter.php | 54 ------- .../Compiler/PassConfig.php | 3 +- .../Compiler/ResolveClassPass.php | 16 --- .../Config/AutowireServiceResource.php | 78 ----------- .../DependencyInjection/ContainerBuilder.php | 16 --- .../DefinitionDecorator.php | 29 ---- .../Loader/XmlFileLoader.php | 26 +--- .../schema/dic/services/services-1.0.xsd | 2 - .../Tests/ChildDefinitionTest.php | 6 - .../Tests/Compiler/AutowirePassTest.php | 97 ++----------- .../Compiler/FactoryReturnTypePassTest.php | 109 --------------- .../Config/AutowireServiceResourceTest.php | 124 ---------------- .../Tests/ContainerBuilderTest.php | 26 ---- .../Tests/DefinitionDecoratorTest.php | 132 ------------------ ...ition.xml => invalid_alias_definition.xml} | 7 +- .../Tests/Fixtures/xml/services5.xml | 3 - .../Tests/Loader/XmlFileLoaderTest.php | 24 +--- .../Component/HttpFoundation/Request.php | 2 +- 25 files changed, 40 insertions(+), 944 deletions(-) delete mode 100644 src/Symfony/Component/DependencyInjection/Compiler/FactoryReturnTypePass.php delete mode 100644 src/Symfony/Component/DependencyInjection/Compiler/LoggingFormatter.php delete mode 100644 src/Symfony/Component/DependencyInjection/Config/AutowireServiceResource.php delete mode 100644 src/Symfony/Component/DependencyInjection/DefinitionDecorator.php delete mode 100644 src/Symfony/Component/DependencyInjection/Tests/Compiler/FactoryReturnTypePassTest.php delete mode 100644 src/Symfony/Component/DependencyInjection/Tests/Config/AutowireServiceResourceTest.php delete mode 100644 src/Symfony/Component/DependencyInjection/Tests/DefinitionDecoratorTest.php rename src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/{legacy_invalid_alias_definition.xml => invalid_alias_definition.xml} (62%) diff --git a/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md b/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md index cd4312f923e8a..9a765a4d96fcb 100644 --- a/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md +++ b/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md @@ -19,6 +19,7 @@ CHANGELOG * Removed absolute template paths support in the template name parser * Removed support of the `KERNEL_DIR` environment variable with `KernelTestCase::getKernelClass()`. * Removed the `KernelTestCase::getPhpUnitXmlDir()` and `KernelTestCase::getPhpUnitCliConfigArgument()` methods. + * Removed the "framework.validation.cache" configuration option. Configure the "cache.validator" service under "framework.cache.pools" instead. 3.4.0 ----- diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php index cafb0f6d24181..e97f8242932c1 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php @@ -1050,16 +1050,7 @@ private function registerValidationConfiguration(array $config, ContainerBuilder } } - if (isset($config['cache']) && $config['cache']) { - @trigger_error('The "framework.validation.cache" option is deprecated since Symfony 3.2 and will be removed in 4.0. Configure the "cache.validator" service under "framework.cache.pools" instead.', E_USER_DEPRECATED); - - $container->setParameter( - 'validator.mapping.cache.prefix', - 'validator_'.$this->getKernelRootHash($container) - ); - - $validatorBuilder->addMethodCall('setMetadataCache', array(new Reference($config['cache']))); - } elseif (!$container->getParameter('kernel.debug')) { + if (!$container->getParameter('kernel.debug')) { $validatorBuilder->addMethodCall('setMetadataCache', array(new Reference('validator.mapping.cache.symfony'))); } } diff --git a/src/Symfony/Component/DependencyInjection/CHANGELOG.md b/src/Symfony/Component/DependencyInjection/CHANGELOG.md index 7c01c34021d7e..2f31f9a29cefb 100644 --- a/src/Symfony/Component/DependencyInjection/CHANGELOG.md +++ b/src/Symfony/Component/DependencyInjection/CHANGELOG.md @@ -4,6 +4,7 @@ CHANGELOG 4.0.0 ----- + * removed autowiring services based on the types they implement * added a third `$methodName` argument to the `getProxyFactoryCode()` method of the `DumperInterface` * removed support for autowiring types @@ -11,6 +12,13 @@ CHANGELOG * removed support for dumping an ucompiled container in `PhpDumper` * removed support for generating a dumped `Container` without populating the method map * removed support for case insensitive service identifiers + * removed the `DefinitionDecorator` class, replaced by `ChildDefinition` + * removed the `AutowireServiceResource` class and related `AutowirePass::createResourceForClass()` method + * removed `LoggingFormatter`, `Compiler::getLoggingFormatter()` and `addLogMessage()` class and methods, use the `ContainerBuilder::log()` method instead + * removed `FactoryReturnTypePass` + * removed `ContainerBuilder::addClassResource()`, use the `addObjectResource()` or the `getReflectionClass()` method instead. + * removed support for top-level anonymous services + * removed silent behavior for unused attributes and elements 3.4.0 ----- diff --git a/src/Symfony/Component/DependencyInjection/ChildDefinition.php b/src/Symfony/Component/DependencyInjection/ChildDefinition.php index 5701caa474e57..644a05a3e01ed 100644 --- a/src/Symfony/Component/DependencyInjection/ChildDefinition.php +++ b/src/Symfony/Component/DependencyInjection/ChildDefinition.php @@ -121,5 +121,3 @@ public function setInstanceofConditionals(array $instanceof) throw new BadMethodCallException('A ChildDefinition cannot have instanceof conditionals set on it.'); } } - -class_alias(ChildDefinition::class, DefinitionDecorator::class); diff --git a/src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php b/src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php index 40e55d33663ae..48c7c8124870a 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php @@ -11,7 +11,6 @@ namespace Symfony\Component\DependencyInjection\Compiler; -use Symfony\Component\DependencyInjection\Config\AutowireServiceResource; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\DependencyInjection\Exception\AutowiringFailedException; @@ -67,30 +66,6 @@ public function process(ContainerBuilder $container) } } - /** - * Creates a resource to help know if this service has changed. - * - * @param \ReflectionClass $reflectionClass - * - * @return AutowireServiceResource - * - * @deprecated since version 3.3, to be removed in 4.0. Use ContainerBuilder::getReflectionClass() instead. - */ - public static function createResourceForClass(\ReflectionClass $reflectionClass) - { - @trigger_error('The '.__METHOD__.'() method is deprecated since version 3.3 and will be removed in 4.0. Use ContainerBuilder::getReflectionClass() instead.', E_USER_DEPRECATED); - - $metadata = array(); - - foreach ($reflectionClass->getMethods(\ReflectionMethod::IS_PUBLIC) as $reflectionMethod) { - if (!$reflectionMethod->isStatic()) { - $metadata[$reflectionMethod->name] = self::getResourceMetadataForMethod($reflectionMethod); - } - } - - return new AutowireServiceResource($reflectionClass->name, $reflectionClass->getFileName(), $metadata); - } - /** * {@inheritdoc} */ @@ -323,24 +298,15 @@ private function getAutowiredReference(TypedReference $reference, $deprecationMe return $reference; } - if (null === $this->types) { - $this->populateAvailableTypes(); + if (!$reference->canBeAutoregistered()) { + return; } - if (isset($this->types[$type])) { - $message = 'Autowiring services based on the types they implement is deprecated since Symfony 3.3 and won\'t be supported in version 4.0.'; - if ($aliasSuggestion = $this->getAliasesSuggestionForType($type = $reference->getType(), $deprecationMessage)) { - $message .= ' '.$aliasSuggestion; - } else { - $message .= sprintf(' You should %s the "%s" service to "%s" instead.', isset($this->types[$this->types[$type]]) ? 'alias' : 'rename (or alias)', $this->types[$type], $type); - } - - @trigger_error($message, E_USER_DEPRECATED); - - return new TypedReference($this->types[$type], $type); + if (null === $this->types) { + $this->populateAvailableTypes(); } - if (!$reference->canBeAutoregistered() || isset($this->types[$type]) || isset($this->ambiguousServiceTypes[$type])) { + if (isset($this->types[$type]) || isset($this->ambiguousServiceTypes[$type])) { return; } @@ -499,30 +465,6 @@ private function createTypeAlternatives(TypedReference $reference) return sprintf(' You should maybe alias this %s to %s.', class_exists($type, false) ? 'class' : 'interface', $message); } - /** - * @deprecated since version 3.3, to be removed in 4.0. - */ - private static function getResourceMetadataForMethod(\ReflectionMethod $method) - { - $methodArgumentsMetadata = array(); - foreach ($method->getParameters() as $parameter) { - try { - $class = $parameter->getClass(); - } catch (\ReflectionException $e) { - // type-hint is against a non-existent class - $class = false; - } - - $methodArgumentsMetadata[] = array( - 'class' => $class, - 'isOptional' => $parameter->isOptional(), - 'defaultValue' => ($parameter->isOptional() && !$parameter->isVariadic()) ? $parameter->getDefaultValue() : null, - ); - } - - return $methodArgumentsMetadata; - } - private function getAliasesSuggestionForType($type, $extraContext = null) { $aliases = array(); diff --git a/src/Symfony/Component/DependencyInjection/Compiler/Compiler.php b/src/Symfony/Component/DependencyInjection/Compiler/Compiler.php index 8f7fc32b0b1b6..5919c1db85e26 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/Compiler.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/Compiler.php @@ -52,24 +52,6 @@ public function getServiceReferenceGraph() return $this->serviceReferenceGraph; } - /** - * Returns the logging formatter which can be used by compilation passes. - * - * @return LoggingFormatter - * - * @deprecated since version 3.3, to be removed in 4.0. Use the ContainerBuilder::log() method instead. - */ - public function getLoggingFormatter() - { - if (null === $this->loggingFormatter) { - @trigger_error(sprintf('The %s() method is deprecated since version 3.3 and will be removed in 4.0. Use the ContainerBuilder::log() method instead.', __METHOD__), E_USER_DEPRECATED); - - $this->loggingFormatter = new LoggingFormatter(); - } - - return $this->loggingFormatter; - } - /** * Adds a pass to the PassConfig. * @@ -82,20 +64,6 @@ public function addPass(CompilerPassInterface $pass, $type = PassConfig::TYPE_BE $this->passConfig->addPass($pass, $type, $priority); } - /** - * Adds a log message. - * - * @param string $string The log message - * - * @deprecated since version 3.3, to be removed in 4.0. Use the ContainerBuilder::log() method instead. - */ - public function addLogMessage($string) - { - @trigger_error(sprintf('The %s() method is deprecated since version 3.3 and will be removed in 4.0. Use the ContainerBuilder::log() method instead.', __METHOD__), E_USER_DEPRECATED); - - $this->log[] = $string; - } - /** * @final */ diff --git a/src/Symfony/Component/DependencyInjection/Compiler/FactoryReturnTypePass.php b/src/Symfony/Component/DependencyInjection/Compiler/FactoryReturnTypePass.php deleted file mode 100644 index 8834ff7e4f2b7..0000000000000 --- a/src/Symfony/Component/DependencyInjection/Compiler/FactoryReturnTypePass.php +++ /dev/null @@ -1,108 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Compiler; - -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Definition; -use Symfony\Component\DependencyInjection\Reference; - -/** - * @author Guilhem N. - * - * @deprecated since version 3.3, to be removed in 4.0. - */ -class FactoryReturnTypePass implements CompilerPassInterface -{ - private $resolveClassPass; - - public function __construct(ResolveClassPass $resolveClassPass = null) - { - if (null === $resolveClassPass) { - @trigger_error('The '.__CLASS__.' class is deprecated since version 3.3 and will be removed in 4.0.', E_USER_DEPRECATED); - } - $this->resolveClassPass = $resolveClassPass; - } - - /** - * {@inheritdoc} - */ - public function process(ContainerBuilder $container) - { - $resolveClassPassChanges = null !== $this->resolveClassPass ? $this->resolveClassPass->getChanges() : array(); - - foreach ($container->getDefinitions() as $id => $definition) { - $this->updateDefinition($container, $id, $definition, $resolveClassPassChanges); - } - } - - private function updateDefinition(ContainerBuilder $container, $id, Definition $definition, array $resolveClassPassChanges, array $previous = array()) - { - // circular reference - $lcId = strtolower($id); - if (isset($previous[$lcId])) { - return; - } - - $factory = $definition->getFactory(); - if (null === $factory || (!isset($resolveClassPassChanges[$lcId]) && null !== $definition->getClass())) { - return; - } - - $class = null; - if (is_string($factory)) { - try { - $m = new \ReflectionFunction($factory); - if (false !== $m->getFileName() && file_exists($m->getFileName())) { - $container->fileExists($m->getFileName()); - } - } catch (\ReflectionException $e) { - return; - } - } else { - if ($factory[0] instanceof Reference) { - $previous[$lcId] = true; - $factoryDefinition = $container->findDefinition((string) $factory[0]); - $this->updateDefinition($container, $factory[0], $factoryDefinition, $resolveClassPassChanges, $previous); - $class = $factoryDefinition->getClass(); - } else { - $class = $factory[0]; - } - - if (!$m = $container->getReflectionClass($class)) { - return; - } - try { - $m = $m->getMethod($factory[1]); - } catch (\ReflectionException $e) { - return; - } - } - - $returnType = $m->getReturnType(); - if (null !== $returnType && !$returnType->isBuiltin()) { - $returnType = $returnType->getName(); - if (null !== $class) { - $declaringClass = $m->getDeclaringClass()->getName(); - if ('self' === strtolower($returnType)) { - $returnType = $declaringClass; - } elseif ('parent' === strtolower($returnType)) { - $returnType = get_parent_class($declaringClass) ?: null; - } - } - - if (null !== $returnType && (!isset($resolveClassPassChanges[$lcId]) || $returnType !== $resolveClassPassChanges[$lcId])) { - @trigger_error(sprintf('Relying on its factory\'s return-type to define the class of service "%s" is deprecated since Symfony 3.3 and won\'t work in 4.0. Set the "class" attribute to "%s" on the service definition instead.', $id, $returnType), E_USER_DEPRECATED); - } - $definition->setClass($returnType); - } - } -} diff --git a/src/Symfony/Component/DependencyInjection/Compiler/LoggingFormatter.php b/src/Symfony/Component/DependencyInjection/Compiler/LoggingFormatter.php deleted file mode 100644 index 0e126efaa5797..0000000000000 --- a/src/Symfony/Component/DependencyInjection/Compiler/LoggingFormatter.php +++ /dev/null @@ -1,54 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Compiler; - -@trigger_error('The '.__NAMESPACE__.'\LoggingFormatter class is deprecated since version 3.3 and will be removed in 4.0. Use the ContainerBuilder::log() method instead.', E_USER_DEPRECATED); - -/** - * Used to format logging messages during the compilation. - * - * @author Johannes M. Schmitt - * - * @deprecated since version 3.3, to be removed in 4.0. Use the ContainerBuilder::log() method instead. - */ -class LoggingFormatter -{ - public function formatRemoveService(CompilerPassInterface $pass, $id, $reason) - { - return $this->format($pass, sprintf('Removed service "%s"; reason: %s.', $id, $reason)); - } - - public function formatInlineService(CompilerPassInterface $pass, $id, $target) - { - return $this->format($pass, sprintf('Inlined service "%s" to "%s".', $id, $target)); - } - - public function formatUpdateReference(CompilerPassInterface $pass, $serviceId, $oldDestId, $newDestId) - { - return $this->format($pass, sprintf('Changed reference of service "%s" previously pointing to "%s" to "%s".', $serviceId, $oldDestId, $newDestId)); - } - - public function formatResolveInheritance(CompilerPassInterface $pass, $childId, $parentId) - { - return $this->format($pass, sprintf('Resolving inheritance for "%s" (parent: %s).', $childId, $parentId)); - } - - public function formatUnusedAutowiringPatterns(CompilerPassInterface $pass, $id, array $patterns) - { - return $this->format($pass, sprintf('Autowiring\'s patterns "%s" for service "%s" don\'t match any method.', implode('", "', $patterns), $id)); - } - - public function format(CompilerPassInterface $pass, $message) - { - return sprintf('%s: %s', get_class($pass), $message); - } -} diff --git a/src/Symfony/Component/DependencyInjection/Compiler/PassConfig.php b/src/Symfony/Component/DependencyInjection/Compiler/PassConfig.php index fa6d2c72fd535..97665c1f6e828 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/PassConfig.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/PassConfig.php @@ -41,7 +41,7 @@ public function __construct() $this->beforeOptimizationPasses = array( 100 => array( - $resolveClassPass = new ResolveClassPass(), + new ResolveClassPass(), new ResolveInstanceofConditionalsPass(), ), ); @@ -53,7 +53,6 @@ public function __construct() new DecoratorServicePass(), new ResolveParameterPlaceHoldersPass(false), new ResolveFactoryClassPass(), - new FactoryReturnTypePass($resolveClassPass), new CheckDefinitionValidityPass(), new RegisterServiceSubscribersPass(), new ResolveNamedArgumentsPass(), diff --git a/src/Symfony/Component/DependencyInjection/Compiler/ResolveClassPass.php b/src/Symfony/Component/DependencyInjection/Compiler/ResolveClassPass.php index c40d6f5d3d0f1..0235e5abb8e3b 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/ResolveClassPass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/ResolveClassPass.php @@ -20,8 +20,6 @@ */ class ResolveClassPass implements CompilerPassInterface { - private $changes = array(); - /** * {@inheritdoc} */ @@ -35,22 +33,8 @@ public function process(ContainerBuilder $container) if ($definition instanceof ChildDefinition && !class_exists($id)) { throw new InvalidArgumentException(sprintf('Service definition "%s" has a parent but no class, and its name looks like a FQCN. Either the class is missing or you want to inherit it from the parent service. To resolve this ambiguity, please rename this service to a non-FQCN (e.g. using dots), or create the missing class.', $id)); } - $this->changes[strtolower($id)] = $id; $definition->setClass($id); } } } - - /** - * @internal - * - * @deprecated since 3.3, to be removed in 4.0. - */ - public function getChanges() - { - $changes = $this->changes; - $this->changes = array(); - - return $changes; - } } diff --git a/src/Symfony/Component/DependencyInjection/Config/AutowireServiceResource.php b/src/Symfony/Component/DependencyInjection/Config/AutowireServiceResource.php deleted file mode 100644 index 8b507efe82eec..0000000000000 --- a/src/Symfony/Component/DependencyInjection/Config/AutowireServiceResource.php +++ /dev/null @@ -1,78 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Config; - -@trigger_error('The '.__NAMESPACE__.'\AutowireServiceResource class is deprecated since version 3.3 and will be removed in 4.0. Use ContainerBuilder::getReflectionClass() instead.', E_USER_DEPRECATED); - -use Symfony\Component\Config\Resource\SelfCheckingResourceInterface; -use Symfony\Component\DependencyInjection\Compiler\AutowirePass; - -/** - * @deprecated since version 3.3, to be removed in 4.0. Use ContainerBuilder::getReflectionClass() instead. - */ -class AutowireServiceResource implements SelfCheckingResourceInterface, \Serializable -{ - private $class; - private $filePath; - private $autowiringMetadata = array(); - - public function __construct($class, $path, array $autowiringMetadata) - { - $this->class = $class; - $this->filePath = $path; - $this->autowiringMetadata = $autowiringMetadata; - } - - public function isFresh($timestamp) - { - if (!file_exists($this->filePath)) { - return false; - } - - // has the file *not* been modified? Definitely fresh - if (@filemtime($this->filePath) <= $timestamp) { - return true; - } - - try { - $reflectionClass = new \ReflectionClass($this->class); - } catch (\ReflectionException $e) { - // the class does not exist anymore! - return false; - } - - return (array) $this === (array) AutowirePass::createResourceForClass($reflectionClass); - } - - public function __toString() - { - return 'service.autowire.'.$this->class; - } - - public function serialize() - { - return serialize(array($this->class, $this->filePath, $this->autowiringMetadata)); - } - - public function unserialize($serialized) - { - list($this->class, $this->filePath, $this->autowiringMetadata) = unserialize($serialized, array('allowed_classes' => false)); - } - - /** - * @deprecated Implemented for compatibility with Symfony 2.8 - */ - public function getResource() - { - return $this->filePath; - } -} diff --git a/src/Symfony/Component/DependencyInjection/ContainerBuilder.php b/src/Symfony/Component/DependencyInjection/ContainerBuilder.php index a14c29d55d206..3423ad515cc23 100644 --- a/src/Symfony/Component/DependencyInjection/ContainerBuilder.php +++ b/src/Symfony/Component/DependencyInjection/ContainerBuilder.php @@ -316,22 +316,6 @@ public function addObjectResource($object) return $this; } - /** - * Adds the given class hierarchy as resources. - * - * @param \ReflectionClass $class - * - * @return $this - * - * @deprecated since version 3.3, to be removed in 4.0. Use addObjectResource() or getReflectionClass() instead. - */ - public function addClassResource(\ReflectionClass $class) - { - @trigger_error('The '.__METHOD__.'() method is deprecated since version 3.3 and will be removed in 4.0. Use the addObjectResource() or the getReflectionClass() method instead.', E_USER_DEPRECATED); - - return $this->addObjectResource($class->name); - } - /** * Retrieves the requested reflection class and registers it for resource tracking. * diff --git a/src/Symfony/Component/DependencyInjection/DefinitionDecorator.php b/src/Symfony/Component/DependencyInjection/DefinitionDecorator.php deleted file mode 100644 index 25109d16b5e80..0000000000000 --- a/src/Symfony/Component/DependencyInjection/DefinitionDecorator.php +++ /dev/null @@ -1,29 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection; - -@trigger_error('The '.__NAMESPACE__.'\DefinitionDecorator class is deprecated since version 3.3 and will be removed in 4.0. Use the Symfony\Component\DependencyInjection\ChildDefinition class instead.', E_USER_DEPRECATED); - -class_exists(ChildDefinition::class); - -if (false) { - /** - * This definition decorates another definition. - * - * @author Johannes M. Schmitt - * - * @deprecated The DefinitionDecorator class is deprecated since version 3.3 and will be removed in 4.0. Use the Symfony\Component\DependencyInjection\ChildDefinition class instead. - */ - class DefinitionDecorator extends Definition - { - } -} diff --git a/src/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php b/src/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php index 692bb3e5d85de..4bec02a8871c5 100644 --- a/src/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php +++ b/src/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php @@ -395,7 +395,7 @@ private function processAnonymousServices(\DOMDocument $xml, $file, $defaults) $node->setAttribute('id', $id); $node->setAttribute('service', $id); - $definitions[$id] = array($services[0], $file, false); + $definitions[$id] = array($services[0], $file); $services[0]->setAttribute('id', $id); // anonymous services are always private @@ -408,27 +408,16 @@ private function processAnonymousServices(\DOMDocument $xml, $file, $defaults) // anonymous services "in the wild" if (false !== $nodes = $xpath->query('//container:services/container:service[not(@id)]')) { foreach ($nodes as $node) { - @trigger_error(sprintf('Top-level anonymous services are deprecated since Symfony 3.4, the "id" attribute will be required in version 4.0 in %s at line %d.', $file, $node->getLineNo()), E_USER_DEPRECATED); - - // give it a unique name - $id = sprintf('%d_%s', ++$count, hash('sha256', $file)); - $node->setAttribute('id', $id); - $definitions[$id] = array($node, $file, true); + throw new InvalidArgumentException(sprintf('Top-level services must have "id" attribute, none found in %s at line %d.', $file, $node->getLineNo())); } } // resolve definitions uksort($definitions, 'strnatcmp'); - foreach (array_reverse($definitions) as $id => list($domElement, $file, $wild)) { - if (null !== $definition = $this->parseDefinition($domElement, $file, $wild ? $defaults : array())) { + foreach (array_reverse($definitions) as $id => list($domElement, $file)) { + if (null !== $definition = $this->parseDefinition($domElement, $file, array())) { $this->setDefinition($id, $definition); } - - if (true === $wild) { - $tmpDomElement = new \DOMElement('_services', null, self::NS); - $domElement->parentNode->replaceChild($tmpDomElement, $domElement); - $tmpDomElement->setAttribute('id', $id); - } } } @@ -481,9 +470,6 @@ private function getArgumentsAsPhp(\DOMElement $node, $name, $file, $lowercase = if (!$arg->getAttribute('id')) { throw new InvalidArgumentException(sprintf('Tag "<%s>" with type="service" has no or empty "id" attribute in "%s".', $name, $file)); } - if ($arg->hasAttribute('strict')) { - @trigger_error(sprintf('The "strict" attribute used when referencing the "%s" service is deprecated since version 3.3 and will be removed in 4.0.', $arg->getAttribute('id')), E_USER_DEPRECATED); - } $arguments[$key] = new Reference($arg->getAttribute('id'), $invalidBehavior); break; @@ -619,13 +605,13 @@ private function validateAlias(\DOMElement $alias, $file) { foreach ($alias->attributes as $name => $node) { if (!in_array($name, array('alias', 'id', 'public'))) { - @trigger_error(sprintf('Using the attribute "%s" is deprecated for the service "%s" which is defined as an alias in "%s". Allowed attributes for service aliases are "alias", "id" and "public". The XmlFileLoader will raise an exception in Symfony 4.0, instead of silently ignoring unsupported attributes.', $name, $alias->getAttribute('id'), $file), E_USER_DEPRECATED); + throw new InvalidArgumentException(sprintf('Invalid attribute "%s" defined for alias "%s" in "%s".', $name, $alias->getAttribute('id'), $file)); } } foreach ($alias->childNodes as $child) { if ($child instanceof \DOMElement && $child->namespaceURI === self::NS) { - @trigger_error(sprintf('Using the element "%s" is deprecated for the service "%s" which is defined as an alias in "%s". The XmlFileLoader will raise an exception in Symfony 4.0, instead of silently ignoring unsupported elements.', $child->localName, $alias->getAttribute('id'), $file), E_USER_DEPRECATED); + throw new InvalidArgumentException(sprintf('Invalid child element "%s" defined for alias "%s" in "%s".', $child->localName, $alias->getAttribute('id'), $file)); } } } diff --git a/src/Symfony/Component/DependencyInjection/Loader/schema/dic/services/services-1.0.xsd b/src/Symfony/Component/DependencyInjection/Loader/schema/dic/services/services-1.0.xsd index 967d080611c43..d644997e7d1a0 100644 --- a/src/Symfony/Component/DependencyInjection/Loader/schema/dic/services/services-1.0.xsd +++ b/src/Symfony/Component/DependencyInjection/Loader/schema/dic/services/services-1.0.xsd @@ -203,7 +203,6 @@ - @@ -216,7 +215,6 @@ - diff --git a/src/Symfony/Component/DependencyInjection/Tests/ChildDefinitionTest.php b/src/Symfony/Component/DependencyInjection/Tests/ChildDefinitionTest.php index a941b960746be..7f359b94f5311 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/ChildDefinitionTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/ChildDefinitionTest.php @@ -13,7 +13,6 @@ use PHPUnit\Framework\TestCase; use Symfony\Component\DependencyInjection\ChildDefinition; -use Symfony\Component\DependencyInjection\DefinitionDecorator; class ChildDefinitionTest extends TestCase { @@ -132,11 +131,6 @@ public function testGetArgumentShouldCheckBounds() $def->getArgument(1); } - public function testDefinitionDecoratorAliasExistsForBackwardsCompatibility() - { - $this->assertInstanceOf(ChildDefinition::class, new DefinitionDecorator('foo')); - } - /** * @expectedException \Symfony\Component\DependencyInjection\Exception\BadMethodCallException */ diff --git a/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowirePassTest.php b/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowirePassTest.php index d5b00fecc5af3..b94b189125d02 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowirePassTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowirePassTest.php @@ -55,10 +55,8 @@ public function testProcessVariadic() } /** - * @group legacy - * @expectedDeprecation Autowiring services based on the types they implement is deprecated since Symfony 3.3 and won't be supported in version 4.0. You should alias the "Symfony\Component\DependencyInjection\Tests\Compiler\B" service to "Symfony\Component\DependencyInjection\Tests\Compiler\A" instead. - * @expectedExceptionInSymfony4 \Symfony\Component\DependencyInjection\Exception\RuntimeException - * @expectedExceptionMessageInSymfony4 Cannot autowire service "c": argument "$a" of method "Symfony\Component\DependencyInjection\Tests\Compiler\C::__construct()" references class "Symfony\Component\DependencyInjection\Tests\Compiler\A" but no such service exists. You should maybe alias this class to the existing "Symfony\Component\DependencyInjection\Tests\Compiler\B" service. + * @expectedException \Symfony\Component\DependencyInjection\Exception\RuntimeException + * @expectedExceptionMessage Cannot autowire service "c": argument "$a" of method "Symfony\Component\DependencyInjection\Tests\Compiler\C::__construct()" references class "Symfony\Component\DependencyInjection\Tests\Compiler\A" but no such service exists. You should maybe alias this class to the existing "Symfony\Component\DependencyInjection\Tests\Compiler\B" service. */ public function testProcessAutowireParent() { @@ -76,32 +74,8 @@ public function testProcessAutowireParent() } /** - * @group legacy - * @expectedDeprecation Autowiring services based on the types they implement is deprecated since Symfony 3.3 and won't be supported in version 4.0. Try changing the type-hint for argument "$a" of method "Symfony\Component\DependencyInjection\Tests\Compiler\C::__construct()" to "Symfony\Component\DependencyInjection\Tests\Compiler\AInterface" instead. - * @expectedExceptionInSymfony4 \Symfony\Component\DependencyInjection\Exception\RuntimeException - * @expectedExceptionMessageInSymfony4 Cannot autowire service "c": argument "$a" of method "Symfony\Component\DependencyInjection\Tests\Compiler\C::__construct()" references class "Symfony\Component\DependencyInjection\Tests\Compiler\A" but no such service exists. You should maybe alias this class to the existing "Symfony\Component\DependencyInjection\Tests\Compiler\B" service. - */ - public function testProcessLegacyAutowireWithAvailableInterface() - { - $container = new ContainerBuilder(); - - $container->setAlias(AInterface::class, B::class); - $container->register(B::class); - $cDefinition = $container->register('c', __NAMESPACE__.'\C'); - $cDefinition->setAutowired(true); - - (new ResolveClassPass())->process($container); - (new AutowirePass())->process($container); - - $this->assertCount(1, $container->getDefinition('c')->getArguments()); - $this->assertEquals(B::class, (string) $container->getDefinition('c')->getArgument(0)); - } - - /** - * @group legacy - * @expectedDeprecation Autowiring services based on the types they implement is deprecated since Symfony 3.3 and won't be supported in version 4.0. You should alias the "Symfony\Component\DependencyInjection\Tests\Compiler\F" service to "Symfony\Component\DependencyInjection\Tests\Compiler\DInterface" instead. - * @expectedExceptionInSymfony4 \Symfony\Component\DependencyInjection\Exception\RuntimeException - * @expectedExceptionMessageInSymfony4 Cannot autowire service "g": argument "$d" of method "Symfony\Component\DependencyInjection\Tests\Compiler\G::__construct()" references interface "Symfony\Component\DependencyInjection\Tests\Compiler\DInterface" but no such service exists. You should maybe alias this interface to the existing "Symfony\Component\DependencyInjection\Tests\Compiler\F" service. + * @expectedException \Symfony\Component\DependencyInjection\Exception\RuntimeException + * @expectedExceptionMessage Cannot autowire service "g": argument "$d" of method "Symfony\Component\DependencyInjection\Tests\Compiler\G::__construct()" references interface "Symfony\Component\DependencyInjection\Tests\Compiler\DInterface" but no such service exists. You should maybe alias this interface to the existing "Symfony\Component\DependencyInjection\Tests\Compiler\F" service. */ public function testProcessAutowireInterface() { @@ -385,10 +359,8 @@ public function testParentClassNotFoundThrowsException() } /** - * @group legacy - * @expectedDeprecation Autowiring services based on the types they implement is deprecated since Symfony 3.3 and won't be supported in version 4.0. You should rename (or alias) the "foo" service to "Symfony\Component\DependencyInjection\Tests\Compiler\Foo" instead. - * @expectedExceptionInSymfony4 \Symfony\Component\DependencyInjection\Exception\AutowiringFailedException - * @expectedExceptionMessageInSymfony4 Cannot autowire service "bar": argument "$foo" of method "Symfony\Component\DependencyInjection\Tests\Compiler\Bar::__construct()" references class "Symfony\Component\DependencyInjection\Tests\Compiler\Foo" but this service is abstract. You should maybe alias this class to the existing "foo" service. + * @expectedException \Symfony\Component\DependencyInjection\Exception\AutowiringFailedException + * @expectedExceptionMessage Cannot autowire service "bar": argument "$foo" of method "Symfony\Component\DependencyInjection\Tests\Compiler\Bar::__construct()" references class "Symfony\Component\DependencyInjection\Tests\Compiler\Foo" but this service is abstract. You should maybe alias this class to the existing "foo" service. */ public function testDontUseAbstractServices() { @@ -590,32 +562,6 @@ public function testTypedReference() $this->assertSame(A::class, $container->getDefinition('autowired.'.A::class)->getClass()); } - /** - * @dataProvider getCreateResourceTests - * @group legacy - */ - public function testCreateResourceForClass($className, $isEqual) - { - $startingResource = AutowirePass::createResourceForClass( - new \ReflectionClass(__NAMESPACE__.'\ClassForResource') - ); - $newResource = AutowirePass::createResourceForClass( - new \ReflectionClass(__NAMESPACE__.'\\'.$className) - ); - - // hack so the objects don't differ by the class name - $startingReflObject = new \ReflectionObject($startingResource); - $reflProp = $startingReflObject->getProperty('class'); - $reflProp->setAccessible(true); - $reflProp->setValue($startingResource, __NAMESPACE__.'\\'.$className); - - if ($isEqual) { - $this->assertEquals($startingResource, $newResource); - } else { - $this->assertNotEquals($startingResource, $newResource); - } - } - public function getCreateResourceTests() { return array( @@ -657,10 +603,8 @@ public function testSetterInjectionCollisionThrowsException() } /** - * @group legacy - * @expectedDeprecation Autowiring services based on the types they implement is deprecated since Symfony 3.3 and won't be supported in version 4.0. You should rename (or alias) the "foo" service to "Symfony\Component\DependencyInjection\Tests\Compiler\Foo" instead. - * @expectedExceptionInSymfony4 \Symfony\Component\DependencyInjection\Exception\AutowiringFailedException - * @expectedExceptionMessageInSymfony4 Cannot autowire service "bar": argument "$foo" of method "Symfony\Component\DependencyInjection\Tests\Compiler\Bar::__construct()" references class "Symfony\Component\DependencyInjection\Tests\Compiler\Foo" but no such service exists. You should maybe alias this class to the existing "foo" service. + * @expectedException \Symfony\Component\DependencyInjection\Exception\AutowiringFailedException + * @expectedExceptionMessage Cannot autowire service "bar": argument "$foo" of method "Symfony\Component\DependencyInjection\Tests\Compiler\Bar::__construct()" references class "Symfony\Component\DependencyInjection\Tests\Compiler\Foo" but no such service exists. You should maybe alias this class to the existing "foo" service. */ public function testProcessDoesNotTriggerDeprecations() { @@ -748,10 +692,8 @@ public function provideNotWireableCalls() } /** - * @group legacy - * @expectedDeprecation Autowiring services based on the types they implement is deprecated since Symfony 3.3 and won't be supported in version 4.0. Try changing the type-hint for argument "$i" of method "Symfony\Component\DependencyInjection\Tests\Compiler\J::__construct()" to "Symfony\Component\DependencyInjection\Tests\Compiler\IInterface" instead. - * @expectedExceptionInSymfony4 \Symfony\Component\DependencyInjection\Exception\AutowiringFailedException - * @expectedExceptionMessageInSymfony4 Cannot autowire service "j": argument "$i" of method "Symfony\Component\DependencyInjection\Tests\Compiler\J::__construct()" references class "Symfony\Component\DependencyInjection\Tests\Compiler\I" but no such service exists. Try changing the type-hint to "Symfony\Component\DependencyInjection\Tests\Compiler\IInterface" instead. + * @expectedException \Symfony\Component\DependencyInjection\Exception\AutowiringFailedException + * @expectedExceptionMessage Cannot autowire service "j": argument "$i" of method "Symfony\Component\DependencyInjection\Tests\Compiler\J::__construct()" references class "Symfony\Component\DependencyInjection\Tests\Compiler\I" but no such service exists. Try changing the type-hint to "Symfony\Component\DependencyInjection\Tests\Compiler\IInterface" instead. */ public function testByIdAlternative() { @@ -766,25 +708,6 @@ public function testByIdAlternative() $pass->process($container); } - /** - * @group legacy - * @expectedDeprecation Autowiring services based on the types they implement is deprecated since Symfony 3.3 and won't be supported in version 4.0. Try changing the type-hint for "Symfony\Component\DependencyInjection\Tests\Compiler\A" in "Symfony\Component\DependencyInjection\Tests\Compiler\Bar" to "Symfony\Component\DependencyInjection\Tests\Compiler\AInterface" instead. - */ - public function testTypedReferenceDeprecationNotice() - { - $container = new ContainerBuilder(); - - $container->register('aClass', A::class); - $container->setAlias(AInterface::class, 'aClass'); - $container - ->register('bar', Bar::class) - ->setProperty('a', array(new TypedReference(A::class, A::class, Bar::class))) - ; - - $pass = new AutowirePass(); - $pass->process($container); - } - /** * @expectedException \Symfony\Component\DependencyInjection\Exception\AutowiringFailedException * @expectedExceptionMessage Cannot autowire service "j": argument "$i" of method "Symfony\Component\DependencyInjection\Tests\Compiler\J::__construct()" references class "Symfony\Component\DependencyInjection\Tests\Compiler\I" but no such service exists. Try changing the type-hint to "Symfony\Component\DependencyInjection\Tests\Compiler\IInterface" instead. diff --git a/src/Symfony/Component/DependencyInjection/Tests/Compiler/FactoryReturnTypePassTest.php b/src/Symfony/Component/DependencyInjection/Tests/Compiler/FactoryReturnTypePassTest.php deleted file mode 100644 index e4d16a1f60c5b..0000000000000 --- a/src/Symfony/Component/DependencyInjection/Tests/Compiler/FactoryReturnTypePassTest.php +++ /dev/null @@ -1,109 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Tests\Compiler; - -use PHPUnit\Framework\TestCase; -use Symfony\Component\DependencyInjection\Compiler\FactoryReturnTypePass; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Reference; -use Symfony\Component\DependencyInjection\Tests\Fixtures\factoryFunction; -use Symfony\Component\DependencyInjection\Tests\Fixtures\FactoryDummy; -use Symfony\Component\DependencyInjection\Tests\Fixtures\FactoryParent; - -/** - * @author Guilhem N. - * - * @group legacy - */ -class FactoryReturnTypePassTest extends TestCase -{ - public function testProcess() - { - $container = new ContainerBuilder(); - - $factory = $container->register('factory'); - $factory->setFactory(array(FactoryDummy::class, 'createFactory')); - - $container->setAlias('alias_factory', 'factory'); - - $foo = $container->register('foo'); - $foo->setFactory(array(new Reference('alias_factory'), 'create')); - - $bar = $container->register('bar', __CLASS__); - $bar->setFactory(array(new Reference('factory'), 'create')); - - $pass = new FactoryReturnTypePass(); - $pass->process($container); - - $this->assertEquals(FactoryDummy::class, $factory->getClass()); - $this->assertEquals(\stdClass::class, $foo->getClass()); - $this->assertEquals(__CLASS__, $bar->getClass()); - } - - /** - * @dataProvider returnTypesProvider - */ - public function testReturnTypes($factory, $returnType) - { - $container = new ContainerBuilder(); - - $service = $container->register('service'); - $service->setFactory($factory); - - $pass = new FactoryReturnTypePass(); - $pass->process($container); - - $this->assertEquals($returnType, $service->getClass()); - } - - public function returnTypesProvider() - { - return array( - // must be loaded before the function as they are in the same file - array(array(FactoryDummy::class, 'createBuiltin'), null), - array(array(FactoryDummy::class, 'createParent'), FactoryParent::class), - array(array(FactoryDummy::class, 'createSelf'), FactoryDummy::class), - array(factoryFunction::class, FactoryDummy::class), - ); - } - - public function testCircularReference() - { - $container = new ContainerBuilder(); - - $factory = $container->register('factory'); - $factory->setFactory(array(new Reference('factory2'), 'createSelf')); - - $factory2 = $container->register('factory2'); - $factory2->setFactory(array(new Reference('factory'), 'create')); - - $pass = new FactoryReturnTypePass(); - $pass->process($container); - - $this->assertNull($factory->getClass()); - $this->assertNull($factory2->getClass()); - } - - /** - * @expectedDeprecation Relying on its factory's return-type to define the class of service "factory" is deprecated since Symfony 3.3 and won't work in 4.0. Set the "class" attribute to "Symfony\Component\DependencyInjection\Tests\Fixtures\FactoryDummy" on the service definition instead. - */ - public function testCompile() - { - $container = new ContainerBuilder(); - - $factory = $container->register('factory'); - $factory->setFactory(array(FactoryDummy::class, 'createFactory')); - $container->compile(); - - $this->assertEquals(FactoryDummy::class, $container->getDefinition('factory')->getClass()); - } -} diff --git a/src/Symfony/Component/DependencyInjection/Tests/Config/AutowireServiceResourceTest.php b/src/Symfony/Component/DependencyInjection/Tests/Config/AutowireServiceResourceTest.php deleted file mode 100644 index 64d99e6375b8f..0000000000000 --- a/src/Symfony/Component/DependencyInjection/Tests/Config/AutowireServiceResourceTest.php +++ /dev/null @@ -1,124 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Tests\Config; - -use PHPUnit\Framework\TestCase; -use Symfony\Component\DependencyInjection\Compiler\AutowirePass; -use Symfony\Component\DependencyInjection\Config\AutowireServiceResource; - -/** - * @group legacy - */ -class AutowireServiceResourceTest extends TestCase -{ - /** - * @var AutowireServiceResource - */ - private $resource; - private $file; - private $class; - private $time; - - protected function setUp() - { - $this->file = realpath(sys_get_temp_dir()).'/tmp.php'; - $this->time = time(); - touch($this->file, $this->time); - - $this->class = __NAMESPACE__.'\Foo'; - $this->resource = new AutowireServiceResource( - $this->class, - $this->file, - array() - ); - } - - public function testToString() - { - $this->assertSame('service.autowire.'.$this->class, (string) $this->resource); - } - - public function testSerializeUnserialize() - { - $unserialized = unserialize(serialize($this->resource)); - - $this->assertEquals($this->resource, $unserialized); - } - - public function testIsFresh() - { - $this->assertTrue($this->resource->isFresh($this->time), '->isFresh() returns true if the resource has not changed in same second'); - $this->assertTrue($this->resource->isFresh($this->time + 10), '->isFresh() returns true if the resource has not changed'); - $this->assertFalse($this->resource->isFresh($this->time - 86400), '->isFresh() returns false if the resource has been updated'); - } - - public function testIsFreshForDeletedResources() - { - unlink($this->file); - - $this->assertFalse($this->resource->isFresh($this->getStaleFileTime()), '->isFresh() returns false if the resource does not exist'); - } - - public function testIsNotFreshChangedResource() - { - $oldResource = new AutowireServiceResource( - $this->class, - $this->file, - array('will_be_different') - ); - - // test with a stale file *and* a resource that *will* be different than the actual - $this->assertFalse($oldResource->isFresh($this->getStaleFileTime()), '->isFresh() returns false if the constructor arguments have changed'); - } - - public function testIsFreshSameConstructorArgs() - { - $oldResource = AutowirePass::createResourceForClass( - new \ReflectionClass(__NAMESPACE__.'\Foo') - ); - - // test with a stale file *but* the resource will not be changed - $this->assertTrue($oldResource->isFresh($this->getStaleFileTime()), '->isFresh() returns false if the constructor arguments have changed'); - } - - public function testNotFreshIfClassNotFound() - { - $resource = new AutowireServiceResource( - 'Some\Non\Existent\Class', - $this->file, - array() - ); - - $this->assertFalse($resource->isFresh($this->getStaleFileTime()), '->isFresh() returns false if the class no longer exists'); - } - - protected function tearDown() - { - if (!file_exists($this->file)) { - return; - } - - unlink($this->file); - } - - private function getStaleFileTime() - { - return $this->time - 10; - } -} - -class Foo -{ - public function __construct($foo) - { - } -} diff --git a/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php b/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php index a8b7f88313a6e..31c17c6fc2f0e 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php @@ -712,32 +712,6 @@ public function testAddObjectResource() $this->assertSame(realpath(__DIR__.'/Fixtures/includes/classes.php'), realpath($resource->getResource())); } - /** - * @group legacy - */ - public function testAddClassResource() - { - $container = new ContainerBuilder(); - - $container->setResourceTracking(false); - $container->addClassResource(new \ReflectionClass('BarClass')); - - $this->assertEmpty($container->getResources(), 'No resources get registered without resource tracking'); - - $container->setResourceTracking(true); - $container->addClassResource(new \ReflectionClass('BarClass')); - - $resources = $container->getResources(); - - $this->assertCount(2, $resources, '2 resources were registered'); - - /* @var $resource \Symfony\Component\Config\Resource\FileResource */ - $resource = end($resources); - - $this->assertInstanceOf('Symfony\Component\Config\Resource\FileResource', $resource); - $this->assertSame(realpath(__DIR__.'/Fixtures/includes/classes.php'), realpath($resource->getResource())); - } - public function testGetReflectionClass() { $container = new ContainerBuilder(); diff --git a/src/Symfony/Component/DependencyInjection/Tests/DefinitionDecoratorTest.php b/src/Symfony/Component/DependencyInjection/Tests/DefinitionDecoratorTest.php deleted file mode 100644 index 92a212ec416a6..0000000000000 --- a/src/Symfony/Component/DependencyInjection/Tests/DefinitionDecoratorTest.php +++ /dev/null @@ -1,132 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Tests; - -use PHPUnit\Framework\TestCase; -use Symfony\Component\DependencyInjection\DefinitionDecorator; - -/** - * @group legacy - */ -class DefinitionDecoratorTest extends TestCase -{ - public function testConstructor() - { - $def = new DefinitionDecorator('foo'); - - $this->assertEquals('foo', $def->getParent()); - $this->assertEquals(array(), $def->getChanges()); - } - - /** - * @dataProvider getPropertyTests - */ - public function testSetProperty($property, $changeKey) - { - $def = new DefinitionDecorator('foo'); - - $getter = 'get'.ucfirst($property); - $setter = 'set'.ucfirst($property); - - $this->assertNull($def->$getter()); - $this->assertSame($def, $def->$setter('foo')); - $this->assertEquals('foo', $def->$getter()); - $this->assertEquals(array($changeKey => true), $def->getChanges()); - } - - public function getPropertyTests() - { - return array( - array('class', 'class'), - array('factory', 'factory'), - array('configurator', 'configurator'), - array('file', 'file'), - ); - } - - public function testSetPublic() - { - $def = new DefinitionDecorator('foo'); - - $this->assertTrue($def->isPublic()); - $this->assertSame($def, $def->setPublic(false)); - $this->assertFalse($def->isPublic()); - $this->assertEquals(array('public' => true), $def->getChanges()); - } - - public function testSetLazy() - { - $def = new DefinitionDecorator('foo'); - - $this->assertFalse($def->isLazy()); - $this->assertSame($def, $def->setLazy(false)); - $this->assertFalse($def->isLazy()); - $this->assertEquals(array('lazy' => true), $def->getChanges()); - } - - public function testSetAutowired() - { - $def = new DefinitionDecorator('foo'); - - $this->assertFalse($def->isAutowired()); - $this->assertSame($def, $def->setAutowired(true)); - $this->assertTrue($def->isAutowired()); - $this->assertSame(array('autowired' => true), $def->getChanges()); - } - - public function testSetArgument() - { - $def = new DefinitionDecorator('foo'); - - $this->assertEquals(array(), $def->getArguments()); - $this->assertSame($def, $def->replaceArgument(0, 'foo')); - $this->assertEquals(array('index_0' => 'foo'), $def->getArguments()); - } - - /** - * @expectedException \InvalidArgumentException - */ - public function testReplaceArgumentShouldRequireIntegerIndex() - { - $def = new DefinitionDecorator('foo'); - - $def->replaceArgument('0', 'foo'); - } - - public function testReplaceArgument() - { - $def = new DefinitionDecorator('foo'); - - $def->setArguments(array(0 => 'foo', 1 => 'bar')); - $this->assertEquals('foo', $def->getArgument(0)); - $this->assertEquals('bar', $def->getArgument(1)); - - $this->assertSame($def, $def->replaceArgument(1, 'baz')); - $this->assertEquals('foo', $def->getArgument(0)); - $this->assertEquals('baz', $def->getArgument(1)); - - $this->assertEquals(array(0 => 'foo', 1 => 'bar', 'index_1' => 'baz'), $def->getArguments()); - } - - /** - * @expectedException \OutOfBoundsException - */ - public function testGetArgumentShouldCheckBounds() - { - $def = new DefinitionDecorator('foo'); - - $def->setArguments(array(0 => 'foo')); - $def->replaceArgument(0, 'foo'); - - $def->getArgument(1); - } -} diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/legacy_invalid_alias_definition.xml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/invalid_alias_definition.xml similarity index 62% rename from src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/legacy_invalid_alias_definition.xml rename to src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/invalid_alias_definition.xml index 52386e5bf52df..8e99561dca608 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/legacy_invalid_alias_definition.xml +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/invalid_alias_definition.xml @@ -1,11 +1,6 @@ - - - - - - + diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services5.xml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services5.xml index 721f028287750..1b72e778c3835 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services5.xml +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services5.xml @@ -18,8 +18,5 @@ - - - diff --git a/src/Symfony/Component/DependencyInjection/Tests/Loader/XmlFileLoaderTest.php b/src/Symfony/Component/DependencyInjection/Tests/Loader/XmlFileLoaderTest.php index e2ebd090ebefe..9a0376b6270f4 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Loader/XmlFileLoaderTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Loader/XmlFileLoaderTest.php @@ -183,7 +183,7 @@ public function testLoadAnonymousServices() $loader = new XmlFileLoader($container, new FileLocator(self::$fixturesPath.'/xml')); $loader->load('services5.xml'); $services = $container->getDefinitions(); - $this->assertCount(7, $services, '->load() attributes unique ids to anonymous services'); + $this->assertCount(6, $services, '->load() attributes unique ids to anonymous services'); // anonymous service as an argument $args = $services['foo']->getArguments(); @@ -212,16 +212,6 @@ public function testLoadAnonymousServices() $this->assertEquals('BuzClass', $inner->getClass(), '->load() uses the same configuration as for the anonymous ones'); $this->assertFalse($inner->isPublic()); - // "wild" service - $service = $container->findTaggedServiceIds('biz_tag'); - $this->assertCount(1, $service); - - foreach ($service as $id => $tag) { - $service = $container->getDefinition($id); - } - $this->assertEquals('BizClass', $service->getClass(), '->load() uses the same configuration as for the anonymous ones'); - $this->assertTrue($service->isPublic()); - // anonymous services are shared when using decoration definitions $container->compile(); $services = $container->getDefinitions(); @@ -231,8 +221,8 @@ public function testLoadAnonymousServices() } /** - * @group legacy - * @expectedDeprecation Top-level anonymous services are deprecated since Symfony 3.4, the "id" attribute will be required in version 4.0 in %sservices_without_id.xml at line 4. + * @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException + * @expectedExceptionMessage Top-level services must have "id" attribute, none found in */ public function testLoadAnonymousServicesWithoutId() { @@ -625,17 +615,15 @@ public function testPrototype() } /** - * @group legacy - * @expectedDeprecation Using the attribute "class" is deprecated for the service "bar" which is defined as an alias %s. - * @expectedDeprecation Using the element "tag" is deprecated for the service "bar" which is defined as an alias %s. - * @expectedDeprecation Using the element "factory" is deprecated for the service "bar" which is defined as an alias %s. + * @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException + * @expectedExceptionMessage Invalid attribute "class" defined for alias "bar" in */ public function testAliasDefinitionContainsUnsupportedElements() { $container = new ContainerBuilder(); $loader = new XmlFileLoader($container, new FileLocator(self::$fixturesPath.'/xml')); - $loader->load('legacy_invalid_alias_definition.xml'); + $loader->load('invalid_alias_definition.xml'); $this->assertTrue($container->has('bar')); } diff --git a/src/Symfony/Component/HttpFoundation/Request.php b/src/Symfony/Component/HttpFoundation/Request.php index e38eb7b7822f8..ed60a1606c3bb 100644 --- a/src/Symfony/Component/HttpFoundation/Request.php +++ b/src/Symfony/Component/HttpFoundation/Request.php @@ -1418,7 +1418,7 @@ public function isMethodSafe(/* $andCacheable = true */) { if (!func_num_args() || func_get_arg(0)) { // setting $andCacheable to false should be deprecated in 4.1 - throw new \BadMethodCallException('Checking only for cacheable HTTP methods with Symfony\Component\HttpFoundation\Request::isMethodSafe() is not supported.', E_USER_DEPRECATED); + throw new \BadMethodCallException('Checking only for cacheable HTTP methods with Symfony\Component\HttpFoundation\Request::isMethodSafe() is not supported.'); } return in_array($this->getMethod(), array('GET', 'HEAD', 'OPTIONS', 'TRACE')); From 05170c84a21c7ef9d6d7636c27992b58e36ae9b7 Mon Sep 17 00:00:00 2001 From: Roland Franssen Date: Mon, 10 Jul 2017 20:09:41 +0200 Subject: [PATCH 0411/1099] [DI] Handle root namespace in service definitions --- .../DependencyInjection/Dumper/PhpDumper.php | 16 ++++++---------- .../Tests/Dumper/PhpDumperTest.php | 13 +++++++++++++ 2 files changed, 19 insertions(+), 10 deletions(-) diff --git a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php index 09d22fcb5fd3d..1665f7542b7ce 100644 --- a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php +++ b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php @@ -377,15 +377,9 @@ private function addServiceReturn($id, $definition) */ private function addServiceInstance($id, Definition $definition) { - $class = $definition->getClass(); - - if ('\\' === substr($class, 0, 1)) { - $class = substr($class, 1); - } - - $class = $this->dumpValue($class); + $class = $this->dumpValue($definition->getClass()); - if (0 === strpos($class, "'") && !preg_match('/^\'[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*(\\\{2}[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)*\'$/', $class)) { + if (0 === strpos($class, "'") && !preg_match('/^\'(?:\\\{2})?[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*(?:\\\{2}[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)*\'$/', $class)) { throw new InvalidArgumentException(sprintf('"%s" is not a valid class name for the "%s" service.', $class, $id)); } @@ -1440,11 +1434,13 @@ private function dumpLiteralClass($class) if (false !== strpos($class, '$')) { throw new RuntimeException('Cannot dump definitions which have a variable class name.'); } - if (0 !== strpos($class, "'") || !preg_match('/^\'[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*(\\\{2}[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)*\'$/', $class)) { + if (0 !== strpos($class, "'") || !preg_match('/^\'(?:\\\{2})?[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*(?:\\\{2}[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)*\'$/', $class)) { throw new RuntimeException(sprintf('Cannot dump definition because of invalid class name (%s)', $class ?: 'n/a')); } - return '\\'.substr(str_replace('\\\\', '\\', $class), 1, -1); + $class = substr(str_replace('\\\\', '\\', $class), 1, -1); + + return 0 === strpos($class, '\\') ? $class : '\\'.$class; } /** diff --git a/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php b/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php index 41b6c375d8aab..1ce5b7b9993d8 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php @@ -339,4 +339,17 @@ public function testCircularReferenceAllowanceForInlinedDefinitionsForLazyServic $this->addToAssertionCount(1); } + + public function testDumpHandlesLiteralClassWithRootNamespace() + { + $container = new ContainerBuilder(); + $container->register('foo', '\\stdClass'); + + $dumper = new PhpDumper($container); + eval('?>'.$dumper->dump(array('class' => 'Symfony_DI_PhpDumper_Test_Literal_Class_With_Root_Namespace'))); + + $container = new \Symfony_DI_PhpDumper_Test_Literal_Class_With_Root_Namespace(); + + $this->assertInstanceOf('stdClass', $container->get('foo')); + } } From 1aa7d68a26e49b11cd5ede3d511dfca5223fe9c2 Mon Sep 17 00:00:00 2001 From: Dany Maillard Date: Tue, 4 Jul 2017 13:07:48 +0200 Subject: [PATCH 0412/1099] Remove enhance sigchild compatibility --- .travis.yml | 2 +- src/Symfony/Component/Process/Process.php | 66 ++----------------- .../Component/Process/Tests/ProcessTest.php | 66 ++----------------- 3 files changed, 11 insertions(+), 123 deletions(-) diff --git a/.travis.yml b/.travis.yml index 66b0e596ecea6..0cabd5b4e6898 100644 --- a/.travis.yml +++ b/.travis.yml @@ -158,7 +158,7 @@ install: echo "$COMPONENTS" | parallel --gnu "tfold {} $PHPUNIT_X {}" tfold tty-group $PHPUNIT --group tty if [[ $PHP = $MIN_PHP ]]; then - echo -e "1\\n0" | xargs -I{} bash -c "tfold src/Symfony/Component/Process.sigchild{} SYMFONY_DEPRECATIONS_HELPER=weak ENHANCE_SIGCHLD={} php-$MIN_PHP/sapi/cli/php ./phpunit --colors=always src/Symfony/Component/Process/" + tfold src/Symfony/Component/Process.sigchild SYMFONY_DEPRECATIONS_HELPER=weak php-$MIN_PHP/sapi/cli/php ./phpunit --colors=always src/Symfony/Component/Process/ fi fi } diff --git a/src/Symfony/Component/Process/Process.php b/src/Symfony/Component/Process/Process.php index a34db920ef545..d0f6c0ce451e9 100644 --- a/src/Symfony/Component/Process/Process.php +++ b/src/Symfony/Component/Process/Process.php @@ -64,7 +64,6 @@ class Process implements \IteratorAggregate private $outputDisabled = false; private $stdout; private $stderr; - private $enhanceSigchildCompatibility; private $process; private $status = self::STATUS_READY; private $incrementalOutputOffset = 0; @@ -165,7 +164,6 @@ public function __construct($commandline, $cwd = null, array $env = null, $input $this->setTimeout($timeout); $this->useFileHandles = '\\' === DIRECTORY_SEPARATOR; $this->pty = false; - $this->enhanceSigchildCompatibility = '\\' !== DIRECTORY_SEPARATOR && $this->isSigchildEnabled(); } public function __destruct() @@ -218,17 +216,12 @@ public function run($callback = null, array $env = array()) * * @return self * - * @throws RuntimeException if PHP was compiled with --enable-sigchild and the enhanced sigchild compatibility mode is not enabled * @throws ProcessFailedException if the process didn't terminate successfully * * @final since version 3.3 */ public function mustRun(callable $callback = null, array $env = array()) { - if (!$this->enhanceSigchildCompatibility && $this->isSigchildEnabled()) { - throw new RuntimeException('This PHP has been compiled with --enable-sigchild. You must use setEnhanceSigchildCompatibility() to use this method.'); - } - if (0 !== $this->run($callback, $env)) { throw new ProcessFailedException($this); } @@ -297,7 +290,7 @@ public function start(callable $callback = null, array $env = array()) if ('\\' === DIRECTORY_SEPARATOR) { $options['bypass_shell'] = true; $commandline = $this->prepareWindowsCommandLine($commandline, $envBackup, $env); - } elseif (!$this->useFileHandles && $this->enhanceSigchildCompatibility && $this->isSigchildEnabled()) { + } elseif (!$this->useFileHandles && $this->isSigchildEnabled()) { // last exit code is output on the fourth pipe and caught to work around --enable-sigchild $descriptors[3] = array('pipe', 'w'); @@ -665,15 +658,9 @@ public function clearErrorOutput() * Returns the exit code returned by the process. * * @return null|int The exit status code, null if the Process is not terminated - * - * @throws RuntimeException In case --enable-sigchild is activated and the sigchild compatibility mode is disabled */ public function getExitCode() { - if (!$this->enhanceSigchildCompatibility && $this->isSigchildEnabled()) { - throw new RuntimeException('This PHP has been compiled with --enable-sigchild. You must use setEnhanceSigchildCompatibility() to use this method.'); - } - $this->updateStatus(false); return $this->exitcode; @@ -716,17 +703,12 @@ public function isSuccessful() * * @return bool * - * @throws RuntimeException In case --enable-sigchild is activated - * @throws LogicException In case the process is not terminated + * @throws LogicException In case the process is not terminated */ public function hasBeenSignaled() { $this->requireProcessIsTerminated(__FUNCTION__); - if (!$this->enhanceSigchildCompatibility && $this->isSigchildEnabled()) { - throw new RuntimeException('This PHP has been compiled with --enable-sigchild. Term signal can not be retrieved.'); - } - return $this->processInformation['signaled']; } @@ -744,7 +726,7 @@ public function getTermSignal() { $this->requireProcessIsTerminated(__FUNCTION__); - if ($this->isSigchildEnabled() && (!$this->enhanceSigchildCompatibility || -1 === $this->processInformation['termsig'])) { + if ($this->isSigchildEnabled() && -1 === $this->processInformation['termsig']) { throw new RuntimeException('This PHP has been compiled with --enable-sigchild. Term signal can not be retrieved.'); } @@ -1153,42 +1135,6 @@ public function setInput($input) return $this; } - /** - * Returns whether sigchild compatibility mode is activated or not. - * - * @return bool - * - * @deprecated since version 3.3, to be removed in 4.0. Sigchild compatibility will always be enabled. - */ - public function getEnhanceSigchildCompatibility() - { - @trigger_error(sprintf('The %s() method is deprecated since version 3.3 and will be removed in 4.0. Sigchild compatibility will always be enabled.', __METHOD__), E_USER_DEPRECATED); - - return $this->enhanceSigchildCompatibility; - } - - /** - * Activates sigchild compatibility mode. - * - * Sigchild compatibility mode is required to get the exit code and - * determine the success of a process when PHP has been compiled with - * the --enable-sigchild option - * - * @param bool $enhance - * - * @return self The current Process instance - * - * @deprecated since version 3.3, to be removed in 4.0. - */ - public function setEnhanceSigchildCompatibility($enhance) - { - @trigger_error(sprintf('The %s() method is deprecated since version 3.3 and will be removed in 4.0. Sigchild compatibility will always be enabled.', __METHOD__), E_USER_DEPRECATED); - - $this->enhanceSigchildCompatibility = (bool) $enhance; - - return $this; - } - /** * Sets whether environment variables will be inherited or not. * @@ -1322,7 +1268,7 @@ protected function updateStatus($blocking) $this->readPipes($running && $blocking, '\\' !== DIRECTORY_SEPARATOR || !$running); - if ($this->fallbackStatus && $this->enhanceSigchildCompatibility && $this->isSigchildEnabled()) { + if ($this->fallbackStatus && $this->isSigchildEnabled()) { $this->processInformation = $this->fallbackStatus + $this->processInformation; } @@ -1431,7 +1377,7 @@ private function close() if ($this->processInformation['signaled'] && 0 < $this->processInformation['termsig']) { // if process has been signaled, no exitcode but a valid termsig, apply Unix convention $this->exitcode = 128 + $this->processInformation['termsig']; - } elseif ($this->enhanceSigchildCompatibility && $this->isSigchildEnabled()) { + } elseif ($this->isSigchildEnabled()) { $this->processInformation['signaled'] = true; $this->processInformation['termsig'] = -1; } @@ -1496,7 +1442,7 @@ private function doSignal($signal, $throwException) return false; } } else { - if (!$this->enhanceSigchildCompatibility || !$this->isSigchildEnabled()) { + if (!$this->isSigchildEnabled()) { $ok = @proc_terminate($this->process, $signal); } elseif (function_exists('posix_kill')) { $ok = @posix_kill($pid, $signal); diff --git a/src/Symfony/Component/Process/Tests/ProcessTest.php b/src/Symfony/Component/Process/Tests/ProcessTest.php index 9b74196c70aed..cab6595474859 100644 --- a/src/Symfony/Component/Process/Tests/ProcessTest.php +++ b/src/Symfony/Component/Process/Tests/ProcessTest.php @@ -28,7 +28,6 @@ class ProcessTest extends TestCase private static $phpBin; private static $process; private static $sigchild; - private static $notEnhancedSigchild = false; public static function setUpBeforeClass() { @@ -420,7 +419,6 @@ public function testExitCodeCommandFailed() if ('\\' === DIRECTORY_SEPARATOR) { $this->markTestSkipped('Windows does not support POSIX exit code'); } - $this->skipIfNotEnhancedSigchild(); // such command run in bash return an exitcode 127 $process = $this->getProcess('nonexistingcommandIhopeneversomeonewouldnameacommandlikethis'); @@ -455,7 +453,6 @@ public function testTTYCommandExitCode() if ('\\' === DIRECTORY_SEPARATOR) { $this->markTestSkipped('Windows does have /dev/tty support'); } - $this->skipIfNotEnhancedSigchild(); $process = $this->getProcess('echo "foo" >> /dev/null'); $process->setTty(true); @@ -481,8 +478,6 @@ public function testTTYInWindowsEnvironment() public function testExitCodeTextIsNullWhenExitCodeIsNull() { - $this->skipIfNotEnhancedSigchild(); - $process = $this->getProcess(''); $this->assertNull($process->getExitCodeText()); } @@ -503,8 +498,6 @@ public function testPTYCommand() public function testMustRun() { - $this->skipIfNotEnhancedSigchild(); - $process = $this->getProcess('echo foo'); $this->assertSame($process, $process->mustRun()); @@ -513,8 +506,6 @@ public function testMustRun() public function testSuccessfulMustRunHasCorrectExitCode() { - $this->skipIfNotEnhancedSigchild(); - $process = $this->getProcess('echo foo')->mustRun(); $this->assertEquals(0, $process->getExitCode()); } @@ -524,16 +515,12 @@ public function testSuccessfulMustRunHasCorrectExitCode() */ public function testMustRunThrowsException() { - $this->skipIfNotEnhancedSigchild(); - $process = $this->getProcess('exit 1'); $process->mustRun(); } public function testExitCodeText() { - $this->skipIfNotEnhancedSigchild(); - $process = $this->getProcess(''); $r = new \ReflectionObject($process); $p = $r->getProperty('exitcode'); @@ -562,8 +549,6 @@ public function testUpdateStatus() public function testGetExitCodeIsNullOnStart() { - $this->skipIfNotEnhancedSigchild(); - $process = $this->getProcessForCode('usleep(100000);'); $this->assertNull($process->getExitCode()); $process->start(); @@ -574,8 +559,6 @@ public function testGetExitCodeIsNullOnStart() public function testGetExitCodeIsNullOnWhenStartingAgain() { - $this->skipIfNotEnhancedSigchild(); - $process = $this->getProcessForCode('usleep(100000);'); $process->run(); $this->assertEquals(0, $process->getExitCode()); @@ -587,8 +570,6 @@ public function testGetExitCodeIsNullOnWhenStartingAgain() public function testGetExitCode() { - $this->skipIfNotEnhancedSigchild(); - $process = $this->getProcess('echo foo'); $process->run(); $this->assertSame(0, $process->getExitCode()); @@ -624,8 +605,6 @@ public function testStop() public function testIsSuccessful() { - $this->skipIfNotEnhancedSigchild(); - $process = $this->getProcess('echo foo'); $process->run(); $this->assertTrue($process->isSuccessful()); @@ -633,8 +612,6 @@ public function testIsSuccessful() public function testIsSuccessfulOnlyAfterTerminated() { - $this->skipIfNotEnhancedSigchild(); - $process = $this->getProcessForCode('usleep(100000);'); $process->start(); @@ -647,8 +624,6 @@ public function testIsSuccessfulOnlyAfterTerminated() public function testIsNotSuccessful() { - $this->skipIfNotEnhancedSigchild(); - $process = $this->getProcessForCode('throw new \Exception(\'BOUM\');'); $process->run(); $this->assertFalse($process->isSuccessful()); @@ -659,7 +634,6 @@ public function testProcessIsNotSignaled() if ('\\' === DIRECTORY_SEPARATOR) { $this->markTestSkipped('Windows does not support POSIX signals'); } - $this->skipIfNotEnhancedSigchild(); $process = $this->getProcess('echo foo'); $process->run(); @@ -671,7 +645,6 @@ public function testProcessWithoutTermSignal() if ('\\' === DIRECTORY_SEPARATOR) { $this->markTestSkipped('Windows does not support POSIX signals'); } - $this->skipIfNotEnhancedSigchild(); $process = $this->getProcess('echo foo'); $process->run(); @@ -683,7 +656,6 @@ public function testProcessIsSignaledIfStopped() if ('\\' === DIRECTORY_SEPARATOR) { $this->markTestSkipped('Windows does not support POSIX signals'); } - $this->skipIfNotEnhancedSigchild(); $process = $this->getProcessForCode('sleep(32);'); $process->start(); @@ -701,7 +673,10 @@ public function testProcessThrowsExceptionWhenExternallySignaled() if (!function_exists('posix_kill')) { $this->markTestSkipped('Function posix_kill is required.'); } - $this->skipIfNotEnhancedSigchild(false); + + if (self::$sigchild) { + $this->markTestSkipped('PHP is compiled with --enable-sigchild.'); + } $process = $this->getProcessForCode('sleep(32.1);'); $process->start(); @@ -912,8 +887,6 @@ public function testSignal() */ public function testExitCodeIsAvailableAfterSignal() { - $this->skipIfNotEnhancedSigchild(); - $process = $this->getProcess('sleep 4'); $process->start(); $process->signal(SIGKILL); @@ -1487,21 +1460,6 @@ private function getProcess($commandline, $cwd = null, array $env = null, $input $process = new Process($commandline, $cwd, $env, $input, $timeout); $process->inheritEnvironmentVariables(); - if (false !== $enhance = getenv('ENHANCE_SIGCHLD')) { - try { - $process->setEnhanceSigchildCompatibility(false); - $process->getExitCode(); - $this->fail('ENHANCE_SIGCHLD must be used together with a sigchild-enabled PHP.'); - } catch (RuntimeException $e) { - $this->assertSame('This PHP has been compiled with --enable-sigchild. You must use setEnhanceSigchildCompatibility() to use this method.', $e->getMessage()); - if ($enhance) { - $process->setEnhanceSigchildCompatibility(true); - } else { - self::$notEnhancedSigchild = true; - } - } - } - if (self::$process) { self::$process->stop(0); } @@ -1516,22 +1474,6 @@ private function getProcessForCode($code, $cwd = null, array $env = null, $input { return $this->getProcess(array(self::$phpBin, '-r', $code), $cwd, $env, $input, $timeout); } - - private function skipIfNotEnhancedSigchild($expectException = true) - { - if (self::$sigchild) { - if (!$expectException) { - $this->markTestSkipped('PHP is compiled with --enable-sigchild.'); - } elseif (self::$notEnhancedSigchild) { - if (method_exists($this, 'expectException')) { - $this->expectException('Symfony\Component\Process\Exception\RuntimeException'); - $this->expectExceptionMessage('This PHP has been compiled with --enable-sigchild.'); - } else { - $this->setExpectedException('Symfony\Component\Process\Exception\RuntimeException', 'This PHP has been compiled with --enable-sigchild.'); - } - } - } - } } class NonStringifiable From 3763515caed048518d91b3c3dd194958658dde6b Mon Sep 17 00:00:00 2001 From: Dany Maillard Date: Sun, 25 Dec 2016 20:27:49 +0100 Subject: [PATCH 0413/1099] Add TokenProcessor --- .../Monolog/Processor/TokenProcessor.php | 43 +++++++++++++++++++ .../Tests/Processor/TokenProcessorTest.php | 42 ++++++++++++++++++ src/Symfony/Bridge/Monolog/composer.json | 1 + 3 files changed, 86 insertions(+) create mode 100644 src/Symfony/Bridge/Monolog/Processor/TokenProcessor.php create mode 100644 src/Symfony/Bridge/Monolog/Tests/Processor/TokenProcessorTest.php diff --git a/src/Symfony/Bridge/Monolog/Processor/TokenProcessor.php b/src/Symfony/Bridge/Monolog/Processor/TokenProcessor.php new file mode 100644 index 0000000000000..11547be22b2ee --- /dev/null +++ b/src/Symfony/Bridge/Monolog/Processor/TokenProcessor.php @@ -0,0 +1,43 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bridge\Monolog\Processor; + +use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface; + +/** + * Adds the current security token to the log entry. + * + * @author Dany Maillard + */ +class TokenProcessor +{ + private $tokenStorage; + + public function __construct(TokenStorageInterface $tokenStorage) + { + $this->tokenStorage = $tokenStorage; + } + + public function __invoke(array $records) + { + $records['extra']['token'] = null; + if (null !== $token = $this->tokenStorage->getToken()) { + $records['extra']['token'] = array( + 'username' => $token->getUsername(), + 'authenticated' => $token->isAuthenticated(), + 'roles' => array_map(function ($role) { return $role->getRole(); }, $token->getRoles()), + ); + } + + return $records; + } +} diff --git a/src/Symfony/Bridge/Monolog/Tests/Processor/TokenProcessorTest.php b/src/Symfony/Bridge/Monolog/Tests/Processor/TokenProcessorTest.php new file mode 100644 index 0000000000000..e78acf47b54c4 --- /dev/null +++ b/src/Symfony/Bridge/Monolog/Tests/Processor/TokenProcessorTest.php @@ -0,0 +1,42 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bridge\Monolog\Tests\Processor; + +use PHPUnit\Framework\TestCase; +use Symfony\Bridge\Monolog\Processor\TokenProcessor; +use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface; +use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken; + +/** + * Tests the TokenProcessor. + * + * @author Dany Maillard + */ +class TokenProcessorTest extends TestCase +{ + public function testProcessor() + { + $token = new UsernamePasswordToken('user', 'password', 'provider', array('ROLE_USER')); + $tokenStorage = $this->getMockBuilder(TokenStorageInterface::class)->getMock(); + $tokenStorage->method('getToken')->willReturn($token); + + $processor = new TokenProcessor($tokenStorage); + $record = array('extra' => array()); + $record = $processor($record); + + $this->assertArrayHasKey('token', $record['extra']); + $this->assertEquals($token->getUsername(), $record['extra']['token']['username']); + $this->assertEquals($token->isAuthenticated(), $record['extra']['token']['authenticated']); + $roles = array_map(function ($role) { return $role->getRole(); }, $token->getRoles()); + $this->assertEquals($roles, $record['extra']['token']['roles']); + } +} diff --git a/src/Symfony/Bridge/Monolog/composer.json b/src/Symfony/Bridge/Monolog/composer.json index b627abad0a79a..fcebd789f2bc0 100644 --- a/src/Symfony/Bridge/Monolog/composer.json +++ b/src/Symfony/Bridge/Monolog/composer.json @@ -23,6 +23,7 @@ "require-dev": { "symfony/console": "~2.8|~3.0|~4.0", "symfony/event-dispatcher": "~2.8|~3.0|~4.0", + "symfony/security-core": "~2.8|~3.0|~4.0", "symfony/var-dumper": "~3.3|~4.0" }, "conflict": { From 2b2c0b7c975663b5559048a124c1ad6343feb9e9 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Wed, 12 Jul 2017 16:37:06 +0200 Subject: [PATCH 0414/1099] fix merge --- src/Symfony/Component/HttpFoundation/Tests/CookieTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/HttpFoundation/Tests/CookieTest.php b/src/Symfony/Component/HttpFoundation/Tests/CookieTest.php index 90d8f4bd4fff7..3986a7e8f8796 100644 --- a/src/Symfony/Component/HttpFoundation/Tests/CookieTest.php +++ b/src/Symfony/Component/HttpFoundation/Tests/CookieTest.php @@ -174,7 +174,7 @@ public function testRawCookie() { $cookie = new Cookie('foo', 'b a r', 0, '/', null, false, false); $this->assertFalse($cookie->isRaw()); - $this->assertEquals('foo=b+a+r; path=/', (string) $cookie); + $this->assertEquals('foo=b%20a%20r; path=/', (string) $cookie); $cookie = new Cookie('foo', 'b+a+r', 0, '/', null, false, false, true); $this->assertTrue($cookie->isRaw()); From 8e6accc4d0226278ba2118507d6a18337ad2b288 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Wed, 12 Jul 2017 16:41:59 +0200 Subject: [PATCH 0415/1099] fix merge --- .../Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php b/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php index 47c24471a66ce..3a7e9d8739f5d 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php @@ -589,6 +589,7 @@ public function testDumpHandlesLiteralClassWithRootNamespace() { $container = new ContainerBuilder(); $container->register('foo', '\\stdClass'); + $container->compile(); $dumper = new PhpDumper($container); eval('?>'.$dumper->dump(array('class' => 'Symfony_DI_PhpDumper_Test_Literal_Class_With_Root_Namespace'))); From 2e0c6bc85522af56bcd07b5e8888bf4e1238aca3 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Wed, 12 Jul 2017 16:53:35 +0200 Subject: [PATCH 0416/1099] [FrameworkBundle] Fix tests --- .../Tests/Routing/RedirectableUrlMatcherTest.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Routing/RedirectableUrlMatcherTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Routing/RedirectableUrlMatcherTest.php index fb5395ea6d26d..fd9ed77b2f7ab 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Routing/RedirectableUrlMatcherTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Routing/RedirectableUrlMatcherTest.php @@ -25,6 +25,10 @@ public function testRedirectWhenNoSlash() $coll->add('foo', new Route('/foo/')); $matcher = new RedirectableUrlMatcher($coll, $context = new RequestContext()); + $parameters = $matcher->match('/foo'); + if ('foo' === $parameters['_route']) { + $parameters['_route'] = null; // FC with behavior on 3.4 + } $this->assertEquals(array( '_controller' => 'Symfony\Bundle\FrameworkBundle\Controller\RedirectController::urlRedirectAction', @@ -35,7 +39,7 @@ public function testRedirectWhenNoSlash() 'httpsPort' => $context->getHttpsPort(), '_route' => null, ), - $matcher->match('/foo') + $parameters ); } From a73522c0de5cc9e58718c717817a85f14be4d48c Mon Sep 17 00:00:00 2001 From: Dany Maillard Date: Sun, 30 Apr 2017 17:09:09 +0200 Subject: [PATCH 0417/1099] Add interval caster --- .../Component/VarDumper/Caster/DateCaster.php | 32 +++++- .../VarDumper/Cloner/AbstractCloner.php | 1 + .../VarDumper/Tests/Caster/DateCasterTest.php | 100 ++++++++++++++++++ 3 files changed, 132 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/VarDumper/Caster/DateCaster.php b/src/Symfony/Component/VarDumper/Caster/DateCaster.php index 2fc57c190b7c3..b96660605f55d 100644 --- a/src/Symfony/Component/VarDumper/Caster/DateCaster.php +++ b/src/Symfony/Component/VarDumper/Caster/DateCaster.php @@ -27,7 +27,7 @@ public static function castDateTime(\DateTimeInterface $d, array $a, Stub $stub, $fromNow = (new \DateTime())->diff($d); $title = $d->format('l, F j, Y') - ."\n".$fromNow->format('%R').(ltrim($fromNow->format('%yy %mm %dd %H:%I:%Ss'), ' 0ymd:s') ?: '0s').' from now' + ."\n".$fromNow->format('%R').self::formatInterval($fromNow).' from now' .($location ? ($d->format('I') ? "\nDST On" : "\nDST Off") : '') ; @@ -38,4 +38,34 @@ public static function castDateTime(\DateTimeInterface $d, array $a, Stub $stub, return $a; } + + public static function castInterval(\DateInterval $interval, array $a, Stub $stub, $isNested, $filter) + { + $now = new \DateTimeImmutable(); + $numberOfSeconds = $now->add($interval)->getTimestamp() - $now->getTimestamp(); + $title = number_format($numberOfSeconds, 0, '.', ' ').'s'; + + $i = array(Caster::PREFIX_VIRTUAL.'interval' => new ConstStub(self::formatInterval($interval), $title)); + + return $filter & Caster::EXCLUDE_VERBOSE ? $i : $i + $a; + } + + private static function formatInterval(\DateInterval $i) + { + $format = '%R ' + .($i->y ? '%yy ' : '') + .($i->m ? '%mm ' : '') + .($i->d ? '%dd ' : '') + ; + + if (\PHP_VERSION_ID >= 70100 && isset($i->f)) { + $format .= $i->h || $i->i || $i->s || $i->f ? '%H:%I:%S.%F' : ''; + } else { + $format .= $i->h || $i->i || $i->s ? '%H:%I:%S' : ''; + } + + $format = '%R ' === $format ? '0s' : $format; + + return $i->format(rtrim($format)); + } } diff --git a/src/Symfony/Component/VarDumper/Cloner/AbstractCloner.php b/src/Symfony/Component/VarDumper/Cloner/AbstractCloner.php index bb2a4b85078f4..745dcc0a8e045 100644 --- a/src/Symfony/Component/VarDumper/Cloner/AbstractCloner.php +++ b/src/Symfony/Component/VarDumper/Cloner/AbstractCloner.php @@ -110,6 +110,7 @@ abstract class AbstractCloner implements ClonerInterface 'RedisArray' => array('Symfony\Component\VarDumper\Caster\RedisCaster', 'castRedisArray'), 'DateTimeInterface' => array('Symfony\Component\VarDumper\Caster\DateCaster', 'castDateTime'), + 'DateInterval' => array('Symfony\Component\VarDumper\Caster\DateCaster', 'castInterval'), ':curl' => array('Symfony\Component\VarDumper\Caster\ResourceCaster', 'castCurl'), ':dba' => array('Symfony\Component\VarDumper\Caster\ResourceCaster', 'castDba'), diff --git a/src/Symfony/Component/VarDumper/Tests/Caster/DateCasterTest.php b/src/Symfony/Component/VarDumper/Tests/Caster/DateCasterTest.php index 10f7896aec8a3..637604e24dc1f 100644 --- a/src/Symfony/Component/VarDumper/Tests/Caster/DateCasterTest.php +++ b/src/Symfony/Component/VarDumper/Tests/Caster/DateCasterTest.php @@ -12,6 +12,7 @@ namespace Symfony\Component\VarDumper\Tests\Caster; use PHPUnit\Framework\TestCase; +use Symfony\Component\VarDumper\Caster\Caster; use Symfony\Component\VarDumper\Caster\DateCaster; use Symfony\Component\VarDumper\Cloner\Stub; use Symfony\Component\VarDumper\Test\VarDumperTestTrait; @@ -84,4 +85,103 @@ public function provideDateTimes() array('2017-04-30 00:00:00.000000', '+02:00', '2017-04-30 00:00:00.000000 +02:00'), ); } + + /** + * @dataProvider provideIntervals + */ + public function testDumpInterval($intervalSpec, $invert, $expected) + { + $interval = new \DateInterval($intervalSpec); + $interval->invert = $invert; + + $xDump = <<assertDumpMatchesFormat($xDump, $interval); + } + + /** + * @dataProvider provideIntervals + */ + public function testDumpIntervalExcludingVerbosity($intervalSpec, $invert, $expected) + { + $interval = new \DateInterval($intervalSpec); + $interval->invert = $invert; + + $xDump = <<assertDumpMatchesFormat($xDump, $interval, Caster::EXCLUDE_VERBOSE); + } + + /** + * @dataProvider provideIntervals + */ + public function testCastInterval($intervalSpec, $invert, $xInterval, $xSeconds) + { + $interval = new \DateInterval($intervalSpec); + $interval->invert = $invert; + $stub = new Stub(); + + $cast = DateCaster::castInterval($interval, array('foo' => 'bar'), $stub, false, Caster::EXCLUDE_VERBOSE); + + $xDump = << $xInterval +] +EODUMP; + + $this->assertDumpMatchesFormat($xDump, $cast); + + if (null === $xSeconds) { + return; + } + + $xDump = <<assertDumpMatchesFormat($xDump, $cast["\0~\0interval"]); + } + + public function provideIntervals() + { + $i = new \DateInterval('PT0S'); + $ms = \PHP_VERSION_ID >= 70100 && isset($i->f) ? '.000000' : ''; + + return array( + array('PT0S', 0, '0s', '0s'), + array('PT1S', 0, '+ 00:00:01'.$ms, '1s'), + array('PT2M', 0, '+ 00:02:00'.$ms, '120s'), + array('PT3H', 0, '+ 03:00:00'.$ms, '10 800s'), + array('P4D', 0, '+ 4d', '345 600s'), + array('P5M', 0, '+ 5m', null), + array('P6Y', 0, '+ 6y', null), + array('P1Y2M3DT4H5M6S', 0, '+ 1y 2m 3d 04:05:06'.$ms, null), + + array('PT0S', 1, '0s', '0s'), + array('PT1S', 1, '- 00:00:01'.$ms, '-1s'), + array('PT2M', 1, '- 00:02:00'.$ms, '-120s'), + array('PT3H', 1, '- 03:00:00'.$ms, '-10 800s'), + array('P4D', 1, '- 4d', '-345 600s'), + array('P5M', 1, '- 5m', null), + array('P6Y', 1, '- 6y', null), + array('P1Y2M3DT4H5M6S', 1, '- 1y 2m 3d 04:05:06'.$ms, null), + ); + } } From c4b6066c9f16b21d9c08e785949efb47ca0fd08a Mon Sep 17 00:00:00 2001 From: Roland Franssen Date: Wed, 12 Jul 2017 20:41:02 +0200 Subject: [PATCH 0418/1099] [DI] Check privates before resolving alias in Container::initialized --- src/Symfony/Component/DependencyInjection/Container.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Symfony/Component/DependencyInjection/Container.php b/src/Symfony/Component/DependencyInjection/Container.php index cd4bed9f91392..9ee97ceead005 100644 --- a/src/Symfony/Component/DependencyInjection/Container.php +++ b/src/Symfony/Component/DependencyInjection/Container.php @@ -366,14 +366,14 @@ public function initialized($id) return false; } - if (isset($this->aliases[$id])) { - $id = $this->aliases[$id]; - } - if (isset($this->privates[$id])) { @trigger_error(sprintf('Checking for the initialization of the "%s" private service is deprecated since Symfony 3.4 and won\'t be supported anymore in Symfony 4.0.', $id), E_USER_DEPRECATED); } + if (isset($this->aliases[$id])) { + $id = $this->aliases[$id]; + } + return isset($this->services[$id]); } From 8289ca6d1ad758cfe7843c8277cfb37f19597629 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Wed, 12 Jul 2017 19:37:18 +0200 Subject: [PATCH 0419/1099] non-conflicting anonymous service ids across files --- .../Loader/YamlFileLoader.php | 6 ++--- .../Tests/Fixtures/yaml/bar/services.yml | 4 +++ .../Tests/Fixtures/yaml/foo/services.yml | 4 +++ .../Tests/Loader/YamlFileLoaderTest.php | 27 ++++++++++++++----- 4 files changed, 31 insertions(+), 10 deletions(-) create mode 100644 src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/bar/services.yml create mode 100644 src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/foo/services.yml diff --git a/src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php b/src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php index 7a0123ba21bf5..8e751be1027c2 100644 --- a/src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php +++ b/src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php @@ -121,11 +121,11 @@ public function load($resource, $type = null) // parameters if (isset($content['parameters'])) { if (!is_array($content['parameters'])) { - throw new InvalidArgumentException(sprintf('The "parameters" key should contain an array in %s. Check your YAML syntax.', $resource)); + throw new InvalidArgumentException(sprintf('The "parameters" key should contain an array in %s. Check your YAML syntax.', $path)); } foreach ($content['parameters'] as $key => $value) { - $this->container->setParameter($key, $this->resolveServices($value, $resource, true)); + $this->container->setParameter($key, $this->resolveServices($value, $path, true)); } } @@ -136,7 +136,7 @@ public function load($resource, $type = null) $this->anonymousServicesCount = 0; $this->setCurrentDir(dirname($path)); try { - $this->parseDefinitions($content, $resource); + $this->parseDefinitions($content, $path); } finally { $this->instanceof = array(); } diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/bar/services.yml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/bar/services.yml new file mode 100644 index 0000000000000..0f846f5f76c6e --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/bar/services.yml @@ -0,0 +1,4 @@ +services: + AppBundle\Foo: + arguments: + - !service {class: AppBundle\Bar } diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/foo/services.yml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/foo/services.yml new file mode 100644 index 0000000000000..76eee552fac22 --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/foo/services.yml @@ -0,0 +1,4 @@ +services: + AppBundle\Hello: + arguments: + - !service {class: AppBundle\World} diff --git a/src/Symfony/Component/DependencyInjection/Tests/Loader/YamlFileLoaderTest.php b/src/Symfony/Component/DependencyInjection/Tests/Loader/YamlFileLoaderTest.php index 2c655d718998f..b8ac2fc0e9296 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Loader/YamlFileLoaderTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Loader/YamlFileLoaderTest.php @@ -501,7 +501,7 @@ public function testDecoratedServicesWithWrongSyntaxThrowsException() /** * @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException - * @expectedExceptionMessage Parameter "tags" must be an array for service "Foo\Bar" in services31_invalid_tags.yml. Check your YAML syntax. + * @expectedExceptionMessageRegExp /Parameter "tags" must be an array for service "Foo\\Bar" in .+services31_invalid_tags\.yml\. Check your YAML syntax./ */ public function testInvalidTagsWithDefaults() { @@ -534,7 +534,7 @@ public function testAnonymousServices() $this->assertCount(1, $args); $this->assertInstanceOf(Reference::class, $args[0]); $this->assertTrue($container->has((string) $args[0])); - $this->assertStringStartsWith('2', (string) $args[0]); + $this->assertRegExp('/^\d+_[A-Za-z0-9]{64}$/', (string) $args[0]); $anonymous = $container->getDefinition((string) $args[0]); $this->assertEquals('Bar', $anonymous->getClass()); @@ -546,7 +546,7 @@ public function testAnonymousServices() $this->assertInternalType('array', $factory); $this->assertInstanceOf(Reference::class, $factory[0]); $this->assertTrue($container->has((string) $factory[0])); - $this->assertStringStartsWith('1', (string) $factory[0]); + $this->assertRegExp('/^\d+_[A-Za-z0-9]{64}$/', (string) $factory[0]); $this->assertEquals('constructFoo', $factory[1]); $anonymous = $container->getDefinition((string) $factory[0]); @@ -555,6 +555,19 @@ public function testAnonymousServices() $this->assertFalse($anonymous->isAutowired()); } + public function testAnonymousServicesInDifferentFilesWithSameNameDoNotConflict() + { + $container = new ContainerBuilder(); + + $loader = new YamlFileLoader($container, new FileLocator(self::$fixturesPath.'/yaml/foo')); + $loader->load('services.yml'); + + $loader = new YamlFileLoader($container, new FileLocator(self::$fixturesPath.'/yaml/bar')); + $loader->load('services.yml'); + + $this->assertCount(5, $container->getDefinitions()); + } + public function testAnonymousServicesInInstanceof() { $container = new ContainerBuilder(); @@ -582,7 +595,7 @@ public function testAnonymousServicesInInstanceof() /** * @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException - * @expectedExceptionMessage Creating an alias using the tag "!service" is not allowed in "anonymous_services_alias.yml". + * @expectedExceptionMessageRegExp /Creating an alias using the tag "!service" is not allowed in ".+anonymous_services_alias\.yml"\./ */ public function testAnonymousServicesWithAliases() { @@ -593,7 +606,7 @@ public function testAnonymousServicesWithAliases() /** * @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException - * @expectedExceptionMessage Using an anonymous service in a parameter is not allowed in "anonymous_services_in_parameters.yml". + * @expectedExceptionMessageRegExp /Using an anonymous service in a parameter is not allowed in ".+anonymous_services_in_parameters\.yml"\./ */ public function testAnonymousServicesInParameters() { @@ -614,7 +627,7 @@ public function testAutoConfigureInstanceof() /** * @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException - * @expectedExceptionMessage Service "_defaults" key must be an array, "NULL" given in "bad_empty_defaults.yml". + * @expectedExceptionMessageRegExp /Service "_defaults" key must be an array, "NULL" given in ".+bad_empty_defaults\.yml"\./ */ public function testEmptyDefaultsThrowsClearException() { @@ -625,7 +638,7 @@ public function testEmptyDefaultsThrowsClearException() /** * @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException - * @expectedExceptionMessage Service "_instanceof" key must be an array, "NULL" given in "bad_empty_instanceof.yml". + * @expectedExceptionMessageRegExp /Service "_instanceof" key must be an array, "NULL" given in ".+bad_empty_instanceof\.yml"\./ */ public function testEmptyInstanceofThrowsClearException() { From 8cd1a2d527b4e24760640e963bcc8362a873168b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9goire=20Pineau?= Date: Thu, 13 Jul 2017 14:40:01 +0200 Subject: [PATCH 0420/1099] [Process] Fixed issue between process builder and exec refs #23495 --- src/Symfony/Component/Process/ProcessBuilder.php | 3 +++ .../Component/Process/Tests/ProcessBuilderTest.php | 13 +++++++++++++ 2 files changed, 16 insertions(+) diff --git a/src/Symfony/Component/Process/ProcessBuilder.php b/src/Symfony/Component/Process/ProcessBuilder.php index 2a5bb2bc3f035..36db35edb5e43 100644 --- a/src/Symfony/Component/Process/ProcessBuilder.php +++ b/src/Symfony/Component/Process/ProcessBuilder.php @@ -272,6 +272,9 @@ public function getProcess() $arguments = array_merge($this->prefix, $this->arguments); $process = new Process($arguments, $this->cwd, $this->env, $this->input, $this->timeout, $this->options); + // to preserve the BC with symfony <3.3, we convert the array structure + // to a string structure to avoid the prefixing with the exec command + $process->setCommandLine($process->getCommandLine()); if ($this->inheritEnv) { $process->inheritEnvironmentVariables(); diff --git a/src/Symfony/Component/Process/Tests/ProcessBuilderTest.php b/src/Symfony/Component/Process/Tests/ProcessBuilderTest.php index 34bb3732722e5..fa7c8c510adf3 100644 --- a/src/Symfony/Component/Process/Tests/ProcessBuilderTest.php +++ b/src/Symfony/Component/Process/Tests/ProcessBuilderTest.php @@ -210,4 +210,17 @@ public function testInvalidInput() $builder = ProcessBuilder::create(); $builder->setInput(array()); } + + public function testDoesNotPrefixExec() + { + if ('\\' === DIRECTORY_SEPARATOR) { + $this->markTestSkipped('This test cannot run on Windows.'); + } + + $builder = ProcessBuilder::create(array('command', '-v', 'ls')); + $process = $builder->getProcess(); + $process->run(); + + $this->assertTrue($process->isSuccessful()); + } } From 878198cefae028386c6dc800ccbf18f2b9cbff3f Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Fri, 14 Jul 2017 16:01:02 +0200 Subject: [PATCH 0421/1099] [Security] validate empty passwords again --- .../Constraints/UserPasswordValidatorTest.php | 23 +++++++++++++++++++ .../Constraints/UserPasswordValidator.php | 2 ++ 2 files changed, 25 insertions(+) diff --git a/src/Symfony/Component/Security/Core/Tests/Validator/Constraints/UserPasswordValidatorTest.php b/src/Symfony/Component/Security/Core/Tests/Validator/Constraints/UserPasswordValidatorTest.php index 7ebe65c647d99..942a4a6350f27 100644 --- a/src/Symfony/Component/Security/Core/Tests/Validator/Constraints/UserPasswordValidatorTest.php +++ b/src/Symfony/Component/Security/Core/Tests/Validator/Constraints/UserPasswordValidatorTest.php @@ -90,6 +90,29 @@ public function testPasswordIsNotValid() ->assertRaised(); } + /** + * @dataProvider emptyPasswordData + */ + public function testEmptyPasswordsAreNotValid($password) + { + $constraint = new UserPassword(array( + 'message' => 'myMessage', + )); + + $this->validator->validate($password, $constraint); + + $this->buildViolation('myMessage') + ->assertRaised(); + } + + public function emptyPasswordData() + { + return array( + array(null), + array(''), + ); + } + /** * @expectedException \Symfony\Component\Validator\Exception\ConstraintDefinitionException */ diff --git a/src/Symfony/Component/Security/Core/Validator/Constraints/UserPasswordValidator.php b/src/Symfony/Component/Security/Core/Validator/Constraints/UserPasswordValidator.php index 5f4c146cab469..c2ab13b2f6d29 100644 --- a/src/Symfony/Component/Security/Core/Validator/Constraints/UserPasswordValidator.php +++ b/src/Symfony/Component/Security/Core/Validator/Constraints/UserPasswordValidator.php @@ -40,6 +40,8 @@ public function validate($password, Constraint $constraint) } if (null === $password || '' === $password) { + $this->context->addViolation($constraint->message); + return; } From 813a5377e1cec10a389dfb109d23bc8f3ad1f44e Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Fri, 14 Jul 2017 14:26:39 +0200 Subject: [PATCH 0422/1099] [Cache] add constructor docblocks for clarity --- .../Component/Cache/Adapter/AbstractAdapter.php | 15 ++++++++++++++- .../Component/Cache/Adapter/ApcuAdapter.php | 7 +++++++ .../Component/Cache/Adapter/DoctrineAdapter.php | 5 +++++ .../Component/Cache/Adapter/FilesystemAdapter.php | 5 +++++ .../Component/Cache/Adapter/PhpFilesAdapter.php | 7 +++++++ .../Component/Cache/Adapter/ProxyAdapter.php | 5 +++++ 6 files changed, 43 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/Cache/Adapter/AbstractAdapter.php b/src/Symfony/Component/Cache/Adapter/AbstractAdapter.php index 84bb841d85df2..628638ea969c4 100644 --- a/src/Symfony/Component/Cache/Adapter/AbstractAdapter.php +++ b/src/Symfony/Component/Cache/Adapter/AbstractAdapter.php @@ -39,6 +39,10 @@ abstract class AbstractAdapter implements AdapterInterface, LoggerAwareInterface */ protected $maxIdLength; + /** + * @param string $namespace + * @param int $defaultLifetime + */ protected function __construct($namespace = '', $defaultLifetime = 0) { $this->namespace = '' === $namespace ? '' : $this->getId($namespace).':'; @@ -81,6 +85,15 @@ function ($deferred, $namespace, &$expiredIds) { ); } + /** + * @param string $namespace + * @param int $defaultLifetime + * @param string $version + * @param string $directory + * @param LoggerInterface|null $logger + * + * @return AdapterInterface + */ public static function createSystemCache($namespace, $defaultLifetime, $version, $directory, LoggerInterface $logger = null) { if (null === self::$apcuSupported) { @@ -139,7 +152,7 @@ abstract protected function doHave($id); /** * Deletes all items in the pool. * - * @param string The prefix used for all identifiers managed by this pool + * @param string $namespace The prefix used for all identifiers managed by this pool * * @return bool True if the pool was successfully cleared, false otherwise */ diff --git a/src/Symfony/Component/Cache/Adapter/ApcuAdapter.php b/src/Symfony/Component/Cache/Adapter/ApcuAdapter.php index ad3aadf1a5257..08179dd8faf5c 100644 --- a/src/Symfony/Component/Cache/Adapter/ApcuAdapter.php +++ b/src/Symfony/Component/Cache/Adapter/ApcuAdapter.php @@ -24,6 +24,13 @@ public static function isSupported() return function_exists('apcu_fetch') && ini_get('apc.enabled'); } + /** + * @param string $namespace + * @param int $defaultLifetime + * @param string|null $version + * + * @throws CacheException if APCu is not enabled + */ public function __construct($namespace = '', $defaultLifetime = 0, $version = null) { if (!static::isSupported()) { diff --git a/src/Symfony/Component/Cache/Adapter/DoctrineAdapter.php b/src/Symfony/Component/Cache/Adapter/DoctrineAdapter.php index ed91bf56cd0e5..70426b5dd5125 100644 --- a/src/Symfony/Component/Cache/Adapter/DoctrineAdapter.php +++ b/src/Symfony/Component/Cache/Adapter/DoctrineAdapter.php @@ -20,6 +20,11 @@ class DoctrineAdapter extends AbstractAdapter { private $provider; + /** + * @param CacheProvider $provider + * @param string $namespace + * @param int $defaultLifetime + */ public function __construct(CacheProvider $provider, $namespace = '', $defaultLifetime = 0) { parent::__construct('', $defaultLifetime); diff --git a/src/Symfony/Component/Cache/Adapter/FilesystemAdapter.php b/src/Symfony/Component/Cache/Adapter/FilesystemAdapter.php index 1c62641cf6d67..c7422d36a2164 100644 --- a/src/Symfony/Component/Cache/Adapter/FilesystemAdapter.php +++ b/src/Symfony/Component/Cache/Adapter/FilesystemAdapter.php @@ -20,6 +20,11 @@ class FilesystemAdapter extends AbstractAdapter { use FilesystemAdapterTrait; + /** + * @param string $namespace + * @param int $defaultLifetime + * @param string|null $directory + */ public function __construct($namespace = '', $defaultLifetime = 0, $directory = null) { parent::__construct('', $defaultLifetime); diff --git a/src/Symfony/Component/Cache/Adapter/PhpFilesAdapter.php b/src/Symfony/Component/Cache/Adapter/PhpFilesAdapter.php index 88107cb9899dc..2ce605a40fca0 100644 --- a/src/Symfony/Component/Cache/Adapter/PhpFilesAdapter.php +++ b/src/Symfony/Component/Cache/Adapter/PhpFilesAdapter.php @@ -29,6 +29,13 @@ public static function isSupported() return function_exists('opcache_invalidate') && ini_get('opcache.enable'); } + /** + * @param string $namespace + * @param int $defaultLifetime + * @param string|null $directory + * + * @throws CacheException if OPcache is not enabled + */ public function __construct($namespace = '', $defaultLifetime = 0, $directory = null) { if (!static::isSupported()) { diff --git a/src/Symfony/Component/Cache/Adapter/ProxyAdapter.php b/src/Symfony/Component/Cache/Adapter/ProxyAdapter.php index 2ed895c873a3e..4f37ffd731931 100644 --- a/src/Symfony/Component/Cache/Adapter/ProxyAdapter.php +++ b/src/Symfony/Component/Cache/Adapter/ProxyAdapter.php @@ -26,6 +26,11 @@ class ProxyAdapter implements AdapterInterface private $createCacheItem; private $poolHash; + /** + * @param CacheItemPoolInterface $pool + * @param string $namespace + * @param int $defaultLifetime + */ public function __construct(CacheItemPoolInterface $pool, $namespace = '', $defaultLifetime = 0) { $this->pool = $pool; From 8f6a0f7694095fa511c9f662d2392e20ea223e5e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Fri, 14 Jul 2017 21:31:42 +0200 Subject: [PATCH 0423/1099] [DI] Remove an unused property in the Compiler --- src/Symfony/Component/DependencyInjection/Compiler/Compiler.php | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Symfony/Component/DependencyInjection/Compiler/Compiler.php b/src/Symfony/Component/DependencyInjection/Compiler/Compiler.php index 5919c1db85e26..e58b3dbe7fce5 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/Compiler.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/Compiler.php @@ -23,7 +23,6 @@ class Compiler { private $passConfig; private $log = array(); - private $loggingFormatter; private $serviceReferenceGraph; public function __construct() From 6de81a775658fb0265f53c195786bb9bf63e709b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Fri, 14 Jul 2017 23:11:01 +0200 Subject: [PATCH 0424/1099] [DI] Remove unused dynamic property --- src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php index 7875f1a376b82..02c17150b4e34 100644 --- a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php +++ b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php @@ -120,7 +120,6 @@ public function dump(array $options = array()) 'debug' => true, ), $options); - $this->classResources = array(); $this->initializeMethodNamesMap($options['base_class']); $this->docStar = $options['debug'] ? '*' : ''; From 101b6815ebd1a301291085d0660fd8e0e06c6631 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Sat, 15 Jul 2017 08:24:25 +0200 Subject: [PATCH 0425/1099] remove symfony/process suggestion --- src/Symfony/Bundle/FrameworkBundle/composer.json | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/composer.json b/src/Symfony/Bundle/FrameworkBundle/composer.json index 6db169024f67e..1105daa373f43 100644 --- a/src/Symfony/Bundle/FrameworkBundle/composer.json +++ b/src/Symfony/Bundle/FrameworkBundle/composer.json @@ -80,7 +80,6 @@ "symfony/validator": "For using validation", "symfony/yaml": "For using the debug:config and lint:yaml commands", "symfony/property-info": "For using the property_info service", - "symfony/process": "For using the server:run, server:start, server:stop, and server:status commands", "symfony/web-link": "For using web links, features such as preloading, prefetching or prerendering" }, "autoload": { From d6534f5cfc48fce5b3f6dff96c073251d99bf587 Mon Sep 17 00:00:00 2001 From: James Johnston Date: Fri, 14 Jul 2017 23:43:02 -0700 Subject: [PATCH 0426/1099] [VarDumper] Added setMinDepth to VarCloner MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This new function allows VarCloner users to specify a minimum tree depth that must be fully explored before we start limiting the number of cloned items via the existing setMaxItems functionality. It’s useful for dumping arguments from a backtrace to ensure some minimum level of detail, while keeping a very low setMaxItems value to ensure fast performance. --- src/Symfony/Component/VarDumper/CHANGELOG.md | 5 + .../VarDumper/Cloner/AbstractCloner.php | 14 +- .../Component/VarDumper/Cloner/VarCloner.php | 21 +- .../VarDumper/Tests/Cloner/VarClonerTest.php | 255 ++++++++++++++++++ 4 files changed, 290 insertions(+), 5 deletions(-) diff --git a/src/Symfony/Component/VarDumper/CHANGELOG.md b/src/Symfony/Component/VarDumper/CHANGELOG.md index 6b08aa77ac7b1..24a5843f64dff 100644 --- a/src/Symfony/Component/VarDumper/CHANGELOG.md +++ b/src/Symfony/Component/VarDumper/CHANGELOG.md @@ -1,6 +1,11 @@ CHANGELOG ========= +3.4.0 +----- + + * added `AbstractCloner::setMinDepth()` function to ensure minimum tree depth + 2.7.0 ----- diff --git a/src/Symfony/Component/VarDumper/Cloner/AbstractCloner.php b/src/Symfony/Component/VarDumper/Cloner/AbstractCloner.php index d77745e931955..bd98dd3185e84 100644 --- a/src/Symfony/Component/VarDumper/Cloner/AbstractCloner.php +++ b/src/Symfony/Component/VarDumper/Cloner/AbstractCloner.php @@ -129,6 +129,7 @@ abstract class AbstractCloner implements ClonerInterface protected $maxItems = 2500; protected $maxString = -1; + protected $minDepth = 1; protected $useExt; private $casters = array(); @@ -168,7 +169,7 @@ public function addCasters(array $casters) } /** - * Sets the maximum number of items to clone past the first level in nested structures. + * Sets the maximum number of items to clone past the minimum depth in nested structures. * * @param int $maxItems */ @@ -187,6 +188,17 @@ public function setMaxString($maxString) $this->maxString = (int) $maxString; } + /** + * Sets the minimum tree depth where we are guaranteed to clone all the items. After this + * depth is reached, only setMaxItems items will be cloned. + * + * @param int $minDepth + */ + public function setMinDepth($minDepth) + { + $this->minDepth = (int) $minDepth; + } + /** * Clones a PHP variable. * diff --git a/src/Symfony/Component/VarDumper/Cloner/VarCloner.php b/src/Symfony/Component/VarDumper/Cloner/VarCloner.php index 6a3b451bda7f7..f1cccd309b714 100644 --- a/src/Symfony/Component/VarDumper/Cloner/VarCloner.php +++ b/src/Symfony/Component/VarDumper/Cloner/VarCloner.php @@ -26,7 +26,7 @@ protected function doClone($var) { $useExt = $this->useExt; $len = 1; // Length of $queue - $pos = 0; // Number of cloned items past the first level + $pos = 0; // Number of cloned items past the minimum depth $refsCounter = 0; // Hard references counter $queue = array(array($var)); // This breadth-first queue is the return value $arrayRefs = array(); // Map of queue indexes to stub array objects @@ -36,6 +36,10 @@ protected function doClone($var) $values = array(); // Map of stub objects' hashes to original values $maxItems = $this->maxItems; $maxString = $this->maxString; + $minDepth = $this->minDepth; + $currentDepth = 0; // Current tree depth + $currentDepthFinalIndex = 0; // Final $queue index for current tree depth + $minimumDepthReached = $minDepth === 0; // Becomes true when minimum tree depth has been reached $cookie = (object) array(); // Unique object used to detect hard references $gid = uniqid(mt_rand(), true); // Unique string used to detect the special $GLOBALS variable $a = null; // Array cast for nested structures @@ -57,6 +61,15 @@ protected function doClone($var) $hashOffset = self::$hashOffset; for ($i = 0; $i < $len; ++$i) { + // Detect when we move on to the next tree depth + if ($i > $currentDepthFinalIndex) { + ++$currentDepth; + $currentDepthFinalIndex = $len - 1; + if ($currentDepth >= $minDepth) { + $minimumDepthReached = true; + } + } + $indexed = true; // Whether the currently iterated array is numerically indexed or not $j = -1; // Position in the currently iterated array $fromObjCast = array_keys($queue[$i]); @@ -166,7 +179,7 @@ protected function doClone($var) $stub->handle = $h; } $stub->value = null; - if (0 <= $maxItems && $maxItems <= $pos) { + if (0 <= $maxItems && $maxItems <= $pos && $minimumDepthReached) { $stub->cut = count($a); $a = null; } @@ -193,7 +206,7 @@ protected function doClone($var) $stub->handle = $h; $a = $this->castResource($stub, 0 < $i); $stub->value = null; - if (0 <= $maxItems && $maxItems <= $pos) { + if (0 <= $maxItems && $maxItems <= $pos && $minimumDepthReached) { $stub->cut = count($a); $a = null; } @@ -226,7 +239,7 @@ protected function doClone($var) } if ($a) { - if ($i && 0 <= $maxItems) { + if ($minimumDepthReached && 0 <= $maxItems) { $k = count($a); if ($pos < $maxItems) { if ($maxItems < $pos += $k) { diff --git a/src/Symfony/Component/VarDumper/Tests/Cloner/VarClonerTest.php b/src/Symfony/Component/VarDumper/Tests/Cloner/VarClonerTest.php index 75774170f32ee..458a2906ec6ab 100644 --- a/src/Symfony/Component/VarDumper/Tests/Cloner/VarClonerTest.php +++ b/src/Symfony/Component/VarDumper/Tests/Cloner/VarClonerTest.php @@ -152,6 +152,261 @@ public function testClone() [useRefHandles:Symfony\Component\VarDumper\Cloner\Data:private] => -1 ) +EOTXT; + $this->assertStringMatchesFormat($expected, print_r($clone, true)); + } + + public function testLimits() + { + // Level 0: + $data = array( + // Level 1: + array( + // Level 2: + array( + // Level 3: + 'Level 3 Item 0', + 'Level 3 Item 1', + 'Level 3 Item 2', + 'Level 3 Item 3', + ), + array( + 'Level 3 Item 4', + 'Level 3 Item 5', + 'Level 3 Item 6', + ), + array( + 'Level 3 Item 7', + ), + ), + array( + array( + 'Level 3 Item 8', + ), + 'Level 2 Item 0', + ), + array( + 'Level 2 Item 1', + ), + 'Level 1 Item 0', + array( + // Test setMaxString: + 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', + 'SHORT', + ), + ); + + $cloner = new VarCloner(); + $cloner->setMinDepth(2); + $cloner->setMaxItems(5); + $cloner->setMaxString(20); + $clone = $cloner->cloneVar($data); + + $expected = << Array + ( + [0] => Array + ( + [0] => Symfony\Component\VarDumper\Cloner\Stub Object + ( + [type] => array + [class] => indexed + [value] => 5 + [cut] => 0 + [handle] => 0 + [refCount] => 0 + [position] => 1 + [attr] => Array + ( + ) + + ) + + ) + + [1] => Array + ( + [0] => Symfony\Component\VarDumper\Cloner\Stub Object + ( + [type] => array + [class] => indexed + [value] => 3 + [cut] => 0 + [handle] => 0 + [refCount] => 0 + [position] => 2 + [attr] => Array + ( + ) + + ) + + [1] => Symfony\Component\VarDumper\Cloner\Stub Object + ( + [type] => array + [class] => indexed + [value] => 2 + [cut] => 0 + [handle] => 0 + [refCount] => 0 + [position] => 3 + [attr] => Array + ( + ) + + ) + + [2] => Symfony\Component\VarDumper\Cloner\Stub Object + ( + [type] => array + [class] => indexed + [value] => 1 + [cut] => 0 + [handle] => 0 + [refCount] => 0 + [position] => 4 + [attr] => Array + ( + ) + + ) + + [3] => Level 1 Item 0 + [4] => Symfony\Component\VarDumper\Cloner\Stub Object + ( + [type] => array + [class] => indexed + [value] => 2 + [cut] => 0 + [handle] => 0 + [refCount] => 0 + [position] => 5 + [attr] => Array + ( + ) + + ) + + ) + + [2] => Array + ( + [0] => Symfony\Component\VarDumper\Cloner\Stub Object + ( + [type] => array + [class] => indexed + [value] => 4 + [cut] => 0 + [handle] => 0 + [refCount] => 0 + [position] => 6 + [attr] => Array + ( + ) + + ) + + [1] => Symfony\Component\VarDumper\Cloner\Stub Object + ( + [type] => array + [class] => indexed + [value] => 3 + [cut] => 2 + [handle] => 0 + [refCount] => 0 + [position] => 7 + [attr] => Array + ( + ) + + ) + + [2] => Symfony\Component\VarDumper\Cloner\Stub Object + ( + [type] => array + [class] => assoc + [value] => 1 + [cut] => 1 + [handle] => 0 + [refCount] => 0 + [position] => 0 + [attr] => Array + ( + ) + + ) + + ) + + [3] => Array + ( + [0] => Symfony\Component\VarDumper\Cloner\Stub Object + ( + [type] => array + [class] => assoc + [value] => 1 + [cut] => 1 + [handle] => 0 + [refCount] => 0 + [position] => 0 + [attr] => Array + ( + ) + + ) + + [1] => Level 2 Item 0 + ) + + [4] => Array + ( + [0] => Level 2 Item 1 + ) + + [5] => Array + ( + [0] => Symfony\Component\VarDumper\Cloner\Stub Object + ( + [type] => string + [class] => utf8 + [value] => ABCDEFGHIJKLMNOPQRST + [cut] => 6 + [handle] => 0 + [refCount] => 0 + [position] => 0 + [attr] => Array + ( + ) + + ) + + [1] => SHORT + ) + + [6] => Array + ( + [0] => Level 3 Item 0 + [1] => Level 3 Item 1 + [2] => Level 3 Item 2 + [3] => Level 3 Item 3 + ) + + [7] => Array + ( + [0] => Level 3 Item 4 + ) + + ) + + [position:Symfony\Component\VarDumper\Cloner\Data:private] => 0 + [key:Symfony\Component\VarDumper\Cloner\Data:private] => 0 + [maxDepth:Symfony\Component\VarDumper\Cloner\Data:private] => 20 + [maxItemsPerDepth:Symfony\Component\VarDumper\Cloner\Data:private] => -1 + [useRefHandles:Symfony\Component\VarDumper\Cloner\Data:private] => -1 +) + EOTXT; $this->assertStringMatchesFormat($expected, print_r($clone, true)); } From 34e7094d3def6c4e939237f2562c7367f16c00f5 Mon Sep 17 00:00:00 2001 From: Maxime Steinhausser Date: Sat, 15 Jul 2017 09:50:22 +0200 Subject: [PATCH 0427/1099] [Profiler] Fix data collector getCasters() call --- .../Form/Extension/DataCollector/FormDataCollector.php | 6 ------ .../Component/HttpKernel/DataCollector/DataCollector.php | 2 +- 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/src/Symfony/Component/Form/Extension/DataCollector/FormDataCollector.php b/src/Symfony/Component/Form/Extension/DataCollector/FormDataCollector.php index 7540449b96ec5..378edf563b972 100644 --- a/src/Symfony/Component/Form/Extension/DataCollector/FormDataCollector.php +++ b/src/Symfony/Component/Form/Extension/DataCollector/FormDataCollector.php @@ -16,7 +16,6 @@ use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\DataCollector\DataCollector; -use Symfony\Component\HttpKernel\DataCollector\Util\ValueExporter; use Symfony\Component\Validator\ConstraintViolationInterface; use Symfony\Component\VarDumper\Caster\Caster; use Symfony\Component\VarDumper\Caster\ClassStub; @@ -68,11 +67,6 @@ class FormDataCollector extends DataCollector implements FormDataCollectorInterf */ private $formsByView; - /** - * @var ValueExporter - */ - private $valueExporter; - private $hasVarDumper; public function __construct(FormDataExtractorInterface $dataExtractor) diff --git a/src/Symfony/Component/HttpKernel/DataCollector/DataCollector.php b/src/Symfony/Component/HttpKernel/DataCollector/DataCollector.php index 770c985637da6..845c2c1380b01 100644 --- a/src/Symfony/Component/HttpKernel/DataCollector/DataCollector.php +++ b/src/Symfony/Component/HttpKernel/DataCollector/DataCollector.php @@ -69,7 +69,7 @@ protected function cloneVar($var) if (class_exists(CutStub::class)) { $this->cloner = new VarCloner(); $this->cloner->setMaxItems(-1); - $this->cloner->addCasters(self::getCasters()); + $this->cloner->addCasters($this->getCasters()); } else { @trigger_error(sprintf('Using the %s() method without the VarDumper component is deprecated since version 3.2 and won\'t be supported in 4.0. Install symfony/var-dumper version 3.2 or above.', __METHOD__), E_USER_DEPRECATED); $this->cloner = false; From 9b40b4af652bc7bbffd030cfe29ac370c0a9146e Mon Sep 17 00:00:00 2001 From: Maxime Steinhausser Date: Fri, 14 Jul 2017 19:53:01 +0200 Subject: [PATCH 0428/1099] [Console] Add a factory command loader for standalone application with lazy-loading needs --- src/Symfony/Component/Console/CHANGELOG.md | 3 +- .../CommandLoader/FactoryCommandLoader.php | 62 +++++++++++++++++++ .../Console/Tests/ApplicationTest.php | 22 +++---- .../FactoryCommandLoaderTest.php | 60 ++++++++++++++++++ 4 files changed, 134 insertions(+), 13 deletions(-) create mode 100644 src/Symfony/Component/Console/CommandLoader/FactoryCommandLoader.php create mode 100644 src/Symfony/Component/Console/Tests/CommandLoader/FactoryCommandLoaderTest.php diff --git a/src/Symfony/Component/Console/CHANGELOG.md b/src/Symfony/Component/Console/CHANGELOG.md index 542d00623bebb..b337ecf992f4d 100644 --- a/src/Symfony/Component/Console/CHANGELOG.md +++ b/src/Symfony/Component/Console/CHANGELOG.md @@ -4,7 +4,8 @@ CHANGELOG 3.4.0 ----- - * added `CommandLoaderInterface` and PSR-11 `ContainerCommandLoader` + * added `CommandLoaderInterface`, `FactoryCommandLoader` and PSR-11 + `ContainerCommandLoader` for commands lazy-loading 3.3.0 ----- diff --git a/src/Symfony/Component/Console/CommandLoader/FactoryCommandLoader.php b/src/Symfony/Component/Console/CommandLoader/FactoryCommandLoader.php new file mode 100644 index 0000000000000..d9c2055710968 --- /dev/null +++ b/src/Symfony/Component/Console/CommandLoader/FactoryCommandLoader.php @@ -0,0 +1,62 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\CommandLoader; + +use Symfony\Component\Console\Exception\CommandNotFoundException; + +/** + * A simple command loader using factories to instantiate commands lazily. + * + * @author Maxime Steinhausser + */ +class FactoryCommandLoader implements CommandLoaderInterface +{ + private $factories; + + /** + * @param callable[] $factories Indexed by command names + */ + public function __construct(array $factories) + { + $this->factories = $factories; + } + + /** + * {@inheritdoc} + */ + public function has($name) + { + return isset($this->factories[$name]); + } + + /** + * {@inheritdoc} + */ + public function get($name) + { + if (!isset($this->factories[$name])) { + throw new CommandNotFoundException(sprintf('Command "%s" does not exist.', $name)); + } + + $factory = $this->factories[$name]; + + return $factory(); + } + + /** + * {@inheritdoc} + */ + public function getNames() + { + return array_keys($this->factories); + } +} diff --git a/src/Symfony/Component/Console/Tests/ApplicationTest.php b/src/Symfony/Component/Console/Tests/ApplicationTest.php index 7bf76ddc8e83d..d475f12bc9140 100644 --- a/src/Symfony/Component/Console/Tests/ApplicationTest.php +++ b/src/Symfony/Component/Console/Tests/ApplicationTest.php @@ -14,7 +14,7 @@ use PHPUnit\Framework\TestCase; use Symfony\Component\Console\Application; use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\CommandLoader\ContainerCommandLoader; +use Symfony\Component\Console\CommandLoader\FactoryCommandLoader; use Symfony\Component\Console\DependencyInjection\AddConsoleCommandPass; use Symfony\Component\Console\Helper\HelperSet; use Symfony\Component\Console\Helper\FormatterHelper; @@ -35,7 +35,6 @@ use Symfony\Component\Console\Event\ConsoleTerminateEvent; use Symfony\Component\Console\Exception\CommandNotFoundException; use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\ServiceLocator; use Symfony\Component\EventDispatcher\EventDispatcher; class ApplicationTest extends TestCase @@ -129,10 +128,9 @@ public function testAllWithCommandLoader() $commands = $application->all('foo'); $this->assertCount(1, $commands, '->all() takes a namespace as its first argument'); - $application->setCommandLoader(new ContainerCommandLoader( - new ServiceLocator(array('foo-bar' => function () { return new \Foo1Command(); })), - array('foo:bar1' => 'foo-bar') - )); + $application->setCommandLoader(new FactoryCommandLoader(array( + 'foo:bar1' => function () { return new \Foo1Command(); }, + ))); $commands = $application->all('foo'); $this->assertCount(2, $commands, '->all() takes a namespace as its first argument'); $this->assertInstanceOf(\FooCommand::class, $commands['foo:bar'], '->all() returns the registered commands'); @@ -202,9 +200,9 @@ public function testHasGetWithCommandLoader() $this->assertEquals($foo, $application->get('foo:bar'), '->get() returns a command by name'); $this->assertEquals($foo, $application->get('afoobar'), '->get() returns a command by alias'); - $application->setCommandLoader(new ContainerCommandLoader(new ServiceLocator(array( - 'foo-bar' => function () { return new \Foo1Command(); }, - )), array('foo:bar1' => 'foo-bar', 'afoobar1' => 'foo-bar'))); + $application->setCommandLoader(new FactoryCommandLoader(array( + 'foo:bar1' => function () { return new \Foo1Command(); }, + ))); $this->assertTrue($application->has('afoobar'), '->has() returns true if an instance is registered for an alias even with command loader'); $this->assertEquals($foo, $application->get('foo:bar'), '->get() returns an instance by name even with command loader'); @@ -321,9 +319,9 @@ public function testFind() public function testFindWithCommandLoader() { $application = new Application(); - $application->setCommandLoader(new ContainerCommandLoader(new ServiceLocator(array( - 'foo-bar' => $f = function () { return new \FooCommand(); }, - )), array('foo:bar' => 'foo-bar'))); + $application->setCommandLoader(new FactoryCommandLoader(array( + 'foo:bar' => $f = function () { return new \FooCommand(); }, + ))); $this->assertInstanceOf('FooCommand', $application->find('foo:bar'), '->find() returns a command if its name exists'); $this->assertInstanceOf('Symfony\Component\Console\Command\HelpCommand', $application->find('h'), '->find() returns a command if its name exists'); diff --git a/src/Symfony/Component/Console/Tests/CommandLoader/FactoryCommandLoaderTest.php b/src/Symfony/Component/Console/Tests/CommandLoader/FactoryCommandLoaderTest.php new file mode 100644 index 0000000000000..5ee6cd1ec36fd --- /dev/null +++ b/src/Symfony/Component/Console/Tests/CommandLoader/FactoryCommandLoaderTest.php @@ -0,0 +1,60 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Tests\CommandLoader; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\CommandLoader\FactoryCommandLoader; + +class FactoryCommandLoaderTest extends TestCase +{ + public function testHas() + { + $loader = new FactoryCommandLoader(array( + 'foo' => function () { return new Command('foo'); }, + 'bar' => function () { return new Command('bar'); }, + )); + + $this->assertTrue($loader->has('foo')); + $this->assertTrue($loader->has('bar')); + $this->assertFalse($loader->has('baz')); + } + + public function testGet() + { + $loader = new FactoryCommandLoader(array( + 'foo' => function () { return new Command('foo'); }, + 'bar' => function () { return new Command('bar'); }, + )); + + $this->assertInstanceOf(Command::class, $loader->get('foo')); + $this->assertInstanceOf(Command::class, $loader->get('bar')); + } + + /** + * @expectedException \Symfony\Component\Console\Exception\CommandNotFoundException + */ + public function testGetUnknownCommandThrows() + { + (new FactoryCommandLoader(array()))->get('unknown'); + } + + public function testGetCommandNames() + { + $loader = new FactoryCommandLoader(array( + 'foo' => function () { return new Command('foo'); }, + 'bar' => function () { return new Command('bar'); }, + )); + + $this->assertSame(array('foo', 'bar'), $loader->getNames()); + } +} From c725a700cf2452443b75db48832f28a9cab86e6b Mon Sep 17 00:00:00 2001 From: Maxime Steinhausser Date: Sat, 15 Jul 2017 09:51:29 +0200 Subject: [PATCH 0429/1099] [Profiler][Validator] ValidatorDataCollector: use new DataCollector::getCasters() method --- .../DataCollector/ValidatorDataCollector.php | 45 +++++++++---------- src/Symfony/Component/Validator/composer.json | 5 ++- 2 files changed, 23 insertions(+), 27 deletions(-) diff --git a/src/Symfony/Component/Validator/DataCollector/ValidatorDataCollector.php b/src/Symfony/Component/Validator/DataCollector/ValidatorDataCollector.php index 02c672191e968..d2b3f4626264c 100644 --- a/src/Symfony/Component/Validator/DataCollector/ValidatorDataCollector.php +++ b/src/Symfony/Component/Validator/DataCollector/ValidatorDataCollector.php @@ -19,8 +19,7 @@ use Symfony\Component\Validator\Validator\TraceableValidator; use Symfony\Component\VarDumper\Caster\Caster; use Symfony\Component\VarDumper\Caster\ClassStub; -use Symfony\Component\VarDumper\Cloner\Data; -use Symfony\Component\VarDumper\Cloner\VarCloner; +use Symfony\Component\VarDumper\Cloner\Stub; /** * @author Maxime Steinhausser @@ -28,7 +27,6 @@ class ValidatorDataCollector extends DataCollector implements LateDataCollectorInterface { private $validator; - private $cloner; public function __construct(TraceableValidator $validator) { @@ -77,29 +75,26 @@ public function getName() return 'validator'; } - /** - * {@inheritdoc} - */ - protected function cloneVar($var) + protected function getCasters() { - if ($var instanceof Data) { - return $var; - } + return parent::getCasters() + array( + \Exception::class => function (\Exception $e, array $a, Stub $s) { + foreach (array("\0Exception\0previous", "\0Exception\0trace") as $k) { + if (isset($a[$k])) { + unset($a[$k]); + ++$s->cut; + } + } - if (null === $this->cloner) { - $this->cloner = new VarCloner(); - $this->cloner->setMaxItems(-1); - $this->cloner->addCasters(array( - FormInterface::class => function (FormInterface $f, array $a) { - return array( - Caster::PREFIX_VIRTUAL.'name' => $f->getName(), - Caster::PREFIX_VIRTUAL.'type_class' => new ClassStub(get_class($f->getConfig()->getType()->getInnerType())), - Caster::PREFIX_VIRTUAL.'data' => $f->getData(), - ); - }, - )); - } - - return $this->cloner->cloneVar($var, Caster::EXCLUDE_VERBOSE); + return $a; + }, + FormInterface::class => function (FormInterface $f, array $a) { + return array( + Caster::PREFIX_VIRTUAL.'name' => $f->getName(), + Caster::PREFIX_VIRTUAL.'type_class' => new ClassStub(get_class($f->getConfig()->getType()->getInnerType())), + Caster::PREFIX_VIRTUAL.'data' => $f->getData(), + ); + }, + ); } } diff --git a/src/Symfony/Component/Validator/composer.json b/src/Symfony/Component/Validator/composer.json index 69b39c9c821b0..a050573d82bef 100644 --- a/src/Symfony/Component/Validator/composer.json +++ b/src/Symfony/Component/Validator/composer.json @@ -22,8 +22,8 @@ }, "require-dev": { "symfony/http-foundation": "~2.8|~3.0|~4.0", - "symfony/http-kernel": "~2.8|~3.0|~4.0.0", - "symfony/var-dumper": "~3.3|~4.0.0", + "symfony/http-kernel": "^3.3.5|~4.0", + "symfony/var-dumper": "~3.3|~4.0", "symfony/intl": "^2.8.18|^3.2.5|~4.0", "symfony/yaml": "~3.3|~4.0", "symfony/config": "~2.8|~3.0|~4.0", @@ -38,6 +38,7 @@ "conflict": { "phpunit/phpunit": "<4.8.35|<5.4.3,>=5.0", "symfony/dependency-injection": "<3.3", + "symfony/http-kernel": "<3.3.5", "symfony/yaml": "<3.3" }, "suggest": { From 7ea2d0437a10905a6352409cc64563864ae5d09f Mon Sep 17 00:00:00 2001 From: Roland Franssen Date: Sat, 15 Jul 2017 14:52:50 +0200 Subject: [PATCH 0430/1099] [SecurityBundle] Clarify deprecation in UserPasswordEncoderCommand::getContainer --- UPGRADE-4.0.md | 2 +- src/Symfony/Bundle/SecurityBundle/CHANGELOG.md | 2 +- .../SecurityBundle/Command/UserPasswordEncoderCommand.php | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/UPGRADE-4.0.md b/UPGRADE-4.0.md index 3ce678b866b4b..17818f7368ca4 100644 --- a/UPGRADE-4.0.md +++ b/UPGRADE-4.0.md @@ -443,7 +443,7 @@ SecurityBundle * The `UserPasswordEncoderCommand` class does not allow `null` as the first argument anymore. - * `UserPasswordEncoderCommand` does not implement `ContainerAwareInterface` anymore. + * `UserPasswordEncoderCommand` does not extend `ContainerAwareCommand` nor implement `ContainerAwareInterface` anymore. Serializer ---------- diff --git a/src/Symfony/Bundle/SecurityBundle/CHANGELOG.md b/src/Symfony/Bundle/SecurityBundle/CHANGELOG.md index 4185d409fb445..238830fd85179 100644 --- a/src/Symfony/Bundle/SecurityBundle/CHANGELOG.md +++ b/src/Symfony/Bundle/SecurityBundle/CHANGELOG.md @@ -7,7 +7,7 @@ CHANGELOG * Deprecated instantiating `UserPasswordEncoderCommand` without its constructor arguments fully provided. * Deprecated `UserPasswordEncoderCommand::getContainer()` and relying on the - `ContainerAwareInterface` interface for this command. + `ContainerAwareCommand` sub class or `ContainerAwareInterface` implementation for this command. * Deprecated the `FirewallMap::$map` and `$container` properties. * [BC BREAK] Keys of the `users` node for `in_memory` user provider are no longer normalized. * deprecated `FirewallContext::getListeners()` diff --git a/src/Symfony/Bundle/SecurityBundle/Command/UserPasswordEncoderCommand.php b/src/Symfony/Bundle/SecurityBundle/Command/UserPasswordEncoderCommand.php index a588bdd331e96..6c3f0327491c4 100644 --- a/src/Symfony/Bundle/SecurityBundle/Command/UserPasswordEncoderCommand.php +++ b/src/Symfony/Bundle/SecurityBundle/Command/UserPasswordEncoderCommand.php @@ -51,7 +51,7 @@ public function __construct(EncoderFactoryInterface $encoderFactory = null, arra */ protected function getContainer() { - @trigger_error(sprintf('Method "%s" is deprecated since version 3.3 and "%s" won\'t implement "%s" anymore in 4.0.', __METHOD__, __CLASS__, ContainerAwareInterface::class), E_USER_DEPRECATED); + @trigger_error(sprintf('Method "%s" is deprecated since version 3.3 and "%s" won\'t extend "%s" nor implement "%s" anymore in 4.0.', __METHOD__, __CLASS__, ContainerAwareCommand::class, ContainerAwareInterface::class), E_USER_DEPRECATED); return parent::getContainer(); } From bc6b57c208b3df06de07d6f4f801ba4a9d0bea9d Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Sun, 16 Jul 2017 14:39:47 +0200 Subject: [PATCH 0431/1099] [WebServerBundle] remove duplicate code --- .../Bundle/WebServerBundle/Command/ServerRunCommand.php | 6 ------ .../Bundle/WebServerBundle/Command/ServerStartCommand.php | 6 ------ 2 files changed, 12 deletions(-) diff --git a/src/Symfony/Bundle/WebServerBundle/Command/ServerRunCommand.php b/src/Symfony/Bundle/WebServerBundle/Command/ServerRunCommand.php index 53ce350e7fae2..a038ba401bf82 100644 --- a/src/Symfony/Bundle/WebServerBundle/Command/ServerRunCommand.php +++ b/src/Symfony/Bundle/WebServerBundle/Command/ServerRunCommand.php @@ -97,12 +97,6 @@ protected function execute(InputInterface $input, OutputInterface $output) $documentRoot = $this->documentRoot; } - if (!is_dir($documentRoot)) { - $io->error(sprintf('The document root directory "%s" does not exist.', $documentRoot)); - - return 1; - } - if (!$env = $this->environment) { if ($input->hasOption('env') && !$env = $input->getOption('env')) { $io->error('The environment must be either passed as second argument of the constructor or through the "--env" input option.'); diff --git a/src/Symfony/Bundle/WebServerBundle/Command/ServerStartCommand.php b/src/Symfony/Bundle/WebServerBundle/Command/ServerStartCommand.php index 7cf83ab54e14e..1ecd066db43ed 100644 --- a/src/Symfony/Bundle/WebServerBundle/Command/ServerStartCommand.php +++ b/src/Symfony/Bundle/WebServerBundle/Command/ServerStartCommand.php @@ -109,12 +109,6 @@ protected function execute(InputInterface $input, OutputInterface $output) $documentRoot = $this->documentRoot; } - if (!is_dir($documentRoot)) { - $io->error(sprintf('The document root directory "%s" does not exist.', $documentRoot)); - - return 1; - } - if (!$env = $this->environment) { if ($input->hasOption('env') && !$env = $input->getOption('env')) { $io->error('The environment must be either passed as second argument of the constructor or through the "--env" input option.'); From 34c8566be140d6fffff5dae3a055c986b8c45740 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Sun, 16 Jul 2017 14:39:52 +0200 Subject: [PATCH 0432/1099] [WebServerBundle] allowed public/ root directory to be auto-discovered along side web/ --- .../Bundle/WebServerBundle/Command/ServerRunCommand.php | 6 ++++++ .../Bundle/WebServerBundle/Command/ServerStartCommand.php | 6 ++++++ .../Bundle/WebServerBundle/Resources/config/webserver.xml | 4 ++-- 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Bundle/WebServerBundle/Command/ServerRunCommand.php b/src/Symfony/Bundle/WebServerBundle/Command/ServerRunCommand.php index a038ba401bf82..4c228ad93bee0 100644 --- a/src/Symfony/Bundle/WebServerBundle/Command/ServerRunCommand.php +++ b/src/Symfony/Bundle/WebServerBundle/Command/ServerRunCommand.php @@ -88,6 +88,12 @@ protected function execute(InputInterface $input, OutputInterface $output) { $io = new SymfonyStyle($input, $output instanceof ConsoleOutputInterface ? $output->getErrorOutput() : $output); + // deprecated, logic to be removed in 4.0 + // this allows the commands to work out of the box with web/ and public/ + if ($this->documentRoot && !is_dir($this->documentRoot) && is_dir(dirname($this->documentRoot).'/web')) { + $this->documentRoot = dirname($this->documentRoot).'/web'; + } + if (null === $documentRoot = $input->getOption('docroot')) { if (!$this->documentRoot) { $io->error('The document root directory must be either passed as first argument of the constructor or through the "--docroot" input option.'); diff --git a/src/Symfony/Bundle/WebServerBundle/Command/ServerStartCommand.php b/src/Symfony/Bundle/WebServerBundle/Command/ServerStartCommand.php index 1ecd066db43ed..57de788608547 100644 --- a/src/Symfony/Bundle/WebServerBundle/Command/ServerStartCommand.php +++ b/src/Symfony/Bundle/WebServerBundle/Command/ServerStartCommand.php @@ -100,6 +100,12 @@ protected function execute(InputInterface $input, OutputInterface $output) return 1; } + // deprecated, logic to be removed in 4.0 + // this allows the commands to work out of the box with web/ and public/ + if ($this->documentRoot && !is_dir($this->documentRoot) && is_dir(dirname($this->documentRoot).'/web')) { + $this->documentRoot = dirname($this->documentRoot).'/web'; + } + if (null === $documentRoot = $input->getOption('docroot')) { if (!$this->documentRoot) { $io->error('The document root directory must be either passed as first argument of the constructor or through the "docroot" input option.'); diff --git a/src/Symfony/Bundle/WebServerBundle/Resources/config/webserver.xml b/src/Symfony/Bundle/WebServerBundle/Resources/config/webserver.xml index 2815c6d2cfbf5..1723e0bcd925f 100644 --- a/src/Symfony/Bundle/WebServerBundle/Resources/config/webserver.xml +++ b/src/Symfony/Bundle/WebServerBundle/Resources/config/webserver.xml @@ -8,13 +8,13 @@ - %kernel.project_dir%/web + %kernel.project_dir%/public %kernel.environment% - %kernel.project_dir%/web + %kernel.project_dir%/public %kernel.environment% From d1ce5322a6aabe5d1675754775d318b1ba88c600 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Fri, 14 Jul 2017 14:26:39 +0200 Subject: [PATCH 0433/1099] [Cache] add constructor docblocks for clarity --- src/Symfony/Component/Cache/Simple/AbstractCache.php | 4 ++++ src/Symfony/Component/Cache/Simple/ApcuCache.php | 5 +++++ src/Symfony/Component/Cache/Simple/DoctrineCache.php | 5 +++++ src/Symfony/Component/Cache/Simple/FilesystemCache.php | 5 +++++ src/Symfony/Component/Cache/Simple/MemcachedCache.php | 5 +++++ src/Symfony/Component/Cache/Simple/PhpFilesCache.php | 7 +++++++ src/Symfony/Component/Cache/Simple/RedisCache.php | 2 ++ 7 files changed, 33 insertions(+) diff --git a/src/Symfony/Component/Cache/Simple/AbstractCache.php b/src/Symfony/Component/Cache/Simple/AbstractCache.php index bbd35780fd5c4..e4046463f1609 100644 --- a/src/Symfony/Component/Cache/Simple/AbstractCache.php +++ b/src/Symfony/Component/Cache/Simple/AbstractCache.php @@ -30,6 +30,10 @@ abstract class AbstractCache implements CacheInterface, LoggerAwareInterface private $defaultLifetime; + /** + * @param string $namespace + * @param int $defaultLifetime + */ protected function __construct($namespace = '', $defaultLifetime = 0) { $this->defaultLifetime = max(0, (int) $defaultLifetime); diff --git a/src/Symfony/Component/Cache/Simple/ApcuCache.php b/src/Symfony/Component/Cache/Simple/ApcuCache.php index 16aa8661f07a2..e583b44341dce 100644 --- a/src/Symfony/Component/Cache/Simple/ApcuCache.php +++ b/src/Symfony/Component/Cache/Simple/ApcuCache.php @@ -17,6 +17,11 @@ class ApcuCache extends AbstractCache { use ApcuTrait; + /** + * @param string $namespace + * @param int $defaultLifetime + * @param string|null $version + */ public function __construct($namespace = '', $defaultLifetime = 0, $version = null) { $this->init($namespace, $defaultLifetime, $version); diff --git a/src/Symfony/Component/Cache/Simple/DoctrineCache.php b/src/Symfony/Component/Cache/Simple/DoctrineCache.php index 395c34dd81bd0..00f0b9c6fc326 100644 --- a/src/Symfony/Component/Cache/Simple/DoctrineCache.php +++ b/src/Symfony/Component/Cache/Simple/DoctrineCache.php @@ -18,6 +18,11 @@ class DoctrineCache extends AbstractCache { use DoctrineTrait; + /** + * @param CacheProvider $provider + * @param string $namespace + * @param int $defaultLifetime + */ public function __construct(CacheProvider $provider, $namespace = '', $defaultLifetime = 0) { parent::__construct('', $defaultLifetime); diff --git a/src/Symfony/Component/Cache/Simple/FilesystemCache.php b/src/Symfony/Component/Cache/Simple/FilesystemCache.php index a60312ea57fed..dac9ade9ca40e 100644 --- a/src/Symfony/Component/Cache/Simple/FilesystemCache.php +++ b/src/Symfony/Component/Cache/Simple/FilesystemCache.php @@ -17,6 +17,11 @@ class FilesystemCache extends AbstractCache { use FilesystemTrait; + /** + * @param string $namespace + * @param int $defaultLifetime + * @param string|null $directory + */ public function __construct($namespace = '', $defaultLifetime = 0, $directory = null) { parent::__construct('', $defaultLifetime); diff --git a/src/Symfony/Component/Cache/Simple/MemcachedCache.php b/src/Symfony/Component/Cache/Simple/MemcachedCache.php index 1d5ee73c31d2c..7717740622c5e 100644 --- a/src/Symfony/Component/Cache/Simple/MemcachedCache.php +++ b/src/Symfony/Component/Cache/Simple/MemcachedCache.php @@ -19,6 +19,11 @@ class MemcachedCache extends AbstractCache protected $maxIdLength = 250; + /** + * @param \Memcached $client + * @param string $namespace + * @param int $defaultLifetime + */ public function __construct(\Memcached $client, $namespace = '', $defaultLifetime = 0) { $this->init($client, $namespace, $defaultLifetime); diff --git a/src/Symfony/Component/Cache/Simple/PhpFilesCache.php b/src/Symfony/Component/Cache/Simple/PhpFilesCache.php index c4d120080637b..810b80f81275c 100644 --- a/src/Symfony/Component/Cache/Simple/PhpFilesCache.php +++ b/src/Symfony/Component/Cache/Simple/PhpFilesCache.php @@ -18,6 +18,13 @@ class PhpFilesCache extends AbstractCache { use PhpFilesTrait; + /** + * @param string $namespace + * @param int $defaultLifetime + * @param string|null $directory + * + * @throws CacheException if OPcache is not enabled + */ public function __construct($namespace = '', $defaultLifetime = 0, $directory = null) { if (!static::isSupported()) { diff --git a/src/Symfony/Component/Cache/Simple/RedisCache.php b/src/Symfony/Component/Cache/Simple/RedisCache.php index 799a3d082fede..e82c0627e241d 100644 --- a/src/Symfony/Component/Cache/Simple/RedisCache.php +++ b/src/Symfony/Component/Cache/Simple/RedisCache.php @@ -19,6 +19,8 @@ class RedisCache extends AbstractCache /** * @param \Redis|\RedisArray|\RedisCluster|\Predis\Client $redisClient + * @param string $namespace + * @param int $defaultLifetime */ public function __construct($redisClient, $namespace = '', $defaultLifetime = 0) { From b2c0dc39011aa689b32d56bb935594a47b7dd859 Mon Sep 17 00:00:00 2001 From: Gregor Harlan Date: Sun, 16 Jul 2017 20:35:34 +0200 Subject: [PATCH 0434/1099] [Stopwatch] Fix precision for root section --- src/Symfony/Component/Stopwatch/Stopwatch.php | 2 +- .../Component/Stopwatch/Tests/StopwatchTest.php | 12 ++++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/Stopwatch/Stopwatch.php b/src/Symfony/Component/Stopwatch/Stopwatch.php index cbe08cc7c1f0f..80a1873f67d3e 100644 --- a/src/Symfony/Component/Stopwatch/Stopwatch.php +++ b/src/Symfony/Component/Stopwatch/Stopwatch.php @@ -38,8 +38,8 @@ class Stopwatch */ public function __construct($morePrecision = false) { - $this->reset(); $this->morePrecision = $morePrecision; + $this->reset(); } /** diff --git a/src/Symfony/Component/Stopwatch/Tests/StopwatchTest.php b/src/Symfony/Component/Stopwatch/Tests/StopwatchTest.php index 519803d9908d2..a63b54d6a2506 100644 --- a/src/Symfony/Component/Stopwatch/Tests/StopwatchTest.php +++ b/src/Symfony/Component/Stopwatch/Tests/StopwatchTest.php @@ -100,6 +100,18 @@ public function testStopWithoutStart() $stopwatch->stop('foo'); } + public function testMorePrecision() + { + $stopwatch = new Stopwatch(true); + + $stopwatch->start('foo'); + $event = $stopwatch->stop('foo'); + + $this->assertInternalType('float', $event->getStartTime()); + $this->assertInternalType('float', $event->getEndTime()); + $this->assertInternalType('float', $event->getDuration()); + } + public function testSection() { $stopwatch = new Stopwatch(); From 6ab8ca0d3627a728c8995e559bc4544c5d82d566 Mon Sep 17 00:00:00 2001 From: Alessandro Chitolina Date: Mon, 17 Jul 2017 11:57:18 +0200 Subject: [PATCH 0435/1099] disable inlining deprecated services --- .../Compiler/InlineServiceDefinitionsPass.php | 2 +- .../Tests/ContainerBuilderTest.php | 21 +++++++++++++++ .../Tests/Dumper/PhpDumperTest.php | 26 +++++++++++++++++++ 3 files changed, 48 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/DependencyInjection/Compiler/InlineServiceDefinitionsPass.php b/src/Symfony/Component/DependencyInjection/Compiler/InlineServiceDefinitionsPass.php index 1beaaf0c53ce0..bf95ea5b0a269 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/InlineServiceDefinitionsPass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/InlineServiceDefinitionsPass.php @@ -113,7 +113,7 @@ private function isInlineableDefinition(ContainerBuilder $container, $id, Defini return true; } - if ($definition->isPublic() || $definition->isLazy()) { + if ($definition->isDeprecated() || $definition->isPublic() || $definition->isLazy()) { return false; } diff --git a/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php b/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php index 732ce97a17dcc..3c14bfc19895e 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php @@ -891,6 +891,27 @@ public function testAutowiring() $this->assertEquals('a', (string) $container->getDefinition('b')->getArgument(0)); } + + /** + * This test checks the trigger of a deprecation note and should not be removed in major releases. + * + * @group legacy + * @expectedDeprecation The "foo" service is deprecated. You should stop using it, as it will soon be removed. + */ + public function testPrivateServiceTriggersDeprecation() + { + $container = new ContainerBuilder(); + $container->register('foo', 'stdClass') + ->setPublic(false) + ->setDeprecated(true); + $container->register('bar', 'stdClass') + ->setPublic(true) + ->setProperty('foo', new Reference('foo')); + + $container->compile(); + + $container->get('bar'); + } } class FooClass diff --git a/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php b/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php index 20e784ec1a7bc..c49586463d7cc 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php @@ -360,4 +360,30 @@ public function testDumpHandlesLiteralClassWithRootNamespace() $this->assertInstanceOf('stdClass', $container->get('foo')); } + + /** + * This test checks the trigger of a deprecation note and should not be removed in major releases. + * + * @group legacy + * @expectedDeprecation The "foo" service is deprecated. You should stop using it, as it will soon be removed. + */ + public function testPrivateServiceTriggersDeprecation() + { + $container = new ContainerBuilder(); + $container->register('foo', 'stdClass') + ->setPublic(false) + ->setDeprecated(true); + $container->register('bar', 'stdClass') + ->setPublic(true) + ->setProperty('foo', new Reference('foo')); + + $container->compile(); + + $dumper = new PhpDumper($container); + eval('?>'.$dumper->dump(array('class' => 'Symfony_DI_PhpDumper_Test_Private_Service_Triggers_Deprecation'))); + + $container = new \Symfony_DI_PhpDumper_Test_Private_Service_Triggers_Deprecation(); + + $container->get('bar'); + } } From 5508a00e741f31fd5fc2be29334fa446d04bf954 Mon Sep 17 00:00:00 2001 From: Jonathan Vollebregt Date: Sun, 16 Jul 2017 10:47:45 +0200 Subject: [PATCH 0436/1099] [HttpFoundation] Set meta refresh time to 0 in RedirectResponse content --- src/Symfony/Component/HttpFoundation/RedirectResponse.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/HttpFoundation/RedirectResponse.php b/src/Symfony/Component/HttpFoundation/RedirectResponse.php index 5a775ad159f3a..4118fff24c892 100644 --- a/src/Symfony/Component/HttpFoundation/RedirectResponse.php +++ b/src/Symfony/Component/HttpFoundation/RedirectResponse.php @@ -83,7 +83,7 @@ public function setTargetUrl($url) - + Redirecting to %1$s From b5b8c1583170f6a8ed91f0e345bb49a0049430b7 Mon Sep 17 00:00:00 2001 From: "Issei.M" Date: Wed, 12 Jul 2017 23:04:14 +0900 Subject: [PATCH 0437/1099] [Security] Fix wrong term in UserProviderInterface --- .../Component/Security/Core/User/UserProviderInterface.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/Security/Core/User/UserProviderInterface.php b/src/Symfony/Component/Security/Core/User/UserProviderInterface.php index d17e3b704d981..03f38f08848ba 100644 --- a/src/Symfony/Component/Security/Core/User/UserProviderInterface.php +++ b/src/Symfony/Component/Security/Core/User/UserProviderInterface.php @@ -50,7 +50,7 @@ interface UserProviderInterface public function loadUserByUsername($username); /** - * Refreshes the user for the account interface. + * Refreshes the user. * * It is up to the implementation to decide if the user data should be * totally reloaded (e.g. from the database), or if the UserInterface @@ -61,7 +61,7 @@ public function loadUserByUsername($username); * * @return UserInterface * - * @throws UnsupportedUserException if the account is not supported + * @throws UnsupportedUserException if the user is not supported */ public function refreshUser(UserInterface $user); From 9f969529f016cfc2767d9c4da38e3975a0d23ef4 Mon Sep 17 00:00:00 2001 From: Roland Franssen Date: Sat, 20 May 2017 15:15:17 +0200 Subject: [PATCH 0438/1099] [DI] Removed deprecated setting private/pre-defined services --- .../DependencyInjection/CHANGELOG.md | 2 + .../DependencyInjection/Container.php | 37 ++++++----- .../Tests/ContainerTest.php | 61 ++++++------------- .../Tests/Dumper/PhpDumperTest.php | 23 +------ 4 files changed, 39 insertions(+), 84 deletions(-) diff --git a/src/Symfony/Component/DependencyInjection/CHANGELOG.md b/src/Symfony/Component/DependencyInjection/CHANGELOG.md index 2f31f9a29cefb..80ef0972860a7 100644 --- a/src/Symfony/Component/DependencyInjection/CHANGELOG.md +++ b/src/Symfony/Component/DependencyInjection/CHANGELOG.md @@ -19,6 +19,8 @@ CHANGELOG * removed `ContainerBuilder::addClassResource()`, use the `addObjectResource()` or the `getReflectionClass()` method instead. * removed support for top-level anonymous services * removed silent behavior for unused attributes and elements + * removed support for setting and accessing private services in `Container` + * removed support for setting pre-defined services in `Container` 3.4.0 ----- diff --git a/src/Symfony/Component/DependencyInjection/Container.php b/src/Symfony/Component/DependencyInjection/Container.php index 49a547545b729..6144d3f0280c1 100644 --- a/src/Symfony/Component/DependencyInjection/Container.php +++ b/src/Symfony/Component/DependencyInjection/Container.php @@ -151,30 +151,25 @@ public function set($id, $service) throw new InvalidArgumentException('You cannot set service "service_container".'); } + if (isset($this->privates[$id])) { + throw new InvalidArgumentException(sprintf('You cannot set the private service "%s".', $id)); + } + + if (isset($this->methodMap[$id])) { + throw new InvalidArgumentException(sprintf('You cannot set the pre-defined service "%s".', $id)); + } + if (isset($this->aliases[$id])) { unset($this->aliases[$id]); } - $this->services[$id] = $service; - if (null === $service) { unset($this->services[$id]); - } - if (isset($this->privates[$id])) { - if (null === $service) { - @trigger_error(sprintf('Unsetting the "%s" private service is deprecated since Symfony 3.2 and won\'t be supported anymore in Symfony 4.0.', $id), E_USER_DEPRECATED); - unset($this->privates[$id]); - } else { - @trigger_error(sprintf('Setting the "%s" private service is deprecated since Symfony 3.2 and won\'t be supported anymore in Symfony 4.0.', $id), E_USER_DEPRECATED); - } - } elseif (isset($this->methodMap[$id])) { - if (null === $service) { - @trigger_error(sprintf('Unsetting the "%s" pre-defined service is deprecated since Symfony 3.3 and won\'t be supported anymore in Symfony 4.0.', $id), E_USER_DEPRECATED); - } else { - @trigger_error(sprintf('Setting the "%s" pre-defined service is deprecated since Symfony 3.3 and won\'t be supported anymore in Symfony 4.0.', $id), E_USER_DEPRECATED); - } + return; } + + $this->services[$id] = $service; } /** @@ -187,7 +182,7 @@ public function set($id, $service) public function has($id) { if (isset($this->privates[$id])) { - @trigger_error(sprintf('Checking for the existence of the "%s" private service is deprecated since Symfony 3.2 and won\'t be supported anymore in Symfony 4.0.', $id), E_USER_DEPRECATED); + return false; } if ('service_container' === $id) { return true; @@ -226,7 +221,11 @@ public function has($id) public function get($id, $invalidBehavior = self::EXCEPTION_ON_INVALID_REFERENCE) { if (isset($this->privates[$id])) { - @trigger_error(sprintf('Requesting the "%s" private service is deprecated since Symfony 3.2 and won\'t be supported anymore in Symfony 4.0.', $id), E_USER_DEPRECATED); + if (self::EXCEPTION_ON_INVALID_REFERENCE === $invalidBehavior) { + throw new ServiceNotFoundException($id); + } + + return; } if ('service_container' === $id) { return $this; @@ -295,7 +294,7 @@ public function initialized($id) } if (isset($this->privates[$id])) { - @trigger_error(sprintf('Checking for the initialization of the "%s" private service is deprecated since Symfony 3.4 and won\'t be supported anymore in Symfony 4.0.', $id), E_USER_DEPRECATED); + return false; } if (isset($this->aliases[$id])) { diff --git a/src/Symfony/Component/DependencyInjection/Tests/ContainerTest.php b/src/Symfony/Component/DependencyInjection/Tests/ContainerTest.php index 9b3db8af6d095..d94b575c7d10c 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/ContainerTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/ContainerTest.php @@ -147,6 +147,7 @@ public function testSet() public function testSetWithNullResetTheService() { $sc = new Container(); + $sc->set('foo', new \stdClass()); $sc->set('foo', null); $this->assertFalse($sc->has('foo'), '->set() with null service resets the service'); } @@ -159,22 +160,6 @@ public function testSetReplacesAlias() $this->assertSame($foo, $c->get('alias'), '->set() replaces an existing alias'); } - /** - * @group legacy - * @expectedDeprecation Unsetting the "bar" pre-defined service is deprecated since Symfony 3.3 and won't be supported anymore in Symfony 4.0. - */ - public function testSetWithNullResetPredefinedService() - { - $sc = new Container(); - $sc->set('foo', new \stdClass()); - $sc->set('foo', null); - $this->assertFalse($sc->has('foo'), '->set() with null service resets the service'); - - $sc = new ProjectServiceContainer(); - $sc->set('bar', null); - $this->assertTrue($sc->has('bar'), '->set() with null service resets the pre-defined service'); - } - public function testGet() { $sc = new ProjectServiceContainer(); @@ -275,15 +260,11 @@ public function testInitialized() $this->assertTrue($sc->initialized('alias'), '->initialized() returns true for alias if aliased service is initialized'); } - /** - * @group legacy - * @expectedDeprecation Checking for the initialization of the "internal" private service is deprecated since Symfony 3.4 and won't be supported anymore in Symfony 4.0. - */ public function testInitializedWithPrivateService() { $sc = new ProjectServiceContainer(); $sc->get('internal_dependency'); - $this->assertTrue($sc->initialized('internal')); + $this->assertFalse($sc->initialized('internal')); } public function testReset() @@ -360,42 +341,37 @@ public function testThatCloningIsNotSupported() } /** - * @group legacy - * @expectedDeprecation Unsetting the "internal" private service is deprecated since Symfony 3.2 and won't be supported anymore in Symfony 4.0. + * @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException + * @expectedExceptionMessage You cannot set the private service "internal". */ - public function testUnsetInternalPrivateServiceIsDeprecated() + public function testUnsetInternalPrivateService() { $c = new ProjectServiceContainer(); $c->set('internal', null); } /** - * @group legacy - * @expectedDeprecation Setting the "internal" private service is deprecated since Symfony 3.2 and won't be supported anymore in Symfony 4.0. + * @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException + * @expectedExceptionMessage You cannot set the private service "internal". */ - public function testChangeInternalPrivateServiceIsDeprecated() + public function testChangeInternalPrivateService() { $c = new ProjectServiceContainer(); - $c->set('internal', $internal = new \stdClass()); - $this->assertSame($c->get('internal'), $internal); + $c->set('internal', new \stdClass()); } - /** - * @group legacy - * @expectedDeprecation Checking for the existence of the "internal" private service is deprecated since Symfony 3.2 and won't be supported anymore in Symfony 4.0. - */ - public function testCheckExistenceOfAnInternalPrivateServiceIsDeprecated() + public function testCheckExistenceOfAnInternalPrivateService() { $c = new ProjectServiceContainer(); $c->get('internal_dependency'); - $this->assertTrue($c->has('internal')); + $this->assertFalse($c->has('internal')); } /** - * @group legacy - * @expectedDeprecation Requesting the "internal" private service is deprecated since Symfony 3.2 and won't be supported anymore in Symfony 4.0. + * @expectedException \Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException + * @expectedExceptionMessage You have requested a non-existent service "internal". */ - public function testRequestAnInternalSharedPrivateServiceIsDeprecated() + public function testRequestAnInternalSharedPrivateService() { $c = new ProjectServiceContainer(); $c->get('internal_dependency'); @@ -403,16 +379,13 @@ public function testRequestAnInternalSharedPrivateServiceIsDeprecated() } /** - * @group legacy - * @expectedDeprecation Setting the "bar" pre-defined service is deprecated since Symfony 3.3 and won't be supported anymore in Symfony 4.0. + * @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException + * @expectedExceptionMessage You cannot set the pre-defined service "bar". */ - public function testReplacingAPreDefinedServiceIsDeprecated() + public function testReplacingAPreDefinedService() { $c = new ProjectServiceContainer(); $c->set('bar', new \stdClass()); - $c->set('bar', $bar = new \stdClass()); - - $this->assertSame($bar, $c->get('bar'), '->set() replaces a pre-defined service'); } } diff --git a/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php b/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php index aaa0084cfe69f..638e42a2a4dd9 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php @@ -267,8 +267,8 @@ public function testFrozenContainerWithoutAliases() } /** - * @group legacy - * @expectedDeprecation Setting the "bar" pre-defined service is deprecated since Symfony 3.3 and won't be supported anymore in Symfony 4.0. + * @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException + * @expectedExceptionMessage You cannot set the pre-defined service "bar". */ public function testOverrideServiceWhenUsingADumpedContainer() { @@ -277,25 +277,6 @@ public function testOverrideServiceWhenUsingADumpedContainer() $container = new \ProjectServiceContainer(); $container->set('bar', $bar = new \stdClass()); - $container->setParameter('foo_bar', 'foo_bar'); - - $this->assertSame($bar, $container->get('bar'), '->set() overrides an already defined service'); - } - - /** - * @group legacy - * @expectedDeprecation Setting the "bar" pre-defined service is deprecated since Symfony 3.3 and won't be supported anymore in Symfony 4.0. - */ - public function testOverrideServiceWhenUsingADumpedContainerAndServiceIsUsedFromAnotherOne() - { - require_once self::$fixturesPath.'/php/services9.php'; - require_once self::$fixturesPath.'/includes/foo.php'; - require_once self::$fixturesPath.'/includes/classes.php'; - - $container = new \ProjectServiceContainer(); - $container->set('bar', $bar = new \stdClass()); - - $this->assertSame($bar, $container->get('foo')->bar, '->set() overrides an already defined service'); } /** From 1bdfe0b39bfc01b9d12c9aa08ff4e576fb56ed3c Mon Sep 17 00:00:00 2001 From: Yonel Ceruto Date: Fri, 14 Jul 2017 18:24:11 -0400 Subject: [PATCH 0439/1099] [FrameworkBundle] Set default public directory on install assets --- .../Command/AssetsInstallCommand.php | 20 ++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/AssetsInstallCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/AssetsInstallCommand.php index 38256791ff565..3e2222f813ec7 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/AssetsInstallCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/AssetsInstallCommand.php @@ -46,16 +46,16 @@ protected function configure() $this ->setName('assets:install') ->setDefinition(array( - new InputArgument('target', InputArgument::OPTIONAL, 'The target directory', 'web'), + new InputArgument('target', InputArgument::OPTIONAL, 'The target directory', 'public'), )) ->addOption('symlink', null, InputOption::VALUE_NONE, 'Symlinks the assets instead of copying it') ->addOption('relative', null, InputOption::VALUE_NONE, 'Make relative symlinks') - ->setDescription('Installs bundles web assets under a public web directory') + ->setDescription('Installs bundles web assets under a public directory') ->setHelp(<<<'EOT' The %command.name% command installs bundle assets into a given -directory (e.g. the web directory). +directory (e.g. the public directory). - php %command.full_name% web + php %command.full_name% public A "bundles" directory will be created inside the target directory and the "Resources/public" directory of each bundle will be copied into it. @@ -63,11 +63,11 @@ protected function configure() To create a symlink to each bundle instead of copying its assets, use the --symlink option (will fall back to hard copies when symbolic links aren't possible: - php %command.full_name% web --symlink + php %command.full_name% public --symlink To make symlink relative, add the --relative option: - php %command.full_name% web --symlink --relative + php %command.full_name% public --symlink --relative EOT ) @@ -85,7 +85,13 @@ protected function execute(InputInterface $input, OutputInterface $output) $targetArg = $this->getContainer()->getParameter('kernel.project_dir').'/'.$targetArg; if (!is_dir($targetArg)) { - throw new \InvalidArgumentException(sprintf('The target directory "%s" does not exist.', $input->getArgument('target'))); + // deprecated, logic to be removed in 4.0 + // this allows the commands to work out of the box with web/ and public/ + if (is_dir(dirname($targetArg).'/web')) { + $targetArg = dirname($targetArg).'/web'; + } else { + throw new \InvalidArgumentException(sprintf('The target directory "%s" does not exist.', $input->getArgument('target'))); + } } } From 6ea71cb2ccc205294798d809e2ee295cfd9a0b5f Mon Sep 17 00:00:00 2001 From: Tobias Schultze Date: Thu, 6 Jul 2017 15:19:41 +0200 Subject: [PATCH 0440/1099] [TwigBridge] deprecate TwigRenderer --- src/Symfony/Bridge/Twig/CHANGELOG.md | 5 +++++ .../Bridge/Twig/Extension/FormExtension.php | 4 ++-- src/Symfony/Bridge/Twig/Form/TwigRenderer.php | 4 ++++ .../Bridge/Twig/Node/FormThemeNode.php | 14 ++++++++++++- .../Bridge/Twig/Node/RenderBlockNode.php | 2 +- .../Twig/Node/SearchAndRenderBlockNode.php | 2 +- ...xtensionBootstrap3HorizontalLayoutTest.php | 7 +++++-- .../FormExtensionBootstrap3LayoutTest.php | 7 +++++-- .../Extension/FormExtensionDivLayoutTest.php | 7 +++++-- .../FormExtensionTableLayoutTest.php | 7 +++++-- .../Tests/Extension/RuntimeLoaderProvider.php | 6 +++--- .../Bridge/Twig/Tests/Node/FormThemeTest.php | 4 ++-- .../Node/SearchAndRenderBlockNodeTest.php | 20 +++++++++---------- .../TwigBundle/Resources/config/form.xml | 2 +- .../DependencyInjection/TwigExtensionTest.php | 4 ++-- 15 files changed, 64 insertions(+), 31 deletions(-) diff --git a/src/Symfony/Bridge/Twig/CHANGELOG.md b/src/Symfony/Bridge/Twig/CHANGELOG.md index b59d85ea0b4a4..0cd6c40e60ecc 100644 --- a/src/Symfony/Bridge/Twig/CHANGELOG.md +++ b/src/Symfony/Bridge/Twig/CHANGELOG.md @@ -1,6 +1,11 @@ CHANGELOG ========= +3.4.0 +----- + + * deprecated `Symfony\Bridge\Twig\Form\TwigRenderer` + 3.3.0 ----- diff --git a/src/Symfony/Bridge/Twig/Extension/FormExtension.php b/src/Symfony/Bridge/Twig/Extension/FormExtension.php index 362879e43a89e..945cd0bc37b1a 100644 --- a/src/Symfony/Bridge/Twig/Extension/FormExtension.php +++ b/src/Symfony/Bridge/Twig/Extension/FormExtension.php @@ -84,7 +84,7 @@ public function getFunctions() new TwigFunction('form', null, array('node_class' => 'Symfony\Bridge\Twig\Node\RenderBlockNode', 'is_safe' => array('html'))), new TwigFunction('form_start', null, array('node_class' => 'Symfony\Bridge\Twig\Node\RenderBlockNode', 'is_safe' => array('html'))), new TwigFunction('form_end', null, array('node_class' => 'Symfony\Bridge\Twig\Node\RenderBlockNode', 'is_safe' => array('html'))), - new TwigFunction('csrf_token', array('Symfony\Bridge\Twig\Form\TwigRenderer', 'renderCsrfToken')), + new TwigFunction('csrf_token', array('Symfony\Component\Form\FormRenderer', 'renderCsrfToken')), ); } @@ -94,7 +94,7 @@ public function getFunctions() public function getFilters() { return array( - new TwigFilter('humanize', array('Symfony\Bridge\Twig\Form\TwigRenderer', 'humanize')), + new TwigFilter('humanize', array('Symfony\Component\Form\FormRenderer', 'humanize')), ); } diff --git a/src/Symfony/Bridge/Twig/Form/TwigRenderer.php b/src/Symfony/Bridge/Twig/Form/TwigRenderer.php index 9718c29cdb689..b8f15b85b4b1d 100644 --- a/src/Symfony/Bridge/Twig/Form/TwigRenderer.php +++ b/src/Symfony/Bridge/Twig/Form/TwigRenderer.php @@ -11,12 +11,16 @@ namespace Symfony\Bridge\Twig\Form; +@trigger_error(sprintf('The %s class is deprecated since version 3.4 and will be removed in 4.0. Use %s instead.', TwigRenderer::class, FormRenderer::class), E_USER_DEPRECATED); + use Symfony\Component\Form\FormRenderer; use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface; use Twig\Environment; /** * @author Bernhard Schussek + * + * @deprecated since version 3.4, to be removed in 4.0. Use Symfony\Component\Form\FormRenderer instead. */ class TwigRenderer extends FormRenderer implements TwigRendererInterface { diff --git a/src/Symfony/Bridge/Twig/Node/FormThemeNode.php b/src/Symfony/Bridge/Twig/Node/FormThemeNode.php index 06d2400c4eb8f..a66a13adc0287 100644 --- a/src/Symfony/Bridge/Twig/Node/FormThemeNode.php +++ b/src/Symfony/Bridge/Twig/Node/FormThemeNode.php @@ -11,7 +11,10 @@ namespace Symfony\Bridge\Twig\Node; +use Symfony\Bridge\Twig\Form\TwigRenderer; +use Symfony\Component\Form\FormRenderer; use Twig\Compiler; +use Twig\Error\RuntimeError; use Twig\Node\Node; /** @@ -26,9 +29,18 @@ public function __construct(Node $form, Node $resources, $lineno, $tag = null) public function compile(Compiler $compiler) { + try { + $compiler->getEnvironment()->getRuntime(FormRenderer::class); + $renderer = FormRenderer::class; + } catch (RuntimeError $e) { + $renderer = TwigRenderer::class; + } + $compiler ->addDebugInfo($this) - ->write('$this->env->getRuntime(\'Symfony\Bridge\Twig\Form\TwigRenderer\')->setTheme(') + ->write('$this->env->getRuntime(') + ->string($renderer) + ->raw(')->setTheme(') ->subcompile($this->getNode('form')) ->raw(', ') ->subcompile($this->getNode('resources')) diff --git a/src/Symfony/Bridge/Twig/Node/RenderBlockNode.php b/src/Symfony/Bridge/Twig/Node/RenderBlockNode.php index 0698fd9001628..dc7d860793f48 100644 --- a/src/Symfony/Bridge/Twig/Node/RenderBlockNode.php +++ b/src/Symfony/Bridge/Twig/Node/RenderBlockNode.php @@ -28,7 +28,7 @@ public function compile(Compiler $compiler) { $compiler->addDebugInfo($this); $arguments = iterator_to_array($this->getNode('arguments')); - $compiler->write('$this->env->getRuntime(\'Symfony\Bridge\Twig\Form\TwigRenderer\')->renderBlock('); + $compiler->write('$this->env->getRuntime(\'Symfony\Component\Form\FormRenderer\')->renderBlock('); if (isset($arguments[0])) { $compiler->subcompile($arguments[0]); diff --git a/src/Symfony/Bridge/Twig/Node/SearchAndRenderBlockNode.php b/src/Symfony/Bridge/Twig/Node/SearchAndRenderBlockNode.php index dcdba5c4db4bf..224e1d60e0aad 100644 --- a/src/Symfony/Bridge/Twig/Node/SearchAndRenderBlockNode.php +++ b/src/Symfony/Bridge/Twig/Node/SearchAndRenderBlockNode.php @@ -24,7 +24,7 @@ class SearchAndRenderBlockNode extends FunctionExpression public function compile(Compiler $compiler) { $compiler->addDebugInfo($this); - $compiler->raw('$this->env->getRuntime(\'Symfony\Bridge\Twig\Form\TwigRenderer\')->searchAndRenderBlock('); + $compiler->raw('$this->env->getRuntime(\'Symfony\Component\Form\FormRenderer\')->searchAndRenderBlock('); preg_match('/_([^_]+)$/', $this->getAttribute('name'), $matches); diff --git a/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionBootstrap3HorizontalLayoutTest.php b/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionBootstrap3HorizontalLayoutTest.php index f82a5d2e33ea4..52de993bee7b6 100644 --- a/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionBootstrap3HorizontalLayoutTest.php +++ b/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionBootstrap3HorizontalLayoutTest.php @@ -12,11 +12,11 @@ namespace Symfony\Bridge\Twig\Tests\Extension; use Symfony\Bridge\Twig\Extension\FormExtension; -use Symfony\Bridge\Twig\Form\TwigRenderer; use Symfony\Bridge\Twig\Form\TwigRendererEngine; use Symfony\Bridge\Twig\Extension\TranslationExtension; use Symfony\Bridge\Twig\Tests\Extension\Fixtures\StubTranslator; use Symfony\Bridge\Twig\Tests\Extension\Fixtures\StubFilesystemLoader; +use Symfony\Component\Form\FormRenderer; use Symfony\Component\Form\FormView; use Symfony\Component\Form\Tests\AbstractBootstrap3HorizontalLayoutTest; use Twig\Environment; @@ -29,6 +29,9 @@ class FormExtensionBootstrap3HorizontalLayoutTest extends AbstractBootstrap3Hori 'choice_attr', ); + /** + * @var FormRenderer + */ private $renderer; protected function setUp() @@ -48,7 +51,7 @@ protected function setUp() 'bootstrap_3_horizontal_layout.html.twig', 'custom_widgets.html.twig', ), $environment); - $this->renderer = new TwigRenderer($rendererEngine, $this->getMockBuilder('Symfony\Component\Security\Csrf\CsrfTokenManagerInterface')->getMock()); + $this->renderer = new FormRenderer($rendererEngine, $this->getMockBuilder('Symfony\Component\Security\Csrf\CsrfTokenManagerInterface')->getMock()); $this->registerTwigRuntimeLoader($environment, $this->renderer); } diff --git a/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionBootstrap3LayoutTest.php b/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionBootstrap3LayoutTest.php index 93f08ed252bbe..15dd4e6d65552 100644 --- a/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionBootstrap3LayoutTest.php +++ b/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionBootstrap3LayoutTest.php @@ -12,11 +12,11 @@ namespace Symfony\Bridge\Twig\Tests\Extension; use Symfony\Bridge\Twig\Extension\FormExtension; -use Symfony\Bridge\Twig\Form\TwigRenderer; use Symfony\Bridge\Twig\Form\TwigRendererEngine; use Symfony\Bridge\Twig\Extension\TranslationExtension; use Symfony\Bridge\Twig\Tests\Extension\Fixtures\StubTranslator; use Symfony\Bridge\Twig\Tests\Extension\Fixtures\StubFilesystemLoader; +use Symfony\Component\Form\FormRenderer; use Symfony\Component\Form\FormView; use Symfony\Component\Form\Tests\AbstractBootstrap3LayoutTest; use Twig\Environment; @@ -25,6 +25,9 @@ class FormExtensionBootstrap3LayoutTest extends AbstractBootstrap3LayoutTest { use RuntimeLoaderProvider; + /** + * @var FormRenderer + */ private $renderer; protected function setUp() @@ -44,7 +47,7 @@ protected function setUp() 'bootstrap_3_layout.html.twig', 'custom_widgets.html.twig', ), $environment); - $this->renderer = new TwigRenderer($rendererEngine, $this->getMockBuilder('Symfony\Component\Security\Csrf\CsrfTokenManagerInterface')->getMock()); + $this->renderer = new FormRenderer($rendererEngine, $this->getMockBuilder('Symfony\Component\Security\Csrf\CsrfTokenManagerInterface')->getMock()); $this->registerTwigRuntimeLoader($environment, $this->renderer); } diff --git a/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionDivLayoutTest.php b/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionDivLayoutTest.php index 5367650e9dcc6..ea835fb91e541 100644 --- a/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionDivLayoutTest.php +++ b/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionDivLayoutTest.php @@ -12,12 +12,12 @@ namespace Symfony\Bridge\Twig\Tests\Extension; use Symfony\Bridge\Twig\Extension\FormExtension; -use Symfony\Bridge\Twig\Form\TwigRenderer; use Symfony\Bridge\Twig\Form\TwigRendererEngine; use Symfony\Bridge\Twig\Extension\TranslationExtension; use Symfony\Bridge\Twig\Tests\Extension\Fixtures\StubTranslator; use Symfony\Bridge\Twig\Tests\Extension\Fixtures\StubFilesystemLoader; use Symfony\Component\Form\ChoiceList\View\ChoiceView; +use Symfony\Component\Form\FormRenderer; use Symfony\Component\Form\FormView; use Symfony\Component\Form\Tests\AbstractDivLayoutTest; use Twig\Environment; @@ -26,6 +26,9 @@ class FormExtensionDivLayoutTest extends AbstractDivLayoutTest { use RuntimeLoaderProvider; + /** + * @var FormRenderer + */ private $renderer; protected function setUp() @@ -48,7 +51,7 @@ protected function setUp() 'form_div_layout.html.twig', 'custom_widgets.html.twig', ), $environment); - $this->renderer = new TwigRenderer($rendererEngine, $this->getMockBuilder('Symfony\Component\Security\Csrf\CsrfTokenManagerInterface')->getMock()); + $this->renderer = new FormRenderer($rendererEngine, $this->getMockBuilder('Symfony\Component\Security\Csrf\CsrfTokenManagerInterface')->getMock()); $this->registerTwigRuntimeLoader($environment, $this->renderer); } diff --git a/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionTableLayoutTest.php b/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionTableLayoutTest.php index 5868e42ca5395..f972205333e4c 100644 --- a/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionTableLayoutTest.php +++ b/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionTableLayoutTest.php @@ -11,8 +11,8 @@ namespace Symfony\Bridge\Twig\Tests\Extension; +use Symfony\Component\Form\FormRenderer; use Symfony\Component\Form\FormView; -use Symfony\Bridge\Twig\Form\TwigRenderer; use Symfony\Bridge\Twig\Form\TwigRendererEngine; use Symfony\Bridge\Twig\Extension\FormExtension; use Symfony\Bridge\Twig\Extension\TranslationExtension; @@ -25,6 +25,9 @@ class FormExtensionTableLayoutTest extends AbstractTableLayoutTest { use RuntimeLoaderProvider; + /** + * @var FormRenderer + */ private $renderer; protected function setUp() @@ -45,7 +48,7 @@ protected function setUp() 'form_table_layout.html.twig', 'custom_widgets.html.twig', ), $environment); - $this->renderer = new TwigRenderer($rendererEngine, $this->getMockBuilder('Symfony\Component\Security\Csrf\CsrfTokenManagerInterface')->getMock()); + $this->renderer = new FormRenderer($rendererEngine, $this->getMockBuilder('Symfony\Component\Security\Csrf\CsrfTokenManagerInterface')->getMock()); $this->registerTwigRuntimeLoader($environment, $this->renderer); } diff --git a/src/Symfony/Bridge/Twig/Tests/Extension/RuntimeLoaderProvider.php b/src/Symfony/Bridge/Twig/Tests/Extension/RuntimeLoaderProvider.php index 90db2c5d6bd44..4934bef87d467 100644 --- a/src/Symfony/Bridge/Twig/Tests/Extension/RuntimeLoaderProvider.php +++ b/src/Symfony/Bridge/Twig/Tests/Extension/RuntimeLoaderProvider.php @@ -11,16 +11,16 @@ namespace Symfony\Bridge\Twig\Tests\Extension; -use Symfony\Bridge\Twig\Form\TwigRenderer; +use Symfony\Component\Form\FormRenderer; use Twig\Environment; trait RuntimeLoaderProvider { - protected function registerTwigRuntimeLoader(Environment $environment, TwigRenderer $renderer) + protected function registerTwigRuntimeLoader(Environment $environment, FormRenderer $renderer) { $loader = $this->getMockBuilder('Twig\RuntimeLoader\RuntimeLoaderInterface')->getMock(); $loader->expects($this->any())->method('load')->will($this->returnValueMap(array( - array('Symfony\Bridge\Twig\Form\TwigRenderer', $renderer), + array('Symfony\Component\Form\FormRenderer', $renderer), ))); $environment->addRuntimeLoader($loader); } diff --git a/src/Symfony/Bridge/Twig/Tests/Node/FormThemeTest.php b/src/Symfony/Bridge/Twig/Tests/Node/FormThemeTest.php index c40fcbdc90b3e..7c3fc9a6a0479 100644 --- a/src/Symfony/Bridge/Twig/Tests/Node/FormThemeTest.php +++ b/src/Symfony/Bridge/Twig/Tests/Node/FormThemeTest.php @@ -52,7 +52,7 @@ public function testCompile() $this->assertEquals( sprintf( - '$this->env->getRuntime(\'Symfony\Bridge\Twig\Form\TwigRenderer\')->setTheme(%s, array(0 => "tpl1", 1 => "tpl2"));', + '$this->env->getRuntime(\'Symfony\Component\Form\FormRenderer\')->setTheme(%s, array(0 => "tpl1", 1 => "tpl2"));', $this->getVariableGetter('form') ), trim($compiler->compile($node)->getSource()) @@ -64,7 +64,7 @@ public function testCompile() $this->assertEquals( sprintf( - '$this->env->getRuntime(\'Symfony\Bridge\Twig\Form\TwigRenderer\')->setTheme(%s, "tpl1");', + '$this->env->getRuntime(\'Symfony\Component\Form\FormRenderer\')->setTheme(%s, "tpl1");', $this->getVariableGetter('form') ), trim($compiler->compile($node)->getSource()) diff --git a/src/Symfony/Bridge/Twig/Tests/Node/SearchAndRenderBlockNodeTest.php b/src/Symfony/Bridge/Twig/Tests/Node/SearchAndRenderBlockNodeTest.php index fe91422a3535f..605445d69a4d9 100644 --- a/src/Symfony/Bridge/Twig/Tests/Node/SearchAndRenderBlockNodeTest.php +++ b/src/Symfony/Bridge/Twig/Tests/Node/SearchAndRenderBlockNodeTest.php @@ -35,7 +35,7 @@ public function testCompileWidget() $this->assertEquals( sprintf( - '$this->env->getRuntime(\'Symfony\Bridge\Twig\Form\TwigRenderer\')->searchAndRenderBlock(%s, \'widget\')', + '$this->env->getRuntime(\'Symfony\Component\Form\FormRenderer\')->searchAndRenderBlock(%s, \'widget\')', $this->getVariableGetter('form') ), trim($compiler->compile($node)->getSource()) @@ -58,7 +58,7 @@ public function testCompileWidgetWithVariables() $this->assertEquals( sprintf( - '$this->env->getRuntime(\'Symfony\Bridge\Twig\Form\TwigRenderer\')->searchAndRenderBlock(%s, \'widget\', array("foo" => "bar"))', + '$this->env->getRuntime(\'Symfony\Component\Form\FormRenderer\')->searchAndRenderBlock(%s, \'widget\', array("foo" => "bar"))', $this->getVariableGetter('form') ), trim($compiler->compile($node)->getSource()) @@ -78,7 +78,7 @@ public function testCompileLabelWithLabel() $this->assertEquals( sprintf( - '$this->env->getRuntime(\'Symfony\Bridge\Twig\Form\TwigRenderer\')->searchAndRenderBlock(%s, \'label\', array("label" => "my label"))', + '$this->env->getRuntime(\'Symfony\Component\Form\FormRenderer\')->searchAndRenderBlock(%s, \'label\', array("label" => "my label"))', $this->getVariableGetter('form') ), trim($compiler->compile($node)->getSource()) @@ -100,7 +100,7 @@ public function testCompileLabelWithNullLabel() // Otherwise the default label is overwritten with null. $this->assertEquals( sprintf( - '$this->env->getRuntime(\'Symfony\Bridge\Twig\Form\TwigRenderer\')->searchAndRenderBlock(%s, \'label\')', + '$this->env->getRuntime(\'Symfony\Component\Form\FormRenderer\')->searchAndRenderBlock(%s, \'label\')', $this->getVariableGetter('form') ), trim($compiler->compile($node)->getSource()) @@ -122,7 +122,7 @@ public function testCompileLabelWithEmptyStringLabel() // Otherwise the default label is overwritten with null. $this->assertEquals( sprintf( - '$this->env->getRuntime(\'Symfony\Bridge\Twig\Form\TwigRenderer\')->searchAndRenderBlock(%s, \'label\')', + '$this->env->getRuntime(\'Symfony\Component\Form\FormRenderer\')->searchAndRenderBlock(%s, \'label\')', $this->getVariableGetter('form') ), trim($compiler->compile($node)->getSource()) @@ -141,7 +141,7 @@ public function testCompileLabelWithDefaultLabel() $this->assertEquals( sprintf( - '$this->env->getRuntime(\'Symfony\Bridge\Twig\Form\TwigRenderer\')->searchAndRenderBlock(%s, \'label\')', + '$this->env->getRuntime(\'Symfony\Component\Form\FormRenderer\')->searchAndRenderBlock(%s, \'label\')', $this->getVariableGetter('form') ), trim($compiler->compile($node)->getSource()) @@ -168,7 +168,7 @@ public function testCompileLabelWithAttributes() // https://github.com/symfony/symfony/issues/5029 $this->assertEquals( sprintf( - '$this->env->getRuntime(\'Symfony\Bridge\Twig\Form\TwigRenderer\')->searchAndRenderBlock(%s, \'label\', array("foo" => "bar"))', + '$this->env->getRuntime(\'Symfony\Component\Form\FormRenderer\')->searchAndRenderBlock(%s, \'label\', array("foo" => "bar"))', $this->getVariableGetter('form') ), trim($compiler->compile($node)->getSource()) @@ -194,7 +194,7 @@ public function testCompileLabelWithLabelAndAttributes() $this->assertEquals( sprintf( - '$this->env->getRuntime(\'Symfony\Bridge\Twig\Form\TwigRenderer\')->searchAndRenderBlock(%s, \'label\', array("foo" => "bar", "label" => "value in argument"))', + '$this->env->getRuntime(\'Symfony\Component\Form\FormRenderer\')->searchAndRenderBlock(%s, \'label\', array("foo" => "bar", "label" => "value in argument"))', $this->getVariableGetter('form') ), trim($compiler->compile($node)->getSource()) @@ -225,7 +225,7 @@ public function testCompileLabelWithLabelThatEvaluatesToNull() // https://github.com/symfony/symfony/issues/5029 $this->assertEquals( sprintf( - '$this->env->getRuntime(\'Symfony\Bridge\Twig\Form\TwigRenderer\')->searchAndRenderBlock(%s, \'label\', (twig_test_empty($_label_ = ((true) ? (null) : (null))) ? array() : array("label" => $_label_)))', + '$this->env->getRuntime(\'Symfony\Component\Form\FormRenderer\')->searchAndRenderBlock(%s, \'label\', (twig_test_empty($_label_ = ((true) ? (null) : (null))) ? array() : array("label" => $_label_)))', $this->getVariableGetter('form') ), trim($compiler->compile($node)->getSource()) @@ -262,7 +262,7 @@ public function testCompileLabelWithLabelThatEvaluatesToNullAndAttributes() // https://github.com/symfony/symfony/issues/5029 $this->assertEquals( sprintf( - '$this->env->getRuntime(\'Symfony\Bridge\Twig\Form\TwigRenderer\')->searchAndRenderBlock(%s, \'label\', array("foo" => "bar", "label" => "value in attributes") + (twig_test_empty($_label_ = ((true) ? (null) : (null))) ? array() : array("label" => $_label_)))', + '$this->env->getRuntime(\'Symfony\Component\Form\FormRenderer\')->searchAndRenderBlock(%s, \'label\', array("foo" => "bar", "label" => "value in attributes") + (twig_test_empty($_label_ = ((true) ? (null) : (null))) ? array() : array("label" => $_label_)))', $this->getVariableGetter('form') ), trim($compiler->compile($node)->getSource()) diff --git a/src/Symfony/Bundle/TwigBundle/Resources/config/form.xml b/src/Symfony/Bundle/TwigBundle/Resources/config/form.xml index 3b0b147c4ba5f..b1cee0ae381f7 100644 --- a/src/Symfony/Bundle/TwigBundle/Resources/config/form.xml +++ b/src/Symfony/Bundle/TwigBundle/Resources/config/form.xml @@ -18,7 +18,7 @@ - + diff --git a/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/TwigExtensionTest.php b/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/TwigExtensionTest.php index e38bf5390617e..cdd686029423a 100644 --- a/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/TwigExtensionTest.php +++ b/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/TwigExtensionTest.php @@ -266,9 +266,9 @@ public function testRuntimeLoader() $loader = $container->getDefinition('twig.runtime_loader'); $args = $container->getDefinition((string) $loader->getArgument(0))->getArgument(0); - $this->assertArrayHasKey('Symfony\Bridge\Twig\Form\TwigRenderer', $args); + $this->assertArrayHasKey('Symfony\Component\Form\FormRenderer', $args); $this->assertArrayHasKey('FooClass', $args); - $this->assertEquals('twig.form.renderer', $args['Symfony\Bridge\Twig\Form\TwigRenderer']->getValues()[0]); + $this->assertEquals('twig.form.renderer', $args['Symfony\Component\Form\FormRenderer']->getValues()[0]); $this->assertEquals('foo', $args['FooClass']->getValues()[0]); } From f25a8b5c41ac9d2abf621f5990d4c59e7889df16 Mon Sep 17 00:00:00 2001 From: Robin Chalas Date: Sat, 15 Jul 2017 14:12:51 +0200 Subject: [PATCH 0441/1099] Fix lazy commands registration --- src/Symfony/Component/Console/Application.php | 5 ++--- .../Console/DependencyInjection/AddConsoleCommandPass.php | 2 ++ 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Component/Console/Application.php b/src/Symfony/Component/Console/Application.php index fff5d0a6e7b8c..e4551e339e3c8 100644 --- a/src/Symfony/Component/Console/Application.php +++ b/src/Symfony/Component/Console/Application.php @@ -466,7 +466,6 @@ public function get($name) $command = $this->commands[$name]; } elseif ($this->commandLoader && $this->commandLoader->has($name)) { $command = $this->commandLoader->get($name); - $command->setName($name); $this->add($command); } else { throw new CommandNotFoundException(sprintf('The command "%s" does not exist.', $name)); @@ -647,7 +646,7 @@ public function all($namespace = null) $commands = $this->commands; foreach ($this->commandLoader->getNames() as $name) { if (!isset($commands[$name])) { - $commands[$name] = $this->commandLoader->get($name); + $commands[$name] = $this->get($name); } } @@ -664,7 +663,7 @@ public function all($namespace = null) if ($this->commandLoader) { foreach ($this->commandLoader->getNames() as $name) { if (!isset($commands[$name]) && $namespace === $this->extractNamespace($name, substr_count($namespace, ':') + 1)) { - $commands[$name] = $this->commandLoader->get($name); + $commands[$name] = $this->get($name); } } } diff --git a/src/Symfony/Component/Console/DependencyInjection/AddConsoleCommandPass.php b/src/Symfony/Component/Console/DependencyInjection/AddConsoleCommandPass.php index 5a323421b13e8..1ceed91573c72 100644 --- a/src/Symfony/Component/Console/DependencyInjection/AddConsoleCommandPass.php +++ b/src/Symfony/Component/Console/DependencyInjection/AddConsoleCommandPass.php @@ -87,6 +87,8 @@ public function process(ContainerBuilder $container) } } + $definition->addMethodCall('setName', array($commandName)); + if ($aliases) { $definition->addMethodCall('setAliases', array($aliases)); } From 58d49f71f1e21c71ce2812649021392187bb7e98 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Mon, 17 Jul 2017 17:30:29 +0200 Subject: [PATCH 0442/1099] conflict for phpdocumentor/reflection-docblock 3.2 phpdocumentor/reflection-docblock included a change in release 3.2.0 which required a tag to be followed by a space. This conflicts with our use of the `@Group` annotation: ```php /** * @var \DateTime[] * @Groups({"a", "b"}) */ public $collection; ``` --- composer.json | 2 +- src/Symfony/Component/PropertyInfo/composer.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/composer.json b/composer.json index b87907b81e328..8730dd64159e8 100644 --- a/composer.json +++ b/composer.json @@ -95,7 +95,7 @@ "sensio/framework-extra-bundle": "^3.0.2" }, "conflict": { - "phpdocumentor/reflection-docblock": "<3.0", + "phpdocumentor/reflection-docblock": "<3.0||>=3.2.0", "phpdocumentor/type-resolver": "<0.2.0", "phpunit/phpunit": "<4.8.35|<5.4.3,>=5.0" }, diff --git a/src/Symfony/Component/PropertyInfo/composer.json b/src/Symfony/Component/PropertyInfo/composer.json index 23069a1e79870..f9df8807396c3 100644 --- a/src/Symfony/Component/PropertyInfo/composer.json +++ b/src/Symfony/Component/PropertyInfo/composer.json @@ -33,7 +33,7 @@ "doctrine/annotations": "~1.0" }, "conflict": { - "phpdocumentor/reflection-docblock": "<3.0", + "phpdocumentor/reflection-docblock": "<3.0||>=3.2.0", "phpdocumentor/type-resolver": "<0.2.0" }, "suggest": { From 30cd70dcad190e3ad13a8b301d95cbcdcccb0400 Mon Sep 17 00:00:00 2001 From: James Johnston Date: Mon, 17 Jul 2017 09:04:54 -0700 Subject: [PATCH 0443/1099] [DebugBundle] Added min_depth to Configuration This enables calling the recently-added setMinDepth function on VarCloner. --- .../Bundle/DebugBundle/DependencyInjection/Configuration.php | 5 +++++ .../DebugBundle/DependencyInjection/DebugExtension.php | 1 + .../Bundle/DebugBundle/Resources/config/schema/debug-1.0.xsd | 1 + 3 files changed, 7 insertions(+) diff --git a/src/Symfony/Bundle/DebugBundle/DependencyInjection/Configuration.php b/src/Symfony/Bundle/DebugBundle/DependencyInjection/Configuration.php index 5761e62a72e1a..4af24cd488393 100644 --- a/src/Symfony/Bundle/DebugBundle/DependencyInjection/Configuration.php +++ b/src/Symfony/Bundle/DebugBundle/DependencyInjection/Configuration.php @@ -36,6 +36,11 @@ public function getConfigTreeBuilder() ->min(-1) ->defaultValue(2500) ->end() + ->integerNode('min_depth') + ->info('Minimum tree depth to clone all the items, 1 is default') + ->min(0) + ->defaultValue(1) + ->end() ->integerNode('max_string_length') ->info('Max length of displayed strings, -1 means no limit') ->min(-1) diff --git a/src/Symfony/Bundle/DebugBundle/DependencyInjection/DebugExtension.php b/src/Symfony/Bundle/DebugBundle/DependencyInjection/DebugExtension.php index ce6d1b7c677e4..835d823664021 100644 --- a/src/Symfony/Bundle/DebugBundle/DependencyInjection/DebugExtension.php +++ b/src/Symfony/Bundle/DebugBundle/DependencyInjection/DebugExtension.php @@ -37,6 +37,7 @@ public function load(array $configs, ContainerBuilder $container) $container->getDefinition('var_dumper.cloner') ->addMethodCall('setMaxItems', array($config['max_items'])) + ->addMethodCall('setMinDepth', array($config['min_depth'])) ->addMethodCall('setMaxString', array($config['max_string_length'])); if (null !== $config['dump_destination']) { diff --git a/src/Symfony/Bundle/DebugBundle/Resources/config/schema/debug-1.0.xsd b/src/Symfony/Bundle/DebugBundle/Resources/config/schema/debug-1.0.xsd index a582ff8b2b70f..32306886020bf 100644 --- a/src/Symfony/Bundle/DebugBundle/Resources/config/schema/debug-1.0.xsd +++ b/src/Symfony/Bundle/DebugBundle/Resources/config/schema/debug-1.0.xsd @@ -8,6 +8,7 @@ + From 72947810a3bce10923c44a1c6b13117bb9f79f40 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Mon, 17 Jul 2017 19:27:31 +0200 Subject: [PATCH 0444/1099] fixed double-declaration --- src/Symfony/Component/Cache/Adapter/AbstractAdapter.php | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/Symfony/Component/Cache/Adapter/AbstractAdapter.php b/src/Symfony/Component/Cache/Adapter/AbstractAdapter.php index 0bffb16f253c9..26b33e683e2ff 100644 --- a/src/Symfony/Component/Cache/Adapter/AbstractAdapter.php +++ b/src/Symfony/Component/Cache/Adapter/AbstractAdapter.php @@ -32,11 +32,6 @@ abstract class AbstractAdapter implements AdapterInterface, LoggerAwareInterface private $createCacheItem; private $mergeByLifetime; - /** - * @var int|null The maximum length to enforce for identifiers or null when no limit applies - */ - protected $maxIdLength; - /** * @param string $namespace * @param int $defaultLifetime From f62dc85fd9b08d71d0ec54ea37ca714a6b54cb54 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Mon, 17 Jul 2017 19:33:01 +0200 Subject: [PATCH 0445/1099] updated CHANGELOG for 2.7.32 --- CHANGELOG-2.7.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/CHANGELOG-2.7.md b/CHANGELOG-2.7.md index f5471bf653f4b..335dfd82e4186 100644 --- a/CHANGELOG-2.7.md +++ b/CHANGELOG-2.7.md @@ -7,6 +7,17 @@ in 2.7 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/v2.7.0...v2.7.1 +* 2.7.32 (2017-07-17) + + * security #23507 [Security] validate empty passwords again (xabbuh) + * bug #23526 [HttpFoundation] Set meta refresh time to 0 in RedirectResponse content (jnvsor) + * bug #23468 [DI] Handle root namespace in service definitions (ro0NL) + * bug #23256 [Security] Fix authentication.failure event not dispatched on AccountStatusException (chalasr) + * bug #23461 Use rawurlencode() to transform the Cookie into a string (javiereguiluz) + * bug #23459 [TwigBundle] allow to configure custom formats in XML configs (xabbuh) + * bug #23261 Fixed absolute url generation for query strings and hash urls (alexander-schranz) + * bug #23398 [Filesystem] Dont copy perms when origin is remote (nicolas-grekas) + * 2.7.31 (2017-07-05) * bug #23378 [FrameworkBundle] Do not remove files from assets dir (1ed) From 5377fe5d6a544b3dc6ee269eeac275f0abb7cbcb Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Mon, 17 Jul 2017 19:33:09 +0200 Subject: [PATCH 0446/1099] update CONTRIBUTORS for 2.7.32 --- CONTRIBUTORS.md | 35 +++++++++++++++++++---------------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index 3e670f8d67e90..47a6cf9986dcf 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -19,13 +19,13 @@ Symfony is the result of the work of many people who made the code better - Ryan Weaver (weaverryan) - Javier Eguiluz (javier.eguiluz) - Hugo Hamon (hhamon) - - Abdellatif Ait boudad (aitboudad) - Maxime Steinhausser (ogizanagi) + - Abdellatif Ait boudad (aitboudad) - Robin Chalas (chalas_r) - Romain Neutron (romain) - Pascal Borreli (pborreli) - - Wouter De Jong (wouterj) - Grégoire Pineau (lyrixx) + - Wouter De Jong (wouterj) - Joseph Bielawski (stloyd) - Karma Dordrak (drak) - Lukas Kahwe Smith (lsmith) @@ -35,8 +35,8 @@ Symfony is the result of the work of many people who made the code better - Benjamin Eberlei (beberlei) - Igor Wiedler (igorw) - Eriksen Costa (eriksencosta) - - Jules Pietri (heah) - Roland Franssen (ro0) + - Jules Pietri (heah) - Sarah Khalil (saro0h) - Guilhem Niot (energetick) - Jonathan Wage (jwage) @@ -93,6 +93,7 @@ Symfony is the result of the work of many people who made the code better - Maxime STEINHAUSSER - Alexander M. Turek (derrabus) - Michal Piotrowski (eventhorizon) + - Dany Maillard (maidmaid) - Issei Murasawa (issei_m) - Tim Nagel (merk) - Brice BERNARD (brikou) @@ -133,7 +134,6 @@ Symfony is the result of the work of many people who made the code better - Guilherme Blanco (guilhermeblanco) - Pablo Godel (pgodel) - Jérémie Augustin (jaugustin) - - Dany Maillard (maidmaid) - Andréia Bohner (andreia) - Rafael Dohms (rdohms) - Arnaud Kleinpeter (nanocom) @@ -141,6 +141,7 @@ Symfony is the result of the work of many people who made the code better - David Maicher (dmaicher) - Mikael Pajunen - Joel Wurtz (brouznouf) + - Jérôme Vasseur (jvasseur) - Grégoire Paris (greg0ire) - Philipp Wahala (hifi) - Vyacheslav Pavlov @@ -150,7 +151,6 @@ Symfony is the result of the work of many people who made the code better - Thomas Rabaix (rande) - Rouven Weßling (realityking) - Teoh Han Hui (teohhanhui) - - Jérôme Vasseur (jvasseur) - Clemens Tolboom - Helmer Aaviksoo - Hiromi Hishida (77web) @@ -162,6 +162,7 @@ Symfony is the result of the work of many people who made the code better - Artur Kotyrba - jeremyFreeAgent (Jérémy Romey) (jeremyfreeagent) - James Halsall (jaitsu) + - Chris Wilkinson (thewilkybarkid) - Warnar Boekkooi (boekkooi) - Dmitrii Chekaliuk (lazyhammer) - Clément JOBEILI (dator) @@ -174,7 +175,6 @@ Symfony is the result of the work of many people who made the code better - Dennis Benkert (denderello) - Benjamin Dulau (dbenjamin) - Mathieu Lemoine (lemoinem) - - Chris Wilkinson (thewilkybarkid) - Andreas Hucks (meandmymonkey) - Noel Guilbert (noel) - Stepan Anchugov (kix) @@ -238,6 +238,7 @@ Symfony is the result of the work of many people who made the code better - Alif Rachmawadi - Kristen Gilden (kgilden) - Pierre-Yves LEBECQ (pylebecq) + - Jordan Samouh (jordansamouh) - Alex Pott - Jakub Kucharovic (jkucharovic) - Uwe Jäger (uwej711) @@ -248,6 +249,7 @@ Symfony is the result of the work of many people who made the code better - GordonsLondon - Jan Sorgalla (jsor) - Ray + - Nikolay Labinskiy (e-moe) - Leo Feyer - Chekote - Thomas Adam @@ -274,8 +276,8 @@ Symfony is the result of the work of many people who made the code better - Marc Weistroff (futurecat) - Christian Schmidt - Hidde Wieringa (hiddewie) + - Alessandro Chitolina - Chad Sikorra (chadsikorra) - - Jordan Samouh (jordansamouh) - Chris Smith (cs278) - Florian Klein (docteurklein) - Manuel Kiessling (manuelkiessling) @@ -294,7 +296,6 @@ Symfony is the result of the work of many people who made the code better - Victor Bocharsky (bocharsky_bw) - Jan Decavele (jandc) - Gustavo Piltcher - - Nikolay Labinskiy (e-moe) - Stepan Tanasiychuk (stfalcon) - Tiago Ribeiro (fixe) - Hidde Boomsma (hboomsma) @@ -309,6 +310,7 @@ Symfony is the result of the work of many people who made the code better - Thomas Schulz (king2500) - Dariusz Rumiński - Berny Cantos (xphere81) + - Thierry Thuon (lepiaf) - Ricard Clau (ricardclau) - Mark Challoner (markchalloner) - Gregor Harlan (gharlan) @@ -327,6 +329,7 @@ Symfony is the result of the work of many people who made the code better - Inal DJAFAR (inalgnu) - Christian Gärtner (dagardner) - Tomasz Kowalczyk (thunderer) + - Michael Babker (mbabker) - François-Xavier de Guillebon (de-gui_f) - Damien Alexandre (damienalexandre) - Felix Labrecque @@ -335,7 +338,6 @@ Symfony is the result of the work of many people who made the code better - Robbert Klarenbeek (robbertkl) - Thomas Calvet (fancyweb) - Niels Keurentjes (curry684) - - Alessandro Chitolina - JhonnyL - hossein zolfi (ocean) - Clément Gautier (clementgautier) @@ -401,6 +403,7 @@ Symfony is the result of the work of many people who made the code better - Olivier Dolbeau (odolbeau) - Jan Rosier (rosier) - Thomas Royer (cydonia7) + - Arturs Vonda - Josip Kruslin - Asmir Mustafic (goetas) - vagrant @@ -428,6 +431,7 @@ Symfony is the result of the work of many people who made the code better - David Badura (davidbadura) - Zander Baldwin - Adam Harvey + - Maxime Veber (nek-) - Alex Bakhturin - Alexander Obuhovich (aik099) - boombatower @@ -441,6 +445,7 @@ Symfony is the result of the work of many people who made the code better - Gladhon - Benoît Burnichon (bburnichon) - Sebastian Bergmann + - Miroslav Sustek - Pablo Díez (pablodip) - Kevin McBride - Sergio Santoro @@ -550,7 +555,6 @@ Symfony is the result of the work of many people who made the code better - Maxime Douailin - Jean Pasdeloup (pasdeloup) - Benjamin Cremer (bcremer) - - Thierry Thuon (lepiaf) - Javier López (loalf) - Reinier Kip - Geoffrey Brier (geoffrey-brier) @@ -572,6 +576,7 @@ Symfony is the result of the work of many people who made the code better - Alex Bogomazov (alebo) - maxime.steinhausser - Stefan Warman + - Thomas Perez (scullwm) - Tristan Maindron (tmaindron) - Wesley Lancel - Ke WANG (yktd26) @@ -580,7 +585,6 @@ Symfony is the result of the work of many people who made the code better - Sergey Kolodyazhnyy (skolodyazhnyy) - umpirski - Denis Brumann (dbrumann) - - Michael Babker (mbabker) - Quentin de Longraye (quentinus95) - Chris Heng (gigablah) - Richard Bradley @@ -590,7 +594,6 @@ Symfony is the result of the work of many people who made the code better - Michael Devery (mickadoo) - Antoine Corcy - Artur Eshenbrener - - Arturs Vonda - Sascha Grossenbacher - Szijarto Tamas - Catalin Dan @@ -620,7 +623,6 @@ Symfony is the result of the work of many people who made the code better - develop - ReenExe - Mark Sonnabaum - - Maxime Veber (nek-) - Richard Quadling - jochenvdv - Arturas Smorgun (asarturas) @@ -669,7 +671,6 @@ Symfony is the result of the work of many people who made the code better - Christian Soronellas (theunic) - Yosmany Garcia (yosmanyga) - Wouter de Wild - - Miroslav Sustek - Degory Valentine - Benoit Lévêque (benoit_leveque) - Jeroen Fiege (fieg) @@ -693,6 +694,7 @@ Symfony is the result of the work of many people who made the code better - Jan Prieser - Adrien Lucas (adrienlucas) - Zhuravlev Alexander (scif) + - Yanick Witschi (toflar) - James Michael DuPont - Tom Klingenberg - Christopher Hall (mythmakr) @@ -834,7 +836,6 @@ Symfony is the result of the work of many people who made the code better - Danilo Silva - Zachary Tong (polyfractal) - Hryhorii Hrebiniuk - - Thomas Perez (scullwm) - Dennis Fridrich (dfridrich) - hamza - dantleech @@ -863,6 +864,7 @@ Symfony is the result of the work of many people who made the code better - Goran Juric - Laurent Ghirardotti (laurentg) - Nicolas Macherey + - AKeeman (akeeman) - Lin Clark - Jeremy David (jeremy.david) - Robin Lehrmann (robinlehrmann) @@ -1104,6 +1106,7 @@ Symfony is the result of the work of many people who made the code better - Max Romanovsky (maxromanovsky) - Mathieu Morlon - Daniel Tschinder + - Alexander Schranz - Rafał Muszyński (rafmus90) - Timothy Anido (xanido) - Rick Prent @@ -1411,6 +1414,7 @@ Symfony is the result of the work of many people who made the code better - Rosio (ben-rosio) - Simon Paarlberg (blamh) - Jeroen Thora (bolle) + - Brieuc THOMAS (brieucthomas) - Masao Maeda (brtriver) - Darius Leskauskas (darles) - David Joos (djoos) @@ -1440,7 +1444,6 @@ Symfony is the result of the work of many people who made the code better - Cyrille Jouineau (tuxosaurus) - Yorkie Chadwick (yorkie76) - GuillaumeVerdon - - Yanick Witschi - Ondrej Mirtes - akimsko - Youpie From f01f3d328a3801288821b9c75f143bdc534ccf1b Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Mon, 17 Jul 2017 19:33:19 +0200 Subject: [PATCH 0447/1099] updated VERSION for 2.7.32 --- 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 00d9c8236590a..44b7ef2bca903 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -58,12 +58,12 @@ abstract class Kernel implements KernelInterface, TerminableInterface protected $startTime; protected $loadClassCache; - const VERSION = '2.7.32-DEV'; + const VERSION = '2.7.32'; const VERSION_ID = 20732; const MAJOR_VERSION = 2; const MINOR_VERSION = 7; const RELEASE_VERSION = 32; - const EXTRA_VERSION = 'DEV'; + const EXTRA_VERSION = ''; const END_OF_MAINTENANCE = '05/2018'; const END_OF_LIFE = '05/2019'; From 3d4e143619791e41ac58691569880ac19a496ae8 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Mon, 17 Jul 2017 19:58:04 +0200 Subject: [PATCH 0448/1099] bumped Symfony version to 2.7.33 --- 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 44b7ef2bca903..6221e163755f1 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -58,12 +58,12 @@ abstract class Kernel implements KernelInterface, TerminableInterface protected $startTime; protected $loadClassCache; - const VERSION = '2.7.32'; - const VERSION_ID = 20732; + const VERSION = '2.7.33-DEV'; + const VERSION_ID = 20733; const MAJOR_VERSION = 2; const MINOR_VERSION = 7; - const RELEASE_VERSION = 32; - const EXTRA_VERSION = ''; + const RELEASE_VERSION = 33; + const EXTRA_VERSION = 'DEV'; const END_OF_MAINTENANCE = '05/2018'; const END_OF_LIFE = '05/2019'; From d3098b22ab724799a0179c9dee48fc5a8cf6f318 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Mon, 17 Jul 2017 19:59:59 +0200 Subject: [PATCH 0449/1099] updated CHANGELOG for 2.8.25 --- CHANGELOG-2.8.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/CHANGELOG-2.8.md b/CHANGELOG-2.8.md index 661863ef7ce54..a73a824d4cf45 100644 --- a/CHANGELOG-2.8.md +++ b/CHANGELOG-2.8.md @@ -7,6 +7,19 @@ in 2.8 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/v2.8.0...v2.8.1 +* 2.8.25 (2017-07-17) + + * security #23507 [Security] validate empty passwords again (xabbuh) + * bug #23526 [HttpFoundation] Set meta refresh time to 0 in RedirectResponse content (jnvsor) + * bug #23540 Disable inlining deprecated services (alekitto) + * bug #23468 [DI] Handle root namespace in service definitions (ro0NL) + * bug #23256 [Security] Fix authentication.failure event not dispatched on AccountStatusException (chalasr) + * bug #23461 Use rawurlencode() to transform the Cookie into a string (javiereguiluz) + * bug #23459 [TwigBundle] allow to configure custom formats in XML configs (xabbuh) + * bug #23460 Don't display the Symfony debug toolbar when printing the page (javiereguiluz) + * bug #23261 Fixed absolute url generation for query strings and hash urls (alexander-schranz) + * bug #23398 [Filesystem] Dont copy perms when origin is remote (nicolas-grekas) + * 2.8.24 (2017-07-05) * bug #23378 [FrameworkBundle] Do not remove files from assets dir (1ed) From 5836f0ea646c9edc6fb63e48575d853d19ea75e7 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Mon, 17 Jul 2017 20:00:03 +0200 Subject: [PATCH 0450/1099] updated VERSION for 2.8.25 --- 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 150fc17cf1987..a94e866c36fbb 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -59,12 +59,12 @@ abstract class Kernel implements KernelInterface, TerminableInterface protected $startTime; protected $loadClassCache; - const VERSION = '2.8.25-DEV'; + const VERSION = '2.8.25'; const VERSION_ID = 20825; const MAJOR_VERSION = 2; const MINOR_VERSION = 8; const RELEASE_VERSION = 25; - const EXTRA_VERSION = 'DEV'; + const EXTRA_VERSION = ''; const END_OF_MAINTENANCE = '11/2018'; const END_OF_LIFE = '11/2019'; From 53b8579bec8894dfb9fb8b3d91591f7d8eaeaedb Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Mon, 17 Jul 2017 20:14:06 +0200 Subject: [PATCH 0451/1099] bumped Symfony version to 2.8.26 --- 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 a94e866c36fbb..69d5dbdceeb39 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -59,12 +59,12 @@ abstract class Kernel implements KernelInterface, TerminableInterface protected $startTime; protected $loadClassCache; - const VERSION = '2.8.25'; - const VERSION_ID = 20825; + const VERSION = '2.8.26-DEV'; + const VERSION_ID = 20826; const MAJOR_VERSION = 2; const MINOR_VERSION = 8; - const RELEASE_VERSION = 25; - const EXTRA_VERSION = ''; + const RELEASE_VERSION = 26; + const EXTRA_VERSION = 'DEV'; const END_OF_MAINTENANCE = '11/2018'; const END_OF_LIFE = '11/2019'; From e81459303bb48ac546c4a6145a608a51720e1e15 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Mon, 17 Jul 2017 20:14:55 +0200 Subject: [PATCH 0452/1099] updated CHANGELOG for 3.2.12 --- CHANGELOG-3.2.md | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/CHANGELOG-3.2.md b/CHANGELOG-3.2.md index de3c3fd9977b5..1a4d44e19981e 100644 --- a/CHANGELOG-3.2.md +++ b/CHANGELOG-3.2.md @@ -7,6 +7,22 @@ in 3.2 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.2.0...v3.2.1 +* 3.2.12 (2017-07-17) + + * bug #23549 [PropertyInfo] conflict for phpdocumentor/reflection-docblock 3.2 (xabbuh) + * security #23507 [Security] validate empty passwords again (xabbuh) + * bug #23526 [HttpFoundation] Set meta refresh time to 0 in RedirectResponse content (jnvsor) + * bug #23540 Disable inlining deprecated services (alekitto) + * bug #23468 [DI] Handle root namespace in service definitions (ro0NL) + * bug #23256 [Security] Fix authentication.failure event not dispatched on AccountStatusException (chalasr) + * bug #23461 Use rawurlencode() to transform the Cookie into a string (javiereguiluz) + * bug #23459 [TwigBundle] allow to configure custom formats in XML configs (xabbuh) + * bug #23460 Don't display the Symfony debug toolbar when printing the page (javiereguiluz) + * bug #23469 [FrameworkBundle] do not wire namespaces for the ArrayAdapter (xabbuh) + * bug #23417 [DI][Security] Prevent unwanted deprecation notices when using Expression Languages (dunglas) + * bug #23261 Fixed absolute url generation for query strings and hash urls (alexander-schranz) + * bug #23398 [Filesystem] Dont copy perms when origin is remote (nicolas-grekas) + * 3.2.11 (2017-07-05) * bug #23390 [Cache] Handle APCu failures gracefully (nicolas-grekas) From 579203a9f05c11119332717ec0b2df9392808859 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Mon, 17 Jul 2017 20:15:00 +0200 Subject: [PATCH 0453/1099] updated VERSION for 3.2.12 --- 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 dd6568b9893b5..d0acb4af856a4 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -58,12 +58,12 @@ abstract class Kernel implements KernelInterface, TerminableInterface protected $startTime; protected $loadClassCache; - const VERSION = '3.2.12-DEV'; + const VERSION = '3.2.12'; const VERSION_ID = 30212; const MAJOR_VERSION = 3; const MINOR_VERSION = 2; const RELEASE_VERSION = 12; - const EXTRA_VERSION = 'DEV'; + const EXTRA_VERSION = ''; const END_OF_MAINTENANCE = '07/2017'; const END_OF_LIFE = '01/2018'; From 95c03f2fb345636eede6d68c81777a20e2e99eda Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Mon, 17 Jul 2017 21:06:44 +0200 Subject: [PATCH 0454/1099] bumped Symfony version to 3.2.13 --- 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 d0acb4af856a4..30d692cbf4e45 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -58,12 +58,12 @@ abstract class Kernel implements KernelInterface, TerminableInterface protected $startTime; protected $loadClassCache; - const VERSION = '3.2.12'; - const VERSION_ID = 30212; + const VERSION = '3.2.13-DEV'; + const VERSION_ID = 30213; const MAJOR_VERSION = 3; const MINOR_VERSION = 2; - const RELEASE_VERSION = 12; - const EXTRA_VERSION = ''; + const RELEASE_VERSION = 13; + const EXTRA_VERSION = 'DEV'; const END_OF_MAINTENANCE = '07/2017'; const END_OF_LIFE = '01/2018'; From 7a608efbed31337bcddb291b0ccbeafd7aa84e1b Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Mon, 17 Jul 2017 21:08:20 +0200 Subject: [PATCH 0455/1099] updated CHANGELOG for 3.3.5 --- CHANGELOG-3.3.md | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/CHANGELOG-3.3.md b/CHANGELOG-3.3.md index b6113a82ad279..01e370cdefd0b 100644 --- a/CHANGELOG-3.3.md +++ b/CHANGELOG-3.3.md @@ -7,6 +7,32 @@ in 3.3 minor versions. To get the diff for a specific change, go to https://github.com/symfony/symfony/commit/XXX where XXX is the change hash To get the diff between two versions, go to https://github.com/symfony/symfony/compare/v3.3.0...v3.3.1 +* 3.3.5 (2017-07-17) + + * bug #23549 [PropertyInfo] conflict for phpdocumentor/reflection-docblock 3.2 (xabbuh) + * bug #23513 [FrameworkBundle] Set default public directory on install assets (yceruto) + * security #23507 [Security] validate empty passwords again (xabbuh) + * bug #23526 [HttpFoundation] Set meta refresh time to 0 in RedirectResponse content (jnvsor) + * bug #23535 Make server:* commands work out of the box with the public/ root dir (fabpot) + * bug #23540 Disable inlining deprecated services (alekitto) + * bug #23498 [Process] Fixed issue between process builder and exec (lyrixx) + * bug #23490 [DependencyInjection] non-conflicting anonymous service ids across files (xabbuh) + * bug #23468 [DI] Handle root namespace in service definitions (ro0NL) + * bug #23477 [Process] Fix parsing args on Windows (nicolas-grekas) + * bug #23256 [Security] Fix authentication.failure event not dispatched on AccountStatusException (chalasr) + * bug #23461 Use rawurlencode() to transform the Cookie into a string (javiereguiluz) + * bug #23465 [HttpKernel][VarDumper] Truncate profiler data & optim perf (nicolas-grekas) + * bug #23457 [FrameworkBundle] check _controller attribute is a string before parsing it (alekitto) + * bug #23459 [TwigBundle] allow to configure custom formats in XML configs (xabbuh) + * bug #23460 Don't display the Symfony debug toolbar when printing the page (javiereguiluz) + * bug #23469 [FrameworkBundle] do not wire namespaces for the ArrayAdapter (xabbuh) + * bug #23434 [DotEnv] Fix variable substitution (brieucthomas) + * bug #23426 Fixed HttpOnly flag when using Cookie::fromString() (Toflar) + * bug #22439 [DX] [TwigBundle] Enhance the new exception page design (sustmi) + * bug #23417 [DI][Security] Prevent unwanted deprecation notices when using Expression Languages (dunglas) + * bug #23261 Fixed absolute url generation for query strings and hash urls (alexander-schranz) + * bug #23398 [Filesystem] Dont copy perms when origin is remote (nicolas-grekas) + * 3.3.4 (2017-07-05) * bug #23413 [VarDumper] Reduce size of serialized Data objects (nicolas-grekas) From d7d9a079175835595b9d1df774169dc9fcb99be1 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Mon, 17 Jul 2017 21:08:23 +0200 Subject: [PATCH 0456/1099] updated VERSION for 3.3.5 --- 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 af60ef900a84b..d73ad52a0e648 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -61,12 +61,12 @@ abstract class Kernel implements KernelInterface, TerminableInterface private $projectDir; - const VERSION = '3.3.5-DEV'; + const VERSION = '3.3.5'; const VERSION_ID = 30305; const MAJOR_VERSION = 3; const MINOR_VERSION = 3; const RELEASE_VERSION = 5; - const EXTRA_VERSION = 'DEV'; + const EXTRA_VERSION = ''; const END_OF_MAINTENANCE = '01/2018'; const END_OF_LIFE = '07/2018'; From 5c2797afd35aaa79ff8e6c8cc4eddd37ccbcb1b5 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Mon, 17 Jul 2017 21:17:46 +0200 Subject: [PATCH 0457/1099] bumped Symfony version to 3.3.6 --- 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 d73ad52a0e648..7517938c1235f 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -61,12 +61,12 @@ abstract class Kernel implements KernelInterface, TerminableInterface private $projectDir; - const VERSION = '3.3.5'; - const VERSION_ID = 30305; + const VERSION = '3.3.6-DEV'; + const VERSION_ID = 30306; const MAJOR_VERSION = 3; const MINOR_VERSION = 3; - const RELEASE_VERSION = 5; - const EXTRA_VERSION = ''; + const RELEASE_VERSION = 6; + const EXTRA_VERSION = 'DEV'; const END_OF_MAINTENANCE = '01/2018'; const END_OF_LIFE = '07/2018'; From 37d8495a59c14edf6aaadb07591eba41624344d3 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Mon, 17 Jul 2017 22:48:54 +0200 Subject: [PATCH 0458/1099] [DI] Minor dumping logic simplification --- src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php index 02c17150b4e34..ade0039a8602c 100644 --- a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php +++ b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php @@ -1608,7 +1608,7 @@ private function getServiceCall($id, Reference $reference = null) $code = sprintf('$this->get(\'%s\')', $id); } - if ($this->container->hasDefinition($id) && (!$this->container->getDefinition($id)->isPublic() || $this->container->getDefinition($id)->isShared())) { + if ($this->container->hasDefinition($id) && $this->container->getDefinition($id)->isShared()) { // The following is PHP 5.5 syntax for what could be written as "(\$this->services['$id'] ?? $code)" on PHP>=7.0 $code = "\${(\$_ = isset(\$this->services['$id']) ? \$this->services['$id'] : $code) && false ?: '_'}"; From 2725fd608047aa28945627bc47920e244e78c125 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Tue, 18 Jul 2017 09:06:47 +0200 Subject: [PATCH 0459/1099] [DI] Mark Container::$privates as internal --- src/Symfony/Component/DependencyInjection/Container.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/DependencyInjection/Container.php b/src/Symfony/Component/DependencyInjection/Container.php index 1ed239b939747..0397649a671cb 100644 --- a/src/Symfony/Component/DependencyInjection/Container.php +++ b/src/Symfony/Component/DependencyInjection/Container.php @@ -56,10 +56,14 @@ class Container implements ResettableContainerInterface protected $services = array(); protected $methodMap = array(); - protected $privates = array(); protected $aliases = array(); protected $loading = array(); + /** + * @internal + */ + protected $privates = array(); + private $underscoreMap = array('_' => '', '.' => '_', '\\' => '_'); private $envCache = array(); From 9922827cc2eb15f41823df30e7fa3b7cf891a512 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Mon, 17 Jul 2017 22:28:29 +0200 Subject: [PATCH 0460/1099] [DI] Resolve aliases earlier --- .../Component/DependencyInjection/Container.php | 14 +++++++------- .../DependencyInjection/Dumper/PhpDumper.php | 8 ++++---- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/Symfony/Component/DependencyInjection/Container.php b/src/Symfony/Component/DependencyInjection/Container.php index 7bf2e36ec2da2..4019504a5a199 100644 --- a/src/Symfony/Component/DependencyInjection/Container.php +++ b/src/Symfony/Component/DependencyInjection/Container.php @@ -249,9 +249,6 @@ public function get($id, $invalidBehavior = self::EXCEPTION_ON_INVALID_REFERENCE // this method can be called thousands of times during a request, avoid // calling strtolower() unless necessary. for ($i = 2;;) { - if ('service_container' === $id) { - return $this; - } if (isset($this->aliases[$id])) { $id = $this->aliases[$id]; } @@ -259,6 +256,9 @@ public function get($id, $invalidBehavior = self::EXCEPTION_ON_INVALID_REFERENCE if (isset($this->services[$id]) || array_key_exists($id, $this->services)) { return $this->services[$id]; } + if ('service_container' === $id) { + return $this; + } if (isset($this->loading[$id])) { throw new ServiceCircularReferenceException($id, array_keys($this->loading)); @@ -328,16 +328,16 @@ public function initialized($id) { $id = strtolower($id); + if (isset($this->aliases[$id])) { + $id = $this->aliases[$id]; + } + if ('service_container' === $id) { // BC: 'service_container' was a synthetic service previously. // @todo Change to false in next major release. return true; } - if (isset($this->aliases[$id])) { - $id = $this->aliases[$id]; - } - return isset($this->services[$id]) || array_key_exists($id, $this->services); } diff --git a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php index 1665f7542b7ce..52f6362c73fb3 100644 --- a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php +++ b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php @@ -1482,6 +1482,10 @@ public function addExpressionLanguageProvider(ExpressionFunctionProviderInterfac */ private function getServiceCall($id, Reference $reference = null) { + while ($this->container->hasAlias($id)) { + $id = (string) $this->container->getAlias($id); + } + if ('service_container' === $id) { return '$this'; } @@ -1490,10 +1494,6 @@ private function getServiceCall($id, Reference $reference = null) return sprintf('$this->get(\'%s\', ContainerInterface::NULL_ON_INVALID_REFERENCE)', $id); } - if ($this->container->hasAlias($id)) { - $id = (string) $this->container->getAlias($id); - } - return sprintf('$this->get(\'%s\')', $id); } From 4917b3071837bfca9b5ce527424f8a8b6abae696 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Tue, 18 Jul 2017 10:09:42 +0200 Subject: [PATCH 0461/1099] fix merge --- .../Component/DependencyInjection/Dumper/PhpDumper.php | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php index 646773693cb8d..1288faa201847 100644 --- a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php +++ b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php @@ -1605,10 +1605,6 @@ private function getServiceCall($id, Reference $reference = null) } elseif (null !== $reference && ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE !== $reference->getInvalidBehavior()) { $code = sprintf('$this->get(\'%s\', ContainerInterface::NULL_ON_INVALID_REFERENCE)', $id); } else { - if ($this->container->hasAlias($id)) { - $id = (string) $this->container->getAlias($id); - } - $code = sprintf('$this->get(\'%s\')', $id); } From c0c1881fe437fc22c1a842bdaad7cb4102b0df31 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Mon, 17 Jul 2017 22:21:41 +0200 Subject: [PATCH 0462/1099] [DI] Optimize use of private and pre-defined services --- .../DependencyInjection/Container.php | 23 -------- .../DependencyInjection/Dumper/PhpDumper.php | 52 +++++-------------- .../Tests/ContainerTest.php | 29 ++--------- .../Tests/Fixtures/php/services1-1.php | 3 +- .../Tests/Fixtures/php/services1.php | 3 +- .../Tests/Fixtures/php/services10.php | 3 +- .../Tests/Fixtures/php/services12.php | 3 +- .../Tests/Fixtures/php/services13.php | 3 +- .../Tests/Fixtures/php/services19.php | 3 +- .../Tests/Fixtures/php/services24.php | 3 +- .../Tests/Fixtures/php/services26.php | 3 +- .../Tests/Fixtures/php/services33.php | 3 +- .../Tests/Fixtures/php/services8.php | 3 +- .../Tests/Fixtures/php/services9_compiled.php | 25 ++++----- .../Fixtures/php/services_array_params.php | 3 +- .../Tests/Fixtures/php/services_locator.php | 27 +++++----- .../Fixtures/php/services_private_frozen.php | 15 +++--- .../Fixtures/php/services_subscriber.php | 19 +++---- 18 files changed, 77 insertions(+), 146 deletions(-) diff --git a/src/Symfony/Component/DependencyInjection/Container.php b/src/Symfony/Component/DependencyInjection/Container.php index db3202c252a8e..def4c4ce15d15 100644 --- a/src/Symfony/Component/DependencyInjection/Container.php +++ b/src/Symfony/Component/DependencyInjection/Container.php @@ -50,11 +50,6 @@ class Container implements ResettableContainerInterface protected $aliases = array(); protected $loading = array(); - /** - * @internal - */ - protected $privates = array(); - private $envCache = array(); private $compiled = false; @@ -155,10 +150,6 @@ public function set($id, $service) throw new InvalidArgumentException('You cannot set service "service_container".'); } - if (isset($this->privates[$id])) { - throw new InvalidArgumentException(sprintf('You cannot set the private service "%s".', $id)); - } - if (isset($this->methodMap[$id])) { throw new InvalidArgumentException(sprintf('You cannot set the pre-defined service "%s".', $id)); } @@ -185,9 +176,6 @@ public function set($id, $service) */ public function has($id) { - if (isset($this->privates[$id])) { - return false; - } if (isset($this->aliases[$id])) { $id = $this->aliases[$id]; } @@ -224,13 +212,6 @@ public function has($id) */ public function get($id, $invalidBehavior = self::EXCEPTION_ON_INVALID_REFERENCE) { - if (isset($this->privates[$id])) { - if (self::EXCEPTION_ON_INVALID_REFERENCE === $invalidBehavior) { - throw new ServiceNotFoundException($id); - } - - return; - } if (isset($this->aliases[$id])) { $id = $this->aliases[$id]; } @@ -293,10 +274,6 @@ public function get($id, $invalidBehavior = self::EXCEPTION_ON_INVALID_REFERENCE */ public function initialized($id) { - if (isset($this->privates[$id])) { - return false; - } - if (isset($this->aliases[$id])) { $id = $this->aliases[$id]; } diff --git a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php index 4c64bbdf8708c..87c0a96922f9c 100644 --- a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php +++ b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php @@ -401,7 +401,7 @@ private function addServiceInstance($id, Definition $definition, $isSimpleInstan $instantiation = ''; if (!$isProxyCandidate && $definition->isShared()) { - $instantiation = "\$this->services['$id'] = ".($isSimpleInstance ? '' : '$instance'); + $instantiation = sprintf('$this->%s[\'%s\'] = %s', $this->container->getDefinition($id)->isPublic() ? 'services' : 'privates', $id, $isSimpleInstance ? '' : '$instance'); } elseif (!$isSimpleInstance) { $instantiation = '$instance'; } @@ -646,7 +646,7 @@ private function addService($id, Definition $definition) // with proxies, for 5.3.3 compatibility, the getter must be public to be accessible to the initializer $isProxyCandidate = $this->getProxyDumper()->isProxyCandidate($definition); - $visibility = $isProxyCandidate ? 'public' : 'protected'; + $visibility = $isProxyCandidate ? 'public' : ($definition->isPublic() ? 'protected' : 'private'); $methodName = $this->generateMethodName($id); $code = <<addMethodMap(); - $code .= $this->addPrivateServices(); $code .= $this->addAliases(); $code .= <<<'EOF' @@ -886,40 +886,12 @@ private function addMethodMap() $code = " \$this->methodMap = array(\n"; ksort($definitions); foreach ($definitions as $id => $definition) { - $code .= ' '.$this->export($id).' => '.$this->export($this->generateMethodName($id)).",\n"; - } - - return $code." );\n"; - } - - /** - * Adds the privates property definition. - * - * @return string - */ - private function addPrivateServices() - { - if (!$definitions = $this->container->getDefinitions()) { - return ''; - } - - $code = ''; - ksort($definitions); - foreach ($definitions as $id => $definition) { - if (!$definition->isPublic()) { - $code .= ' '.$this->export($id)." => true,\n"; + if ($definition->isPublic()) { + $code .= ' '.$this->export($id).' => '.$this->export($this->generateMethodName($id)).",\n"; } } - if (empty($code)) { - return ''; - } - - $out = " \$this->privates = array(\n"; - $out .= $code; - $out .= " );\n"; - - return $out; + return $code." );\n"; } /** @@ -1535,8 +1507,12 @@ private function getServiceCall($id, Reference $reference = null) return '$this'; } - if ($this->container->hasDefinition($id) && !$this->container->getDefinition($id)->isPublic()) { + if ($this->container->hasDefinition($id)) { $code = sprintf('$this->%s()', $this->generateMethodName($id)); + + if ($this->container->getDefinition($id)->isShared()) { + $code = sprintf('($this->%s[\'%s\'] ?? %s)', $this->container->getDefinition($id)->isPublic() ? 'services' : 'privates', $id, $code); + } } elseif (null !== $reference && ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE !== $reference->getInvalidBehavior()) { $code = sprintf('$this->get(\'%s\', ContainerInterface::NULL_ON_INVALID_REFERENCE)', $id); } else { @@ -1547,10 +1523,6 @@ private function getServiceCall($id, Reference $reference = null) $code = sprintf('$this->get(\'%s\')', $id); } - if ($this->container->hasDefinition($id) && $this->container->getDefinition($id)->isShared()) { - $code = "(\$this->services['$id'] ?? $code)"; - } - return $code; } diff --git a/src/Symfony/Component/DependencyInjection/Tests/ContainerTest.php b/src/Symfony/Component/DependencyInjection/Tests/ContainerTest.php index 4a3566b27a119..6e72c6075d9e2 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/ContainerTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/ContainerTest.php @@ -134,7 +134,7 @@ public function testGetServiceIds() $sc = new ProjectServiceContainer(); $sc->set('foo', $obj = new \stdClass()); - $this->assertEquals(array('service_container', 'internal', 'bar', 'foo_bar', 'foo.baz', 'circular', 'throw_exception', 'throws_exception_on_service_configuration', 'internal_dependency', 'foo'), $sc->getServiceIds(), '->getServiceIds() returns defined service ids by factory methods in the method map, followed by service ids defined by set()'); + $this->assertEquals(array('service_container', 'bar', 'foo_bar', 'foo.baz', 'circular', 'throw_exception', 'throws_exception_on_service_configuration', 'internal_dependency', 'foo'), $sc->getServiceIds(), '->getServiceIds() returns defined service ids by factory methods in the method map, followed by service ids defined by set()'); } public function testSet() @@ -340,26 +340,6 @@ public function testThatCloningIsNotSupported() $this->assertTrue($clone->isPrivate()); } - /** - * @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException - * @expectedExceptionMessage You cannot set the private service "internal". - */ - public function testUnsetInternalPrivateService() - { - $c = new ProjectServiceContainer(); - $c->set('internal', null); - } - - /** - * @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException - * @expectedExceptionMessage You cannot set the private service "internal". - */ - public function testChangeInternalPrivateService() - { - $c = new ProjectServiceContainer(); - $c->set('internal', new \stdClass()); - } - public function testCheckExistenceOfAnInternalPrivateService() { $c = new ProjectServiceContainer(); @@ -396,7 +376,6 @@ class ProjectServiceContainer extends Container public $__foo_baz; public $__internal; protected $methodMap = array( - 'internal' => 'getInternalService', 'bar' => 'getBarService', 'foo_bar' => 'getFooBarService', 'foo.baz' => 'getFoo_BazService', @@ -414,13 +393,13 @@ public function __construct() $this->__foo_bar = new \stdClass(); $this->__foo_baz = new \stdClass(); $this->__internal = new \stdClass(); - $this->privates = array('internal' => true); + $this->privates = array(); $this->aliases = array('alias' => 'bar'); } protected function getInternalService() { - return $this->services['internal'] = $this->__internal; + return $this->privates['internal'] = $this->__internal; } protected function getBarService() @@ -459,7 +438,7 @@ protected function getInternalDependencyService() { $this->services['internal_dependency'] = $instance = new \stdClass(); - $instance->internal = isset($this->services['internal']) ? $this->services['internal'] : $this->getInternalService(); + $instance->internal = $this->privates['internal'] ?? $this->getInternalService(); return $instance; } diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services1-1.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services1-1.php index 32f488e8f342b..01f159f842037 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services1-1.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services1-1.php @@ -22,13 +22,14 @@ class Container extends AbstractContainer { private $parameters; private $targetDirs = array(); + private $privates = array(); /** * Constructor. */ public function __construct() { - $this->services = array(); + $this->services = $this->privates = array(); $this->aliases = array(); } diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services1.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services1.php index baa1874a9ab4e..967146d410e62 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services1.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services1.php @@ -20,13 +20,14 @@ class ProjectServiceContainer extends Container { private $parameters; private $targetDirs = array(); + private $privates = array(); /** * Constructor. */ public function __construct() { - $this->services = array(); + $this->services = $this->privates = array(); $this->aliases = array(); } diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services10.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services10.php index 97bdc025c88bd..78ce81547277e 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services10.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services10.php @@ -20,6 +20,7 @@ class ProjectServiceContainer extends Container { private $parameters; private $targetDirs = array(); + private $privates = array(); /** * Constructor. @@ -28,7 +29,7 @@ public function __construct() { $this->parameters = $this->getDefaultParameters(); - $this->services = array(); + $this->services = $this->privates = array(); $this->methodMap = array( 'test' => 'getTestService', ); diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services12.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services12.php index 4961457b29366..db9faadd187c6 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services12.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services12.php @@ -20,6 +20,7 @@ class ProjectServiceContainer extends Container { private $parameters; private $targetDirs = array(); + private $privates = array(); /** * Constructor. @@ -32,7 +33,7 @@ public function __construct() } $this->parameters = $this->getDefaultParameters(); - $this->services = array(); + $this->services = $this->privates = array(); $this->methodMap = array( 'test' => 'getTestService', ); diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services13.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services13.php index da30f18e5fe82..35a68aa9b3f2f 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services13.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services13.php @@ -20,13 +20,14 @@ class ProjectServiceContainer extends Container { private $parameters; private $targetDirs = array(); + private $privates = array(); /** * Constructor. */ public function __construct() { - $this->services = array(); + $this->services = $this->privates = array(); $this->methodMap = array( 'bar' => 'getBarService', ); diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services19.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services19.php index 81ab4a6ca6bf9..6e384da3b9d7a 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services19.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services19.php @@ -20,13 +20,14 @@ class ProjectServiceContainer extends Container { private $parameters; private $targetDirs = array(); + private $privates = array(); /** * Constructor. */ public function __construct() { - $this->services = array(); + $this->services = $this->privates = array(); $this->methodMap = array( 'service_from_anonymous_factory' => 'getServiceFromAnonymousFactoryService', 'service_with_method_call_and_factory' => 'getServiceWithMethodCallAndFactoryService', diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services24.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services24.php index f64c99f5d081d..382613ccf4691 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services24.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services24.php @@ -20,13 +20,14 @@ class ProjectServiceContainer extends Container { private $parameters; private $targetDirs = array(); + private $privates = array(); /** * Constructor. */ public function __construct() { - $this->services = array(); + $this->services = $this->privates = array(); $this->methodMap = array( 'foo' => 'getFooService', ); diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services26.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services26.php index 54166bb0163af..0fc608186a4d6 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services26.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services26.php @@ -20,6 +20,7 @@ class ProjectServiceContainer extends Container { private $parameters; private $targetDirs = array(); + private $privates = array(); /** * Constructor. @@ -28,7 +29,7 @@ public function __construct() { $this->parameters = $this->getDefaultParameters(); - $this->services = array(); + $this->services = $this->privates = array(); $this->methodMap = array( 'test' => 'getTestService', ); diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services33.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services33.php index 3c3ac43244249..548ce20c8bc5d 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services33.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services33.php @@ -20,13 +20,14 @@ class ProjectServiceContainer extends Container { private $parameters; private $targetDirs = array(); + private $privates = array(); /** * Constructor. */ public function __construct() { - $this->services = array(); + $this->services = $this->privates = array(); $this->methodMap = array( 'Symfony\\Component\\DependencyInjection\\Tests\\Fixtures\\Container33\\Foo' => 'getSymfony_Component_DependencyInjection_Tests_Fixtures_Container33_FooService', ); diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services8.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services8.php index b9721035df5a7..17bbbfae714d4 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services8.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services8.php @@ -20,6 +20,7 @@ class ProjectServiceContainer extends Container { private $parameters; private $targetDirs = array(); + private $privates = array(); /** * Constructor. @@ -28,7 +29,7 @@ public function __construct() { $this->parameters = $this->getDefaultParameters(); - $this->services = array(); + $this->services = $this->privates = array(); $this->aliases = array(); } diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_compiled.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_compiled.php index 8fb33d8cbd44c..3d47bac17eb80 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_compiled.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_compiled.php @@ -20,6 +20,7 @@ class ProjectServiceContainer extends Container { private $parameters; private $targetDirs = array(); + private $privates = array(); /** * Constructor. @@ -28,7 +29,7 @@ public function __construct() { $this->parameters = $this->getDefaultParameters(); - $this->services = array(); + $this->services = $this->privates = array(); $this->methodMap = array( 'BAR' => 'getBARService', 'BAR2' => 'getBAR2Service', @@ -87,7 +88,7 @@ protected function getBARService() { $this->services['BAR'] = $instance = new \stdClass(); - $instance->bar = ($this->services['bar'] ?? $this->get('bar')); + $instance->bar = ($this->services['bar'] ?? $this->getBar3Service()); return $instance; } @@ -115,7 +116,7 @@ protected function getBAR2Service() */ protected function getBar3Service() { - $a = ($this->services['foo.baz'] ?? $this->get('foo.baz')); + $a = ($this->services['foo.baz'] ?? $this->getFoo_BazService()); $this->services['bar'] = $instance = new \Bar\FooClass('foo', $a, $this->getParameter('foo_bar')); @@ -149,7 +150,7 @@ protected function getBazService() { $this->services['baz'] = $instance = new \Baz(); - $instance->setFoo(($this->services['foo_with_inline'] ?? $this->get('foo_with_inline'))); + $instance->setFoo(($this->services['foo_with_inline'] ?? $this->getFooWithInlineService())); return $instance; } @@ -165,7 +166,7 @@ protected function getBazService() protected function getConfiguredServiceService() { $a = new \ConfClass(); - $a->setFoo(($this->services['baz'] ?? $this->get('baz'))); + $a->setFoo(($this->services['baz'] ?? $this->getBazService())); $this->services['configured_service'] = $instance = new \stdClass(); @@ -244,7 +245,7 @@ protected function getDeprecatedServiceService() */ protected function getFactoryServiceService() { - return $this->services['factory_service'] = ($this->services['foo.baz'] ?? $this->get('foo.baz'))->getInstance(); + return $this->services['factory_service'] = ($this->services['foo.baz'] ?? $this->getFoo_BazService())->getInstance(); } /** @@ -270,14 +271,14 @@ protected function getFactoryServiceSimpleService() */ protected function getFooService() { - $a = ($this->services['foo.baz'] ?? $this->get('foo.baz')); + $a = ($this->services['foo.baz'] ?? $this->getFoo_BazService()); $this->services['foo'] = $instance = \Bar\FooClass::getInstance('foo', $a, array('bar' => 'foo is bar', 'foobar' => 'bar'), true, $this); $instance->foo = 'bar'; $instance->moo = $a; $instance->qux = array('bar' => 'foo is bar', 'foobar' => 'bar'); - $instance->setBar(($this->services['bar'] ?? $this->get('bar'))); + $instance->setBar(($this->services['bar'] ?? $this->getBar3Service())); $instance->initialize(); sc_configure($instance); @@ -326,7 +327,7 @@ protected function getFooWithInlineService() $this->services['foo_with_inline'] = $instance = new \Foo(); $a->pub = 'pub'; - $a->setBaz(($this->services['baz'] ?? $this->get('baz'))); + $a->setBaz(($this->services['baz'] ?? $this->getBazService())); $instance->setBar($a); @@ -344,7 +345,7 @@ protected function getFooWithInlineService() protected function getLazyContextService() { return $this->services['lazy_context'] = new \LazyContext(new RewindableGenerator(function () { - yield 'k1' => ($this->services['foo.baz'] ?? $this->get('foo.baz')); + yield 'k1' => ($this->services['foo.baz'] ?? $this->getFoo_BazService()); yield 'k2' => $this; }, 2), new RewindableGenerator(function () { return new \EmptyIterator(); @@ -362,7 +363,7 @@ protected function getLazyContextService() protected function getLazyContextIgnoreInvalidRefService() { return $this->services['lazy_context_ignore_invalid_ref'] = new \LazyContext(new RewindableGenerator(function () { - yield 0 => ($this->services['foo.baz'] ?? $this->get('foo.baz')); + yield 0 => ($this->services['foo.baz'] ?? $this->getFoo_BazService()); }, 1), new RewindableGenerator(function () { return new \EmptyIterator(); }, 0)); @@ -382,7 +383,7 @@ protected function getMethodCall1Service() $this->services['method_call1'] = $instance = new \Bar\FooClass(); - $instance->setBar(($this->services['foo'] ?? $this->get('foo'))); + $instance->setBar(($this->services['foo'] ?? $this->getFooService())); $instance->setBar(NULL); $instance->setBar(($this->get("foo")->foo() . (($this->hasParameter("foo")) ? ($this->getParameter("foo")) : ("default")))); diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_array_params.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_array_params.php index 9c1643fa6f4f5..d5f4f2ae9d886 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_array_params.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_array_params.php @@ -20,6 +20,7 @@ class ProjectServiceContainer extends Container { private $parameters; private $targetDirs = array(); + private $privates = array(); /** * Constructor. @@ -32,7 +33,7 @@ public function __construct() } $this->parameters = $this->getDefaultParameters(); - $this->services = array(); + $this->services = $this->privates = array(); $this->methodMap = array( 'bar' => 'getBarService', ); diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_locator.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_locator.php index 98305c1a1df6d..a413e1cfdc639 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_locator.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_locator.php @@ -20,16 +20,16 @@ class ProjectServiceContainer extends Container { private $parameters; private $targetDirs = array(); + private $privates = array(); /** * Constructor. */ public function __construct() { - $this->services = array(); + $this->services = $this->privates = array(); $this->methodMap = array( 'bar_service' => 'getBarServiceService', - 'baz_service' => 'getBazServiceService', 'foo_service' => 'getFooServiceService', 'translator.loader_1' => 'getTranslator_Loader1Service', 'translator.loader_2' => 'getTranslator_Loader2Service', @@ -38,9 +38,6 @@ public function __construct() 'translator_2' => 'getTranslator2Service', 'translator_3' => 'getTranslator3Service', ); - $this->privates = array( - 'baz_service' => true, - ); $this->aliases = array(); } @@ -71,7 +68,7 @@ public function isCompiled() */ protected function getBarServiceService() { - return $this->services['bar_service'] = new \stdClass(($this->services['baz_service'] ?? $this->getBazServiceService())); + return $this->services['bar_service'] = new \stdClass(($this->privates['baz_service'] ?? $this->getBazServiceService())); } /** @@ -85,9 +82,9 @@ protected function getBarServiceService() protected function getFooServiceService() { return $this->services['foo_service'] = new \Symfony\Component\DependencyInjection\ServiceLocator(array('bar' => function () { - return ($this->services['bar_service'] ?? $this->get('bar_service')); + return ($this->services['bar_service'] ?? $this->getBarServiceService()); }, 'baz' => function (): \stdClass { - return ($this->services['baz_service'] ?? $this->getBazServiceService()); + return ($this->privates['baz_service'] ?? $this->getBazServiceService()); }, 'nil' => function () { return NULL; })); @@ -143,7 +140,7 @@ protected function getTranslator_Loader3Service() protected function getTranslator1Service() { return $this->services['translator_1'] = new \Symfony\Component\DependencyInjection\Tests\Fixtures\StubbedTranslator(new \Symfony\Component\DependencyInjection\ServiceLocator(array('translator.loader_1' => function () { - return ($this->services['translator.loader_1'] ?? $this->get('translator.loader_1')); + return ($this->services['translator.loader_1'] ?? $this->getTranslator_Loader1Service()); }))); } @@ -158,10 +155,10 @@ protected function getTranslator1Service() protected function getTranslator2Service() { $this->services['translator_2'] = $instance = new \Symfony\Component\DependencyInjection\Tests\Fixtures\StubbedTranslator(new \Symfony\Component\DependencyInjection\ServiceLocator(array('translator.loader_2' => function () { - return ($this->services['translator.loader_2'] ?? $this->get('translator.loader_2')); + return ($this->services['translator.loader_2'] ?? $this->getTranslator_Loader2Service()); }))); - $instance->addResource('db', ($this->services['translator.loader_2'] ?? $this->get('translator.loader_2')), 'nl'); + $instance->addResource('db', ($this->services['translator.loader_2'] ?? $this->getTranslator_Loader2Service()), 'nl'); return $instance; } @@ -176,10 +173,10 @@ protected function getTranslator2Service() */ protected function getTranslator3Service() { - $a = ($this->services['translator.loader_3'] ?? $this->get('translator.loader_3')); + $a = ($this->services['translator.loader_3'] ?? $this->getTranslator_Loader3Service()); $this->services['translator_3'] = $instance = new \Symfony\Component\DependencyInjection\Tests\Fixtures\StubbedTranslator(new \Symfony\Component\DependencyInjection\ServiceLocator(array('translator.loader_3' => function () { - return ($this->services['translator.loader_3'] ?? $this->get('translator.loader_3')); + return ($this->services['translator.loader_3'] ?? $this->getTranslator_Loader3Service()); }))); $instance->addResource('db', $a, 'nl'); @@ -200,8 +197,8 @@ protected function getTranslator3Service() * * @return \stdClass A stdClass instance */ - protected function getBazServiceService() + private function getBazServiceService() { - return $this->services['baz_service'] = new \stdClass(); + return $this->privates['baz_service'] = new \stdClass(); } } diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_private_frozen.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_private_frozen.php index 1df28c328a58a..7bd14e1608e27 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_private_frozen.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_private_frozen.php @@ -20,21 +20,18 @@ class ProjectServiceContainer extends Container { private $parameters; private $targetDirs = array(); + private $privates = array(); /** * Constructor. */ public function __construct() { - $this->services = array(); + $this->services = $this->privates = array(); $this->methodMap = array( 'bar_service' => 'getBarServiceService', - 'baz_service' => 'getBazServiceService', 'foo_service' => 'getFooServiceService', ); - $this->privates = array( - 'baz_service' => true, - ); $this->aliases = array(); } @@ -65,7 +62,7 @@ public function isCompiled() */ protected function getBarServiceService() { - return $this->services['bar_service'] = new \stdClass(($this->services['baz_service'] ?? $this->getBazServiceService())); + return $this->services['bar_service'] = new \stdClass(($this->privates['baz_service'] ?? $this->getBazServiceService())); } /** @@ -78,7 +75,7 @@ protected function getBarServiceService() */ protected function getFooServiceService() { - return $this->services['foo_service'] = new \stdClass(($this->services['baz_service'] ?? $this->getBazServiceService())); + return $this->services['foo_service'] = new \stdClass(($this->privates['baz_service'] ?? $this->getBazServiceService())); } /** @@ -93,8 +90,8 @@ protected function getFooServiceService() * * @return \stdClass A stdClass instance */ - protected function getBazServiceService() + private function getBazServiceService() { - return $this->services['baz_service'] = new \stdClass(); + return $this->privates['baz_service'] = new \stdClass(); } } diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_subscriber.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_subscriber.php index 1d852fab35a58..aaaeaa45f6c09 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_subscriber.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_subscriber.php @@ -20,21 +20,18 @@ class ProjectServiceContainer extends Container { private $parameters; private $targetDirs = array(); + private $privates = array(); /** * Constructor. */ public function __construct() { - $this->services = array(); + $this->services = $this->privates = array(); $this->methodMap = array( 'Symfony\\Component\\DependencyInjection\\Tests\\Fixtures\\TestServiceSubscriber' => 'getSymfony_Component_DependencyInjection_Tests_Fixtures_TestServiceSubscriberService', - 'autowired.Symfony\\Component\\DependencyInjection\\Tests\\Fixtures\\CustomDefinition' => 'getAutowired_Symfony_Component_DependencyInjection_Tests_Fixtures_CustomDefinitionService', 'foo_service' => 'getFooServiceService', ); - $this->privates = array( - 'autowired.Symfony\\Component\\DependencyInjection\\Tests\\Fixtures\\CustomDefinition' => true, - ); $this->aliases = array(); } @@ -81,13 +78,13 @@ protected function getSymfony_Component_DependencyInjection_Tests_Fixtures_TestS protected function getFooServiceService() { return $this->services['foo_service'] = new \Symfony\Component\DependencyInjection\Tests\Fixtures\TestServiceSubscriber(new \Symfony\Component\DependencyInjection\ServiceLocator(array('Symfony\\Component\\DependencyInjection\\Tests\\Fixtures\\CustomDefinition' => function (): \Symfony\Component\DependencyInjection\Tests\Fixtures\CustomDefinition { - return ($this->services['autowired.Symfony\Component\DependencyInjection\Tests\Fixtures\CustomDefinition'] ?? $this->getAutowired_Symfony_Component_DependencyInjection_Tests_Fixtures_CustomDefinitionService()); + return ($this->privates['autowired.Symfony\Component\DependencyInjection\Tests\Fixtures\CustomDefinition'] ?? $this->getAutowired_Symfony_Component_DependencyInjection_Tests_Fixtures_CustomDefinitionService()); }, 'Symfony\\Component\\DependencyInjection\\Tests\\Fixtures\\TestServiceSubscriber' => function (): \Symfony\Component\DependencyInjection\Tests\Fixtures\TestServiceSubscriber { - return ($this->services['Symfony\Component\DependencyInjection\Tests\Fixtures\TestServiceSubscriber'] ?? $this->get('Symfony\Component\DependencyInjection\Tests\Fixtures\TestServiceSubscriber')); + return ($this->services['Symfony\Component\DependencyInjection\Tests\Fixtures\TestServiceSubscriber'] ?? $this->getSymfony_Component_DependencyInjection_Tests_Fixtures_TestServiceSubscriberService()); }, 'bar' => function (): \Symfony\Component\DependencyInjection\Tests\Fixtures\CustomDefinition { - return ($this->services['Symfony\Component\DependencyInjection\Tests\Fixtures\TestServiceSubscriber'] ?? $this->get('Symfony\Component\DependencyInjection\Tests\Fixtures\TestServiceSubscriber')); + return ($this->services['Symfony\Component\DependencyInjection\Tests\Fixtures\TestServiceSubscriber'] ?? $this->getSymfony_Component_DependencyInjection_Tests_Fixtures_TestServiceSubscriberService()); }, 'baz' => function (): \Symfony\Component\DependencyInjection\Tests\Fixtures\CustomDefinition { - return ($this->services['autowired.Symfony\Component\DependencyInjection\Tests\Fixtures\CustomDefinition'] ?? $this->getAutowired_Symfony_Component_DependencyInjection_Tests_Fixtures_CustomDefinitionService()); + return ($this->privates['autowired.Symfony\Component\DependencyInjection\Tests\Fixtures\CustomDefinition'] ?? $this->getAutowired_Symfony_Component_DependencyInjection_Tests_Fixtures_CustomDefinitionService()); }))); } @@ -105,8 +102,8 @@ protected function getFooServiceService() * * @return \Symfony\Component\DependencyInjection\Tests\Fixtures\CustomDefinition A Symfony\Component\DependencyInjection\Tests\Fixtures\CustomDefinition instance */ - protected function getAutowired_Symfony_Component_DependencyInjection_Tests_Fixtures_CustomDefinitionService() + private function getAutowired_Symfony_Component_DependencyInjection_Tests_Fixtures_CustomDefinitionService() { - return $this->services['autowired.Symfony\Component\DependencyInjection\Tests\Fixtures\CustomDefinition'] = new \Symfony\Component\DependencyInjection\Tests\Fixtures\CustomDefinition(); + return $this->privates['autowired.Symfony\Component\DependencyInjection\Tests\Fixtures\CustomDefinition'] = new \Symfony\Component\DependencyInjection\Tests\Fixtures\CustomDefinition(); } } From 62410b6b7e09fcaead3a12a3e9a9beac4b840960 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Tue, 18 Jul 2017 11:04:59 +0200 Subject: [PATCH 0463/1099] [TwigBridge] fix tests --- .../Bridge/Twig/Tests/Node/FormThemeTest.php | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Bridge/Twig/Tests/Node/FormThemeTest.php b/src/Symfony/Bridge/Twig/Tests/Node/FormThemeTest.php index 7c3fc9a6a0479..05d6507fd7438 100644 --- a/src/Symfony/Bridge/Twig/Tests/Node/FormThemeTest.php +++ b/src/Symfony/Bridge/Twig/Tests/Node/FormThemeTest.php @@ -13,6 +13,9 @@ use PHPUnit\Framework\TestCase; use Symfony\Bridge\Twig\Node\FormThemeNode; +use Symfony\Bridge\Twig\Tests\Extension\RuntimeLoaderProvider; +use Symfony\Component\Form\FormRenderer; +use Symfony\Component\Form\FormRendererEngineInterface; use Twig\Compiler; use Twig\Environment; use Twig\Node\Expression\ArrayExpression; @@ -22,6 +25,8 @@ class FormThemeTest extends TestCase { + use RuntimeLoaderProvider; + public function testConstructor() { $form = new NameExpression('form', 0); @@ -48,11 +53,14 @@ public function testCompile() $node = new FormThemeNode($form, $resources, 0); - $compiler = new Compiler(new Environment($this->getMockBuilder('Twig\Loader\LoaderInterface')->getMock())); + $environment = new Environment($this->getMockBuilder('Twig\Loader\LoaderInterface')->getMock()); + $formRenderer = new FormRenderer($this->getMockBuilder(FormRendererEngineInterface::class)->getMock()); + $this->registerTwigRuntimeLoader($environment, $formRenderer); + $compiler = new Compiler($environment); $this->assertEquals( sprintf( - '$this->env->getRuntime(\'Symfony\Component\Form\FormRenderer\')->setTheme(%s, array(0 => "tpl1", 1 => "tpl2"));', + '$this->env->getRuntime("Symfony\\\\Component\\\\Form\\\\FormRenderer")->setTheme(%s, array(0 => "tpl1", 1 => "tpl2"));', $this->getVariableGetter('form') ), trim($compiler->compile($node)->getSource()) @@ -64,7 +72,7 @@ public function testCompile() $this->assertEquals( sprintf( - '$this->env->getRuntime(\'Symfony\Component\Form\FormRenderer\')->setTheme(%s, "tpl1");', + '$this->env->getRuntime("Symfony\\\\Component\\\\Form\\\\FormRenderer")->setTheme(%s, "tpl1");', $this->getVariableGetter('form') ), trim($compiler->compile($node)->getSource()) From aae494cac63ebbae42127b56cf162330ca25175b Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Fri, 19 May 2017 19:32:02 +0200 Subject: [PATCH 0464/1099] [TwigBridge] remove deprecated features --- .../Bridge/Twig/Extension/FormExtension.php | 91 +------------------ .../Bridge/Twig/Extension/YamlExtension.php | 10 +- src/Symfony/Bridge/Twig/Form/TwigRenderer.php | 49 ---------- .../Bridge/Twig/Form/TwigRendererEngine.php | 22 +---- .../Twig/Form/TwigRendererEngineInterface.php | 28 ------ .../Twig/Form/TwigRendererInterface.php | 28 ------ .../Bridge/Twig/Node/FormThemeNode.php | 11 +-- 7 files changed, 5 insertions(+), 234 deletions(-) delete mode 100644 src/Symfony/Bridge/Twig/Form/TwigRenderer.php delete mode 100644 src/Symfony/Bridge/Twig/Form/TwigRendererEngineInterface.php delete mode 100644 src/Symfony/Bridge/Twig/Form/TwigRendererInterface.php diff --git a/src/Symfony/Bridge/Twig/Extension/FormExtension.php b/src/Symfony/Bridge/Twig/Extension/FormExtension.php index 945cd0bc37b1a..4ca968bca9a8c 100644 --- a/src/Symfony/Bridge/Twig/Extension/FormExtension.php +++ b/src/Symfony/Bridge/Twig/Extension/FormExtension.php @@ -12,12 +12,8 @@ namespace Symfony\Bridge\Twig\Extension; use Symfony\Bridge\Twig\TokenParser\FormThemeTokenParser; -use Symfony\Bridge\Twig\Form\TwigRendererInterface; -use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\Form\ChoiceList\View\ChoiceView; -use Twig\Environment; use Twig\Extension\AbstractExtension; -use Twig\Extension\InitRuntimeInterface; use Twig\TwigFilter; use Twig\TwigFunction; use Twig\TwigTest; @@ -28,37 +24,8 @@ * @author Fabien Potencier * @author Bernhard Schussek */ -class FormExtension extends AbstractExtension implements InitRuntimeInterface +class FormExtension extends AbstractExtension { - /** - * @deprecated since version 3.2, to be removed in 4.0 alongside with magic methods below - */ - private $renderer; - - public function __construct($renderer = null) - { - if ($renderer instanceof TwigRendererInterface) { - @trigger_error(sprintf('Passing a Twig Form Renderer to the "%s" constructor is deprecated since version 3.2 and won\'t be possible in 4.0. Pass the Twig\Environment to the TwigRendererEngine constructor instead.', static::class), E_USER_DEPRECATED); - } elseif (null !== $renderer && !(is_array($renderer) && isset($renderer[0], $renderer[1]) && $renderer[0] instanceof ContainerInterface)) { - throw new \InvalidArgumentException(sprintf('Passing any arguments the constructor of %s is reserved for internal use.', __CLASS__)); - } - $this->renderer = $renderer; - } - - /** - * {@inheritdoc} - * - * To be removed in 4.0 - */ - public function initRuntime(Environment $environment) - { - if ($this->renderer instanceof TwigRendererInterface) { - $this->renderer->setEnvironment($environment); - } elseif (null !== $this->renderer) { - $this->renderer[2] = $environment; - } - } - /** * {@inheritdoc} */ @@ -108,62 +75,6 @@ public function getTests() ); } - /** - * @internal - */ - public function __get($name) - { - if ('renderer' === $name) { - @trigger_error(sprintf('Using the "%s::$renderer" property is deprecated since version 3.2 as it will be removed in 4.0.', __CLASS__), E_USER_DEPRECATED); - - if (is_array($this->renderer)) { - $renderer = $this->renderer[0]->get($this->renderer[1]); - if (isset($this->renderer[2])) { - $renderer->setEnvironment($this->renderer[2]); - } - $this->renderer = $renderer; - } - } - - return $this->$name; - } - - /** - * @internal - */ - public function __set($name, $value) - { - if ('renderer' === $name) { - @trigger_error(sprintf('Using the "%s::$renderer" property is deprecated since version 3.2 as it will be removed in 4.0.', __CLASS__), E_USER_DEPRECATED); - } - - $this->$name = $value; - } - - /** - * @internal - */ - public function __isset($name) - { - if ('renderer' === $name) { - @trigger_error(sprintf('Using the "%s::$renderer" property is deprecated since version 3.2 as it will be removed in 4.0.', __CLASS__), E_USER_DEPRECATED); - } - - return isset($this->$name); - } - - /** - * @internal - */ - public function __unset($name) - { - if ('renderer' === $name) { - @trigger_error(sprintf('Using the "%s::$renderer" property is deprecated since version 3.2 as it will be removed in 4.0.', __CLASS__), E_USER_DEPRECATED); - } - - unset($this->$name); - } - /** * {@inheritdoc} */ diff --git a/src/Symfony/Bridge/Twig/Extension/YamlExtension.php b/src/Symfony/Bridge/Twig/Extension/YamlExtension.php index 79418fb8ff9f1..81f1d32446ab1 100644 --- a/src/Symfony/Bridge/Twig/Extension/YamlExtension.php +++ b/src/Symfony/Bridge/Twig/Extension/YamlExtension.php @@ -43,15 +43,7 @@ public function encode($input, $inline = 0, $dumpObjects = 0) } if (defined('Symfony\Component\Yaml\Yaml::DUMP_OBJECT')) { - if (is_bool($dumpObjects)) { - @trigger_error('Passing a boolean flag to toggle object support is deprecated since version 3.1 and will be removed in 4.0. Use the Yaml::DUMP_OBJECT flag instead.', E_USER_DEPRECATED); - - $flags = $dumpObjects ? Yaml::DUMP_OBJECT : 0; - } else { - $flags = $dumpObjects; - } - - return $dumper->dump($input, $inline, 0, $flags); + return $dumper->dump($input, $inline, 0, $dumpObjects); } return $dumper->dump($input, $inline, 0, false, $dumpObjects); diff --git a/src/Symfony/Bridge/Twig/Form/TwigRenderer.php b/src/Symfony/Bridge/Twig/Form/TwigRenderer.php deleted file mode 100644 index 696738b5a70b7..0000000000000 --- a/src/Symfony/Bridge/Twig/Form/TwigRenderer.php +++ /dev/null @@ -1,49 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bridge\Twig\Form; - -@trigger_error(sprintf('The %s class is deprecated since version 3.4 and will be removed in 4.0. Use %s instead.', TwigRenderer::class, FormRenderer::class), E_USER_DEPRECATED); - -use Symfony\Component\Form\FormRenderer; -use Symfony\Component\Security\Csrf\CsrfTokenManagerInterface; -use Twig\Environment; - -/** - * @author Bernhard Schussek - * - * @deprecated since version 3.4, to be removed in 4.0. Use Symfony\Component\Form\FormRenderer instead. - */ -class TwigRenderer extends FormRenderer implements TwigRendererInterface -{ - public function __construct(TwigRendererEngineInterface $engine, CsrfTokenManagerInterface $csrfTokenManager = null) - { - parent::__construct($engine, $csrfTokenManager); - } - - /** - * Returns the engine used by this renderer. - * - * @return TwigRendererEngineInterface The renderer engine - */ - public function getEngine() - { - return parent::getEngine(); - } - - /** - * {@inheritdoc} - */ - public function setEnvironment(Environment $environment) - { - $this->getEngine()->setEnvironment($environment); - } -} diff --git a/src/Symfony/Bridge/Twig/Form/TwigRendererEngine.php b/src/Symfony/Bridge/Twig/Form/TwigRendererEngine.php index 7e375f45e2996..2c14da516d642 100644 --- a/src/Symfony/Bridge/Twig/Form/TwigRendererEngine.php +++ b/src/Symfony/Bridge/Twig/Form/TwigRendererEngine.php @@ -19,7 +19,7 @@ /** * @author Bernhard Schussek */ -class TwigRendererEngine extends AbstractRendererEngine implements TwigRendererEngineInterface +class TwigRendererEngine extends AbstractRendererEngine { /** * @var Environment @@ -31,30 +31,12 @@ class TwigRendererEngine extends AbstractRendererEngine implements TwigRendererE */ private $template; - public function __construct(array $defaultThemes = array(), Environment $environment = null) + public function __construct(array $defaultThemes, Environment $environment) { - if (null === $environment) { - @trigger_error(sprintf('Not passing a Twig Environment as the second argument for "%s" constructor is deprecated since version 3.2 and won\'t be possible in 4.0.', static::class), E_USER_DEPRECATED); - } - parent::__construct($defaultThemes); $this->environment = $environment; } - /** - * {@inheritdoc} - * - * @deprecated since version 3.3, to be removed in 4.0 - */ - public function setEnvironment(Environment $environment) - { - if ($this->environment) { - @trigger_error(sprintf('The "%s()" method is deprecated since version 3.3 and will be removed in 4.0. Pass the Twig Environment as second argument of the constructor instead.', __METHOD__), E_USER_DEPRECATED); - } - - $this->environment = $environment; - } - /** * {@inheritdoc} */ diff --git a/src/Symfony/Bridge/Twig/Form/TwigRendererEngineInterface.php b/src/Symfony/Bridge/Twig/Form/TwigRendererEngineInterface.php deleted file mode 100644 index a58f491f1c8a0..0000000000000 --- a/src/Symfony/Bridge/Twig/Form/TwigRendererEngineInterface.php +++ /dev/null @@ -1,28 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bridge\Twig\Form; - -use Symfony\Component\Form\FormRendererEngineInterface; -use Twig\Environment; - -// BC/FC with namespaced Twig -class_exists('Twig\Environment'); - -/** - * @author Bernhard Schussek - * - * @deprecated since version 3.2, to be removed in 4.0. - */ -interface TwigRendererEngineInterface extends FormRendererEngineInterface -{ - public function setEnvironment(Environment $environment); -} diff --git a/src/Symfony/Bridge/Twig/Form/TwigRendererInterface.php b/src/Symfony/Bridge/Twig/Form/TwigRendererInterface.php deleted file mode 100644 index 3bcbf5992d76f..0000000000000 --- a/src/Symfony/Bridge/Twig/Form/TwigRendererInterface.php +++ /dev/null @@ -1,28 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bridge\Twig\Form; - -use Symfony\Component\Form\FormRendererInterface; -use Twig\Environment; - -// BC/FC with namespaced Twig -class_exists('Twig\Environment'); - -/** - * @author Bernhard Schussek - * - * @deprecated since version 3.2, to be removed in 4.0. - */ -interface TwigRendererInterface extends FormRendererInterface -{ - public function setEnvironment(Environment $environment); -} diff --git a/src/Symfony/Bridge/Twig/Node/FormThemeNode.php b/src/Symfony/Bridge/Twig/Node/FormThemeNode.php index a66a13adc0287..17b613cbf46bd 100644 --- a/src/Symfony/Bridge/Twig/Node/FormThemeNode.php +++ b/src/Symfony/Bridge/Twig/Node/FormThemeNode.php @@ -11,10 +11,8 @@ namespace Symfony\Bridge\Twig\Node; -use Symfony\Bridge\Twig\Form\TwigRenderer; use Symfony\Component\Form\FormRenderer; use Twig\Compiler; -use Twig\Error\RuntimeError; use Twig\Node\Node; /** @@ -29,17 +27,10 @@ public function __construct(Node $form, Node $resources, $lineno, $tag = null) public function compile(Compiler $compiler) { - try { - $compiler->getEnvironment()->getRuntime(FormRenderer::class); - $renderer = FormRenderer::class; - } catch (RuntimeError $e) { - $renderer = TwigRenderer::class; - } - $compiler ->addDebugInfo($this) ->write('$this->env->getRuntime(') - ->string($renderer) + ->string(FormRenderer::class) ->raw(')->setTheme(') ->subcompile($this->getNode('form')) ->raw(', ') From c0af0031ec83b794ad10857ef3f4f75e36c937c0 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Tue, 18 Jul 2017 13:37:51 +0200 Subject: [PATCH 0465/1099] [FrameworkBundle] Make RouterCacheWarmer implement ServiceSubscriberInterface --- .../Twig/Extension/RoutingExtension.php | 2 +- .../CacheWarmer/RouterCacheWarmer.php | 30 +++++++++++++++---- .../Resources/config/routing.xml | 3 +- 3 files changed, 28 insertions(+), 7 deletions(-) diff --git a/src/Symfony/Bridge/Twig/Extension/RoutingExtension.php b/src/Symfony/Bridge/Twig/Extension/RoutingExtension.php index 97b1ea31360ce..92a520eda3fb5 100644 --- a/src/Symfony/Bridge/Twig/Extension/RoutingExtension.php +++ b/src/Symfony/Bridge/Twig/Extension/RoutingExtension.php @@ -91,7 +91,7 @@ public function getUrl($name, $parameters = array(), $schemeRelative = false) * * @return array An array with the contexts the URL is safe * - * To be made @final in 3.4, and the type-hint be changed to "\Twig\Node\Node" in 4.0. + * @final since version 3.4, type-hint to be changed to "\Twig\Node\Node" in 4.0 */ public function isUrlGenerationSafe(\Twig_Node $argsNode) { diff --git a/src/Symfony/Bundle/FrameworkBundle/CacheWarmer/RouterCacheWarmer.php b/src/Symfony/Bundle/FrameworkBundle/CacheWarmer/RouterCacheWarmer.php index a650960c948e2..ffde2dcd92293 100644 --- a/src/Symfony/Bundle/FrameworkBundle/CacheWarmer/RouterCacheWarmer.php +++ b/src/Symfony/Bundle/FrameworkBundle/CacheWarmer/RouterCacheWarmer.php @@ -11,6 +11,8 @@ namespace Symfony\Bundle\FrameworkBundle\CacheWarmer; +use Psr\Container\ContainerInterface; +use Symfony\Component\DependencyInjection\ServiceSubscriberInterface; use Symfony\Component\HttpKernel\CacheWarmer\CacheWarmerInterface; use Symfony\Component\HttpKernel\CacheWarmer\WarmableInterface; use Symfony\Component\Routing\RouterInterface; @@ -20,20 +22,28 @@ * * @author Fabien Potencier * - * @final since version 3.4, to be given a container instead in 4.0 + * @final since version 3.4 */ -class RouterCacheWarmer implements CacheWarmerInterface +class RouterCacheWarmer implements CacheWarmerInterface, ServiceSubscriberInterface { protected $router; /** * Constructor. * - * @param RouterInterface $router A Router instance + * @param ContainerInterface $container */ - public function __construct(RouterInterface $router) + public function __construct($container) { - $this->router = $router; + // As this cache warmer is optional, dependencies should be lazy-loaded, that's why a container should be injected. + if ($container instanceof ContainerInterface) { + $this->router = $container->get('router'); // For BC, the $router property must be populated in the constructor + } elseif ($container instanceof RouterInterface) { + $this->router = $container; + @trigger_error(sprintf('Using a "%s" as first argument of %s is deprecated since version 3.4 and will be unsupported in version 4.0. Use a %s instead.', RouterInterface::class, __CLASS__, ContainerInterface::class), E_USER_DEPRECATED); + } else { + throw new \InvalidArgumentException(sprintf('%s only accepts instance of Psr\Container\ContainerInterface as first argument.', __CLASS__)); + } } /** @@ -57,4 +67,14 @@ public function isOptional() { return true; } + + /** + * {@inheritdoc} + */ + public static function getSubscribedServices() + { + return array( + 'router' => RouterInterface::class, + ); + } } diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/routing.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/routing.xml index 1278a0cb2208e..22bd38f8b80d6 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/routing.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/routing.xml @@ -97,8 +97,9 @@ + - + From 0bd1f09152f535357697a2ccd2f2e29e532d2725 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Tue, 18 Jul 2017 13:58:52 +0200 Subject: [PATCH 0466/1099] remove useless comment --- src/Symfony/Bundle/FrameworkBundle/HttpCache/HttpCache.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/HttpCache/HttpCache.php b/src/Symfony/Bundle/FrameworkBundle/HttpCache/HttpCache.php index 06aa922210569..d1e7829fc79e8 100644 --- a/src/Symfony/Bundle/FrameworkBundle/HttpCache/HttpCache.php +++ b/src/Symfony/Bundle/FrameworkBundle/HttpCache/HttpCache.php @@ -54,7 +54,7 @@ public function __construct(HttpKernelInterface $kernel, $cacheDir = null) protected function forward(Request $request, $raw = false, Response $entry = null) { $this->getKernel()->boot(); - $this->getKernel()->getContainer()->set('cache', $this); // to be removed in 4.0? + $this->getKernel()->getContainer()->set('cache', $this); return parent::forward($request, $raw, $entry); } From 86ec5e10a740140a758af092528107149f607acd Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Tue, 18 Jul 2017 13:29:29 +0200 Subject: [PATCH 0467/1099] Remove last legacy codes --- .../Twig/Extension/RoutingExtension.php | 4 ++-- .../CacheWarmer/RouterCacheWarmer.php | 24 ++++++------------- .../DependencyInjection/Configuration.php | 13 +--------- .../Resources/config/validator.xml | 11 --------- .../WebProfilerExtensionTest.php | 2 +- src/Symfony/Component/Form/FormInterface.php | 2 +- 6 files changed, 12 insertions(+), 44 deletions(-) diff --git a/src/Symfony/Bridge/Twig/Extension/RoutingExtension.php b/src/Symfony/Bridge/Twig/Extension/RoutingExtension.php index 92a520eda3fb5..4875b1fab8452 100644 --- a/src/Symfony/Bridge/Twig/Extension/RoutingExtension.php +++ b/src/Symfony/Bridge/Twig/Extension/RoutingExtension.php @@ -91,9 +91,9 @@ public function getUrl($name, $parameters = array(), $schemeRelative = false) * * @return array An array with the contexts the URL is safe * - * @final since version 3.4, type-hint to be changed to "\Twig\Node\Node" in 4.0 + * @final since version 3.4 */ - public function isUrlGenerationSafe(\Twig_Node $argsNode) + public function isUrlGenerationSafe(Node $argsNode) { // support named arguments $paramsNode = $argsNode->hasNode('parameters') ? $argsNode->getNode('parameters') : ( diff --git a/src/Symfony/Bundle/FrameworkBundle/CacheWarmer/RouterCacheWarmer.php b/src/Symfony/Bundle/FrameworkBundle/CacheWarmer/RouterCacheWarmer.php index ffde2dcd92293..5c360bc334409 100644 --- a/src/Symfony/Bundle/FrameworkBundle/CacheWarmer/RouterCacheWarmer.php +++ b/src/Symfony/Bundle/FrameworkBundle/CacheWarmer/RouterCacheWarmer.php @@ -26,24 +26,12 @@ */ class RouterCacheWarmer implements CacheWarmerInterface, ServiceSubscriberInterface { - protected $router; + private $container; - /** - * Constructor. - * - * @param ContainerInterface $container - */ - public function __construct($container) + public function __construct(ContainerInterface $container) { // As this cache warmer is optional, dependencies should be lazy-loaded, that's why a container should be injected. - if ($container instanceof ContainerInterface) { - $this->router = $container->get('router'); // For BC, the $router property must be populated in the constructor - } elseif ($container instanceof RouterInterface) { - $this->router = $container; - @trigger_error(sprintf('Using a "%s" as first argument of %s is deprecated since version 3.4 and will be unsupported in version 4.0. Use a %s instead.', RouterInterface::class, __CLASS__, ContainerInterface::class), E_USER_DEPRECATED); - } else { - throw new \InvalidArgumentException(sprintf('%s only accepts instance of Psr\Container\ContainerInterface as first argument.', __CLASS__)); - } + $this->container = $container; } /** @@ -53,8 +41,10 @@ public function __construct($container) */ public function warmUp($cacheDir) { - if ($this->router instanceof WarmableInterface) { - $this->router->warmUp($cacheDir); + $router = $this->container->get('router'); + + if ($router instanceof WarmableInterface) { + $router->warmUp($cacheDir); } } diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php index 917abe4a6978a..62313cb441652 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php @@ -629,18 +629,7 @@ private function addValidationSection(ArrayNodeDefinition $rootNode) ->info('validation configuration') ->{!class_exists(FullStack::class) && class_exists(Validation::class) ? 'canBeDisabled' : 'canBeEnabled'}() ->children() - ->scalarNode('cache') - ->beforeNormalization() - // Can be removed in 4.0, when validator.mapping.cache.doctrine.apc is removed - ->ifString()->then(function ($v) { - if ('validator.mapping.cache.doctrine.apc' === $v && !class_exists('Doctrine\Common\Cache\ApcCache')) { - throw new LogicException('Doctrine APC cache for the validator cannot be enabled as the Doctrine Cache package is not installed.'); - } - - return $v; - }) - ->end() - ->end() + ->scalarNode('cache')->end() ->booleanNode('enable_annotations')->{!class_exists(FullStack::class) && class_exists(Annotation::class) ? 'defaultTrue' : 'defaultFalse'}()->end() ->arrayNode('static_method') ->defaultValue(array('loadValidatorMetadata')) diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/validator.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/validator.xml index aa472d380cb33..6d7344c292fca 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/validator.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/validator.xml @@ -49,17 +49,6 @@ - - - - - %validator.mapping.cache.prefix% - - - - The "%service_id%" service is deprecated since Symfony 3.4 and will be removed in 4.0. Use a Psr6 cache like "validator.mapping.cache.symfony" instead. - - diff --git a/src/Symfony/Bundle/WebProfilerBundle/Tests/DependencyInjection/WebProfilerExtensionTest.php b/src/Symfony/Bundle/WebProfilerBundle/Tests/DependencyInjection/WebProfilerExtensionTest.php index af0573e5a362d..44ca1ed2cc038 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Tests/DependencyInjection/WebProfilerExtensionTest.php +++ b/src/Symfony/Bundle/WebProfilerBundle/Tests/DependencyInjection/WebProfilerExtensionTest.php @@ -31,7 +31,7 @@ public static function assertSaneContainer(Container $container, $message = '', { $errors = array(); foreach ($container->getServiceIds() as $id) { - if (in_array($id, $knownPrivates, true)) { // to be removed in 4.0 + if (in_array($id, $knownPrivates, true)) { // for BC with 3.4 continue; } try { diff --git a/src/Symfony/Component/Form/FormInterface.php b/src/Symfony/Component/Form/FormInterface.php index 98869977638c4..877b0449cee4f 100644 --- a/src/Symfony/Component/Form/FormInterface.php +++ b/src/Symfony/Component/Form/FormInterface.php @@ -189,7 +189,7 @@ public function addError(FormError $error); /** * Returns whether the form and all children are valid. * - * If the form is not submitted, this method always returns false (but will throw an exception in 4.0). + * @throws Exception\LogicException If the form is not submitted. * * @return bool */ From 53b01903ceb91e1b0fb17c0f1a66faae3d68c51d Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Tue, 18 Jul 2017 13:08:22 +0200 Subject: [PATCH 0468/1099] [Config] Make ClassExistenceResource throw on invalid parents --- .../Resource/ClassExistenceResource.php | 25 ++++++++++++++++--- .../Compiler/AutowirePass.php | 12 ++++----- .../Compiler/FactoryReturnTypePass.php | 2 +- .../ResolveInstanceofConditionalsPass.php | 2 +- .../DependencyInjection/ContainerBuilder.php | 8 +++++- .../Tests/Compiler/AutowirePassTest.php | 6 ++--- 6 files changed, 40 insertions(+), 15 deletions(-) diff --git a/src/Symfony/Component/Config/Resource/ClassExistenceResource.php b/src/Symfony/Component/Config/Resource/ClassExistenceResource.php index 8a86a4209961b..ada9a89b949e6 100644 --- a/src/Symfony/Component/Config/Resource/ClassExistenceResource.php +++ b/src/Symfony/Component/Config/Resource/ClassExistenceResource.php @@ -25,6 +25,7 @@ class ClassExistenceResource implements SelfCheckingResourceInterface, \Serializ private $exists; private static $autoloadLevel = 0; + private static $autoloadedClass; private static $existsCache = array(); /** @@ -57,6 +58,8 @@ public function getResource() /** * {@inheritdoc} + * + * @throws \ReflectionException when a parent class/interface/trait is not found */ public function isFresh($timestamp) { @@ -68,12 +71,13 @@ public function isFresh($timestamp) if (!self::$autoloadLevel++) { spl_autoload_register(__CLASS__.'::throwOnRequiredClass'); } + $autoloadedClass = self::$autoloadedClass; + self::$autoloadedClass = $this->resource; try { $exists = class_exists($this->resource) || interface_exists($this->resource, false) || trait_exists($this->resource, false); - } catch (\ReflectionException $e) { - $exists = false; } finally { + self::$autoloadedClass = $autoloadedClass; if (!--self::$autoloadLevel) { spl_autoload_unregister(__CLASS__.'::throwOnRequiredClass'); } @@ -112,7 +116,10 @@ public function unserialize($serialized) */ private static function throwOnRequiredClass($class) { - $e = new \ReflectionException("Class $class does not exist"); + if (self::$autoloadedClass === $class) { + return; + } + $e = new \ReflectionException("Class $class not found"); $trace = $e->getTrace(); $autoloadFrame = array( 'function' => 'spl_autoload_call', @@ -138,6 +145,18 @@ private static function throwOnRequiredClass($class) case 'is_callable': return; } + + $props = array( + 'file' => $trace[$i]['file'], + 'line' => $trace[$i]['line'], + 'trace' => array_slice($trace, 0, 1 + $i), + ); + + foreach ($props as $p => $v) { + $r = new \ReflectionProperty('Exception', $p); + $r->setAccessible(true); + $r->setValue($e, $v); + } } throw $e; diff --git a/src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php b/src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php index 8382d303859e1..055347b6f80f3 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php @@ -124,8 +124,8 @@ private function doProcessValue($value, $isRoot = false) if (!$value instanceof Definition || !$value->isAutowired() || $value->isAbstract() || !$value->getClass()) { return $value; } - if (!$reflectionClass = $this->container->getReflectionClass($value->getClass())) { - $this->container->log($this, sprintf('Skipping service "%s": Class or interface "%s" does not exist.', $this->currentId, $value->getClass())); + if (!$reflectionClass = $this->container->getReflectionClass($value->getClass(), false)) { + $this->container->log($this, sprintf('Skipping service "%s": Class or interface "%s" cannot be loaded.', $this->currentId, $value->getClass())); return $value; } @@ -388,7 +388,7 @@ private function populateAvailableType($id, Definition $definition) unset($this->ambiguousServiceTypes[$type]); } - if ($definition->isDeprecated() || !$reflectionClass = $this->container->getReflectionClass($definition->getClass())) { + if ($definition->isDeprecated() || !$reflectionClass = $this->container->getReflectionClass($definition->getClass(), false)) { return; } @@ -444,7 +444,7 @@ private function set($type, $id) */ private function createAutowiredDefinition($type) { - if (!($typeHint = $this->container->getReflectionClass($type)) || !$typeHint->isInstantiable()) { + if (!($typeHint = $this->container->getReflectionClass($type, false)) || !$typeHint->isInstantiable()) { return; } @@ -478,8 +478,8 @@ private function createAutowiredDefinition($type) private function createTypeNotFoundMessage(TypedReference $reference, $label) { - if (!$r = $this->container->getReflectionClass($type = $reference->getType())) { - $message = sprintf('has type "%s" but this class does not exist.', $type); + if (!$r = $this->container->getReflectionClass($type = $reference->getType(), false)) { + $message = sprintf('has type "%s" but this class cannot be loaded.', $type); } else { $message = $this->container->has($type) ? 'this service is abstract' : 'no such service exists'; $message = sprintf('references %s "%s" but %s.%s', $r->isInterface() ? 'interface' : 'class', $type, $message, $this->createTypeAlternatives($reference)); diff --git a/src/Symfony/Component/DependencyInjection/Compiler/FactoryReturnTypePass.php b/src/Symfony/Component/DependencyInjection/Compiler/FactoryReturnTypePass.php index 3ba4a8caa02f2..85b5872b0e7d3 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/FactoryReturnTypePass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/FactoryReturnTypePass.php @@ -81,7 +81,7 @@ private function updateDefinition(ContainerBuilder $container, $id, Definition $ $class = $factory[0]; } - if (!$m = $container->getReflectionClass($class)) { + if (!$m = $container->getReflectionClass($class, false)) { return; } try { diff --git a/src/Symfony/Component/DependencyInjection/Compiler/ResolveInstanceofConditionalsPass.php b/src/Symfony/Component/DependencyInjection/Compiler/ResolveInstanceofConditionalsPass.php index 82f13ed2d0e17..32d7ad2911408 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/ResolveInstanceofConditionalsPass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/ResolveInstanceofConditionalsPass.php @@ -66,7 +66,7 @@ private function processDefinition(ContainerBuilder $container, $id, Definition $instanceofTags = array(); foreach ($conditionals as $interface => $instanceofDefs) { - if ($interface !== $class && (!$container->getReflectionClass($class))) { + if ($interface !== $class && (!$container->getReflectionClass($class, false))) { continue; } diff --git a/src/Symfony/Component/DependencyInjection/ContainerBuilder.php b/src/Symfony/Component/DependencyInjection/ContainerBuilder.php index 14dd957e9ea13..c824cc959de9d 100644 --- a/src/Symfony/Component/DependencyInjection/ContainerBuilder.php +++ b/src/Symfony/Component/DependencyInjection/ContainerBuilder.php @@ -337,12 +337,15 @@ public function addClassResource(\ReflectionClass $class) * Retrieves the requested reflection class and registers it for resource tracking. * * @param string $class + * @param bool $throw * * @return \ReflectionClass|null * + * @throws \ReflectionException when a parent class/interface/trait is not found and $throw is true + * * @final */ - public function getReflectionClass($class) + public function getReflectionClass($class, $throw = true) { if (!$class = $this->getParameterBag()->resolveValue($class)) { return; @@ -357,6 +360,9 @@ public function getReflectionClass($class) $classReflector = $resource->isFresh(0) ? false : new \ReflectionClass($class); } } catch (\ReflectionException $e) { + if ($throw) { + throw $e; + } $classReflector = false; } diff --git a/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowirePassTest.php b/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowirePassTest.php index 41ad5634132c0..76cf290283230 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowirePassTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowirePassTest.php @@ -359,7 +359,7 @@ public function testDontTriggerAutowiring() /** * @expectedException \Symfony\Component\DependencyInjection\Exception\AutowiringFailedException - * @expectedExceptionMessage Cannot autowire service "a": argument "$r" of method "Symfony\Component\DependencyInjection\Tests\Compiler\BadTypeHintedArgument::__construct()" has type "Symfony\Component\DependencyInjection\Tests\Compiler\NotARealClass" but this class does not exist. + * @expectedExceptionMessage Cannot autowire service "a": argument "$r" of method "Symfony\Component\DependencyInjection\Tests\Compiler\BadTypeHintedArgument::__construct()" has type "Symfony\Component\DependencyInjection\Tests\Compiler\NotARealClass" but this class cannot be loaded. */ public function testClassNotFoundThrowsException() { @@ -374,7 +374,7 @@ public function testClassNotFoundThrowsException() /** * @expectedException \Symfony\Component\DependencyInjection\Exception\AutowiringFailedException - * @expectedExceptionMessage Cannot autowire service "a": argument "$r" of method "Symfony\Component\DependencyInjection\Tests\Compiler\BadParentTypeHintedArgument::__construct()" has type "Symfony\Component\DependencyInjection\Tests\Compiler\OptionalServiceClass" but this class does not exist. + * @expectedExceptionMessage Cannot autowire service "a": argument "$r" of method "Symfony\Component\DependencyInjection\Tests\Compiler\BadParentTypeHintedArgument::__construct()" has type "Symfony\Component\DependencyInjection\Tests\Compiler\OptionalServiceClass" but this class cannot be loaded. */ public function testParentClassNotFoundThrowsException() { @@ -744,7 +744,7 @@ public function testNotWireableCalls($method, $expectedMsg) public function provideNotWireableCalls() { return array( - array('setNotAutowireable', 'Cannot autowire service "foo": argument "$n" of method "Symfony\Component\DependencyInjection\Tests\Compiler\NotWireable::setNotAutowireable()" has type "Symfony\Component\DependencyInjection\Tests\Compiler\NotARealClass" but this class does not exist.'), + array('setNotAutowireable', 'Cannot autowire service "foo": argument "$n" of method "Symfony\Component\DependencyInjection\Tests\Compiler\NotWireable::setNotAutowireable()" has type "Symfony\Component\DependencyInjection\Tests\Compiler\NotARealClass" but this class cannot be loaded.'), array('setDifferentNamespace', 'Cannot autowire service "foo": argument "$n" of method "Symfony\Component\DependencyInjection\Tests\Compiler\NotWireable::setDifferentNamespace()" references class "stdClass" but no such service exists. It cannot be auto-registered because it is from a different root namespace.'), array(null, 'Cannot autowire service "foo": method "Symfony\Component\DependencyInjection\Tests\Compiler\NotWireable::setProtectedMethod()" must be public.'), ); From 305ae5e5d47de6746aa93af964980fee44bbc916 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Tue, 18 Jul 2017 18:05:00 +0200 Subject: [PATCH 0469/1099] [VarDumper] Use "C" locale when using "comma" flags --- src/Symfony/Component/VarDumper/Dumper/AbstractDumper.php | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/Symfony/Component/VarDumper/Dumper/AbstractDumper.php b/src/Symfony/Component/VarDumper/Dumper/AbstractDumper.php index b266258623c67..0f42d8a6c465c 100644 --- a/src/Symfony/Component/VarDumper/Dumper/AbstractDumper.php +++ b/src/Symfony/Component/VarDumper/Dumper/AbstractDumper.php @@ -123,6 +123,10 @@ public function setIndentPad($pad) */ public function dump(Data $data, $output = null) { + if ($locale = $this->flags & (self::DUMP_COMMA_SEPARATOR | self::DUMP_TRAILING_COMMA) ? setlocale(LC_NUMERIC, 0) : null) { + setlocale(LC_NUMERIC, 'C'); + } + if ($returnDump = true === $output) { $output = fopen('php://memory', 'r+b'); } @@ -143,6 +147,9 @@ public function dump(Data $data, $output = null) if ($output) { $this->setOutput($prevOutput); } + if ($locale) { + setlocale(LC_NUMERIC, $locale); + } } } From eed8a5143d324d5de1e5c50d2215c9a39d365d1d Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Tue, 18 Jul 2017 17:30:43 +0200 Subject: [PATCH 0470/1099] [VarDumper] Move locale sniffing to dump() time --- src/Symfony/Component/VarDumper/Dumper/AbstractDumper.php | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/VarDumper/Dumper/AbstractDumper.php b/src/Symfony/Component/VarDumper/Dumper/AbstractDumper.php index bed08bf47e0ab..abbe9629540ba 100644 --- a/src/Symfony/Component/VarDumper/Dumper/AbstractDumper.php +++ b/src/Symfony/Component/VarDumper/Dumper/AbstractDumper.php @@ -39,8 +39,8 @@ abstract class AbstractDumper implements DataDumperInterface, DumperInterface public function __construct($output = null, $charset = null) { $this->setCharset($charset ?: ini_get('php.output_encoding') ?: ini_get('default_charset') ?: 'UTF-8'); - $this->decimalPoint = (string) 0.5; - $this->decimalPoint = $this->decimalPoint[1]; + $this->decimalPoint = localeconv(); + $this->decimalPoint = $this->decimalPoint['decimal_point']; $this->setOutput($output ?: static::$defaultOutput); if (!$output && is_string(static::$defaultOutput)) { static::$defaultOutput = $this->outputStream; @@ -134,6 +134,9 @@ public function setIndentPad($pad) */ public function dump(Data $data, $output = null) { + $this->decimalPoint = localeconv(); + $this->decimalPoint = $this->decimalPoint['decimal_point']; + $exception = null; if ($output) { $prevOutput = $this->setOutput($output); From 04b7b04b65b7df233b56061b8dd3337317ecb544 Mon Sep 17 00:00:00 2001 From: Shaun Simmons Date: Tue, 18 Jul 2017 17:34:47 -0400 Subject: [PATCH 0471/1099] Change "this" to "that" to avoid confusion --- .../DependencyInjection/Compiler/PriorityTaggedServiceTrait.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/DependencyInjection/Compiler/PriorityTaggedServiceTrait.php b/src/Symfony/Component/DependencyInjection/Compiler/PriorityTaggedServiceTrait.php index 64c041e93f3a7..04e6cc67a55d9 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/PriorityTaggedServiceTrait.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/PriorityTaggedServiceTrait.php @@ -26,7 +26,7 @@ trait PriorityTaggedServiceTrait * * The order of additions must be respected for services having the same priority, * and knowing that the \SplPriorityQueue class does not respect the FIFO method, - * we should not use this class. + * we should not use that class. * * @see https://bugs.php.net/bug.php?id=53710 * @see https://bugs.php.net/bug.php?id=60926 From c0556cb20447208e277e26a851680802983e0ab9 Mon Sep 17 00:00:00 2001 From: David Maicher Date: Mon, 17 Jul 2017 22:35:32 +0200 Subject: [PATCH 0472/1099] [FrameworkBundle] fix ValidatorCacheWarmer: use serializing ArrayAdapter --- .../AbstractPhpFileCacheWarmer.php | 92 +++++++++++++++++++ .../CacheWarmer/AnnotationsCacheWarmer.php | 75 ++++----------- .../CacheWarmer/SerializerCacheWarmer.php | 59 +++--------- .../CacheWarmer/ValidatorCacheWarmer.php | 62 ++++--------- 4 files changed, 143 insertions(+), 145 deletions(-) create mode 100644 src/Symfony/Bundle/FrameworkBundle/CacheWarmer/AbstractPhpFileCacheWarmer.php diff --git a/src/Symfony/Bundle/FrameworkBundle/CacheWarmer/AbstractPhpFileCacheWarmer.php b/src/Symfony/Bundle/FrameworkBundle/CacheWarmer/AbstractPhpFileCacheWarmer.php new file mode 100644 index 0000000000000..25801a7829c91 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/CacheWarmer/AbstractPhpFileCacheWarmer.php @@ -0,0 +1,92 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\FrameworkBundle\CacheWarmer; + +use Psr\Cache\CacheItemPoolInterface; +use Symfony\Component\Cache\Adapter\AdapterInterface; +use Symfony\Component\Cache\Adapter\ArrayAdapter; +use Symfony\Component\Cache\Adapter\PhpArrayAdapter; +use Symfony\Component\Cache\Adapter\ProxyAdapter; +use Symfony\Component\HttpKernel\CacheWarmer\CacheWarmerInterface; + +/** + * @internal + */ +abstract class AbstractPhpFileCacheWarmer implements CacheWarmerInterface +{ + private $phpArrayFile; + private $fallbackPool; + + /** + * @param string $phpArrayFile The PHP file where metadata are cached + * @param CacheItemPoolInterface $fallbackPool The pool where runtime-discovered metadata are cached + */ + public function __construct($phpArrayFile, CacheItemPoolInterface $fallbackPool) + { + $this->phpArrayFile = $phpArrayFile; + if (!$fallbackPool instanceof AdapterInterface) { + $fallbackPool = new ProxyAdapter($fallbackPool); + } + $this->fallbackPool = $fallbackPool; + } + + /** + * {@inheritdoc} + */ + public function isOptional() + { + return true; + } + + /** + * {@inheritdoc} + */ + public function warmUp($cacheDir) + { + $arrayAdapter = new ArrayAdapter(); + + spl_autoload_register(array(PhpArrayAdapter::class, 'throwOnRequiredClass')); + try { + if (!$this->doWarmUp($cacheDir, $arrayAdapter)) { + return; + } + } finally { + spl_autoload_unregister(array(PhpArrayAdapter::class, 'throwOnRequiredClass')); + } + + // the ArrayAdapter stores the values serialized + // to avoid mutation of the data after it was written to the cache + // so here we un-serialize the values first + $values = array_map(function ($val) { return null !== $val ? unserialize($val) : null; }, $arrayAdapter->getValues()); + + $this->warmUpPhpArrayAdapter(new PhpArrayAdapter($this->phpArrayFile, $this->fallbackPool), $values); + + foreach ($values as $k => $v) { + $item = $this->fallbackPool->getItem($k); + $this->fallbackPool->saveDeferred($item->set($v)); + } + $this->fallbackPool->commit(); + } + + protected function warmUpPhpArrayAdapter(PhpArrayAdapter $phpArrayAdapter, array $values) + { + $phpArrayAdapter->warmUp($values); + } + + /** + * @param string $cacheDir + * @param ArrayAdapter $arrayAdapter + * + * @return bool false if there is nothing to warm-up + */ + abstract protected function doWarmUp($cacheDir, ArrayAdapter $arrayAdapter); +} diff --git a/src/Symfony/Bundle/FrameworkBundle/CacheWarmer/AnnotationsCacheWarmer.php b/src/Symfony/Bundle/FrameworkBundle/CacheWarmer/AnnotationsCacheWarmer.php index a6fb4ed095d2b..4026b53bd7740 100644 --- a/src/Symfony/Bundle/FrameworkBundle/CacheWarmer/AnnotationsCacheWarmer.php +++ b/src/Symfony/Bundle/FrameworkBundle/CacheWarmer/AnnotationsCacheWarmer.php @@ -15,12 +15,8 @@ use Doctrine\Common\Annotations\CachedReader; use Doctrine\Common\Annotations\Reader; use Psr\Cache\CacheItemPoolInterface; -use Symfony\Component\Cache\Adapter\AdapterInterface; use Symfony\Component\Cache\Adapter\ArrayAdapter; -use Symfony\Component\Cache\Adapter\PhpArrayAdapter; -use Symfony\Component\Cache\Adapter\ProxyAdapter; use Symfony\Component\Cache\DoctrineProvider; -use Symfony\Component\HttpKernel\CacheWarmer\CacheWarmerInterface; /** * Warms up annotation caches for classes found in composer's autoload class map @@ -28,11 +24,9 @@ * * @author Titouan Galopin */ -class AnnotationsCacheWarmer implements CacheWarmerInterface +class AnnotationsCacheWarmer extends AbstractPhpFileCacheWarmer { private $annotationReader; - private $phpArrayFile; - private $fallbackPool; /** * @param Reader $annotationReader @@ -41,70 +35,41 @@ class AnnotationsCacheWarmer implements CacheWarmerInterface */ public function __construct(Reader $annotationReader, $phpArrayFile, CacheItemPoolInterface $fallbackPool) { + parent::__construct($phpArrayFile, $fallbackPool); $this->annotationReader = $annotationReader; - $this->phpArrayFile = $phpArrayFile; - if (!$fallbackPool instanceof AdapterInterface) { - $fallbackPool = new ProxyAdapter($fallbackPool); - } - $this->fallbackPool = $fallbackPool; } /** * {@inheritdoc} */ - public function warmUp($cacheDir) + protected function doWarmUp($cacheDir, ArrayAdapter $arrayAdapter) { - $adapter = new PhpArrayAdapter($this->phpArrayFile, $this->fallbackPool); $annotatedClassPatterns = $cacheDir.'/annotations.map'; if (!is_file($annotatedClassPatterns)) { - $adapter->warmUp(array()); - - return; + return true; } $annotatedClasses = include $annotatedClassPatterns; - - $arrayPool = new ArrayAdapter(0, false); - $reader = new CachedReader($this->annotationReader, new DoctrineProvider($arrayPool)); - - spl_autoload_register(array($adapter, 'throwOnRequiredClass')); - try { - foreach ($annotatedClasses as $class) { - try { - $this->readAllComponents($reader, $class); - } catch (\ReflectionException $e) { - // ignore failing reflection - } catch (AnnotationException $e) { - /* - * Ignore any AnnotationException to not break the cache warming process if an Annotation is badly - * configured or could not be found / read / etc. - * - * In particular cases, an Annotation in your code can be used and defined only for a specific - * environment but is always added to the annotations.map file by some Symfony default behaviors, - * and you always end up with a not found Annotation. - */ - } + $reader = new CachedReader($this->annotationReader, new DoctrineProvider($arrayAdapter)); + + foreach ($annotatedClasses as $class) { + try { + $this->readAllComponents($reader, $class); + } catch (\ReflectionException $e) { + // ignore failing reflection + } catch (AnnotationException $e) { + /* + * Ignore any AnnotationException to not break the cache warming process if an Annotation is badly + * configured or could not be found / read / etc. + * + * In particular cases, an Annotation in your code can be used and defined only for a specific + * environment but is always added to the annotations.map file by some Symfony default behaviors, + * and you always end up with a not found Annotation. + */ } - } finally { - spl_autoload_unregister(array($adapter, 'throwOnRequiredClass')); - } - - $values = $arrayPool->getValues(); - $adapter->warmUp($values); - - foreach ($values as $k => $v) { - $item = $this->fallbackPool->getItem($k); - $this->fallbackPool->saveDeferred($item->set($v)); } - $this->fallbackPool->commit(); - } - /** - * {@inheritdoc} - */ - public function isOptional() - { return true; } diff --git a/src/Symfony/Bundle/FrameworkBundle/CacheWarmer/SerializerCacheWarmer.php b/src/Symfony/Bundle/FrameworkBundle/CacheWarmer/SerializerCacheWarmer.php index c017f51268b3d..75cc2bcf9b384 100644 --- a/src/Symfony/Bundle/FrameworkBundle/CacheWarmer/SerializerCacheWarmer.php +++ b/src/Symfony/Bundle/FrameworkBundle/CacheWarmer/SerializerCacheWarmer.php @@ -13,11 +13,7 @@ use Doctrine\Common\Annotations\AnnotationException; use Psr\Cache\CacheItemPoolInterface; -use Symfony\Component\Cache\Adapter\AdapterInterface; use Symfony\Component\Cache\Adapter\ArrayAdapter; -use Symfony\Component\Cache\Adapter\PhpArrayAdapter; -use Symfony\Component\Cache\Adapter\ProxyAdapter; -use Symfony\Component\HttpKernel\CacheWarmer\CacheWarmerInterface; use Symfony\Component\Serializer\Mapping\Factory\CacheClassMetadataFactory; use Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactory; use Symfony\Component\Serializer\Mapping\Loader\LoaderChain; @@ -30,11 +26,9 @@ * * @author Titouan Galopin */ -class SerializerCacheWarmer implements CacheWarmerInterface +class SerializerCacheWarmer extends AbstractPhpFileCacheWarmer { private $loaders; - private $phpArrayFile; - private $fallbackPool; /** * @param LoaderInterface[] $loaders The serializer metadata loaders @@ -43,60 +37,33 @@ class SerializerCacheWarmer implements CacheWarmerInterface */ public function __construct(array $loaders, $phpArrayFile, CacheItemPoolInterface $fallbackPool) { + parent::__construct($phpArrayFile, $fallbackPool); $this->loaders = $loaders; - $this->phpArrayFile = $phpArrayFile; - if (!$fallbackPool instanceof AdapterInterface) { - $fallbackPool = new ProxyAdapter($fallbackPool); - } - $this->fallbackPool = $fallbackPool; } /** * {@inheritdoc} */ - public function warmUp($cacheDir) + protected function doWarmUp($cacheDir, ArrayAdapter $arrayAdapter) { if (!class_exists(CacheClassMetadataFactory::class) || !method_exists(XmlFileLoader::class, 'getMappedClasses') || !method_exists(YamlFileLoader::class, 'getMappedClasses')) { - return; + return false; } - $adapter = new PhpArrayAdapter($this->phpArrayFile, $this->fallbackPool); - $arrayPool = new ArrayAdapter(0, false); - - $metadataFactory = new CacheClassMetadataFactory(new ClassMetadataFactory(new LoaderChain($this->loaders)), $arrayPool); + $metadataFactory = new CacheClassMetadataFactory(new ClassMetadataFactory(new LoaderChain($this->loaders)), $arrayAdapter); - spl_autoload_register(array($adapter, 'throwOnRequiredClass')); - try { - foreach ($this->extractSupportedLoaders($this->loaders) as $loader) { - foreach ($loader->getMappedClasses() as $mappedClass) { - try { - $metadataFactory->getMetadataFor($mappedClass); - } catch (\ReflectionException $e) { - // ignore failing reflection - } catch (AnnotationException $e) { - // ignore failing annotations - } + foreach ($this->extractSupportedLoaders($this->loaders) as $loader) { + foreach ($loader->getMappedClasses() as $mappedClass) { + try { + $metadataFactory->getMetadataFor($mappedClass); + } catch (\ReflectionException $e) { + // ignore failing reflection + } catch (AnnotationException $e) { + // ignore failing annotations } } - } finally { - spl_autoload_unregister(array($adapter, 'throwOnRequiredClass')); - } - - $values = $arrayPool->getValues(); - $adapter->warmUp($values); - - foreach ($values as $k => $v) { - $item = $this->fallbackPool->getItem($k); - $this->fallbackPool->saveDeferred($item->set($v)); } - $this->fallbackPool->commit(); - } - /** - * {@inheritdoc} - */ - public function isOptional() - { return true; } diff --git a/src/Symfony/Bundle/FrameworkBundle/CacheWarmer/ValidatorCacheWarmer.php b/src/Symfony/Bundle/FrameworkBundle/CacheWarmer/ValidatorCacheWarmer.php index 81291d772fbf0..20f76cb4fdd73 100644 --- a/src/Symfony/Bundle/FrameworkBundle/CacheWarmer/ValidatorCacheWarmer.php +++ b/src/Symfony/Bundle/FrameworkBundle/CacheWarmer/ValidatorCacheWarmer.php @@ -13,11 +13,8 @@ use Doctrine\Common\Annotations\AnnotationException; use Psr\Cache\CacheItemPoolInterface; -use Symfony\Component\Cache\Adapter\AdapterInterface; use Symfony\Component\Cache\Adapter\ArrayAdapter; use Symfony\Component\Cache\Adapter\PhpArrayAdapter; -use Symfony\Component\Cache\Adapter\ProxyAdapter; -use Symfony\Component\HttpKernel\CacheWarmer\CacheWarmerInterface; use Symfony\Component\Validator\Mapping\Cache\Psr6Cache; use Symfony\Component\Validator\Mapping\Factory\LazyLoadingMetadataFactory; use Symfony\Component\Validator\Mapping\Loader\LoaderChain; @@ -31,11 +28,9 @@ * * @author Titouan Galopin */ -class ValidatorCacheWarmer implements CacheWarmerInterface +class ValidatorCacheWarmer extends AbstractPhpFileCacheWarmer { private $validatorBuilder; - private $phpArrayFile; - private $fallbackPool; /** * @param ValidatorBuilderInterface $validatorBuilder @@ -44,64 +39,43 @@ class ValidatorCacheWarmer implements CacheWarmerInterface */ public function __construct(ValidatorBuilderInterface $validatorBuilder, $phpArrayFile, CacheItemPoolInterface $fallbackPool) { + parent::__construct($phpArrayFile, $fallbackPool); $this->validatorBuilder = $validatorBuilder; - $this->phpArrayFile = $phpArrayFile; - if (!$fallbackPool instanceof AdapterInterface) { - $fallbackPool = new ProxyAdapter($fallbackPool); - } - $this->fallbackPool = $fallbackPool; } /** * {@inheritdoc} */ - public function warmUp($cacheDir) + protected function doWarmUp($cacheDir, ArrayAdapter $arrayAdapter) { if (!method_exists($this->validatorBuilder, 'getLoaders')) { - return; + return false; } - $adapter = new PhpArrayAdapter($this->phpArrayFile, $this->fallbackPool); - $arrayPool = new ArrayAdapter(0, false); - $loaders = $this->validatorBuilder->getLoaders(); - $metadataFactory = new LazyLoadingMetadataFactory(new LoaderChain($loaders), new Psr6Cache($arrayPool)); + $metadataFactory = new LazyLoadingMetadataFactory(new LoaderChain($loaders), new Psr6Cache($arrayAdapter)); - spl_autoload_register(array($adapter, 'throwOnRequiredClass')); - try { - foreach ($this->extractSupportedLoaders($loaders) as $loader) { - foreach ($loader->getMappedClasses() as $mappedClass) { - try { - if ($metadataFactory->hasMetadataFor($mappedClass)) { - $metadataFactory->getMetadataFor($mappedClass); - } - } catch (\ReflectionException $e) { - // ignore failing reflection - } catch (AnnotationException $e) { - // ignore failing annotations + foreach ($this->extractSupportedLoaders($loaders) as $loader) { + foreach ($loader->getMappedClasses() as $mappedClass) { + try { + if ($metadataFactory->hasMetadataFor($mappedClass)) { + $metadataFactory->getMetadataFor($mappedClass); } + } catch (\ReflectionException $e) { + // ignore failing reflection + } catch (AnnotationException $e) { + // ignore failing annotations } } - } finally { - spl_autoload_unregister(array($adapter, 'throwOnRequiredClass')); } - $values = $arrayPool->getValues(); - $adapter->warmUp(array_filter($values)); - - foreach ($values as $k => $v) { - $item = $this->fallbackPool->getItem($k); - $this->fallbackPool->saveDeferred($item->set($v)); - } - $this->fallbackPool->commit(); + return true; } - /** - * {@inheritdoc} - */ - public function isOptional() + protected function warmUpPhpArrayAdapter(PhpArrayAdapter $phpArrayAdapter, array $values) { - return true; + // make sure we don't cache null values + parent::warmUpPhpArrayAdapter($phpArrayAdapter, array_filter($values)); } /** From 295fda9a31e66463570a9fd92c0076d772ab9503 Mon Sep 17 00:00:00 2001 From: Maxime Steinhausser Date: Tue, 18 Jul 2017 19:41:39 +0200 Subject: [PATCH 0473/1099] [WebProfilerBundle][TwigBundle] Fix infinite js loop on exception pages --- .../TwigBundle/Resources/views/base_js.html.twig | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/Symfony/Bundle/TwigBundle/Resources/views/base_js.html.twig b/src/Symfony/Bundle/TwigBundle/Resources/views/base_js.html.twig index 4ce8013c4463a..036af2b025904 100644 --- a/src/Symfony/Bundle/TwigBundle/Resources/views/base_js.html.twig +++ b/src/Symfony/Bundle/TwigBundle/Resources/views/base_js.html.twig @@ -512,14 +512,14 @@ var altContent = toggle.getAttribute('data-toggle-alt-content'); toggle.innerHTML = currentContent !== altContent ? altContent : originalContent; }); + } - /* Prevents from disallowing clicks on links inside toggles */ - var toggleLinks = document.querySelectorAll('.sf-toggle a'); - for (var i = 0; i < toggleLinks.length; i++) { - addEventListener(toggleLinks[i], 'click', function(e) { - e.stopPropagation(); - }); - } + /* Prevents from disallowing clicks on links inside toggles */ + var toggleLinks = document.querySelectorAll('.sf-toggle a'); + for (var i = 0; i < toggleLinks.length; i++) { + addEventListener(toggleLinks[i], 'click', function(e) { + e.stopPropagation(); + }); } } }; From 338761245100e09dafdce47f7646ef7d4fc14f64 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Wed, 19 Jul 2017 07:07:01 +0200 Subject: [PATCH 0474/1099] [Security] refactored tests --- ...efaultAuthenticationSuccessHandlerTest.php | 80 +++++++------------ 1 file changed, 31 insertions(+), 49 deletions(-) diff --git a/src/Symfony/Component/Security/Http/Tests/Authentication/DefaultAuthenticationSuccessHandlerTest.php b/src/Symfony/Component/Security/Http/Tests/Authentication/DefaultAuthenticationSuccessHandlerTest.php index 2c133014cc136..70836170c7048 100644 --- a/src/Symfony/Component/Security/Http/Tests/Authentication/DefaultAuthenticationSuccessHandlerTest.php +++ b/src/Symfony/Component/Security/Http/Tests/Authentication/DefaultAuthenticationSuccessHandlerTest.php @@ -12,31 +12,28 @@ namespace Symfony\Component\Security\Http\Tests\Authentication; use PHPUnit\Framework\TestCase; +use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Security\Http\Authentication\DefaultAuthenticationSuccessHandler; class DefaultAuthenticationSuccessHandlerTest extends TestCase { private $httpUtils = null; - - private $request = null; - private $token = null; protected function setUp() { $this->httpUtils = $this->getMockBuilder('Symfony\Component\Security\Http\HttpUtils')->getMock(); - $this->request = $this->getMockBuilder('Symfony\Component\HttpFoundation\Request')->getMock(); - $this->request->headers = $this->getMockBuilder('Symfony\Component\HttpFoundation\HeaderBag')->getMock(); $this->token = $this->getMockBuilder('Symfony\Component\Security\Core\Authentication\Token\TokenInterface')->getMock(); } public function testRequestIsRedirected() { - $response = $this->expectRedirectResponse('/'); + $request = Request::create('/'); + $response = $this->expectRedirectResponse($request, '/'); $handler = new DefaultAuthenticationSuccessHandler($this->httpUtils, array()); - $result = $handler->onAuthenticationSuccess($this->request, $this->token); + $result = $handler->onAuthenticationSuccess($request, $this->token); $this->assertSame($response, $result); } @@ -48,24 +45,22 @@ public function testDefaultTargetPathCanBeForced() 'default_target_path' => '/dashboard', ); - $response = $this->expectRedirectResponse('/dashboard'); + $request = Request::create('/'); + $response = $this->expectRedirectResponse($request, '/dashboard'); $handler = new DefaultAuthenticationSuccessHandler($this->httpUtils, $options); - $result = $handler->onAuthenticationSuccess($this->request, $this->token); + $result = $handler->onAuthenticationSuccess($request, $this->token); $this->assertSame($response, $result); } public function testTargetPathIsPassedWithRequest() { - $this->request->expects($this->once()) - ->method('get')->with('_target_path') - ->will($this->returnValue('/dashboard')); - - $response = $this->expectRedirectResponse('/dashboard'); + $request = Request::create('/?_target_path=/dashboard'); + $response = $this->expectRedirectResponse($request, '/dashboard'); $handler = new DefaultAuthenticationSuccessHandler($this->httpUtils, array()); - $result = $handler->onAuthenticationSuccess($this->request, $this->token); + $result = $handler->onAuthenticationSuccess($request, $this->token); $this->assertSame($response, $result); } @@ -73,15 +68,11 @@ public function testTargetPathIsPassedWithRequest() public function testTargetPathParameterIsCustomised() { $options = array('target_path_parameter' => '_my_target_path'); - - $this->request->expects($this->once()) - ->method('get')->with('_my_target_path') - ->will($this->returnValue('/dashboard')); - - $response = $this->expectRedirectResponse('/dashboard'); + $request = Request::create('/?_my_target_path=/dashboard'); + $response = $this->expectRedirectResponse($request, '/dashboard'); $handler = new DefaultAuthenticationSuccessHandler($this->httpUtils, $options); - $result = $handler->onAuthenticationSuccess($this->request, $this->token); + $result = $handler->onAuthenticationSuccess($request, $this->token); $this->assertSame($response, $result); } @@ -95,16 +86,14 @@ public function testTargetPathIsTakenFromTheSession() $session->expects($this->once()) ->method('remove')->with('_security.admin.target_path'); - $this->request->expects($this->any()) - ->method('getSession') - ->will($this->returnValue($session)); - - $response = $this->expectRedirectResponse('/admin/dashboard'); + $request = Request::create('/?_my_target_path=/dashboard'); + $request->setSession($session); + $response = $this->expectRedirectResponse($request, '/admin/dashboard'); $handler = new DefaultAuthenticationSuccessHandler($this->httpUtils, array()); $handler->setProviderKey('admin'); - $result = $handler->onAuthenticationSuccess($this->request, $this->token); + $result = $handler->onAuthenticationSuccess($request, $this->token); $this->assertSame($response, $result); } @@ -112,15 +101,12 @@ public function testTargetPathIsTakenFromTheSession() public function testTargetPathIsPassedAsReferer() { $options = array('use_referer' => true); - - $this->request->headers->expects($this->once()) - ->method('get')->with('Referer') - ->will($this->returnValue('/dashboard')); - - $response = $this->expectRedirectResponse('/dashboard'); + $request = Request::create('/'); + $request->headers->set('Referer', '/dashboard'); + $response = $this->expectRedirectResponse($request, '/dashboard'); $handler = new DefaultAuthenticationSuccessHandler($this->httpUtils, $options); - $result = $handler->onAuthenticationSuccess($this->request, $this->token); + $result = $handler->onAuthenticationSuccess($request, $this->token); $this->assertSame($response, $result); } @@ -128,41 +114,37 @@ public function testTargetPathIsPassedAsReferer() public function testRefererHasToBeDifferentThatLoginUrl() { $options = array('use_referer' => true); - - $this->request->headers->expects($this->any()) - ->method('get')->with('Referer') - ->will($this->returnValue('/login')); - + $request = Request::create('/'); + $request->headers->set('Referer', '/login'); $this->httpUtils->expects($this->once()) - ->method('generateUri')->with($this->request, '/login') + ->method('generateUri')->with($request, '/login') ->will($this->returnValue('/login')); - $response = $this->expectRedirectResponse('/'); + $response = $this->expectRedirectResponse($request, '/'); $handler = new DefaultAuthenticationSuccessHandler($this->httpUtils, $options); - $result = $handler->onAuthenticationSuccess($this->request, $this->token); + $result = $handler->onAuthenticationSuccess($request, $this->token); $this->assertSame($response, $result); } public function testRefererTargetPathIsIgnoredByDefault() { - $this->request->headers->expects($this->never())->method('get'); - - $response = $this->expectRedirectResponse('/'); + $request = Request::create('/'); + $response = $this->expectRedirectResponse($request, '/'); $handler = new DefaultAuthenticationSuccessHandler($this->httpUtils, array()); - $result = $handler->onAuthenticationSuccess($this->request, $this->token); + $result = $handler->onAuthenticationSuccess($request, $this->token); $this->assertSame($response, $result); } - private function expectRedirectResponse($path) + private function expectRedirectResponse(Request $request, $path) { $response = new Response(); $this->httpUtils->expects($this->once()) ->method('createRedirectResponse') - ->with($this->request, $path) + ->with($request, $path) ->will($this->returnValue($response)); return $response; From b1f1ae26b47e6aaf5282584d880724fed66a86df Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Wed, 19 Jul 2017 07:42:44 +0200 Subject: [PATCH 0475/1099] [Security] simplified tests --- ...efaultAuthenticationSuccessHandlerTest.php | 195 +++++++----------- 1 file changed, 70 insertions(+), 125 deletions(-) diff --git a/src/Symfony/Component/Security/Http/Tests/Authentication/DefaultAuthenticationSuccessHandlerTest.php b/src/Symfony/Component/Security/Http/Tests/Authentication/DefaultAuthenticationSuccessHandlerTest.php index 70836170c7048..8d39e63cd5a2c 100644 --- a/src/Symfony/Component/Security/Http/Tests/Authentication/DefaultAuthenticationSuccessHandlerTest.php +++ b/src/Symfony/Component/Security/Http/Tests/Authentication/DefaultAuthenticationSuccessHandlerTest.php @@ -15,138 +15,83 @@ use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Security\Http\Authentication\DefaultAuthenticationSuccessHandler; +use Symfony\Component\Security\Http\HttpUtils; class DefaultAuthenticationSuccessHandlerTest extends TestCase { - private $httpUtils = null; - private $token = null; - - protected function setUp() - { - $this->httpUtils = $this->getMockBuilder('Symfony\Component\Security\Http\HttpUtils')->getMock(); - $this->token = $this->getMockBuilder('Symfony\Component\Security\Core\Authentication\Token\TokenInterface')->getMock(); - } - - public function testRequestIsRedirected() - { - $request = Request::create('/'); - $response = $this->expectRedirectResponse($request, '/'); - - $handler = new DefaultAuthenticationSuccessHandler($this->httpUtils, array()); - $result = $handler->onAuthenticationSuccess($request, $this->token); - - $this->assertSame($response, $result); - } - - public function testDefaultTargetPathCanBeForced() - { - $options = array( - 'always_use_default_target_path' => true, - 'default_target_path' => '/dashboard', - ); - - $request = Request::create('/'); - $response = $this->expectRedirectResponse($request, '/dashboard'); - - $handler = new DefaultAuthenticationSuccessHandler($this->httpUtils, $options); - $result = $handler->onAuthenticationSuccess($request, $this->token); - - $this->assertSame($response, $result); - } - - public function testTargetPathIsPassedWithRequest() - { - $request = Request::create('/?_target_path=/dashboard'); - $response = $this->expectRedirectResponse($request, '/dashboard'); - - $handler = new DefaultAuthenticationSuccessHandler($this->httpUtils, array()); - $result = $handler->onAuthenticationSuccess($request, $this->token); - - $this->assertSame($response, $result); - } - - public function testTargetPathParameterIsCustomised() + /** + * @dataProvider getRequestRedirections + */ + public function testRequestRedirections(Request $request, $options, $redirectedUrl) { - $options = array('target_path_parameter' => '_my_target_path'); - $request = Request::create('/?_my_target_path=/dashboard'); - $response = $this->expectRedirectResponse($request, '/dashboard'); - - $handler = new DefaultAuthenticationSuccessHandler($this->httpUtils, $options); - $result = $handler->onAuthenticationSuccess($request, $this->token); - - $this->assertSame($response, $result); + $httpUtils = new HttpUtils(); + $token = $this->getMockBuilder('Symfony\Component\Security\Core\Authentication\Token\TokenInterface')->getMock(); + $handler = new DefaultAuthenticationSuccessHandler($httpUtils, $options); + if ($request->hasSession()) { + $handler->setProviderKey('admin'); + } + $this->assertSame('http://localhost'.$redirectedUrl, $handler->onAuthenticationSuccess($request, $token)->getTargetUrl()); } - public function testTargetPathIsTakenFromTheSession() + public function getRequestRedirections() { $session = $this->getMockBuilder('Symfony\Component\HttpFoundation\Session\SessionInterface')->getMock(); - $session->expects($this->once()) - ->method('get')->with('_security.admin.target_path') - ->will($this->returnValue('/admin/dashboard')); - $session->expects($this->once()) - ->method('remove')->with('_security.admin.target_path'); - - $request = Request::create('/?_my_target_path=/dashboard'); - $request->setSession($session); - $response = $this->expectRedirectResponse($request, '/admin/dashboard'); - - $handler = new DefaultAuthenticationSuccessHandler($this->httpUtils, array()); - $handler->setProviderKey('admin'); - - $result = $handler->onAuthenticationSuccess($request, $this->token); - - $this->assertSame($response, $result); - } - - public function testTargetPathIsPassedAsReferer() - { - $options = array('use_referer' => true); - $request = Request::create('/'); - $request->headers->set('Referer', '/dashboard'); - $response = $this->expectRedirectResponse($request, '/dashboard'); - - $handler = new DefaultAuthenticationSuccessHandler($this->httpUtils, $options); - $result = $handler->onAuthenticationSuccess($request, $this->token); - - $this->assertSame($response, $result); - } - - public function testRefererHasToBeDifferentThatLoginUrl() - { - $options = array('use_referer' => true); - $request = Request::create('/'); - $request->headers->set('Referer', '/login'); - $this->httpUtils->expects($this->once()) - ->method('generateUri')->with($request, '/login') - ->will($this->returnValue('/login')); - - $response = $this->expectRedirectResponse($request, '/'); - - $handler = new DefaultAuthenticationSuccessHandler($this->httpUtils, $options); - $result = $handler->onAuthenticationSuccess($request, $this->token); - - $this->assertSame($response, $result); - } - - public function testRefererTargetPathIsIgnoredByDefault() - { - $request = Request::create('/'); - $response = $this->expectRedirectResponse($request, '/'); - - $handler = new DefaultAuthenticationSuccessHandler($this->httpUtils, array()); - $result = $handler->onAuthenticationSuccess($request, $this->token); - - $this->assertSame($response, $result); - } - - private function expectRedirectResponse(Request $request, $path) - { - $response = new Response(); - $this->httpUtils->expects($this->once()) - ->method('createRedirectResponse') - ->with($request, $path) - ->will($this->returnValue($response)); - - return $response; + $session->expects($this->once())->method('get')->with('_security.admin.target_path')->will($this->returnValue('/admin/dashboard')); + $session->expects($this->once())->method('remove')->with('_security.admin.target_path'); + $requestWithSession = Request::create('/'); + $requestWithSession->setSession($session); + + return array( + 'default' => array( + Request::create('/'), + array(), + '/', + ), + 'forced target path' => array( + Request::create('/'), + array('always_use_default_target_path' => true, 'default_target_path' => '/dashboard'), + '/dashboard', + ), + 'target path as query string' => array( + Request::create('/?_target_path=/dashboard'), + array(), + '/dashboard', + ), + 'target path name as query string is customized' => array( + Request::create('/?_my_target_path=/dashboard'), + array('target_path_parameter' => '_my_target_path'), + '/dashboard', + ), + 'target path name as query string is customized and nested' => array( + Request::create('/?_target_path[value]=/dashboard'), + array('target_path_parameter' => '_target_path[value]'), + '/dashboard', + ), + 'target path in session' => array( + $requestWithSession, + array(), + '/admin/dashboard', + ), + 'target path as referer' => array( + Request::create('/', 'GET', array(), array(), array(), array('HTTP_REFERER' => 'http://localhost/dashboard')), + array('use_referer' => true), + '/dashboard', + ), + 'target path as referer is ignored if not configured' => array( + Request::create('/', 'GET', array(), array(), array(), array('HTTP_REFERER' => 'http://localhost/dashboard')), + array(), + '/', + ), + 'target path should be different than login URL' => array( + Request::create('/', 'GET', array(), array(), array(), array('HTTP_REFERER' => 'http://localhost/login')), + array('use_referer' => true, 'login_path' => '/login'), + '/', + ), + 'target path should be different than login URL (query string does not matter)' => array( + Request::create('/', 'GET', array(), array(), array(), array('HTTP_REFERER' => 'http://localhost/login?t=1&p=2')), + array('use_referer' => true, 'login_path' => '/login'), + '/', + ), + ); } } From 9c7a1406cb81f4d1ccd7e3521347e2d847b7467c Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Wed, 19 Jul 2017 07:57:00 +0200 Subject: [PATCH 0476/1099] [Security] fixed default target path when referer contains a query string --- .../DefaultAuthenticationSuccessHandler.php | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/Security/Http/Authentication/DefaultAuthenticationSuccessHandler.php b/src/Symfony/Component/Security/Http/Authentication/DefaultAuthenticationSuccessHandler.php index b6a7df5062046..7da6e35572b47 100644 --- a/src/Symfony/Component/Security/Http/Authentication/DefaultAuthenticationSuccessHandler.php +++ b/src/Symfony/Component/Security/Http/Authentication/DefaultAuthenticationSuccessHandler.php @@ -118,8 +118,14 @@ protected function determineTargetUrl(Request $request) return $targetUrl; } - if ($this->options['use_referer'] && ($targetUrl = $request->headers->get('Referer')) && $targetUrl !== $this->httpUtils->generateUri($request, $this->options['login_path'])) { - return $targetUrl; + if ($this->options['use_referer']) { + $targetUrl = $request->headers->get('Referer'); + if (false !== $pos = strpos($targetUrl, '?')) { + $targetUrl = substr($targetUrl, 0, $pos); + } + if ($targetUrl !== $this->httpUtils->generateUri($request, $this->options['login_path'])) { + return $targetUrl; + } } return $this->options['default_target_path']; From 022ac0be096a303aa4de7be64b84be9ffee3ecd9 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Wed, 19 Jul 2017 08:04:16 +0200 Subject: [PATCH 0477/1099] [Security] added more tests --- ...DefaultAuthenticationSuccessHandlerTest.php | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/src/Symfony/Component/Security/Http/Tests/Authentication/DefaultAuthenticationSuccessHandlerTest.php b/src/Symfony/Component/Security/Http/Tests/Authentication/DefaultAuthenticationSuccessHandlerTest.php index 8d39e63cd5a2c..b42f840358e03 100644 --- a/src/Symfony/Component/Security/Http/Tests/Authentication/DefaultAuthenticationSuccessHandlerTest.php +++ b/src/Symfony/Component/Security/Http/Tests/Authentication/DefaultAuthenticationSuccessHandlerTest.php @@ -13,7 +13,6 @@ use PHPUnit\Framework\TestCase; use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Security\Http\Authentication\DefaultAuthenticationSuccessHandler; use Symfony\Component\Security\Http\HttpUtils; @@ -24,7 +23,9 @@ class DefaultAuthenticationSuccessHandlerTest extends TestCase */ public function testRequestRedirections(Request $request, $options, $redirectedUrl) { - $httpUtils = new HttpUtils(); + $urlGenerator = $this->getMockBuilder('Symfony\Component\Routing\Generator\UrlGeneratorInterface')->getMock(); + $urlGenerator->expects($this->any())->method('generate')->will($this->returnValue('http://localhost/login')); + $httpUtils = new HttpUtils($urlGenerator); $token = $this->getMockBuilder('Symfony\Component\Security\Core\Authentication\Token\TokenInterface')->getMock(); $handler = new DefaultAuthenticationSuccessHandler($httpUtils, $options); if ($request->hasSession()) { @@ -73,25 +74,30 @@ public function getRequestRedirections() '/admin/dashboard', ), 'target path as referer' => array( - Request::create('/', 'GET', array(), array(), array(), array('HTTP_REFERER' => 'http://localhost/dashboard')), + Request::create('/', 'GET', array(), array(), array(), array('HTTP_REFERER' => 'http://localhost/dashboard')), array('use_referer' => true), '/dashboard', ), 'target path as referer is ignored if not configured' => array( - Request::create('/', 'GET', array(), array(), array(), array('HTTP_REFERER' => 'http://localhost/dashboard')), + Request::create('/', 'GET', array(), array(), array(), array('HTTP_REFERER' => 'http://localhost/dashboard')), array(), '/', ), 'target path should be different than login URL' => array( - Request::create('/', 'GET', array(), array(), array(), array('HTTP_REFERER' => 'http://localhost/login')), + Request::create('/', 'GET', array(), array(), array(), array('HTTP_REFERER' => 'http://localhost/login')), array('use_referer' => true, 'login_path' => '/login'), '/', ), 'target path should be different than login URL (query string does not matter)' => array( - Request::create('/', 'GET', array(), array(), array(), array('HTTP_REFERER' => 'http://localhost/login?t=1&p=2')), + Request::create('/', 'GET', array(), array(), array(), array('HTTP_REFERER' => 'http://localhost/login?t=1&p=2')), array('use_referer' => true, 'login_path' => '/login'), '/', ), + 'target path should be different than login URL (login_path as a route)' => array( + Request::create('/', 'GET', array(), array(), array(), array('HTTP_REFERER' => 'http://localhost/login?t=1&p=2')), + array('use_referer' => true, 'login_path' => 'login_route'), + '/', + ), ); } } From 535208042a6afa33c2043ab766bfcd1a2ced17ea Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Wed, 19 Jul 2017 08:45:45 +0200 Subject: [PATCH 0478/1099] document the TwigRenderer class deprecation --- UPGRADE-3.4.md | 6 ++++++ UPGRADE-4.0.md | 3 +++ 2 files changed, 9 insertions(+) diff --git a/UPGRADE-3.4.md b/UPGRADE-3.4.md index 1c3993685dde0..0e1e966d6660d 100644 --- a/UPGRADE-3.4.md +++ b/UPGRADE-3.4.md @@ -77,6 +77,12 @@ SecurityBundle * `FirewallContext::getListeners()` now returns `\Traversable|array` +TwigBridge +---------- + + * deprecated the `Symfony\Bridge\Twig\Form\TwigRenderer` class, use the `FormRenderer` + class from the Form component instead + Validator --------- diff --git a/UPGRADE-4.0.md b/UPGRADE-4.0.md index 3b11ad422f864..1a7a2542376ca 100644 --- a/UPGRADE-4.0.md +++ b/UPGRADE-4.0.md @@ -514,6 +514,9 @@ TwigBundle TwigBridge ---------- + * removed the `Symfony\Bridge\Twig\Form\TwigRenderer` class, use the `FormRenderer` + class from the Form component instead + * Removed the possibility to inject the Form `TwigRenderer` into the `FormExtension`. Upgrade Twig to `^1.30`, inject the `Twig_Environment` into the `TwigRendererEngine` and load the `TwigRenderer` using the `Twig_FactoryRuntimeLoader` instead. From fa0b9428c5c895f14f60d7f5544a29aeba725f62 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Wed, 19 Jul 2017 09:37:29 +0200 Subject: [PATCH 0479/1099] [Config] Minor fix --- .../Component/Config/Resource/ClassExistenceResource.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/Config/Resource/ClassExistenceResource.php b/src/Symfony/Component/Config/Resource/ClassExistenceResource.php index ada9a89b949e6..623124ab8d988 100644 --- a/src/Symfony/Component/Config/Resource/ClassExistenceResource.php +++ b/src/Symfony/Component/Config/Resource/ClassExistenceResource.php @@ -149,7 +149,7 @@ private static function throwOnRequiredClass($class) $props = array( 'file' => $trace[$i]['file'], 'line' => $trace[$i]['line'], - 'trace' => array_slice($trace, 0, 1 + $i), + 'trace' => array_slice($trace, 1 + $i), ); foreach ($props as $p => $v) { From 25a47d8796e584348bec48822fa351f864b5a690 Mon Sep 17 00:00:00 2001 From: Javier Eguiluz Date: Wed, 19 Jul 2017 10:54:05 +0200 Subject: [PATCH 0480/1099] Fix the design of the profiler exceptions when there is no message --- .../Resources/views/Exception/exception.html.twig | 9 ++++----- .../Bundle/TwigBundle/Resources/views/exception.css.twig | 3 ++- .../Resources/views/Collector/exception.css.twig | 5 ++++- 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/src/Symfony/Bundle/TwigBundle/Resources/views/Exception/exception.html.twig b/src/Symfony/Bundle/TwigBundle/Resources/views/Exception/exception.html.twig index 8ed5226ad5ffa..d42a9dec47c58 100644 --- a/src/Symfony/Bundle/TwigBundle/Resources/views/Exception/exception.html.twig +++ b/src/Symfony/Bundle/TwigBundle/Resources/views/Exception/exception.html.twig @@ -1,4 +1,4 @@ -
+
- {% if exception.message is not empty %} -
-
+ +
+

{{- exception.message|nl2br|format_file_from_text -}}

@@ -25,7 +25,6 @@
- {% endif %}
diff --git a/src/Symfony/Bundle/TwigBundle/Resources/views/exception.css.twig b/src/Symfony/Bundle/TwigBundle/Resources/views/exception.css.twig index ba3dd9412e266..9d03015f2f04e 100644 --- a/src/Symfony/Bundle/TwigBundle/Resources/views/exception.css.twig +++ b/src/Symfony/Bundle/TwigBundle/Resources/views/exception.css.twig @@ -79,7 +79,8 @@ header .container { display: flex; justify-content: space-between; } .exception-hierarchy .icon { margin: 0 3px; opacity: .7; } .exception-hierarchy .icon svg { height: 13px; width: 13px; vertical-align: -2px; } -.exception-message-wrapper { display: flex; align-items: flex-start; min-height: 70px; padding: 10px 0 8px; } +.exception-without-message .exception-message-wrapper { display: none; } +.exception-message-wrapper .container { display: flex; align-items: flex-start; min-height: 70px; padding: 10px 0 8px; } .exception-message { flex-grow: 1; } .exception-message, .exception-message a { color: #FFF; font-size: 21px; font-weight: 400; margin: 0; } .exception-message.long { font-size: 18px; } diff --git a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/exception.css.twig b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/exception.css.twig index 8a64ed5936473..c849cb29666ff 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/exception.css.twig +++ b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/exception.css.twig @@ -16,6 +16,9 @@ margin: 1em 0; padding: 10px; } +.exception-summary.exception-without-message { + display: none; +} .exception-message { color: #B0413E; @@ -26,6 +29,6 @@ display: none; } -.exception-message-wrapper { +.exception-message-wrapper .container { min-height: auto; } From 8a71aa31bbb1f6be8f7e507ff5273e9d775333b2 Mon Sep 17 00:00:00 2001 From: Robin Chalas Date: Mon, 17 Jul 2017 18:13:39 +0200 Subject: [PATCH 0481/1099] Fix registering lazy command services with autoconfigure enabled --- .../DependencyInjection/AddConsoleCommandPass.php | 13 ++++--------- .../Component/Console/Tests/ApplicationTest.php | 5 +++-- .../AddConsoleCommandPassTest.php | 8 +++++--- 3 files changed, 12 insertions(+), 14 deletions(-) diff --git a/src/Symfony/Component/Console/DependencyInjection/AddConsoleCommandPass.php b/src/Symfony/Component/Console/DependencyInjection/AddConsoleCommandPass.php index 1ceed91573c72..67034098c218a 100644 --- a/src/Symfony/Component/Console/DependencyInjection/AddConsoleCommandPass.php +++ b/src/Symfony/Component/Console/DependencyInjection/AddConsoleCommandPass.php @@ -70,20 +70,15 @@ public function process(ContainerBuilder $container) $serviceIds[$commandId] = false; $commandName = $tags[0]['command']; + unset($tags[0]); $lazyCommandMap[$commandName] = $id; $lazyCommandRefs[$id] = new TypedReference($id, $class); $aliases = array(); foreach ($tags as $tag) { - if (!isset($tag['command'])) { - throw new InvalidArgumentException(sprintf('Missing "command" attribute on tag "%s" for service "%s".', $this->commandTag, $id)); - } - if ($commandName !== $tag['command']) { - throw new InvalidArgumentException(sprintf('The "command" attribute must be the same on each "%s" tag for service "%s".', $this->commandTag, $id)); - } - if (isset($tag['alias'])) { - $aliases[] = $tag['alias']; - $lazyCommandMap[$tag['alias']] = $id; + if (isset($tag['command'])) { + $aliases[] = $tag['command']; + $lazyCommandMap[$tag['command']] = $id; } } diff --git a/src/Symfony/Component/Console/Tests/ApplicationTest.php b/src/Symfony/Component/Console/Tests/ApplicationTest.php index 7bf76ddc8e83d..4409d8dedf4b4 100644 --- a/src/Symfony/Component/Console/Tests/ApplicationTest.php +++ b/src/Symfony/Component/Console/Tests/ApplicationTest.php @@ -1431,8 +1431,9 @@ public function testRunLazyCommandService() $container->addCompilerPass(new AddConsoleCommandPass()); $container ->register('lazy-command', LazyCommand::class) - ->addTag('console.command', array('command' => 'lazy:command', 'alias' => 'lazy:alias')) - ->addTag('console.command', array('command' => 'lazy:command', 'alias' => 'lazy:alias2')); + ->addTag('console.command', array('command' => 'lazy:command')) + ->addTag('console.command', array('command' => 'lazy:alias')) + ->addTag('console.command', array('command' => 'lazy:alias2')); $container->compile(); $application = new Application(); diff --git a/src/Symfony/Component/Console/Tests/DependencyInjection/AddConsoleCommandPassTest.php b/src/Symfony/Component/Console/Tests/DependencyInjection/AddConsoleCommandPassTest.php index 6454dd63df8db..596d9e0d2dcc8 100644 --- a/src/Symfony/Component/Console/Tests/DependencyInjection/AddConsoleCommandPassTest.php +++ b/src/Symfony/Component/Console/Tests/DependencyInjection/AddConsoleCommandPassTest.php @@ -56,13 +56,14 @@ public function testProcess($public) $this->assertSame(array($alias => $id), $container->getParameter('console.command.ids')); } - public function testProcessRegisterLazyCommands() + public function testProcessRegistersLazyCommands() { $container = new ContainerBuilder(); - $container + $command = $container ->register('my-command', MyCommand::class) ->setPublic(false) - ->addTag('console.command', array('command' => 'my:command', 'alias' => 'my:alias')) + ->addTag('console.command', array('command' => 'my:command')) + ->addTag('console.command', array('command' => 'my:alias')) ; (new AddConsoleCommandPass())->process($container); @@ -74,6 +75,7 @@ public function testProcessRegisterLazyCommands() $this->assertSame(array('my:command' => 'my-command', 'my:alias' => 'my-command'), $commandLoader->getArgument(1)); $this->assertEquals(array(array('my-command' => new ServiceClosureArgument(new TypedReference('my-command', MyCommand::class)))), $commandLocator->getArguments()); $this->assertSame(array('console.command.symfony_component_console_tests_dependencyinjection_mycommand' => false), $container->getParameter('console.command.ids')); + $this->assertSame(array(array('setName', array('my:command')), array('setAliases', array(array('my:alias')))), $command->getMethodCalls()); } public function visibilityProvider() From 432d2deb3177059229386b421a58fd6c036e3ca9 Mon Sep 17 00:00:00 2001 From: Iltar van der Berg Date: Wed, 19 Jul 2017 14:11:33 +0200 Subject: [PATCH 0482/1099] Fixed typo in docblock --- .../Security/Core/Exception/AuthenticationExpiredException.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/Security/Core/Exception/AuthenticationExpiredException.php b/src/Symfony/Component/Security/Core/Exception/AuthenticationExpiredException.php index caf2e6cc38601..7bc174f05ce82 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-authentcated between requests. + * AuthenticationServiceException 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. From b03f0bdb0632142793fddec172c81b4b89e003ec Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Wed, 19 Jul 2017 17:17:35 +0200 Subject: [PATCH 0483/1099] [Bridge\Doctrine] Fix BC with DI v3.4 --- src/Symfony/Bridge/Doctrine/ManagerRegistry.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Bridge/Doctrine/ManagerRegistry.php b/src/Symfony/Bridge/Doctrine/ManagerRegistry.php index 6153166e79b8b..38bb2f69ddda2 100644 --- a/src/Symfony/Bridge/Doctrine/ManagerRegistry.php +++ b/src/Symfony/Bridge/Doctrine/ManagerRegistry.php @@ -49,10 +49,13 @@ protected function resetService($name) } $manager->setProxyInitializer(\Closure::bind( function (&$wrappedInstance, LazyLoadingInterface $manager) use ($name) { + if (isset($this->normalizedIds[$normalizedId = strtolower($name)])) { // BC with DI v3.4 + $name = $this->normalizedIds[$normalizedId]; + } if (isset($this->aliases[$name])) { $name = $this->aliases[$name]; } - $method = $this->methodMap[$name] ?? 'get'.$name.'Service'; + $method = $this->methodMap[$name] ?? 'get'.strtr($name, $this->underscoreMap).'Service'; // BC with DI v3.4 $wrappedInstance = $this->{$method}(false); $manager->setProxyInitializer(null); From 7ae578cc1acab2c44a6e2634cbbe59dc2518b3b5 Mon Sep 17 00:00:00 2001 From: Gavin Staniforth Date: Tue, 20 Jun 2017 16:21:01 +0100 Subject: [PATCH 0484/1099] fix(security): ensure the 'route' index is set before attempting to use it --- src/Symfony/Component/Security/Http/HttpUtils.php | 2 +- .../Component/Security/Http/Tests/HttpUtilsTest.php | 13 +++++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/Security/Http/HttpUtils.php b/src/Symfony/Component/Security/Http/HttpUtils.php index ed737a2f61695..56add79926d3e 100644 --- a/src/Symfony/Component/Security/Http/HttpUtils.php +++ b/src/Symfony/Component/Security/Http/HttpUtils.php @@ -108,7 +108,7 @@ public function checkRequestPath(Request $request, $path) $parameters = $this->urlMatcher->match($request->getPathInfo()); } - return $path === $parameters['_route']; + return isset($parameters['_route']) && $path === $parameters['_route']; } catch (MethodNotAllowedException $e) { return false; } catch (ResourceNotFoundException $e) { diff --git a/src/Symfony/Component/Security/Http/Tests/HttpUtilsTest.php b/src/Symfony/Component/Security/Http/Tests/HttpUtilsTest.php index 3d0e63b6fe1b9..b508012665e87 100644 --- a/src/Symfony/Component/Security/Http/Tests/HttpUtilsTest.php +++ b/src/Symfony/Component/Security/Http/Tests/HttpUtilsTest.php @@ -221,6 +221,19 @@ public function testCheckRequestPathWithUrlMatcherLoadingException() $utils->checkRequestPath($this->getRequest(), 'foobar'); } + public function testCheckPathWithoutRouteParam() + { + $urlMatcher = $this->getMockBuilder('Symfony\Component\Routing\Matcher\UrlMatcherInterface')->getMock(); + $urlMatcher + ->expects($this->any()) + ->method('match') + ->willReturn(array('_controller' => 'PathController')) + ; + + $utils = new HttpUtils(null, $urlMatcher); + $this->assertFalse($utils->checkRequestPath($this->getRequest(), 'path/index.html')); + } + /** * @expectedException \InvalidArgumentException * @expectedExceptionMessage Matcher must either implement UrlMatcherInterface or RequestMatcherInterface From ab91659ad6205157caf24ed5598886d64d128d06 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Wed, 19 Jul 2017 21:33:00 +0200 Subject: [PATCH 0485/1099] [PropertyInfo] Use rawurlencode to escape PSR-6 keys --- .../PropertyInfoCacheExtractor.php | 28 ++----------------- .../Tests/PropertyInfoCacheExtractorTest.php | 25 ----------------- 2 files changed, 2 insertions(+), 51 deletions(-) diff --git a/src/Symfony/Component/PropertyInfo/PropertyInfoCacheExtractor.php b/src/Symfony/Component/PropertyInfo/PropertyInfoCacheExtractor.php index 69ade35dfeeea..269b90810e217 100644 --- a/src/Symfony/Component/PropertyInfo/PropertyInfoCacheExtractor.php +++ b/src/Symfony/Component/PropertyInfo/PropertyInfoCacheExtractor.php @@ -106,7 +106,8 @@ private function extract($method, array $arguments) return call_user_func_array(array($this->propertyInfoExtractor, $method), $arguments); } - $key = $this->escape($method.'.'.$serializedArguments); + // Calling rawurlencode escapes special characters not allowed in PSR-6's keys + $key = rawurlencode($method.'.'.$serializedArguments); if (array_key_exists($key, $this->arrayCache)) { return $this->arrayCache[$key]; @@ -124,29 +125,4 @@ private function extract($method, array $arguments) return $this->arrayCache[$key] = $value; } - - /** - * Escapes a key according to PSR-6. - * - * Replaces characters forbidden by PSR-6 and the _ char by the _ char followed by the ASCII - * code of the escaped char. - * - * @param string $key - * - * @return string - */ - private function escape($key) - { - return strtr($key, array( - '{' => '_123', - '}' => '_125', - '(' => '_40', - ')' => '_41', - '/' => '_47', - '\\' => '_92', - '@' => '_64', - ':' => '_58', - '_' => '_95', - )); - } } diff --git a/src/Symfony/Component/PropertyInfo/Tests/PropertyInfoCacheExtractorTest.php b/src/Symfony/Component/PropertyInfo/Tests/PropertyInfoCacheExtractorTest.php index 455d39fa96c22..d31a7bd51ddde 100644 --- a/src/Symfony/Component/PropertyInfo/Tests/PropertyInfoCacheExtractorTest.php +++ b/src/Symfony/Component/PropertyInfo/Tests/PropertyInfoCacheExtractorTest.php @@ -61,29 +61,4 @@ public function testGetProperties() parent::testGetProperties(); parent::testGetProperties(); } - - /** - * @dataProvider escapeDataProvider - */ - public function testEscape($toEscape, $expected) - { - $reflectionMethod = new \ReflectionMethod($this->propertyInfo, 'escape'); - $reflectionMethod->setAccessible(true); - - $this->assertSame($expected, $reflectionMethod->invoke($this->propertyInfo, $toEscape)); - } - - public function escapeDataProvider() - { - return array( - array('foo_bar', 'foo_95bar'), - array('foo_95bar', 'foo_9595bar'), - array('foo{bar}', 'foo_123bar_125'), - array('foo(bar)', 'foo_40bar_41'), - array('foo/bar', 'foo_47bar'), - array('foo\bar', 'foo_92bar'), - array('foo@bar', 'foo_64bar'), - array('foo:bar', 'foo_58bar'), - ); - } } From 14c310f5fb8ee6cb0f7ae5c8c8f8aa5a894af844 Mon Sep 17 00:00:00 2001 From: Mike Francis Date: Wed, 19 Jul 2017 12:17:30 +0100 Subject: [PATCH 0486/1099] Fix case sensitive sameSite cookie --- src/Symfony/Component/HttpFoundation/Cookie.php | 4 ++++ src/Symfony/Component/HttpFoundation/Tests/CookieTest.php | 6 ++++++ 2 files changed, 10 insertions(+) diff --git a/src/Symfony/Component/HttpFoundation/Cookie.php b/src/Symfony/Component/HttpFoundation/Cookie.php index 492c6fbe75193..5ea881c6e3670 100644 --- a/src/Symfony/Component/HttpFoundation/Cookie.php +++ b/src/Symfony/Component/HttpFoundation/Cookie.php @@ -77,6 +77,10 @@ public function __construct($name, $value = null, $expire = 0, $path = '/', $dom $this->httpOnly = (bool) $httpOnly; $this->raw = (bool) $raw; + if (null !== $sameSite) { + $sameSite = strtolower($sameSite); + } + if (!in_array($sameSite, array(self::SAMESITE_LAX, self::SAMESITE_STRICT, null), true)) { throw new \InvalidArgumentException('The "sameSite" parameter value is not valid.'); } diff --git a/src/Symfony/Component/HttpFoundation/Tests/CookieTest.php b/src/Symfony/Component/HttpFoundation/Tests/CookieTest.php index 3986a7e8f8796..ad6d3f508c1ed 100644 --- a/src/Symfony/Component/HttpFoundation/Tests/CookieTest.php +++ b/src/Symfony/Component/HttpFoundation/Tests/CookieTest.php @@ -180,4 +180,10 @@ public function testRawCookie() $this->assertTrue($cookie->isRaw()); $this->assertEquals('foo=b+a+r; path=/', (string) $cookie); } + + public function testSameSiteAttributeIsCaseInsensitive() + { + $cookie = new Cookie('foo', 'bar', 0, '/', null, false, true, false, 'Lax'); + $this->assertEquals('lax', $cookie->getSameSite()); + } } From f0d0c5ffefc2363116e262a55f362647485927cc Mon Sep 17 00:00:00 2001 From: Rob Frawley 2nd Date: Fri, 7 Jul 2017 20:26:52 -0400 Subject: [PATCH 0487/1099] add (filesystem|phpfiles) cache (adapter|simple) prune method and prune command - added `Symfony\Component\Cache\PruneableInterface` so PSR-6 or PSR-16 cache implementations can declare support for manual stale cache pruning - added FilesystemTrait::prune() and PhpFilesTrait::prune() implementations - now FilesystemAdapter, PhpFilesAdapter, FilesystemCache, and PhpFilesCache implement PruneableInterface and supports manual stale cache pruning - Added `cache:pool:prune` command via `Symfony\Bundle\FrameworkBundle\Command\CachePoolPruneCommand` to allow manual stale cache item pruning of supported PSR-6 and PSR-16 cache pool implementations - Added `Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\CachePoolPrunerPass` compiler pass to fetch all cache pools implementing `PruneableInterface` and pass them to the command as an `IteratorArgument` so these references are lazy loaded by the command - updated changelogs as appropriate --- .../Bundle/FrameworkBundle/CHANGELOG.md | 2 + .../Command/CachePoolPruneCommand.php | 70 +++++++++++ .../Compiler/CachePoolPrunerPass.php | 60 ++++++++++ .../FrameworkBundle/FrameworkBundle.php | 2 + .../Resources/config/cache.xml | 5 + .../Tests/Command/CachePruneCommandTest.php | 112 ++++++++++++++++++ .../Compiler/CachePoolPrunerPassTest.php | 82 +++++++++++++ .../Bundle/FrameworkBundle/composer.json | 2 +- .../Cache/Adapter/FilesystemAdapter.php | 3 +- .../Cache/Adapter/PhpFilesAdapter.php | 3 +- src/Symfony/Component/Cache/CHANGELOG.md | 8 ++ .../Component/Cache/PruneableInterface.php | 23 ++++ .../Cache/Simple/FilesystemCache.php | 3 +- .../Component/Cache/Simple/PhpFilesCache.php | 3 +- .../Cache/Tests/Adapter/AdapterTestCase.php | 58 +++++++++ .../Tests/Adapter/FilesystemAdapterTest.php | 9 ++ .../Tests/Adapter/PhpFilesAdapterTest.php | 9 ++ .../Cache/Tests/Simple/CacheTestCase.php | 52 ++++++++ .../Tests/Simple/FilesystemCacheTest.php | 9 ++ .../Cache/Tests/Simple/PhpFilesCacheTest.php | 9 ++ .../Cache/Traits/FilesystemTrait.php | 25 ++++ .../Component/Cache/Traits/PhpFilesTrait.php | 30 +++++ 22 files changed, 574 insertions(+), 5 deletions(-) create mode 100644 src/Symfony/Bundle/FrameworkBundle/Command/CachePoolPruneCommand.php create mode 100644 src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/CachePoolPrunerPass.php create mode 100644 src/Symfony/Bundle/FrameworkBundle/Tests/Command/CachePruneCommandTest.php create mode 100644 src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/CachePoolPrunerPassTest.php create mode 100644 src/Symfony/Component/Cache/PruneableInterface.php diff --git a/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md b/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md index 2067942665051..a06afaae0a726 100644 --- a/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md +++ b/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md @@ -20,6 +20,8 @@ CHANGELOG `Symfony\Component\Translation\DependencyInjection\TranslatorPass` instead * Added `command` attribute to the `console.command` tag which takes the command name as value, using it makes the command lazy + * Added `cache:pool:prune` command to allow manual stale cache item pruning of supported PSR-6 and PSR-16 cache pool + implementations 3.3.0 ----- diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/CachePoolPruneCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/CachePoolPruneCommand.php new file mode 100644 index 0000000000000..741979bd4f501 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Command/CachePoolPruneCommand.php @@ -0,0 +1,70 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\FrameworkBundle\Command; + +use Symfony\Component\Cache\PruneableInterface; +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Style\SymfonyStyle; + +/** + * Cache pool pruner command. + * + * @author Rob Frawley 2nd + */ +final class CachePoolPruneCommand extends Command +{ + private $pools; + + /** + * @param iterable|PruneableInterface[] $pools + */ + public function __construct($pools) + { + parent::__construct(); + + $this->pools = $pools; + } + + /** + * {@inheritdoc} + */ + protected function configure() + { + $this + ->setName('cache:pool:prune') + ->setDescription('Prune cache pools') + ->setHelp(<<<'EOF' +The %command.name% command deletes all expired items from all pruneable pools. + + %command.full_name% +EOF + ) + ; + } + + /** + * {@inheritdoc} + */ + protected function execute(InputInterface $input, OutputInterface $output) + { + $io = new SymfonyStyle($input, $output); + + foreach ($this->pools as $name => $pool) { + $io->comment(sprintf('Pruning cache pool: %s', $name)); + $pool->prune(); + } + + $io->success('Successfully pruned cache pool(s).'); + } +} diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/CachePoolPrunerPass.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/CachePoolPrunerPass.php new file mode 100644 index 0000000000000..cd79f58ce84cd --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/CachePoolPrunerPass.php @@ -0,0 +1,60 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler; + +use Symfony\Component\Cache\PruneableInterface; +use Symfony\Component\DependencyInjection\Argument\IteratorArgument; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; +use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; +use Symfony\Component\DependencyInjection\Reference; + +/** + * @author Rob Frawley 2nd + */ +class CachePoolPrunerPass implements CompilerPassInterface +{ + private $cacheCommandServiceId; + private $cachePoolTag; + + public function __construct($cacheCommandServiceId = 'cache.command.pool_pruner', $cachePoolTag = 'cache.pool') + { + $this->cacheCommandServiceId = $cacheCommandServiceId; + $this->cachePoolTag = $cachePoolTag; + } + + /** + * {@inheritdoc} + */ + public function process(ContainerBuilder $container) + { + if (!$container->hasDefinition($this->cacheCommandServiceId)) { + return; + } + + $services = array(); + + foreach ($container->findTaggedServiceIds($this->cachePoolTag) as $id => $tags) { + $class = $container->getParameterBag()->resolveValue($container->getDefinition($id)->getClass()); + + if (!$reflection = $container->getReflectionClass($class)) { + throw new InvalidArgumentException(sprintf('Class "%s" used for service "%s" cannot be found.', $class, $id)); + } + + if ($reflection->implementsInterface(PruneableInterface::class)) { + $services[$id] = new Reference($id); + } + } + + $container->getDefinition($this->cacheCommandServiceId)->replaceArgument(0, new IteratorArgument($services)); + } +} diff --git a/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php b/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php index f26a78a53d906..63017892a73ef 100644 --- a/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php +++ b/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php @@ -16,6 +16,7 @@ use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\CacheCollectorPass; use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\CachePoolPass; use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\CachePoolClearerPass; +use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\CachePoolPrunerPass; use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\DataCollectorTranslatorPass; use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\TemplatingPass; use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\ProfilerPass; @@ -108,6 +109,7 @@ public function build(ContainerBuilder $container) $container->addCompilerPass(new CachePoolPass(), PassConfig::TYPE_BEFORE_OPTIMIZATION, 32); $this->addCompilerPassIfExists($container, ValidateWorkflowsPass::class); $container->addCompilerPass(new CachePoolClearerPass(), PassConfig::TYPE_AFTER_REMOVING); + $container->addCompilerPass(new CachePoolPrunerPass(), PassConfig::TYPE_AFTER_REMOVING); $this->addCompilerPassIfExists($container, FormPass::class); if ($container->getParameter('kernel.debug')) { diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/cache.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/cache.xml index e0d5788bc4879..182d07e6b3faf 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/cache.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/cache.xml @@ -100,6 +100,11 @@ + + + + + diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/CachePruneCommandTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/CachePruneCommandTest.php new file mode 100644 index 0000000000000..3477c650f7419 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/CachePruneCommandTest.php @@ -0,0 +1,112 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\FrameworkBundle\Tests\Command; + +use Symfony\Bundle\FrameworkBundle\Command\CachePoolPruneCommand; +use Symfony\Bundle\FrameworkBundle\Console\Application; +use Symfony\Bundle\FrameworkBundle\Tests\TestCase; +use Symfony\Component\Cache\PruneableInterface; +use Symfony\Component\Console\Tester\CommandTester; +use Symfony\Component\DependencyInjection\Argument\RewindableGenerator; +use Symfony\Component\HttpKernel\KernelInterface; + +class CachePruneCommandTest extends TestCase +{ + public function testCommandWithPools() + { + $tester = $this->getCommandTester($this->getKernel(), $this->getRewindableGenerator()); + $tester->execute(array()); + } + + public function testCommandWithNoPools() + { + $tester = $this->getCommandTester($this->getKernel(), $this->getEmptyRewindableGenerator()); + $tester->execute(array()); + } + + /** + * @return RewindableGenerator + */ + private function getRewindableGenerator() + { + return new RewindableGenerator(function () { + yield 'foo_pool' => $this->getPruneableInterfaceMock(); + yield 'bar_pool' => $this->getPruneableInterfaceMock(); + }, 2); + } + + /** + * @return RewindableGenerator + */ + private function getEmptyRewindableGenerator() + { + return new RewindableGenerator(function () { + return new \ArrayIterator(array()); + }, 0); + } + + /** + * @return \PHPUnit_Framework_MockObject_MockObject|KernelInterface + */ + private function getKernel() + { + $container = $this + ->getMockBuilder('Symfony\Component\DependencyInjection\ContainerInterface') + ->getMock(); + + $kernel = $this + ->getMockBuilder(KernelInterface::class) + ->getMock(); + + $kernel + ->expects($this->any()) + ->method('getContainer') + ->willReturn($container); + + $kernel + ->expects($this->once()) + ->method('getBundles') + ->willReturn(array()); + + return $kernel; + } + + /** + * @return \PHPUnit_Framework_MockObject_MockObject|PruneableInterface + */ + private function getPruneableInterfaceMock() + { + $pruneable = $this + ->getMockBuilder(PruneableInterface::class) + ->getMock(); + + $pruneable + ->expects($this->atLeastOnce()) + ->method('prune'); + + return $pruneable; + } + + /** + * @param KernelInterface $kernel + * @param RewindableGenerator $generator + * + * @return CommandTester + */ + private function getCommandTester(KernelInterface $kernel, RewindableGenerator $generator) + { + $application = new Application($kernel); + $application->add(new CachePoolPruneCommand($generator)); + + return new CommandTester($application->find('cache:pool:prune')); + } +} diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/CachePoolPrunerPassTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/CachePoolPrunerPassTest.php new file mode 100644 index 0000000000000..51dba222a3a44 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/CachePoolPrunerPassTest.php @@ -0,0 +1,82 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\Compiler; + +use PHPUnit\Framework\TestCase; +use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\CachePoolPrunerPass; +use Symfony\Component\Cache\Adapter\FilesystemAdapter; +use Symfony\Component\Cache\Adapter\PhpFilesAdapter; +use Symfony\Component\DependencyInjection\Argument\IteratorArgument; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Reference; + +class CachePoolPrunerPassTest extends TestCase +{ + public function testCompilerPassReplacesCommandArgument() + { + $container = new ContainerBuilder(); + $container->register('cache.command.pool_pruner')->addArgument(array()); + $container->register('pool.foo', FilesystemAdapter::class)->addTag('cache.pool'); + $container->register('pool.bar', PhpFilesAdapter::class)->addTag('cache.pool'); + + $pass = new CachePoolPrunerPass(); + $pass->process($container); + + $expected = array( + 'pool.foo' => new Reference('pool.foo'), + 'pool.bar' => new Reference('pool.bar'), + ); + $argument = $container->getDefinition('cache.command.pool_pruner')->getArgument(0); + + $this->assertInstanceOf(IteratorArgument::class, $argument); + $this->assertEquals($expected, $argument->getValues()); + } + + public function testCompilePassIsIgnoredIfCommandDoesNotExist() + { + $container = $this + ->getMockBuilder(ContainerBuilder::class) + ->setMethods(array('hasDefinition', 'getDefinition', 'findTaggedServiceIds')) + ->getMock(); + + $container + ->expects($this->atLeastOnce()) + ->method('hasDefinition') + ->with('cache.command.pool_pruner') + ->will($this->returnValue(false)); + + $container + ->expects($this->never()) + ->method('getDefinition'); + + $container + ->expects($this->never()) + ->method('findTaggedServiceIds'); + + $pass = new CachePoolPrunerPass(); + $pass->process($container); + } + + /** + * @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException + * @expectedExceptionMessage Class "Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\Compiler\NotFound" used for service "pool.not-found" cannot be found. + */ + public function testCompilerPassThrowsOnInvalidDefinitionClass() + { + $container = new ContainerBuilder(); + $container->register('cache.command.pool_pruner')->addArgument(array()); + $container->register('pool.not-found', NotFound::class)->addTag('cache.pool'); + + $pass = new CachePoolPrunerPass(); + $pass->process($container); + } +} diff --git a/src/Symfony/Bundle/FrameworkBundle/composer.json b/src/Symfony/Bundle/FrameworkBundle/composer.json index 955835a040972..e544cef349e61 100644 --- a/src/Symfony/Bundle/FrameworkBundle/composer.json +++ b/src/Symfony/Bundle/FrameworkBundle/composer.json @@ -18,7 +18,7 @@ "require": { "php": ">=5.5.9", "ext-xml": "*", - "symfony/cache": "~3.3|~4.0", + "symfony/cache": "~3.4|~4.0", "symfony/class-loader": "~3.2", "symfony/dependency-injection": "~3.3|~4.0", "symfony/config": "~3.3|~4.0", diff --git a/src/Symfony/Component/Cache/Adapter/FilesystemAdapter.php b/src/Symfony/Component/Cache/Adapter/FilesystemAdapter.php index a6bb335bbdc3f..d071964ec2c5c 100644 --- a/src/Symfony/Component/Cache/Adapter/FilesystemAdapter.php +++ b/src/Symfony/Component/Cache/Adapter/FilesystemAdapter.php @@ -11,9 +11,10 @@ namespace Symfony\Component\Cache\Adapter; +use Symfony\Component\Cache\PruneableInterface; use Symfony\Component\Cache\Traits\FilesystemTrait; -class FilesystemAdapter extends AbstractAdapter +class FilesystemAdapter extends AbstractAdapter implements PruneableInterface { use FilesystemTrait; diff --git a/src/Symfony/Component/Cache/Adapter/PhpFilesAdapter.php b/src/Symfony/Component/Cache/Adapter/PhpFilesAdapter.php index fee500dbfc7e2..3ce1ac7d13ab7 100644 --- a/src/Symfony/Component/Cache/Adapter/PhpFilesAdapter.php +++ b/src/Symfony/Component/Cache/Adapter/PhpFilesAdapter.php @@ -12,9 +12,10 @@ namespace Symfony\Component\Cache\Adapter; use Symfony\Component\Cache\Exception\CacheException; +use Symfony\Component\Cache\PruneableInterface; use Symfony\Component\Cache\Traits\PhpFilesTrait; -class PhpFilesAdapter extends AbstractAdapter +class PhpFilesAdapter extends AbstractAdapter implements PruneableInterface { use PhpFilesTrait; diff --git a/src/Symfony/Component/Cache/CHANGELOG.md b/src/Symfony/Component/Cache/CHANGELOG.md index 9a4a31dd83531..e8172d94988d4 100644 --- a/src/Symfony/Component/Cache/CHANGELOG.md +++ b/src/Symfony/Component/Cache/CHANGELOG.md @@ -1,6 +1,14 @@ CHANGELOG ========= +3.4.0 +----- + + * added PruneableInterface so PSR-6 or PSR-16 cache implementations can declare support for manual stale cache pruning + * added FilesystemTrait::prune() and PhpFilesTrait::prune() implementations + * now FilesystemAdapter, PhpFilesAdapter, FilesystemCache, and PhpFilesCache implement PruneableInterface and support + manual stale cache pruning + 3.3.0 ----- diff --git a/src/Symfony/Component/Cache/PruneableInterface.php b/src/Symfony/Component/Cache/PruneableInterface.php new file mode 100644 index 0000000000000..cd366adb55290 --- /dev/null +++ b/src/Symfony/Component/Cache/PruneableInterface.php @@ -0,0 +1,23 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache; + +/** + * Interface for adapters and simple cache implementations that allow pruning expired items. + */ +interface PruneableInterface +{ + /** + * @return bool + */ + public function prune(); +} diff --git a/src/Symfony/Component/Cache/Simple/FilesystemCache.php b/src/Symfony/Component/Cache/Simple/FilesystemCache.php index dac9ade9ca40e..ccd579534288e 100644 --- a/src/Symfony/Component/Cache/Simple/FilesystemCache.php +++ b/src/Symfony/Component/Cache/Simple/FilesystemCache.php @@ -11,9 +11,10 @@ namespace Symfony\Component\Cache\Simple; +use Symfony\Component\Cache\PruneableInterface; use Symfony\Component\Cache\Traits\FilesystemTrait; -class FilesystemCache extends AbstractCache +class FilesystemCache extends AbstractCache implements PruneableInterface { use FilesystemTrait; diff --git a/src/Symfony/Component/Cache/Simple/PhpFilesCache.php b/src/Symfony/Component/Cache/Simple/PhpFilesCache.php index 810b80f81275c..38a9fe3e5f18d 100644 --- a/src/Symfony/Component/Cache/Simple/PhpFilesCache.php +++ b/src/Symfony/Component/Cache/Simple/PhpFilesCache.php @@ -12,9 +12,10 @@ namespace Symfony\Component\Cache\Simple; use Symfony\Component\Cache\Exception\CacheException; +use Symfony\Component\Cache\PruneableInterface; use Symfony\Component\Cache\Traits\PhpFilesTrait; -class PhpFilesCache extends AbstractCache +class PhpFilesCache extends AbstractCache implements PruneableInterface { use PhpFilesTrait; diff --git a/src/Symfony/Component/Cache/Tests/Adapter/AdapterTestCase.php b/src/Symfony/Component/Cache/Tests/Adapter/AdapterTestCase.php index c3cbd3bef7e54..6ba02b0d158ff 100644 --- a/src/Symfony/Component/Cache/Tests/Adapter/AdapterTestCase.php +++ b/src/Symfony/Component/Cache/Tests/Adapter/AdapterTestCase.php @@ -12,6 +12,7 @@ namespace Symfony\Component\Cache\Tests\Adapter; use Cache\IntegrationTests\CachePoolTest; +use Symfony\Component\Cache\PruneableInterface; abstract class AdapterTestCase extends CachePoolTest { @@ -22,6 +23,10 @@ protected function setUp() if (!array_key_exists('testDeferredSaveWithoutCommit', $this->skippedTests) && defined('HHVM_VERSION')) { $this->skippedTests['testDeferredSaveWithoutCommit'] = 'Destructors are called late on HHVM.'; } + + if (!array_key_exists('testPrune', $this->skippedTests) && !$this->createCachePool() instanceof PruneableInterface) { + $this->skippedTests['testPrune'] = 'Not a pruneable cache pool.'; + } } public function testDefaultLifeTime() @@ -67,6 +72,59 @@ public function testNotUnserializable() } $this->assertFalse($item->isHit()); } + + public function testPrune() + { + if (isset($this->skippedTests[__FUNCTION__])) { + $this->markTestSkipped($this->skippedTests[__FUNCTION__]); + } + + if (!method_exists($this, 'isPruned')) { + $this->fail('Test classes for pruneable caches must implement `isPruned($cache, $name)` method.'); + } + + $cache = $this->createCachePool(); + + $doSet = function ($name, $value, \DateInterval $expiresAfter = null) use ($cache) { + $item = $cache->getItem($name); + $item->set($value); + + if ($expiresAfter) { + $item->expiresAfter($expiresAfter); + } + + $cache->save($item); + }; + + $doSet('foo', 'foo-val'); + $doSet('bar', 'bar-val', new \DateInterval('PT20S')); + $doSet('baz', 'baz-val', new \DateInterval('PT40S')); + $doSet('qux', 'qux-val', new \DateInterval('PT80S')); + + $cache->prune(); + $this->assertFalse($this->isPruned($cache, 'foo')); + $this->assertFalse($this->isPruned($cache, 'bar')); + $this->assertFalse($this->isPruned($cache, 'baz')); + $this->assertFalse($this->isPruned($cache, 'qux')); + + sleep(30); + $cache->prune(); + $this->assertFalse($this->isPruned($cache, 'foo')); + $this->assertTrue($this->isPruned($cache, 'bar')); + $this->assertFalse($this->isPruned($cache, 'baz')); + $this->assertFalse($this->isPruned($cache, 'qux')); + + sleep(30); + $cache->prune(); + $this->assertFalse($this->isPruned($cache, 'foo')); + $this->assertTrue($this->isPruned($cache, 'baz')); + $this->assertFalse($this->isPruned($cache, 'qux')); + + sleep(30); + $cache->prune(); + $this->assertFalse($this->isPruned($cache, 'foo')); + $this->assertTrue($this->isPruned($cache, 'qux')); + } } class NotUnserializable implements \Serializable diff --git a/src/Symfony/Component/Cache/Tests/Adapter/FilesystemAdapterTest.php b/src/Symfony/Component/Cache/Tests/Adapter/FilesystemAdapterTest.php index 68357860f24e0..b6757514eb67e 100644 --- a/src/Symfony/Component/Cache/Tests/Adapter/FilesystemAdapterTest.php +++ b/src/Symfony/Component/Cache/Tests/Adapter/FilesystemAdapterTest.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Cache\Tests\Adapter; +use Psr\Cache\CacheItemPoolInterface; use Symfony\Component\Cache\Adapter\FilesystemAdapter; /** @@ -49,4 +50,12 @@ public static function rmdir($dir) } rmdir($dir); } + + protected function isPruned(CacheItemPoolInterface $cache, $name) + { + $getFileMethod = (new \ReflectionObject($cache))->getMethod('getFile'); + $getFileMethod->setAccessible(true); + + return !file_exists($getFileMethod->invoke($cache, $name)); + } } diff --git a/src/Symfony/Component/Cache/Tests/Adapter/PhpFilesAdapterTest.php b/src/Symfony/Component/Cache/Tests/Adapter/PhpFilesAdapterTest.php index 05e312cbf7f6c..8e93c937f6a65 100644 --- a/src/Symfony/Component/Cache/Tests/Adapter/PhpFilesAdapterTest.php +++ b/src/Symfony/Component/Cache/Tests/Adapter/PhpFilesAdapterTest.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Cache\Tests\Adapter; +use Psr\Cache\CacheItemPoolInterface; use Symfony\Component\Cache\Adapter\PhpFilesAdapter; /** @@ -35,4 +36,12 @@ public static function tearDownAfterClass() { FilesystemAdapterTest::rmdir(sys_get_temp_dir().'/symfony-cache'); } + + protected function isPruned(CacheItemPoolInterface $cache, $name) + { + $getFileMethod = (new \ReflectionObject($cache))->getMethod('getFile'); + $getFileMethod->setAccessible(true); + + return !file_exists($getFileMethod->invoke($cache, $name)); + } } diff --git a/src/Symfony/Component/Cache/Tests/Simple/CacheTestCase.php b/src/Symfony/Component/Cache/Tests/Simple/CacheTestCase.php index b3799ebcda24c..600cd338be540 100644 --- a/src/Symfony/Component/Cache/Tests/Simple/CacheTestCase.php +++ b/src/Symfony/Component/Cache/Tests/Simple/CacheTestCase.php @@ -12,9 +12,19 @@ namespace Symfony\Component\Cache\Tests\Simple; use Cache\IntegrationTests\SimpleCacheTest; +use Symfony\Component\Cache\PruneableInterface; abstract class CacheTestCase extends SimpleCacheTest { + protected function setUp() + { + parent::setUp(); + + if (!array_key_exists('testPrune', $this->skippedTests) && !$this->createSimpleCache() instanceof PruneableInterface) { + $this->skippedTests['testPrune'] = 'Not a pruneable cache pool.'; + } + } + public static function validKeys() { if (defined('HHVM_VERSION')) { @@ -59,6 +69,48 @@ public function testNotUnserializable() } $this->assertNull($value); } + + public function testPrune() + { + if (isset($this->skippedTests[__FUNCTION__])) { + $this->markTestSkipped($this->skippedTests[__FUNCTION__]); + } + + if (!method_exists($this, 'isPruned')) { + $this->fail('Test classes for pruneable caches must implement `isPruned($cache, $name)` method.'); + } + + $cache = $this->createSimpleCache(); + + $cache->set('foo', 'foo-val'); + $cache->set('bar', 'bar-val', new \DateInterval('PT20S')); + $cache->set('baz', 'baz-val', new \DateInterval('PT40S')); + $cache->set('qux', 'qux-val', new \DateInterval('PT80S')); + + $cache->prune(); + $this->assertFalse($this->isPruned($cache, 'foo')); + $this->assertFalse($this->isPruned($cache, 'bar')); + $this->assertFalse($this->isPruned($cache, 'baz')); + $this->assertFalse($this->isPruned($cache, 'qux')); + + sleep(30); + $cache->prune(); + $this->assertFalse($this->isPruned($cache, 'foo')); + $this->assertTrue($this->isPruned($cache, 'bar')); + $this->assertFalse($this->isPruned($cache, 'baz')); + $this->assertFalse($this->isPruned($cache, 'qux')); + + sleep(30); + $cache->prune(); + $this->assertFalse($this->isPruned($cache, 'foo')); + $this->assertTrue($this->isPruned($cache, 'baz')); + $this->assertFalse($this->isPruned($cache, 'qux')); + + sleep(30); + $cache->prune(); + $this->assertFalse($this->isPruned($cache, 'foo')); + $this->assertTrue($this->isPruned($cache, 'qux')); + } } class NotUnserializable implements \Serializable diff --git a/src/Symfony/Component/Cache/Tests/Simple/FilesystemCacheTest.php b/src/Symfony/Component/Cache/Tests/Simple/FilesystemCacheTest.php index 0f2d519cada48..620305a58a44e 100644 --- a/src/Symfony/Component/Cache/Tests/Simple/FilesystemCacheTest.php +++ b/src/Symfony/Component/Cache/Tests/Simple/FilesystemCacheTest.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Cache\Tests\Simple; +use Psr\SimpleCache\CacheInterface; use Symfony\Component\Cache\Simple\FilesystemCache; /** @@ -22,4 +23,12 @@ public function createSimpleCache($defaultLifetime = 0) { return new FilesystemCache('', $defaultLifetime); } + + protected function isPruned(CacheInterface $cache, $name) + { + $getFileMethod = (new \ReflectionObject($cache))->getMethod('getFile'); + $getFileMethod->setAccessible(true); + + return !file_exists($getFileMethod->invoke($cache, $name)); + } } diff --git a/src/Symfony/Component/Cache/Tests/Simple/PhpFilesCacheTest.php b/src/Symfony/Component/Cache/Tests/Simple/PhpFilesCacheTest.php index 3118fcf94e2ca..7a402682ae247 100644 --- a/src/Symfony/Component/Cache/Tests/Simple/PhpFilesCacheTest.php +++ b/src/Symfony/Component/Cache/Tests/Simple/PhpFilesCacheTest.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Cache\Tests\Simple; +use Psr\SimpleCache\CacheInterface; use Symfony\Component\Cache\Simple\PhpFilesCache; /** @@ -30,4 +31,12 @@ public function createSimpleCache() return new PhpFilesCache('sf-cache'); } + + protected function isPruned(CacheInterface $cache, $name) + { + $getFileMethod = (new \ReflectionObject($cache))->getMethod('getFile'); + $getFileMethod->setAccessible(true); + + return !file_exists($getFileMethod->invoke($cache, $name)); + } } diff --git a/src/Symfony/Component/Cache/Traits/FilesystemTrait.php b/src/Symfony/Component/Cache/Traits/FilesystemTrait.php index 1db720452fff5..bcb940cb0f754 100644 --- a/src/Symfony/Component/Cache/Traits/FilesystemTrait.php +++ b/src/Symfony/Component/Cache/Traits/FilesystemTrait.php @@ -15,6 +15,7 @@ /** * @author Nicolas Grekas + * @author Rob Frawley 2nd * * @internal */ @@ -22,6 +23,30 @@ trait FilesystemTrait { use FilesystemCommonTrait; + /** + * @return bool + */ + public function prune() + { + $time = time(); + $pruned = true; + + foreach (new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($this->directory, \FilesystemIterator::SKIP_DOTS), \RecursiveIteratorIterator::LEAVES_ONLY) as $file) { + if (!$h = @fopen($file, 'rb')) { + continue; + } + + if ($time >= (int) $expiresAt = fgets($h)) { + fclose($h); + $pruned = isset($expiresAt[0]) && @unlink($file) && !file_exists($file) && $pruned; + } else { + fclose($h); + } + } + + return $pruned; + } + /** * {@inheritdoc} */ diff --git a/src/Symfony/Component/Cache/Traits/PhpFilesTrait.php b/src/Symfony/Component/Cache/Traits/PhpFilesTrait.php index 259caf0c74168..4a7c296134fc9 100644 --- a/src/Symfony/Component/Cache/Traits/PhpFilesTrait.php +++ b/src/Symfony/Component/Cache/Traits/PhpFilesTrait.php @@ -17,6 +17,7 @@ /** * @author Piotr Stankowski * @author Nicolas Grekas + * @author Rob Frawley 2nd * * @internal */ @@ -31,6 +32,35 @@ public static function isSupported() return function_exists('opcache_invalidate') && ini_get('opcache.enable'); } + /** + * @return bool + */ + public function prune() + { + $time = time(); + $pruned = true; + $allowCompile = 'cli' !== PHP_SAPI || ini_get('opcache.enable_cli'); + + set_error_handler($this->includeHandler); + try { + foreach (new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($this->directory, \FilesystemIterator::SKIP_DOTS), \RecursiveIteratorIterator::LEAVES_ONLY) as $file) { + list($expiresAt) = include $file; + + if ($time >= $expiresAt) { + $pruned = @unlink($file) && !file_exists($file) && $pruned; + + if ($allowCompile) { + @opcache_invalidate($file, true); + } + } + } + } finally { + restore_error_handler(); + } + + return $pruned; + } + /** * {@inheritdoc} */ From 178a0f73b7d3ee78c04e51fbf77b2f2bfec02f4b Mon Sep 17 00:00:00 2001 From: Ryan Weaver Date: Thu, 20 Jul 2017 19:10:01 -0400 Subject: [PATCH 0488/1099] Fixing a bug where if a core class was autowired, autowiring tried to autowire optional args as if they were required --- .../Compiler/AutowirePass.php | 6 ++++++ .../Tests/Compiler/AutowirePassTest.php | 17 +++++++++++++++++ 2 files changed, 23 insertions(+) diff --git a/src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php b/src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php index 055347b6f80f3..a59444fcac375 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php @@ -273,6 +273,12 @@ private function autowireMethod(\ReflectionFunctionAbstract $reflectionMethod, a // no default value? Then fail if (!$parameter->isDefaultValueAvailable()) { + // For core classes, isDefaultValueAvailable() can + // be false when isOptional() returns true. If the + // argument *is* optional, allow it to be missing + if ($parameter->isOptional()) { + continue; + } throw new AutowiringFailedException($this->currentId, sprintf('Cannot autowire service "%s": argument "$%s" of method "%s()" must have a type-hint or be given a value explicitly.', $this->currentId, $parameter->name, $class !== $this->currentId ? $class.'::'.$method : $method)); } diff --git a/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowirePassTest.php b/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowirePassTest.php index 76cf290283230..c78c3499c86e5 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowirePassTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowirePassTest.php @@ -512,6 +512,23 @@ public function testOptionalScalarArgsNotPassedIfLast() ); } + public function testOptionalArgsNoRequiredForCoreClasses() + { + $container = new ContainerBuilder(); + + $container->register('pdo_service', \PDO::class) + ->addArgument('sqlite:/foo.db') + ->setAutowired(true); + + (new AutowirePass())->process($container); + + $definition = $container->getDefinition('pdo_service'); + $this->assertEquals( + array('sqlite:/foo.db'), + $definition->getArguments() + ); + } + public function testSetterInjection() { $container = new ContainerBuilder(); From ef1e50802ed4af6e4d59688d4facd84925327ae6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9goire=20Pineau?= Date: Wed, 19 Jul 2017 13:44:58 +0200 Subject: [PATCH 0489/1099] [WebProfilerBundle] Display trace and context in the logger profiler --- .../views/Collector/logger.html.twig | 42 ++++++++++--------- 1 file changed, 22 insertions(+), 20 deletions(-) diff --git a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/logger.html.twig b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/logger.html.twig index 373233afa863f..6e92022a441cf 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/logger.html.twig +++ b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/logger.html.twig @@ -224,31 +224,33 @@ {% endmacro %} {% macro render_log_message(category, log_index, log) %} - {% if log.context.exception.trace is defined %} - {{ profiler_dump_log(log.message, log.context) }} - - {% set context_id = 'context-' ~ category ~ '-' ~ log_index %} + {% set has_context = log.context is defined and log.context is not empty %} + {% set has_trace = log.context.exception.trace is defined %} - - {% elseif log.context is defined and log.context is not empty %} + {% if not has_context %} + {{ profiler_dump_log(log.message) }} + {% else %} {{ profiler_dump_log(log.message, log.context) }} - {% set context_id = 'context-' ~ category ~ '-' ~ log_index %} +
+ {% set context_id = 'context-' ~ category ~ '-' ~ log_index %} + Show context -
+ +
+ {{ profiler_dump(log.context, maxDepth=1) }} +
-
- {{ profiler_dump(log.context, maxDepth=1) }} + {% if has_trace %} +
+ {{ profiler_dump(log.context.exception.trace, maxDepth=1) }}
- - {% else %} - {{ profiler_dump_log(log.message) }} + {% endif %} {% endif %} {% endmacro %} From 5441b1ad38d4a42e799cdb26d665dd8c85ac53c8 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Fri, 21 Jul 2017 12:50:19 +0200 Subject: [PATCH 0490/1099] use Precise on Travis to keep PHP LDAP support --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 42cdc02bae497..af674057da4b8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,6 @@ language: php +dist: precise sudo: false git: From ccca65b727ec9efcf02de5ab9a317bb230d87e91 Mon Sep 17 00:00:00 2001 From: Dany Maillard Date: Fri, 21 Jul 2017 14:15:00 +0200 Subject: [PATCH 0491/1099] Remove hhvm compat --- .../Component/VarDumper/Caster/DateCaster.php | 7 +------ .../VarDumper/Tests/Caster/DateCasterTest.php | 19 ++++++++----------- 2 files changed, 9 insertions(+), 17 deletions(-) diff --git a/src/Symfony/Component/VarDumper/Caster/DateCaster.php b/src/Symfony/Component/VarDumper/Caster/DateCaster.php index b96660605f55d..bca8a902d3694 100644 --- a/src/Symfony/Component/VarDumper/Caster/DateCaster.php +++ b/src/Symfony/Component/VarDumper/Caster/DateCaster.php @@ -56,14 +56,9 @@ private static function formatInterval(\DateInterval $i) .($i->y ? '%yy ' : '') .($i->m ? '%mm ' : '') .($i->d ? '%dd ' : '') + .($i->h || $i->i || $i->s || $i->f ? '%H:%I:%S.%F' : '') ; - if (\PHP_VERSION_ID >= 70100 && isset($i->f)) { - $format .= $i->h || $i->i || $i->s || $i->f ? '%H:%I:%S.%F' : ''; - } else { - $format .= $i->h || $i->i || $i->s ? '%H:%I:%S' : ''; - } - $format = '%R ' === $format ? '0s' : $format; return $i->format(rtrim($format)); diff --git a/src/Symfony/Component/VarDumper/Tests/Caster/DateCasterTest.php b/src/Symfony/Component/VarDumper/Tests/Caster/DateCasterTest.php index d5860df5e1963..627a47490c555 100644 --- a/src/Symfony/Component/VarDumper/Tests/Caster/DateCasterTest.php +++ b/src/Symfony/Component/VarDumper/Tests/Caster/DateCasterTest.php @@ -157,27 +157,24 @@ public function testCastInterval($intervalSpec, $invert, $xInterval, $xSeconds) public function provideIntervals() { - $i = new \DateInterval('PT0S'); - $ms = \PHP_VERSION_ID >= 70100 && isset($i->f) ? '.000000' : ''; - return array( array('PT0S', 0, '0s', '0s'), - array('PT1S', 0, '+ 00:00:01'.$ms, '1s'), - array('PT2M', 0, '+ 00:02:00'.$ms, '120s'), - array('PT3H', 0, '+ 03:00:00'.$ms, '10 800s'), + array('PT1S', 0, '+ 00:00:01.000000', '1s'), + array('PT2M', 0, '+ 00:02:00.000000', '120s'), + array('PT3H', 0, '+ 03:00:00.000000', '10 800s'), array('P4D', 0, '+ 4d', '345 600s'), array('P5M', 0, '+ 5m', null), array('P6Y', 0, '+ 6y', null), - array('P1Y2M3DT4H5M6S', 0, '+ 1y 2m 3d 04:05:06'.$ms, null), + array('P1Y2M3DT4H5M6S', 0, '+ 1y 2m 3d 04:05:06.000000', null), array('PT0S', 1, '0s', '0s'), - array('PT1S', 1, '- 00:00:01'.$ms, '-1s'), - array('PT2M', 1, '- 00:02:00'.$ms, '-120s'), - array('PT3H', 1, '- 03:00:00'.$ms, '-10 800s'), + array('PT1S', 1, '- 00:00:01.000000', '-1s'), + array('PT2M', 1, '- 00:02:00.000000', '-120s'), + array('PT3H', 1, '- 03:00:00.000000', '-10 800s'), array('P4D', 1, '- 4d', '-345 600s'), array('P5M', 1, '- 5m', null), array('P6Y', 1, '- 6y', null), - array('P1Y2M3DT4H5M6S', 1, '- 1y 2m 3d 04:05:06'.$ms, null), + array('P1Y2M3DT4H5M6S', 1, '- 1y 2m 3d 04:05:06.000000', null), ); } } From 5c4bfacdef92fd4ea66b67c734b7857cb7e43005 Mon Sep 17 00:00:00 2001 From: Dany Maillard Date: Wed, 19 Jul 2017 15:26:15 +0200 Subject: [PATCH 0492/1099] Add time zone caster --- .../Component/VarDumper/Caster/DateCaster.php | 11 ++ .../VarDumper/Cloner/AbstractCloner.php | 1 + .../VarDumper/Tests/Caster/DateCasterTest.php | 105 ++++++++++++++++++ src/Symfony/Component/VarDumper/composer.json | 1 + 4 files changed, 118 insertions(+) diff --git a/src/Symfony/Component/VarDumper/Caster/DateCaster.php b/src/Symfony/Component/VarDumper/Caster/DateCaster.php index b96660605f55d..5a59ca48e1e7a 100644 --- a/src/Symfony/Component/VarDumper/Caster/DateCaster.php +++ b/src/Symfony/Component/VarDumper/Caster/DateCaster.php @@ -68,4 +68,15 @@ private static function formatInterval(\DateInterval $i) return $i->format(rtrim($format)); } + + public static function castTimeZone(\DateTimeZone $timeZone, array $a, Stub $stub, $isNested, $filter) + { + $location = $timeZone->getLocation(); + $formatted = (new \Datetime('now', $timeZone))->format($location ? 'e (P)' : 'P'); + $title = $location && extension_loaded('intl') ? \Locale::getDisplayRegion('-'.$location['country_code'], \Locale::getDefault()) : ''; + + $z = array(Caster::PREFIX_VIRTUAL.'timezone' => new ConstStub($formatted, $title)); + + return $filter & Caster::EXCLUDE_VERBOSE ? $z : $z + $a; + } } diff --git a/src/Symfony/Component/VarDumper/Cloner/AbstractCloner.php b/src/Symfony/Component/VarDumper/Cloner/AbstractCloner.php index 14d76bd5ed36f..7b5093c44bff6 100644 --- a/src/Symfony/Component/VarDumper/Cloner/AbstractCloner.php +++ b/src/Symfony/Component/VarDumper/Cloner/AbstractCloner.php @@ -111,6 +111,7 @@ abstract class AbstractCloner implements ClonerInterface 'DateTimeInterface' => array('Symfony\Component\VarDumper\Caster\DateCaster', 'castDateTime'), 'DateInterval' => array('Symfony\Component\VarDumper\Caster\DateCaster', 'castInterval'), + 'DateTimeZone' => array('Symfony\Component\VarDumper\Caster\DateCaster', 'castTimeZone'), ':curl' => array('Symfony\Component\VarDumper\Caster\ResourceCaster', 'castCurl'), ':dba' => array('Symfony\Component\VarDumper\Caster\ResourceCaster', 'castDba'), diff --git a/src/Symfony/Component/VarDumper/Tests/Caster/DateCasterTest.php b/src/Symfony/Component/VarDumper/Tests/Caster/DateCasterTest.php index 637604e24dc1f..1c395e56c4290 100644 --- a/src/Symfony/Component/VarDumper/Tests/Caster/DateCasterTest.php +++ b/src/Symfony/Component/VarDumper/Tests/Caster/DateCasterTest.php @@ -184,4 +184,109 @@ public function provideIntervals() array('P1Y2M3DT4H5M6S', 1, '- 1y 2m 3d 04:05:06'.$ms, null), ); } + + /** + * @dataProvider provideTimeZones + */ + public function testDumpTimeZone($timezone, $expected) + { + if ((defined('HHVM_VERSION_ID') || PHP_VERSION_ID <= 50509) && !preg_match('/\w+\/\w+/', $timezone)) { + $this->markTestSkipped('DateTimeZone GMT offsets are supported since 5.5.10. See https://github.com/facebook/hhvm/issues/5875 for HHVM.'); + } + + $timezone = new \DateTimeZone($timezone); + + $xDump = <<assertDumpMatchesFormat($xDump, $timezone); + } + + /** + * @dataProvider provideTimeZones + */ + public function testDumpTimeZoneExcludingVerbosity($timezone, $expected) + { + if ((defined('HHVM_VERSION_ID') || PHP_VERSION_ID <= 50509) && !preg_match('/\w+\/\w+/', $timezone)) { + $this->markTestSkipped('DateTimeZone GMT offsets are supported since 5.5.10. See https://github.com/facebook/hhvm/issues/5875 for HHVM.'); + } + + $timezone = new \DateTimeZone($timezone); + + $xDump = <<assertDumpMatchesFormat($xDump, $timezone, Caster::EXCLUDE_VERBOSE); + } + + /** + * @dataProvider provideTimeZones + */ + public function testCastTimeZone($timezone, $xTimezone, $xRegion) + { + if ((defined('HHVM_VERSION_ID') || PHP_VERSION_ID <= 50509) && !preg_match('/\w+\/\w+/', $timezone)) { + $this->markTestSkipped('DateTimeZone GMT offsets are supported since 5.5.10. See https://github.com/facebook/hhvm/issues/5875 for HHVM.'); + } + + $timezone = new \DateTimeZone($timezone); + $stub = new Stub(); + + $cast = DateCaster::castTimeZone($timezone, array('foo' => 'bar'), $stub, false, Caster::EXCLUDE_VERBOSE); + + $xDump = << $xTimezone +] +EODUMP; + + $this->assertDumpMatchesFormat($xDump, $cast); + + $xDump = <<assertDumpMatchesFormat($xDump, $cast["\0~\0timezone"]); + } + + public function provideTimeZones() + { + $xRegion = extension_loaded('intl') ? '%s' : ''; + + return array( + // type 1 (UTC offset) + array('-12:00', '-12:00', ''), + array('+00:00', '+00:00', ''), + array('+14:00', '+14:00', ''), + + // type 2 (timezone abbreviation) + array('GMT', '+00:00', ''), + array('a', '+01:00', ''), + array('b', '+02:00', ''), + array('z', '+00:00', ''), + + // type 3 (timezone identifier) + array('Africa/Tunis', 'Africa/Tunis (+01:00)', $xRegion), + array('America/Panama', 'America/Panama (-05:00)', $xRegion), + array('Asia/Jerusalem', 'Asia/Jerusalem (+03:00)', $xRegion), + array('Atlantic/Canary', 'Atlantic/Canary (+01:00)', $xRegion), + array('Australia/Perth', 'Australia/Perth (+08:00)', $xRegion), + array('Europe/Zurich', 'Europe/Zurich (+02:00)', $xRegion), + array('Pacific/Tahiti', 'Pacific/Tahiti (-10:00)', $xRegion), + ); + } } diff --git a/src/Symfony/Component/VarDumper/composer.json b/src/Symfony/Component/VarDumper/composer.json index 32cf575ed4ebc..2cf287b4f2171 100644 --- a/src/Symfony/Component/VarDumper/composer.json +++ b/src/Symfony/Component/VarDumper/composer.json @@ -28,6 +28,7 @@ }, "suggest": { "ext-iconv": "To convert non-UTF-8 strings to UTF-8 (or symfony/polyfill-iconv in case ext-iconv cannot be used).", + "ext-intl": "To show region name in time zone dump", "ext-symfony_debug": "" }, "autoload": { From 164015e1fff1fe22c7fd36b443525974733e8fe2 Mon Sep 17 00:00:00 2001 From: Dany Maillard Date: Fri, 21 Jul 2017 15:54:53 +0200 Subject: [PATCH 0493/1099] Remove hhvm compat --- src/Symfony/Component/VarDumper/Caster/DateCaster.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/VarDumper/Caster/DateCaster.php b/src/Symfony/Component/VarDumper/Caster/DateCaster.php index bdfc899edd68b..bc0f8d6cf8c8a 100644 --- a/src/Symfony/Component/VarDumper/Caster/DateCaster.php +++ b/src/Symfony/Component/VarDumper/Caster/DateCaster.php @@ -68,7 +68,7 @@ public static function castTimeZone(\DateTimeZone $timeZone, array $a, Stub $stu { $location = $timeZone->getLocation(); $formatted = (new \Datetime('now', $timeZone))->format($location ? 'e (P)' : 'P'); - $title = $location && extension_loaded('intl') ? \Locale::getDisplayRegion('-'.$location['country_code'], \Locale::getDefault()) : ''; + $title = $location && extension_loaded('intl') ? \Locale::getDisplayRegion('-'.$location['country_code']) : ''; $z = array(Caster::PREFIX_VIRTUAL.'timezone' => new ConstStub($formatted, $title)); From 52e2821597fdeb32363e02301e650cf25e7785e6 Mon Sep 17 00:00:00 2001 From: David Badura Date: Fri, 21 Jul 2017 19:43:13 +0200 Subject: [PATCH 0494/1099] Router: allow HEAD method to be defined first --- .../Routing/Matcher/Dumper/PhpMatcherDumper.php | 2 +- .../Routing/Tests/Fixtures/dumper/url_matcher4.php | 11 +++++++++++ .../Tests/Matcher/Dumper/PhpMatcherDumperTest.php | 9 +++++++++ 3 files changed, 21 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/Routing/Matcher/Dumper/PhpMatcherDumper.php b/src/Symfony/Component/Routing/Matcher/Dumper/PhpMatcherDumper.php index 8eae68c4c280e..1397bac448d4d 100644 --- a/src/Symfony/Component/Routing/Matcher/Dumper/PhpMatcherDumper.php +++ b/src/Symfony/Component/Routing/Matcher/Dumper/PhpMatcherDumper.php @@ -307,7 +307,7 @@ private function compileRoute(Route $route, $name, $supportsRedirections, $paren if (in_array('GET', $methods)) { // Since we treat HEAD requests like GET requests we don't need to match it. $methodVariable = 'canonicalMethod'; - $methods = array_filter($methods, function ($method) { return 'HEAD' !== $method; }); + $methods = array_values(array_filter($methods, function ($method) { return 'HEAD' !== $method; })); } if (1 === count($methods)) { diff --git a/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher4.php b/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher4.php index b90e49af89d9c..c638dca2a5be1 100644 --- a/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher4.php +++ b/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher4.php @@ -57,6 +57,17 @@ public function match($pathinfo) } not_head_and_get: + // get_and_head + if ('/get_and_head' === $pathinfo) { + if ('GET' !== $canonicalMethod) { + $allow[] = 'GET'; + goto not_get_and_head; + } + + return array('_route' => 'get_and_head'); + } + not_get_and_head: + // post_and_head if ('/post_and_get' === $pathinfo) { if (!in_array($requestMethod, array('POST', 'HEAD'))) { diff --git a/src/Symfony/Component/Routing/Tests/Matcher/Dumper/PhpMatcherDumperTest.php b/src/Symfony/Component/Routing/Tests/Matcher/Dumper/PhpMatcherDumperTest.php index 9d4f086be7702..4fb65f4a11a47 100644 --- a/src/Symfony/Component/Routing/Tests/Matcher/Dumper/PhpMatcherDumperTest.php +++ b/src/Symfony/Component/Routing/Tests/Matcher/Dumper/PhpMatcherDumperTest.php @@ -297,6 +297,15 @@ public function getRouteCollections() array(), '', array(), + array('HEAD', 'GET') + )); + $headMatchCasesCollection->add('get_and_head', new Route( + '/get_and_head', + array(), + array(), + array(), + '', + array(), array('GET', 'HEAD') )); $headMatchCasesCollection->add('post_and_head', new Route( From 98391402d1c84857231ec0eccc79f4afab036b44 Mon Sep 17 00:00:00 2001 From: Roland Franssen Date: Sat, 15 Jul 2017 12:11:15 +0200 Subject: [PATCH 0495/1099] [TwigBundle] Commands as a service --- UPGRADE-3.4.md | 15 ++++++ UPGRADE-4.0.md | 10 ++++ src/Symfony/Bridge/Twig/CHANGELOG.md | 2 + .../Bridge/Twig/Command/DebugCommand.php | 37 ++++++++++--- .../Bridge/Twig/Command/LintCommand.php | 54 +++++++++++++------ .../Twig/Tests/Command/LintCommandTest.php | 23 ++++++-- src/Symfony/Bundle/TwigBundle/CHANGELOG.md | 6 +++ .../TwigBundle/Command/DebugCommand.php | 4 ++ .../Bundle/TwigBundle/Command/LintCommand.php | 9 +--- .../DependencyInjection/TwigExtension.php | 5 ++ .../TwigBundle/Resources/config/console.xml | 25 +++++++++ 11 files changed, 156 insertions(+), 34 deletions(-) create mode 100644 src/Symfony/Bundle/TwigBundle/Resources/config/console.xml diff --git a/UPGRADE-3.4.md b/UPGRADE-3.4.md index 0e1e966d6660d..503e74922ce41 100644 --- a/UPGRADE-3.4.md +++ b/UPGRADE-3.4.md @@ -83,6 +83,21 @@ TwigBridge * deprecated the `Symfony\Bridge\Twig\Form\TwigRenderer` class, use the `FormRenderer` class from the Form component instead + * deprecated `Symfony\Bridge\Twig\Command\DebugCommand::set/getTwigEnvironment` and the ability + to pass a command name as first argument + + * deprecated `Symfony\Bridge\Twig\Command\LintCommand::set/getTwigEnvironment` and the ability + to pass a command name as first argument + +TwigBundle +---------- + + * deprecated the `Symfony\Bundle\TwigBundle\Command\DebugCommand` class, use the `DebugCommand` + class from the Twig bridge instead + + * deprecated relying on the `ContainerAwareInterface` implementation for + `Symfony\Bundle\TwigBundle\Command\LintCommand` + Validator --------- diff --git a/UPGRADE-4.0.md b/UPGRADE-4.0.md index 1a7a2542376ca..ca1f8f10e1933 100644 --- a/UPGRADE-4.0.md +++ b/UPGRADE-4.0.md @@ -511,6 +511,10 @@ TwigBundle * The `ContainerAwareRuntimeLoader` class has been removed. Use the Twig `Twig_ContainerRuntimeLoader` class instead. + * Removed `DebugCommand` in favor of `Symfony\Bridge\Twig\Command\DebugCommand`. + + * Removed `ContainerAwareInterface` implementation in `Symfony\Bundle\TwigBundle\Command\LintCommand`. + TwigBridge ---------- @@ -550,6 +554,12 @@ TwigBridge * The `TwigRendererEngine::setEnvironment()` method has been removed. Pass the Twig Environment as second argument of the constructor instead. + + * Removed `Symfony\Bridge\Twig\Command\DebugCommand::set/getTwigEnvironment` and the ability + to pass a command name as first argument. + + * Removed `Symfony\Bridge\Twig\Command\LintCommand::set/getTwigEnvironment` and the ability + to pass a command name as first argument. Validator --------- diff --git a/src/Symfony/Bridge/Twig/CHANGELOG.md b/src/Symfony/Bridge/Twig/CHANGELOG.md index 0cd6c40e60ecc..c9cfec886177a 100644 --- a/src/Symfony/Bridge/Twig/CHANGELOG.md +++ b/src/Symfony/Bridge/Twig/CHANGELOG.md @@ -5,6 +5,8 @@ CHANGELOG ----- * deprecated `Symfony\Bridge\Twig\Form\TwigRenderer` + * deprecated `Symfony\Bridge\Twig\Command\DebugCommand::set/getTwigEnvironment` and the ability to pass a command name as first argument + * deprecated `Symfony\Bridge\Twig\Command\LintCommand::set/getTwigEnvironment` and the ability to pass a command name as first argument 3.3.0 ----- diff --git a/src/Symfony/Bridge/Twig/Command/DebugCommand.php b/src/Symfony/Bridge/Twig/Command/DebugCommand.php index e6357df51ea8e..a0239b5f42a28 100644 --- a/src/Symfony/Bridge/Twig/Command/DebugCommand.php +++ b/src/Symfony/Bridge/Twig/Command/DebugCommand.php @@ -29,15 +29,27 @@ class DebugCommand extends Command private $twig; /** - * {@inheritdoc} + * @param Environment $twig */ - public function __construct($name = 'debug:twig') + public function __construct($twig = null) { - parent::__construct($name); + parent::__construct(); + + if (!$twig instanceof Environment) { + @trigger_error(sprintf('Passing a command name as the first argument of "%s" is deprecated since version 3.4 and will be removed in 4.0. If the command was registered by convention, make it a service instead.', __METHOD__), E_USER_DEPRECATED); + + $this->setName(null === $twig ? 'debug:twig' : $twig); + + return; + } + + $this->twig = $twig; } public function setTwigEnvironment(Environment $twig) { + @trigger_error(sprintf('Method "%s" is deprecated since version 3.4 and will be removed in 4.0.', __METHOD__), E_USER_DEPRECATED); + $this->twig = $twig; } @@ -46,12 +58,15 @@ public function setTwigEnvironment(Environment $twig) */ protected function getTwigEnvironment() { + @trigger_error(sprintf('Method "%s" is deprecated since version 3.4 and will be removed in 4.0.', __METHOD__), E_USER_DEPRECATED); + return $this->twig; } protected function configure() { $this + ->setName('debug:twig') ->setDefinition(array( new InputArgument('filter', InputArgument::OPTIONAL, 'Show details for all entries matching this filter'), new InputOption('format', null, InputOption::VALUE_REQUIRED, 'The output format (text or json)', 'text'), @@ -80,9 +95,17 @@ protected function configure() protected function execute(InputInterface $input, OutputInterface $output) { $io = new SymfonyStyle($input, $output); - $twig = $this->getTwigEnvironment(); - if (null === $twig) { + // BC to be removed in 4.0 + if (__CLASS__ !== get_class($this)) { + $r = new \ReflectionMethod($this, 'getTwigEnvironment'); + if (__CLASS__ !== $r->getDeclaringClass()->getName()) { + @trigger_error(sprintf('Usage of method "%s" is deprecated since version 3.4 and will no longer be supported in 4.0.', get_class($this).'::getTwigEnvironment'), E_USER_DEPRECATED); + + $this->twig = $this->getTwigEnvironment(); + } + } + if (null === $this->twig) { throw new \RuntimeException('The Twig environment needs to be set.'); } @@ -91,7 +114,7 @@ protected function execute(InputInterface $input, OutputInterface $output) if ($input->getOption('format') === 'json') { $data = array(); foreach ($types as $type) { - foreach ($twig->{'get'.ucfirst($type)}() as $name => $entity) { + foreach ($this->twig->{'get'.ucfirst($type)}() as $name => $entity) { $data[$type][$name] = $this->getMetadata($type, $entity); } } @@ -105,7 +128,7 @@ protected function execute(InputInterface $input, OutputInterface $output) foreach ($types as $index => $type) { $items = array(); - foreach ($twig->{'get'.ucfirst($type)}() as $name => $entity) { + foreach ($this->twig->{'get'.ucfirst($type)}() as $name => $entity) { if (!$filter || false !== strpos($name, $filter)) { $items[$name] = $name.$this->getPrettyMetadata($type, $entity); } diff --git a/src/Symfony/Bridge/Twig/Command/LintCommand.php b/src/Symfony/Bridge/Twig/Command/LintCommand.php index 01857fc1af08d..c9eac4de6058e 100644 --- a/src/Symfony/Bridge/Twig/Command/LintCommand.php +++ b/src/Symfony/Bridge/Twig/Command/LintCommand.php @@ -34,15 +34,27 @@ class LintCommand extends Command private $twig; /** - * {@inheritdoc} + * @param Environment $twig */ - public function __construct($name = 'lint:twig') + public function __construct($twig = null) { - parent::__construct($name); + parent::__construct(); + + if (!$twig instanceof Environment) { + @trigger_error(sprintf('Passing a command name as the first argument of "%s" is deprecated since version 3.4 and will be removed in 4.0. If the command was registered by convention, make it a service instead.', __METHOD__), E_USER_DEPRECATED); + + $this->setName(null === $twig ? 'lint:twig' : $twig); + + return; + } + + $this->twig = $twig; } public function setTwigEnvironment(Environment $twig) { + @trigger_error(sprintf('Method "%s" is deprecated since version 3.4 and will be removed in 4.0.', __METHOD__), E_USER_DEPRECATED); + $this->twig = $twig; } @@ -51,12 +63,15 @@ public function setTwigEnvironment(Environment $twig) */ protected function getTwigEnvironment() { + @trigger_error(sprintf('Method "%s" is deprecated since version 3.4 and will be removed in 4.0.', __METHOD__), E_USER_DEPRECATED); + return $this->twig; } protected function configure() { $this + ->setName('lint:twig') ->setDescription('Lints a template and outputs encountered errors') ->addOption('format', null, InputOption::VALUE_REQUIRED, 'The output format', 'txt') ->addArgument('filename', InputArgument::IS_ARRAY) @@ -86,7 +101,16 @@ protected function execute(InputInterface $input, OutputInterface $output) { $io = new SymfonyStyle($input, $output); - if (null === $twig = $this->getTwigEnvironment()) { + // BC to be removed in 4.0 + if (__CLASS__ !== get_class($this)) { + $r = new \ReflectionMethod($this, 'getTwigEnvironment'); + if (__CLASS__ !== $r->getDeclaringClass()->getName()) { + @trigger_error(sprintf('Usage of method "%s" is deprecated since version 3.4 and will no longer be supported in 4.0.', get_class($this).'::getTwigEnvironment'), E_USER_DEPRECATED); + + $this->twig = $this->getTwigEnvironment(); + } + } + if (null === $this->twig) { throw new \RuntimeException('The Twig environment needs to be set.'); } @@ -102,20 +126,20 @@ protected function execute(InputInterface $input, OutputInterface $output) $template .= fread(STDIN, 1024); } - return $this->display($input, $output, $io, array($this->validate($twig, $template, uniqid('sf_', true)))); + return $this->display($input, $output, $io, array($this->validate($template, uniqid('sf_', true)))); } - $filesInfo = $this->getFilesInfo($twig, $filenames); + $filesInfo = $this->getFilesInfo($filenames); return $this->display($input, $output, $io, $filesInfo); } - private function getFilesInfo(Environment $twig, array $filenames) + private function getFilesInfo(array $filenames) { $filesInfo = array(); foreach ($filenames as $filename) { foreach ($this->findFiles($filename) as $file) { - $filesInfo[] = $this->validate($twig, file_get_contents($file), $file); + $filesInfo[] = $this->validate(file_get_contents($file), $file); } } @@ -133,17 +157,17 @@ protected function findFiles($filename) throw new \RuntimeException(sprintf('File or directory "%s" is not readable', $filename)); } - private function validate(Environment $twig, $template, $file) + private function validate($template, $file) { - $realLoader = $twig->getLoader(); + $realLoader = $this->twig->getLoader(); try { $temporaryLoader = new ArrayLoader(array((string) $file => $template)); - $twig->setLoader($temporaryLoader); - $nodeTree = $twig->parse($twig->tokenize(new Source($template, (string) $file))); - $twig->compile($nodeTree); - $twig->setLoader($realLoader); + $this->twig->setLoader($temporaryLoader); + $nodeTree = $this->twig->parse($this->twig->tokenize(new Source($template, (string) $file))); + $this->twig->compile($nodeTree); + $this->twig->setLoader($realLoader); } catch (Error $e) { - $twig->setLoader($realLoader); + $this->twig->setLoader($realLoader); return array('template' => $template, 'file' => $file, 'line' => $e->getTemplateLine(), 'valid' => false, 'exception' => $e); } diff --git a/src/Symfony/Bridge/Twig/Tests/Command/LintCommandTest.php b/src/Symfony/Bridge/Twig/Tests/Command/LintCommandTest.php index ef7698c39c83e..db87d6e131fdb 100644 --- a/src/Symfony/Bridge/Twig/Tests/Command/LintCommandTest.php +++ b/src/Symfony/Bridge/Twig/Tests/Command/LintCommandTest.php @@ -68,15 +68,30 @@ public function testLintFileCompileTimeException() $this->assertRegExp('/ERROR in \S+ \(line /', trim($tester->getDisplay())); } + /** + * @group legacy + * @expectedDeprecation Passing a command name as the first argument of "Symfony\Bridge\Twig\Command\LintCommand::__construct" is deprecated since version 3.4 and will be removed in 4.0. If the command was registered by convention, make it a service instead. + * @expectedException \RuntimeException + * @expectedExceptionMessage The Twig environment needs to be set. + */ + public function testLegacyLintCommand() + { + $command = new LintCommand(); + + $application = new Application(); + $application->add($command); + $command = $application->find('lint:twig'); + + $tester = new CommandTester($command); + $tester->execute(array()); + } + /** * @return CommandTester */ private function createCommandTester() { - $twig = new Environment(new FilesystemLoader()); - - $command = new LintCommand(); - $command->setTwigEnvironment($twig); + $command = new LintCommand(new Environment(new FilesystemLoader())); $application = new Application(); $application->add($command); diff --git a/src/Symfony/Bundle/TwigBundle/CHANGELOG.md b/src/Symfony/Bundle/TwigBundle/CHANGELOG.md index 9f666dbc29dd7..58a6a7229653d 100644 --- a/src/Symfony/Bundle/TwigBundle/CHANGELOG.md +++ b/src/Symfony/Bundle/TwigBundle/CHANGELOG.md @@ -1,6 +1,12 @@ CHANGELOG ========= +3.4.0 +----- + + * deprecated `Symfony\Bundle\TwigBundle\Command\DebugCommand`, use `Symfony\Bridge\Twig\Command\DebugCommand` instead + * deprecated relying on the `ContainerAwareInterface` implementation for `Symfony\Bundle\TwigBundle\Command\LintCommand` + 3.3.0 ----- diff --git a/src/Symfony/Bundle/TwigBundle/Command/DebugCommand.php b/src/Symfony/Bundle/TwigBundle/Command/DebugCommand.php index e2f25cc22ed19..de943d2bed76a 100644 --- a/src/Symfony/Bundle/TwigBundle/Command/DebugCommand.php +++ b/src/Symfony/Bundle/TwigBundle/Command/DebugCommand.php @@ -11,6 +11,8 @@ namespace Symfony\Bundle\TwigBundle\Command; +@trigger_error(sprintf('The %s class is deprecated since version 3.4 and will be removed in 4.0. Use Symfony\Bridge\Twig\Command\DebugCommand instead.', DebugCommand::class), E_USER_DEPRECATED); + use Symfony\Bridge\Twig\Command\DebugCommand as BaseDebugCommand; use Symfony\Component\DependencyInjection\ContainerAwareInterface; use Symfony\Component\DependencyInjection\ContainerAwareTrait; @@ -19,6 +21,8 @@ * Lists twig functions, filters, globals and tests present in the current project. * * @author Jordi Boggiano + * + * @deprecated since version 3.4, to be removed in 4.0. */ final class DebugCommand extends BaseDebugCommand implements ContainerAwareInterface { diff --git a/src/Symfony/Bundle/TwigBundle/Command/LintCommand.php b/src/Symfony/Bundle/TwigBundle/Command/LintCommand.php index b6cbb6be7a29b..1474a4de0a3f5 100644 --- a/src/Symfony/Bundle/TwigBundle/Command/LintCommand.php +++ b/src/Symfony/Bundle/TwigBundle/Command/LintCommand.php @@ -24,16 +24,9 @@ */ final class LintCommand extends BaseLintCommand implements ContainerAwareInterface { + // BC to be removed in 4.0 use ContainerAwareTrait; - /** - * {@inheritdoc} - */ - protected function getTwigEnvironment() - { - return $this->container->get('twig'); - } - /** * {@inheritdoc} */ diff --git a/src/Symfony/Bundle/TwigBundle/DependencyInjection/TwigExtension.php b/src/Symfony/Bundle/TwigBundle/DependencyInjection/TwigExtension.php index 09daf1322f307..b3cde40b6f14e 100644 --- a/src/Symfony/Bundle/TwigBundle/DependencyInjection/TwigExtension.php +++ b/src/Symfony/Bundle/TwigBundle/DependencyInjection/TwigExtension.php @@ -13,6 +13,7 @@ use Symfony\Bridge\Twig\Extension\WebLinkExtension; use Symfony\Component\Config\FileLocator; +use Symfony\Component\Console\Application; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\DependencyInjection\Loader\XmlFileLoader; @@ -49,6 +50,10 @@ public function load(array $configs, ContainerBuilder $container) $loader->load('templating.xml'); } + if (class_exists(Application::class)) { + $loader->load('console.xml'); + } + if (!interface_exists('Symfony\Component\Translation\TranslatorInterface')) { $container->removeDefinition('twig.translation.extractor'); } diff --git a/src/Symfony/Bundle/TwigBundle/Resources/config/console.xml b/src/Symfony/Bundle/TwigBundle/Resources/config/console.xml new file mode 100644 index 0000000000000..92347d699c1b1 --- /dev/null +++ b/src/Symfony/Bundle/TwigBundle/Resources/config/console.xml @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + + + + + + + The "%service_id%" service is deprecated since Symfony 3.4 and will be removed in 4.0. Use "twig.command.debug" instead. + + + From 1ba95738fb3cc240acb98f2a2e3391759dbf2034 Mon Sep 17 00:00:00 2001 From: Christopher Parotat Date: Sat, 22 Jul 2017 01:40:13 +0200 Subject: [PATCH 0496/1099] [Validator] Fix IbanValidator for ukrainian IBANs The ukrainian bank identifier consists of six digits and not letters. Also fix the broken links to the current SWIFT IBAN registry pdf. --- .../Component/Validator/Constraints/IbanValidator.php | 4 ++-- .../Validator/Tests/Constraints/IbanValidatorTest.php | 5 ++++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Component/Validator/Constraints/IbanValidator.php b/src/Symfony/Component/Validator/Constraints/IbanValidator.php index ae4eb112b744c..20300b00abf77 100644 --- a/src/Symfony/Component/Validator/Constraints/IbanValidator.php +++ b/src/Symfony/Component/Validator/Constraints/IbanValidator.php @@ -34,7 +34,7 @@ class IbanValidator extends ConstraintValidator * a BBAN (Basic Bank Account Number) which has a fixed length per country and, * included within it, a bank identifier with a fixed position and a fixed length per country * - * @see http://www.swift.com/dsp/resources/documents/IBAN_Registry.pdf + * @see https://www.swift.com/sites/default/files/resources/iban_registry.pdf * * @var array */ @@ -130,7 +130,7 @@ class IbanValidator extends ConstraintValidator 'TL' => 'TL\d{2}\d{3}\d{14}\d{2}', // Timor-Leste 'TN' => 'TN59\d{2}\d{3}\d{13}\d{2}', // Tunisia 'TR' => 'TR\d{2}\d{5}[\dA-Z]{1}[\dA-Z]{16}', // Turkey - 'UA' => 'UA\d{2}[A-Z]{6}[\dA-Z]{19}', // Ukraine + 'UA' => 'UA\d{2}\d{6}[\dA-Z]{19}', // Ukraine 'VG' => 'VG\d{2}[A-Z]{4}\d{16}', // Virgin Islands, British 'WF' => 'FR\d{2}\d{5}\d{5}[\dA-Z]{11}\d{2}', // Wallis and Futuna Islands 'XK' => 'XK\d{2}\d{4}\d{10}\d{2}', // Republic of Kosovo diff --git a/src/Symfony/Component/Validator/Tests/Constraints/IbanValidatorTest.php b/src/Symfony/Component/Validator/Tests/Constraints/IbanValidatorTest.php index e9deb11de4943..f16dafd827361 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/IbanValidatorTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/IbanValidatorTest.php @@ -118,7 +118,7 @@ public function getValidIbans() //Extended country list //http://www.nordea.com/Our+services/International+products+and+services/Cash+Management/IBAN+countries/908462.html - // http://www.swift.com/dsp/resources/documents/IBAN_Registry.pdf + // https://www.swift.com/sites/default/files/resources/iban_registry.pdf array('AO06000600000100037131174'), //Angola array('AZ21NABZ00000000137010001944'), //Azerbaijan array('BH29BMAG1299123456BH00'), //Bahrain @@ -156,6 +156,7 @@ public function getValidIbans() array('TL380080012345678910157'), //Timor-Leste array('TN5914207207100707129648'), //Tunisia array('TR330006100519786457841326'), //Turkey + array('UA213223130000026007233566001'), //Ukraine array('AE260211000000230064016'), //United Arab Emirates ); } @@ -268,6 +269,7 @@ public function getIbansWithInvalidFormat() array('TL3800800123456789101571'), //Timor-Leste array('TN59142072071007071296481'), //Tunisia array('TR3300061005197864578413261'), //Turkey + array('UA21AAAA1300000260072335660012'), //Ukraine array('AE2602110000002300640161'), //United Arab Emirates ); } @@ -377,6 +379,7 @@ public function getIbansWithValidFormatButIncorrectChecksum() array('TL380080012345678910158'), //Timor-Leste array('TN5914207207100707129649'), //Tunisia array('TR330006100519786457841327'), //Turkey + array('UA213223130000026007233566002'), //Ukraine array('AE260211000000230064017'), //United Arab Emirates ); } From 7816f3b7c700d2e90b6d23d023fd63e685a5e6ff Mon Sep 17 00:00:00 2001 From: Valentin Date: Thu, 1 Jun 2017 23:44:40 +0300 Subject: [PATCH 0497/1099] [DoctrineBridge][PropertyInfo] Added support for Doctrine Embeddables --- .../PropertyInfo/DoctrineExtractor.php | 16 ++++++++- .../PropertyInfo/DoctrineExtractorTest.php | 36 +++++++++++++++++++ .../Fixtures/DoctrineEmbeddable.php | 28 +++++++++++++++ .../Fixtures/DoctrineWithEmbedded.php | 36 +++++++++++++++++++ 4 files changed, 115 insertions(+), 1 deletion(-) create mode 100644 src/Symfony/Bridge/Doctrine/Tests/PropertyInfo/Fixtures/DoctrineEmbeddable.php create mode 100644 src/Symfony/Bridge/Doctrine/Tests/PropertyInfo/Fixtures/DoctrineWithEmbedded.php diff --git a/src/Symfony/Bridge/Doctrine/PropertyInfo/DoctrineExtractor.php b/src/Symfony/Bridge/Doctrine/PropertyInfo/DoctrineExtractor.php index aba31792f99ee..200cc582d414a 100644 --- a/src/Symfony/Bridge/Doctrine/PropertyInfo/DoctrineExtractor.php +++ b/src/Symfony/Bridge/Doctrine/PropertyInfo/DoctrineExtractor.php @@ -50,7 +50,17 @@ public function getProperties($class, array $context = array()) return; } - return array_merge($metadata->getFieldNames(), $metadata->getAssociationNames()); + $properties = array_merge($metadata->getFieldNames(), $metadata->getAssociationNames()); + + if ($metadata instanceof ClassMetadataInfo && class_exists('Doctrine\ORM\Mapping\Embedded') && $metadata->embeddedClasses) { + $properties = array_filter($properties, function ($property) { + return false === strpos($property, '.'); + }); + + $properties = array_merge($properties, array_keys($metadata->embeddedClasses)); + } + + return $properties; } /** @@ -105,6 +115,10 @@ public function getTypes($class, $property, array $context = array()) )); } + if ($metadata instanceof ClassMetadataInfo && class_exists('Doctrine\ORM\Mapping\Embedded') && isset($metadata->embeddedClasses[$property])) { + return array(new Type(Type::BUILTIN_TYPE_OBJECT, false, $metadata->embeddedClasses[$property]['class'])); + } + if ($metadata->hasField($property)) { $typeOfField = $metadata->getTypeOfField($property); $nullable = $metadata instanceof ClassMetadataInfo && $metadata->isNullable($property); diff --git a/src/Symfony/Bridge/Doctrine/Tests/PropertyInfo/DoctrineExtractorTest.php b/src/Symfony/Bridge/Doctrine/Tests/PropertyInfo/DoctrineExtractorTest.php index 2224517db6708..ecbfbbe32c865 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/PropertyInfo/DoctrineExtractorTest.php +++ b/src/Symfony/Bridge/Doctrine/Tests/PropertyInfo/DoctrineExtractorTest.php @@ -62,6 +62,21 @@ public function testGetProperties() ); } + public function testGetPropertiesWithEmbedded() + { + if (!class_exists('Doctrine\ORM\Mapping\Embedded')) { + $this->markTestSkipped('@Embedded is not available in Doctrine ORM lower than 2.5.'); + } + + $this->assertEquals( + array( + 'id', + 'embedded', + ), + $this->extractor->getProperties('Symfony\Bridge\Doctrine\Tests\PropertyInfo\Fixtures\DoctrineWithEmbedded') + ); + } + /** * @dataProvider typesProvider */ @@ -70,6 +85,27 @@ public function testExtract($property, array $type = null) $this->assertEquals($type, $this->extractor->getTypes('Symfony\Bridge\Doctrine\Tests\PropertyInfo\Fixtures\DoctrineDummy', $property, array())); } + public function testExtractWithEmbedded() + { + if (!class_exists('Doctrine\ORM\Mapping\Embedded')) { + $this->markTestSkipped('@Embedded is not available in Doctrine ORM lower than 2.5.'); + } + + $expectedTypes = array(new Type( + Type::BUILTIN_TYPE_OBJECT, + false, + 'Symfony\Bridge\Doctrine\Tests\PropertyInfo\Fixtures\DoctrineEmbeddable' + )); + + $actualTypes = $this->extractor->getTypes( + 'Symfony\Bridge\Doctrine\Tests\PropertyInfo\Fixtures\DoctrineWithEmbedded', + 'embedded', + array() + ); + + $this->assertEquals($expectedTypes, $actualTypes); + } + public function typesProvider() { return array( diff --git a/src/Symfony/Bridge/Doctrine/Tests/PropertyInfo/Fixtures/DoctrineEmbeddable.php b/src/Symfony/Bridge/Doctrine/Tests/PropertyInfo/Fixtures/DoctrineEmbeddable.php new file mode 100644 index 0000000000000..a00856ed7331e --- /dev/null +++ b/src/Symfony/Bridge/Doctrine/Tests/PropertyInfo/Fixtures/DoctrineEmbeddable.php @@ -0,0 +1,28 @@ + + * + * 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\Embeddable; + +/** + * @Embeddable + * + * @author Udaltsov Valentin + */ +class DoctrineEmbeddable +{ + /** + * @Column(type="string") + */ + protected $field; +} diff --git a/src/Symfony/Bridge/Doctrine/Tests/PropertyInfo/Fixtures/DoctrineWithEmbedded.php b/src/Symfony/Bridge/Doctrine/Tests/PropertyInfo/Fixtures/DoctrineWithEmbedded.php new file mode 100644 index 0000000000000..a1e011338f0b0 --- /dev/null +++ b/src/Symfony/Bridge/Doctrine/Tests/PropertyInfo/Fixtures/DoctrineWithEmbedded.php @@ -0,0 +1,36 @@ + + * + * 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\Embedded; + +/** + * @Entity + * + * @author Udaltsov Valentin + */ +class DoctrineWithEmbedded +{ + /** + * @Id + * @Column(type="smallint") + */ + public $id; + + /** + * @Embedded(class="DoctrineEmbeddable") + */ + protected $embedded; +} From 76951126013abbd5dc36af43aaa0185f8318a265 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Thu, 20 Jul 2017 19:25:39 +0200 Subject: [PATCH 0498/1099] feature #22317 [Console] Make SymfonyQuestionHelper::ask optional by default (ro0NL) This PR was merged into the 4.0-dev branch. Discussion ---------- [Console] Make SymfonyQuestionHelper::ask optional by default | Q | A | ------------- | --- | Branch? | master | Bug fix? | no | New feature? | yes | BC breaks? | no | Deprecations? | yes | Tests pass? | yes (nothing in core depends on it) | Fixed tickets | #... | License | MIT | Doc PR | symfony/symfony-docs#... i noticed when writing commands i always keep doing ```php $io = new SymfonyStyle($input, $output); $answer = $io->ask('...', null, function ($value) { return $value; }); // instead of just $answer = $io->ask('...'); ``` only to bypass a built-in validation, of which im not sure why it's there. Note the base question helper doesnt make this assumption... Commits ------- 2da429cd0a [Console] Make SymfonyQuestionHelper::ask optional by default --- UPGRADE-3.3.md | 2 ++ UPGRADE-4.0.md | 2 ++ .../Bundle/WebServerBundle/Command/ServerStartCommand.php | 2 +- src/Symfony/Component/Console/CHANGELOG.md | 1 + .../Component/Console/Helper/SymfonyQuestionHelper.php | 4 ++++ 5 files changed, 10 insertions(+), 1 deletion(-) diff --git a/UPGRADE-3.3.md b/UPGRADE-3.3.md index b8d2524654386..7f61c71f57de4 100644 --- a/UPGRADE-3.3.md +++ b/UPGRADE-3.3.md @@ -72,6 +72,8 @@ Console have been deprecated in favor of the `console.error` event and the `ConsoleErrorEvent` class. The deprecated event and class will be removed in 4.0. + * The `SymfonyQuestionHelper::ask` default validation has been deprecated and will be removed in 4.0. Apply validation using `Question::setValidator` instead. + Debug ----- diff --git a/UPGRADE-4.0.md b/UPGRADE-4.0.md index ca1f8f10e1933..32248ac4e0855 100644 --- a/UPGRADE-4.0.md +++ b/UPGRADE-4.0.md @@ -61,6 +61,8 @@ Console * The `console.exception` event and the related `ConsoleExceptionEvent` class have been removed in favor of the `console.error` event and the `ConsoleErrorEvent` class. + * The `SymfonyQuestionHelper::ask` default validation has been removed in favor of `Question::setValidator`. + Debug ----- diff --git a/src/Symfony/Bundle/WebServerBundle/Command/ServerStartCommand.php b/src/Symfony/Bundle/WebServerBundle/Command/ServerStartCommand.php index 57de788608547..af90a53f32c99 100644 --- a/src/Symfony/Bundle/WebServerBundle/Command/ServerStartCommand.php +++ b/src/Symfony/Bundle/WebServerBundle/Command/ServerStartCommand.php @@ -93,7 +93,7 @@ protected function execute(InputInterface $input, OutputInterface $output) 'You can either install it or use the "server:run" command instead.', )); - if ($io->ask('Do you want to execute server:run immediately? [yN] ', false)) { + if ($io->confirm('Do you want to execute server:run immediately?', false)) { return $this->getApplication()->find('server:run')->run($input, $output); } diff --git a/src/Symfony/Component/Console/CHANGELOG.md b/src/Symfony/Component/Console/CHANGELOG.md index b337ecf992f4d..616f70e137c0c 100644 --- a/src/Symfony/Component/Console/CHANGELOG.md +++ b/src/Symfony/Component/Console/CHANGELOG.md @@ -18,6 +18,7 @@ CHANGELOG * deprecated console.exception event in favor of console.error * added ability to handle `CommandNotFoundException` through the `console.error` event +* deprecated default validation in `SymfonyQuestionHelper::ask` 3.2.0 ------ diff --git a/src/Symfony/Component/Console/Helper/SymfonyQuestionHelper.php b/src/Symfony/Component/Console/Helper/SymfonyQuestionHelper.php index 25e094a04f45c..cf071d594d44a 100644 --- a/src/Symfony/Component/Console/Helper/SymfonyQuestionHelper.php +++ b/src/Symfony/Component/Console/Helper/SymfonyQuestionHelper.php @@ -29,6 +29,8 @@ class SymfonyQuestionHelper extends QuestionHelper { /** * {@inheritdoc} + * + * To be removed in 4.0 */ public function ask(InputInterface $input, OutputInterface $output, Question $question) { @@ -39,6 +41,8 @@ public function ask(InputInterface $input, OutputInterface $output, Question $qu } else { // make required if (!is_array($value) && !is_bool($value) && 0 === strlen($value)) { + @trigger_error('The default question validator is deprecated since Symfony 3.3 and will not be used anymore in version 4.0. Set a custom question validator if needed.', E_USER_DEPRECATED); + throw new LogicException('A value is required.'); } } From 445c56aa3ea152ae51906782abbf76ff707a02db Mon Sep 17 00:00:00 2001 From: Roland Franssen Date: Sat, 22 Jul 2017 20:45:32 +0200 Subject: [PATCH 0499/1099] Remove unused mocks/vars --- .../FrameworkBundle/Tests/Command/RouterDebugCommandTest.php | 4 ---- .../FrameworkBundle/Tests/Command/RouterMatchCommandTest.php | 4 ---- .../Tests/Functional/ConfigDebugCommandTest.php | 2 +- 3 files changed, 1 insertion(+), 9 deletions(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/RouterDebugCommandTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/RouterDebugCommandTest.php index 597082485a0b6..a8ef3cd421c9c 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/RouterDebugCommandTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/RouterDebugCommandTest.php @@ -71,10 +71,6 @@ private function getKernel() ->will($this->returnValue($routeCollection)) ; - $loader = $this->getMockBuilder('Symfony\Bundle\FrameworkBundle\Routing\DelegatingLoader') - ->disableOriginalConstructor() - ->getMock(); - $container = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerInterface')->getMock(); $container ->expects($this->once()) diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/RouterMatchCommandTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/RouterMatchCommandTest.php index 384bd7ca53079..fe77fa5703465 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/RouterMatchCommandTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/RouterMatchCommandTest.php @@ -70,10 +70,6 @@ private function getKernel() ->will($this->returnValue($requestContext)) ; - $loader = $this->getMockBuilder('Symfony\Bundle\FrameworkBundle\Routing\DelegatingLoader') - ->disableOriginalConstructor() - ->getMock(); - $container = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerInterface')->getMock(); $container ->expects($this->atLeastOnce()) diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/ConfigDebugCommandTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/ConfigDebugCommandTest.php index 5b40325e08eb9..a98879938d13e 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/ConfigDebugCommandTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/ConfigDebugCommandTest.php @@ -61,7 +61,7 @@ public function testParametersValuesAreResolved() public function testDumpUndefinedBundleOption() { $tester = $this->createCommandTester(); - $ret = $tester->execute(array('name' => 'TestBundle', 'path' => 'foo')); + $tester->execute(array('name' => 'TestBundle', 'path' => 'foo')); $this->assertContains('Unable to find configuration for "test.foo"', $tester->getDisplay()); } From 07ff4dd163486baade30b767a5d56d84e7540b31 Mon Sep 17 00:00:00 2001 From: Roland Franssen Date: Sat, 22 Jul 2017 20:52:59 +0200 Subject: [PATCH 0500/1099] Remove unused prop + added @deprecated --- .../Tests/Functional/CachePoolClearCommandTest.php | 2 -- .../SecurityBundle/Command/UserPasswordEncoderCommand.php | 2 ++ 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/CachePoolClearCommandTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/CachePoolClearCommandTest.php index 59949dfdfda9b..c4ea8e3974e51 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/CachePoolClearCommandTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/CachePoolClearCommandTest.php @@ -19,8 +19,6 @@ */ class CachePoolClearCommandTest extends WebTestCase { - private $application; - protected function setUp() { static::bootKernel(array('test_case' => 'CachePoolClear', 'root_config' => 'config.yml')); diff --git a/src/Symfony/Bundle/SecurityBundle/Command/UserPasswordEncoderCommand.php b/src/Symfony/Bundle/SecurityBundle/Command/UserPasswordEncoderCommand.php index 6c3f0327491c4..2e1fc2ef50103 100644 --- a/src/Symfony/Bundle/SecurityBundle/Command/UserPasswordEncoderCommand.php +++ b/src/Symfony/Bundle/SecurityBundle/Command/UserPasswordEncoderCommand.php @@ -48,6 +48,8 @@ public function __construct(EncoderFactoryInterface $encoderFactory = null, arra /** * {@inheritdoc} + * + * @deprecated since version 3.3, to be removed in 4.0 */ protected function getContainer() { From cccc88f738b64d09739bb6a4365855827c63f16b Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Fri, 21 Jul 2017 14:42:57 +0200 Subject: [PATCH 0501/1099] [Cache] Handle unserialization failures for Memcached --- src/Symfony/Component/Cache/Traits/MemcachedTrait.php | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/Cache/Traits/MemcachedTrait.php b/src/Symfony/Component/Cache/Traits/MemcachedTrait.php index 8139d31fa9b7e..c2832946f98c2 100644 --- a/src/Symfony/Component/Cache/Traits/MemcachedTrait.php +++ b/src/Symfony/Component/Cache/Traits/MemcachedTrait.php @@ -26,6 +26,7 @@ trait MemcachedTrait 'persistent_id' => null, 'username' => null, 'password' => null, + 'serializer' => 'php', ); private $client; @@ -194,7 +195,14 @@ protected function doSave(array $values, $lifetime) */ protected function doFetch(array $ids) { - return $this->checkResultCode($this->client->getMulti($ids)); + $unserializeCallbackHandler = ini_set('unserialize_callback_func', __CLASS__.'::handleUnserializeCallback'); + try { + return $this->checkResultCode($this->client->getMulti($ids)); + } catch (\Error $e) { + throw new \ErrorException($e->getMessage(), $e->getCode(), E_ERROR, $e->getFile(), $e->getLine()); + } finally { + ini_set('unserialize_callback_func', $unserializeCallbackHandler); + } } /** From 70cc4e86f4d32f3b2d51d23f7d2b2076fc11fe09 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Sun, 23 Jul 2017 11:15:20 +0200 Subject: [PATCH 0502/1099] [DI] Fix test --- .../Tests/Compiler/AutowirePassTest.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowirePassTest.php b/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowirePassTest.php index c78c3499c86e5..757db3f229c95 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowirePassTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowirePassTest.php @@ -516,15 +516,15 @@ public function testOptionalArgsNoRequiredForCoreClasses() { $container = new ContainerBuilder(); - $container->register('pdo_service', \PDO::class) - ->addArgument('sqlite:/foo.db') + $container->register('foo', \SplFileObject::class) + ->addArgument('foo.txt') ->setAutowired(true); (new AutowirePass())->process($container); - $definition = $container->getDefinition('pdo_service'); + $definition = $container->getDefinition('foo'); $this->assertEquals( - array('sqlite:/foo.db'), + array('foo.txt'), $definition->getArguments() ); } From d30c75178144edc03ed135da7112456053b136d1 Mon Sep 17 00:00:00 2001 From: "Konstantin.Myakshin" Date: Sun, 23 Jul 2017 12:48:31 +0300 Subject: [PATCH 0503/1099] Add some phpdocs for IDE autocompletion and better SCA --- .../Form/Extension/Core/EventListener/ResizeFormListener.php | 2 ++ src/Symfony/Component/Form/Extension/Core/Type/ChoiceType.php | 1 + .../Form/Extension/Validator/Constraints/FormValidator.php | 1 + 3 files changed, 4 insertions(+) diff --git a/src/Symfony/Component/Form/Extension/Core/EventListener/ResizeFormListener.php b/src/Symfony/Component/Form/Extension/Core/EventListener/ResizeFormListener.php index 17d60a3d30cef..4b339181e9905 100644 --- a/src/Symfony/Component/Form/Extension/Core/EventListener/ResizeFormListener.php +++ b/src/Symfony/Component/Form/Extension/Core/EventListener/ResizeFormListener.php @@ -15,6 +15,7 @@ use Symfony\Component\Form\FormEvent; use Symfony\Component\Form\Exception\UnexpectedTypeException; use Symfony\Component\EventDispatcher\EventSubscriberInterface; +use Symfony\Component\Form\FormInterface; /** * Resize a collection form element based on the data sent from the client. @@ -146,6 +147,7 @@ public function onSubmit(FormEvent $event) if ($this->deleteEmpty) { $previousData = $event->getForm()->getData(); + /** @var FormInterface $child */ foreach ($form as $name => $child) { $isNew = !isset($previousData[$name]); diff --git a/src/Symfony/Component/Form/Extension/Core/Type/ChoiceType.php b/src/Symfony/Component/Form/Extension/Core/Type/ChoiceType.php index a45cb3a27860c..6c0c0b4295cde 100644 --- a/src/Symfony/Component/Form/Extension/Core/Type/ChoiceType.php +++ b/src/Symfony/Component/Form/Extension/Core/Type/ChoiceType.php @@ -120,6 +120,7 @@ public function buildForm(FormBuilderInterface $builder, array $options) // Reconstruct the data as mapping from child names to values $data = array(); + /** @var FormInterface $child */ foreach ($form as $child) { $value = $child->getConfig()->getOption('value'); diff --git a/src/Symfony/Component/Form/Extension/Validator/Constraints/FormValidator.php b/src/Symfony/Component/Form/Extension/Validator/Constraints/FormValidator.php index 5b989f1a60ca8..b5a06156c0db4 100644 --- a/src/Symfony/Component/Form/Extension/Validator/Constraints/FormValidator.php +++ b/src/Symfony/Component/Form/Extension/Validator/Constraints/FormValidator.php @@ -83,6 +83,7 @@ public function validate($form, Constraint $constraint) } else { $childrenSynchronized = true; + /** @var FormInterface $child */ foreach ($form as $child) { if (!$child->isSynchronized()) { $childrenSynchronized = false; From 8630abe27a1a75f97eaa5423411a93514330c13d Mon Sep 17 00:00:00 2001 From: "Konstantin.Myakshin" Date: Sat, 12 Nov 2016 00:23:04 +0200 Subject: [PATCH 0504/1099] [Form] Allow pass filter callback to delete_empty option. --- .../Core/EventListener/ResizeFormListener.php | 9 ++-- .../Extension/Core/Type/CollectionType.php | 1 + .../Core/Type/CollectionTypeTest.php | 44 +++++++++++++++++++ 3 files changed, 50 insertions(+), 4 deletions(-) diff --git a/src/Symfony/Component/Form/Extension/Core/EventListener/ResizeFormListener.php b/src/Symfony/Component/Form/Extension/Core/EventListener/ResizeFormListener.php index c3218ae4ec1cf..4cef560ee6525 100644 --- a/src/Symfony/Component/Form/Extension/Core/EventListener/ResizeFormListener.php +++ b/src/Symfony/Component/Form/Extension/Core/EventListener/ResizeFormListener.php @@ -48,7 +48,7 @@ class ResizeFormListener implements EventSubscriberInterface protected $allowDelete; /** - * @var bool + * @var bool|callable */ private $deleteEmpty; @@ -148,14 +148,15 @@ public function onSubmit(FormEvent $event) throw new UnexpectedTypeException($data, 'array or (\Traversable and \ArrayAccess)'); } - if ($this->deleteEmpty) { - $previousData = $event->getForm()->getData(); + if ($entryFilter = $this->deleteEmpty) { + $previousData = $form->getData(); foreach ($form as $name => $child) { $isNew = !isset($previousData[$name]); + $isEmpty = is_callable($entryFilter) ? $entryFilter($child->getData()) : $child->isEmpty(); // $isNew can only be true if allowAdd is true, so we don't // need to check allowAdd again - if ($child->isEmpty() && ($isNew || $this->allowDelete)) { + if ($isEmpty && ($isNew || $this->allowDelete)) { unset($data[$name]); $form->remove($name); } diff --git a/src/Symfony/Component/Form/Extension/Core/Type/CollectionType.php b/src/Symfony/Component/Form/Extension/Core/Type/CollectionType.php index 64ae8832ffe4d..e342efa52484a 100644 --- a/src/Symfony/Component/Form/Extension/Core/Type/CollectionType.php +++ b/src/Symfony/Component/Form/Extension/Core/Type/CollectionType.php @@ -100,6 +100,7 @@ public function configureOptions(OptionsResolver $resolver) )); $resolver->setNormalizer('entry_options', $entryOptionsNormalizer); + $resolver->setAllowedTypes('delete_empty', array('bool', 'callable')); } /** diff --git a/src/Symfony/Component/Form/Tests/Extension/Core/Type/CollectionTypeTest.php b/src/Symfony/Component/Form/Tests/Extension/Core/Type/CollectionTypeTest.php index 7ed25ce27e42f..977cb8cf43948 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Core/Type/CollectionTypeTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Core/Type/CollectionTypeTest.php @@ -12,6 +12,7 @@ namespace Symfony\Component\Form\Tests\Extension\Core\Type; use Symfony\Component\Form\Tests\Fixtures\Author; +use Symfony\Component\Form\Tests\Fixtures\AuthorType; class CollectionTypeTest extends BaseTypeTest { @@ -110,6 +111,49 @@ public function testResizedDownIfSubmittedWithEmptyDataAndDeleteEmpty() $this->assertEquals(array('foo@foo.com'), $form->getData()); } + public function testResizedDownWithDeleteEmptyCallable() + { + $form = $this->factory->create(static::TESTED_TYPE, null, array( + 'entry_type' => AuthorType::class, + 'allow_delete' => true, + 'delete_empty' => function (Author $obj = null) { + return null === $obj || empty($obj->firstName); + }, + )); + + $form->setData(array(new Author('Bob'), new Author('Alice'))); + $form->submit(array(array('firstName' => 'Bob'), array('firstName' => ''))); + + $this->assertTrue($form->has('0')); + $this->assertFalse($form->has('1')); + $this->assertEquals(new Author('Bob'), $form[0]->getData()); + $this->assertEquals(array(new Author('Bob')), $form->getData()); + } + + public function testResizedDownIfSubmittedWithCompoundEmptyDataDeleteEmptyAndNoDataClass() + { + $form = $this->factory->create(static::TESTED_TYPE, null, array( + 'entry_type' => AuthorType::class, + // If the field is not required, no new Author will be created if the + // form is completely empty + 'entry_options' => array('data_class' => null), + 'allow_add' => true, + 'allow_delete' => true, + 'delete_empty' => function ($author) { + return empty($author['firstName']); + }, + )); + $form->setData(array(array('firstName' => 'first', 'lastName' => 'last'))); + $form->submit(array( + array('firstName' => 's_first', 'lastName' => 's_last'), + array('firstName' => '', 'lastName' => ''), + )); + $this->assertTrue($form->has('0')); + $this->assertFalse($form->has('1')); + $this->assertEquals(array('firstName' => 's_first', 'lastName' => 's_last'), $form[0]->getData()); + $this->assertEquals(array(array('firstName' => 's_first', 'lastName' => 's_last')), $form->getData()); + } + public function testDontAddEmptyDataIfDeleteEmpty() { $form = $this->factory->create(static::TESTED_TYPE, null, array( From 88666ddc2c07ebc83d3fdd4f5ae34adff7859093 Mon Sep 17 00:00:00 2001 From: Robin Chalas Date: Sun, 23 Jul 2017 12:22:06 +0200 Subject: [PATCH 0505/1099] Fix merge --- .../Bridge/Twig/Command/DebugCommand.php | 44 +------------------ .../Bridge/Twig/Command/LintCommand.php | 44 +------------------ .../Twig/Tests/Command/LintCommandTest.php | 18 -------- .../TwigBundle/Command/DebugCommand.php | 38 ---------------- .../TwigBundle/Resources/config/console.xml | 5 --- .../Console/Helper/SymfonyQuestionHelper.php | 26 ----------- 6 files changed, 2 insertions(+), 173 deletions(-) delete mode 100644 src/Symfony/Bundle/TwigBundle/Command/DebugCommand.php diff --git a/src/Symfony/Bridge/Twig/Command/DebugCommand.php b/src/Symfony/Bridge/Twig/Command/DebugCommand.php index a0239b5f42a28..37a37786dba32 100644 --- a/src/Symfony/Bridge/Twig/Command/DebugCommand.php +++ b/src/Symfony/Bridge/Twig/Command/DebugCommand.php @@ -28,41 +28,13 @@ class DebugCommand extends Command { private $twig; - /** - * @param Environment $twig - */ - public function __construct($twig = null) + public function __construct(Environment $twig) { parent::__construct(); - if (!$twig instanceof Environment) { - @trigger_error(sprintf('Passing a command name as the first argument of "%s" is deprecated since version 3.4 and will be removed in 4.0. If the command was registered by convention, make it a service instead.', __METHOD__), E_USER_DEPRECATED); - - $this->setName(null === $twig ? 'debug:twig' : $twig); - - return; - } - - $this->twig = $twig; - } - - public function setTwigEnvironment(Environment $twig) - { - @trigger_error(sprintf('Method "%s" is deprecated since version 3.4 and will be removed in 4.0.', __METHOD__), E_USER_DEPRECATED); - $this->twig = $twig; } - /** - * @return Environment $twig - */ - protected function getTwigEnvironment() - { - @trigger_error(sprintf('Method "%s" is deprecated since version 3.4 and will be removed in 4.0.', __METHOD__), E_USER_DEPRECATED); - - return $this->twig; - } - protected function configure() { $this @@ -95,20 +67,6 @@ protected function configure() protected function execute(InputInterface $input, OutputInterface $output) { $io = new SymfonyStyle($input, $output); - - // BC to be removed in 4.0 - if (__CLASS__ !== get_class($this)) { - $r = new \ReflectionMethod($this, 'getTwigEnvironment'); - if (__CLASS__ !== $r->getDeclaringClass()->getName()) { - @trigger_error(sprintf('Usage of method "%s" is deprecated since version 3.4 and will no longer be supported in 4.0.', get_class($this).'::getTwigEnvironment'), E_USER_DEPRECATED); - - $this->twig = $this->getTwigEnvironment(); - } - } - if (null === $this->twig) { - throw new \RuntimeException('The Twig environment needs to be set.'); - } - $types = array('functions', 'filters', 'tests', 'globals'); if ($input->getOption('format') === 'json') { diff --git a/src/Symfony/Bridge/Twig/Command/LintCommand.php b/src/Symfony/Bridge/Twig/Command/LintCommand.php index c9eac4de6058e..2973f6b4deaf8 100644 --- a/src/Symfony/Bridge/Twig/Command/LintCommand.php +++ b/src/Symfony/Bridge/Twig/Command/LintCommand.php @@ -33,41 +33,13 @@ class LintCommand extends Command { private $twig; - /** - * @param Environment $twig - */ - public function __construct($twig = null) + public function __construct(Environment $twig) { parent::__construct(); - if (!$twig instanceof Environment) { - @trigger_error(sprintf('Passing a command name as the first argument of "%s" is deprecated since version 3.4 and will be removed in 4.0. If the command was registered by convention, make it a service instead.', __METHOD__), E_USER_DEPRECATED); - - $this->setName(null === $twig ? 'lint:twig' : $twig); - - return; - } - - $this->twig = $twig; - } - - public function setTwigEnvironment(Environment $twig) - { - @trigger_error(sprintf('Method "%s" is deprecated since version 3.4 and will be removed in 4.0.', __METHOD__), E_USER_DEPRECATED); - $this->twig = $twig; } - /** - * @return Environment $twig - */ - protected function getTwigEnvironment() - { - @trigger_error(sprintf('Method "%s" is deprecated since version 3.4 and will be removed in 4.0.', __METHOD__), E_USER_DEPRECATED); - - return $this->twig; - } - protected function configure() { $this @@ -100,20 +72,6 @@ protected function configure() protected function execute(InputInterface $input, OutputInterface $output) { $io = new SymfonyStyle($input, $output); - - // BC to be removed in 4.0 - if (__CLASS__ !== get_class($this)) { - $r = new \ReflectionMethod($this, 'getTwigEnvironment'); - if (__CLASS__ !== $r->getDeclaringClass()->getName()) { - @trigger_error(sprintf('Usage of method "%s" is deprecated since version 3.4 and will no longer be supported in 4.0.', get_class($this).'::getTwigEnvironment'), E_USER_DEPRECATED); - - $this->twig = $this->getTwigEnvironment(); - } - } - if (null === $this->twig) { - throw new \RuntimeException('The Twig environment needs to be set.'); - } - $filenames = $input->getArgument('filename'); if (0 === count($filenames)) { diff --git a/src/Symfony/Bridge/Twig/Tests/Command/LintCommandTest.php b/src/Symfony/Bridge/Twig/Tests/Command/LintCommandTest.php index db87d6e131fdb..ce7175ab1adfe 100644 --- a/src/Symfony/Bridge/Twig/Tests/Command/LintCommandTest.php +++ b/src/Symfony/Bridge/Twig/Tests/Command/LintCommandTest.php @@ -68,24 +68,6 @@ public function testLintFileCompileTimeException() $this->assertRegExp('/ERROR in \S+ \(line /', trim($tester->getDisplay())); } - /** - * @group legacy - * @expectedDeprecation Passing a command name as the first argument of "Symfony\Bridge\Twig\Command\LintCommand::__construct" is deprecated since version 3.4 and will be removed in 4.0. If the command was registered by convention, make it a service instead. - * @expectedException \RuntimeException - * @expectedExceptionMessage The Twig environment needs to be set. - */ - public function testLegacyLintCommand() - { - $command = new LintCommand(); - - $application = new Application(); - $application->add($command); - $command = $application->find('lint:twig'); - - $tester = new CommandTester($command); - $tester->execute(array()); - } - /** * @return CommandTester */ diff --git a/src/Symfony/Bundle/TwigBundle/Command/DebugCommand.php b/src/Symfony/Bundle/TwigBundle/Command/DebugCommand.php deleted file mode 100644 index de943d2bed76a..0000000000000 --- a/src/Symfony/Bundle/TwigBundle/Command/DebugCommand.php +++ /dev/null @@ -1,38 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\TwigBundle\Command; - -@trigger_error(sprintf('The %s class is deprecated since version 3.4 and will be removed in 4.0. Use Symfony\Bridge\Twig\Command\DebugCommand instead.', DebugCommand::class), E_USER_DEPRECATED); - -use Symfony\Bridge\Twig\Command\DebugCommand as BaseDebugCommand; -use Symfony\Component\DependencyInjection\ContainerAwareInterface; -use Symfony\Component\DependencyInjection\ContainerAwareTrait; - -/** - * Lists twig functions, filters, globals and tests present in the current project. - * - * @author Jordi Boggiano - * - * @deprecated since version 3.4, to be removed in 4.0. - */ -final class DebugCommand extends BaseDebugCommand implements ContainerAwareInterface -{ - use ContainerAwareTrait; - - /** - * {@inheritdoc} - */ - protected function getTwigEnvironment() - { - return $this->container->get('twig'); - } -} diff --git a/src/Symfony/Bundle/TwigBundle/Resources/config/console.xml b/src/Symfony/Bundle/TwigBundle/Resources/config/console.xml index 92347d699c1b1..8a1b157489655 100644 --- a/src/Symfony/Bundle/TwigBundle/Resources/config/console.xml +++ b/src/Symfony/Bundle/TwigBundle/Resources/config/console.xml @@ -16,10 +16,5 @@ - - - - The "%service_id%" service is deprecated since Symfony 3.4 and will be removed in 4.0. Use "twig.command.debug" instead. - diff --git a/src/Symfony/Component/Console/Helper/SymfonyQuestionHelper.php b/src/Symfony/Component/Console/Helper/SymfonyQuestionHelper.php index cf071d594d44a..a63225149297d 100644 --- a/src/Symfony/Component/Console/Helper/SymfonyQuestionHelper.php +++ b/src/Symfony/Component/Console/Helper/SymfonyQuestionHelper.php @@ -27,32 +27,6 @@ */ class SymfonyQuestionHelper extends QuestionHelper { - /** - * {@inheritdoc} - * - * To be removed in 4.0 - */ - public function ask(InputInterface $input, OutputInterface $output, Question $question) - { - $validator = $question->getValidator(); - $question->setValidator(function ($value) use ($validator) { - if (null !== $validator) { - $value = $validator($value); - } else { - // make required - if (!is_array($value) && !is_bool($value) && 0 === strlen($value)) { - @trigger_error('The default question validator is deprecated since Symfony 3.3 and will not be used anymore in version 4.0. Set a custom question validator if needed.', E_USER_DEPRECATED); - - throw new LogicException('A value is required.'); - } - } - - return $value; - }); - - return parent::ask($input, $output, $question); - } - /** * {@inheritdoc} */ From 9fd425ea141e8812241d67ccba3effe5ecfa0f2e Mon Sep 17 00:00:00 2001 From: Guilhem Niot Date: Sun, 23 Jul 2017 14:40:01 +0200 Subject: [PATCH 0506/1099] Suggest using quotes instead of Yaml::PARSE_KEYS_AS_STRINGS --- UPGRADE-3.3.md | 13 +++++-------- UPGRADE-4.0.md | 18 ++++++++---------- src/Symfony/Component/Yaml/CHANGELOG.md | 13 +++++-------- src/Symfony/Component/Yaml/Inline.php | 2 +- src/Symfony/Component/Yaml/Parser.php | 2 +- .../Component/Yaml/Tests/InlineTest.php | 2 +- .../Component/Yaml/Tests/ParserTest.php | 4 ++-- 7 files changed, 23 insertions(+), 31 deletions(-) diff --git a/UPGRADE-3.3.md b/UPGRADE-3.3.md index b8d2524654386..e43c365e6c5b6 100644 --- a/UPGRADE-3.3.md +++ b/UPGRADE-3.3.md @@ -365,8 +365,7 @@ Yaml * Deprecated support for implicitly parsing non-string mapping keys as strings. Mapping keys that are no strings will lead to a `ParseException` in Symfony - 4.0. Use the `PARSE_KEYS_AS_STRINGS` flag to opt-in for keys to be parsed as - strings. + 4.0. Use quotes to opt-in for keys to be parsed as strings. Before: @@ -374,7 +373,6 @@ Yaml $yaml = << Date: Sun, 23 Jul 2017 18:14:03 +0300 Subject: [PATCH 0507/1099] Removed references for non existent validator constraints --- .../Form/Extension/Validator/ValidatorTypeGuesser.php | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/Symfony/Component/Form/Extension/Validator/ValidatorTypeGuesser.php b/src/Symfony/Component/Form/Extension/Validator/ValidatorTypeGuesser.php index c90443a9dcfad..4a5ed4d69e5da 100644 --- a/src/Symfony/Component/Form/Extension/Validator/ValidatorTypeGuesser.php +++ b/src/Symfony/Component/Form/Extension/Validator/ValidatorTypeGuesser.php @@ -151,8 +151,6 @@ public function guessTypeForConstraint(Constraint $constraint) case 'Symfony\Component\Validator\Constraints\Count': return new TypeGuess('Symfony\Component\Form\Extension\Core\Type\CollectionType', array(), Guess::LOW_CONFIDENCE); - case 'Symfony\Component\Validator\Constraints\True': - case 'Symfony\Component\Validator\Constraints\False': case 'Symfony\Component\Validator\Constraints\IsTrue': case 'Symfony\Component\Validator\Constraints\IsFalse': return new TypeGuess('Symfony\Component\Form\Extension\Core\Type\CheckboxType', array(), Guess::MEDIUM_CONFIDENCE); @@ -171,7 +169,6 @@ public function guessRequiredForConstraint(Constraint $constraint) switch (get_class($constraint)) { case 'Symfony\Component\Validator\Constraints\NotNull': case 'Symfony\Component\Validator\Constraints\NotBlank': - case 'Symfony\Component\Validator\Constraints\True': case 'Symfony\Component\Validator\Constraints\IsTrue': return new ValueGuess(true, Guess::HIGH_CONFIDENCE); } From 1b56b2b30074a8c50e6306329f71ab05343de06c Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Mon, 24 Jul 2017 08:49:18 +0200 Subject: [PATCH 0508/1099] [VarDumper] Remove dead code --- .../Component/VarDumper/Cloner/VarCloner.php | 37 ++++++++----------- 1 file changed, 16 insertions(+), 21 deletions(-) diff --git a/src/Symfony/Component/VarDumper/Cloner/VarCloner.php b/src/Symfony/Component/VarDumper/Cloner/VarCloner.php index 6c8520b5f1e57..ed5ab725b7541 100644 --- a/src/Symfony/Component/VarDumper/Cloner/VarCloner.php +++ b/src/Symfony/Component/VarDumper/Cloner/VarCloner.php @@ -44,15 +44,10 @@ protected function doClone($var) $a = null; // Array cast for nested structures $stub = null; // Stub capturing the main properties of an original item value // or null if the original value is used directly - $zval = array( // Main properties of the current value - 'type' => null, - 'zval_isref' => null, - 'zval_hash' => null, - 'array_count' => null, - 'object_class' => null, - 'object_handle' => null, - 'resource_type' => null, - ); + $zvalType = null; // Main properties of the current value + $zvalIsRef = null; + $zvalHash = null; + if (!self::$hashMask) { self::initHashMask(); } @@ -84,14 +79,14 @@ protected function doClone($var) $k = $j; } $refs[$k] = $cookie; - if ($zval['zval_isref'] = $vals[$k] === $cookie) { - $zval['zval_hash'] = $v instanceof Stub ? spl_object_hash($v) : null; + if ($zvalIsRef = $vals[$k] === $cookie) { + $zvalHash = $v instanceof Stub ? spl_object_hash($v) : null; } - $zval['type'] = gettype($v); - if ($zval['zval_isref']) { + $zvalType = gettype($v); + if ($zvalIsRef) { $vals[$k] = &$stub; // Break hard references to make $queue completely unset($stub); // independent from the original structure - if (isset($hardRefs[$zval['zval_hash']])) { + if (isset($hardRefs[$zvalHash])) { $vals[$k] = $refs[$k] = $v; if ($v->value instanceof Stub && (Stub::TYPE_OBJECT === $v->value->type || Stub::TYPE_RESOURCE === $v->value->type)) { ++$v->value->refCount; @@ -102,7 +97,7 @@ protected function doClone($var) } // Create $stub when the original value $v can not be used directly // If $v is a nested structure, put that structure in array $a - switch ($zval['type']) { + switch ($zvalType) { case 'string': if (isset($v[0]) && !preg_match('//u', $v)) { $stub = new Stub(); @@ -148,15 +143,15 @@ protected function doClone($var) $a = $v; } - $stub->value = $zval['array_count'] ?: count($a); + $stub->value = count($a); } break; case 'object': - if (empty($objRefs[$h = $zval['object_handle'] ?: ($hashMask ^ hexdec(substr(spl_object_hash($v), $hashOffset, PHP_INT_SIZE)))])) { + if (empty($objRefs[$h = $hashMask ^ hexdec(substr(spl_object_hash($v), $hashOffset, PHP_INT_SIZE))])) { $stub = new Stub(); $stub->type = Stub::TYPE_OBJECT; - $stub->class = $zval['object_class'] ?: get_class($v); + $stub->class = get_class($v); $stub->value = $v; $stub->handle = $h; $a = $this->castObject($stub, 0 < $i); @@ -188,7 +183,7 @@ protected function doClone($var) if (empty($resRefs[$h = (int) $v])) { $stub = new Stub(); $stub->type = Stub::TYPE_RESOURCE; - if ('Unknown' === $stub->class = $zval['resource_type'] ?: @get_resource_type($v)) { + if ('Unknown' === $stub->class = @get_resource_type($v)) { $stub->class = 'Closed'; } $stub->value = $v; @@ -211,7 +206,7 @@ protected function doClone($var) } if (isset($stub)) { - if ($zval['zval_isref']) { + if ($zvalIsRef) { $refs[$k] = new Stub(); $refs[$k]->value = $stub; $h = spl_object_hash($refs[$k]); @@ -245,7 +240,7 @@ protected function doClone($var) $stub->position = $len++; } $stub = $a = null; - } elseif ($zval['zval_isref']) { + } elseif ($zvalIsRef) { $refs[$k] = $vals[$k] = new Stub(); $refs[$k]->value = $v; $h = spl_object_hash($refs[$k]); From fe48ab1f8bb33dc33059510760a82ade7735d87f Mon Sep 17 00:00:00 2001 From: Roland Franssen Date: Mon, 24 Jul 2017 20:55:44 +0200 Subject: [PATCH 0509/1099] [Form] Static call TimezoneType::getTimezones --- src/Symfony/Component/Form/Extension/Core/Type/TimezoneType.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/Form/Extension/Core/Type/TimezoneType.php b/src/Symfony/Component/Form/Extension/Core/Type/TimezoneType.php index beb83dde4f0cf..486f0a28e40ff 100644 --- a/src/Symfony/Component/Form/Extension/Core/Type/TimezoneType.php +++ b/src/Symfony/Component/Form/Extension/Core/Type/TimezoneType.php @@ -66,7 +66,7 @@ public function loadChoiceList($value = null) return $this->choiceList; } - return $this->choiceList = new ArrayChoiceList($this->getTimezones(), $value); + return $this->choiceList = new ArrayChoiceList(self::getTimezones(), $value); } /** From 320cf40b71440d6c76fd3dbede91f09b88a1b8fe Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Mon, 24 Jul 2017 16:06:58 +0200 Subject: [PATCH 0510/1099] [DI] Fix resetting private services --- .../LazyProxy/PhpDumper/ProxyDumper.php | 3 ++- .../DependencyInjection/Dumper/PhpDumper.php | 22 +++++++++++++++++++ .../Tests/Fixtures/php/services1-1.php | 9 ++++++++ .../Tests/Fixtures/php/services1.php | 9 ++++++++ .../Tests/Fixtures/php/services10.php | 9 ++++++++ .../Tests/Fixtures/php/services12.php | 9 ++++++++ .../Tests/Fixtures/php/services13.php | 9 ++++++++ .../Tests/Fixtures/php/services19.php | 9 ++++++++ .../Tests/Fixtures/php/services24.php | 9 ++++++++ .../Tests/Fixtures/php/services26.php | 9 ++++++++ .../Tests/Fixtures/php/services33.php | 9 ++++++++ .../Tests/Fixtures/php/services8.php | 9 ++++++++ .../Tests/Fixtures/php/services9_compiled.php | 9 ++++++++ .../Fixtures/php/services_array_params.php | 9 ++++++++ .../Tests/Fixtures/php/services_locator.php | 9 ++++++++ .../Fixtures/php/services_private_frozen.php | 9 ++++++++ .../Fixtures/php/services_subscriber.php | 9 ++++++++ 17 files changed, 159 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Bridge/ProxyManager/LazyProxy/PhpDumper/ProxyDumper.php b/src/Symfony/Bridge/ProxyManager/LazyProxy/PhpDumper/ProxyDumper.php index 563e2d1baa4cc..29c6c3617e5e3 100644 --- a/src/Symfony/Bridge/ProxyManager/LazyProxy/PhpDumper/ProxyDumper.php +++ b/src/Symfony/Bridge/ProxyManager/LazyProxy/PhpDumper/ProxyDumper.php @@ -14,6 +14,7 @@ use ProxyManager\Generator\ClassGenerator; use ProxyManager\GeneratorStrategy\BaseGeneratorStrategy; use ProxyManager\ProxyGenerator\LazyLoadingValueHolderGenerator; +use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\DependencyInjection\LazyProxy\PhpDumper\DumperInterface; @@ -69,7 +70,7 @@ public function getProxyFactoryCode(Definition $definition, $id, $methodName = n $instantiation = 'return'; if ($definition->isShared()) { - $instantiation .= " \$this->services['$id'] ="; + $instantiation .= sprintf(' $this->%s[\'%s\'] =', $definition->isPublic() || !method_exists(ContainerBuilder::class, 'addClassResource') ? 'services' : 'privates', $id); } if (null === $methodName) { diff --git a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php index 077f7fef223c3..5ee485be40dc0 100644 --- a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php +++ b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php @@ -153,6 +153,7 @@ public function dump(array $options = array()) $code = $this->startClass($options['class'], $options['base_class'], $options['namespace']). $this->addConstructor(). + $this->addReset(). $this->addCompile(). $this->addIsCompiled(). $this->addServices(). @@ -831,6 +832,27 @@ public function __construct() return $code; } + /** + * Adds the reset method for a compiled container. + * + * @return string + */ + private function addReset() + { + return <<docStar} + * {@inheritdoc} + */ + public function reset() + { + \$this->privates = array(); + parent::reset(); + } + +EOF; + } + /** * Adds the compile method for a compiled container. * diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services1-1.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services1-1.php index 01f159f842037..5f74931f7a290 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services1-1.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services1-1.php @@ -34,6 +34,15 @@ public function __construct() $this->aliases = array(); } + /** + * {@inheritdoc} + */ + public function reset() + { + $this->privates = array(); + parent::reset(); + } + /** * {@inheritdoc} */ diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services1.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services1.php index 967146d410e62..ca73b472a5710 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services1.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services1.php @@ -32,6 +32,15 @@ public function __construct() $this->aliases = array(); } + /** + * {@inheritdoc} + */ + public function reset() + { + $this->privates = array(); + parent::reset(); + } + /** * {@inheritdoc} */ diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services10.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services10.php index 78ce81547277e..28c09cb74f504 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services10.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services10.php @@ -37,6 +37,15 @@ public function __construct() $this->aliases = array(); } + /** + * {@inheritdoc} + */ + public function reset() + { + $this->privates = array(); + parent::reset(); + } + /** * {@inheritdoc} */ diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services12.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services12.php index db9faadd187c6..e3042f6d8b593 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services12.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services12.php @@ -41,6 +41,15 @@ public function __construct() $this->aliases = array(); } + /** + * {@inheritdoc} + */ + public function reset() + { + $this->privates = array(); + parent::reset(); + } + /** * {@inheritdoc} */ diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services13.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services13.php index 35a68aa9b3f2f..e79b934632ef8 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services13.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services13.php @@ -35,6 +35,15 @@ public function __construct() $this->aliases = array(); } + /** + * {@inheritdoc} + */ + public function reset() + { + $this->privates = array(); + parent::reset(); + } + /** * {@inheritdoc} */ diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services19.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services19.php index 6e384da3b9d7a..1168381f0dba6 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services19.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services19.php @@ -36,6 +36,15 @@ public function __construct() $this->aliases = array(); } + /** + * {@inheritdoc} + */ + public function reset() + { + $this->privates = array(); + parent::reset(); + } + /** * {@inheritdoc} */ diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services24.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services24.php index 382613ccf4691..ce66c1794f12a 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services24.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services24.php @@ -35,6 +35,15 @@ public function __construct() $this->aliases = array(); } + /** + * {@inheritdoc} + */ + public function reset() + { + $this->privates = array(); + parent::reset(); + } + /** * {@inheritdoc} */ diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services26.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services26.php index 0fc608186a4d6..0eccfb26c42a9 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services26.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services26.php @@ -37,6 +37,15 @@ public function __construct() $this->aliases = array(); } + /** + * {@inheritdoc} + */ + public function reset() + { + $this->privates = array(); + parent::reset(); + } + /** * {@inheritdoc} */ diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services33.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services33.php index 548ce20c8bc5d..de77e5bdb4634 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services33.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services33.php @@ -35,6 +35,15 @@ public function __construct() $this->aliases = array(); } + /** + * {@inheritdoc} + */ + public function reset() + { + $this->privates = array(); + parent::reset(); + } + /** * {@inheritdoc} */ diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services8.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services8.php index 17bbbfae714d4..004c7b8008be6 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services8.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services8.php @@ -34,6 +34,15 @@ public function __construct() $this->aliases = array(); } + /** + * {@inheritdoc} + */ + public function reset() + { + $this->privates = array(); + parent::reset(); + } + /** * {@inheritdoc} */ diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_compiled.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_compiled.php index 3d47bac17eb80..f8f17c8577168 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_compiled.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_compiled.php @@ -60,6 +60,15 @@ public function __construct() ); } + /** + * {@inheritdoc} + */ + public function reset() + { + $this->privates = array(); + parent::reset(); + } + /** * {@inheritdoc} */ diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_array_params.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_array_params.php index d5f4f2ae9d886..b6931b99822b3 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_array_params.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_array_params.php @@ -41,6 +41,15 @@ public function __construct() $this->aliases = array(); } + /** + * {@inheritdoc} + */ + public function reset() + { + $this->privates = array(); + parent::reset(); + } + /** * {@inheritdoc} */ diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_locator.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_locator.php index a413e1cfdc639..68fa5bcd136a4 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_locator.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_locator.php @@ -42,6 +42,15 @@ public function __construct() $this->aliases = array(); } + /** + * {@inheritdoc} + */ + public function reset() + { + $this->privates = array(); + parent::reset(); + } + /** * {@inheritdoc} */ diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_private_frozen.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_private_frozen.php index 7bd14e1608e27..329c2a4af1bda 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_private_frozen.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_private_frozen.php @@ -36,6 +36,15 @@ public function __construct() $this->aliases = array(); } + /** + * {@inheritdoc} + */ + public function reset() + { + $this->privates = array(); + parent::reset(); + } + /** * {@inheritdoc} */ diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_subscriber.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_subscriber.php index aaaeaa45f6c09..fb63dee8a1adb 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_subscriber.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_subscriber.php @@ -36,6 +36,15 @@ public function __construct() $this->aliases = array(); } + /** + * {@inheritdoc} + */ + public function reset() + { + $this->privates = array(); + parent::reset(); + } + /** * {@inheritdoc} */ From 0d5012d20ec42824b8e871f7de2d68200800e6bc Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Mon, 24 Jul 2017 13:52:13 +0200 Subject: [PATCH 0511/1099] [VarDumper] Dont use Stub objects for arrays --- .../VarDumper/Cloner/AbstractCloner.php | 4 +- .../Component/VarDumper/Cloner/Data.php | 97 ++------ .../Component/VarDumper/Cloner/Stub.php | 36 ++- .../Component/VarDumper/Cloner/VarCloner.php | 219 ++++++++---------- .../VarDumper/Tests/Cloner/VarClonerTest.php | 43 +--- 5 files changed, 160 insertions(+), 239 deletions(-) diff --git a/src/Symfony/Component/VarDumper/Cloner/AbstractCloner.php b/src/Symfony/Component/VarDumper/Cloner/AbstractCloner.php index 45e0b6ad771b1..8fd192d0e402c 100644 --- a/src/Symfony/Component/VarDumper/Cloner/AbstractCloner.php +++ b/src/Symfony/Component/VarDumper/Cloner/AbstractCloner.php @@ -213,7 +213,7 @@ public function cloneVar($var, $filter = 0) gc_disable(); } try { - $data = $this->doClone($var); + return new Data($this->doClone($var)); } finally { if ($gc) { gc_enable(); @@ -221,8 +221,6 @@ public function cloneVar($var, $filter = 0) restore_error_handler(); $this->prevErrorHandler = null; } - - return new Data($data); } /** diff --git a/src/Symfony/Component/VarDumper/Cloner/Data.php b/src/Symfony/Component/VarDumper/Cloner/Data.php index 655fae0ca6fe5..b3d0cfab495ac 100644 --- a/src/Symfony/Component/VarDumper/Cloner/Data.php +++ b/src/Symfony/Component/VarDumper/Cloner/Data.php @@ -16,7 +16,7 @@ /** * @author Nicolas Grekas */ -class Data implements \ArrayAccess, \Countable, \IteratorAggregate, \Serializable +class Data implements \ArrayAccess, \Countable, \IteratorAggregate { private $data; private $position = 0; @@ -72,7 +72,7 @@ public function getValue($recursive = false) if ($item instanceof Stub && Stub::TYPE_REF === $item->type && !$item->position) { $item = $item->value; } - if (!$item instanceof Stub) { + if (!($item = $this->getStub($item)) instanceof Stub) { return $item; } if (Stub::TYPE_STRING === $item->type) { @@ -82,7 +82,7 @@ public function getValue($recursive = false) $children = $item->position ? $this->data[$item->position] : array(); foreach ($children as $k => $v) { - if ($recursive && !$v instanceof Stub) { + if ($recursive && !($v = $this->getStub($v)) instanceof Stub) { continue; } $children[$k] = clone $this; @@ -90,12 +90,12 @@ public function getValue($recursive = false) $children[$k]->position = $item->position; if ($recursive) { - if ($v instanceof Stub && Stub::TYPE_REF === $v->type && $v->value instanceof Stub) { + if (Stub::TYPE_REF === $v->type && ($v = $this->getStub($v->value)) instanceof Stub) { $recursive = (array) $recursive; - if (isset($recursive[$v->value->position])) { + if (isset($recursive[$v->position])) { continue; } - $recursive[$v->value->position] = true; + $recursive[$v->position] = true; } $children[$k] = $children[$k]->getValue($recursive); } @@ -123,7 +123,7 @@ public function getIterator() public function __get($key) { if (null !== $data = $this->seek($key)) { - $item = $data->data[$data->position][$data->key]; + $item = $this->getStub($data->data[$data->position][$data->key]); return $item instanceof Stub || array() === $item ? $data : $item; } @@ -236,7 +236,7 @@ public function seek($key) if ($item instanceof Stub && Stub::TYPE_REF === $item->type && !$item->position) { $item = $item->value; } - if (!$item instanceof Stub || !$item->position) { + if (!($item = $this->getStub($item)) instanceof Stub || !$item->position) { return; } $keys = array($key); @@ -278,57 +278,6 @@ public function dump(DumperInterface $dumper) $this->dumpItem($dumper, new Cursor(), $refs, $this->data[$this->position][$this->key]); } - /** - * @internal - */ - public function serialize() - { - $data = $this->data; - - foreach ($data as $i => $values) { - foreach ($values as $k => $v) { - if ($v instanceof Stub) { - if (Stub::TYPE_ARRAY === $v->type) { - $v = self::mapStubConsts($v, false); - $data[$i][$k] = array($v->class, $v->position, $v->cut); - } else { - $v = self::mapStubConsts($v, false); - $data[$i][$k] = array($v->class, $v->position, $v->cut, $v->type, $v->value, $v->handle, $v->refCount, $v->attr); - } - } - } - } - - return serialize(array($data, $this->position, $this->key, $this->maxDepth, $this->maxItemsPerDepth, $this->useRefHandles)); - } - - /** - * @internal - */ - public function unserialize($serialized) - { - list($data, $this->position, $this->key, $this->maxDepth, $this->maxItemsPerDepth, $this->useRefHandles) = unserialize($serialized); - - foreach ($data as $i => $values) { - foreach ($values as $k => $v) { - if ($v && is_array($v)) { - $s = new Stub(); - if (3 === count($v)) { - $s->type = Stub::TYPE_ARRAY; - $s = self::mapStubConsts($s, false); - list($s->class, $s->position, $s->cut) = $v; - $s->value = $s->cut + count($data[$s->position]); - } else { - list($s->class, $s->position, $s->cut, $s->type, $s->value, $s->handle, $s->refCount, $s->attr) = $v; - } - $data[$i][$k] = self::mapStubConsts($s, true); - } - } - } - - $this->data = $data; - } - /** * Depth-first dumping of items. * @@ -346,7 +295,10 @@ private function dumpItem($dumper, $cursor, &$refs, $item) if (!$item instanceof Stub) { $cursor->attr = array(); - $type = gettype($item); + $type = \gettype($item); + if ($item && 'array' === $type) { + $item = $this->getStub($item); + } } elseif (Stub::TYPE_REF === $item->type) { if ($item->handle) { if (!isset($refs[$r = $item->handle - (PHP_INT_MAX >> 1)])) { @@ -360,7 +312,7 @@ private function dumpItem($dumper, $cursor, &$refs, $item) } $cursor->attr = $item->attr; $type = $item->class ?: gettype($item->value); - $item = $item->value; + $item = $this->getStub($item->value); } if ($item instanceof Stub) { if ($item->refCount) { @@ -458,21 +410,20 @@ private function dumpChildren($dumper, $parentCursor, &$refs, $children, $hashCu return $hashCut; } - private static function mapStubConsts(Stub $stub, $resolve) + private function getStub($item) { - static $stubConstIndexes, $stubConstValues; - - if (null === $stubConstIndexes) { - $r = new \ReflectionClass(Stub::class); - $stubConstIndexes = array_flip(array_values($r->getConstants())); - $stubConstValues = array_flip($stubConstIndexes); + if (!$item || !\is_array($item)) { + return $item; } - $map = $resolve ? $stubConstValues : $stubConstIndexes; - - $stub = clone $stub; - $stub->type = $map[$stub->type]; - $stub->class = isset($map[$stub->class]) ? $map[$stub->class] : $stub->class; + $stub = new Stub(); + $stub->type = Stub::TYPE_ARRAY; + foreach ($item as $stub->class => $stub->position) { + } + if (isset($item[0])) { + $stub->cut = $item[0]; + } + $stub->value = $stub->cut + \count($this->data[$stub->position]); return $stub; } diff --git a/src/Symfony/Component/VarDumper/Cloner/Stub.php b/src/Symfony/Component/VarDumper/Cloner/Stub.php index 313c591fc835a..3b8e60d90ee6e 100644 --- a/src/Symfony/Component/VarDumper/Cloner/Stub.php +++ b/src/Symfony/Component/VarDumper/Cloner/Stub.php @@ -16,19 +16,19 @@ * * @author Nicolas Grekas */ -class Stub +class Stub implements \Serializable { - const TYPE_REF = 'ref'; - const TYPE_STRING = 'string'; - const TYPE_ARRAY = 'array'; - const TYPE_OBJECT = 'object'; - const TYPE_RESOURCE = 'resource'; + const TYPE_REF = 1; + const TYPE_STRING = 2; + const TYPE_ARRAY = 3; + const TYPE_OBJECT = 4; + const TYPE_RESOURCE = 5; - const STRING_BINARY = 'bin'; - const STRING_UTF8 = 'utf8'; + const STRING_BINARY = 1; + const STRING_UTF8 = 2; - const ARRAY_ASSOC = 'assoc'; - const ARRAY_INDEXED = 'indexed'; + const ARRAY_ASSOC = 1; + const ARRAY_INDEXED = 2; public $type = self::TYPE_REF; public $class = ''; @@ -38,4 +38,20 @@ class Stub public $refCount = 0; public $position = 0; public $attr = array(); + + /** + * @internal + */ + public function serialize() + { + return \serialize(array($this->class, $this->position, $this->cut, $this->type, $this->value, $this->handle, $this->refCount, $this->attr)); + } + + /** + * @internal + */ + public function unserialize($serialized) + { + list($this->class, $this->position, $this->cut, $this->type, $this->value, $this->handle, $this->refCount, $this->attr) = \unserialize($serialized); + } } diff --git a/src/Symfony/Component/VarDumper/Cloner/VarCloner.php b/src/Symfony/Component/VarDumper/Cloner/VarCloner.php index 6a3b451bda7f7..108ab01e17652 100644 --- a/src/Symfony/Component/VarDumper/Cloner/VarCloner.php +++ b/src/Symfony/Component/VarDumper/Cloner/VarCloner.php @@ -24,12 +24,11 @@ class VarCloner extends AbstractCloner */ protected function doClone($var) { - $useExt = $this->useExt; $len = 1; // Length of $queue $pos = 0; // Number of cloned items past the first level $refsCounter = 0; // Hard references counter $queue = array(array($var)); // This breadth-first queue is the return value - $arrayRefs = array(); // Map of queue indexes to stub array objects + $indexedArrays = array(); // Map of queue indexes that hold numerically indexed arrays $hardRefs = array(); // Map of original zval hashes to stub objects $objRefs = array(); // Map of original object handles to their stub object couterpart $resRefs = array(); // Map of original resource handles to their stub object couterpart @@ -41,92 +40,99 @@ protected function doClone($var) $a = null; // Array cast for nested structures $stub = null; // Stub capturing the main properties of an original item value // or null if the original value is used directly - $zval = array( // Main properties of the current value - 'type' => null, - 'zval_isref' => null, - 'zval_hash' => null, - 'array_count' => null, - 'object_class' => null, - 'object_handle' => null, - 'resource_type' => null, - ); + if (!self::$hashMask) { self::initHashMask(); } $hashMask = self::$hashMask; $hashOffset = self::$hashOffset; + $arrayStub = new Stub(); + $arrayStub->type = Stub::TYPE_ARRAY; + $fromObjCast = false; for ($i = 0; $i < $len; ++$i) { - $indexed = true; // Whether the currently iterated array is numerically indexed or not - $j = -1; // Position in the currently iterated array - $fromObjCast = array_keys($queue[$i]); - $fromObjCast = array_keys(array_flip($fromObjCast)) !== $fromObjCast; - $refs = $vals = $fromObjCast ? array_values($queue[$i]) : $queue[$i]; - foreach ($queue[$i] as $k => $v) { - // $k is the original key - // $v is the original value or a stub object in case of hard references - if ($k !== ++$j) { - $indexed = false; - } - if ($fromObjCast) { - $k = $j; - } - if ($useExt) { - $zval = symfony_zval_info($k, $refs); - } else { - $refs[$k] = $cookie; - if ($zval['zval_isref'] = $vals[$k] === $cookie) { - $zval['zval_hash'] = $v instanceof Stub ? spl_object_hash($v) : null; + $refs = $vals = $queue[$i]; + if (\PHP_VERSION_ID < 70200 && empty($indexedArrays[$i])) { + // see https://wiki.php.net/rfc/convert_numeric_keys_in_object_array_casts + foreach ($vals as $k => $v) { + if (\is_int($k)) { + continue; + } + foreach (array($k => true) as $j => $v) { + } + if ($k !== $j) { + $fromObjCast = true; + $refs = $vals = \array_values($queue[$i]); + break; } - $zval['type'] = gettype($v); } - if ($zval['zval_isref']) { + } + foreach ($vals as $k => $v) { + // $v is the original value or a stub object in case of hard references + $refs[$k] = $cookie; + if ($zvalIsRef = $vals[$k] === $cookie) { $vals[$k] = &$stub; // Break hard references to make $queue completely unset($stub); // independent from the original structure - if (isset($hardRefs[$zval['zval_hash']])) { - $vals[$k] = $useExt ? ($v = $hardRefs[$zval['zval_hash']]) : ($refs[$k] = $v); + if ($v instanceof Stub && isset($hardRefs[\spl_object_hash($v)])) { + $vals[$k] = $refs[$k] = $v; if ($v->value instanceof Stub && (Stub::TYPE_OBJECT === $v->value->type || Stub::TYPE_RESOURCE === $v->value->type)) { ++$v->value->refCount; } ++$v->refCount; continue; } + $refs[$k] = $vals[$k] = new Stub(); + $refs[$k]->value = $v; + $h = \spl_object_hash($refs[$k]); + $hardRefs[$h] = &$refs[$k]; + $values[$h] = $v; + $vals[$k]->handle = ++$refsCounter; } // Create $stub when the original value $v can not be used directly // If $v is a nested structure, put that structure in array $a - switch ($zval['type']) { - case 'string': - if (isset($v[0]) && !preg_match('//u', $v)) { + switch (true) { + case empty($v): + case true === $v: + case \is_int($v): + case \is_float($v): + break; + + case \is_string($v): + if (!\preg_match('//u', $v)) { $stub = new Stub(); $stub->type = Stub::TYPE_STRING; $stub->class = Stub::STRING_BINARY; - if (0 <= $maxString && 0 < $cut = strlen($v) - $maxString) { + if (0 <= $maxString && 0 < $cut = \strlen($v) - $maxString) { $stub->cut = $cut; - $stub->value = substr($v, 0, -$cut); + $stub->value = \substr($v, 0, -$cut); } else { $stub->value = $v; } - } elseif (0 <= $maxString && isset($v[1 + ($maxString >> 2)]) && 0 < $cut = mb_strlen($v, 'UTF-8') - $maxString) { + } elseif (0 <= $maxString && isset($v[1 + ($maxString >> 2)]) && 0 < $cut = \mb_strlen($v, 'UTF-8') - $maxString) { $stub = new Stub(); $stub->type = Stub::TYPE_STRING; $stub->class = Stub::STRING_UTF8; $stub->cut = $cut; - $stub->value = mb_substr($v, 0, $maxString, 'UTF-8'); + $stub->value = \mb_substr($v, 0, $maxString, 'UTF-8'); } break; - case 'integer': - break; + case \is_array($v): + $stub = $arrayStub; + $stub->class = Stub::ARRAY_INDEXED; - case 'array': - if ($v) { - $stub = $arrayRefs[$len] = new Stub(); - $stub->type = Stub::TYPE_ARRAY; - $stub->class = Stub::ARRAY_ASSOC; + $j = -1; + foreach ($v as $gk => $gv) { + if ($gk !== ++$j) { + $stub->class = Stub::ARRAY_ASSOC; + break; + } + } + $a = $v; + if (Stub::ARRAY_ASSOC === $stub->class) { // Copies of $GLOBALS have very strange behavior, // let's detect them with some black magic - $a = $v; $a[$gid] = true; // Happens with copies of $GLOBALS @@ -136,19 +142,23 @@ protected function doClone($var) foreach ($v as $gk => &$gv) { $a[$gk] = &$gv; } + unset($gv); } else { $a = $v; } - - $stub->value = $zval['array_count'] ?: count($a); + } else { + $indexedArrays[$len] = true; } + + $stub->value = \count($a); break; - case 'object': - if (empty($objRefs[$h = $zval['object_handle'] ?: ($hashMask ^ hexdec(substr(spl_object_hash($v), $hashOffset, PHP_INT_SIZE)))])) { + case \is_object($v): + case $v instanceof \__PHP_Incomplete_Class: + if (empty($objRefs[$h = $hashMask ^ \hexdec(\substr(\spl_object_hash($v), $hashOffset, \PHP_INT_SIZE))])) { $stub = new Stub(); $stub->type = Stub::TYPE_OBJECT; - $stub->class = $zval['object_class'] ?: get_class($v); + $stub->class = \get_class($v); $stub->value = $v; $stub->handle = $h; $a = $this->castObject($stub, 0 < $i); @@ -156,18 +166,12 @@ protected function doClone($var) if (Stub::TYPE_OBJECT !== $stub->type || null === $stub->value) { break; } - if ($useExt) { - $zval['type'] = $stub->value; - $zval = symfony_zval_info('type', $zval); - $h = $zval['object_handle']; - } else { - $h = $hashMask ^ hexdec(substr(spl_object_hash($stub->value), $hashOffset, PHP_INT_SIZE)); - } + $h = $hashMask ^ \hexdec(\substr(\spl_object_hash($stub->value), $hashOffset, \PHP_INT_SIZE)); $stub->handle = $h; } $stub->value = null; if (0 <= $maxItems && $maxItems <= $pos) { - $stub->cut = count($a); + $stub->cut = \count($a); $a = null; } } @@ -180,13 +184,11 @@ protected function doClone($var) } break; - case 'resource': - case 'unknown type': - case 'resource (closed)': + default: // resource if (empty($resRefs[$h = (int) $v])) { $stub = new Stub(); $stub->type = Stub::TYPE_RESOURCE; - if ('Unknown' === $stub->class = $zval['resource_type'] ?: @get_resource_type($v)) { + if ('Unknown' === $stub->class = @\get_resource_type($v)) { $stub->class = 'Closed'; } $stub->value = $v; @@ -194,7 +196,7 @@ protected function doClone($var) $a = $this->castResource($stub, 0 < $i); $stub->value = null; if (0 <= $maxItems && $maxItems <= $pos) { - $stub->cut = count($a); + $stub->cut = \count($a); $a = null; } } @@ -209,66 +211,51 @@ protected function doClone($var) } if (isset($stub)) { - if ($zval['zval_isref']) { - if ($useExt) { - $vals[$k] = $hardRefs[$zval['zval_hash']] = $v = new Stub(); - $v->value = $stub; - } else { - $refs[$k] = new Stub(); - $refs[$k]->value = $stub; - $h = spl_object_hash($refs[$k]); - $vals[$k] = $hardRefs[$h] = &$refs[$k]; - $values[$h] = $v; - } - $vals[$k]->handle = ++$refsCounter; - } else { - $vals[$k] = $stub; - } - if ($a) { - if ($i && 0 <= $maxItems) { - $k = count($a); - if ($pos < $maxItems) { - if ($maxItems < $pos += $k) { - $a = array_slice($a, 0, $maxItems - $pos); - if ($stub->cut >= 0) { - $stub->cut += $pos - $maxItems; - } - } - } else { + if (!$i || 0 > $maxItems) { + $queue[$len] = $a; + $stub->position = $len++; + } elseif ($pos < $maxItems) { + if ($maxItems < $pos += \count($a)) { + $a = \array_slice($a, 0, $maxItems - $pos); if ($stub->cut >= 0) { - $stub->cut += $k; + $stub->cut += $pos - $maxItems; } - $stub = $a = null; - unset($arrayRefs[$len]); - continue; } + $queue[$len] = $a; + $stub->position = $len++; + } elseif ($stub->cut >= 0) { + $stub->cut += \count($a); + $stub->position = 0; } - $queue[$len] = $a; - $stub->position = $len++; } - $stub = $a = null; - } elseif ($zval['zval_isref']) { - if ($useExt) { - $vals[$k] = $hardRefs[$zval['zval_hash']] = new Stub(); - $vals[$k]->value = $v; + + if ($arrayStub === $stub) { + if ($arrayStub->cut) { + $stub = array($arrayStub->cut, $arrayStub->class => $arrayStub->position); + $arrayStub->cut = 0; + } else { + $stub = array($arrayStub->class => $arrayStub->position); + } + } + + if ($zvalIsRef) { + $refs[$k]->value = $stub; } else { - $refs[$k] = $vals[$k] = new Stub(); - $refs[$k]->value = $v; - $h = spl_object_hash($refs[$k]); - $hardRefs[$h] = &$refs[$k]; - $values[$h] = $v; + $vals[$k] = $stub; } - $vals[$k]->handle = ++$refsCounter; + + $stub = $a = null; } } if ($fromObjCast) { + $fromObjCast = false; $refs = $vals; $vals = array(); $j = -1; foreach ($queue[$i] as $k => $v) { - foreach (array($k => $v) as $a => $v) { + foreach (array($k => true) as $a => $v) { } if ($a !== $k) { $vals = (object) $vals; @@ -281,13 +268,7 @@ protected function doClone($var) } $queue[$i] = $vals; - - if (isset($arrayRefs[$i])) { - if ($indexed) { - $arrayRefs[$i]->class = Stub::ARRAY_INDEXED; - } - unset($arrayRefs[$i]); - } + unset($indexedArrays[$i]); } foreach ($values as $h => $v) { diff --git a/src/Symfony/Component/VarDumper/Tests/Cloner/VarClonerTest.php b/src/Symfony/Component/VarDumper/Tests/Cloner/VarClonerTest.php index 75774170f32ee..8509afaaccb24 100644 --- a/src/Symfony/Component/VarDumper/Tests/Cloner/VarClonerTest.php +++ b/src/Symfony/Component/VarDumper/Tests/Cloner/VarClonerTest.php @@ -33,19 +33,9 @@ public function testMaxIntBoundary() ( [0] => Array ( - [0] => Symfony\Component\VarDumper\Cloner\Stub Object + [0] => Array ( - [type] => array - [class] => assoc - [value] => 1 - [cut] => 0 - [handle] => 0 - [refCount] => 0 - [position] => 1 - [attr] => Array - ( - ) - + [1] => 1 ) ) @@ -84,7 +74,7 @@ public function testClone() ( [0] => Symfony\Component\VarDumper\Cloner\Stub Object ( - [type] => object + [type] => 4 [class] => stdClass [value] => [cut] => 0 @@ -103,7 +93,7 @@ public function testClone() ( [\000+\0001] => Symfony\Component\VarDumper\Cloner\Stub Object ( - [type] => object + [type] => 4 [class] => stdClass [value] => [cut] => 0 @@ -118,7 +108,7 @@ public function testClone() [\000+\0002] => Symfony\Component\VarDumper\Cloner\Stub Object ( - [type] => object + [type] => 4 [class] => stdClass [value] => [cut] => 0 @@ -174,24 +164,9 @@ public function testJsonCast() [0]=> array(1) { [0]=> - object(Symfony\Component\VarDumper\Cloner\Stub)#%i (8) { - ["type"]=> - string(5) "array" - ["class"]=> - string(5) "assoc" - ["value"]=> + array(1) { + [1]=> int(1) - ["cut"]=> - int(0) - ["handle"]=> - int(0) - ["refCount"]=> - int(0) - ["position"]=> - int(1) - ["attr"]=> - array(0) { - } } } [1]=> @@ -199,7 +174,7 @@ public function testJsonCast() ["1"]=> object(Symfony\Component\VarDumper\Cloner\Stub)#%i (8) { ["type"]=> - string(6) "object" + int(4) ["class"]=> string(8) "stdClass" ["value"]=> @@ -259,7 +234,7 @@ public function testCaster() ( [0] => Symfony\Component\VarDumper\Cloner\Stub Object ( - [type] => object + [type] => 4 [class] => %s [value] => [cut] => 0 From 973b2d39730a64613ee0e3f0d6a312f9cddc81cb Mon Sep 17 00:00:00 2001 From: fmarchalemisys <30406081+fmarchalemisys@users.noreply.github.com> Date: Mon, 24 Jul 2017 16:01:47 +0200 Subject: [PATCH 0512/1099] [Form][TwigBridge] Don't render _method in form_rest() for a child form --- .../Bridge/Twig/Resources/views/Form/form_div_layout.html.twig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 0a52cc5110c82..a27c81dd495ae 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 @@ -303,7 +303,7 @@ {% endif %} {%- endfor %} - {% if not form.methodRendered %} + {% if not form.methodRendered and form.parent is null %} {%- do form.setMethodRendered() -%} {% set method = method|upper %} {%- if method in ["GET", "POST"] -%} From f3da6cf6a2d09c860b419572a30d2cd20c73c1d9 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Mon, 24 Jul 2017 22:27:32 +0200 Subject: [PATCH 0513/1099] [DI] Fix using private services in expressions --- .../Compiler/AnalyzeServiceReferencesPass.php | 28 +++++++ .../DependencyInjection/Dumper/PhpDumper.php | 10 ++- .../ExpressionLanguage.php | 4 +- .../ExpressionLanguageProvider.php | 9 +- .../Tests/Dumper/PhpDumperTest.php | 16 ++++ .../Tests/Fixtures/php/services9.php | 2 +- .../Tests/Fixtures/php/services9_compiled.php | 2 +- .../php/services_private_in_expression.php | 83 +++++++++++++++++++ 8 files changed, 148 insertions(+), 6 deletions(-) create mode 100644 src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_private_in_expression.php diff --git a/src/Symfony/Component/DependencyInjection/Compiler/AnalyzeServiceReferencesPass.php b/src/Symfony/Component/DependencyInjection/Compiler/AnalyzeServiceReferencesPass.php index 717fc378e498e..68b2a0217263c 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/AnalyzeServiceReferencesPass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/AnalyzeServiceReferencesPass.php @@ -12,8 +12,10 @@ namespace Symfony\Component\DependencyInjection\Compiler; use Symfony\Component\DependencyInjection\Definition; +use Symfony\Component\DependencyInjection\ExpressionLanguage; use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\ExpressionLanguage\Expression; /** * Run this pass before passes that need to know more about the relation of @@ -32,6 +34,7 @@ class AnalyzeServiceReferencesPass implements RepeatablePassInterface private $currentDefinition; private $repeatedPass; private $onlyConstructorArguments; + private $expressionLanguage; /** * @param bool $onlyConstructorArguments Sets this Service Reference pass to ignore method calls @@ -97,6 +100,8 @@ private function processArguments(array $arguments) foreach ($arguments as $argument) { if (is_array($argument)) { $this->processArguments($argument); + } elseif ($argument instanceof Expression) { + $this->getExpressionLanguage()->compile((string) $argument, array('this' => 'container')); } elseif ($argument instanceof Reference) { $this->graph->connect( $this->currentId, @@ -143,4 +148,27 @@ private function getDefinitionId($id) return $id; } + + private function getExpressionLanguage() + { + if (null === $this->expressionLanguage) { + $providers = $this->container->getExpressionLanguageProviders(); + $this->expressionLanguage = new ExpressionLanguage(null, $providers, function ($arg) { + if ('""' === substr_replace($arg, '', 1, -1)) { + $id = stripcslashes(substr($arg, 1, -1)); + + $this->graph->connect( + $this->currentId, + $this->currentDefinition, + $this->getDefinitionId($id), + $this->getDefinition($id) + ); + } + + return sprintf('$this->get(%s)', $arg); + }); + } + + return $this->expressionLanguage; + } } diff --git a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php index 19b1ba17c7ffb..c43b677883e18 100644 --- a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php +++ b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php @@ -1597,7 +1597,15 @@ private function getExpressionLanguage() throw new RuntimeException('Unable to use expressions as the Symfony ExpressionLanguage component is not installed.'); } $providers = $this->container->getExpressionLanguageProviders(); - $this->expressionLanguage = new ExpressionLanguage(null, $providers); + $this->expressionLanguage = new ExpressionLanguage(null, $providers, function ($arg) { + $id = '""' === substr_replace($arg, '', 1, -1) ? stripcslashes(substr($arg, 1, -1)) : null; + + if (null !== $id && ($this->container->hasAlias($id) || $this->container->hasDefinition($id))) { + return $this->getServiceCall($id); + } + + return sprintf('$this->get(%s)', $arg); + }); if ($this->container->isTrackingResources()) { foreach ($providers as $provider) { diff --git a/src/Symfony/Component/DependencyInjection/ExpressionLanguage.php b/src/Symfony/Component/DependencyInjection/ExpressionLanguage.php index d80985fa670e5..051d41b84ba4b 100644 --- a/src/Symfony/Component/DependencyInjection/ExpressionLanguage.php +++ b/src/Symfony/Component/DependencyInjection/ExpressionLanguage.php @@ -25,10 +25,10 @@ class ExpressionLanguage extends BaseExpressionLanguage /** * {@inheritdoc} */ - public function __construct($cache = null, array $providers = array()) + public function __construct($cache = null, array $providers = array(), callable $serviceCompiler = null) { // prepend the default provider to let users override it easily - array_unshift($providers, new ExpressionLanguageProvider()); + array_unshift($providers, new ExpressionLanguageProvider($serviceCompiler)); parent::__construct($cache, $providers); } diff --git a/src/Symfony/Component/DependencyInjection/ExpressionLanguageProvider.php b/src/Symfony/Component/DependencyInjection/ExpressionLanguageProvider.php index ce6d69522e191..e2084aa85da6d 100644 --- a/src/Symfony/Component/DependencyInjection/ExpressionLanguageProvider.php +++ b/src/Symfony/Component/DependencyInjection/ExpressionLanguageProvider.php @@ -24,10 +24,17 @@ */ class ExpressionLanguageProvider implements ExpressionFunctionProviderInterface { + private $serviceCompiler; + + public function __construct(callable $serviceCompiler = null) + { + $this->serviceCompiler = $serviceCompiler; + } + public function getFunctions() { return array( - new ExpressionFunction('service', function ($arg) { + new ExpressionFunction('service', $this->serviceCompiler ?: function ($arg) { return sprintf('$this->get(%s)', $arg); }, function (array $variables, $value) { return $variables['container']->get($value); diff --git a/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php b/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php index 2ff01d120b169..179650df467ad 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php @@ -425,6 +425,22 @@ public function testPrivateWithIgnoreOnInvalidReference() $this->assertInstanceOf('BazClass', $container->get('bar')->getBaz()); } + public function testExpressionReferencingPrivateService() + { + $container = new ContainerBuilder(); + $container->register('private_bar', 'stdClass') + ->setPublic(false); + $container->register('private_foo', 'stdClass') + ->setPublic(false); + $container->register('public_foo', 'stdClass') + ->addArgument(new Expression('service("private_foo")')); + + $container->compile(); + $dumper = new PhpDumper($container); + + $this->assertStringEqualsFile(self::$fixturesPath.'/php/services_private_in_expression.php', $dumper->dump()); + } + public function testDumpHandlesLiteralClassWithRootNamespace() { $container = new ContainerBuilder(); diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9.php index 306375d1b5541..0f5789fef3fd8 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9.php @@ -306,7 +306,7 @@ protected function getMethodCall1Service() if ($this->has('foobaz')) { $instance->setBar($this->get('foobaz', ContainerInterface::NULL_ON_INVALID_REFERENCE)); } - $instance->setBar(($this->get("foo")->foo() . (($this->hasParameter("foo")) ? ($this->getParameter("foo")) : ("default")))); + $instance->setBar(($this->get('foo')->foo() . (($this->hasParameter("foo")) ? ($this->getParameter("foo")) : ("default")))); return $instance; } diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_compiled.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_compiled.php index f8b263c2a01f3..751b76c852c5e 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_compiled.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_compiled.php @@ -299,7 +299,7 @@ protected function getMethodCall1Service() $instance->setBar($this->get('foo')); $instance->setBar(NULL); - $instance->setBar(($this->get("foo")->foo() . (($this->hasParameter("foo")) ? ($this->getParameter("foo")) : ("default")))); + $instance->setBar(($this->get('foo')->foo() . (($this->hasParameter("foo")) ? ($this->getParameter("foo")) : ("default")))); return $instance; } diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_private_in_expression.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_private_in_expression.php new file mode 100644 index 0000000000000..a50653f55b6eb --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_private_in_expression.php @@ -0,0 +1,83 @@ +services = array(); + $this->methodMap = array( + 'private_foo' => 'getPrivateFooService', + 'public_foo' => 'getPublicFooService', + ); + $this->privates = array( + 'private_foo' => true, + ); + + $this->aliases = array(); + } + + /** + * {@inheritdoc} + */ + public function compile() + { + throw new LogicException('You cannot compile a dumped frozen container.'); + } + + /** + * {@inheritdoc} + */ + public function isFrozen() + { + return true; + } + + /** + * Gets the 'public_foo' service. + * + * This service is shared. + * This method always returns the same instance of the service. + * + * @return \stdClass A stdClass instance + */ + protected function getPublicFooService() + { + return $this->services['public_foo'] = new \stdClass(${($_ = isset($this->services['private_foo']) ? $this->services['private_foo'] : $this->getPrivateFooService()) && false ?: '_'}); + } + + /** + * Gets the 'private_foo' service. + * + * This service is shared. + * This method always returns the same instance of the service. + * + * This service is private. + * If you want to be able to request this service from the container directly, + * make it public, otherwise you might end up with broken code. + * + * @return \stdClass A stdClass instance + */ + protected function getPrivateFooService() + { + return $this->services['private_foo'] = new \stdClass(); + } +} From 3c2f5f7a248fb8675e9d5259714eae388eb81e4d Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Tue, 25 Jul 2017 16:01:38 +0200 Subject: [PATCH 0514/1099] [VarDumper] Adapt to php 7.2 changes --- .../Component/VarDumper/Caster/Caster.php | 2 +- .../VarDumper/Tests/CliDumperTest.php | 47 +++++++++++++++---- .../VarDumper/Tests/VarClonerTest.php | 2 +- 3 files changed, 39 insertions(+), 12 deletions(-) diff --git a/src/Symfony/Component/VarDumper/Caster/Caster.php b/src/Symfony/Component/VarDumper/Caster/Caster.php index db052c8498a15..4123870043abc 100644 --- a/src/Symfony/Component/VarDumper/Caster/Caster.php +++ b/src/Symfony/Component/VarDumper/Caster/Caster.php @@ -54,7 +54,7 @@ public static function castObject($obj, \ReflectionClass $reflector) if ($a) { $p = array_keys($a); foreach ($p as $i => $k) { - if (isset($k[0]) && "\0" !== $k[0] && !$reflector->hasProperty($k)) { + if (isset($k[0]) ? "\0" !== $k[0] && !$reflector->hasProperty($k) : \PHP_VERSION_ID >= 70200) { $p[$i] = self::PREFIX_DYNAMIC.$k; } elseif (isset($k[16]) && "\0" === $k[16] && 0 === strpos($k, "\0class@anonymous\0")) { $p[$i] = "\0".$reflector->getParentClass().'@anonymous'.strrchr($k, "\0"); diff --git a/src/Symfony/Component/VarDumper/Tests/CliDumperTest.php b/src/Symfony/Component/VarDumper/Tests/CliDumperTest.php index f8acf0d562438..ebf5eed35e8ce 100644 --- a/src/Symfony/Component/VarDumper/Tests/CliDumperTest.php +++ b/src/Symfony/Component/VarDumper/Tests/CliDumperTest.php @@ -141,8 +141,22 @@ public function testJsonCast() $var[] = &$v; $var[''] = 2; - $this->assertDumpMatchesFormat( - <<<'EOTXT' + if (\PHP_VERSION_ID >= 70200) { + $this->assertDumpMatchesFormat( + <<<'EOTXT' +array:4 [ + 0 => {} + 1 => &1 null + 2 => &1 null + "" => 2 +] +EOTXT + , + $var + ); + } else { + $this->assertDumpMatchesFormat( + <<<'EOTXT' array:4 [ "0" => {} "1" => &1 null @@ -150,9 +164,10 @@ public function testJsonCast() "" => 2 ] EOTXT - , - $var - ); + , + $var + ); + } } public function testObjectCast() @@ -160,16 +175,28 @@ public function testObjectCast() $var = (object) array(1 => 1); $var->{1} = 2; - $this->assertDumpMatchesFormat( - <<<'EOTXT' + if (\PHP_VERSION_ID >= 70200) { + $this->assertDumpMatchesFormat( + <<<'EOTXT' +{ + +"1": 2 +} +EOTXT + , + $var + ); + } else { + $this->assertDumpMatchesFormat( + <<<'EOTXT' { +1: 1 +"1": 2 } EOTXT - , - $var - ); + , + $var + ); + } } public function testClosedResource() diff --git a/src/Symfony/Component/VarDumper/Tests/VarClonerTest.php b/src/Symfony/Component/VarDumper/Tests/VarClonerTest.php index 8ca59bdddfe71..6e98d6ecbcd78 100644 --- a/src/Symfony/Component/VarDumper/Tests/VarClonerTest.php +++ b/src/Symfony/Component/VarDumper/Tests/VarClonerTest.php @@ -203,7 +203,7 @@ public function testJsonCast() EOTXT; ob_start(); var_dump($clone); - $this->assertStringMatchesFormat($expected, ob_get_clean()); + $this->assertStringMatchesFormat(\PHP_VERSION_ID >= 70200 ? str_replace('"1"', '1', $expected) : $expected, ob_get_clean()); } public function testCaster() From eebae7ec7124def32d8d9153da4e4b174219885c Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Wed, 26 Jul 2017 08:11:54 +0200 Subject: [PATCH 0515/1099] [DI] use assertStringEqualsFile when possible --- .../DependencyInjection/Tests/Dumper/PhpDumperTest.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php b/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php index 1ce5b7b9993d8..e238649361a3f 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php @@ -119,13 +119,13 @@ public function testAddService() // without compilation $container = include self::$fixturesPath.'/containers/container9.php'; $dumper = new PhpDumper($container); - $this->assertEquals(str_replace('%path%', str_replace('\\', '\\\\', self::$fixturesPath.DIRECTORY_SEPARATOR.'includes'.DIRECTORY_SEPARATOR), file_get_contents(self::$fixturesPath.'/php/services9.php')), $dumper->dump(), '->dump() dumps services'); + $this->assertStringEqualsFile(self::$fixturesPath.'/php/services9.php', str_replace(str_replace('\\', '\\\\', self::$fixturesPath.DIRECTORY_SEPARATOR.'includes'.DIRECTORY_SEPARATOR), '%path%', $dumper->dump()), '->dump() dumps services'); // with compilation $container = include self::$fixturesPath.'/containers/container9.php'; $container->compile(); $dumper = new PhpDumper($container); - $this->assertEquals(str_replace('%path%', str_replace('\\', '\\\\', self::$fixturesPath.DIRECTORY_SEPARATOR.'includes'.DIRECTORY_SEPARATOR), file_get_contents(self::$fixturesPath.'/php/services9_compiled.php')), $dumper->dump(), '->dump() dumps services'); + $this->assertStringEqualsFile(self::$fixturesPath.'/php/services9_compiled.php', str_replace(str_replace('\\', '\\\\', self::$fixturesPath.DIRECTORY_SEPARATOR.'includes'.DIRECTORY_SEPARATOR), '%path%', $dumper->dump()), '->dump() dumps services'); $dumper = new PhpDumper($container = new ContainerBuilder()); $container->register('foo', 'FooClass')->addArgument(new \stdClass()); @@ -145,7 +145,7 @@ public function testLegacySynchronizedServices() { $container = include self::$fixturesPath.'/containers/container20.php'; $dumper = new PhpDumper($container); - $this->assertEquals(str_replace('%path%', str_replace('\\', '\\\\', self::$fixturesPath.DIRECTORY_SEPARATOR.'includes'.DIRECTORY_SEPARATOR), file_get_contents(self::$fixturesPath.'/php/services20.php')), $dumper->dump(), '->dump() dumps services'); + $this->assertStringEqualsFile(self::$fixturesPath.'/php/services20.php', str_replace(str_replace('\\', '\\\\', self::$fixturesPath.DIRECTORY_SEPARATOR.'includes'.DIRECTORY_SEPARATOR), '%path%', $dumper->dump()), '->dump() dumps services'); } public function testServicesWithAnonymousFactories() From 8b1199767b62cf07b5a639f4008b2fe2959089fc Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Wed, 26 Jul 2017 09:14:13 +0200 Subject: [PATCH 0516/1099] [DI] cleanup --- .../DependencyInjection/Dumper/PhpDumper.php | 10 +- .../Tests/ContainerTest.php | 2 +- .../Tests/Dumper/PhpDumperTest.php | 2 +- .../Tests/Fixtures/php/services9.php | 547 ------------------ 4 files changed, 7 insertions(+), 554 deletions(-) delete mode 100644 src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9.php diff --git a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php index 6d66780827e7d..b1a326912ee1f 100644 --- a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php +++ b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php @@ -548,7 +548,7 @@ private function addServiceConfigurator($id, Definition $definition, $variableNa } $class = $this->dumpValue($callable[0]); - // If the class is a string we can optimize call_user_func away + // If the class is a string we can optimize away if (0 === strpos($class, "'") && false === strpos($class, '$')) { return sprintf(" %s::%s(\$%s);\n", $this->dumpLiteralClass($class), $callable[1], $variableName); } @@ -557,7 +557,7 @@ private function addServiceConfigurator($id, Definition $definition, $variableNa return sprintf(" (%s)->%s(\$%s);\n", $this->dumpValue($callable[0]), $callable[1], $variableName); } - return sprintf(" call_user_func(array(%s, '%s'), \$%s);\n", $this->dumpValue($callable[0]), $callable[1], $variableName); + return sprintf(" [%s, '%s'](\$%s);\n", $this->dumpValue($callable[0]), $callable[1], $variableName); } return sprintf(" %s(\$%s);\n", $callable, $variableName); @@ -731,7 +731,7 @@ private function addNewInstance(Definition $definition, $return, $instantiation, } $class = $this->dumpValue($callable[0]); - // If the class is a string we can optimize call_user_func away + // If the class is a string we can optimize away if (0 === strpos($class, "'") && false === strpos($class, '$')) { if ("''" === $class) { throw new RuntimeException(sprintf('Cannot dump definition: The "%s" service is defined to be created by a factory but is missing the service reference, did you forget to define the factory service id or class?', $id)); @@ -744,7 +744,7 @@ private function addNewInstance(Definition $definition, $return, $instantiation, return sprintf(" $return{$instantiation}(%s)->%s(%s);\n", $this->dumpValue($callable[0]), $callable[1], $arguments ? implode(', ', $arguments) : ''); } - return sprintf(" $return{$instantiation}call_user_func(array(%s, '%s')%s);\n", $this->dumpValue($callable[0]), $callable[1], $arguments ? ', '.implode(', ', $arguments) : ''); + return sprintf(" $return{$instantiation}[%s, '%s'](%s);\n", $this->dumpValue($callable[0]), $callable[1], $arguments ? implode(', ', $arguments) : ''); } return sprintf(" $return{$instantiation}%s(%s);\n", $this->dumpLiteralClass($this->dumpValue($callable)), $arguments ? implode(', ', $arguments) : ''); @@ -1411,7 +1411,7 @@ private function dumpValue($value, $interpolate = true) } if ($factory[0] instanceof Definition) { - return sprintf("call_user_func(array(%s, '%s')%s)", $this->dumpValue($factory[0]), $factory[1], count($arguments) > 0 ? ', '.implode(', ', $arguments) : ''); + return sprintf("[%s, '%s'](%s)", $this->dumpValue($factory[0]), $factory[1], implode(', ', $arguments)); } if ($factory[0] instanceof Reference) { diff --git a/src/Symfony/Component/DependencyInjection/Tests/ContainerTest.php b/src/Symfony/Component/DependencyInjection/Tests/ContainerTest.php index 6e72c6075d9e2..46780ed3f01ac 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/ContainerTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/ContainerTest.php @@ -230,7 +230,7 @@ public function testGetCircularReference() */ public function testGetSyntheticServiceThrows() { - require_once __DIR__.'/Fixtures/php/services9.php'; + require_once __DIR__.'/Fixtures/php/services9_compiled.php'; $container = new \ProjectServiceContainer(); $container->get('request'); diff --git a/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php b/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php index 3c2e98cb218d5..8a70f8d381a56 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php @@ -272,7 +272,7 @@ public function testFrozenContainerWithoutAliases() */ public function testOverrideServiceWhenUsingADumpedContainer() { - require_once self::$fixturesPath.'/php/services9.php'; + require_once self::$fixturesPath.'/php/services9_compiled.php'; require_once self::$fixturesPath.'/includes/foo.php'; $container = new \ProjectServiceContainer(); diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9.php deleted file mode 100644 index a568de2997265..0000000000000 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9.php +++ /dev/null @@ -1,547 +0,0 @@ -getDefaultParameters())); - $this->methodMap = array( - 'BAR' => 'getBARService', - 'BAR2' => 'getBAR2Service', - 'bar' => 'getBar3Service', - 'bar2' => 'getBar22Service', - 'baz' => 'getBazService', - 'configurator_service' => 'getConfiguratorServiceService', - 'configurator_service_simple' => 'getConfiguratorServiceSimpleService', - 'configured_service' => 'getConfiguredServiceService', - 'configured_service_simple' => 'getConfiguredServiceSimpleService', - 'decorated' => 'getDecoratedService', - 'decorator_service' => 'getDecoratorServiceService', - 'decorator_service_with_name' => 'getDecoratorServiceWithNameService', - 'deprecated_service' => 'getDeprecatedServiceService', - 'factory_service' => 'getFactoryServiceService', - 'factory_service_simple' => 'getFactoryServiceSimpleService', - 'factory_simple' => 'getFactorySimpleService', - 'foo' => 'getFooService', - 'foo.baz' => 'getFoo_BazService', - 'foo_bar' => 'getFooBarService', - 'foo_with_inline' => 'getFooWithInlineService', - 'inlined' => 'getInlinedService', - 'lazy_context' => 'getLazyContextService', - 'lazy_context_ignore_invalid_ref' => 'getLazyContextIgnoreInvalidRefService', - 'method_call1' => 'getMethodCall1Service', - 'new_factory' => 'getNewFactoryService', - 'new_factory_service' => 'getNewFactoryServiceService', - 'service_from_static_method' => 'getServiceFromStaticMethodService', - ); - $this->privates = array( - 'configurator_service' => true, - 'configurator_service_simple' => true, - 'factory_simple' => true, - 'inlined' => true, - 'new_factory' => true, - ); - $this->aliases = array( - 'Psr\\Container\\ContainerInterface' => 'service_container', - 'Symfony\\Component\\DependencyInjection\\ContainerInterface' => 'service_container', - 'alias_for_alias' => 'foo', - 'alias_for_foo' => 'foo', - ); - } - - /** - * Gets the 'BAR' service. - * - * This service is shared. - * This method always returns the same instance of the service. - * - * @return \stdClass A stdClass instance - */ - protected function getBARService() - { - $this->services['BAR'] = $instance = new \stdClass(); - - $instance->bar = ($this->services['bar'] ?? $this->get('bar')); - - return $instance; - } - - /** - * Gets the 'BAR2' service. - * - * This service is shared. - * This method always returns the same instance of the service. - * - * @return \stdClass A stdClass instance - */ - protected function getBAR2Service() - { - return $this->services['BAR2'] = new \stdClass(); - } - - /** - * Gets the 'bar' service. - * - * This service is shared. - * This method always returns the same instance of the service. - * - * @return \Bar\FooClass A Bar\FooClass instance - */ - protected function getBar3Service() - { - $a = ($this->services['foo.baz'] ?? $this->get('foo.baz')); - - $this->services['bar'] = $instance = new \Bar\FooClass('foo', $a, $this->getParameter('foo_bar')); - - $a->configure($instance); - - return $instance; - } - - /** - * Gets the 'bar2' service. - * - * This service is shared. - * This method always returns the same instance of the service. - * - * @return \stdClass A stdClass instance - */ - protected function getBar22Service() - { - return $this->services['bar2'] = new \stdClass(); - } - - /** - * Gets the 'baz' service. - * - * This service is shared. - * This method always returns the same instance of the service. - * - * @return \Baz A Baz instance - */ - protected function getBazService() - { - $this->services['baz'] = $instance = new \Baz(); - - $instance->setFoo(($this->services['foo_with_inline'] ?? $this->get('foo_with_inline'))); - - return $instance; - } - - /** - * Gets the 'configured_service' service. - * - * This service is shared. - * This method always returns the same instance of the service. - * - * @return \stdClass A stdClass instance - */ - protected function getConfiguredServiceService() - { - $this->services['configured_service'] = $instance = new \stdClass(); - - ($this->services['configurator_service'] ?? $this->getConfiguratorServiceService())->configureStdClass($instance); - - return $instance; - } - - /** - * Gets the 'configured_service_simple' service. - * - * This service is shared. - * This method always returns the same instance of the service. - * - * @return \stdClass A stdClass instance - */ - protected function getConfiguredServiceSimpleService() - { - $this->services['configured_service_simple'] = $instance = new \stdClass(); - - ($this->services['configurator_service_simple'] ?? $this->getConfiguratorServiceSimpleService())->configureStdClass($instance); - - return $instance; - } - - /** - * Gets the 'decorated' service. - * - * This service is shared. - * This method always returns the same instance of the service. - * - * @return \stdClass A stdClass instance - */ - protected function getDecoratedService() - { - return $this->services['decorated'] = new \stdClass(); - } - - /** - * Gets the 'decorator_service' service. - * - * This service is shared. - * This method always returns the same instance of the service. - * - * @return \stdClass A stdClass instance - */ - protected function getDecoratorServiceService() - { - return $this->services['decorator_service'] = new \stdClass(); - } - - /** - * Gets the 'decorator_service_with_name' service. - * - * This service is shared. - * This method always returns the same instance of the service. - * - * @return \stdClass A stdClass instance - */ - protected function getDecoratorServiceWithNameService() - { - return $this->services['decorator_service_with_name'] = new \stdClass(); - } - - /** - * Gets the 'deprecated_service' service. - * - * This service is shared. - * This method always returns the same instance of the service. - * - * @return \stdClass A stdClass instance - * - * @deprecated The "deprecated_service" service is deprecated. You should stop using it, as it will soon be removed. - */ - protected function getDeprecatedServiceService() - { - @trigger_error('The "deprecated_service" service is deprecated. You should stop using it, as it will soon be removed.', E_USER_DEPRECATED); - - return $this->services['deprecated_service'] = new \stdClass(); - } - - /** - * Gets the 'factory_service' service. - * - * This service is shared. - * This method always returns the same instance of the service. - * - * @return \Bar A Bar instance - */ - protected function getFactoryServiceService() - { - return $this->services['factory_service'] = ($this->services['foo.baz'] ?? $this->get('foo.baz'))->getInstance(); - } - - /** - * Gets the 'factory_service_simple' service. - * - * This service is shared. - * This method always returns the same instance of the service. - * - * @return \Bar A Bar instance - */ - protected function getFactoryServiceSimpleService() - { - return $this->services['factory_service_simple'] = ($this->services['factory_simple'] ?? $this->getFactorySimpleService())->getInstance(); - } - - /** - * Gets the 'foo' service. - * - * This service is shared. - * This method always returns the same instance of the service. - * - * @return \Bar\FooClass A Bar\FooClass instance - */ - protected function getFooService() - { - $a = ($this->services['foo.baz'] ?? $this->get('foo.baz')); - - $this->services['foo'] = $instance = \Bar\FooClass::getInstance('foo', $a, array($this->getParameter('foo') => 'foo is '.$this->getParameter('foo').'', 'foobar' => $this->getParameter('foo')), true, $this); - - $instance->foo = 'bar'; - $instance->moo = $a; - $instance->qux = array($this->getParameter('foo') => 'foo is '.$this->getParameter('foo').'', 'foobar' => $this->getParameter('foo')); - $instance->setBar(($this->services['bar'] ?? $this->get('bar'))); - $instance->initialize(); - sc_configure($instance); - - return $instance; - } - - /** - * Gets the 'foo.baz' service. - * - * This service is shared. - * This method always returns the same instance of the service. - * - * @return object A %baz_class% instance - */ - protected function getFoo_BazService() - { - $this->services['foo.baz'] = $instance = call_user_func(array($this->getParameter('baz_class'), 'getInstance')); - - call_user_func(array($this->getParameter('baz_class'), 'configureStatic1'), $instance); - - return $instance; - } - - /** - * Gets the 'foo_bar' service. - * - * @return object A %foo_class% instance - */ - protected function getFooBarService() - { - $class = $this->getParameter('foo_class'); - - return new $class(); - } - - /** - * Gets the 'foo_with_inline' service. - * - * This service is shared. - * This method always returns the same instance of the service. - * - * @return \Foo A Foo instance - */ - protected function getFooWithInlineService() - { - $this->services['foo_with_inline'] = $instance = new \Foo(); - - $instance->setBar(($this->services['inlined'] ?? $this->getInlinedService())); - - return $instance; - } - - /** - * Gets the 'lazy_context' service. - * - * This service is shared. - * This method always returns the same instance of the service. - * - * @return \LazyContext A LazyContext instance - */ - protected function getLazyContextService() - { - return $this->services['lazy_context'] = new \LazyContext(new RewindableGenerator(function () { - yield 'k1' => ($this->services['foo.baz'] ?? $this->get('foo.baz')); - yield 'k2' => $this; - }, 2), new RewindableGenerator(function () { - return new \EmptyIterator(); - }, 0)); - } - - /** - * Gets the 'lazy_context_ignore_invalid_ref' service. - * - * This service is shared. - * This method always returns the same instance of the service. - * - * @return \LazyContext A LazyContext instance - */ - protected function getLazyContextIgnoreInvalidRefService() - { - return $this->services['lazy_context_ignore_invalid_ref'] = new \LazyContext(new RewindableGenerator(function () { - yield 0 => ($this->services['foo.baz'] ?? $this->get('foo.baz')); - if ($this->has('invalid')) { - yield 1 => $this->get('invalid', ContainerInterface::NULL_ON_INVALID_REFERENCE); - } - }, function () { - return 1 + (int) ($this->has('invalid')); - }), new RewindableGenerator(function () { - return new \EmptyIterator(); - }, 0)); - } - - /** - * Gets the 'method_call1' service. - * - * This service is shared. - * This method always returns the same instance of the service. - * - * @return \Bar\FooClass A Bar\FooClass instance - */ - protected function getMethodCall1Service() - { - require_once '%path%foo.php'; - - $this->services['method_call1'] = $instance = new \Bar\FooClass(); - - $instance->setBar(($this->services['foo'] ?? $this->get('foo'))); - $instance->setBar($this->get('foo2', ContainerInterface::NULL_ON_INVALID_REFERENCE)); - if ($this->has('foo3')) { - $instance->setBar($this->get('foo3', ContainerInterface::NULL_ON_INVALID_REFERENCE)); - } - if ($this->has('foobaz')) { - $instance->setBar($this->get('foobaz', ContainerInterface::NULL_ON_INVALID_REFERENCE)); - } - $instance->setBar((${($_ = isset($this->services['foo']) ? $this->services['foo'] : $this->get('foo')) && false ?: '_'}->foo() . (($this->hasParameter("foo")) ? ($this->getParameter("foo")) : ("default")))); - - return $instance; - } - - /** - * Gets the 'new_factory_service' service. - * - * This service is shared. - * This method always returns the same instance of the service. - * - * @return \FooBarBaz A FooBarBaz instance - */ - protected function getNewFactoryServiceService() - { - $this->services['new_factory_service'] = $instance = ($this->services['new_factory'] ?? $this->getNewFactoryService())->getInstance(); - - $instance->foo = 'bar'; - - return $instance; - } - - /** - * Gets the 'service_from_static_method' service. - * - * This service is shared. - * This method always returns the same instance of the service. - * - * @return \Bar\FooClass A Bar\FooClass instance - */ - protected function getServiceFromStaticMethodService() - { - return $this->services['service_from_static_method'] = \Bar\FooClass::getInstance(); - } - - /** - * Gets the 'configurator_service' service. - * - * This service is shared. - * This method always returns the same instance of the service. - * - * This service is private. - * If you want to be able to request this service from the container directly, - * make it public, otherwise you might end up with broken code. - * - * @return \ConfClass A ConfClass instance - */ - protected function getConfiguratorServiceService() - { - $this->services['configurator_service'] = $instance = new \ConfClass(); - - $instance->setFoo(($this->services['baz'] ?? $this->get('baz'))); - - return $instance; - } - - /** - * Gets the 'configurator_service_simple' service. - * - * This service is shared. - * This method always returns the same instance of the service. - * - * This service is private. - * If you want to be able to request this service from the container directly, - * make it public, otherwise you might end up with broken code. - * - * @return \ConfClass A ConfClass instance - */ - protected function getConfiguratorServiceSimpleService() - { - return $this->services['configurator_service_simple'] = new \ConfClass('bar'); - } - - /** - * Gets the 'factory_simple' service. - * - * This service is shared. - * This method always returns the same instance of the service. - * - * This service is private. - * If you want to be able to request this service from the container directly, - * make it public, otherwise you might end up with broken code. - * - * @return \SimpleFactoryClass A SimpleFactoryClass instance - */ - protected function getFactorySimpleService() - { - return $this->services['factory_simple'] = new \SimpleFactoryClass('foo'); - } - - /** - * Gets the 'inlined' service. - * - * This service is shared. - * This method always returns the same instance of the service. - * - * This service is private. - * If you want to be able to request this service from the container directly, - * make it public, otherwise you might end up with broken code. - * - * @return \Bar A Bar instance - */ - protected function getInlinedService() - { - $this->services['inlined'] = $instance = new \Bar(); - - $instance->pub = 'pub'; - $instance->setBaz(($this->services['baz'] ?? $this->get('baz'))); - - return $instance; - } - - /** - * Gets the 'new_factory' service. - * - * This service is shared. - * This method always returns the same instance of the service. - * - * This service is private. - * If you want to be able to request this service from the container directly, - * make it public, otherwise you might end up with broken code. - * - * @return \FactoryClass A FactoryClass instance - */ - protected function getNewFactoryService() - { - $this->services['new_factory'] = $instance = new \FactoryClass(); - - $instance->foo = 'bar'; - - return $instance; - } - - /** - * Gets the default parameters. - * - * @return array An array of the default parameters - */ - protected function getDefaultParameters() - { - return array( - 'baz_class' => 'BazClass', - 'foo_class' => 'Bar\\FooClass', - 'foo' => 'bar', - ); - } -} From 1ade5d86583c38836f22ccf4900eb5b608a495e8 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Wed, 26 Jul 2017 09:27:50 +0200 Subject: [PATCH 0517/1099] [DI] Make dumped docblocks less verbose --- .../DependencyInjection/Dumper/PhpDumper.php | 29 +--- .../Tests/Fixtures/php/services10.php | 7 +- .../Tests/Fixtures/php/services12.php | 7 +- .../Tests/Fixtures/php/services13.php | 7 +- .../Tests/Fixtures/php/services19.php | 14 +- .../Tests/Fixtures/php/services20.php | 14 +- .../Tests/Fixtures/php/services9.php | 129 +++++------------- .../Tests/Fixtures/php/services9_compiled.php | 93 ++++--------- 8 files changed, 79 insertions(+), 221 deletions(-) diff --git a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php index 52f6362c73fb3..721c4dc68c62b 100644 --- a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php +++ b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php @@ -565,7 +565,7 @@ private function addService($id, Definition $definition) if ($definition->isSynthetic()) { $return[] = '@throws RuntimeException always since this service is expected to be injected dynamically'; } elseif ($class = $definition->getClass()) { - $return[] = sprintf('@return %s A %s instance', 0 === strpos($class, '%') ? 'object' : '\\'.ltrim($class, '\\'), ltrim($class, '\\')); + $return[] = sprintf(0 === strpos($class, '%') ? '@return object A %1$s instance' : '@return \%s', ltrim($class, '\\')); } elseif ($definition->getFactory()) { $factory = $definition->getFactory(); if (is_string($factory)) { @@ -593,32 +593,13 @@ private function addService($id, Definition $definition) $return = implode("\n * ", $return); - $doc = ''; - if (ContainerInterface::SCOPE_PROTOTYPE !== $scope) { - $doc .= <<<'EOF' - - * - * This service is shared. - * This method always returns the same instance of the service. -EOF; - } - - if (!$definition->isPublic()) { - $doc .= <<<'EOF' - - * - * This service is private. - * If you want to be able to request this service from the container directly, - * make it public, otherwise you might end up with broken code. -EOF; - } + $shared = ContainerInterface::SCOPE_PROTOTYPE !== $scope ? ' shared' : ''; + $public = $definition->isPublic() ? 'public' : 'private'; if ($definition->isLazy()) { $lazyInitialization = '$lazyLoad = true'; - $lazyInitializationDoc = "\n * @param bool \$lazyLoad whether to try lazy-loading the service with a proxy\n *"; } else { $lazyInitialization = ''; - $lazyInitializationDoc = ''; } // with proxies, for 5.3.3 compatibility, the getter must be public to be accessible to the initializer @@ -627,8 +608,8 @@ private function addService($id, Definition $definition) $code = <<docStar} - * Gets the '$id' service.$doc - *$lazyInitializationDoc + * Gets the $public '$id'$shared service. + * * $return */ {$visibility} function get{$this->camelize($id)}Service($lazyInitialization) diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services10.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services10.php index f792957101fac..923c437bb06a1 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services10.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services10.php @@ -55,12 +55,9 @@ public function isFrozen() } /** - * Gets the 'test' service. + * Gets the public 'test' shared service. * - * This service is shared. - * This method always returns the same instance of the service. - * - * @return \stdClass A stdClass instance + * @return \stdClass */ protected function getTestService() { diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services12.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services12.php index 5faa1a9781368..2119719828d67 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services12.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services12.php @@ -59,12 +59,9 @@ public function isFrozen() } /** - * Gets the 'test' service. + * Gets the public 'test' shared service. * - * This service is shared. - * This method always returns the same instance of the service. - * - * @return \stdClass A stdClass instance + * @return \stdClass */ protected function getTestService() { diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services13.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services13.php index 37e3e7e1a1e69..eaf9c4bef0edc 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services13.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services13.php @@ -53,12 +53,9 @@ public function isFrozen() } /** - * Gets the 'bar' service. + * Gets the public 'bar' shared service. * - * This service is shared. - * This method always returns the same instance of the service. - * - * @return \stdClass A stdClass instance + * @return \stdClass */ protected function getBarService() { diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services19.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services19.php index 985f0a96283d5..a3fde04b78a4b 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services19.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services19.php @@ -32,12 +32,9 @@ public function __construct() } /** - * Gets the 'service_from_anonymous_factory' service. + * Gets the public 'service_from_anonymous_factory' shared service. * - * This service is shared. - * This method always returns the same instance of the service. - * - * @return \Bar\FooClass A Bar\FooClass instance + * @return \Bar\FooClass */ protected function getServiceFromAnonymousFactoryService() { @@ -45,12 +42,9 @@ protected function getServiceFromAnonymousFactoryService() } /** - * Gets the 'service_with_method_call_and_factory' service. - * - * This service is shared. - * This method always returns the same instance of the service. + * Gets the public 'service_with_method_call_and_factory' shared service. * - * @return \Bar\FooClass A Bar\FooClass instance + * @return \Bar\FooClass */ protected function getServiceWithMethodCallAndFactoryService() { diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services20.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services20.php index ec0887ecbcab1..ba9a8902e4d06 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services20.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services20.php @@ -32,12 +32,9 @@ public function __construct() } /** - * Gets the 'depends_on_request' service. + * Gets the public 'depends_on_request' shared service. * - * This service is shared. - * This method always returns the same instance of the service. - * - * @return \stdClass A stdClass instance + * @return \stdClass */ protected function getDependsOnRequestService() { @@ -49,12 +46,9 @@ protected function getDependsOnRequestService() } /** - * Gets the 'request' service. - * - * This service is shared. - * This method always returns the same instance of the service. + * Gets the public 'request' shared service. * - * @return \Request A Request instance + * @return \Request */ protected function getRequestService() { diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9.php index ce8930b8ddeba..1d352601431a6 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9.php @@ -52,12 +52,9 @@ public function __construct() } /** - * Gets the 'bar' service. + * Gets the public 'bar' shared service. * - * This service is shared. - * This method always returns the same instance of the service. - * - * @return \Bar\FooClass A Bar\FooClass instance + * @return \Bar\FooClass */ protected function getBarService() { @@ -71,12 +68,9 @@ protected function getBarService() } /** - * Gets the 'baz' service. - * - * This service is shared. - * This method always returns the same instance of the service. + * Gets the public 'baz' shared service. * - * @return \Baz A Baz instance + * @return \Baz */ protected function getBazService() { @@ -88,12 +82,9 @@ protected function getBazService() } /** - * Gets the 'configured_service' service. - * - * This service is shared. - * This method always returns the same instance of the service. + * Gets the public 'configured_service' shared service. * - * @return \stdClass A stdClass instance + * @return \stdClass */ protected function getConfiguredServiceService() { @@ -105,12 +96,9 @@ protected function getConfiguredServiceService() } /** - * Gets the 'decorated' service. + * Gets the public 'decorated' shared service. * - * This service is shared. - * This method always returns the same instance of the service. - * - * @return \stdClass A stdClass instance + * @return \stdClass */ protected function getDecoratedService() { @@ -118,12 +106,9 @@ protected function getDecoratedService() } /** - * Gets the 'decorator_service' service. - * - * This service is shared. - * This method always returns the same instance of the service. + * Gets the public 'decorator_service' shared service. * - * @return \stdClass A stdClass instance + * @return \stdClass */ protected function getDecoratorServiceService() { @@ -131,12 +116,9 @@ protected function getDecoratorServiceService() } /** - * Gets the 'decorator_service_with_name' service. + * Gets the public 'decorator_service_with_name' shared service. * - * This service is shared. - * This method always returns the same instance of the service. - * - * @return \stdClass A stdClass instance + * @return \stdClass */ protected function getDecoratorServiceWithNameService() { @@ -144,12 +126,9 @@ protected function getDecoratorServiceWithNameService() } /** - * Gets the 'factory_service' service. - * - * This service is shared. - * This method always returns the same instance of the service. + * Gets the public 'factory_service' shared service. * - * @return \Bar A Bar instance + * @return \Bar */ protected function getFactoryServiceService() { @@ -157,12 +136,9 @@ protected function getFactoryServiceService() } /** - * Gets the 'foo' service. - * - * This service is shared. - * This method always returns the same instance of the service. + * Gets the public 'foo' shared service. * - * @return \Bar\FooClass A Bar\FooClass instance + * @return \Bar\FooClass */ protected function getFooService() { @@ -181,10 +157,7 @@ protected function getFooService() } /** - * Gets the 'foo.baz' service. - * - * This service is shared. - * This method always returns the same instance of the service. + * Gets the public 'foo.baz' shared service. * * @return object A %baz_class% instance */ @@ -198,7 +171,7 @@ protected function getFoo_BazService() } /** - * Gets the 'foo_bar' service. + * Gets the public 'foo_bar' service. * * @return object A %foo_class% instance */ @@ -210,12 +183,9 @@ protected function getFooBarService() } /** - * Gets the 'foo_with_inline' service. - * - * This service is shared. - * This method always returns the same instance of the service. + * Gets the public 'foo_with_inline' shared service. * - * @return \Foo A Foo instance + * @return \Foo */ protected function getFooWithInlineService() { @@ -227,12 +197,9 @@ protected function getFooWithInlineService() } /** - * Gets the 'method_call1' service. + * Gets the public 'method_call1' shared service. * - * This service is shared. - * This method always returns the same instance of the service. - * - * @return \Bar\FooClass A Bar\FooClass instance + * @return \Bar\FooClass */ protected function getMethodCall1Service() { @@ -254,12 +221,9 @@ protected function getMethodCall1Service() } /** - * Gets the 'new_factory_service' service. - * - * This service is shared. - * This method always returns the same instance of the service. + * Gets the public 'new_factory_service' shared service. * - * @return \FooBarBaz A FooBarBaz instance + * @return \FooBarBaz */ protected function getNewFactoryServiceService() { @@ -271,10 +235,7 @@ protected function getNewFactoryServiceService() } /** - * Gets the 'request' service. - * - * This service is shared. - * This method always returns the same instance of the service. + * Gets the public 'request' shared service. * * @throws RuntimeException always since this service is expected to be injected dynamically */ @@ -284,12 +245,9 @@ protected function getRequestService() } /** - * Gets the 'service_from_static_method' service. + * Gets the public 'service_from_static_method' shared service. * - * This service is shared. - * This method always returns the same instance of the service. - * - * @return \Bar\FooClass A Bar\FooClass instance + * @return \Bar\FooClass */ protected function getServiceFromStaticMethodService() { @@ -297,16 +255,9 @@ protected function getServiceFromStaticMethodService() } /** - * Gets the 'configurator_service' service. - * - * This service is shared. - * This method always returns the same instance of the service. + * Gets the private 'configurator_service' shared service. * - * This service is private. - * If you want to be able to request this service from the container directly, - * make it public, otherwise you might end up with broken code. - * - * @return \ConfClass A ConfClass instance + * @return \ConfClass */ protected function getConfiguratorServiceService() { @@ -318,16 +269,9 @@ protected function getConfiguratorServiceService() } /** - * Gets the 'inlined' service. - * - * This service is shared. - * This method always returns the same instance of the service. - * - * This service is private. - * If you want to be able to request this service from the container directly, - * make it public, otherwise you might end up with broken code. + * Gets the private 'inlined' shared service. * - * @return \Bar A Bar instance + * @return \Bar */ protected function getInlinedService() { @@ -340,16 +284,9 @@ protected function getInlinedService() } /** - * Gets the 'new_factory' service. - * - * This service is shared. - * This method always returns the same instance of the service. - * - * This service is private. - * If you want to be able to request this service from the container directly, - * make it public, otherwise you might end up with broken code. + * Gets the private 'new_factory' shared service. * - * @return \FactoryClass A FactoryClass instance + * @return \FactoryClass */ protected function getNewFactoryService() { diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_compiled.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_compiled.php index 559560fa6da60..22d447e303aa9 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_compiled.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_compiled.php @@ -71,12 +71,9 @@ public function isFrozen() } /** - * Gets the 'bar' service. + * Gets the public 'bar' shared service. * - * This service is shared. - * This method always returns the same instance of the service. - * - * @return \Bar\FooClass A Bar\FooClass instance + * @return \Bar\FooClass */ protected function getBarService() { @@ -90,12 +87,9 @@ protected function getBarService() } /** - * Gets the 'baz' service. - * - * This service is shared. - * This method always returns the same instance of the service. + * Gets the public 'baz' shared service. * - * @return \Baz A Baz instance + * @return \Baz */ protected function getBazService() { @@ -107,12 +101,9 @@ protected function getBazService() } /** - * Gets the 'configured_service' service. + * Gets the public 'configured_service' shared service. * - * This service is shared. - * This method always returns the same instance of the service. - * - * @return \stdClass A stdClass instance + * @return \stdClass */ protected function getConfiguredServiceService() { @@ -127,12 +118,9 @@ protected function getConfiguredServiceService() } /** - * Gets the 'decorator_service' service. - * - * This service is shared. - * This method always returns the same instance of the service. + * Gets the public 'decorator_service' shared service. * - * @return \stdClass A stdClass instance + * @return \stdClass */ protected function getDecoratorServiceService() { @@ -140,12 +128,9 @@ protected function getDecoratorServiceService() } /** - * Gets the 'decorator_service_with_name' service. + * Gets the public 'decorator_service_with_name' shared service. * - * This service is shared. - * This method always returns the same instance of the service. - * - * @return \stdClass A stdClass instance + * @return \stdClass */ protected function getDecoratorServiceWithNameService() { @@ -153,12 +138,9 @@ protected function getDecoratorServiceWithNameService() } /** - * Gets the 'factory_service' service. - * - * This service is shared. - * This method always returns the same instance of the service. + * Gets the public 'factory_service' shared service. * - * @return \Bar A Bar instance + * @return \Bar */ protected function getFactoryServiceService() { @@ -166,12 +148,9 @@ protected function getFactoryServiceService() } /** - * Gets the 'foo' service. - * - * This service is shared. - * This method always returns the same instance of the service. + * Gets the public 'foo' shared service. * - * @return \Bar\FooClass A Bar\FooClass instance + * @return \Bar\FooClass */ protected function getFooService() { @@ -190,12 +169,9 @@ protected function getFooService() } /** - * Gets the 'foo.baz' service. + * Gets the public 'foo.baz' shared service. * - * This service is shared. - * This method always returns the same instance of the service. - * - * @return \BazClass A BazClass instance + * @return \BazClass */ protected function getFoo_BazService() { @@ -207,9 +183,9 @@ protected function getFoo_BazService() } /** - * Gets the 'foo_bar' service. + * Gets the public 'foo_bar' service. * - * @return \Bar\FooClass A Bar\FooClass instance + * @return \Bar\FooClass */ protected function getFooBarService() { @@ -217,12 +193,9 @@ protected function getFooBarService() } /** - * Gets the 'foo_with_inline' service. - * - * This service is shared. - * This method always returns the same instance of the service. + * Gets the public 'foo_with_inline' shared service. * - * @return \Foo A Foo instance + * @return \Foo */ protected function getFooWithInlineService() { @@ -239,12 +212,9 @@ protected function getFooWithInlineService() } /** - * Gets the 'method_call1' service. - * - * This service is shared. - * This method always returns the same instance of the service. + * Gets the public 'method_call1' shared service. * - * @return \Bar\FooClass A Bar\FooClass instance + * @return \Bar\FooClass */ protected function getMethodCall1Service() { @@ -260,12 +230,9 @@ protected function getMethodCall1Service() } /** - * Gets the 'new_factory_service' service. + * Gets the public 'new_factory_service' shared service. * - * This service is shared. - * This method always returns the same instance of the service. - * - * @return \FooBarBaz A FooBarBaz instance + * @return \FooBarBaz */ protected function getNewFactoryServiceService() { @@ -280,10 +247,7 @@ protected function getNewFactoryServiceService() } /** - * Gets the 'request' service. - * - * This service is shared. - * This method always returns the same instance of the service. + * Gets the public 'request' shared service. * * @throws RuntimeException always since this service is expected to be injected dynamically */ @@ -293,12 +257,9 @@ protected function getRequestService() } /** - * Gets the 'service_from_static_method' service. - * - * This service is shared. - * This method always returns the same instance of the service. + * Gets the public 'service_from_static_method' shared service. * - * @return \Bar\FooClass A Bar\FooClass instance + * @return \Bar\FooClass */ protected function getServiceFromStaticMethodService() { From dd9b5eb9ca3e51549b65214a7b99c057f7d310eb Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Wed, 26 Jul 2017 10:13:02 +0200 Subject: [PATCH 0518/1099] minor fix --- src/Symfony/Component/VarDumper/Cloner/Data.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/VarDumper/Cloner/Data.php b/src/Symfony/Component/VarDumper/Cloner/Data.php index b3d0cfab495ac..3de76cdc7da42 100644 --- a/src/Symfony/Component/VarDumper/Cloner/Data.php +++ b/src/Symfony/Component/VarDumper/Cloner/Data.php @@ -423,7 +423,7 @@ private function getStub($item) if (isset($item[0])) { $stub->cut = $item[0]; } - $stub->value = $stub->cut + \count($this->data[$stub->position]); + $stub->value = $stub->cut + ($stub->position ? \count($this->data[$stub->position]) : 0); return $stub; } From 636777dc611b28f81970c56afce3f8dfdaea5296 Mon Sep 17 00:00:00 2001 From: Christian Schmidt Date: Wed, 26 Jul 2017 16:58:46 +0200 Subject: [PATCH 0519/1099] [Debug] HTML-escape array key --- src/Symfony/Component/Debug/ExceptionHandler.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/Debug/ExceptionHandler.php b/src/Symfony/Component/Debug/ExceptionHandler.php index 0c43ba6a05477..e3a58393b8264 100644 --- a/src/Symfony/Component/Debug/ExceptionHandler.php +++ b/src/Symfony/Component/Debug/ExceptionHandler.php @@ -94,7 +94,7 @@ public function setHandler($handler) * * @param string $format The format for links to source files * - * @return string The previous file link format. + * @return string The previous file link format */ public function setFileLinkFormat($format) { @@ -418,7 +418,7 @@ private function formatArgs(array $args) $formattedValue = str_replace("\n", '', var_export($this->escapeHtml((string) $item[1]), true)); } - $result[] = is_int($key) ? $formattedValue : sprintf("'%s' => %s", $key, $formattedValue); + $result[] = is_int($key) ? $formattedValue : sprintf("'%s' => %s", $this->escapeHtml($key), $formattedValue); } return implode(', ', $result); From 7b6d8948cea71235eeb6c23ee33c8e1ceecbd6d1 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Wed, 26 Jul 2017 18:05:14 +0200 Subject: [PATCH 0520/1099] [Console][WebServerBundle] Use "exec" when possible --- src/Symfony/Bundle/WebServerBundle/WebServer.php | 9 ++++----- src/Symfony/Bundle/WebServerBundle/composer.json | 4 ++-- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/src/Symfony/Bundle/WebServerBundle/WebServer.php b/src/Symfony/Bundle/WebServerBundle/WebServer.php index b65cec1cb768b..8edbe2bf56ec2 100644 --- a/src/Symfony/Bundle/WebServerBundle/WebServer.php +++ b/src/Symfony/Bundle/WebServerBundle/WebServer.php @@ -13,7 +13,6 @@ use Symfony\Component\Process\PhpExecutableFinder; use Symfony\Component\Process\Process; -use Symfony\Component\Process\ProcessBuilder; use Symfony\Component\Process\Exception\RuntimeException; /** @@ -151,11 +150,11 @@ private function createServerProcess(WebServerConfig $config) throw new \RuntimeException('Unable to find the PHP binary.'); } - $builder = new ProcessBuilder(array($binary, '-S', $config->getAddress(), $config->getRouter())); - $builder->setWorkingDirectory($config->getDocumentRoot()); - $builder->setTimeout(null); + $process = new Process(array($binary, '-S', $config->getAddress(), $config->getRouter())); + $process->setWorkingDirectory($config->getDocumentRoot()); + $process->setTimeout(null); - return $builder->getProcess(); + return $process; } private function getDefaultPidFile() diff --git a/src/Symfony/Bundle/WebServerBundle/composer.json b/src/Symfony/Bundle/WebServerBundle/composer.json index ce8a60d136eb0..829e110c35206 100644 --- a/src/Symfony/Bundle/WebServerBundle/composer.json +++ b/src/Symfony/Bundle/WebServerBundle/composer.json @@ -17,9 +17,9 @@ ], "require": { "php": ">=5.5.9", - "symfony/console": "~2.8.8|~3.0.8|~3.1.2|~3.2", + "symfony/console": "~3.3", "symfony/http-kernel": "~3.3", - "symfony/process": "~2.8|~3.0" + "symfony/process": "~3.3" }, "autoload": { "psr-4": { "Symfony\\Bundle\\WebServerBundle\\": "" }, From 31843d6f9830835fe9110d9bb4f3234e9056ee5d Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Thu, 27 Jul 2017 10:00:45 +0200 Subject: [PATCH 0521/1099] [ProxyManager] Cleanup fixtures --- .../Tests/LazyProxy/Dumper/PhpDumperTest.php | 40 ++-- .../LazyProxy/Fixtures/php/lazy_service.php | 185 ------------------ .../Fixtures/php/lazy_service_structure.txt | 2 +- .../Fixtures/php/lazy_service_with_hints.php | 180 ----------------- 4 files changed, 21 insertions(+), 386 deletions(-) delete mode 100644 src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/Fixtures/php/lazy_service.php delete mode 100644 src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/Fixtures/php/lazy_service_with_hints.php diff --git a/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/Dumper/PhpDumperTest.php b/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/Dumper/PhpDumperTest.php index d6f3d0d2e839e..62cc3cd38d38f 100644 --- a/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/Dumper/PhpDumperTest.php +++ b/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/Dumper/PhpDumperTest.php @@ -26,21 +26,9 @@ class PhpDumperTest extends TestCase { public function testDumpContainerWithProxyService() { - $container = new ContainerBuilder(); - - $container->register('foo', 'stdClass'); - $container->getDefinition('foo')->setLazy(true); - $container->compile(); - - $dumper = new PhpDumper($container); - - $dumper->setProxyDumper(new ProxyDumper()); - - $dumpedString = $dumper->dump(); - $this->assertStringMatchesFormatFile( __DIR__.'/../Fixtures/php/lazy_service_structure.txt', - $dumpedString, + $this->dumpLazyServiceProjectServiceContainer(), '->dump() does generate proxy lazy loading logic.' ); } @@ -50,18 +38,15 @@ public function testDumpContainerWithProxyService() */ public function testDumpContainerWithProxyServiceWillShareProxies() { - // detecting ProxyManager v2 - if (class_exists('ProxyManager\ProxyGenerator\LazyLoading\MethodGenerator\StaticProxyConstructor')) { - require_once __DIR__.'/../Fixtures/php/lazy_service_with_hints.php'; - } else { - require_once __DIR__.'/../Fixtures/php/lazy_service.php'; + if (!class_exists('LazyServiceProjectServiceContainer', false)) { + eval('?>'.$this->dumpLazyServiceProjectServiceContainer()); } $container = new \LazyServiceProjectServiceContainer(); - /* @var $proxy \stdClass_c1d194250ee2e2b7d2eab8b8212368a8 */ $proxy = $container->get('foo'); - $this->assertInstanceOf('stdClass_c1d194250ee2e2b7d2eab8b8212368a8', $proxy); + $this->assertInstanceOf('stdClass', $proxy); + $this->assertInstanceOf('ProxyManager\Proxy\LazyLoadingInterface', $proxy); $this->assertSame($proxy, $container->get('foo')); $this->assertFalse($proxy->isProxyInitialized()); @@ -71,4 +56,19 @@ public function testDumpContainerWithProxyServiceWillShareProxies() $this->assertTrue($proxy->isProxyInitialized()); $this->assertSame($proxy, $container->get('foo')); } + + private function dumpLazyServiceProjectServiceContainer() + { + $container = new ContainerBuilder(); + + $container->register('foo', 'stdClass'); + $container->getDefinition('foo')->setLazy(true); + $container->compile(); + + $dumper = new PhpDumper($container); + + $dumper->setProxyDumper(new ProxyDumper()); + + return $dumper->dump(array('class' => 'LazyServiceProjectServiceContainer')); + } } diff --git a/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/Fixtures/php/lazy_service.php b/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/Fixtures/php/lazy_service.php deleted file mode 100644 index 8971f655f4e3a..0000000000000 --- a/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/Fixtures/php/lazy_service.php +++ /dev/null @@ -1,185 +0,0 @@ -services = - $this->scopedServices = - $this->scopeStacks = array(); - $this->scopes = array(); - $this->scopeChildren = array(); - } - - /** - * Gets the 'foo' service. - * - * This service is shared. - * This method always returns the same instance of the service. - * - * @param bool $lazyLoad whether to try lazy-loading the service with a proxy - * - * @return stdClass A stdClass instance - */ - public function getFooService($lazyLoad = true) - { - if ($lazyLoad) { - $container = $this; - - return $this->services['foo'] = new stdClass_c1d194250ee2e2b7d2eab8b8212368a8( - function (&$wrappedInstance, \ProxyManager\Proxy\LazyLoadingInterface $proxy) use ($container) { - $wrappedInstance = $container->getFooService(false); - - $proxy->setProxyInitializer(null); - - return true; - } - ); - } - - return new \stdClass(); - } -} - -class stdClass_c1d194250ee2e2b7d2eab8b8212368a8 extends \stdClass implements \ProxyManager\Proxy\LazyLoadingInterface, \ProxyManager\Proxy\ValueHolderInterface -{ - /** - * @var \Closure|null initializer responsible for generating the wrapped object - */ - private $valueHolder5157dd96e88c0 = null; - - /** - * @var \Closure|null initializer responsible for generating the wrapped object - */ - private $initializer5157dd96e8924 = null; - - /** - * @override constructor for lazy initialization - * - * @param \Closure|null $initializer - */ - public function __construct($initializer) - { - $this->initializer5157dd96e8924 = $initializer; - } - - /** - * @param string $name - */ - public function __get($name) - { - $this->initializer5157dd96e8924 && $this->initializer5157dd96e8924->__invoke($this->valueHolder5157dd96e88c0, $this, '__get', array('name' => $name)); - - return $this->valueHolder5157dd96e88c0->$name; - } - - /** - * @param string $name - * @param mixed $value - */ - public function __set($name, $value) - { - $this->initializer5157dd96e8924 && $this->initializer5157dd96e8924->__invoke($this->valueHolder5157dd96e88c0, $this, '__set', array('name' => $name, 'value' => $value)); - - $this->valueHolder5157dd96e88c0->$name = $value; - } - - /** - * @param string $name - * - * @return bool - */ - public function __isset($name) - { - $this->initializer5157dd96e8924 && $this->initializer5157dd96e8924->__invoke($this->valueHolder5157dd96e88c0, $this, '__isset', array('name' => $name)); - - return isset($this->valueHolder5157dd96e88c0->$name); - } - - /** - * @param string $name - */ - public function __unset($name) - { - $this->initializer5157dd96e8924 && $this->initializer5157dd96e8924->__invoke($this->valueHolder5157dd96e88c0, $this, '__unset', array('name' => $name)); - - unset($this->valueHolder5157dd96e88c0->$name); - } - - public function __clone() - { - $this->initializer5157dd96e8924 && $this->initializer5157dd96e8924->__invoke($this->valueHolder5157dd96e88c0, $this, '__clone', array()); - - $this->valueHolder5157dd96e88c0 = clone $this->valueHolder5157dd96e88c0; - } - - public function __sleep() - { - $this->initializer5157dd96e8924 && $this->initializer5157dd96e8924->__invoke($this->valueHolder5157dd96e88c0, $this, '__sleep', array()); - - return array('valueHolder5157dd96e88c0'); - } - - public function __wakeup() - { - } - - /** - * {@inheritdoc} - */ - public function setProxyInitializer(\Closure $initializer = null) - { - $this->initializer5157dd96e8924 = $initializer; - } - - /** - * {@inheritdoc} - */ - public function getProxyInitializer() - { - return $this->initializer5157dd96e8924; - } - - /** - * {@inheritdoc} - */ - public function initializeProxy() - { - return $this->initializer5157dd96e8924 && $this->initializer5157dd96e8924->__invoke($this->valueHolder5157dd96e88c0, $this, 'initializeProxy', array()); - } - - /** - * {@inheritdoc} - */ - public function isProxyInitialized() - { - return null !== $this->valueHolder5157dd96e88c0; - } - - /** - * {@inheritdoc} - */ - public function getWrappedValueHolderValue() - { - return $this->valueHolder5157dd96e88c0; - } -} diff --git a/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/Fixtures/php/lazy_service_structure.txt b/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/Fixtures/php/lazy_service_structure.txt index a0e3642f4949e..ad9a3fe1587f5 100644 --- a/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/Fixtures/php/lazy_service_structure.txt +++ b/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/Fixtures/php/lazy_service_structure.txt @@ -1,7 +1,7 @@ services = array(); - } - - /** - * Gets the 'foo' service. - * - * This service is shared. - * This method always returns the same instance of the service. - * - * @param bool $lazyLoad whether to try lazy-loading the service with a proxy - * - * @return stdClass A stdClass instance - */ - public function getFooService($lazyLoad = true) - { - if ($lazyLoad) { - $container = $this; - - return $this->services['foo'] = new stdClass_c1d194250ee2e2b7d2eab8b8212368a8( - function (&$wrappedInstance, \ProxyManager\Proxy\LazyLoadingInterface $proxy) use ($container) { - $wrappedInstance = $this->getFooService(false); - - $proxy->setProxyInitializer(null); - - return true; - } - ); - } - - return new \stdClass(); - } -} - -class stdClass_c1d194250ee2e2b7d2eab8b8212368a8 extends \stdClass implements \ProxyManager\Proxy\LazyLoadingInterface, \ProxyManager\Proxy\ValueHolderInterface -{ - /** - * @var \Closure|null initializer responsible for generating the wrapped object - */ - private $valueHolder5157dd96e88c0 = null; - - /** - * @var \Closure|null initializer responsible for generating the wrapped object - */ - private $initializer5157dd96e8924 = null; - - /** - * @override constructor for lazy initialization - * - * @param \Closure|null $initializer - */ - public function __construct($initializer) - { - $this->initializer5157dd96e8924 = $initializer; - } - - /** - * @param string $name - */ - public function __get($name) - { - $this->initializer5157dd96e8924 && $this->initializer5157dd96e8924->__invoke($this->valueHolder5157dd96e88c0, $this, '__get', array('name' => $name)); - - return $this->valueHolder5157dd96e88c0->$name; - } - - /** - * @param string $name - * @param mixed $value - */ - public function __set($name, $value) - { - $this->initializer5157dd96e8924 && $this->initializer5157dd96e8924->__invoke($this->valueHolder5157dd96e88c0, $this, '__set', array('name' => $name, 'value' => $value)); - - $this->valueHolder5157dd96e88c0->$name = $value; - } - - /** - * @param string $name - * - * @return bool - */ - public function __isset($name) - { - $this->initializer5157dd96e8924 && $this->initializer5157dd96e8924->__invoke($this->valueHolder5157dd96e88c0, $this, '__isset', array('name' => $name)); - - return isset($this->valueHolder5157dd96e88c0->$name); - } - - /** - * @param string $name - */ - public function __unset($name) - { - $this->initializer5157dd96e8924 && $this->initializer5157dd96e8924->__invoke($this->valueHolder5157dd96e88c0, $this, '__unset', array('name' => $name)); - - unset($this->valueHolder5157dd96e88c0->$name); - } - - public function __clone() - { - $this->initializer5157dd96e8924 && $this->initializer5157dd96e8924->__invoke($this->valueHolder5157dd96e88c0, $this, '__clone', array()); - - $this->valueHolder5157dd96e88c0 = clone $this->valueHolder5157dd96e88c0; - } - - public function __sleep() - { - $this->initializer5157dd96e8924 && $this->initializer5157dd96e8924->__invoke($this->valueHolder5157dd96e88c0, $this, '__sleep', array()); - - return array('valueHolder5157dd96e88c0'); - } - - public function __wakeup() - { - } - - /** - * {@inheritdoc} - */ - public function setProxyInitializer(\Closure $initializer = null) - { - $this->initializer5157dd96e8924 = $initializer; - } - - /** - * {@inheritdoc} - */ - public function getProxyInitializer() - { - return $this->initializer5157dd96e8924; - } - - /** - * {@inheritdoc} - */ - public function initializeProxy(): bool - { - return $this->initializer5157dd96e8924 && $this->initializer5157dd96e8924->__invoke($this->valueHolder5157dd96e88c0, $this, 'initializeProxy', array()); - } - - /** - * {@inheritdoc} - */ - public function isProxyInitialized(): bool - { - return null !== $this->valueHolder5157dd96e88c0; - } - - /** - * {@inheritdoc} - */ - public function getWrappedValueHolderValue() - { - return $this->valueHolder5157dd96e88c0; - } -} From f4c5cff97d657d86579a34b2868f2e4d2ce2e6b8 Mon Sep 17 00:00:00 2001 From: Tobias Nyholm Date: Wed, 19 Jul 2017 16:45:25 +0200 Subject: [PATCH 0522/1099] [Workflow] Adding workflow name to the announce event --- src/Symfony/Component/Workflow/CHANGELOG.md | 5 ++++ .../Component/Workflow/Tests/WorkflowTest.php | 29 +++++++++++++++++++ src/Symfony/Component/Workflow/Workflow.php | 2 +- 3 files changed, 35 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/Workflow/CHANGELOG.md b/src/Symfony/Component/Workflow/CHANGELOG.md index 51a52777dfa8e..d1b50cb4ef497 100644 --- a/src/Symfony/Component/Workflow/CHANGELOG.md +++ b/src/Symfony/Component/Workflow/CHANGELOG.md @@ -1,6 +1,11 @@ CHANGELOG ========= +3.4.0 +----- + + * Added support for `Event::getWorkflowName()` for "announce" events. + 3.3.0 ----- diff --git a/src/Symfony/Component/Workflow/Tests/WorkflowTest.php b/src/Symfony/Component/Workflow/Tests/WorkflowTest.php index 212bd5f3f9411..3ca61914aad1c 100644 --- a/src/Symfony/Component/Workflow/Tests/WorkflowTest.php +++ b/src/Symfony/Component/Workflow/Tests/WorkflowTest.php @@ -276,6 +276,35 @@ public function testApplyWithEventDispatcher() $this->assertSame($eventNameExpected, $eventDispatcher->dispatchedEvents); } + public function testEventName() + { + $definition = $this->createComplexWorkflowDefinition(); + $subject = new \stdClass(); + $subject->marking = null; + $dispatcher = new EventDispatcher(); + $name = 'workflow_name'; + $workflow = new Workflow($definition, new MultipleStateMarkingStore(), $dispatcher, $name); + + $assertWorkflowName = function (Event $event) use ($name) { + $this->assertEquals($name, $event->getWorkflowName()); + }; + + $eventNames = array( + 'workflow.guard', + 'workflow.leave', + 'workflow.transition', + 'workflow.enter', + 'workflow.entered', + 'workflow.announce', + ); + + foreach ($eventNames as $eventName) { + $dispatcher->addListener($eventName, $assertWorkflowName); + } + + $workflow->apply($subject, 't1'); + } + public function testMarkingStateOnApplyWithEventDispatcher() { $definition = new Definition(range('a', 'f'), array(new Transition('t', range('a', 'c'), range('d', 'f')))); diff --git a/src/Symfony/Component/Workflow/Workflow.php b/src/Symfony/Component/Workflow/Workflow.php index 1791b568d79be..617c05b381e09 100644 --- a/src/Symfony/Component/Workflow/Workflow.php +++ b/src/Symfony/Component/Workflow/Workflow.php @@ -298,7 +298,7 @@ private function announce($subject, Transition $initialTransition, Marking $mark return; } - $event = new Event($subject, $marking, $initialTransition); + $event = new Event($subject, $marking, $initialTransition, $this->name); $this->dispatcher->dispatch('workflow.announce', $event); $this->dispatcher->dispatch(sprintf('workflow.%s.announce', $this->name), $event); From 0754617c52f4bab9c2c53d717592145388ba7832 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Thu, 27 Jul 2017 14:55:51 +0200 Subject: [PATCH 0523/1099] [DI][ProxyManager] Pass the factory code to execute to DumperInterface::getProxyFactoryCode() --- .../LazyProxy/PhpDumper/ProxyDumper.php | 15 ++++++++------- .../Tests/LazyProxy/PhpDumper/ProxyDumperTest.php | 2 +- .../DependencyInjection/Dumper/PhpDumper.php | 2 +- .../LazyProxy/PhpDumper/DumperInterface.php | 6 +++--- .../LazyProxy/PhpDumper/NullDumper.php | 2 +- .../Tests/Fixtures/includes/classes.php | 2 +- .../Tests/LazyProxy/PhpDumper/NullDumperTest.php | 2 +- .../Component/DependencyInjection/composer.json | 1 + 8 files changed, 17 insertions(+), 15 deletions(-) diff --git a/src/Symfony/Bridge/ProxyManager/LazyProxy/PhpDumper/ProxyDumper.php b/src/Symfony/Bridge/ProxyManager/LazyProxy/PhpDumper/ProxyDumper.php index b91bfeb922cf8..a8cdc7de3bbc3 100644 --- a/src/Symfony/Bridge/ProxyManager/LazyProxy/PhpDumper/ProxyDumper.php +++ b/src/Symfony/Bridge/ProxyManager/LazyProxy/PhpDumper/ProxyDumper.php @@ -65,7 +65,7 @@ public function isProxyCandidate(Definition $definition) /** * {@inheritdoc} */ - public function getProxyFactoryCode(Definition $definition, $id, $methodName = null) + public function getProxyFactoryCode(Definition $definition, $id, $factoryCode = null) { $instantiation = 'return'; @@ -73,11 +73,12 @@ public function getProxyFactoryCode(Definition $definition, $id, $methodName = n $instantiation .= " \$this->services['$id'] ="; } - if (func_num_args() >= 3) { - $methodName = func_get_arg(2); - } else { - @trigger_error(sprintf('You must use the third argument of %s to define the method to call to construct your service since version 3.1, not using it won\'t be supported in 4.0.', __METHOD__), E_USER_DEPRECATED); - $methodName = 'get'.Container::camelize($id).'Service'; + if (null === $factoryCode) { + @trigger_error(sprintf('The "%s()" method expects a third argument defining the code to execute to construct your service since version 3.4, providing it will be required in 4.0.', __METHOD__), E_USER_DEPRECATED); + $factoryCode = '$this->get'.Container::camelize($id).'Service(false)'; + } elseif (false === strpos($factoryCode, '(')) { + @trigger_error(sprintf('The "%s()" method expects its third argument to define the code to execute to construct your service since version 3.4, providing it will be required in 4.0.', __METHOD__), E_USER_DEPRECATED); + $factoryCode = "\$this->$factoryCode(false)"; } $proxyClass = $this->getProxyClassName($definition); @@ -92,7 +93,7 @@ public function getProxyFactoryCode(Definition $definition, $id, $methodName = n $instantiation $constructorCall( function (&\$wrappedInstance, \ProxyManager\Proxy\LazyLoadingInterface \$proxy) { - \$wrappedInstance = \$this->$methodName(false); + \$wrappedInstance = $factoryCode; \$proxy->setProxyInitializer(null); diff --git a/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/PhpDumper/ProxyDumperTest.php b/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/PhpDumper/ProxyDumperTest.php index 64082c8f7f3f1..58de413674fa5 100644 --- a/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/PhpDumper/ProxyDumperTest.php +++ b/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/PhpDumper/ProxyDumperTest.php @@ -67,7 +67,7 @@ public function testGetProxyFactoryCodeWithCustomMethod() $definition->setLazy(true); - $code = $this->dumper->getProxyFactoryCode($definition, 'foo', 'getFoo2Service'); + $code = $this->dumper->getProxyFactoryCode($definition, 'foo', '$this->getFoo2Service(false)'); $this->assertStringMatchesFormat( '%wif ($lazyLoad) {%wreturn $this->services[\'foo\'] =%s' diff --git a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php index 86222ac551fa0..9021f70530a0e 100644 --- a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php +++ b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php @@ -639,7 +639,7 @@ private function addService($id, Definition $definition) EOF; - $code .= $isProxyCandidate ? $this->getProxyDumper()->getProxyFactoryCode($definition, $id, $methodName) : ''; + $code .= $isProxyCandidate ? $this->getProxyDumper()->getProxyFactoryCode($definition, $id, "\$this->$methodName(false)") : ''; if ($definition->isDeprecated()) { $code .= sprintf(" @trigger_error(%s, E_USER_DEPRECATED);\n\n", $this->export($definition->getDeprecationMessage($id))); diff --git a/src/Symfony/Component/DependencyInjection/LazyProxy/PhpDumper/DumperInterface.php b/src/Symfony/Component/DependencyInjection/LazyProxy/PhpDumper/DumperInterface.php index ce88eba9742fd..0e06ce09b551b 100644 --- a/src/Symfony/Component/DependencyInjection/LazyProxy/PhpDumper/DumperInterface.php +++ b/src/Symfony/Component/DependencyInjection/LazyProxy/PhpDumper/DumperInterface.php @@ -33,12 +33,12 @@ public function isProxyCandidate(Definition $definition); * Generates the code to be used to instantiate a proxy in the dumped factory code. * * @param Definition $definition - * @param string $id service identifier - * @param string $methodName the method name to get the service, will be added to the interface in 4.0 + * @param string $id service identifier + * @param string $factoryCode the code to execute to create the service, will be added to the interface in 4.0 * * @return string */ - public function getProxyFactoryCode(Definition $definition, $id/**, $methodName = null */); + public function getProxyFactoryCode(Definition $definition, $id/**, $factoryCode = null */); /** * Generates the code for the lazy proxy. diff --git a/src/Symfony/Component/DependencyInjection/LazyProxy/PhpDumper/NullDumper.php b/src/Symfony/Component/DependencyInjection/LazyProxy/PhpDumper/NullDumper.php index 30cbdef0a6ad8..67f9fae94dbf8 100644 --- a/src/Symfony/Component/DependencyInjection/LazyProxy/PhpDumper/NullDumper.php +++ b/src/Symfony/Component/DependencyInjection/LazyProxy/PhpDumper/NullDumper.php @@ -33,7 +33,7 @@ public function isProxyCandidate(Definition $definition) /** * {@inheritdoc} */ - public function getProxyFactoryCode(Definition $definition, $id, $methodName = null) + public function getProxyFactoryCode(Definition $definition, $id, $factoryCode = null) { return ''; } diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/includes/classes.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/includes/classes.php index 717dcdc52e579..cbb6a6e507faf 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/includes/classes.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/includes/classes.php @@ -88,7 +88,7 @@ public function isProxyCandidate(Definition $definition) return false; } - public function getProxyFactoryCode(Definition $definition, $id, $methodName = null) + public function getProxyFactoryCode(Definition $definition, $id, $factoryCall = null) { return ''; } diff --git a/src/Symfony/Component/DependencyInjection/Tests/LazyProxy/PhpDumper/NullDumperTest.php b/src/Symfony/Component/DependencyInjection/Tests/LazyProxy/PhpDumper/NullDumperTest.php index cde2c147e752c..b1b9b399c3728 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/LazyProxy/PhpDumper/NullDumperTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/LazyProxy/PhpDumper/NullDumperTest.php @@ -28,7 +28,7 @@ public function testNullDumper() $definition = new Definition('stdClass'); $this->assertFalse($dumper->isProxyCandidate($definition)); - $this->assertSame('', $dumper->getProxyFactoryCode($definition, 'foo')); + $this->assertSame('', $dumper->getProxyFactoryCode($definition, 'foo', '(false)')); $this->assertSame('', $dumper->getProxyCode($definition)); } } diff --git a/src/Symfony/Component/DependencyInjection/composer.json b/src/Symfony/Component/DependencyInjection/composer.json index f5124f9c8521e..ba391a2bd9a98 100644 --- a/src/Symfony/Component/DependencyInjection/composer.json +++ b/src/Symfony/Component/DependencyInjection/composer.json @@ -34,6 +34,7 @@ "conflict": { "symfony/config": "<3.3.1", "symfony/finder": "<3.3", + "symfony/proxy-manager-bridge": "<3.4", "symfony/yaml": "<3.3" }, "provide": { From 0caed939cdda45da1e4af39fde23397344621b0f Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Wed, 26 Jul 2017 09:41:52 +0200 Subject: [PATCH 0524/1099] [DI] Inline trivial private servives --- .../DependencyInjection/Dumper/PhpDumper.php | 60 +++++++++++++++++-- .../Tests/Fixtures/containers/container9.php | 1 + .../Tests/Fixtures/php/services9_compiled.php | 16 ++++- .../Tests/Fixtures/php/services_locator.php | 14 +---- .../Fixtures/php/services_private_frozen.php | 14 +---- .../php/services_private_in_expression.php | 12 +--- .../Fixtures/php/services_subscriber.php | 14 +---- .../Tests/Fixtures/xml/services9.xml | 1 + .../Tests/Fixtures/yaml/services9.yml | 1 + 9 files changed, 81 insertions(+), 52 deletions(-) diff --git a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php index 1492979e8ee9d..a090938baa362 100644 --- a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php +++ b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php @@ -446,6 +446,50 @@ private function isSimpleInstance($id, Definition $definition) return true; } + /** + * Checks if the definition is a trivial instance. + * + * @param Definition $definition + * + * @return bool + */ + private function isTrivialInstance(Definition $definition) + { + if ($definition->isPublic() || $definition->getMethodCalls() || $definition->getProperties() || $definition->getConfigurator()) { + return false; + } + if ($definition->isDeprecated() || $definition->isLazy() || $definition->getFactory() || 3 < count($definition->getArguments())) { + return false; + } + + foreach ($definition->getArguments() as $arg) { + if (!$arg || ($arg instanceof Reference && 'service_container' !== (string) $arg)) { + continue; + } + if (is_array($arg) && 3 >= count($arg)) { + foreach ($arg as $k => $v) { + if ($this->dumpValue($k) !== $this->dumpValue($k, false)) { + return false; + } + if (!$v || ($v instanceof Reference && 'service_container' !== (string) $v)) { + continue; + } + if (!is_scalar($v) || $this->dumpValue($v) !== $this->dumpValue($v, false)) { + return false; + } + } + } elseif (!is_scalar($arg) || $this->dumpValue($arg) !== $this->dumpValue($arg, false)) { + return false; + } + } + + if (false !== strpos($this->dumpLiteralClass($this->dumpValue($definition->getClass())), '$')) { + return false; + } + + return true; + } + /** * Adds method calls to a service definition. * @@ -675,7 +719,7 @@ private function addServices() foreach ($definitions as $id => $definition) { if ($definition->isPublic()) { $publicServices .= $this->addService($id, $definition); - } else { + } elseif (!$this->isTrivialInstance($definition)) { $privateServices .= $this->addService($id, $definition); } } @@ -1504,10 +1548,18 @@ private function getServiceCall($id, Reference $reference = null) } if ($this->container->hasDefinition($id)) { - $code = sprintf('$this->%s()', $this->generateMethodName($id)); + $definition = $this->container->getDefinition($id); - if ($this->container->getDefinition($id)->isShared()) { - $code = sprintf('($this->%s[\'%s\'] ?? %s)', $this->container->getDefinition($id)->isPublic() ? 'services' : 'privates', $id, $code); + if ($definition->isPublic() || !$this->isTrivialInstance($definition)) { + $code = sprintf('$this->%s()', $this->generateMethodName($id)); + } else { + $code = substr($this->addNewInstance($definition, '', '', $id), 8, -2); + if ($definition->isShared()) { + $code = sprintf('($this->privates[\'%s\'] = %s)', $id, $code); + } + } + if ($definition->isShared()) { + $code = sprintf('($this->%s[\'%s\'] ?? %s)', $definition->isPublic() ? 'services' : 'privates', $id, $code); } } elseif (null !== $reference && ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE !== $reference->getInvalidBehavior()) { $code = sprintf('$this->get(\'%s\', ContainerInterface::NULL_ON_INVALID_REFERENCE)', $id); diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container9.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container9.php index 472a211537160..b662cf53c1211 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container9.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container9.php @@ -125,6 +125,7 @@ $container ->register('factory_simple', 'SimpleFactoryClass') ->addArgument('foo') + ->setDeprecated(true) ->setPublic(false) ; $container diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_compiled.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_compiled.php index ef25100d11b5f..e59b6fed95da5 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_compiled.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_compiled.php @@ -231,7 +231,7 @@ protected function getFactoryServiceService() */ protected function getFactoryServiceSimpleService() { - return $this->services['factory_service_simple'] = (new \SimpleFactoryClass('foo'))->getInstance(); + return $this->services['factory_service_simple'] = ($this->privates['factory_simple'] ?? $this->getFactorySimpleService())->getInstance(); } /** @@ -372,6 +372,20 @@ protected function getServiceFromStaticMethodService() return $this->services['service_from_static_method'] = \Bar\FooClass::getInstance(); } + /** + * Gets the private 'factory_simple' shared service. + * + * @return \SimpleFactoryClass + * + * @deprecated The "factory_simple" service is deprecated. You should stop using it, as it will soon be removed. + */ + private function getFactorySimpleService() + { + @trigger_error('The "factory_simple" service is deprecated. You should stop using it, as it will soon be removed.', E_USER_DEPRECATED); + + return $this->privates['factory_simple'] = new \SimpleFactoryClass('foo'); + } + /** * {@inheritdoc} */ diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_locator.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_locator.php index cd4d4ca2246f4..852011ac7d1ca 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_locator.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_locator.php @@ -74,7 +74,7 @@ public function isCompiled() */ protected function getBarServiceService() { - return $this->services['bar_service'] = new \stdClass(($this->privates['baz_service'] ?? $this->getBazServiceService())); + return $this->services['bar_service'] = new \stdClass(($this->privates['baz_service'] ?? ($this->privates['baz_service'] = new \stdClass()))); } /** @@ -87,7 +87,7 @@ protected function getFooServiceService() return $this->services['foo_service'] = new \Symfony\Component\DependencyInjection\ServiceLocator(array('bar' => function () { return ($this->services['bar_service'] ?? $this->getBarServiceService()); }, 'baz' => function (): \stdClass { - return ($this->privates['baz_service'] ?? $this->getBazServiceService()); + return ($this->privates['baz_service'] ?? ($this->privates['baz_service'] = new \stdClass())); }, 'nil' => function () { return NULL; })); @@ -169,14 +169,4 @@ protected function getTranslator3Service() return $instance; } - - /** - * Gets the private 'baz_service' shared service. - * - * @return \stdClass - */ - private function getBazServiceService() - { - return $this->privates['baz_service'] = new \stdClass(); - } } diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_private_frozen.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_private_frozen.php index 678a62130ba7e..9a0611949b57e 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_private_frozen.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_private_frozen.php @@ -68,7 +68,7 @@ public function isCompiled() */ protected function getBarServiceService() { - return $this->services['bar_service'] = new \stdClass(($this->privates['baz_service'] ?? $this->getBazServiceService())); + return $this->services['bar_service'] = new \stdClass(($this->privates['baz_service'] ?? ($this->privates['baz_service'] = new \stdClass()))); } /** @@ -78,16 +78,6 @@ protected function getBarServiceService() */ protected function getFooServiceService() { - return $this->services['foo_service'] = new \stdClass(($this->privates['baz_service'] ?? $this->getBazServiceService())); - } - - /** - * Gets the private 'baz_service' shared service. - * - * @return \stdClass - */ - private function getBazServiceService() - { - return $this->privates['baz_service'] = new \stdClass(); + return $this->services['foo_service'] = new \stdClass(($this->privates['baz_service'] ?? ($this->privates['baz_service'] = new \stdClass()))); } } diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_private_in_expression.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_private_in_expression.php index 96e8c8c52c493..8e3060e130436 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_private_in_expression.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_private_in_expression.php @@ -67,16 +67,6 @@ public function isCompiled() */ protected function getPublicFooService() { - return $this->services['public_foo'] = new \stdClass(($this->privates['private_foo'] ?? $this->getPrivateFooService())); - } - - /** - * Gets the private 'private_foo' shared service. - * - * @return \stdClass - */ - private function getPrivateFooService() - { - return $this->privates['private_foo'] = new \stdClass(); + return $this->services['public_foo'] = new \stdClass(($this->privates['private_foo'] ?? ($this->privates['private_foo'] = new \stdClass()))); } } diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_subscriber.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_subscriber.php index 0c8311c5ff4cc..e29fed9d2a727 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_subscriber.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_subscriber.php @@ -79,23 +79,13 @@ protected function getSymfony_Component_DependencyInjection_Tests_Fixtures_TestS protected function getFooServiceService() { return $this->services['foo_service'] = new \Symfony\Component\DependencyInjection\Tests\Fixtures\TestServiceSubscriber(new \Symfony\Component\DependencyInjection\ServiceLocator(array('Symfony\\Component\\DependencyInjection\\Tests\\Fixtures\\CustomDefinition' => function (): \Symfony\Component\DependencyInjection\Tests\Fixtures\CustomDefinition { - return ($this->privates['autowired.Symfony\Component\DependencyInjection\Tests\Fixtures\CustomDefinition'] ?? $this->getAutowired_Symfony_Component_DependencyInjection_Tests_Fixtures_CustomDefinitionService()); + return ($this->privates['autowired.Symfony\Component\DependencyInjection\Tests\Fixtures\CustomDefinition'] ?? ($this->privates['autowired.Symfony\Component\DependencyInjection\Tests\Fixtures\CustomDefinition'] = new \Symfony\Component\DependencyInjection\Tests\Fixtures\CustomDefinition())); }, 'Symfony\\Component\\DependencyInjection\\Tests\\Fixtures\\TestServiceSubscriber' => function (): \Symfony\Component\DependencyInjection\Tests\Fixtures\TestServiceSubscriber { return ($this->services['Symfony\Component\DependencyInjection\Tests\Fixtures\TestServiceSubscriber'] ?? $this->getSymfony_Component_DependencyInjection_Tests_Fixtures_TestServiceSubscriberService()); }, 'bar' => function (): \Symfony\Component\DependencyInjection\Tests\Fixtures\CustomDefinition { return ($this->services['Symfony\Component\DependencyInjection\Tests\Fixtures\TestServiceSubscriber'] ?? $this->getSymfony_Component_DependencyInjection_Tests_Fixtures_TestServiceSubscriberService()); }, 'baz' => function (): \Symfony\Component\DependencyInjection\Tests\Fixtures\CustomDefinition { - return ($this->privates['autowired.Symfony\Component\DependencyInjection\Tests\Fixtures\CustomDefinition'] ?? $this->getAutowired_Symfony_Component_DependencyInjection_Tests_Fixtures_CustomDefinitionService()); + return ($this->privates['autowired.Symfony\Component\DependencyInjection\Tests\Fixtures\CustomDefinition'] ?? ($this->privates['autowired.Symfony\Component\DependencyInjection\Tests\Fixtures\CustomDefinition'] = new \Symfony\Component\DependencyInjection\Tests\Fixtures\CustomDefinition())); }))); } - - /** - * Gets the private 'autowired.Symfony\Component\DependencyInjection\Tests\Fixtures\CustomDefinition' shared autowired service. - * - * @return \Symfony\Component\DependencyInjection\Tests\Fixtures\CustomDefinition - */ - private function getAutowired_Symfony_Component_DependencyInjection_Tests_Fixtures_CustomDefinitionService() - { - return $this->privates['autowired.Symfony\Component\DependencyInjection\Tests\Fixtures\CustomDefinition'] = new \Symfony\Component\DependencyInjection\Tests\Fixtures\CustomDefinition(); - } } diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services9.xml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services9.xml index 5f46821a0f90e..9b78f7d9eed3f 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services9.xml +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services9.xml @@ -112,6 +112,7 @@ foo + The "%service_id%" service is deprecated. You should stop using it, as it will soon be removed. diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services9.yml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services9.yml index e91fbb208c1ae..ddd4c25dd5188 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services9.yml +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services9.yml @@ -105,6 +105,7 @@ services: factory: [Bar\FooClass, getInstance] factory_simple: class: SimpleFactoryClass + deprecated: The "%service_id%" service is deprecated. You should stop using it, as it will soon be removed. public: false arguments: ['foo'] factory_service_simple: From 92fa55dd8b59aff66ed4456eba857b99698a93dd Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Wed, 26 Jul 2017 15:23:18 +0200 Subject: [PATCH 0525/1099] [VarDumper] Keep and reuse array stubs in memory --- .../Component/VarDumper/Cloner/VarCloner.php | 79 ++++++++++--------- 1 file changed, 40 insertions(+), 39 deletions(-) diff --git a/src/Symfony/Component/VarDumper/Cloner/VarCloner.php b/src/Symfony/Component/VarDumper/Cloner/VarCloner.php index 108ab01e17652..5399c66010a89 100644 --- a/src/Symfony/Component/VarDumper/Cloner/VarCloner.php +++ b/src/Symfony/Component/VarDumper/Cloner/VarCloner.php @@ -16,8 +16,10 @@ */ class VarCloner extends AbstractCloner { + private static $gid; private static $hashMask = 0; private static $hashOffset = 0; + private static $arrayCache = array(); /** * {@inheritdoc} @@ -36,14 +38,15 @@ protected function doClone($var) $maxItems = $this->maxItems; $maxString = $this->maxString; $cookie = (object) array(); // Unique object used to detect hard references - $gid = uniqid(mt_rand(), true); // Unique string used to detect the special $GLOBALS variable $a = null; // Array cast for nested structures $stub = null; // Stub capturing the main properties of an original item value // or null if the original value is used directly if (!self::$hashMask) { + self::$gid = uniqid(mt_rand(), true); // Unique string used to detect the special $GLOBALS variable self::initHashMask(); } + $gid = self::$gid; $hashMask = self::$hashMask; $hashOffset = self::$hashOffset; $arrayStub = new Stub(); @@ -58,9 +61,9 @@ protected function doClone($var) if (\is_int($k)) { continue; } - foreach (array($k => true) as $j => $v) { + foreach (array($k => true) as $gk => $gv) { } - if ($k !== $j) { + if ($gk !== $k) { $fromObjCast = true; $refs = $vals = \array_values($queue[$i]); break; @@ -95,7 +98,7 @@ protected function doClone($var) case true === $v: case \is_int($v): case \is_float($v): - break; + continue 2; case \is_string($v): if (!\preg_match('//u', $v)) { @@ -114,7 +117,10 @@ protected function doClone($var) $stub->class = Stub::STRING_UTF8; $stub->cut = $cut; $stub->value = \mb_substr($v, 0, $maxString, 'UTF-8'); + } else { + continue 2; } + $a = null; break; case \is_array($v): @@ -146,11 +152,9 @@ protected function doClone($var) } else { $a = $v; } - } else { + } elseif (\PHP_VERSION_ID < 70200) { $indexedArrays[$len] = true; } - - $stub->value = \count($a); break; case \is_object($v): @@ -210,42 +214,40 @@ protected function doClone($var) break; } - if (isset($stub)) { - if ($a) { - if (!$i || 0 > $maxItems) { - $queue[$len] = $a; - $stub->position = $len++; - } elseif ($pos < $maxItems) { - if ($maxItems < $pos += \count($a)) { - $a = \array_slice($a, 0, $maxItems - $pos); - if ($stub->cut >= 0) { - $stub->cut += $pos - $maxItems; - } + if ($a) { + if (!$i || 0 > $maxItems) { + $queue[$len] = $a; + $stub->position = $len++; + } elseif ($pos < $maxItems) { + if ($maxItems < $pos += \count($a)) { + $a = \array_slice($a, 0, $maxItems - $pos); + if ($stub->cut >= 0) { + $stub->cut += $pos - $maxItems; } - $queue[$len] = $a; - $stub->position = $len++; - } elseif ($stub->cut >= 0) { - $stub->cut += \count($a); - $stub->position = 0; - } - } - - if ($arrayStub === $stub) { - if ($arrayStub->cut) { - $stub = array($arrayStub->cut, $arrayStub->class => $arrayStub->position); - $arrayStub->cut = 0; - } else { - $stub = array($arrayStub->class => $arrayStub->position); } + $queue[$len] = $a; + $stub->position = $len++; + } elseif ($stub->cut >= 0) { + $stub->cut += \count($a); + $stub->position = 0; } + } - if ($zvalIsRef) { - $refs[$k]->value = $stub; + if ($arrayStub === $stub) { + if ($arrayStub->cut) { + $stub = array($arrayStub->cut, $arrayStub->class => $arrayStub->position); + $arrayStub->cut = 0; + } elseif (isset(self::$arrayCache[$arrayStub->class][$arrayStub->position])) { + $stub = self::$arrayCache[$arrayStub->class][$arrayStub->position]; } else { - $vals[$k] = $stub; + self::$arrayCache[$arrayStub->class][$arrayStub->position] = $stub = array($arrayStub->class => $arrayStub->position); } + } - $stub = $a = null; + if ($zvalIsRef) { + $refs[$k]->value = $stub; + } else { + $vals[$k] = $stub; } } @@ -255,9 +257,9 @@ protected function doClone($var) $vals = array(); $j = -1; foreach ($queue[$i] as $k => $v) { - foreach (array($k => true) as $a => $v) { + foreach (array($k => true) as $gk => $gv) { } - if ($a !== $k) { + if ($gk !== $k) { $vals = (object) $vals; $vals->{$k} = $refs[++$j]; $vals = (array) $vals; @@ -268,7 +270,6 @@ protected function doClone($var) } $queue[$i] = $vals; - unset($indexedArrays[$i]); } foreach ($values as $h => $v) { From f1aa45c5174433699604fe090ad3d8ecea4dcc62 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Fri, 21 Jul 2017 12:04:43 +0200 Subject: [PATCH 0526/1099] [DI] Remove unused props from the PhpDumper --- .../DependencyInjection/Dumper/PhpDumper.php | 31 +++++++++---------- 1 file changed, 14 insertions(+), 17 deletions(-) diff --git a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php index 721c4dc68c62b..4d576df1bd6c8 100644 --- a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php +++ b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php @@ -255,12 +255,11 @@ private function addProxyClasses() /** * Generates the require_once statement for service includes. * - * @param string $id The service id * @param Definition $definition * * @return string */ - private function addServiceInclude($id, $definition) + private function addServiceInclude($definition) { $template = " require_once %s;\n"; $code = ''; @@ -335,9 +334,9 @@ private function addServiceInlinedDefinitions($id, $definition) $code .= $this->addNewInstance($id, $sDefinition, '$'.$name, ' = '); if (!$this->hasReference($id, $sDefinition->getMethodCalls(), true) && !$this->hasReference($id, $sDefinition->getProperties(), true)) { - $code .= $this->addServiceProperties(null, $sDefinition, $name); - $code .= $this->addServiceMethodCalls(null, $sDefinition, $name); - $code .= $this->addServiceConfigurator(null, $sDefinition, $name); + $code .= $this->addServiceProperties($sDefinition, $name); + $code .= $this->addServiceMethodCalls($sDefinition, $name); + $code .= $this->addServiceConfigurator($sDefinition, $name); } $code .= "\n"; @@ -437,13 +436,12 @@ private function isSimpleInstance($id, Definition $definition) /** * Adds method calls to a service definition. * - * @param string $id * @param Definition $definition * @param string $variableName * * @return string */ - private function addServiceMethodCalls($id, Definition $definition, $variableName = 'instance') + private function addServiceMethodCalls(Definition $definition, $variableName = 'instance') { $calls = ''; foreach ($definition->getMethodCalls() as $call) { @@ -458,7 +456,7 @@ private function addServiceMethodCalls($id, Definition $definition, $variableNam return $calls; } - private function addServiceProperties($id, Definition $definition, $variableName = 'instance') + private function addServiceProperties(Definition $definition, $variableName = 'instance') { $code = ''; foreach ($definition->getProperties() as $name => $value) { @@ -501,9 +499,9 @@ private function addServiceInlinedDefinitionsSetup($id, Definition $definition) } $name = (string) $this->definitionVariables->offsetGet($iDefinition); - $code .= $this->addServiceProperties(null, $iDefinition, $name); - $code .= $this->addServiceMethodCalls(null, $iDefinition, $name); - $code .= $this->addServiceConfigurator(null, $iDefinition, $name); + $code .= $this->addServiceProperties($iDefinition, $name); + $code .= $this->addServiceMethodCalls($iDefinition, $name); + $code .= $this->addServiceConfigurator($iDefinition, $name); } if ('' !== $code) { @@ -516,13 +514,12 @@ private function addServiceInlinedDefinitionsSetup($id, Definition $definition) /** * Adds configurator definition. * - * @param string $id * @param Definition $definition * @param string $variableName * * @return string */ - private function addServiceConfigurator($id, Definition $definition, $variableName = 'instance') + private function addServiceConfigurator(Definition $definition, $variableName = 'instance') { if (!$callable = $definition->getConfigurator()) { return ''; @@ -633,14 +630,14 @@ private function addService($id, Definition $definition) $code .= sprintf(" throw new RuntimeException('You have requested a synthetic service (\"%s\"). The DIC does not know how to construct this service.');\n }\n", $id); } else { $code .= - $this->addServiceInclude($id, $definition). + $this->addServiceInclude($definition). $this->addServiceLocalTempVariables($id, $definition). $this->addServiceInlinedDefinitions($id, $definition). $this->addServiceInstance($id, $definition). $this->addServiceInlinedDefinitionsSetup($id, $definition). - $this->addServiceProperties($id, $definition). - $this->addServiceMethodCalls($id, $definition). - $this->addServiceConfigurator($id, $definition). + $this->addServiceProperties($definition). + $this->addServiceMethodCalls($definition). + $this->addServiceConfigurator($definition). $this->addServiceReturn($id, $definition) ; } From 3e0501a7557829fe6755313afff2bebac7b36f8d Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Fri, 28 Jul 2017 17:42:30 +0200 Subject: [PATCH 0527/1099] fix merge --- .../ProxyManager/Tests/LazyProxy/PhpDumper/ProxyDumperTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/PhpDumper/ProxyDumperTest.php b/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/PhpDumper/ProxyDumperTest.php index 1a2b4b3bd95dc..696e0f04f1329 100644 --- a/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/PhpDumper/ProxyDumperTest.php +++ b/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/PhpDumper/ProxyDumperTest.php @@ -81,7 +81,7 @@ public function testGetProxyFactoryCodeWithCustomMethod() /** * @expectedException \InvalidArgumentException - * @expectedExceptionMessage Missing name of method to call to construct the service "foo". + * @expectedExceptionMessage Missing factory code to construct the service "foo". */ public function testGetProxyFactoryCodeWithoutCustomMethod() { From 0347e5a5d3cf2831f3d9a986bdca793058bb7849 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Fri, 28 Jul 2017 18:35:04 +0200 Subject: [PATCH 0528/1099] [Form] Add notice to upgrade to PHP v7.0.8+ --- .../Form/Extension/DataCollector/FormDataCollector.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Symfony/Component/Form/Extension/DataCollector/FormDataCollector.php b/src/Symfony/Component/Form/Extension/DataCollector/FormDataCollector.php index 378edf563b972..0b5ec7397564c 100644 --- a/src/Symfony/Component/Form/Extension/DataCollector/FormDataCollector.php +++ b/src/Symfony/Component/Form/Extension/DataCollector/FormDataCollector.php @@ -85,6 +85,9 @@ public function __construct(FormDataExtractorInterface $dataExtractor) */ public function collect(Request $request, Response $response, \Exception $exception = null) { + if (70000 <= \PHP_VERSION_ID && \PHP_VERSION_ID < 70800) { + @trigger_error('A bug in PHP v7.0.0 to v7.0.7 is breaking the Form panel, please upgrade to v7.0.8 or more.', E_USER_DEPRECATED); + } } /** From 21f1e102b68cfcfe4392fc36ce53752fbcb59d4c Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Fri, 28 Jul 2017 18:45:44 +0200 Subject: [PATCH 0529/1099] fix merge --- .../Bridge/ProxyManager/Tests/LazyProxy/Dumper/PhpDumperTest.php | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/Dumper/PhpDumperTest.php b/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/Dumper/PhpDumperTest.php index 8b7c4808e113a..62cc3cd38d38f 100644 --- a/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/Dumper/PhpDumperTest.php +++ b/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/Dumper/PhpDumperTest.php @@ -12,7 +12,6 @@ namespace Symfony\Bridge\ProxyManager\Tests\LazyProxy\Dumper; use PHPUnit\Framework\TestCase; -use ProxyManager\ProxyGenerator\LazyLoading\MethodGenerator\StaticProxyConstructor; use Symfony\Bridge\ProxyManager\LazyProxy\PhpDumper\ProxyDumper; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Dumper\PhpDumper; From 8fd5569577ae13504d4098ddd498f78085e00407 Mon Sep 17 00:00:00 2001 From: Alexander Schwenn Date: Tue, 25 Jul 2017 00:00:19 +0200 Subject: [PATCH 0530/1099] [HttpFoundation] Generate safe fallback filename for wrongly encoded filename --- .../Component/HttpFoundation/BinaryFileResponse.php | 4 ++-- .../HttpFoundation/Tests/BinaryFileResponseTest.php | 11 +++++++++++ 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/HttpFoundation/BinaryFileResponse.php b/src/Symfony/Component/HttpFoundation/BinaryFileResponse.php index 0314621907356..177b708e8f054 100644 --- a/src/Symfony/Component/HttpFoundation/BinaryFileResponse.php +++ b/src/Symfony/Component/HttpFoundation/BinaryFileResponse.php @@ -150,7 +150,7 @@ public function setAutoEtag() * Sets the Content-Disposition header with the given filename. * * @param string $disposition ResponseHeaderBag::DISPOSITION_INLINE or ResponseHeaderBag::DISPOSITION_ATTACHMENT - * @param string $filename Optionally use this filename instead of the real name of the file + * @param string $filename Optionally use this UTF-8 encoded filename instead of the real name of the file * @param string $filenameFallback A fallback filename, containing only ASCII characters. Defaults to an automatically encoded filename * * @return $this @@ -162,7 +162,7 @@ public function setContentDisposition($disposition, $filename = '', $filenameFal } if ('' === $filenameFallback && (!preg_match('/^[\x20-\x7e]*$/', $filename) || false !== strpos($filename, '%'))) { - $encoding = mb_detect_encoding($filename, null, true); + $encoding = mb_detect_encoding($filename, null, true) ?: '8bit'; for ($i = 0, $filenameLength = mb_strlen($filename, $encoding); $i < $filenameLength; ++$i) { $char = mb_substr($filename, $i, 1, $encoding); diff --git a/src/Symfony/Component/HttpFoundation/Tests/BinaryFileResponseTest.php b/src/Symfony/Component/HttpFoundation/Tests/BinaryFileResponseTest.php index e4607201a2151..e41a2372b9df8 100644 --- a/src/Symfony/Component/HttpFoundation/Tests/BinaryFileResponseTest.php +++ b/src/Symfony/Component/HttpFoundation/Tests/BinaryFileResponseTest.php @@ -68,6 +68,17 @@ public function testSetContentDispositionGeneratesSafeFallbackFilename() $this->assertSame('attachment; filename="f__.html"; filename*=utf-8\'\'f%C3%B6%C3%B6.html', $response->headers->get('Content-Disposition')); } + public function testSetContentDispositionGeneratesSafeFallbackFilenameForWronglyEncodedFilename() + { + $response = new BinaryFileResponse(__FILE__); + + $iso88591EncodedFilename = utf8_decode('föö.html'); + $response->setContentDisposition(ResponseHeaderBag::DISPOSITION_ATTACHMENT, $iso88591EncodedFilename); + + // the parameter filename* is invalid in this case (rawurldecode('f%F6%F6') does not provide a UTF-8 string but an ISO-8859-1 encoded one) + $this->assertSame('attachment; filename="f__.html"; filename*=utf-8\'\'f%F6%F6.html', $response->headers->get('Content-Disposition')); + } + /** * @dataProvider provideRanges */ From 7168d89cf2e99d75c76f5554923681bc320faed3 Mon Sep 17 00:00:00 2001 From: AbdElKader Bouadjadja Date: Fri, 28 Jul 2017 23:20:34 +0200 Subject: [PATCH 0531/1099] Remove unused constant --- .../Security/Core/Tests/Encoder/BCryptPasswordEncoderTest.php | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Symfony/Component/Security/Core/Tests/Encoder/BCryptPasswordEncoderTest.php b/src/Symfony/Component/Security/Core/Tests/Encoder/BCryptPasswordEncoderTest.php index b6b6ab8c8015d..0977d7350736a 100644 --- a/src/Symfony/Component/Security/Core/Tests/Encoder/BCryptPasswordEncoderTest.php +++ b/src/Symfony/Component/Security/Core/Tests/Encoder/BCryptPasswordEncoderTest.php @@ -20,7 +20,6 @@ class BCryptPasswordEncoderTest extends TestCase { const PASSWORD = 'password'; - const BYTES = '0123456789abcdef'; const VALID_COST = '04'; /** From a6f44d2a231e4f7861c5da3e2213c44a2988ae57 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Sat, 29 Jul 2017 08:57:55 +0200 Subject: [PATCH 0532/1099] fixed CS --- .../Form/Extension/DataCollector/FormDataCollector.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/Form/Extension/DataCollector/FormDataCollector.php b/src/Symfony/Component/Form/Extension/DataCollector/FormDataCollector.php index 0b5ec7397564c..cef08dce5b375 100644 --- a/src/Symfony/Component/Form/Extension/DataCollector/FormDataCollector.php +++ b/src/Symfony/Component/Form/Extension/DataCollector/FormDataCollector.php @@ -86,7 +86,7 @@ public function __construct(FormDataExtractorInterface $dataExtractor) public function collect(Request $request, Response $response, \Exception $exception = null) { if (70000 <= \PHP_VERSION_ID && \PHP_VERSION_ID < 70800) { - @trigger_error('A bug in PHP v7.0.0 to v7.0.7 is breaking the Form panel, please upgrade to v7.0.8 or more.', E_USER_DEPRECATED); + @trigger_error('A bug in PHP 7.0.0 to 7.0.7 is breaking the Form panel, please upgrade to 7.0.8 or higher.', E_USER_DEPRECATED); } } From 33b737b82f7c06791470e9e60015d25f078579c8 Mon Sep 17 00:00:00 2001 From: Robin Chalas Date: Sat, 29 Jul 2017 02:26:04 +0200 Subject: [PATCH 0533/1099] Make dump() variadic --- .../Component/VarDumper/Resources/functions/dump.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/VarDumper/Resources/functions/dump.php b/src/Symfony/Component/VarDumper/Resources/functions/dump.php index b6c243c8b6e2f..aa7880cbd2bbd 100644 --- a/src/Symfony/Component/VarDumper/Resources/functions/dump.php +++ b/src/Symfony/Component/VarDumper/Resources/functions/dump.php @@ -15,9 +15,11 @@ /** * @author Nicolas Grekas */ - function dump($var) + function dump($var, ...$moreVars) { - foreach (func_get_args() as $var) { + VarDumper::dump($var); + + foreach ($moreVars as $var) { VarDumper::dump($var); } } From 15ceb18316a2449ce5645c7a759470bd1a416e43 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Sat, 29 Jul 2017 23:25:23 +0200 Subject: [PATCH 0534/1099] [Bridge/ProxyManager] Relax test to allow protected factories on master --- .../Tests/LazyProxy/Fixtures/php/lazy_service_structure.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/Fixtures/php/lazy_service_structure.txt b/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/Fixtures/php/lazy_service_structure.txt index 09729e790539a..88e2933cd9015 100644 --- a/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/Fixtures/php/lazy_service_structure.txt +++ b/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/Fixtures/php/lazy_service_structure.txt @@ -3,7 +3,7 @@ use %a class LazyServiceProjectServiceContainer extends Container {%a - public function getFooService($lazyLoad = true) + p%s function getFooService($lazyLoad = true) { if ($lazyLoad) { From b984d512fb70b16a365a9e83fdc60954a9eff853 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Sat, 29 Jul 2017 23:53:09 +0200 Subject: [PATCH 0535/1099] fix typo --- .../Form/Extension/DataCollector/FormDataCollector.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/Form/Extension/DataCollector/FormDataCollector.php b/src/Symfony/Component/Form/Extension/DataCollector/FormDataCollector.php index cef08dce5b375..943ad3fba5f3d 100644 --- a/src/Symfony/Component/Form/Extension/DataCollector/FormDataCollector.php +++ b/src/Symfony/Component/Form/Extension/DataCollector/FormDataCollector.php @@ -85,7 +85,7 @@ public function __construct(FormDataExtractorInterface $dataExtractor) */ public function collect(Request $request, Response $response, \Exception $exception = null) { - if (70000 <= \PHP_VERSION_ID && \PHP_VERSION_ID < 70800) { + if (70000 <= \PHP_VERSION_ID && \PHP_VERSION_ID < 70008) { @trigger_error('A bug in PHP 7.0.0 to 7.0.7 is breaking the Form panel, please upgrade to 7.0.8 or higher.', E_USER_DEPRECATED); } } From 2282a6f895dfa2b0cf8756ccfe992a3101e646f6 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Fri, 28 Jul 2017 15:02:25 +0200 Subject: [PATCH 0536/1099] Bump minimal PHP version to ^5.5.9|>=7.0.8 --- composer.json | 2 +- src/Symfony/Bridge/Doctrine/composer.json | 2 +- src/Symfony/Bridge/Monolog/composer.json | 2 +- src/Symfony/Bridge/ProxyManager/composer.json | 2 +- src/Symfony/Bridge/Twig/composer.json | 2 +- src/Symfony/Bundle/DebugBundle/composer.json | 2 +- src/Symfony/Bundle/FrameworkBundle/composer.json | 2 +- src/Symfony/Bundle/SecurityBundle/composer.json | 2 +- src/Symfony/Bundle/TwigBundle/composer.json | 2 +- src/Symfony/Bundle/WebProfilerBundle/composer.json | 2 +- src/Symfony/Bundle/WebServerBundle/composer.json | 2 +- src/Symfony/Component/Asset/composer.json | 2 +- src/Symfony/Component/BrowserKit/composer.json | 2 +- src/Symfony/Component/Cache/composer.json | 2 +- src/Symfony/Component/ClassLoader/composer.json | 2 +- src/Symfony/Component/Config/composer.json | 2 +- src/Symfony/Component/Console/composer.json | 2 +- src/Symfony/Component/CssSelector/composer.json | 2 +- src/Symfony/Component/Debug/composer.json | 2 +- src/Symfony/Component/DependencyInjection/composer.json | 2 +- src/Symfony/Component/DomCrawler/composer.json | 2 +- src/Symfony/Component/Dotenv/composer.json | 2 +- src/Symfony/Component/EventDispatcher/composer.json | 2 +- src/Symfony/Component/ExpressionLanguage/composer.json | 2 +- src/Symfony/Component/Filesystem/composer.json | 2 +- src/Symfony/Component/Finder/composer.json | 2 +- .../Form/Extension/DataCollector/FormDataCollector.php | 3 --- src/Symfony/Component/Form/composer.json | 2 +- src/Symfony/Component/HttpFoundation/composer.json | 2 +- src/Symfony/Component/HttpKernel/composer.json | 2 +- src/Symfony/Component/Inflector/composer.json | 2 +- src/Symfony/Component/Intl/composer.json | 2 +- src/Symfony/Component/Ldap/composer.json | 2 +- src/Symfony/Component/OptionsResolver/composer.json | 2 +- src/Symfony/Component/Process/composer.json | 2 +- src/Symfony/Component/PropertyAccess/composer.json | 2 +- src/Symfony/Component/PropertyInfo/composer.json | 2 +- src/Symfony/Component/Routing/composer.json | 2 +- src/Symfony/Component/Security/Core/composer.json | 2 +- src/Symfony/Component/Security/Csrf/composer.json | 2 +- src/Symfony/Component/Security/Guard/composer.json | 2 +- src/Symfony/Component/Security/Http/composer.json | 2 +- src/Symfony/Component/Security/composer.json | 2 +- src/Symfony/Component/Serializer/composer.json | 2 +- src/Symfony/Component/Stopwatch/composer.json | 2 +- src/Symfony/Component/Templating/composer.json | 2 +- src/Symfony/Component/Translation/composer.json | 2 +- src/Symfony/Component/Validator/composer.json | 2 +- src/Symfony/Component/VarDumper/composer.json | 2 +- src/Symfony/Component/WebLink/composer.json | 2 +- src/Symfony/Component/Workflow/composer.json | 2 +- src/Symfony/Component/Yaml/composer.json | 2 +- 52 files changed, 51 insertions(+), 54 deletions(-) diff --git a/composer.json b/composer.json index cf55aeb8ef072..faf29256bc0c9 100644 --- a/composer.json +++ b/composer.json @@ -16,7 +16,7 @@ } ], "require": { - "php": ">=5.5.9", + "php": "^5.5.9|>=7.0.8", "ext-xml": "*", "doctrine/common": "~2.4", "fig/link-util": "^1.0", diff --git a/src/Symfony/Bridge/Doctrine/composer.json b/src/Symfony/Bridge/Doctrine/composer.json index 67854035ce6b8..8876d794a1100 100644 --- a/src/Symfony/Bridge/Doctrine/composer.json +++ b/src/Symfony/Bridge/Doctrine/composer.json @@ -16,7 +16,7 @@ } ], "require": { - "php": ">=5.5.9", + "php": "^5.5.9|>=7.0.8", "doctrine/common": "~2.4", "symfony/polyfill-mbstring": "~1.0" }, diff --git a/src/Symfony/Bridge/Monolog/composer.json b/src/Symfony/Bridge/Monolog/composer.json index d60949aab872c..23240155d267f 100644 --- a/src/Symfony/Bridge/Monolog/composer.json +++ b/src/Symfony/Bridge/Monolog/composer.json @@ -16,7 +16,7 @@ } ], "require": { - "php": ">=5.5.9", + "php": "^5.5.9|>=7.0.8", "monolog/monolog": "~1.19", "symfony/http-kernel": "~2.8|~3.0" }, diff --git a/src/Symfony/Bridge/ProxyManager/composer.json b/src/Symfony/Bridge/ProxyManager/composer.json index 42751d000e59d..43a674eac9b25 100644 --- a/src/Symfony/Bridge/ProxyManager/composer.json +++ b/src/Symfony/Bridge/ProxyManager/composer.json @@ -16,7 +16,7 @@ } ], "require": { - "php": ">=5.5.9", + "php": "^5.5.9|>=7.0.8", "symfony/dependency-injection": "~2.8|~3.0", "ocramius/proxy-manager": "~0.4|~1.0|~2.0" }, diff --git a/src/Symfony/Bridge/Twig/composer.json b/src/Symfony/Bridge/Twig/composer.json index 8fe41945b72aa..e00e3dc7fad35 100644 --- a/src/Symfony/Bridge/Twig/composer.json +++ b/src/Symfony/Bridge/Twig/composer.json @@ -16,7 +16,7 @@ } ], "require": { - "php": ">=5.5.9", + "php": "^5.5.9|>=7.0.8", "twig/twig": "~1.34|~2.4" }, "require-dev": { diff --git a/src/Symfony/Bundle/DebugBundle/composer.json b/src/Symfony/Bundle/DebugBundle/composer.json index 77e2d1c5621ba..15a8611363ad5 100644 --- a/src/Symfony/Bundle/DebugBundle/composer.json +++ b/src/Symfony/Bundle/DebugBundle/composer.json @@ -16,7 +16,7 @@ } ], "require": { - "php": ">=5.5.9", + "php": "^5.5.9|>=7.0.8", "ext-xml": "*", "symfony/http-kernel": "~2.8|~3.0", "symfony/twig-bridge": "~2.8|~3.0", diff --git a/src/Symfony/Bundle/FrameworkBundle/composer.json b/src/Symfony/Bundle/FrameworkBundle/composer.json index 1105daa373f43..c605471911974 100644 --- a/src/Symfony/Bundle/FrameworkBundle/composer.json +++ b/src/Symfony/Bundle/FrameworkBundle/composer.json @@ -16,7 +16,7 @@ } ], "require": { - "php": ">=5.5.9", + "php": "^5.5.9|>=7.0.8", "ext-xml": "*", "symfony/cache": "~3.3", "symfony/class-loader": "~3.2", diff --git a/src/Symfony/Bundle/SecurityBundle/composer.json b/src/Symfony/Bundle/SecurityBundle/composer.json index 2c9a641e503d7..48de2c03ef46a 100644 --- a/src/Symfony/Bundle/SecurityBundle/composer.json +++ b/src/Symfony/Bundle/SecurityBundle/composer.json @@ -16,7 +16,7 @@ } ], "require": { - "php": ">=5.5.9", + "php": "^5.5.9|>=7.0.8", "ext-xml": "*", "symfony/security": "~3.3", "symfony/dependency-injection": "~3.3", diff --git a/src/Symfony/Bundle/TwigBundle/composer.json b/src/Symfony/Bundle/TwigBundle/composer.json index 1b3cc91c1969c..1a0908a580a83 100644 --- a/src/Symfony/Bundle/TwigBundle/composer.json +++ b/src/Symfony/Bundle/TwigBundle/composer.json @@ -16,7 +16,7 @@ } ], "require": { - "php": ">=5.5.9", + "php": "^5.5.9|>=7.0.8", "symfony/config": "~3.2", "symfony/twig-bridge": "^3.3", "symfony/http-foundation": "~2.8|~3.0", diff --git a/src/Symfony/Bundle/WebProfilerBundle/composer.json b/src/Symfony/Bundle/WebProfilerBundle/composer.json index 626ac4d307d51..12b168150c58d 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/composer.json +++ b/src/Symfony/Bundle/WebProfilerBundle/composer.json @@ -16,7 +16,7 @@ } ], "require": { - "php": ">=5.5.9", + "php": "^5.5.9|>=7.0.8", "symfony/http-kernel": "~3.2", "symfony/polyfill-php70": "~1.0", "symfony/routing": "~2.8|~3.0", diff --git a/src/Symfony/Bundle/WebServerBundle/composer.json b/src/Symfony/Bundle/WebServerBundle/composer.json index 829e110c35206..d1c64e970fcca 100644 --- a/src/Symfony/Bundle/WebServerBundle/composer.json +++ b/src/Symfony/Bundle/WebServerBundle/composer.json @@ -16,7 +16,7 @@ } ], "require": { - "php": ">=5.5.9", + "php": "^5.5.9|>=7.0.8", "symfony/console": "~3.3", "symfony/http-kernel": "~3.3", "symfony/process": "~3.3" diff --git a/src/Symfony/Component/Asset/composer.json b/src/Symfony/Component/Asset/composer.json index 8ed8d9d725212..39ccf2c00170d 100644 --- a/src/Symfony/Component/Asset/composer.json +++ b/src/Symfony/Component/Asset/composer.json @@ -16,7 +16,7 @@ } ], "require": { - "php": ">=5.5.9" + "php": "^5.5.9|>=7.0.8" }, "suggest": { "symfony/http-foundation": "" diff --git a/src/Symfony/Component/BrowserKit/composer.json b/src/Symfony/Component/BrowserKit/composer.json index a18d66e81ea73..b6b7cb01016ab 100644 --- a/src/Symfony/Component/BrowserKit/composer.json +++ b/src/Symfony/Component/BrowserKit/composer.json @@ -16,7 +16,7 @@ } ], "require": { - "php": ">=5.5.9", + "php": "^5.5.9|>=7.0.8", "symfony/dom-crawler": "~2.8|~3.0" }, "require-dev": { diff --git a/src/Symfony/Component/Cache/composer.json b/src/Symfony/Component/Cache/composer.json index 5c0df4b2a598a..f32117b038479 100644 --- a/src/Symfony/Component/Cache/composer.json +++ b/src/Symfony/Component/Cache/composer.json @@ -20,7 +20,7 @@ "psr/simple-cache-implementation": "1.0" }, "require": { - "php": ">=5.5.9", + "php": "^5.5.9|>=7.0.8", "psr/cache": "~1.0", "psr/log": "~1.0", "psr/simple-cache": "^1.0" diff --git a/src/Symfony/Component/ClassLoader/composer.json b/src/Symfony/Component/ClassLoader/composer.json index a1dfc3fa0e096..d1b10ef649f46 100644 --- a/src/Symfony/Component/ClassLoader/composer.json +++ b/src/Symfony/Component/ClassLoader/composer.json @@ -17,7 +17,7 @@ ], "minimum-stability": "dev", "require": { - "php": ">=5.5.9" + "php": "^5.5.9|>=7.0.8" }, "require-dev": { "symfony/finder": "~2.8|~3.0", diff --git a/src/Symfony/Component/Config/composer.json b/src/Symfony/Component/Config/composer.json index 7a51c91ed591a..f2bff19662b41 100644 --- a/src/Symfony/Component/Config/composer.json +++ b/src/Symfony/Component/Config/composer.json @@ -16,7 +16,7 @@ } ], "require": { - "php": ">=5.5.9", + "php": "^5.5.9|>=7.0.8", "symfony/filesystem": "~2.8|~3.0" }, "require-dev": { diff --git a/src/Symfony/Component/Console/composer.json b/src/Symfony/Component/Console/composer.json index db76bf3b2c7a7..d4fef1ea5856c 100644 --- a/src/Symfony/Component/Console/composer.json +++ b/src/Symfony/Component/Console/composer.json @@ -16,7 +16,7 @@ } ], "require": { - "php": ">=5.5.9", + "php": "^5.5.9|>=7.0.8", "symfony/polyfill-mbstring": "~1.0", "symfony/debug": "~2.8|~3.0" }, diff --git a/src/Symfony/Component/CssSelector/composer.json b/src/Symfony/Component/CssSelector/composer.json index e94cfbded0d33..9661f70ea317d 100644 --- a/src/Symfony/Component/CssSelector/composer.json +++ b/src/Symfony/Component/CssSelector/composer.json @@ -20,7 +20,7 @@ } ], "require": { - "php": ">=5.5.9" + "php": "^5.5.9|>=7.0.8" }, "autoload": { "psr-4": { "Symfony\\Component\\CssSelector\\": "" }, diff --git a/src/Symfony/Component/Debug/composer.json b/src/Symfony/Component/Debug/composer.json index 6531eefd999ee..38323dd41c11a 100644 --- a/src/Symfony/Component/Debug/composer.json +++ b/src/Symfony/Component/Debug/composer.json @@ -16,7 +16,7 @@ } ], "require": { - "php": ">=5.5.9", + "php": "^5.5.9|>=7.0.8", "psr/log": "~1.0" }, "conflict": { diff --git a/src/Symfony/Component/DependencyInjection/composer.json b/src/Symfony/Component/DependencyInjection/composer.json index 8c88d4f02a790..0ce0ffeeaf57b 100644 --- a/src/Symfony/Component/DependencyInjection/composer.json +++ b/src/Symfony/Component/DependencyInjection/composer.json @@ -16,7 +16,7 @@ } ], "require": { - "php": ">=5.5.9", + "php": "^5.5.9|>=7.0.8", "psr/container": "^1.0" }, "require-dev": { diff --git a/src/Symfony/Component/DomCrawler/composer.json b/src/Symfony/Component/DomCrawler/composer.json index 84df31fdeae2f..8835234c1171c 100644 --- a/src/Symfony/Component/DomCrawler/composer.json +++ b/src/Symfony/Component/DomCrawler/composer.json @@ -16,7 +16,7 @@ } ], "require": { - "php": ">=5.5.9", + "php": "^5.5.9|>=7.0.8", "symfony/polyfill-mbstring": "~1.0" }, "require-dev": { diff --git a/src/Symfony/Component/Dotenv/composer.json b/src/Symfony/Component/Dotenv/composer.json index 020342bdd4a96..0e6eda933f3fc 100644 --- a/src/Symfony/Component/Dotenv/composer.json +++ b/src/Symfony/Component/Dotenv/composer.json @@ -16,7 +16,7 @@ } ], "require": { - "php": ">=5.5.9" + "php": "^5.5.9|>=7.0.8" }, "require-dev": { "symfony/process": "^3.2" diff --git a/src/Symfony/Component/EventDispatcher/composer.json b/src/Symfony/Component/EventDispatcher/composer.json index faa0429e2d1a0..994e8ca64ad3c 100644 --- a/src/Symfony/Component/EventDispatcher/composer.json +++ b/src/Symfony/Component/EventDispatcher/composer.json @@ -16,7 +16,7 @@ } ], "require": { - "php": ">=5.5.9" + "php": "^5.5.9|>=7.0.8" }, "require-dev": { "symfony/dependency-injection": "~3.3", diff --git a/src/Symfony/Component/ExpressionLanguage/composer.json b/src/Symfony/Component/ExpressionLanguage/composer.json index d9d95f00cf4e4..cd8933d6be356 100644 --- a/src/Symfony/Component/ExpressionLanguage/composer.json +++ b/src/Symfony/Component/ExpressionLanguage/composer.json @@ -16,7 +16,7 @@ } ], "require": { - "php": ">=5.5.9", + "php": "^5.5.9|>=7.0.8", "symfony/cache": "~3.1" }, "autoload": { diff --git a/src/Symfony/Component/Filesystem/composer.json b/src/Symfony/Component/Filesystem/composer.json index 715a34f7d86bc..122b6cea016d8 100644 --- a/src/Symfony/Component/Filesystem/composer.json +++ b/src/Symfony/Component/Filesystem/composer.json @@ -16,7 +16,7 @@ } ], "require": { - "php": ">=5.5.9" + "php": "^5.5.9|>=7.0.8" }, "autoload": { "psr-4": { "Symfony\\Component\\Filesystem\\": "" }, diff --git a/src/Symfony/Component/Finder/composer.json b/src/Symfony/Component/Finder/composer.json index b57dd8bcda24e..8eed8f53e5be5 100644 --- a/src/Symfony/Component/Finder/composer.json +++ b/src/Symfony/Component/Finder/composer.json @@ -16,7 +16,7 @@ } ], "require": { - "php": ">=5.5.9" + "php": "^5.5.9|>=7.0.8" }, "autoload": { "psr-4": { "Symfony\\Component\\Finder\\": "" }, diff --git a/src/Symfony/Component/Form/Extension/DataCollector/FormDataCollector.php b/src/Symfony/Component/Form/Extension/DataCollector/FormDataCollector.php index 943ad3fba5f3d..378edf563b972 100644 --- a/src/Symfony/Component/Form/Extension/DataCollector/FormDataCollector.php +++ b/src/Symfony/Component/Form/Extension/DataCollector/FormDataCollector.php @@ -85,9 +85,6 @@ public function __construct(FormDataExtractorInterface $dataExtractor) */ public function collect(Request $request, Response $response, \Exception $exception = null) { - if (70000 <= \PHP_VERSION_ID && \PHP_VERSION_ID < 70008) { - @trigger_error('A bug in PHP 7.0.0 to 7.0.7 is breaking the Form panel, please upgrade to 7.0.8 or higher.', E_USER_DEPRECATED); - } } /** diff --git a/src/Symfony/Component/Form/composer.json b/src/Symfony/Component/Form/composer.json index 85250b87f357b..a88c0d64eec09 100644 --- a/src/Symfony/Component/Form/composer.json +++ b/src/Symfony/Component/Form/composer.json @@ -16,7 +16,7 @@ } ], "require": { - "php": ">=5.5.9", + "php": "^5.5.9|>=7.0.8", "symfony/event-dispatcher": "~2.8|~3.0", "symfony/intl": "^2.8.18|^3.2.5", "symfony/options-resolver": "~2.8|~3.0", diff --git a/src/Symfony/Component/HttpFoundation/composer.json b/src/Symfony/Component/HttpFoundation/composer.json index dfa25f79ec405..a964975ecb3f2 100644 --- a/src/Symfony/Component/HttpFoundation/composer.json +++ b/src/Symfony/Component/HttpFoundation/composer.json @@ -16,7 +16,7 @@ } ], "require": { - "php": ">=5.5.9", + "php": "^5.5.9|>=7.0.8", "symfony/polyfill-mbstring": "~1.1" }, "require-dev": { diff --git a/src/Symfony/Component/HttpKernel/composer.json b/src/Symfony/Component/HttpKernel/composer.json index babc8663b6487..cc543c6d854fb 100644 --- a/src/Symfony/Component/HttpKernel/composer.json +++ b/src/Symfony/Component/HttpKernel/composer.json @@ -16,7 +16,7 @@ } ], "require": { - "php": ">=5.5.9", + "php": "^5.5.9|>=7.0.8", "symfony/event-dispatcher": "~2.8|~3.0", "symfony/http-foundation": "~3.3", "symfony/debug": "~2.8|~3.0", diff --git a/src/Symfony/Component/Inflector/composer.json b/src/Symfony/Component/Inflector/composer.json index 79f4ed788f62b..df6c12f518746 100644 --- a/src/Symfony/Component/Inflector/composer.json +++ b/src/Symfony/Component/Inflector/composer.json @@ -23,7 +23,7 @@ } ], "require": { - "php": ">=5.5.9" + "php": "^5.5.9|>=7.0.8" }, "autoload": { "psr-4": { "Symfony\\Component\\Inflector\\": "" }, diff --git a/src/Symfony/Component/Intl/composer.json b/src/Symfony/Component/Intl/composer.json index dea362ed22040..452582bb8fecb 100644 --- a/src/Symfony/Component/Intl/composer.json +++ b/src/Symfony/Component/Intl/composer.json @@ -24,7 +24,7 @@ } ], "require": { - "php": ">=5.5.9", + "php": "^5.5.9|>=7.0.8", "symfony/polyfill-intl-icu": "~1.0" }, "require-dev": { diff --git a/src/Symfony/Component/Ldap/composer.json b/src/Symfony/Component/Ldap/composer.json index a2f580f4319fc..5cc3ce11e8c6d 100644 --- a/src/Symfony/Component/Ldap/composer.json +++ b/src/Symfony/Component/Ldap/composer.json @@ -16,7 +16,7 @@ } ], "require": { - "php": ">=5.5.9", + "php": "^5.5.9|>=7.0.8", "symfony/polyfill-php56": "~1.0", "symfony/options-resolver": "~2.8|~3.0", "ext-ldap": "*" diff --git a/src/Symfony/Component/OptionsResolver/composer.json b/src/Symfony/Component/OptionsResolver/composer.json index a751730af3819..4311b59c78172 100644 --- a/src/Symfony/Component/OptionsResolver/composer.json +++ b/src/Symfony/Component/OptionsResolver/composer.json @@ -16,7 +16,7 @@ } ], "require": { - "php": ">=5.5.9" + "php": "^5.5.9|>=7.0.8" }, "autoload": { "psr-4": { "Symfony\\Component\\OptionsResolver\\": "" }, diff --git a/src/Symfony/Component/Process/composer.json b/src/Symfony/Component/Process/composer.json index f899c52b2b818..a6d7c7c464bb0 100644 --- a/src/Symfony/Component/Process/composer.json +++ b/src/Symfony/Component/Process/composer.json @@ -16,7 +16,7 @@ } ], "require": { - "php": ">=5.5.9" + "php": "^5.5.9|>=7.0.8" }, "autoload": { "psr-4": { "Symfony\\Component\\Process\\": "" }, diff --git a/src/Symfony/Component/PropertyAccess/composer.json b/src/Symfony/Component/PropertyAccess/composer.json index 508dd78cc70f4..011ffa7783e46 100644 --- a/src/Symfony/Component/PropertyAccess/composer.json +++ b/src/Symfony/Component/PropertyAccess/composer.json @@ -16,7 +16,7 @@ } ], "require": { - "php": ">=5.5.9", + "php": "^5.5.9|>=7.0.8", "symfony/polyfill-php70": "~1.0", "symfony/inflector": "~3.1" }, diff --git a/src/Symfony/Component/PropertyInfo/composer.json b/src/Symfony/Component/PropertyInfo/composer.json index 4d6cac3ef98d9..fbc8f06a73a6d 100644 --- a/src/Symfony/Component/PropertyInfo/composer.json +++ b/src/Symfony/Component/PropertyInfo/composer.json @@ -23,7 +23,7 @@ } ], "require": { - "php": ">=5.5.9", + "php": "^5.5.9|>=7.0.8", "symfony/inflector": "~3.1" }, "require-dev": { diff --git a/src/Symfony/Component/Routing/composer.json b/src/Symfony/Component/Routing/composer.json index 38069dc4e9ab0..bb4f6a554bd7b 100644 --- a/src/Symfony/Component/Routing/composer.json +++ b/src/Symfony/Component/Routing/composer.json @@ -16,7 +16,7 @@ } ], "require": { - "php": ">=5.5.9" + "php": "^5.5.9|>=7.0.8" }, "require-dev": { "symfony/config": "~2.8|~3.0", diff --git a/src/Symfony/Component/Security/Core/composer.json b/src/Symfony/Component/Security/Core/composer.json index 3e045fb227545..09db36781a2d0 100644 --- a/src/Symfony/Component/Security/Core/composer.json +++ b/src/Symfony/Component/Security/Core/composer.json @@ -16,7 +16,7 @@ } ], "require": { - "php": ">=5.5.9", + "php": "^5.5.9|>=7.0.8", "symfony/polyfill-php56": "~1.0" }, "require-dev": { diff --git a/src/Symfony/Component/Security/Csrf/composer.json b/src/Symfony/Component/Security/Csrf/composer.json index 913cc458b2e2a..46cca3a0abab0 100644 --- a/src/Symfony/Component/Security/Csrf/composer.json +++ b/src/Symfony/Component/Security/Csrf/composer.json @@ -16,7 +16,7 @@ } ], "require": { - "php": ">=5.5.9", + "php": "^5.5.9|>=7.0.8", "symfony/polyfill-php56": "~1.0", "symfony/polyfill-php70": "~1.0", "symfony/security-core": "~2.8|~3.0" diff --git a/src/Symfony/Component/Security/Guard/composer.json b/src/Symfony/Component/Security/Guard/composer.json index 4bf473a89fa93..b21039a275cd6 100644 --- a/src/Symfony/Component/Security/Guard/composer.json +++ b/src/Symfony/Component/Security/Guard/composer.json @@ -16,7 +16,7 @@ } ], "require": { - "php": ">=5.5.9", + "php": "^5.5.9|>=7.0.8", "symfony/security-core": "~2.8|~3.0", "symfony/security-http": "~3.1" }, diff --git a/src/Symfony/Component/Security/Http/composer.json b/src/Symfony/Component/Security/Http/composer.json index b1458eaa93c7a..595364436723c 100644 --- a/src/Symfony/Component/Security/Http/composer.json +++ b/src/Symfony/Component/Security/Http/composer.json @@ -16,7 +16,7 @@ } ], "require": { - "php": ">=5.5.9", + "php": "^5.5.9|>=7.0.8", "symfony/security-core": "~3.2", "symfony/event-dispatcher": "~2.8|~3.0", "symfony/http-foundation": "~2.8|~3.0", diff --git a/src/Symfony/Component/Security/composer.json b/src/Symfony/Component/Security/composer.json index e6835fe883e2e..f39bfcf8ccb58 100644 --- a/src/Symfony/Component/Security/composer.json +++ b/src/Symfony/Component/Security/composer.json @@ -16,7 +16,7 @@ } ], "require": { - "php": ">=5.5.9", + "php": "^5.5.9|>=7.0.8", "symfony/event-dispatcher": "~2.8|~3.0", "symfony/http-foundation": "~2.8|~3.0", "symfony/http-kernel": "~3.3", diff --git a/src/Symfony/Component/Serializer/composer.json b/src/Symfony/Component/Serializer/composer.json index 37dd110bc3f25..cd9fd883716d7 100644 --- a/src/Symfony/Component/Serializer/composer.json +++ b/src/Symfony/Component/Serializer/composer.json @@ -16,7 +16,7 @@ } ], "require": { - "php": ">=5.5.9" + "php": "^5.5.9|>=7.0.8" }, "require-dev": { "symfony/yaml": "~3.3", diff --git a/src/Symfony/Component/Stopwatch/composer.json b/src/Symfony/Component/Stopwatch/composer.json index 0b40c8d102d0d..06194a018693e 100644 --- a/src/Symfony/Component/Stopwatch/composer.json +++ b/src/Symfony/Component/Stopwatch/composer.json @@ -16,7 +16,7 @@ } ], "require": { - "php": ">=5.5.9" + "php": "^5.5.9|>=7.0.8" }, "autoload": { "psr-4": { "Symfony\\Component\\Stopwatch\\": "" }, diff --git a/src/Symfony/Component/Templating/composer.json b/src/Symfony/Component/Templating/composer.json index 7b1d0fb03bf5e..6b34d63a4ebe4 100644 --- a/src/Symfony/Component/Templating/composer.json +++ b/src/Symfony/Component/Templating/composer.json @@ -16,7 +16,7 @@ } ], "require": { - "php": ">=5.5.9" + "php": "^5.5.9|>=7.0.8" }, "require-dev": { "psr/log": "~1.0" diff --git a/src/Symfony/Component/Translation/composer.json b/src/Symfony/Component/Translation/composer.json index e107e2538a15d..f9ed96dc62446 100644 --- a/src/Symfony/Component/Translation/composer.json +++ b/src/Symfony/Component/Translation/composer.json @@ -16,7 +16,7 @@ } ], "require": { - "php": ">=5.5.9", + "php": "^5.5.9|>=7.0.8", "symfony/polyfill-mbstring": "~1.0" }, "require-dev": { diff --git a/src/Symfony/Component/Validator/composer.json b/src/Symfony/Component/Validator/composer.json index ca441954b894f..3fd2d05fcabc4 100644 --- a/src/Symfony/Component/Validator/composer.json +++ b/src/Symfony/Component/Validator/composer.json @@ -16,7 +16,7 @@ } ], "require": { - "php": ">=5.5.9", + "php": "^5.5.9|>=7.0.8", "symfony/polyfill-mbstring": "~1.0", "symfony/translation": "~2.8|~3.0" }, diff --git a/src/Symfony/Component/VarDumper/composer.json b/src/Symfony/Component/VarDumper/composer.json index 930896026ae53..ae74aa4901a45 100644 --- a/src/Symfony/Component/VarDumper/composer.json +++ b/src/Symfony/Component/VarDumper/composer.json @@ -16,7 +16,7 @@ } ], "require": { - "php": ">=5.5.9", + "php": "^5.5.9|>=7.0.8", "symfony/polyfill-mbstring": "~1.0" }, "require-dev": { diff --git a/src/Symfony/Component/WebLink/composer.json b/src/Symfony/Component/WebLink/composer.json index 336feaf006031..a3df726a63b94 100644 --- a/src/Symfony/Component/WebLink/composer.json +++ b/src/Symfony/Component/WebLink/composer.json @@ -16,7 +16,7 @@ } ], "require": { - "php": ">=5.5.9", + "php": "^5.5.9|>=7.0.8", "fig/link-util": "^1.0", "psr/link": "^1.0" }, diff --git a/src/Symfony/Component/Workflow/composer.json b/src/Symfony/Component/Workflow/composer.json index 2e5825f48d0fb..7feef3fe983d6 100644 --- a/src/Symfony/Component/Workflow/composer.json +++ b/src/Symfony/Component/Workflow/composer.json @@ -20,7 +20,7 @@ } ], "require": { - "php": ">=5.5.9", + "php": "^5.5.9|>=7.0.8", "symfony/property-access": "~2.3|~3.0" }, "require-dev": { diff --git a/src/Symfony/Component/Yaml/composer.json b/src/Symfony/Component/Yaml/composer.json index 698b5ced17364..2103d6cfd0092 100644 --- a/src/Symfony/Component/Yaml/composer.json +++ b/src/Symfony/Component/Yaml/composer.json @@ -16,7 +16,7 @@ } ], "require": { - "php": ">=5.5.9" + "php": "^5.5.9|>=7.0.8" }, "require-dev": { "symfony/console": "~2.8|~3.0" From 2769550950451ce0a38b0424aed98ba1076598d1 Mon Sep 17 00:00:00 2001 From: Adam Szaraniec Date: Fri, 28 Jul 2017 23:27:31 +0400 Subject: [PATCH 0537/1099] improve sql explain table display --- .../Resources/views/Profiler/profiler.css.twig | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/profiler.css.twig b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/profiler.css.twig index 94ac2abd2548e..c8c0a8c55e7d8 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/profiler.css.twig +++ b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/profiler.css.twig @@ -874,6 +874,13 @@ table.logs .metadata { margin: .5em 0; padding: 1em; } +.sql-explain { + overflow-x: auto; + max-width: 920px; +} +.sql-explain table td, .sql-explain table tr { + word-break: normal; +} .queries-table pre { {{ mixins.break_long_words|raw }} margin: 0; From 67ecc713642f40e18917b609f41219b82057b5b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9my=20Deruss=C3=A9?= Date: Mon, 31 Jul 2017 09:31:57 +0200 Subject: [PATCH 0538/1099] Deprecate Filesystem/LockHandler --- UPGRADE-3.4.md | 7 +++++ UPGRADE-4.0.md | 7 +++++ .../Console/Command/LockableTrait.php | 31 ++++++++++++------- .../Tests/Command/LockableTraitTest.php | 14 +++++++-- src/Symfony/Component/Console/composer.json | 4 +-- .../Component/Filesystem/LockHandler.php | 6 ++++ .../Filesystem/Tests/LockHandlerTest.php | 3 ++ .../Component/Lock/Store/SemaphoreStore.php | 19 ++++++++++-- .../Tests/Store/BlockingStoreTestTrait.php | 8 ++--- 9 files changed, 77 insertions(+), 22 deletions(-) diff --git a/UPGRADE-3.4.md b/UPGRADE-3.4.md index 503e74922ce41..1619ec95adf04 100644 --- a/UPGRADE-3.4.md +++ b/UPGRADE-3.4.md @@ -11,6 +11,13 @@ Debug * Support for stacked errors in the `ErrorHandler` is deprecated and will be removed in Symfony 4.0. +Filesystem +---------- + + * The `Symfony\Component\Filesystem\LockHandler` class has been deprecated, + use the `Symfony\Component\Lock\Store\FlockStore` class + or the `Symfony\Component\Lock\Store\FlockStore\SemaphoreStore` class directly instead. + Finder ------ diff --git a/UPGRADE-4.0.md b/UPGRADE-4.0.md index 5a8042835c2da..aabaed1c3c18c 100644 --- a/UPGRADE-4.0.md +++ b/UPGRADE-4.0.md @@ -147,6 +147,13 @@ ExpressionLanguage class has been removed. You should use the `CacheItemPoolInterface` interface instead. +Filesystem +---------- + + * The `Symfony\Component\Filesystem\LockHandler` has been removed, + use the `Symfony\Component\Lock\Store\FlockStore` class + or the `Symfony\Component\Lock\Store\FlockStore\SemaphoreStore` class directly instead. + Finder ------ diff --git a/src/Symfony/Component/Console/Command/LockableTrait.php b/src/Symfony/Component/Console/Command/LockableTrait.php index 95597705941ca..b521f3b7708b9 100644 --- a/src/Symfony/Component/Console/Command/LockableTrait.php +++ b/src/Symfony/Component/Console/Command/LockableTrait.php @@ -13,7 +13,10 @@ use Symfony\Component\Console\Exception\LogicException; use Symfony\Component\Console\Exception\RuntimeException; -use Symfony\Component\Filesystem\LockHandler; +use Symfony\Component\Lock\Factory; +use Symfony\Component\Lock\Lock; +use Symfony\Component\Lock\Store\FlockStore; +use Symfony\Component\Lock\Store\SemaphoreStore; /** * Basic lock feature for commands. @@ -22,7 +25,8 @@ */ trait LockableTrait { - private $lockHandler; + /** @var Lock */ + private $lock; /** * Locks a command. @@ -31,18 +35,23 @@ trait LockableTrait */ private function lock($name = null, $blocking = false) { - if (!class_exists(LockHandler::class)) { - throw new RuntimeException('To enable the locking feature you must install the symfony/filesystem component.'); + if (!class_exists(SemaphoreStore::class)) { + throw new RuntimeException('To enable the locking feature you must install the symfony/lock component.'); } - if (null !== $this->lockHandler) { + if (null !== $this->lock) { throw new LogicException('A lock is already in place.'); } - $this->lockHandler = new LockHandler($name ?: $this->getName()); + if (SemaphoreStore::isSupported($blocking)) { + $store = new SemaphoreStore(); + } else { + $store = new FlockStore(sys_get_temp_dir()); + } - if (!$this->lockHandler->lock($blocking)) { - $this->lockHandler = null; + $this->lock = (new Factory($store))->createLock($name ?: $this->getName()); + if (!$this->lock->acquire($blocking)) { + $this->lock = null; return false; } @@ -55,9 +64,9 @@ private function lock($name = null, $blocking = false) */ private function release() { - if ($this->lockHandler) { - $this->lockHandler->release(); - $this->lockHandler = null; + if ($this->lock) { + $this->lock->release(); + $this->lock = null; } } } diff --git a/src/Symfony/Component/Console/Tests/Command/LockableTraitTest.php b/src/Symfony/Component/Console/Tests/Command/LockableTraitTest.php index d45da73bf329c..401ff823a7761 100644 --- a/src/Symfony/Component/Console/Tests/Command/LockableTraitTest.php +++ b/src/Symfony/Component/Console/Tests/Command/LockableTraitTest.php @@ -13,7 +13,9 @@ use PHPUnit\Framework\TestCase; use Symfony\Component\Console\Tester\CommandTester; -use Symfony\Component\Filesystem\LockHandler; +use Symfony\Component\Lock\Factory; +use Symfony\Component\Lock\Store\FlockStore; +use Symfony\Component\Lock\Store\SemaphoreStore; class LockableTraitTest extends TestCase { @@ -39,8 +41,14 @@ public function testLockReturnsFalseIfAlreadyLockedByAnotherCommand() { $command = new \FooLockCommand(); - $lock = new LockHandler($command->getName()); - $lock->lock(); + if (SemaphoreStore::isSupported(false)) { + $store = new SemaphoreStore(); + } else { + $store = new FlockStore(sys_get_temp_dir()); + } + + $lock = (new Factory($store))->createLock($command->getName()); + $lock->acquire(); $tester = new CommandTester($command); $this->assertSame(1, $tester->execute(array())); diff --git a/src/Symfony/Component/Console/composer.json b/src/Symfony/Component/Console/composer.json index 5f7fe6ec1aa3b..472136c87ea10 100644 --- a/src/Symfony/Component/Console/composer.json +++ b/src/Symfony/Component/Console/composer.json @@ -25,13 +25,13 @@ "symfony/http-kernel": "~2.8|~3.0|~4.0", "symfony/event-dispatcher": "~2.8|~3.0|~4.0", "symfony/dependency-injection": "~3.3|~4.0", - "symfony/filesystem": "~2.8|~3.0|~4.0", + "symfony/lock": "~3.4|~4.0", "symfony/process": "~3.3|~4.0", "psr/log": "~1.0" }, "suggest": { "symfony/event-dispatcher": "", - "symfony/filesystem": "", + "symfony/lock": "", "symfony/process": "", "psr/log": "For using the console logger" }, diff --git a/src/Symfony/Component/Filesystem/LockHandler.php b/src/Symfony/Component/Filesystem/LockHandler.php index 3496faae21336..a05529f13c3ec 100644 --- a/src/Symfony/Component/Filesystem/LockHandler.php +++ b/src/Symfony/Component/Filesystem/LockHandler.php @@ -11,7 +11,11 @@ namespace Symfony\Component\Filesystem; +@trigger_error(sprintf('The %s class is deprecated since version 3.4 and will be removed in 4.0. Use %s or %s instead.', LockHandler::class, SemaphoreStore::class, FlockStore::class), E_USER_DEPRECATED); + use Symfony\Component\Filesystem\Exception\IOException; +use Symfony\Component\Lock\Store\FlockStore; +use Symfony\Component\Lock\Store\SemaphoreStore; /** * LockHandler class provides a simple abstraction to lock anything by means of @@ -25,6 +29,8 @@ * @author Grégoire Pineau * @author Romain Neutron * @author Nicolas Grekas + * + * @deprecated since version 3.4, to be removed in 4.0. Use Symfony\Component\Lock\Store\SemaphoreStore or Symfony\Component\Lock\Store\FlockStore instead. */ class LockHandler { diff --git a/src/Symfony/Component/Filesystem/Tests/LockHandlerTest.php b/src/Symfony/Component/Filesystem/Tests/LockHandlerTest.php index 9ed871ea5a2a3..e0b2281e0552a 100644 --- a/src/Symfony/Component/Filesystem/Tests/LockHandlerTest.php +++ b/src/Symfony/Component/Filesystem/Tests/LockHandlerTest.php @@ -16,6 +16,9 @@ use Symfony\Component\Filesystem\Filesystem; use Symfony\Component\Filesystem\LockHandler; +/** + * @group legacy + */ class LockHandlerTest extends TestCase { /** diff --git a/src/Symfony/Component/Lock/Store/SemaphoreStore.php b/src/Symfony/Component/Lock/Store/SemaphoreStore.php index 9b375fe8d9746..006f6f3f14f80 100644 --- a/src/Symfony/Component/Lock/Store/SemaphoreStore.php +++ b/src/Symfony/Component/Lock/Store/SemaphoreStore.php @@ -24,9 +24,24 @@ */ class SemaphoreStore implements StoreInterface { - public static function isSupported() + /** + * Returns whether or not the store is supported. + * + * @param bool|null $blocking When not null, checked again the blocking mode. + * + * @return bool + */ + public static function isSupported($blocking = null) { - return extension_loaded('sysvsem'); + if (!extension_loaded('sysvsem')) { + return false; + } + + if ($blocking === false && \PHP_VERSION_ID < 50601) { + return false; + } + + return true; } public function __construct() diff --git a/src/Symfony/Component/Lock/Tests/Store/BlockingStoreTestTrait.php b/src/Symfony/Component/Lock/Tests/Store/BlockingStoreTestTrait.php index 566f7eb562daf..d95837ff7456d 100644 --- a/src/Symfony/Component/Lock/Tests/Store/BlockingStoreTestTrait.php +++ b/src/Symfony/Component/Lock/Tests/Store/BlockingStoreTestTrait.php @@ -35,7 +35,7 @@ abstract protected function getStore(); public function testBlockingLocks() { // Amount a microsecond used to order async actions - $clockDelay = 50000; + $clockDelay = 200000; if (\PHP_VERSION_ID < 50600 || defined('HHVM_VERSION_ID')) { $this->markTestSkipped('The PHP engine does not keep resource in child forks'); @@ -49,7 +49,7 @@ public function testBlockingLocks() if ($childPID1 = pcntl_fork()) { // give time to fork to start - usleep(2 * $clockDelay); + usleep(1 * $clockDelay); try { // This call should failed given the lock should already by acquired by the child #1 @@ -69,8 +69,8 @@ public function testBlockingLocks() } else { try { $store->save($key); - // Wait 3 ClockDelay to let parent process to finish - usleep(3 * $clockDelay); + // Wait 2 ClockDelay to let parent process to finish + usleep(2 * $clockDelay); $store->delete($key); exit(0); } catch (\Exception $e) { From a0cd96812e3055a2a9cfebfbde5ad460d12a1ac5 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Tue, 1 Aug 2017 09:06:55 +0200 Subject: [PATCH 0539/1099] updated CHANGELOG for 2.7.33 --- CHANGELOG-2.7.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/CHANGELOG-2.7.md b/CHANGELOG-2.7.md index 335dfd82e4186..d08766327bc5e 100644 --- a/CHANGELOG-2.7.md +++ b/CHANGELOG-2.7.md @@ -7,6 +7,17 @@ in 2.7 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/v2.7.0...v2.7.1 +* 2.7.33 (2017-08-01) + + * bug #22244 [Console] Fix passing options with defaultCommand (Jakub Sacha) + * bug #23684 [Debug] Missing escape in debug output (c960657) + * bug #23662 [VarDumper] Adapt to php 7.2 changes (nicolas-grekas) + * bug #23649 [Form][TwigBridge] Don't render _method in form_rest() for a child form (fmarchalemisys) + * bug #23619 [Validator] Fix IbanValidator for ukrainian IBANs (paroe) + * bug #23238 [Security] ensure the 'route' index is set before attempting to use it (gsdevme) + * bug #23580 Fix login redirect when referer contains a query string (fabpot) + * bug #23574 [VarDumper] Move locale sniffing to dump() time (nicolas-grekas) + * 2.7.32 (2017-07-17) * security #23507 [Security] validate empty passwords again (xabbuh) From 55123da8f52a01f12c2e6960edff5707ad04add2 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Tue, 1 Aug 2017 09:07:01 +0200 Subject: [PATCH 0540/1099] update CONTRIBUTORS for 2.7.33 --- CONTRIBUTORS.md | 39 ++++++++++++++++++++++++--------------- 1 file changed, 24 insertions(+), 15 deletions(-) diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index 47a6cf9986dcf..1b059f5012cb7 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -20,11 +20,11 @@ Symfony is the result of the work of many people who made the code better - Javier Eguiluz (javier.eguiluz) - Hugo Hamon (hhamon) - Maxime Steinhausser (ogizanagi) - - Abdellatif Ait boudad (aitboudad) - Robin Chalas (chalas_r) + - Abdellatif Ait boudad (aitboudad) + - Grégoire Pineau (lyrixx) - Romain Neutron (romain) - Pascal Borreli (pborreli) - - Grégoire Pineau (lyrixx) - Wouter De Jong (wouterj) - Joseph Bielawski (stloyd) - Karma Dordrak (drak) @@ -34,8 +34,8 @@ Symfony is the result of the work of many people who made the code better - Jean-François Simon (jfsimon) - Benjamin Eberlei (beberlei) - Igor Wiedler (igorw) - - Eriksen Costa (eriksencosta) - Roland Franssen (ro0) + - Eriksen Costa (eriksencosta) - Jules Pietri (heah) - Sarah Khalil (saro0h) - Guilhem Niot (energetick) @@ -66,6 +66,7 @@ Symfony is the result of the work of many people who made the code better - Eric Clemmons (ericclemmons) - Charles Sarrazin (csarrazi) - Christian Raue + - Konstantin Myakshin (koc) - Arnout Boks (aboks) - Deni - Henrik Westphal (snc) @@ -73,7 +74,7 @@ Symfony is the result of the work of many people who made the code better - Jáchym Toušek (enumag) - Titouan Galopin (tgalopin) - Douglas Greenshields (shieldo) - - Konstantin Myakshin (koc) + - Dany Maillard (maidmaid) - Lee McDermott - Brandon Turner - Luis Cordova (cordoval) @@ -89,23 +90,22 @@ Symfony is the result of the work of many people who made the code better - Fran Moreno (franmomu) - Antoine Hérault (herzult) - Paráda József (paradajozsef) + - Issei Murasawa (issei_m) - Arnaud Le Blanc (arnaud-lb) - Maxime STEINHAUSSER - Alexander M. Turek (derrabus) - Michal Piotrowski (eventhorizon) - - Dany Maillard (maidmaid) - - Issei Murasawa (issei_m) - Tim Nagel (merk) + - Yonel Ceruto González (yonelceruto) - Brice BERNARD (brikou) - Baptiste Clavié (talus) - Vladimir Reznichenko (kalessil) - marc.weistroff - - Yonel Ceruto González (yonelceruto) - lenar + - Tobias Nyholm (tobias) - Włodzimierz Gajda (gajdaw) - Alexander Schwenn (xelaris) - Jacob Dreesen (jdreesen) - - Tobias Nyholm (tobias) - Florian Voutzinos (florianv) - Colin Frei - Adrien Brault (adrienbrault) @@ -132,13 +132,13 @@ Symfony is the result of the work of many people who made the code better - Daniel Gomes (danielcsgomes) - Hidenori Goto (hidenorigoto) - Guilherme Blanco (guilhermeblanco) + - David Maicher (dmaicher) - Pablo Godel (pgodel) - Jérémie Augustin (jaugustin) - Andréia Bohner (andreia) - Rafael Dohms (rdohms) - Arnaud Kleinpeter (nanocom) - jwdeitch - - David Maicher (dmaicher) - Mikael Pajunen - Joel Wurtz (brouznouf) - Jérôme Vasseur (jvasseur) @@ -175,6 +175,7 @@ Symfony is the result of the work of many people who made the code better - Dennis Benkert (denderello) - Benjamin Dulau (dbenjamin) - Mathieu Lemoine (lemoinem) + - Christian Schmidt - Andreas Hucks (meandmymonkey) - Noel Guilbert (noel) - Stepan Anchugov (kix) @@ -200,7 +201,6 @@ Symfony is the result of the work of many people who made the code better - John Kary (johnkary) - Justin Hileman (bobthecow) - Blanchon Vincent (blanchonvincent) - - Christian Schmidt - Michele Orselli (orso) - Tom Van Looy (tvlooy) - Sven Paulus (subsven) @@ -236,6 +236,7 @@ Symfony is the result of the work of many people who made the code better - Katsuhiro OGAWA - Patrick McDougle (patrick-mcdougle) - Alif Rachmawadi + - Alessandro Chitolina - Kristen Gilden (kgilden) - Pierre-Yves LEBECQ (pylebecq) - Jordan Samouh (jordansamouh) @@ -261,6 +262,8 @@ Symfony is the result of the work of many people who made the code better - Pavel Batanov (scaytrase) - Nikita Konstantinov - Wodor Wodorski + - Rob Frawley 2nd (robfrawley) + - Gregor Harlan (gharlan) - Thomas Lallement (raziel057) - Giorgio Premi - Matthieu Napoli (mnapoli) @@ -276,7 +279,6 @@ Symfony is the result of the work of many people who made the code better - Marc Weistroff (futurecat) - Christian Schmidt - Hidde Wieringa (hiddewie) - - Alessandro Chitolina - Chad Sikorra (chadsikorra) - Chris Smith (cs278) - Florian Klein (docteurklein) @@ -313,7 +315,6 @@ Symfony is the result of the work of many people who made the code better - Thierry Thuon (lepiaf) - Ricard Clau (ricardclau) - Mark Challoner (markchalloner) - - Gregor Harlan (gharlan) - Gennady Telegin (gtelegin) - Ben Davies (bendavies) - Erin Millard @@ -322,7 +323,6 @@ Symfony is the result of the work of many people who made the code better - Magnus Nordlander (magnusnordlander) - alquerci - Francesco Levorato - - Rob Frawley 2nd (robfrawley) - Vitaliy Zakharov (zakharovvi) - Tobias Sjösten (tobiassjosten) - Gyula Sallai (salla) @@ -339,6 +339,7 @@ Symfony is the result of the work of many people who made the code better - Thomas Calvet (fancyweb) - Niels Keurentjes (curry684) - JhonnyL + - David Badura (davidbadura) - hossein zolfi (ocean) - Clément Gautier (clementgautier) - Eduardo Gulias (egulias) @@ -428,7 +429,6 @@ Symfony is the result of the work of many people who made the code better - Christian Wahler - Gintautas Miselis - Rob Bast - - David Badura (davidbadura) - Zander Baldwin - Adam Harvey - Maxime Veber (nek-) @@ -543,6 +543,7 @@ Symfony is the result of the work of many people who made the code better - Max Rath (drak3) - Stéphane Escandell (sescandell) - Konstantin S. M. Möllers (ksmmoellers) + - James Johnston - Sinan Eldem - Alexandre Dupuy (satchette) - Andre Rømcke (andrerom) @@ -591,6 +592,7 @@ Symfony is the result of the work of many people who made the code better - Ulumuddin Yunus (joenoez) - Luc Vieillescazes (iamluc) - Johann Saunier (prophet777) + - Valentin Udaltsov (vudaltsov) - Michael Devery (mickadoo) - Antoine Corcy - Artur Eshenbrener @@ -909,6 +911,7 @@ Symfony is the result of the work of many people who made the code better - Alex Demchenko (pilot) - Tadas Gliaubicas (tadcka) - Benoit Garret + - Jakub Sacha - DerManoMann - Olaf Klischat - orlovv @@ -1173,6 +1176,7 @@ Symfony is the result of the work of many people who made the code better - Malte Wunsch - wusuopu - povilas + - Gavin Staniforth - Alessandro Tagliapietra (alex88) - Biji (biji) - Gunnar Lium (gunnarlium) @@ -1234,6 +1238,7 @@ Symfony is the result of the work of many people who made the code better - flack - izzyp - František Bereň + - Mike Francis - Christoph Nissle (derstoffel) - Ionel Scutelnicu (ionelscutelnicu) - Nicolas Tallefourtané (nicolab) @@ -1244,6 +1249,7 @@ Symfony is the result of the work of many people who made the code better - jjanvier - Julius Beckmann - Romain Dorgueil + - Christopher Parotat - Grayson Koonce (breerly) - Fabien LUCAS (flucas2) - Indra Gunawan (indragunawan) @@ -1535,11 +1541,13 @@ Symfony is the result of the work of many people who made the code better - Ladislav Tánczos - Brian Freytag - Skorney + - fmarchalemisys - mieszko4 - Steve Preston - Neophy7e - bokonet - Arrilot + - Shaun Simmons - Markus Staab - Pierre-Louis LAUNAY - djama @@ -1568,6 +1576,7 @@ Symfony is the result of the work of many people who made the code better - Penny Leach - Richard Trebichavský - g123456789l + - Jonathan Vollebregt - oscartv - DanSync - Peter Zwosta @@ -1680,7 +1689,6 @@ Symfony is the result of the work of many people who made the code better - Moritz Kraft (userfriendly) - Víctor Mateo (victormateo) - Vincent (vincent1870) - - Valentin Udaltsov (vudaltsov) - Eugene Babushkin (warl) - Wouter Sioen (wouter_sioen) - Xavier Amado (xamado) @@ -1702,6 +1710,7 @@ Symfony is the result of the work of many people who made the code better - Sergey Fedotov - Michael - fh-github@fholzhauer.de + - AbdElKader Bouadjadja - Jan Emrich - Mark Topper - Xavier REN From b30d34baf60f97d03548de60d7f22198f4ad0a2c Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Tue, 1 Aug 2017 09:07:03 +0200 Subject: [PATCH 0541/1099] updated VERSION for 2.7.33 --- 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 6221e163755f1..60ced9c9d646e 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -58,12 +58,12 @@ abstract class Kernel implements KernelInterface, TerminableInterface protected $startTime; protected $loadClassCache; - const VERSION = '2.7.33-DEV'; + const VERSION = '2.7.33'; const VERSION_ID = 20733; const MAJOR_VERSION = 2; const MINOR_VERSION = 7; const RELEASE_VERSION = 33; - const EXTRA_VERSION = 'DEV'; + const EXTRA_VERSION = ''; const END_OF_MAINTENANCE = '05/2018'; const END_OF_LIFE = '05/2019'; From 8acbd12a24af4714a4c83d57bf766286a69a240c Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Tue, 1 Aug 2017 09:21:40 +0200 Subject: [PATCH 0542/1099] bumped Symfony version to 2.7.34 --- 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 60ced9c9d646e..401a3626d84b4 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -58,12 +58,12 @@ abstract class Kernel implements KernelInterface, TerminableInterface protected $startTime; protected $loadClassCache; - const VERSION = '2.7.33'; - const VERSION_ID = 20733; + const VERSION = '2.7.34-DEV'; + const VERSION_ID = 20734; const MAJOR_VERSION = 2; const MINOR_VERSION = 7; - const RELEASE_VERSION = 33; - const EXTRA_VERSION = ''; + const RELEASE_VERSION = 34; + const EXTRA_VERSION = 'DEV'; const END_OF_MAINTENANCE = '05/2018'; const END_OF_LIFE = '05/2019'; From acd0af6d29c7e15d3c8dc53a14c2ed4bdef3a9e0 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Tue, 1 Aug 2017 11:05:00 +0200 Subject: [PATCH 0543/1099] updated CHANGELOG for 2.8.26 --- CHANGELOG-2.8.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/CHANGELOG-2.8.md b/CHANGELOG-2.8.md index a73a824d4cf45..5fdc52f111daa 100644 --- a/CHANGELOG-2.8.md +++ b/CHANGELOG-2.8.md @@ -7,6 +7,19 @@ in 2.8 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/v2.8.0...v2.8.1 +* 2.8.26 (2017-08-01) + + * bug #22244 [Console] Fix passing options with defaultCommand (Jakub Sacha) + * bug #23684 [Debug] Missing escape in debug output (c960657) + * bug #23662 [VarDumper] Adapt to php 7.2 changes (nicolas-grekas) + * bug #23649 [Form][TwigBridge] Don't render _method in form_rest() for a child form (fmarchalemisys) + * bug #23023 [DoctrineBridge][PropertyInfo] Added support for Doctrine Embeddables (vudaltsov) + * bug #23619 [Validator] Fix IbanValidator for ukrainian IBANs (paroe) + * bug #23238 [Security] ensure the 'route' index is set before attempting to use it (gsdevme) + * bug #23330 [WebProfilerBundle] Fix full sized dump hovering in toolbar (ogizanagi) + * bug #23580 Fix login redirect when referer contains a query string (fabpot) + * bug #23574 [VarDumper] Move locale sniffing to dump() time (nicolas-grekas) + * 2.8.25 (2017-07-17) * security #23507 [Security] validate empty passwords again (xabbuh) From d2e8f38a78a3028f15f4f86686003f9de780b7f0 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Tue, 1 Aug 2017 11:05:02 +0200 Subject: [PATCH 0544/1099] updated VERSION for 2.8.26 --- 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 69d5dbdceeb39..118d67aaec835 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -59,12 +59,12 @@ abstract class Kernel implements KernelInterface, TerminableInterface protected $startTime; protected $loadClassCache; - const VERSION = '2.8.26-DEV'; + const VERSION = '2.8.26'; const VERSION_ID = 20826; const MAJOR_VERSION = 2; const MINOR_VERSION = 8; const RELEASE_VERSION = 26; - const EXTRA_VERSION = 'DEV'; + const EXTRA_VERSION = ''; const END_OF_MAINTENANCE = '11/2018'; const END_OF_LIFE = '11/2019'; From ee4dc20e0f91a7023c92b94e87973f722294758c Mon Sep 17 00:00:00 2001 From: Ben Scott Date: Sun, 30 Jul 2017 15:50:35 +0100 Subject: [PATCH 0545/1099] Autoconfigure instances of ArgumentValueResolverInterface Add the controller.argument_value_resolver tag to instances of ArgumentValueResolverInterface --- .../FrameworkBundle/DependencyInjection/FrameworkExtension.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php index a3c92a026be52..b7219c473f0f4 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php @@ -42,6 +42,7 @@ use Symfony\Component\Form\FormTypeInterface; use Symfony\Component\HttpKernel\CacheClearer\CacheClearerInterface; use Symfony\Component\HttpKernel\CacheWarmer\CacheWarmerInterface; +use Symfony\Component\HttpKernel\Controller\ArgumentValueResolverInterface; use Symfony\Component\HttpKernel\DataCollector\DataCollectorInterface; use Symfony\Component\HttpKernel\DependencyInjection\Extension; use Symfony\Component\PropertyAccess\PropertyAccessor; @@ -269,6 +270,8 @@ public function load(array $configs, ContainerBuilder $container) ->addTag('config_cache.resource_checker'); $container->registerForAutoconfiguration(ServiceSubscriberInterface::class) ->addTag('container.service_subscriber'); + $container->registerForAutoconfiguration(ArgumentValueResolverInterface::class) + ->addTag('controller.argument_value_resolver'); $container->registerForAutoconfiguration(AbstractController::class) ->addTag('controller.service_arguments'); $container->registerForAutoconfiguration(Controller::class) From 6f05bebe1f6829a964396de552e69cbb56d571f0 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Tue, 1 Aug 2017 11:29:28 +0200 Subject: [PATCH 0546/1099] bumped Symfony version to 2.8.27 --- 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 118d67aaec835..ff1dc40d15fb8 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -59,12 +59,12 @@ abstract class Kernel implements KernelInterface, TerminableInterface protected $startTime; protected $loadClassCache; - const VERSION = '2.8.26'; - const VERSION_ID = 20826; + const VERSION = '2.8.27-DEV'; + const VERSION_ID = 20827; const MAJOR_VERSION = 2; const MINOR_VERSION = 8; - const RELEASE_VERSION = 26; - const EXTRA_VERSION = ''; + const RELEASE_VERSION = 27; + const EXTRA_VERSION = 'DEV'; const END_OF_MAINTENANCE = '11/2018'; const END_OF_LIFE = '11/2019'; From ab0cbd48616ba1501d94ca5129e3ab80b8f5e8f5 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Tue, 1 Aug 2017 11:40:12 +0200 Subject: [PATCH 0547/1099] updated CHANGELOG for 3.2.13 --- CHANGELOG-3.2.md | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/CHANGELOG-3.2.md b/CHANGELOG-3.2.md index 1a4d44e19981e..544ae4b071c06 100644 --- a/CHANGELOG-3.2.md +++ b/CHANGELOG-3.2.md @@ -7,6 +7,22 @@ in 3.2 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.2.0...v3.2.1 +* 3.2.13 (2017-08-01) + + * bug #22244 [Console] Fix passing options with defaultCommand (Jakub Sacha) + * bug #23684 [Debug] Missing escape in debug output (c960657) + * bug #23654 [DI] Fix using private services in expressions (nicolas-grekas) + * bug #23662 [VarDumper] Adapt to php 7.2 changes (nicolas-grekas) + * bug #23649 [Form][TwigBridge] Don't render _method in form_rest() for a child form (fmarchalemisys) + * bug #23023 [DoctrineBridge][PropertyInfo] Added support for Doctrine Embeddables (vudaltsov) + * bug #23619 [Validator] Fix IbanValidator for ukrainian IBANs (paroe) + * bug #23586 Fix case sensitive sameSite cookie (mikefrancis) + * bug #23238 [Security] ensure the 'route' index is set before attempting to use it (gsdevme) + * bug #23330 [WebProfilerBundle] Fix full sized dump hovering in toolbar (ogizanagi) + * bug #23580 Fix login redirect when referer contains a query string (fabpot) + * bug #23558 [FrameworkBundle] fix ValidatorCacheWarmer: use serializing ArrayAdapter (dmaicher) + * bug #23574 [VarDumper] Move locale sniffing to dump() time (nicolas-grekas) + * 3.2.12 (2017-07-17) * bug #23549 [PropertyInfo] conflict for phpdocumentor/reflection-docblock 3.2 (xabbuh) From 7ce788b5ddb7f811dae50cb48376ef2e6395e8df Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Tue, 1 Aug 2017 11:40:19 +0200 Subject: [PATCH 0548/1099] updated VERSION for 3.2.13 --- 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 30d692cbf4e45..3b3d87814b6ab 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -58,12 +58,12 @@ abstract class Kernel implements KernelInterface, TerminableInterface protected $startTime; protected $loadClassCache; - const VERSION = '3.2.13-DEV'; + const VERSION = '3.2.13'; const VERSION_ID = 30213; const MAJOR_VERSION = 3; const MINOR_VERSION = 2; const RELEASE_VERSION = 13; - const EXTRA_VERSION = 'DEV'; + const EXTRA_VERSION = ''; const END_OF_MAINTENANCE = '07/2017'; const END_OF_LIFE = '01/2018'; From 927f95001913724cb12e6b79043193497e7062e1 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Tue, 1 Aug 2017 12:20:44 +0200 Subject: [PATCH 0549/1099] bumped Symfony version to 3.2.14 --- 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 3b3d87814b6ab..9093145d3404b 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -58,12 +58,12 @@ abstract class Kernel implements KernelInterface, TerminableInterface protected $startTime; protected $loadClassCache; - const VERSION = '3.2.13'; - const VERSION_ID = 30213; + const VERSION = '3.2.14-DEV'; + const VERSION_ID = 30214; const MAJOR_VERSION = 3; const MINOR_VERSION = 2; - const RELEASE_VERSION = 13; - const EXTRA_VERSION = ''; + const RELEASE_VERSION = 14; + const EXTRA_VERSION = 'DEV'; const END_OF_MAINTENANCE = '07/2017'; const END_OF_LIFE = '01/2018'; From bdc8ca0d960697dcc381b50edfe18cb301d7a8ff Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Tue, 1 Aug 2017 12:25:49 +0200 Subject: [PATCH 0550/1099] updated CHANGELOG for 3.3.6 --- CHANGELOG-3.3.md | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/CHANGELOG-3.3.md b/CHANGELOG-3.3.md index 01e370cdefd0b..e005c1dabe0d0 100644 --- a/CHANGELOG-3.3.md +++ b/CHANGELOG-3.3.md @@ -7,6 +7,35 @@ in 3.3 minor versions. To get the diff for a specific change, go to https://github.com/symfony/symfony/commit/XXX where XXX is the change hash To get the diff between two versions, go to https://github.com/symfony/symfony/compare/v3.3.0...v3.3.1 +* 3.3.6 (2017-08-01) + + * bug #22244 [Console] Fix passing options with defaultCommand (Jakub Sacha) + * bug #23705 [Form] Add notice to upgrade to PHP v7.0.8+ (nicolas-grekas) + * bug #23683 [VarDumper] Keep and reuse array stubs in memory (nicolas-grekas) + * bug #23686 [Console][WebServerBundle] Use "exec" when possible (nicolas-grekas) + * bug #23684 [Debug] Missing escape in debug output (c960657) + * bug #23644 [VarDumper] Dont use Stub objects for arrays - lower GC pressure (nicolas-grekas) + * bug #23615 [Cache] Handle serialization failures for Memcached (nicolas-grekas) + * bug #23654 [DI] Fix using private services in expressions (nicolas-grekas) + * bug #23662 [VarDumper] Adapt to php 7.2 changes (nicolas-grekas) + * bug #23649 [Form][TwigBridge] Don't render _method in form_rest() for a child form (fmarchalemisys) + * bug #23588 [WebProfilerBundle] Display trace and context in the logger profiler (lyrixx) + * bug #23023 [DoctrineBridge][PropertyInfo] Added support for Doctrine Embeddables (vudaltsov) + * bug #23618 [Routing] allow HEAD method to be defined first (DavidBadura) + * bug #23619 [Validator] Fix IbanValidator for ukrainian IBANs (paroe) + * bug #23605 [DI][Bug] Autowiring thinks optional args on core classes are required (weaverryan) + * bug #23586 Fix case sensitive sameSite cookie (mikefrancis) + * bug #23584 Fix the design of the profiler exceptions when there is no message (javiereguiluz) + * bug #23238 [Security] ensure the 'route' index is set before attempting to use it (gsdevme) + * bug #23330 [WebProfilerBundle] Fix full sized dump hovering in toolbar (ogizanagi) + * bug #23581 [Config] Minor fix (nicolas-grekas) + * bug #23580 Fix login redirect when referer contains a query string (fabpot) + * bug #23577 [WebProfilerBundle][TwigBundle] Fix infinite js loop on exception pages (ogizanagi) + * bug #23558 [FrameworkBundle] fix ValidatorCacheWarmer: use serializing ArrayAdapter (dmaicher) + * bug #23573 [Config] Make ClassExistenceResource throw on invalid parents (nicolas-grekas) + * bug #23574 [VarDumper] Move locale sniffing to dump() time (nicolas-grekas) + * bug #23575 [VarDumper] Use "C" locale when using "comma" flags (nicolas-grekas) + * 3.3.5 (2017-07-17) * bug #23549 [PropertyInfo] conflict for phpdocumentor/reflection-docblock 3.2 (xabbuh) From cb1835aa28e1ca8325e762f3602cbd89a3a6c0bf Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Tue, 1 Aug 2017 12:25:59 +0200 Subject: [PATCH 0551/1099] updated VERSION for 3.3.6 --- 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 7517938c1235f..0372a86cf7cbb 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -61,12 +61,12 @@ abstract class Kernel implements KernelInterface, TerminableInterface private $projectDir; - const VERSION = '3.3.6-DEV'; + const VERSION = '3.3.6'; const VERSION_ID = 30306; const MAJOR_VERSION = 3; const MINOR_VERSION = 3; const RELEASE_VERSION = 6; - const EXTRA_VERSION = 'DEV'; + const EXTRA_VERSION = ''; const END_OF_MAINTENANCE = '01/2018'; const END_OF_LIFE = '07/2018'; From 468b44a03136ea2735c8040961c350a81a522fd8 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Tue, 1 Aug 2017 13:24:30 +0200 Subject: [PATCH 0552/1099] bumped Symfony version to 3.3.7 --- 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 0372a86cf7cbb..f6a62a6341cfa 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -61,12 +61,12 @@ abstract class Kernel implements KernelInterface, TerminableInterface private $projectDir; - const VERSION = '3.3.6'; - const VERSION_ID = 30306; + const VERSION = '3.3.7-DEV'; + const VERSION_ID = 30307; const MAJOR_VERSION = 3; const MINOR_VERSION = 3; - const RELEASE_VERSION = 6; - const EXTRA_VERSION = ''; + const RELEASE_VERSION = 7; + const EXTRA_VERSION = 'DEV'; const END_OF_MAINTENANCE = '01/2018'; const END_OF_LIFE = '07/2018'; From ce86449f814f45e95e089ccf28a1a8c53e175905 Mon Sep 17 00:00:00 2001 From: Valentin Date: Tue, 1 Aug 2017 18:09:35 +0300 Subject: [PATCH 0553/1099] Docblock improvement --- .../Component/Security/Guard/GuardAuthenticatorInterface.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Symfony/Component/Security/Guard/GuardAuthenticatorInterface.php b/src/Symfony/Component/Security/Guard/GuardAuthenticatorInterface.php index fef4a04fb9702..307d70f9e973e 100644 --- a/src/Symfony/Component/Security/Guard/GuardAuthenticatorInterface.php +++ b/src/Symfony/Component/Security/Guard/GuardAuthenticatorInterface.php @@ -153,6 +153,7 @@ public function onAuthenticationSuccess(Request $request, TokenInterface $token, * done by having a _remember_me checkbox in your form, but * can be configured by the "always_remember_me" and "remember_me_parameter" * parameters under the "remember_me" firewall key + * D) The onAuthenticationSuccess method returns a Response object * * @return bool */ From 39ab789ce385c5f29f3a77d9470f80207e295786 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9my=20Deruss=C3=A9?= Date: Wed, 2 Aug 2017 07:32:45 +0200 Subject: [PATCH 0554/1099] Remove Filesystem\LockHandler --- src/Symfony/Component/Filesystem/CHANGELOG.md | 5 + .../Component/Filesystem/LockHandler.php | 115 -------------- .../Filesystem/Tests/LockHandlerTest.php | 141 ------------------ 3 files changed, 5 insertions(+), 256 deletions(-) delete mode 100644 src/Symfony/Component/Filesystem/LockHandler.php delete mode 100644 src/Symfony/Component/Filesystem/Tests/LockHandlerTest.php diff --git a/src/Symfony/Component/Filesystem/CHANGELOG.md b/src/Symfony/Component/Filesystem/CHANGELOG.md index 4a275e86f0cad..f3ad3dd387ac1 100644 --- a/src/Symfony/Component/Filesystem/CHANGELOG.md +++ b/src/Symfony/Component/Filesystem/CHANGELOG.md @@ -1,6 +1,11 @@ CHANGELOG ========= +4.0.0 +----- + + * removed `LockHandler` + 3.3.0 ----- diff --git a/src/Symfony/Component/Filesystem/LockHandler.php b/src/Symfony/Component/Filesystem/LockHandler.php deleted file mode 100644 index 3496faae21336..0000000000000 --- a/src/Symfony/Component/Filesystem/LockHandler.php +++ /dev/null @@ -1,115 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Filesystem; - -use Symfony\Component\Filesystem\Exception\IOException; - -/** - * LockHandler class provides a simple abstraction to lock anything by means of - * a file lock. - * - * A locked file is created based on the lock name when calling lock(). Other - * lock handlers will not be able to lock the same name until it is released - * (explicitly by calling release() or implicitly when the instance holding the - * lock is destroyed). - * - * @author Grégoire Pineau - * @author Romain Neutron - * @author Nicolas Grekas - */ -class LockHandler -{ - private $file; - private $handle; - - /** - * @param string $name The lock name - * @param string|null $lockPath The directory to store the lock. Default values will use temporary directory - * - * @throws IOException If the lock directory could not be created or is not writable - */ - public function __construct($name, $lockPath = null) - { - $lockPath = $lockPath ?: sys_get_temp_dir(); - - if (!is_dir($lockPath)) { - $fs = new Filesystem(); - $fs->mkdir($lockPath); - } - - if (!is_writable($lockPath)) { - throw new IOException(sprintf('The directory "%s" is not writable.', $lockPath), 0, null, $lockPath); - } - - $this->file = sprintf('%s/sf.%s.%s.lock', $lockPath, preg_replace('/[^a-z0-9\._-]+/i', '-', $name), hash('sha256', $name)); - } - - /** - * Lock the resource. - * - * @param bool $blocking wait until the lock is released - * - * @return bool Returns true if the lock was acquired, false otherwise - * - * @throws IOException If the lock file could not be created or opened - */ - public function lock($blocking = false) - { - if ($this->handle) { - return true; - } - - $error = null; - - // Silence error reporting - set_error_handler(function ($errno, $msg) use (&$error) { - $error = $msg; - }); - - if (!$this->handle = fopen($this->file, 'r')) { - if ($this->handle = fopen($this->file, 'x')) { - chmod($this->file, 0444); - } elseif (!$this->handle = fopen($this->file, 'r')) { - usleep(100); // Give some time for chmod() to complete - $this->handle = fopen($this->file, 'r'); - } - } - restore_error_handler(); - - if (!$this->handle) { - throw new IOException($error, 0, null, $this->file); - } - - // On Windows, even if PHP doc says the contrary, LOCK_NB works, see - // https://bugs.php.net/54129 - if (!flock($this->handle, LOCK_EX | ($blocking ? 0 : LOCK_NB))) { - fclose($this->handle); - $this->handle = null; - - return false; - } - - return true; - } - - /** - * Release the resource. - */ - public function release() - { - if ($this->handle) { - flock($this->handle, LOCK_UN | LOCK_NB); - fclose($this->handle); - $this->handle = null; - } - } -} diff --git a/src/Symfony/Component/Filesystem/Tests/LockHandlerTest.php b/src/Symfony/Component/Filesystem/Tests/LockHandlerTest.php deleted file mode 100644 index 9ed871ea5a2a3..0000000000000 --- a/src/Symfony/Component/Filesystem/Tests/LockHandlerTest.php +++ /dev/null @@ -1,141 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Filesystem\Tests; - -use PHPUnit\Framework\TestCase; -use Symfony\Component\Filesystem\Exception\IOException; -use Symfony\Component\Filesystem\Filesystem; -use Symfony\Component\Filesystem\LockHandler; - -class LockHandlerTest extends TestCase -{ - /** - * @expectedException \Symfony\Component\Filesystem\Exception\IOException - * @expectedExceptionMessage Failed to create "/a/b/c/d/e": mkdir(): Permission denied. - */ - public function testConstructWhenRepositoryDoesNotExist() - { - if (!getenv('USER') || 'root' === getenv('USER')) { - $this->markTestSkipped('This test will fail if run under superuser'); - } - new LockHandler('lock', '/a/b/c/d/e'); - } - - /** - * @expectedException \Symfony\Component\Filesystem\Exception\IOException - * @expectedExceptionMessage The directory "/" is not writable. - */ - public function testConstructWhenRepositoryIsNotWriteable() - { - if (!getenv('USER') || 'root' === getenv('USER')) { - $this->markTestSkipped('This test will fail if run under superuser'); - } - new LockHandler('lock', '/'); - } - - public function testErrorHandlingInLockIfLockPathBecomesUnwritable() - { - // skip test on Windows; PHP can't easily set file as unreadable on Windows - if ('\\' === DIRECTORY_SEPARATOR) { - $this->markTestSkipped('This test cannot run on Windows.'); - } - - $lockPath = sys_get_temp_dir().'/'.uniqid('', true); - $e = null; - $wrongMessage = null; - - try { - mkdir($lockPath); - - $lockHandler = new LockHandler('lock', $lockPath); - - chmod($lockPath, 0444); - - $lockHandler->lock(); - } catch (IOException $e) { - if (false === strpos($e->getMessage(), 'Permission denied')) { - $wrongMessage = $e->getMessage(); - } else { - $this->addToAssertionCount(1); - } - } catch (\Exception $e) { - } catch (\Throwable $e) { - } - - if (is_dir($lockPath)) { - $fs = new Filesystem(); - $fs->remove($lockPath); - } - - $this->assertInstanceOf('Symfony\Component\Filesystem\Exception\IOException', $e, sprintf('Expected IOException to be thrown, got %s instead.', get_class($e))); - $this->assertNull($wrongMessage, sprintf('Expected exception message to contain "Permission denied", got "%s" instead.', $wrongMessage)); - } - - public function testConstructSanitizeName() - { - $lock = new LockHandler(''); - - $file = sprintf('%s/sf.-php-echo-hello-word-.4b3d9d0d27ddef3a78a64685dda3a963e478659a9e5240feaf7b4173a8f28d5f.lock', sys_get_temp_dir()); - // ensure the file does not exist before the lock - @unlink($file); - - $lock->lock(); - - $this->assertFileExists($file); - - $lock->release(); - } - - public function testLockRelease() - { - $name = 'symfony-test-filesystem.lock'; - - $l1 = new LockHandler($name); - $l2 = new LockHandler($name); - - $this->assertTrue($l1->lock()); - $this->assertFalse($l2->lock()); - - $l1->release(); - - $this->assertTrue($l2->lock()); - $l2->release(); - } - - public function testLockTwice() - { - $name = 'symfony-test-filesystem.lock'; - - $lockHandler = new LockHandler($name); - - $this->assertTrue($lockHandler->lock()); - $this->assertTrue($lockHandler->lock()); - - $lockHandler->release(); - } - - public function testLockIsReleased() - { - $name = 'symfony-test-filesystem.lock'; - - $l1 = new LockHandler($name); - $l2 = new LockHandler($name); - - $this->assertTrue($l1->lock()); - $this->assertFalse($l2->lock()); - - $l1 = null; - - $this->assertTrue($l2->lock()); - $l2->release(); - } -} From a63ab776247cb76ee0c0fec9c37f6a09d2ee0b61 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Wed, 2 Aug 2017 07:57:29 +0200 Subject: [PATCH 0555/1099] [Config] Fix checking class existence freshness --- .../Config/Resource/ClassExistenceResource.php | 7 ++++++- .../Config/Tests/Fixtures/BadParent.php | 7 +++++++ .../Resource/ClassExistenceResourceTest.php | 17 +++++++++++++++++ 3 files changed, 30 insertions(+), 1 deletion(-) create mode 100644 src/Symfony/Component/Config/Tests/Fixtures/BadParent.php diff --git a/src/Symfony/Component/Config/Resource/ClassExistenceResource.php b/src/Symfony/Component/Config/Resource/ClassExistenceResource.php index 623124ab8d988..e3fd095b6008d 100644 --- a/src/Symfony/Component/Config/Resource/ClassExistenceResource.php +++ b/src/Symfony/Component/Config/Resource/ClassExistenceResource.php @@ -65,7 +65,7 @@ public function isFresh($timestamp) { $loaded = class_exists($this->resource, false) || interface_exists($this->resource, false) || trait_exists($this->resource, false); - if (null !== $exists = &self::$existsCache[$this->resource]) { + if (null !== $exists = &self::$existsCache[(int) (0 >= $timestamp)][$this->resource]) { $exists = $exists || $loaded; } elseif (!$exists = $loaded) { if (!self::$autoloadLevel++) { @@ -76,6 +76,11 @@ public function isFresh($timestamp) try { $exists = class_exists($this->resource) || interface_exists($this->resource, false) || trait_exists($this->resource, false); + } catch (\ReflectionException $e) { + if (0 >= $timestamp) { + unset(self::$existsCache[1][$this->resource]); + throw $e; + } } finally { self::$autoloadedClass = $autoloadedClass; if (!--self::$autoloadLevel) { diff --git a/src/Symfony/Component/Config/Tests/Fixtures/BadParent.php b/src/Symfony/Component/Config/Tests/Fixtures/BadParent.php new file mode 100644 index 0000000000000..68d7296ed8696 --- /dev/null +++ b/src/Symfony/Component/Config/Tests/Fixtures/BadParent.php @@ -0,0 +1,7 @@ +assertTrue($res->isFresh(time())); + } + + /** + * @expectedException \ReflectionException + * @expectedExceptionMessage Class Symfony\Component\Config\Tests\Fixtures\MissingParent not found + */ + public function testBadParentWithNoTimestamp() + { + $res = new ClassExistenceResource(BadParent::class, false); + $res->isFresh(0); + } + public function testConditionalClass() { $res = new ClassExistenceResource(ConditionalClass::class, false); From 103b23efb62e42c4bb53064471b22bf28ccdf7ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Parmentier?= Date: Wed, 2 Aug 2017 16:33:39 +0200 Subject: [PATCH 0556/1099] Fix comment --- .../FrameworkBundle/DependencyInjection/FrameworkExtension.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php index 131db0ae86343..c6b1f294ab269 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php @@ -1273,7 +1273,7 @@ private function registerSecurityCsrfConfiguration(array $config, ContainerBuild private function registerSerializerConfiguration(array $config, ContainerBuilder $container, XmlFileLoader $loader) { if (class_exists('Symfony\Component\Serializer\Normalizer\DataUriNormalizer')) { - // Run after serializer.normalizer.object + // Run before serializer.normalizer.object $definition = $container->register('serializer.normalizer.data_uri', DataUriNormalizer::class); $definition->setPublic(false); $definition->addTag('serializer.normalizer', array('priority' => -920)); From 5cc1648ba4baee3bf254fa9232c87ede0b4ffd7f Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Wed, 2 Aug 2017 17:07:40 +0200 Subject: [PATCH 0557/1099] [DI] Generate shorter method names for class-based ids --- .../DependencyInjection/Dumper/PhpDumper.php | 3 ++- .../Tests/Fixtures/containers/container33.php | 9 ++----- .../Tests/Fixtures/php/services33.php | 24 ++++++++++++++----- .../Fixtures/php/services_subscriber.php | 12 +++++----- 4 files changed, 28 insertions(+), 20 deletions(-) diff --git a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php index 9d84c0cb73206..03d8f9babf100 100644 --- a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php +++ b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php @@ -1633,7 +1633,8 @@ private function generateMethodName($id) return $this->serviceIdToMethodNameMap[$id]; } - $name = Container::camelize($id); + $i = strrpos($id, '\\'); + $name = Container::camelize(false !== $i && isset($id[1 + $i]) ? substr($id, 1 + $i) : $id); $name = preg_replace('/[^a-zA-Z0-9_\x7f-\xff]/', '', $name); $methodName = 'get'.$name.'Service'; $suffix = 1; diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container33.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container33.php index 6deb52d170af8..ec68f929d449e 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container33.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container33.php @@ -4,14 +4,9 @@ use Symfony\Component\DependencyInjection\ContainerBuilder; -if (!class_exists(Foo::class, false)) { - class Foo - { - } -} - $container = new ContainerBuilder(); -$container->register(Foo::class); +$container->register(\Foo\Foo::class); +$container->register(\Bar\Foo::class); return $container; diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services33.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services33.php index 51337422c249b..20eda55d99e0f 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services33.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services33.php @@ -28,10 +28,12 @@ public function __construct() { $this->services = array(); $this->normalizedIds = array( - 'symfony\\component\\dependencyinjection\\tests\\fixtures\\container33\\foo' => 'Symfony\\Component\\DependencyInjection\\Tests\\Fixtures\\Container33\\Foo', + 'bar\\foo' => 'Bar\\Foo', + 'foo\\foo' => 'Foo\\Foo', ); $this->methodMap = array( - 'Symfony\\Component\\DependencyInjection\\Tests\\Fixtures\\Container33\\Foo' => 'getSymfony_Component_DependencyInjection_Tests_Fixtures_Container33_FooService', + 'Bar\\Foo' => 'getFooService', + 'Foo\\Foo' => 'getFoo2Service', ); $this->aliases = array(); @@ -64,12 +66,22 @@ public function isFrozen() } /** - * Gets the public 'Symfony\Component\DependencyInjection\Tests\Fixtures\Container33\Foo' shared service. + * Gets the public 'Bar\Foo' shared service. * - * @return \Symfony\Component\DependencyInjection\Tests\Fixtures\Container33\Foo + * @return \Bar\Foo */ - protected function getSymfony_Component_DependencyInjection_Tests_Fixtures_Container33_FooService() + protected function getFooService() { - return $this->services['Symfony\Component\DependencyInjection\Tests\Fixtures\Container33\Foo'] = new \Symfony\Component\DependencyInjection\Tests\Fixtures\Container33\Foo(); + return $this->services['Bar\Foo'] = new \Bar\Foo(); + } + + /** + * Gets the public 'Foo\Foo' shared service. + * + * @return \Foo\Foo + */ + protected function getFoo2Service() + { + return $this->services['Foo\Foo'] = new \Foo\Foo(); } } diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_subscriber.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_subscriber.php index 01c385358b136..f5d94836dd1d9 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_subscriber.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_subscriber.php @@ -32,8 +32,8 @@ public function __construct() 'symfony\\component\\dependencyinjection\\tests\\fixtures\\testservicesubscriber' => 'Symfony\\Component\\DependencyInjection\\Tests\\Fixtures\\TestServiceSubscriber', ); $this->methodMap = array( - 'Symfony\\Component\\DependencyInjection\\Tests\\Fixtures\\TestServiceSubscriber' => 'getSymfony_Component_DependencyInjection_Tests_Fixtures_TestServiceSubscriberService', - 'autowired.Symfony\\Component\\DependencyInjection\\Tests\\Fixtures\\CustomDefinition' => 'getAutowired_Symfony_Component_DependencyInjection_Tests_Fixtures_CustomDefinitionService', + 'Symfony\\Component\\DependencyInjection\\Tests\\Fixtures\\TestServiceSubscriber' => 'getTestServiceSubscriberService', + 'autowired.Symfony\\Component\\DependencyInjection\\Tests\\Fixtures\\CustomDefinition' => 'getCustomDefinitionService', 'foo_service' => 'getFooServiceService', ); $this->privates = array( @@ -74,7 +74,7 @@ public function isFrozen() * * @return \Symfony\Component\DependencyInjection\Tests\Fixtures\TestServiceSubscriber */ - protected function getSymfony_Component_DependencyInjection_Tests_Fixtures_TestServiceSubscriberService() + protected function getTestServiceSubscriberService() { return $this->services['Symfony\Component\DependencyInjection\Tests\Fixtures\TestServiceSubscriber'] = new \Symfony\Component\DependencyInjection\Tests\Fixtures\TestServiceSubscriber(); } @@ -87,13 +87,13 @@ protected function getSymfony_Component_DependencyInjection_Tests_Fixtures_TestS protected function getFooServiceService() { return $this->services['foo_service'] = new \Symfony\Component\DependencyInjection\Tests\Fixtures\TestServiceSubscriber(new \Symfony\Component\DependencyInjection\ServiceLocator(array('Symfony\\Component\\DependencyInjection\\Tests\\Fixtures\\CustomDefinition' => function () { - $f = function (\Symfony\Component\DependencyInjection\Tests\Fixtures\CustomDefinition $v) { return $v; }; return $f(${($_ = isset($this->services['autowired.Symfony\Component\DependencyInjection\Tests\Fixtures\CustomDefinition']) ? $this->services['autowired.Symfony\Component\DependencyInjection\Tests\Fixtures\CustomDefinition'] : $this->getAutowired_Symfony_Component_DependencyInjection_Tests_Fixtures_CustomDefinitionService()) && false ?: '_'}); + $f = function (\Symfony\Component\DependencyInjection\Tests\Fixtures\CustomDefinition $v) { return $v; }; return $f(${($_ = isset($this->services['autowired.Symfony\Component\DependencyInjection\Tests\Fixtures\CustomDefinition']) ? $this->services['autowired.Symfony\Component\DependencyInjection\Tests\Fixtures\CustomDefinition'] : $this->getCustomDefinitionService()) && false ?: '_'}); }, 'Symfony\\Component\\DependencyInjection\\Tests\\Fixtures\\TestServiceSubscriber' => function () { $f = function (\Symfony\Component\DependencyInjection\Tests\Fixtures\TestServiceSubscriber $v) { return $v; }; return $f(${($_ = isset($this->services['Symfony\Component\DependencyInjection\Tests\Fixtures\TestServiceSubscriber']) ? $this->services['Symfony\Component\DependencyInjection\Tests\Fixtures\TestServiceSubscriber'] : $this->get('Symfony\Component\DependencyInjection\Tests\Fixtures\TestServiceSubscriber')) && false ?: '_'}); }, 'bar' => function () { $f = function (\Symfony\Component\DependencyInjection\Tests\Fixtures\CustomDefinition $v) { return $v; }; return $f(${($_ = isset($this->services['Symfony\Component\DependencyInjection\Tests\Fixtures\TestServiceSubscriber']) ? $this->services['Symfony\Component\DependencyInjection\Tests\Fixtures\TestServiceSubscriber'] : $this->get('Symfony\Component\DependencyInjection\Tests\Fixtures\TestServiceSubscriber')) && false ?: '_'}); }, 'baz' => function () { - $f = function (\Symfony\Component\DependencyInjection\Tests\Fixtures\CustomDefinition $v) { return $v; }; return $f(${($_ = isset($this->services['autowired.Symfony\Component\DependencyInjection\Tests\Fixtures\CustomDefinition']) ? $this->services['autowired.Symfony\Component\DependencyInjection\Tests\Fixtures\CustomDefinition'] : $this->getAutowired_Symfony_Component_DependencyInjection_Tests_Fixtures_CustomDefinitionService()) && false ?: '_'}); + $f = function (\Symfony\Component\DependencyInjection\Tests\Fixtures\CustomDefinition $v) { return $v; }; return $f(${($_ = isset($this->services['autowired.Symfony\Component\DependencyInjection\Tests\Fixtures\CustomDefinition']) ? $this->services['autowired.Symfony\Component\DependencyInjection\Tests\Fixtures\CustomDefinition'] : $this->getCustomDefinitionService()) && false ?: '_'}); }))); } @@ -102,7 +102,7 @@ protected function getFooServiceService() * * @return \Symfony\Component\DependencyInjection\Tests\Fixtures\CustomDefinition */ - protected function getAutowired_Symfony_Component_DependencyInjection_Tests_Fixtures_CustomDefinitionService() + protected function getCustomDefinitionService() { return $this->services['autowired.Symfony\Component\DependencyInjection\Tests\Fixtures\CustomDefinition'] = new \Symfony\Component\DependencyInjection\Tests\Fixtures\CustomDefinition(); } From 81396c7facd4d3806734f7402b6b8b6b9eca1df5 Mon Sep 17 00:00:00 2001 From: Yonel Ceruto Date: Tue, 1 Aug 2017 10:05:24 -0400 Subject: [PATCH 0558/1099] Removed useless argument $definition --- src/Symfony/Component/Form/DependencyInjection/FormPass.php | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Component/Form/DependencyInjection/FormPass.php b/src/Symfony/Component/Form/DependencyInjection/FormPass.php index 55e4cc1239b2f..88574558b7b7a 100644 --- a/src/Symfony/Component/Form/DependencyInjection/FormPass.php +++ b/src/Symfony/Component/Form/DependencyInjection/FormPass.php @@ -16,7 +16,6 @@ use Symfony\Component\DependencyInjection\Compiler\ServiceLocatorTagPass; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; -use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; use Symfony\Component\DependencyInjection\Reference; @@ -53,12 +52,12 @@ public function process(ContainerBuilder $container) if (new IteratorArgument(array()) != $definition->getArgument(2)) { return; } - $definition->replaceArgument(0, $this->processFormTypes($container, $definition)); + $definition->replaceArgument(0, $this->processFormTypes($container)); $definition->replaceArgument(1, $this->processFormTypeExtensions($container)); $definition->replaceArgument(2, $this->processFormTypeGuessers($container)); } - private function processFormTypes(ContainerBuilder $container, Definition $definition) + private function processFormTypes(ContainerBuilder $container) { // Get service locator argument $servicesMap = array(); From 969a20780e533ffe85f199171a4833ece264487b Mon Sep 17 00:00:00 2001 From: Guilhem Niot Date: Sat, 29 Jul 2017 15:29:10 +0200 Subject: [PATCH 0559/1099] [DependencyInjection] Deprecate autowiring service auto-registration --- UPGRADE-3.4.md | 58 ++++++++++++++++--- UPGRADE-4.0.md | 54 +++++++++++++++-- .../DependencyInjection/CHANGELOG.md | 1 + .../Compiler/AutowirePass.php | 2 + .../Tests/Compiler/AutowirePassTest.php | 15 +++++ .../Tests/Dumper/PhpDumperTest.php | 4 ++ .../Fixtures/php/services_subscriber.php | 16 ++--- 7 files changed, 130 insertions(+), 20 deletions(-) diff --git a/UPGRADE-3.4.md b/UPGRADE-3.4.md index 503e74922ce41..7530e8aca0381 100644 --- a/UPGRADE-3.4.md +++ b/UPGRADE-3.4.md @@ -4,6 +4,50 @@ UPGRADE FROM 3.3 to 3.4 DependencyInjection ------------------- + * Autowiring service auto-registration is deprecated and won't be supported + in Symfony 4.0. Explicitly inject your dependencies or create services + whose ids are their fully-qualified class name. + + Before: + + ```php + namespace App\Controller; + + use App\Mailer; + + class DefaultController + { + public function __construct(Mailer $mailer) { + // ... + } + + // ... + } + ``` + ```yml + services: + App\Controller\DefaultController: + autowire: true + ``` + + After: + + ```php + // same PHP code + ``` + ```yml + services: + App\Controller\DefaultController: + autowire: true + + # or + # App\Controller\DefaultController: + # arguments: { $mailer: "@App\Mailer" } + + App\Mailer: + autowire: true +  ``` + * Top-level anonymous services in XML are deprecated and will throw an exception in Symfony 4.0. Debug @@ -30,13 +74,13 @@ FrameworkBundle require symfony/stopwatch` in your `dev` environment. * Using the `KERNEL_DIR` environment variable or the automatic guessing based - on the `phpunit.xml` / `phpunit.xml.dist` file location is deprecated since 3.4. + on the `phpunit.xml` / `phpunit.xml.dist` file location is deprecated since 3.4. Set the `KERNEL_CLASS` environment variable to the fully-qualified class name - of your Kernel instead. Not setting the `KERNEL_CLASS` environment variable - will throw an exception on 4.0 unless you override the `KernelTestCase::createKernel()` + of your Kernel instead. Not setting the `KERNEL_CLASS` environment variable + will throw an exception on 4.0 unless you override the `KernelTestCase::createKernel()` or `KernelTestCase::getKernelClass()` method. - - * The `KernelTestCase::getPhpUnitXmlDir()` and `KernelTestCase::getPhpUnitCliConfigArgument()` + + * The `KernelTestCase::getPhpUnitXmlDir()` and `KernelTestCase::getPhpUnitCliConfigArgument()` methods are deprecated since 3.4 and will be removed in 4.0. * The `--no-prefix` option of the `translation:update` command is deprecated and @@ -83,7 +127,7 @@ TwigBridge * deprecated the `Symfony\Bridge\Twig\Form\TwigRenderer` class, use the `FormRenderer` class from the Form component instead - * deprecated `Symfony\Bridge\Twig\Command\DebugCommand::set/getTwigEnvironment` and the ability + * deprecated `Symfony\Bridge\Twig\Command\DebugCommand::set/getTwigEnvironment` and the ability to pass a command name as first argument * deprecated `Symfony\Bridge\Twig\Command\LintCommand::set/getTwigEnvironment` and the ability @@ -95,7 +139,7 @@ TwigBundle * deprecated the `Symfony\Bundle\TwigBundle\Command\DebugCommand` class, use the `DebugCommand` class from the Twig bridge instead - * deprecated relying on the `ContainerAwareInterface` implementation for + * deprecated relying on the `ContainerAwareInterface` implementation for `Symfony\Bundle\TwigBundle\Command\LintCommand` Validator diff --git a/UPGRADE-4.0.md b/UPGRADE-4.0.md index 5a8042835c2da..65f0619525af7 100644 --- a/UPGRADE-4.0.md +++ b/UPGRADE-4.0.md @@ -77,6 +77,50 @@ Debug DependencyInjection ------------------- + * Autowiring service auto-registration is not supported anymore. + Explicitly inject your dependencies or create services whose ids are + their fully-qualified class name. + + Before: + + ```php + namespace App\Controller; + + use App\Mailer; + + class DefaultController + { + public function __construct(Mailer $mailer) { + // ... + } + + // ... + } + ``` + ```yml + services: + App\Controller\DefaultController: + autowire: true + ``` + + After: + + ```php + // same PHP code + ``` + ```yml + services: + App\Controller\DefaultController: + autowire: true + + # or + # App\Controller\DefaultController: + # arguments: { $mailer: "@App\Mailer" } + + App\Mailer: + autowire: true +  ``` + * Autowiring services based on the types they implement is not supported anymore. Rename (or alias) your services to their FQCN id to make them autowirable. * `_defaults` and `_instanceof` are now reserved service names in Yaml configurations. Please rename any services with that names. @@ -338,9 +382,9 @@ FrameworkBundle class instead. * Using the `KERNEL_DIR` environment variable and the automatic guessing based - on the `phpunit.xml` file location have been removed from the `KernelTestCase::getKernelClass()` + on the `phpunit.xml` file location have been removed from the `KernelTestCase::getKernelClass()` method implementation. Set the `KERNEL_CLASS` environment variable to the - fully-qualified class name of your Kernel or override the `KernelTestCase::createKernel()` + fully-qualified class name of your Kernel or override the `KernelTestCase::createKernel()` or `KernelTestCase::getKernelClass()` method instead. * The `Symfony\Bundle\FrameworkBundle\Validator\ConstraintValidatorFactory` class has been removed. @@ -349,10 +393,10 @@ FrameworkBundle * The `--no-prefix` option of the `translation:update` command has been removed. - * The `Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\AddCacheClearerPass` class has been removed. + * The `Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\AddCacheClearerPass` class has been removed. Use the `Symfony\Component\HttpKernel\DependencyInjection\AddCacheClearerPass` class instead. - * The `Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\AddCacheWarmerPass` class has been removed. + * The `Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\AddCacheWarmerPass` class has been removed. Use the `Symfony\Component\HttpKernel\DependencyInjection\AddCacheWarmerPass` class instead. * The `Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\TranslationDumperPass` @@ -554,7 +598,7 @@ TwigBridge * The `TwigRendererEngine::setEnvironment()` method has been removed. Pass the Twig Environment as second argument of the constructor instead. - * Removed `Symfony\Bridge\Twig\Command\DebugCommand::set/getTwigEnvironment` and the ability + * Removed `Symfony\Bridge\Twig\Command\DebugCommand::set/getTwigEnvironment` and the ability to pass a command name as first argument. * Removed `Symfony\Bridge\Twig\Command\LintCommand::set/getTwigEnvironment` and the ability diff --git a/src/Symfony/Component/DependencyInjection/CHANGELOG.md b/src/Symfony/Component/DependencyInjection/CHANGELOG.md index 3037dad65cc5d..1ae4818cd42bc 100644 --- a/src/Symfony/Component/DependencyInjection/CHANGELOG.md +++ b/src/Symfony/Component/DependencyInjection/CHANGELOG.md @@ -4,6 +4,7 @@ CHANGELOG 3.4.0 ----- + * deprecated autowiring service auto-registration * deprecated the ability to check for the initialization of a private service with the `Container::initialized()` method * deprecated support for top-level anonymous services in XML diff --git a/src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php b/src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php index a59444fcac375..4e93e92aa666b 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php @@ -477,6 +477,8 @@ private function createAutowiredDefinition($type) $this->currentId = $currentId; } + @trigger_error(sprintf('Using autowiring service auto-registration for type "%s" is deprecated since version 3.4 and won\'t be supported in 4.0. Create a service named "%s" instead.', $type, $type), E_USER_DEPRECATED); + $this->container->log($this, sprintf('Type "%s" has been auto-registered for service "%s".', $type, $this->currentId)); return new TypedReference($argumentId, $type); diff --git a/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowirePassTest.php b/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowirePassTest.php index 757db3f229c95..adf83b1dbb6f3 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowirePassTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowirePassTest.php @@ -287,6 +287,11 @@ public function testWithTypeSet() $this->assertEquals(CollisionInterface::class, (string) $container->getDefinition('a')->getArgument(0)); } + /** + * @group legacy + * @expectedDeprecation Using autowiring service auto-registration for type "Symfony\Component\DependencyInjection\Tests\Compiler\Lille" is deprecated since version 3.4 and won't be supported in 4.0. Create a service named "Symfony\Component\DependencyInjection\Tests\Compiler\Lille" instead. + * @expectedDeprecation Using autowiring service auto-registration for type "Symfony\Component\DependencyInjection\Tests\Compiler\Dunglas" is deprecated since version 3.4 and won't be supported in 4.0. Create a service named "Symfony\Component\DependencyInjection\Tests\Compiler\Dunglas" instead. + */ public function testCreateDefinition() { $container = new ContainerBuilder(); @@ -368,6 +373,8 @@ public function testClassNotFoundThrowsException() $aDefinition = $container->register('a', __NAMESPACE__.'\BadTypeHintedArgument'); $aDefinition->setAutowired(true); + $container->register(Dunglas::class, Dunglas::class); + $pass = new AutowirePass(); $pass->process($container); } @@ -383,6 +390,8 @@ public function testParentClassNotFoundThrowsException() $aDefinition = $container->register('a', __NAMESPACE__.'\BadParentTypeHintedArgument'); $aDefinition->setAutowired(true); + $container->register(Dunglas::class, Dunglas::class); + $pass = new AutowirePass(); $pass->process($container); } @@ -595,6 +604,10 @@ public function testExplicitMethodInjection() ); } + /** + * @group legacy + * @expectedDeprecation Using autowiring service auto-registration for type "Symfony\Component\DependencyInjection\Tests\Compiler\A" is deprecated since version 3.4 and won't be supported in 4.0. Create a service named "Symfony\Component\DependencyInjection\Tests\Compiler\A" instead. + */ public function testTypedReference() { $container = new ContainerBuilder(); @@ -653,6 +666,8 @@ public function testIgnoreServiceWithClassNotExisting() $barDefinition = $container->register('bar', __NAMESPACE__.'\Bar'); $barDefinition->setAutowired(true); + $container->register(Foo::class, Foo::class); + $pass = new AutowirePass(); $pass->process($container); diff --git a/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php b/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php index 6e7889725ec02..4afb445c68ca8 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php @@ -28,6 +28,7 @@ use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\DependencyInjection\Loader\YamlFileLoader; use Symfony\Component\DependencyInjection\ServiceLocator; +use Symfony\Component\DependencyInjection\Tests\Fixtures\CustomDefinition; use Symfony\Component\DependencyInjection\Tests\Fixtures\TestServiceSubscriber; use Symfony\Component\DependencyInjection\Variable; use Symfony\Component\ExpressionLanguage\Expression; @@ -560,6 +561,9 @@ public function testServiceSubscriber() )) ; $container->register(TestServiceSubscriber::class, TestServiceSubscriber::class); + + $container->register(CustomDefinition::class, CustomDefinition::class) + ->setPublic(false); $container->compile(); $dumper = new PhpDumper($container); diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_subscriber.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_subscriber.php index 01c385358b136..4e45a4fe64628 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_subscriber.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_subscriber.php @@ -28,16 +28,16 @@ public function __construct() { $this->services = array(); $this->normalizedIds = array( - 'autowired.symfony\\component\\dependencyinjection\\tests\\fixtures\\customdefinition' => 'autowired.Symfony\\Component\\DependencyInjection\\Tests\\Fixtures\\CustomDefinition', + 'symfony\\component\\dependencyinjection\\tests\\fixtures\\customdefinition' => 'Symfony\\Component\\DependencyInjection\\Tests\\Fixtures\\CustomDefinition', 'symfony\\component\\dependencyinjection\\tests\\fixtures\\testservicesubscriber' => 'Symfony\\Component\\DependencyInjection\\Tests\\Fixtures\\TestServiceSubscriber', ); $this->methodMap = array( + 'Symfony\\Component\\DependencyInjection\\Tests\\Fixtures\\CustomDefinition' => 'getSymfony_Component_DependencyInjection_Tests_Fixtures_CustomDefinitionService', 'Symfony\\Component\\DependencyInjection\\Tests\\Fixtures\\TestServiceSubscriber' => 'getSymfony_Component_DependencyInjection_Tests_Fixtures_TestServiceSubscriberService', - 'autowired.Symfony\\Component\\DependencyInjection\\Tests\\Fixtures\\CustomDefinition' => 'getAutowired_Symfony_Component_DependencyInjection_Tests_Fixtures_CustomDefinitionService', 'foo_service' => 'getFooServiceService', ); $this->privates = array( - 'autowired.Symfony\\Component\\DependencyInjection\\Tests\\Fixtures\\CustomDefinition' => true, + 'Symfony\\Component\\DependencyInjection\\Tests\\Fixtures\\CustomDefinition' => true, ); $this->aliases = array(); @@ -87,23 +87,23 @@ protected function getSymfony_Component_DependencyInjection_Tests_Fixtures_TestS protected function getFooServiceService() { return $this->services['foo_service'] = new \Symfony\Component\DependencyInjection\Tests\Fixtures\TestServiceSubscriber(new \Symfony\Component\DependencyInjection\ServiceLocator(array('Symfony\\Component\\DependencyInjection\\Tests\\Fixtures\\CustomDefinition' => function () { - $f = function (\Symfony\Component\DependencyInjection\Tests\Fixtures\CustomDefinition $v) { return $v; }; return $f(${($_ = isset($this->services['autowired.Symfony\Component\DependencyInjection\Tests\Fixtures\CustomDefinition']) ? $this->services['autowired.Symfony\Component\DependencyInjection\Tests\Fixtures\CustomDefinition'] : $this->getAutowired_Symfony_Component_DependencyInjection_Tests_Fixtures_CustomDefinitionService()) && false ?: '_'}); + $f = function (\Symfony\Component\DependencyInjection\Tests\Fixtures\CustomDefinition $v = null) { return $v; }; return $f(${($_ = isset($this->services['Symfony\Component\DependencyInjection\Tests\Fixtures\CustomDefinition']) ? $this->services['Symfony\Component\DependencyInjection\Tests\Fixtures\CustomDefinition'] : $this->getSymfony_Component_DependencyInjection_Tests_Fixtures_CustomDefinitionService()) && false ?: '_'}); }, 'Symfony\\Component\\DependencyInjection\\Tests\\Fixtures\\TestServiceSubscriber' => function () { $f = function (\Symfony\Component\DependencyInjection\Tests\Fixtures\TestServiceSubscriber $v) { return $v; }; return $f(${($_ = isset($this->services['Symfony\Component\DependencyInjection\Tests\Fixtures\TestServiceSubscriber']) ? $this->services['Symfony\Component\DependencyInjection\Tests\Fixtures\TestServiceSubscriber'] : $this->get('Symfony\Component\DependencyInjection\Tests\Fixtures\TestServiceSubscriber')) && false ?: '_'}); }, 'bar' => function () { $f = function (\Symfony\Component\DependencyInjection\Tests\Fixtures\CustomDefinition $v) { return $v; }; return $f(${($_ = isset($this->services['Symfony\Component\DependencyInjection\Tests\Fixtures\TestServiceSubscriber']) ? $this->services['Symfony\Component\DependencyInjection\Tests\Fixtures\TestServiceSubscriber'] : $this->get('Symfony\Component\DependencyInjection\Tests\Fixtures\TestServiceSubscriber')) && false ?: '_'}); }, 'baz' => function () { - $f = function (\Symfony\Component\DependencyInjection\Tests\Fixtures\CustomDefinition $v) { return $v; }; return $f(${($_ = isset($this->services['autowired.Symfony\Component\DependencyInjection\Tests\Fixtures\CustomDefinition']) ? $this->services['autowired.Symfony\Component\DependencyInjection\Tests\Fixtures\CustomDefinition'] : $this->getAutowired_Symfony_Component_DependencyInjection_Tests_Fixtures_CustomDefinitionService()) && false ?: '_'}); + $f = function (\Symfony\Component\DependencyInjection\Tests\Fixtures\CustomDefinition $v = null) { return $v; }; return $f(${($_ = isset($this->services['Symfony\Component\DependencyInjection\Tests\Fixtures\CustomDefinition']) ? $this->services['Symfony\Component\DependencyInjection\Tests\Fixtures\CustomDefinition'] : $this->getSymfony_Component_DependencyInjection_Tests_Fixtures_CustomDefinitionService()) && false ?: '_'}); }))); } /** - * Gets the private 'autowired.Symfony\Component\DependencyInjection\Tests\Fixtures\CustomDefinition' shared autowired service. + * Gets the private 'Symfony\Component\DependencyInjection\Tests\Fixtures\CustomDefinition' shared service. * * @return \Symfony\Component\DependencyInjection\Tests\Fixtures\CustomDefinition */ - protected function getAutowired_Symfony_Component_DependencyInjection_Tests_Fixtures_CustomDefinitionService() + protected function getSymfony_Component_DependencyInjection_Tests_Fixtures_CustomDefinitionService() { - return $this->services['autowired.Symfony\Component\DependencyInjection\Tests\Fixtures\CustomDefinition'] = new \Symfony\Component\DependencyInjection\Tests\Fixtures\CustomDefinition(); + return $this->services['Symfony\Component\DependencyInjection\Tests\Fixtures\CustomDefinition'] = new \Symfony\Component\DependencyInjection\Tests\Fixtures\CustomDefinition(); } } From b63c55c72c19b3a822880002b44ff8c4cad063e8 Mon Sep 17 00:00:00 2001 From: Guilhem Niot Date: Mon, 29 May 2017 22:10:45 +0200 Subject: [PATCH 0560/1099] [Yaml] Recommend using quotes instead of PARSE_KEYS_AS_STRINGS --- UPGRADE-3.4.md | 41 ++++++++++++--- UPGRADE-4.0.md | 36 +++++++++++-- .../Loader/YamlFileLoader.php | 2 +- .../Routing/Loader/YamlFileLoader.php | 3 +- .../Mapping/Loader/YamlFileLoader.php | 3 +- .../Translation/Loader/YamlFileLoader.php | 3 +- .../Mapping/Loader/YamlFileLoader.php | 2 +- src/Symfony/Component/Yaml/Inline.php | 2 +- src/Symfony/Component/Yaml/Parser.php | 6 ++- .../Component/Yaml/Tests/DumperTest.php | 2 +- .../Component/Yaml/Tests/InlineTest.php | 17 +++--- .../Component/Yaml/Tests/ParserTest.php | 52 ++++++++----------- src/Symfony/Component/Yaml/Yaml.php | 4 ++ 13 files changed, 114 insertions(+), 59 deletions(-) diff --git a/UPGRADE-3.4.md b/UPGRADE-3.4.md index 503e74922ce41..68b21db3e2ad2 100644 --- a/UPGRADE-3.4.md +++ b/UPGRADE-3.4.md @@ -30,13 +30,13 @@ FrameworkBundle require symfony/stopwatch` in your `dev` environment. * Using the `KERNEL_DIR` environment variable or the automatic guessing based - on the `phpunit.xml` / `phpunit.xml.dist` file location is deprecated since 3.4. + on the `phpunit.xml` / `phpunit.xml.dist` file location is deprecated since 3.4. Set the `KERNEL_CLASS` environment variable to the fully-qualified class name - of your Kernel instead. Not setting the `KERNEL_CLASS` environment variable - will throw an exception on 4.0 unless you override the `KernelTestCase::createKernel()` + of your Kernel instead. Not setting the `KERNEL_CLASS` environment variable + will throw an exception on 4.0 unless you override the `KernelTestCase::createKernel()` or `KernelTestCase::getKernelClass()` method. - - * The `KernelTestCase::getPhpUnitXmlDir()` and `KernelTestCase::getPhpUnitCliConfigArgument()` + + * The `KernelTestCase::getPhpUnitXmlDir()` and `KernelTestCase::getPhpUnitCliConfigArgument()` methods are deprecated since 3.4 and will be removed in 4.0. * The `--no-prefix` option of the `translation:update` command is deprecated and @@ -83,7 +83,7 @@ TwigBridge * deprecated the `Symfony\Bridge\Twig\Form\TwigRenderer` class, use the `FormRenderer` class from the Form component instead - * deprecated `Symfony\Bridge\Twig\Command\DebugCommand::set/getTwigEnvironment` and the ability + * deprecated `Symfony\Bridge\Twig\Command\DebugCommand::set/getTwigEnvironment` and the ability to pass a command name as first argument * deprecated `Symfony\Bridge\Twig\Command\LintCommand::set/getTwigEnvironment` and the ability @@ -95,7 +95,7 @@ TwigBundle * deprecated the `Symfony\Bundle\TwigBundle\Command\DebugCommand` class, use the `DebugCommand` class from the Twig bridge instead - * deprecated relying on the `ContainerAwareInterface` implementation for + * deprecated relying on the `ContainerAwareInterface` implementation for `Symfony\Bundle\TwigBundle\Command\LintCommand` Validator @@ -111,3 +111,30 @@ Yaml * Using the non-specific tag `!` is deprecated and will have a different behavior in 4.0. Use a plain integer or `!!float` instead. + + * Using the `Yaml::PARSE_KEYS_AS_STRINGS` flag is deprecated as it will be + removed in 4.0. + + Before: + + ```php + $yaml = <<yamlParser->parse(file_get_contents($file), Yaml::PARSE_CONSTANT | Yaml::PARSE_CUSTOM_TAGS | Yaml::PARSE_KEYS_AS_STRINGS); + $configuration = $this->yamlParser->parse(file_get_contents($file), Yaml::PARSE_CONSTANT | Yaml::PARSE_CUSTOM_TAGS); } catch (ParseException $e) { throw new InvalidArgumentException(sprintf('The file "%s" does not contain valid YAML.', $file), 0, $e); } diff --git a/src/Symfony/Component/Routing/Loader/YamlFileLoader.php b/src/Symfony/Component/Routing/Loader/YamlFileLoader.php index 7ae5e84d109aa..31314011b95b4 100644 --- a/src/Symfony/Component/Routing/Loader/YamlFileLoader.php +++ b/src/Symfony/Component/Routing/Loader/YamlFileLoader.php @@ -17,7 +17,6 @@ use Symfony\Component\Yaml\Exception\ParseException; use Symfony\Component\Yaml\Parser as YamlParser; use Symfony\Component\Config\Loader\FileLoader; -use Symfony\Component\Yaml\Yaml; /** * YamlFileLoader loads Yaml routing files. @@ -59,7 +58,7 @@ public function load($file, $type = null) } try { - $parsedConfig = $this->yamlParser->parse(file_get_contents($path), Yaml::PARSE_KEYS_AS_STRINGS); + $parsedConfig = $this->yamlParser->parse(file_get_contents($path)); } catch (ParseException $e) { throw new \InvalidArgumentException(sprintf('The file "%s" does not contain valid YAML.', $path), 0, $e); } diff --git a/src/Symfony/Component/Serializer/Mapping/Loader/YamlFileLoader.php b/src/Symfony/Component/Serializer/Mapping/Loader/YamlFileLoader.php index 20a1d48aade65..e3afa4763271e 100644 --- a/src/Symfony/Component/Serializer/Mapping/Loader/YamlFileLoader.php +++ b/src/Symfony/Component/Serializer/Mapping/Loader/YamlFileLoader.php @@ -15,7 +15,6 @@ use Symfony\Component\Serializer\Mapping\AttributeMetadata; use Symfony\Component\Serializer\Mapping\ClassMetadataInterface; use Symfony\Component\Yaml\Parser; -use Symfony\Component\Yaml\Yaml; /** * YAML File Loader. @@ -114,7 +113,7 @@ private function getClassesFromYaml() $this->yamlParser = new Parser(); } - $classes = $this->yamlParser->parse(file_get_contents($this->file), Yaml::PARSE_KEYS_AS_STRINGS); + $classes = $this->yamlParser->parse(file_get_contents($this->file)); if (empty($classes)) { return array(); diff --git a/src/Symfony/Component/Translation/Loader/YamlFileLoader.php b/src/Symfony/Component/Translation/Loader/YamlFileLoader.php index 5897767b6bf03..41e390d0e967d 100644 --- a/src/Symfony/Component/Translation/Loader/YamlFileLoader.php +++ b/src/Symfony/Component/Translation/Loader/YamlFileLoader.php @@ -15,7 +15,6 @@ use Symfony\Component\Translation\Exception\LogicException; use Symfony\Component\Yaml\Parser as YamlParser; use Symfony\Component\Yaml\Exception\ParseException; -use Symfony\Component\Yaml\Yaml; /** * YamlFileLoader loads translations from Yaml files. @@ -40,7 +39,7 @@ protected function loadResource($resource) } try { - $messages = $this->yamlParser->parse(file_get_contents($resource), Yaml::PARSE_KEYS_AS_STRINGS); + $messages = $this->yamlParser->parse(file_get_contents($resource)); } catch (ParseException $e) { throw new InvalidResourceException(sprintf('Error parsing YAML, invalid file "%s"', $resource), 0, $e); } diff --git a/src/Symfony/Component/Validator/Mapping/Loader/YamlFileLoader.php b/src/Symfony/Component/Validator/Mapping/Loader/YamlFileLoader.php index f1727d370498d..ff6c65d05e763 100644 --- a/src/Symfony/Component/Validator/Mapping/Loader/YamlFileLoader.php +++ b/src/Symfony/Component/Validator/Mapping/Loader/YamlFileLoader.php @@ -116,7 +116,7 @@ protected function parseNodes(array $nodes) private function parseFile($path) { try { - $classes = $this->yamlParser->parse(file_get_contents($path), Yaml::PARSE_KEYS_AS_STRINGS | Yaml::PARSE_CONSTANT); + $classes = $this->yamlParser->parse(file_get_contents($path), Yaml::PARSE_CONSTANT); } catch (ParseException $e) { throw new \InvalidArgumentException(sprintf('The file "%s" does not contain valid YAML.', $path), 0, $e); } diff --git a/src/Symfony/Component/Yaml/Inline.php b/src/Symfony/Component/Yaml/Inline.php index 6a911e9090158..ef14528a46511 100644 --- a/src/Symfony/Component/Yaml/Inline.php +++ b/src/Symfony/Component/Yaml/Inline.php @@ -490,7 +490,7 @@ private static function parseMapping($mapping, $flags, &$i = 0, $references = ar @trigger_error('Omitting the key of a mapping is deprecated and will throw a ParseException in 4.0.', E_USER_DEPRECATED); } - if (!(Yaml::PARSE_KEYS_AS_STRINGS & $flags)) { + if (!$isKeyQuoted) { $evaluatedKey = self::evaluateScalar($key, $flags, $references); if ('' !== $key && $evaluatedKey !== $key && !is_string($evaluatedKey) && !is_int($evaluatedKey)) { diff --git a/src/Symfony/Component/Yaml/Parser.php b/src/Symfony/Component/Yaml/Parser.php index 82db443e0583b..8bb19fbb06889 100644 --- a/src/Symfony/Component/Yaml/Parser.php +++ b/src/Symfony/Component/Yaml/Parser.php @@ -86,6 +86,10 @@ public function parse($value, $flags = 0) } } + if (Yaml::PARSE_KEYS_AS_STRINGS & $flags) { + @trigger_error('Using the Yaml::PARSE_KEYS_AS_STRINGS flag is deprecated since version 3.4 as it will be removed in 4.0. Quote your keys when they are evaluable instead.', E_USER_DEPRECATED); + } + if (false === preg_match('//u', $value)) { throw new ParseException('The YAML value does not appear to be valid UTF-8.'); } @@ -236,7 +240,7 @@ private function doParse($value, $flags) throw $e; } - if (!(Yaml::PARSE_KEYS_AS_STRINGS & $flags) && !is_string($key) && !is_int($key)) { + if (!is_string($key) && !is_int($key)) { $keyType = is_numeric($key) ? 'numeric key' : 'non-string key'; @trigger_error(sprintf('Implicit casting of %s to string is deprecated since version 3.3 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0. Quote your evaluable mapping keys instead.', $keyType), E_USER_DEPRECATED); } diff --git a/src/Symfony/Component/Yaml/Tests/DumperTest.php b/src/Symfony/Component/Yaml/Tests/DumperTest.php index 1c80bec6506c2..329cfbe3a6839 100644 --- a/src/Symfony/Component/Yaml/Tests/DumperTest.php +++ b/src/Symfony/Component/Yaml/Tests/DumperTest.php @@ -125,7 +125,7 @@ public function testSpecifications() // TODO } else { eval('$expected = '.trim($test['php']).';'); - $this->assertSame($expected, $this->parser->parse($this->dumper->dump($expected, 10), Yaml::PARSE_KEYS_AS_STRINGS), $test['test']); + $this->assertSame($expected, $this->parser->parse($this->dumper->dump($expected, 10)), $test['test']); } } } diff --git a/src/Symfony/Component/Yaml/Tests/InlineTest.php b/src/Symfony/Component/Yaml/Tests/InlineTest.php index b48263f8cd6ac..3448113021688 100644 --- a/src/Symfony/Component/Yaml/Tests/InlineTest.php +++ b/src/Symfony/Component/Yaml/Tests/InlineTest.php @@ -385,8 +385,8 @@ public function getTestsForParse() array('[\'foo,bar\', \'foo bar\']', array('foo,bar', 'foo bar')), // mappings - array('{foo: bar,bar: foo,false: false,null: null,integer: 12}', array('foo' => 'bar', 'bar' => 'foo', 'false' => false, 'null' => null, 'integer' => 12), Yaml::PARSE_KEYS_AS_STRINGS), - array('{ foo : bar, bar : foo, false : false, null : null, integer : 12 }', array('foo' => 'bar', 'bar' => 'foo', 'false' => false, 'null' => null, 'integer' => 12), Yaml::PARSE_KEYS_AS_STRINGS), + array('{foo: bar,bar: foo,"false": false, "null": null,integer: 12}', array('foo' => 'bar', 'bar' => 'foo', 'false' => false, 'null' => null, 'integer' => 12)), + array('{ foo : bar, bar : foo, "false" : false, "null" : null, integer : 12 }', array('foo' => 'bar', 'bar' => 'foo', 'false' => false, 'null' => null, 'integer' => 12)), array('{foo: \'bar\', bar: \'foo: bar\'}', array('foo' => 'bar', 'bar' => 'foo: bar')), array('{\'foo\': \'bar\', "bar": \'foo: bar\'}', array('foo' => 'bar', 'bar' => 'foo: bar')), array('{\'foo\'\'\': \'bar\', "bar\"": \'foo: bar\'}', array('foo\'' => 'bar', 'bar"' => 'foo: bar')), @@ -456,8 +456,8 @@ public function getTestsForParseWithMapObjects() array('[\'foo,bar\', \'foo bar\']', array('foo,bar', 'foo bar')), // mappings - array('{foo: bar,bar: foo,false: false,null: null,integer: 12}', (object) array('foo' => 'bar', 'bar' => 'foo', 'false' => false, 'null' => null, 'integer' => 12), Yaml::PARSE_OBJECT_FOR_MAP | Yaml::PARSE_KEYS_AS_STRINGS), - array('{ foo : bar, bar : foo, false : false, null : null, integer : 12 }', (object) array('foo' => 'bar', 'bar' => 'foo', 'false' => false, 'null' => null, 'integer' => 12), Yaml::PARSE_OBJECT_FOR_MAP | Yaml::PARSE_KEYS_AS_STRINGS), + array('{foo: bar,bar: foo,"false": false,"null": null,integer: 12}', (object) array('foo' => 'bar', 'bar' => 'foo', 'false' => false, 'null' => null, 'integer' => 12), Yaml::PARSE_OBJECT_FOR_MAP), + array('{ foo : bar, bar : foo, "false" : false, "null" : null, integer : 12 }', (object) array('foo' => 'bar', 'bar' => 'foo', 'false' => false, 'null' => null, 'integer' => 12), Yaml::PARSE_OBJECT_FOR_MAP), array('{foo: \'bar\', bar: \'foo: bar\'}', (object) array('foo' => 'bar', 'bar' => 'foo: bar')), array('{\'foo\': \'bar\', "bar": \'foo: bar\'}', (object) array('foo' => 'bar', 'bar' => 'foo: bar')), array('{\'foo\'\'\': \'bar\', "bar\"": \'foo: bar\'}', (object) array('foo\'' => 'bar', 'bar"' => 'foo: bar')), @@ -538,7 +538,7 @@ public function getTestsForDump() array('[\'foo,bar\', \'foo bar\']', array('foo,bar', 'foo bar')), // mappings - array('{ foo: bar, bar: foo, \'false\': false, \'null\': null, integer: 12 }', array('foo' => 'bar', 'bar' => 'foo', 'false' => false, 'null' => null, 'integer' => 12), Yaml::PARSE_KEYS_AS_STRINGS), + array('{ foo: bar, bar: foo, \'false\': false, \'null\': null, integer: 12 }', array('foo' => 'bar', 'bar' => 'foo', 'false' => false, 'null' => null, 'integer' => 12)), array('{ foo: bar, bar: \'foo: bar\' }', array('foo' => 'bar', 'bar' => 'foo: bar')), // nested sequences and mappings @@ -554,7 +554,7 @@ public function getTestsForDump() array('[foo, \'@foo.baz\', { \'%foo%\': \'foo is %foo%\', bar: \'%foo%\' }, true, \'@service_container\']', array('foo', '@foo.baz', array('%foo%' => 'foo is %foo%', 'bar' => '%foo%'), true, '@service_container')), - array('{ foo: { bar: { 1: 2, baz: 3 } } }', array('foo' => array('bar' => array(1 => 2, 'baz' => 3))), Yaml::PARSE_KEYS_AS_STRINGS), + array('{ foo: { bar: { 1: 2, baz: 3 } } }', array('foo' => array('bar' => array(1 => 2, 'baz' => 3)))), ); } @@ -739,11 +739,14 @@ public function testImplicitStringCastingOfMappingKeysIsDeprecated($yaml, $expec } /** + * @group legacy + * @expectedDeprecation Using the Yaml::PARSE_KEYS_AS_STRINGS flag is deprecated since version 3.4 as it will be removed in 4.0. Quote your keys when they are evaluable instead. + * @expectedDeprecation Implicit casting of incompatible mapping keys to strings is deprecated since version 3.3 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0. Quote your evaluable mapping keys instead. * @dataProvider getNotPhpCompatibleMappingKeyData */ public function testExplicitStringCastingOfMappingKeys($yaml, $expected) { - $this->assertSame($expected, Inline::parse($yaml, Yaml::PARSE_KEYS_AS_STRINGS)); + $this->assertSame($expected, Yaml::parse($yaml, Yaml::PARSE_KEYS_AS_STRINGS)); } public function getNotPhpCompatibleMappingKeyData() diff --git a/src/Symfony/Component/Yaml/Tests/ParserTest.php b/src/Symfony/Component/Yaml/Tests/ParserTest.php index b75fd1b324b73..1baa79bc359b0 100644 --- a/src/Symfony/Component/Yaml/Tests/ParserTest.php +++ b/src/Symfony/Component/Yaml/Tests/ParserTest.php @@ -71,6 +71,8 @@ public function getDataFormSpecifications() } /** + * @group legacy + * @expectedDeprecationMessage Using the Yaml::PARSE_KEYS_AS_STRINGS flag is deprecated since version 3.4 as it will be removed in 4.0. Quote your keys when they are evaluable * @dataProvider getNonStringMappingKeysData */ public function testNonStringMappingKeys($expected, $yaml, $comment) @@ -510,14 +512,10 @@ public function testObjectSupportDisabledButNoExceptions($input) /** * @dataProvider getObjectForMapTests */ - public function testObjectForMap($yaml, $expected, $explicitlyParseKeysAsStrings = false) + public function testObjectForMap($yaml, $expected) { $flags = Yaml::PARSE_OBJECT_FOR_MAP; - if ($explicitlyParseKeysAsStrings) { - $flags |= Yaml::PARSE_KEYS_AS_STRINGS; - } - $this->assertEquals($expected, $this->parser->parse($yaml, $flags)); } @@ -577,18 +575,18 @@ public function getObjectForMapTests() $expected->map = new \stdClass(); $expected->map->{1} = 'one'; $expected->map->{2} = 'two'; - $tests['numeric-keys'] = array($yaml, $expected, true); + $tests['numeric-keys'] = array($yaml, $expected); $yaml = <<<'YAML' map: - 0: one - 1: two + '0': one + '1': two YAML; $expected = new \stdClass(); $expected->map = new \stdClass(); $expected->map->{0} = 'one'; $expected->map->{1} = 'two'; - $tests['zero-indexed-numeric-keys'] = array($yaml, $expected, true); + $tests['zero-indexed-numeric-keys'] = array($yaml, $expected); return $tests; } @@ -1120,37 +1118,29 @@ public function testBooleanKeys() $this->assertEquals($expected, $this->parser->parse($yaml)); } - public function testExplicitStringCastingOfFloatKeys() + public function testExplicitStringCasting() { $yaml = <<<'EOF' -foo: - 1.2: "bar" - 1.3: "baz" -EOF; +'1.2': "bar" +!!str 1.3: "baz" - $expected = array( - 'foo' => array( - '1.2' => 'bar', - '1.3' => 'baz', - ), - ); - - $this->assertEquals($expected, $this->parser->parse($yaml, Yaml::PARSE_KEYS_AS_STRINGS)); - } +'true': foo +!!str false: bar - public function testExplicitStringCastingOfBooleanKeys() - { - $yaml = <<<'EOF' -true: foo -false: bar +!!str null: 'null' +'~': 'null' EOF; $expected = array( + '1.2' => 'bar', + '1.3' => 'baz', 'true' => 'foo', 'false' => 'bar', + 'null' => 'null', + '~' => 'null', ); - $this->assertEquals($expected, $this->parser->parse($yaml, Yaml::PARSE_KEYS_AS_STRINGS)); + $this->assertEquals($expected, $this->parser->parse($yaml)); } /** @@ -1843,6 +1833,10 @@ public function testPhpConstantTagMappingKey() $this->assertSame($expected, $this->parser->parse($yaml, Yaml::PARSE_CONSTANT)); } + /** + * @group legacy + * @expectedDeprecation Using the Yaml::PARSE_KEYS_AS_STRINGS flag is deprecated since version 3.4 as it will be removed in 4.0. Quote your keys when they are evaluable instead. + */ public function testPhpConstantTagMappingKeyWithKeysCastToStrings() { $yaml = << Date: Thu, 3 Aug 2017 12:36:17 +0200 Subject: [PATCH 0561/1099] fix merge --- src/Symfony/Component/Console/composer.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/Console/composer.json b/src/Symfony/Component/Console/composer.json index f32fd949d811f..9ee609a98aed1 100644 --- a/src/Symfony/Component/Console/composer.json +++ b/src/Symfony/Component/Console/composer.json @@ -25,13 +25,13 @@ "symfony/http-kernel": "~3.4|~4.0", "symfony/event-dispatcher": "~3.4|~4.0", "symfony/dependency-injection": "~3.4|~4.0", - "symfony/filesystem": "~3.4|~4.0", + "symfony/lock": "~3.4|~4.0", "symfony/process": "~3.4|~4.0", "psr/log": "~1.0" }, "suggest": { "symfony/event-dispatcher": "", - "symfony/filesystem": "", + "symfony/lock": "", "symfony/process": "", "psr/log": "For using the console logger" }, From bc22cdd034f9b3653469ce42ddf49093ef17be57 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Wed, 2 Aug 2017 14:30:55 +0200 Subject: [PATCH 0562/1099] Consistently use 7 chars of sha256 for hash-based id generation --- .../AbstractDoctrineExtension.php | 3 +-- src/Symfony/Bridge/Doctrine/composer.json | 4 ++-- .../DependencyInjection/Compiler/CachePoolPass.php | 2 +- .../DependencyInjection/FrameworkExtensionTest.php | 4 ++-- src/Symfony/Bundle/FrameworkBundle/composer.json | 2 +- .../DependencyInjection/SecurityExtension.php | 5 ++--- .../CompleteConfigurationTest.php | 4 ++-- src/Symfony/Bundle/SecurityBundle/composer.json | 6 +++--- .../Compiler/ServiceLocatorTagPass.php | 4 ++-- .../DependencyInjection/ContainerBuilder.php | 14 ++++++++++++++ .../DependencyInjection/Loader/XmlFileLoader.php | 6 ++++-- .../DependencyInjection/Loader/YamlFileLoader.php | 5 ++++- .../Tests/Loader/YamlFileLoaderTest.php | 4 ++-- .../Component/DomCrawler/Field/FileFormField.php | 2 +- .../HttpFoundation/BinaryFileResponse.php | 2 +- src/Symfony/Component/HttpKernel/Kernel.php | 2 +- src/Symfony/Component/Lock/Store/FlockStore.php | 2 +- .../Component/Lock/Tests/Store/FlockStoreTest.php | 5 +++-- .../Translation/Dumper/XliffFileDumper.php | 4 ++-- .../Translation/Tests/Dumper/FileDumperTest.php | 2 ++ .../Tests/fixtures/resources-2.0-clean.xlf | 6 +++--- .../Translation/Tests/fixtures/resources-clean.xlf | 6 +++--- .../Tests/fixtures/resources-target-attributes.xlf | 2 +- .../Tests/fixtures/resources-tool-info.xlf | 2 +- src/Symfony/Component/Translation/Translator.php | 2 +- 25 files changed, 60 insertions(+), 40 deletions(-) diff --git a/src/Symfony/Bridge/Doctrine/DependencyInjection/AbstractDoctrineExtension.php b/src/Symfony/Bridge/Doctrine/DependencyInjection/AbstractDoctrineExtension.php index 37875b53b570a..67015602306ca 100644 --- a/src/Symfony/Bridge/Doctrine/DependencyInjection/AbstractDoctrineExtension.php +++ b/src/Symfony/Bridge/Doctrine/DependencyInjection/AbstractDoctrineExtension.php @@ -387,8 +387,7 @@ protected function loadCacheDriver($cacheName, $objectManagerName, array $cacheD $seed = '_'.$container->getParameter('kernel.root_dir'); } $seed .= '.'.$container->getParameter('kernel.name').'.'.$container->getParameter('kernel.environment').'.'.$container->getParameter('kernel.debug'); - $hash = hash('sha256', $seed); - $namespace = 'sf_'.$this->getMappingResourceExtension().'_'.$objectManagerName.'_'.$hash; + $namespace = 'sf_'.$this->getMappingResourceExtension().'_'.$objectManagerName.'_'.ContainerBuilder::hash($seed); $cacheDriver['namespace'] = $namespace; } diff --git a/src/Symfony/Bridge/Doctrine/composer.json b/src/Symfony/Bridge/Doctrine/composer.json index 6558860588e60..d09bcd8c3a55d 100644 --- a/src/Symfony/Bridge/Doctrine/composer.json +++ b/src/Symfony/Bridge/Doctrine/composer.json @@ -22,7 +22,7 @@ }, "require-dev": { "symfony/stopwatch": "~2.8|~3.0|~4.0", - "symfony/dependency-injection": "~3.3|~4.0", + "symfony/dependency-injection": "~3.4|~4.0", "symfony/form": "^3.2.5|~4.0", "symfony/http-kernel": "~2.8|~3.0|~4.0", "symfony/property-access": "~2.8|~3.0|~4.0", @@ -38,7 +38,7 @@ }, "conflict": { "phpunit/phpunit": "<4.8.35|<5.4.3,>=5.0", - "symfony/dependency-injection": "<3.3" + "symfony/dependency-injection": "<3.4" }, "suggest": { "symfony/form": "", diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/CachePoolPass.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/CachePoolPass.php index 967c6133f43f7..c63175e2d3ac0 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/CachePoolPass.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/CachePoolPass.php @@ -111,7 +111,7 @@ public static function getServiceProvider(ContainerBuilder $container, $name) if ($usedEnvs || preg_match('#^[a-z]++://#', $name)) { $dsn = $name; - if (!$container->hasDefinition($name = md5($dsn))) { + if (!$container->hasDefinition($name = 'cache_connection.'.ContainerBuilder::hash($dsn))) { $definition = new Definition(AbstractAdapter::class); $definition->setPublic(false); $definition->setFactory(array(AbstractAdapter::class, 'createConnection')); diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php index 10fbdbf5363c8..734876bfdd59c 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php @@ -937,7 +937,7 @@ public function testCacheDefaultRedisProvider() $container = $this->createContainerFromFile('cache'); $redisUrl = 'redis://localhost'; - $providerId = md5($redisUrl); + $providerId = 'cache_connection.'.ContainerBuilder::hash($redisUrl); $this->assertTrue($container->hasDefinition($providerId)); @@ -951,7 +951,7 @@ public function testCacheDefaultRedisProviderWithEnvVar() $container = $this->createContainerFromFile('cache_env_var'); $redisUrl = 'redis://paas.com'; - $providerId = md5($redisUrl); + $providerId = 'cache_connection.'.ContainerBuilder::hash($redisUrl); $this->assertTrue($container->hasDefinition($providerId)); diff --git a/src/Symfony/Bundle/FrameworkBundle/composer.json b/src/Symfony/Bundle/FrameworkBundle/composer.json index e544cef349e61..dd7c103e5e1b2 100644 --- a/src/Symfony/Bundle/FrameworkBundle/composer.json +++ b/src/Symfony/Bundle/FrameworkBundle/composer.json @@ -20,7 +20,7 @@ "ext-xml": "*", "symfony/cache": "~3.4|~4.0", "symfony/class-loader": "~3.2", - "symfony/dependency-injection": "~3.3|~4.0", + "symfony/dependency-injection": "~3.4|~4.0", "symfony/config": "~3.3|~4.0", "symfony/event-dispatcher": "^3.3.1|~4.0", "symfony/http-foundation": "~3.3|~4.0", diff --git a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php index 226b197a5a15c..787b7f2a2ae8d 100644 --- a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php +++ b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php @@ -666,7 +666,7 @@ private function createSwitchUserListener($container, $id, $config, $defaultProv private function createExpression($container, $expression) { - if (isset($this->expressions[$id = 'security.expression.'.sha1($expression)])) { + if (isset($this->expressions[$id = 'security.expression.'.ContainerBuilder::hash($expression)])) { return $this->expressions[$id]; } @@ -686,8 +686,7 @@ private function createRequestMatcher($container, $path = null, $host = null, $m $methods = array_map('strtoupper', (array) $methods); } - $serialized = serialize(array($path, $host, $methods, $ip, $attributes)); - $id = 'security.request_matcher.'.md5($serialized).sha1($serialized); + $id = 'security.request_matcher.'.ContainerBuilder::hash(array($path, $host, $methods, $ip, $attributes)); if (isset($this->requestMatchers[$id])) { return $this->requestMatchers[$id]; diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/CompleteConfigurationTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/CompleteConfigurationTest.php index 6bfe37efd777d..9ccc1762e85bc 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/CompleteConfigurationTest.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/CompleteConfigurationTest.php @@ -84,7 +84,7 @@ public function testFirewalls() array( 'simple', 'security.user_checker', - 'security.request_matcher.707b20193d4cb9f2718114abcbebb32af48f948484fc166a03482f49bf14f25e271f72c7', + 'security.request_matcher.6tndozi', false, ), array( @@ -117,7 +117,7 @@ public function testFirewalls() array( 'host', 'security.user_checker', - 'security.request_matcher.dda8b565689ad8509623ee68fb2c639cd81cd4cb339d60edbaf7d67d30e6aa09bd8c63c3', + 'security.request_matcher.and0kk1', true, false, 'security.user.provider.concrete.default', diff --git a/src/Symfony/Bundle/SecurityBundle/composer.json b/src/Symfony/Bundle/SecurityBundle/composer.json index d8b8aa56b7830..64fdfa46b144b 100644 --- a/src/Symfony/Bundle/SecurityBundle/composer.json +++ b/src/Symfony/Bundle/SecurityBundle/composer.json @@ -19,7 +19,7 @@ "php": ">=5.5.9", "ext-xml": "*", "symfony/security": "~3.4|~4.0", - "symfony/dependency-injection": "~3.3|~4.0", + "symfony/dependency-injection": "~3.4|~4.0", "symfony/http-kernel": "~3.3|~4.0", "symfony/polyfill-php70": "~1.0" }, @@ -29,7 +29,7 @@ "symfony/console": "~3.2|~4.0", "symfony/css-selector": "~2.8|~3.0|~4.0", "symfony/dom-crawler": "~2.8|~3.0|~4.0", - "symfony/event-dispatcher": "~3.3|~4.0", + "symfony/event-dispatcher": "^3.3.1|~4.0", "symfony/form": "^2.8.18|^3.2.5|~4.0", "symfony/framework-bundle": "^3.2.8|~4.0", "symfony/http-foundation": "~2.8|~3.0|~4.0", @@ -47,7 +47,7 @@ }, "conflict": { "symfony/var-dumper": "<3.3", - "symfony/event-dispatcher": "<3.3" + "symfony/event-dispatcher": "<3.3.1" }, "suggest": { "symfony/security-acl": "For using the ACL functionality of this bundle" diff --git a/src/Symfony/Component/DependencyInjection/Compiler/ServiceLocatorTagPass.php b/src/Symfony/Component/DependencyInjection/Compiler/ServiceLocatorTagPass.php index bf9f83bbe80d0..1575ba99a0552 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/ServiceLocatorTagPass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/ServiceLocatorTagPass.php @@ -57,7 +57,7 @@ protected function processValue($value, $isRoot = false) if ($public = $value->isPublic()) { $value->setPublic(false); } - $id = 'service_locator.'.md5(serialize($value)); + $id = 'service_locator.'.ContainerBuilder::hash($value); if ($isRoot) { if ($id !== $this->currentId) { @@ -90,7 +90,7 @@ public static function register(ContainerBuilder $container, array $refMap) ->setPublic(false) ->addTag('container.service_locator'); - if (!$container->has($id = 'service_locator.'.md5(serialize($locator)))) { + if (!$container->has($id = 'service_locator.'.ContainerBuilder::hash($locator))) { $container->setDefinition($id, $locator); } diff --git a/src/Symfony/Component/DependencyInjection/ContainerBuilder.php b/src/Symfony/Component/DependencyInjection/ContainerBuilder.php index c824cc959de9d..d07f879effe01 100644 --- a/src/Symfony/Component/DependencyInjection/ContainerBuilder.php +++ b/src/Symfony/Component/DependencyInjection/ContainerBuilder.php @@ -1391,6 +1391,20 @@ public static function getServiceConditionals($value) return $services; } + /** + * Computes a reasonably unique hash of a value. + * + * @param mixed $value A serializable value + * + * @return string + */ + public static function hash($value) + { + $hash = substr(base64_encode(hash('sha256', serialize($value), true)), 0, 7); + + return str_replace(array('/', '+'), array('.', '_'), strtolower($hash)); + } + /** * Retrieves the currently set proxy instantiator or instantiates one. * diff --git a/src/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php b/src/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php index fa4c33d51459a..2daf77067b095 100644 --- a/src/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php +++ b/src/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php @@ -17,6 +17,7 @@ use Symfony\Component\DependencyInjection\Argument\IteratorArgument; use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\DependencyInjection\ChildDefinition; +use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; use Symfony\Component\DependencyInjection\Exception\RuntimeException; @@ -386,6 +387,7 @@ private function processAnonymousServices(\DOMDocument $xml, $file, $defaults) { $definitions = array(); $count = 0; + $suffix = ContainerBuilder::hash($file); $xpath = new \DOMXPath($xml); $xpath->registerNamespace('container', self::NS); @@ -395,7 +397,7 @@ private function processAnonymousServices(\DOMDocument $xml, $file, $defaults) foreach ($nodes as $node) { if ($services = $this->getChildren($node, 'service')) { // give it a unique name - $id = sprintf('%d_%s', ++$count, hash('sha256', $file)); + $id = sprintf('%d_%s', ++$count, preg_replace('/^.*\\\\/', '', $node->getAttribute('class')).$suffix); $node->setAttribute('id', $id); $node->setAttribute('service', $id); @@ -415,7 +417,7 @@ private function processAnonymousServices(\DOMDocument $xml, $file, $defaults) @trigger_error(sprintf('Top-level anonymous services are deprecated since Symfony 3.4, the "id" attribute will be required in version 4.0 in %s at line %d.', $file, $node->getLineNo()), E_USER_DEPRECATED); // give it a unique name - $id = sprintf('%d_%s', ++$count, hash('sha256', $file)); + $id = sprintf('%d_%s', ++$count, preg_replace('/^.*\\\\/', '', $node->getAttribute('class')).$suffix); $node->setAttribute('id', $id); $definitions[$id] = array($node, $file, true); } diff --git a/src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php b/src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php index 221a218cc32c3..be9408029d3e2 100644 --- a/src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php +++ b/src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php @@ -15,6 +15,7 @@ use Symfony\Component\DependencyInjection\Argument\ArgumentInterface; use Symfony\Component\DependencyInjection\Argument\IteratorArgument; use Symfony\Component\DependencyInjection\ChildDefinition; +use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\DependencyInjection\Reference; @@ -98,6 +99,7 @@ class YamlFileLoader extends FileLoader private $yamlParser; private $anonymousServicesCount; + private $anonymousServicesSuffix; /** * {@inheritdoc} @@ -134,6 +136,7 @@ public function load($resource, $type = null) // services $this->anonymousServicesCount = 0; + $this->anonymousServicesSuffix = ContainerBuilder::hash($path); $this->setCurrentDir(dirname($path)); try { $this->parseDefinitions($content, $path); @@ -691,7 +694,7 @@ private function resolveServices($value, $file, $isParameter = false) $instanceof = $this->instanceof; $this->instanceof = array(); - $id = sprintf('%d_%s', ++$this->anonymousServicesCount, hash('sha256', $file)); + $id = sprintf('%d_%s', ++$this->anonymousServicesCount, preg_replace('/^.*\\\\/', '', isset($argument['class']) ? $argument['class'] : '').$this->anonymousServicesSuffix); $this->parseDefinition($id, $argument, $file, array()); if (!$this->container->hasDefinition($id)) { diff --git a/src/Symfony/Component/DependencyInjection/Tests/Loader/YamlFileLoaderTest.php b/src/Symfony/Component/DependencyInjection/Tests/Loader/YamlFileLoaderTest.php index b8ac2fc0e9296..1af6f7c1ce595 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Loader/YamlFileLoaderTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Loader/YamlFileLoaderTest.php @@ -534,7 +534,7 @@ public function testAnonymousServices() $this->assertCount(1, $args); $this->assertInstanceOf(Reference::class, $args[0]); $this->assertTrue($container->has((string) $args[0])); - $this->assertRegExp('/^\d+_[A-Za-z0-9]{64}$/', (string) $args[0]); + $this->assertRegExp('/^\d+_Bar[._A-Za-z0-9]{7}$/', (string) $args[0]); $anonymous = $container->getDefinition((string) $args[0]); $this->assertEquals('Bar', $anonymous->getClass()); @@ -546,7 +546,7 @@ public function testAnonymousServices() $this->assertInternalType('array', $factory); $this->assertInstanceOf(Reference::class, $factory[0]); $this->assertTrue($container->has((string) $factory[0])); - $this->assertRegExp('/^\d+_[A-Za-z0-9]{64}$/', (string) $factory[0]); + $this->assertRegExp('/^\d+_Quz[._A-Za-z0-9]{7}$/', (string) $factory[0]); $this->assertEquals('constructFoo', $factory[1]); $anonymous = $container->getDefinition((string) $factory[0]); diff --git a/src/Symfony/Component/DomCrawler/Field/FileFormField.php b/src/Symfony/Component/DomCrawler/Field/FileFormField.php index 0e0f94347a5ee..fc21239f01059 100644 --- a/src/Symfony/Component/DomCrawler/Field/FileFormField.php +++ b/src/Symfony/Component/DomCrawler/Field/FileFormField.php @@ -59,7 +59,7 @@ public function setValue($value) $name = $info['basename']; // copy to a tmp location - $tmp = sys_get_temp_dir().'/'.sha1(uniqid(mt_rand(), true)); + $tmp = sys_get_temp_dir().'/'.strtr(substr(base64_encode(hash('sha256', uniqid(mt_rand(), true), true)), 0, 7), '/', '_'); if (array_key_exists('extension', $info)) { $tmp .= '.'.$info['extension']; } diff --git a/src/Symfony/Component/HttpFoundation/BinaryFileResponse.php b/src/Symfony/Component/HttpFoundation/BinaryFileResponse.php index 5f18aa93094ec..a950e0cb72221 100644 --- a/src/Symfony/Component/HttpFoundation/BinaryFileResponse.php +++ b/src/Symfony/Component/HttpFoundation/BinaryFileResponse.php @@ -141,7 +141,7 @@ public function setAutoLastModified() */ public function setAutoEtag() { - $this->setEtag(sha1_file($this->file->getPathname())); + $this->setEtag(substr(base64_encode(hash_file('sha256', $this->file->getPathname(), true)), 0, 32)); return $this; } diff --git a/src/Symfony/Component/HttpKernel/Kernel.php b/src/Symfony/Component/HttpKernel/Kernel.php index ad8ba1b711b3b..4b065f56a0fc0 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -754,7 +754,7 @@ protected function dumpContainer(ConfigCache $cache, ContainerBuilder $container $dumper = new PhpDumper($container); if (class_exists('ProxyManager\Configuration') && class_exists('Symfony\Bridge\ProxyManager\LazyProxy\PhpDumper\ProxyDumper')) { - $dumper->setProxyDumper(new ProxyDumper(md5($cache->getPath()))); + $dumper->setProxyDumper(new ProxyDumper(substr(hash('sha256', $cache->getPath()), 0, 7))); } $content = $dumper->dump(array('class' => $class, 'base_class' => $baseClass, 'file' => $cache->getPath(), 'debug' => $this->debug)); diff --git a/src/Symfony/Component/Lock/Store/FlockStore.php b/src/Symfony/Component/Lock/Store/FlockStore.php index 6bd28c83a42e8..cd0a276de4a38 100644 --- a/src/Symfony/Component/Lock/Store/FlockStore.php +++ b/src/Symfony/Component/Lock/Store/FlockStore.php @@ -71,7 +71,7 @@ private function lock(Key $key, $blocking) $fileName = sprintf('%s/sf.%s.%s.lock', $this->lockPath, preg_replace('/[^a-z0-9\._-]+/i', '-', $key), - hash('sha256', $key) + strtr(substr(base64_encode(hash('sha256', $key, true)), 0, 7), '/', '_') ); // Silence error reporting diff --git a/src/Symfony/Component/Lock/Tests/Store/FlockStoreTest.php b/src/Symfony/Component/Lock/Tests/Store/FlockStoreTest.php index 17c59c440a9cc..53d2ae78dc78a 100644 --- a/src/Symfony/Component/Lock/Tests/Store/FlockStoreTest.php +++ b/src/Symfony/Component/Lock/Tests/Store/FlockStoreTest.php @@ -62,8 +62,9 @@ public function testSaveSanitizeName() $key = new Key(''); $file = sprintf( - '%s/sf.-php-echo-hello-word-.4b3d9d0d27ddef3a78a64685dda3a963e478659a9e5240feaf7b4173a8f28d5f.lock', - sys_get_temp_dir() + '%s/sf.-php-echo-hello-word-.%s.lock', + sys_get_temp_dir(), + strtr(substr(base64_encode(hash('sha256', $key, true)), 0, 7), '/', '_') ); // ensure the file does not exist before the store @unlink($file); diff --git a/src/Symfony/Component/Translation/Dumper/XliffFileDumper.php b/src/Symfony/Component/Translation/Dumper/XliffFileDumper.php index 47b05c81b12db..64588b167991d 100644 --- a/src/Symfony/Component/Translation/Dumper/XliffFileDumper.php +++ b/src/Symfony/Component/Translation/Dumper/XliffFileDumper.php @@ -85,7 +85,7 @@ private function dumpXliff1($defaultLocale, MessageCatalogue $messages, $domain, foreach ($messages->all($domain) as $source => $target) { $translation = $dom->createElement('trans-unit'); - $translation->setAttribute('id', md5($source)); + $translation->setAttribute('id', strtr(substr(base64_encode(hash('sha256', $source, true)), 0, 7), '/+', '._')); $translation->setAttribute('resname', $source); $s = $translation->appendChild($dom->createElement('source')); @@ -145,7 +145,7 @@ private function dumpXliff2($defaultLocale, MessageCatalogue $messages, $domain, foreach ($messages->all($domain) as $source => $target) { $translation = $dom->createElement('unit'); - $translation->setAttribute('id', md5($source)); + $translation->setAttribute('id', strtr(substr(base64_encode(hash('sha256', $source, true)), 0, 7), '/+', '._')); $segment = $translation->appendChild($dom->createElement('segment')); diff --git a/src/Symfony/Component/Translation/Tests/Dumper/FileDumperTest.php b/src/Symfony/Component/Translation/Tests/Dumper/FileDumperTest.php index 9ed4c91eca4cc..79205195393ec 100644 --- a/src/Symfony/Component/Translation/Tests/Dumper/FileDumperTest.php +++ b/src/Symfony/Component/Translation/Tests/Dumper/FileDumperTest.php @@ -28,6 +28,8 @@ public function testDump() $dumper->dump($catalogue, array('path' => $tempDir)); $this->assertFileExists($tempDir.'/messages.en.concrete'); + + @unlink($tempDir.'/messages.en.concrete'); } /** diff --git a/src/Symfony/Component/Translation/Tests/fixtures/resources-2.0-clean.xlf b/src/Symfony/Component/Translation/Tests/fixtures/resources-2.0-clean.xlf index 2efa155e6561f..06047dde542fe 100644 --- a/src/Symfony/Component/Translation/Tests/fixtures/resources-2.0-clean.xlf +++ b/src/Symfony/Component/Translation/Tests/fixtures/resources-2.0-clean.xlf @@ -1,19 +1,19 @@ - + foo bar - + key - + key.with.cdata & ]]> diff --git a/src/Symfony/Component/Translation/Tests/fixtures/resources-clean.xlf b/src/Symfony/Component/Translation/Tests/fixtures/resources-clean.xlf index 436e19ec98beb..00c8a5c2416e8 100644 --- a/src/Symfony/Component/Translation/Tests/fixtures/resources-clean.xlf +++ b/src/Symfony/Component/Translation/Tests/fixtures/resources-clean.xlf @@ -5,18 +5,18 @@ - + foo bar baz - + key baz qux - + key.with.cdata & ]]> diff --git a/src/Symfony/Component/Translation/Tests/fixtures/resources-target-attributes.xlf b/src/Symfony/Component/Translation/Tests/fixtures/resources-target-attributes.xlf index e3afb498b76b4..700d28186e89e 100644 --- a/src/Symfony/Component/Translation/Tests/fixtures/resources-target-attributes.xlf +++ b/src/Symfony/Component/Translation/Tests/fixtures/resources-target-attributes.xlf @@ -5,7 +5,7 @@ - + foo bar diff --git a/src/Symfony/Component/Translation/Tests/fixtures/resources-tool-info.xlf b/src/Symfony/Component/Translation/Tests/fixtures/resources-tool-info.xlf index 1ed06d2ac427b..1c2ae954e5fcc 100644 --- a/src/Symfony/Component/Translation/Tests/fixtures/resources-tool-info.xlf +++ b/src/Symfony/Component/Translation/Tests/fixtures/resources-tool-info.xlf @@ -5,7 +5,7 @@ - + foo bar diff --git a/src/Symfony/Component/Translation/Translator.php b/src/Symfony/Component/Translation/Translator.php index 5f8eb033040b7..897aced2717b5 100644 --- a/src/Symfony/Component/Translation/Translator.php +++ b/src/Symfony/Component/Translation/Translator.php @@ -363,7 +363,7 @@ private function getFallbackContent(MessageCatalogue $catalogue) private function getCatalogueCachePath($locale) { - return $this->cacheDir.'/catalogue.'.$locale.'.'.sha1(serialize($this->fallbackLocales)).'.php'; + return $this->cacheDir.'/catalogue.'.$locale.'.'.strtr(substr(base64_encode(hash('sha256', serialize($this->fallbackLocales), true)), 0, 7), '/', '_').'.php'; } private function doLoadCatalogue($locale) From 2d79ffa0caac35839fc1be50f0d71139cce44bda Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Mon, 31 Jul 2017 15:17:36 +0200 Subject: [PATCH 0563/1099] [Bridge\ProxyManager] Dont call __destruct() on non-instantiated services --- .../LazyLoadingValueHolderFactoryV1.php | 31 ++++++++++++++ .../LazyLoadingValueHolderFactoryV2.php | 32 +++++++++++++++ .../Instantiator/RuntimeInstantiator.php | 6 ++- .../LazyLoadingValueHolderGenerator.php | 41 +++++++++++++++++++ .../LazyProxy/PhpDumper/ProxyDumper.php | 1 - .../Tests/LazyProxy/ContainerBuilderTest.php | 6 +++ .../Tests/LazyProxy/Fixtures/includes/foo.php | 7 ++++ 7 files changed, 122 insertions(+), 2 deletions(-) create mode 100644 src/Symfony/Bridge/ProxyManager/LazyProxy/Instantiator/LazyLoadingValueHolderFactoryV1.php create mode 100644 src/Symfony/Bridge/ProxyManager/LazyProxy/Instantiator/LazyLoadingValueHolderFactoryV2.php create mode 100644 src/Symfony/Bridge/ProxyManager/LazyProxy/PhpDumper/LazyLoadingValueHolderGenerator.php diff --git a/src/Symfony/Bridge/ProxyManager/LazyProxy/Instantiator/LazyLoadingValueHolderFactoryV1.php b/src/Symfony/Bridge/ProxyManager/LazyProxy/Instantiator/LazyLoadingValueHolderFactoryV1.php new file mode 100644 index 0000000000000..3298b84d46278 --- /dev/null +++ b/src/Symfony/Bridge/ProxyManager/LazyProxy/Instantiator/LazyLoadingValueHolderFactoryV1.php @@ -0,0 +1,31 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bridge\ProxyManager\LazyProxy\Instantiator; + +use ProxyManager\Factory\LazyLoadingValueHolderFactory as BaseFactory; +use Symfony\Bridge\ProxyManager\LazyProxy\PhpDumper\LazyLoadingValueHolderGenerator; + +/** + * @internal + */ +class LazyLoadingValueHolderFactoryV1 extends BaseFactory +{ + private $generatorV1; + + /** + * {@inheritdoc} + */ + protected function getGenerator() + { + return $this->generatorV1 ?: $this->generatorV1 = new LazyLoadingValueHolderGenerator(); + } +} diff --git a/src/Symfony/Bridge/ProxyManager/LazyProxy/Instantiator/LazyLoadingValueHolderFactoryV2.php b/src/Symfony/Bridge/ProxyManager/LazyProxy/Instantiator/LazyLoadingValueHolderFactoryV2.php new file mode 100644 index 0000000000000..f41fc20b5d523 --- /dev/null +++ b/src/Symfony/Bridge/ProxyManager/LazyProxy/Instantiator/LazyLoadingValueHolderFactoryV2.php @@ -0,0 +1,32 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bridge\ProxyManager\LazyProxy\Instantiator; + +use ProxyManager\ProxyGenerator\ProxyGeneratorInterface; +use ProxyManager\Factory\LazyLoadingValueHolderFactory as BaseFactory; +use Symfony\Bridge\ProxyManager\LazyProxy\PhpDumper\LazyLoadingValueHolderGenerator; + +/** + * @internal + */ +class LazyLoadingValueHolderFactoryV2 extends BaseFactory +{ + private $generator; + + /** + * {@inheritdoc} + */ + protected function getGenerator(): ProxyGeneratorInterface + { + return $this->generator ?: $this->generator = new LazyLoadingValueHolderGenerator(); + } +} diff --git a/src/Symfony/Bridge/ProxyManager/LazyProxy/Instantiator/RuntimeInstantiator.php b/src/Symfony/Bridge/ProxyManager/LazyProxy/Instantiator/RuntimeInstantiator.php index 0101026794c7c..33fc49e1012d9 100644 --- a/src/Symfony/Bridge/ProxyManager/LazyProxy/Instantiator/RuntimeInstantiator.php +++ b/src/Symfony/Bridge/ProxyManager/LazyProxy/Instantiator/RuntimeInstantiator.php @@ -36,7 +36,11 @@ public function __construct() $config = new Configuration(); $config->setGeneratorStrategy(new EvaluatingGeneratorStrategy()); - $this->factory = new LazyLoadingValueHolderFactory($config); + if (method_exists('ProxyManager\Version', 'getVersion')) { + $this->factory = new LazyLoadingValueHolderFactoryV2($config); + } else { + $this->factory = new LazyLoadingValueHolderFactoryV1($config); + } } /** diff --git a/src/Symfony/Bridge/ProxyManager/LazyProxy/PhpDumper/LazyLoadingValueHolderGenerator.php b/src/Symfony/Bridge/ProxyManager/LazyProxy/PhpDumper/LazyLoadingValueHolderGenerator.php new file mode 100644 index 0000000000000..1d9432f622b41 --- /dev/null +++ b/src/Symfony/Bridge/ProxyManager/LazyProxy/PhpDumper/LazyLoadingValueHolderGenerator.php @@ -0,0 +1,41 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bridge\ProxyManager\LazyProxy\PhpDumper; + +use ProxyManager\ProxyGenerator\LazyLoadingValueHolderGenerator as BaseGenerator; +use Zend\Code\Generator\ClassGenerator; + +/** + * @internal + */ +class LazyLoadingValueHolderGenerator extends BaseGenerator +{ + /** + * {@inheritdoc} + */ + public function generate(\ReflectionClass $originalClass, ClassGenerator $classGenerator) + { + parent::generate($originalClass, $classGenerator); + + if ($classGenerator->hasMethod('__destruct')) { + $destructor = $classGenerator->getMethod('__destruct'); + $body = $destructor->getBody(); + $newBody = preg_replace('/^(\$this->initializer[a-zA-Z0-9]++) && .*;\n\nreturn (\$this->valueHolder)/', '$1 || $2', $body); + + if ($body === $newBody) { + throw new \UnexpectedValueException(sprintf('Unexpected lazy-proxy format generated for method %s::__destruct()', $originalClass->name)); + } + + $destructor->setBody($newBody); + } + } +} diff --git a/src/Symfony/Bridge/ProxyManager/LazyProxy/PhpDumper/ProxyDumper.php b/src/Symfony/Bridge/ProxyManager/LazyProxy/PhpDumper/ProxyDumper.php index eb72a7d5d83cb..40791358500a0 100644 --- a/src/Symfony/Bridge/ProxyManager/LazyProxy/PhpDumper/ProxyDumper.php +++ b/src/Symfony/Bridge/ProxyManager/LazyProxy/PhpDumper/ProxyDumper.php @@ -13,7 +13,6 @@ use ProxyManager\Generator\ClassGenerator; use ProxyManager\GeneratorStrategy\BaseGeneratorStrategy; -use ProxyManager\ProxyGenerator\LazyLoadingValueHolderGenerator; use Symfony\Component\DependencyInjection\Container; use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\DependencyInjection\Definition; diff --git a/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/ContainerBuilderTest.php b/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/ContainerBuilderTest.php index b634a69488a34..858e9d76b64c9 100644 --- a/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/ContainerBuilderTest.php +++ b/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/ContainerBuilderTest.php @@ -39,6 +39,9 @@ public function testCreateProxyServiceWithRuntimeInstantiator() /* @var $foo1 \ProxyManager\Proxy\LazyLoadingInterface|\ProxyManager\Proxy\ValueHolderInterface */ $foo1 = $builder->get('foo1'); + $foo1->__destruct(); + $this->assertSame(0, $foo1::$destructorCount); + $this->assertSame($foo1, $builder->get('foo1'), 'The same proxy is retrieved on multiple subsequent calls'); $this->assertInstanceOf('\ProxyManagerBridgeFooClass', $foo1); $this->assertInstanceOf('\ProxyManager\Proxy\LazyLoadingInterface', $foo1); @@ -50,5 +53,8 @@ public function testCreateProxyServiceWithRuntimeInstantiator() $this->assertTrue($foo1->isProxyInitialized()); $this->assertInstanceOf('\ProxyManagerBridgeFooClass', $foo1->getWrappedValueHolderValue()); $this->assertNotInstanceOf('\ProxyManager\Proxy\LazyLoadingInterface', $foo1->getWrappedValueHolderValue()); + + $foo1->__destruct(); + $this->assertSame(1, $foo1::$destructorCount); } } diff --git a/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/Fixtures/includes/foo.php b/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/Fixtures/includes/foo.php index 16c898a370845..8ffc5be9af40a 100644 --- a/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/Fixtures/includes/foo.php +++ b/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/Fixtures/includes/foo.php @@ -2,6 +2,8 @@ class ProxyManagerBridgeFooClass { + public static $destructorCount = 0; + public $foo; public $moo; @@ -38,4 +40,9 @@ public function setBar($value = null) { $this->bar = $value; } + + public function __destruct() + { + ++self::$destructorCount; + } } From feb5e62a5a8c04744e866b7f81dc297adc85fd24 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Thu, 3 Aug 2017 13:53:37 +0200 Subject: [PATCH 0564/1099] [FrameworkBundle] Warmup annotations for bundle-less controllers and entities --- .../DependencyInjection/FrameworkExtension.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php index 131db0ae86343..b5359b4f7a467 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php @@ -242,8 +242,8 @@ public function load(array $configs, ContainerBuilder $container) } $this->addAnnotatedClassesToCompile(array( - '**Bundle\\Controller\\', - '**Bundle\\Entity\\', + '**\\Controller\\', + '**\\Entity\\', // Added explicitly so that we don't rely on the class map being dumped to make it work 'Symfony\\Bundle\\FrameworkBundle\\Controller\\Controller', From 47c68e12ea9feda162875cb61009f817ea35237c Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Thu, 3 Aug 2017 20:22:22 +0200 Subject: [PATCH 0565/1099] [Workflow] do not emit not needed guard events --- .../Component/Workflow/Tests/WorkflowTest.php | 25 +++++++++++++++++++ src/Symfony/Component/Workflow/Workflow.php | 13 ++++++++-- 2 files changed, 36 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/Workflow/Tests/WorkflowTest.php b/src/Symfony/Component/Workflow/Tests/WorkflowTest.php index 3ca61914aad1c..45dcbc73ccb62 100644 --- a/src/Symfony/Component/Workflow/Tests/WorkflowTest.php +++ b/src/Symfony/Component/Workflow/Tests/WorkflowTest.php @@ -137,6 +137,31 @@ public function testCanWithGuard() $this->assertFalse($workflow->can($subject, 't1')); } + public function testCanDoesNotTriggerGuardEventsForNotEnabledTransitions() + { + $definition = $this->createComplexWorkflowDefinition(); + $subject = new \stdClass(); + $subject->marking = null; + + $dispatchedEvents = array(); + $eventDispatcher = new EventDispatcher(); + + $workflow = new Workflow($definition, new MultipleStateMarkingStore(), $eventDispatcher, 'workflow_name'); + $workflow->apply($subject, 't1'); + $workflow->apply($subject, 't2'); + + $eventDispatcher->addListener('workflow.workflow_name.guard.t3', function () use (&$dispatchedEvents) { + $dispatchedEvents[] = 'workflow_name.guard.t3'; + }); + $eventDispatcher->addListener('workflow.workflow_name.guard.t4', function () use (&$dispatchedEvents) { + $dispatchedEvents[] = 'workflow_name.guard.t4'; + }); + + $workflow->can($subject, 't3'); + + $this->assertSame(array('workflow_name.guard.t3'), $dispatchedEvents); + } + /** * @expectedException \Symfony\Component\Workflow\Exception\LogicException * @expectedExceptionMessage Unable to apply transition "t2" for workflow "unnamed". diff --git a/src/Symfony/Component/Workflow/Workflow.php b/src/Symfony/Component/Workflow/Workflow.php index 617c05b381e09..6f22fb7dc3846 100644 --- a/src/Symfony/Component/Workflow/Workflow.php +++ b/src/Symfony/Component/Workflow/Workflow.php @@ -92,10 +92,19 @@ public function getMarking($subject) */ public function can($subject, $transitionName) { - $transitions = $this->getEnabledTransitions($subject); + $transitions = $this->definition->getTransitions(); + $marking = $this->getMarking($subject); foreach ($transitions as $transition) { - if ($transitionName === $transition->getName()) { + foreach ($transition->getFroms() as $place) { + if (!$marking->has($place)) { + // do not emit guard events for transitions where the marking does not contain + // all "from places" (thus the transition couldn't be applied anyway) + continue 2; + } + } + + if ($transitionName === $transition->getName() && $this->doCan($subject, $marking, $transition)) { return true; } } From e5ef9fb74a5d17a7b5df184c08ad28a3ec1d5e21 Mon Sep 17 00:00:00 2001 From: Javier Eguiluz Date: Thu, 3 Aug 2017 22:11:44 +0200 Subject: [PATCH 0566/1099] Avoid infinite loops when profiler data is malformed --- .../HttpKernel/Profiler/FileProfilerStorage.php | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Component/HttpKernel/Profiler/FileProfilerStorage.php b/src/Symfony/Component/HttpKernel/Profiler/FileProfilerStorage.php index 29da4abf32ccf..045058991063d 100644 --- a/src/Symfony/Component/HttpKernel/Profiler/FileProfilerStorage.php +++ b/src/Symfony/Component/HttpKernel/Profiler/FileProfilerStorage.php @@ -144,11 +144,19 @@ public function write(Profile $profile) } } + $profileToken = $profile->getToken(); + // when there are errors in sub-requests, the parent and/or children tokens + // may equal the profile token, resulting in infinite loops + $parentToken = $profile->getParentToken() !== $profileToken ? $profile->getParentToken() : null; + $childrenToken = array_filter(array_map(function ($p) use ($profileToken) { + return $profileToken !== $p->getToken() ? $p->getToken() : null; + }, $profile->getChildren())); + // Store profile $data = array( - 'token' => $profile->getToken(), - 'parent' => $profile->getParentToken(), - 'children' => array_map(function ($p) { return $p->getToken(); }, $profile->getChildren()), + 'token' => $profileToken, + 'parent' => $parentToken, + 'children' => $childrenToken, 'data' => $profile->getCollectors(), 'ip' => $profile->getIp(), 'method' => $profile->getMethod(), From 56ee4aa5431a4e3a036b30b9e651ca75a216e17a Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Fri, 21 Jul 2017 20:01:38 +0200 Subject: [PATCH 0567/1099] better errors when security deps are missing --- .../Compiler/WorkflowGuardListenerPass.php | 50 +++++++ .../FrameworkExtension.php | 6 + .../FrameworkBundle/FrameworkBundle.php | 2 + .../WorkflowGuardListenerPassTest.php | 127 ++++++++++++++++++ 4 files changed, 185 insertions(+) create mode 100644 src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/WorkflowGuardListenerPass.php create mode 100644 src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/WorkflowGuardListenerPassTest.php diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/WorkflowGuardListenerPass.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/WorkflowGuardListenerPass.php new file mode 100644 index 0000000000000..349d78cfc4fed --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/WorkflowGuardListenerPass.php @@ -0,0 +1,50 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler; + +use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Exception\LogicException; + +/** + * @author Christian Flothmann + */ +class WorkflowGuardListenerPass implements CompilerPassInterface +{ + /** + * {@inheritdoc} + */ + public function process(ContainerBuilder $container) + { + if (!$container->hasParameter('workflow.has_guard_listeners')) { + return; + } + + $container->getParameterBag()->remove('workflow.has_guard_listeners'); + + if (!$container->has('security.token_storage')) { + throw new LogicException('The "security.token_storage" service is needed to be able to use the workflow guard listener.'); + } + + if (!$container->has('security.authorization_checker')) { + throw new LogicException('The "security.authorization_checker" service is needed to be able to use the workflow guard listener.'); + } + + if (!$container->has('security.authentication.trust_resolver')) { + throw new LogicException('The "security.authentication.trust_resolver" service is needed to be able to use the workflow guard listener.'); + } + + if (!$container->has('security.role_hierarchy')) { + throw new LogicException('The "security.role_hierarchy" service is needed to be able to use the workflow guard listener.'); + } + } +} diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php index 131db0ae86343..1ffb86e17dc7b 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php @@ -46,6 +46,7 @@ use Symfony\Component\PropertyInfo\PropertyDescriptionExtractorInterface; use Symfony\Component\PropertyInfo\PropertyListExtractorInterface; use Symfony\Component\PropertyInfo\PropertyTypeExtractorInterface; +use Symfony\Component\Security\Core\Security; use Symfony\Component\Serializer\Encoder\CsvEncoder; use Symfony\Component\Serializer\Encoder\DecoderInterface; use Symfony\Component\Serializer\Encoder\EncoderInterface; @@ -597,6 +598,10 @@ private function registerWorkflowConfiguration(array $workflows, ContainerBuilde throw new LogicException('Cannot guard workflows as the ExpressionLanguage component is not installed.'); } + if (!class_exists(Security::class)) { + throw new LogicException('Cannot guard workflows as the Security component is not installed.'); + } + $eventName = sprintf('workflow.%s.guard.%s', $name, $transitionName); $guard->addTag('kernel.event_listener', array('event' => $eventName, 'method' => 'onTransition')); $configuration[$eventName] = $config['guard']; @@ -612,6 +617,7 @@ private function registerWorkflowConfiguration(array $workflows, ContainerBuilde )); $container->setDefinition(sprintf('%s.listener.guard', $workflowId), $guard); + $container->setParameter('workflow.has_guard_listeners', true); } } } diff --git a/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php b/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php index 99ab06b337772..104795e5593c3 100644 --- a/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php +++ b/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php @@ -28,6 +28,7 @@ use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\TranslationExtractorPass; use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\TranslationDumperPass; use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\UnusedTagsPass; +use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\WorkflowGuardListenerPass; use Symfony\Component\Config\DependencyInjection\ConfigCachePass; use Symfony\Component\Console\DependencyInjection\AddConsoleCommandPass; use Symfony\Component\HttpKernel\DependencyInjection\ControllerArgumentValueResolverPass; @@ -109,6 +110,7 @@ public function build(ContainerBuilder $container) $this->addCompilerPassIfExists($container, ValidateWorkflowsPass::class); $container->addCompilerPass(new CachePoolClearerPass(), PassConfig::TYPE_AFTER_REMOVING); $this->addCompilerPassIfExists($container, FormPass::class); + $container->addCompilerPass(new WorkflowGuardListenerPass()); if ($container->getParameter('kernel.debug')) { $container->addCompilerPass(new AddDebugLogProcessorPass(), PassConfig::TYPE_BEFORE_OPTIMIZATION, -32); diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/WorkflowGuardListenerPassTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/WorkflowGuardListenerPassTest.php new file mode 100644 index 0000000000000..fead9e28f26d0 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/WorkflowGuardListenerPassTest.php @@ -0,0 +1,127 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\Compiler; + +use PHPUnit\Framework\TestCase; +use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\WorkflowGuardListenerPass; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Exception\LogicException; +use Symfony\Component\Security\Core\Authentication\AuthenticationTrustResolverInterface; +use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface; +use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface; +use Symfony\Component\Security\Core\Role\RoleHierarchy; +use Symfony\Component\Workflow\EventListener\GuardListener; + +class WorkflowGuardListenerPassTest extends TestCase +{ + private $container; + private $compilerPass; + + protected function setUp() + { + $this->container = new ContainerBuilder(); + $this->container->register('foo.listener.guard', GuardListener::class); + $this->container->register('bar.listener.guard', GuardListener::class); + $this->compilerPass = new WorkflowGuardListenerPass(); + } + + public function testListenersAreNotRemovedIfParameterIsNotSet() + { + $this->compilerPass->process($this->container); + + $this->assertTrue($this->container->hasDefinition('foo.listener.guard')); + $this->assertTrue($this->container->hasDefinition('bar.listener.guard')); + } + + public function testParameterIsRemovedWhenThePassIsProcessed() + { + $this->container->setParameter('workflow.has_guard_listeners', array('foo.listener.guard', 'bar.listener.guard')); + + try { + $this->compilerPass->process($this->container); + } catch (LogicException $e) { + // Here, we are not interested in the exception handling. This is tested further down. + } + + $this->assertFalse($this->container->hasParameter('workflow.has_guard_listeners')); + } + + public function testListenersAreNotRemovedIfAllDependenciesArePresent() + { + $this->container->setParameter('workflow.has_guard_listeners', array('foo.listener.guard', 'bar.listener.guard')); + $this->container->register('security.token_storage', TokenStorageInterface::class); + $this->container->register('security.authorization_checker', AuthorizationCheckerInterface::class); + $this->container->register('security.authentication.trust_resolver', AuthenticationTrustResolverInterface::class); + $this->container->register('security.role_hierarchy', RoleHierarchy::class); + + $this->compilerPass->process($this->container); + + $this->assertTrue($this->container->hasDefinition('foo.listener.guard')); + $this->assertTrue($this->container->hasDefinition('bar.listener.guard')); + } + + /** + * @expectedException \Symfony\Component\DependencyInjection\Exception\LogicException + * @expectedExceptionMessage The "security.token_storage" service is needed to be able to use the workflow guard listener. + */ + public function testListenersAreRemovedIfTheTokenStorageServiceIsNotPresent() + { + $this->container->setParameter('workflow.has_guard_listeners', array('foo.listener.guard', 'bar.listener.guard')); + $this->container->register('security.authorization_checker', AuthorizationCheckerInterface::class); + $this->container->register('security.authentication.trust_resolver', AuthenticationTrustResolverInterface::class); + $this->container->register('security.role_hierarchy', RoleHierarchy::class); + + $this->compilerPass->process($this->container); + } + + /** + * @expectedException \Symfony\Component\DependencyInjection\Exception\LogicException + * @expectedExceptionMessage The "security.authorization_checker" service is needed to be able to use the workflow guard listener. + */ + public function testListenersAreRemovedIfTheAuthorizationCheckerServiceIsNotPresent() + { + $this->container->setParameter('workflow.has_guard_listeners', array('foo.listener.guard', 'bar.listener.guard')); + $this->container->register('security.token_storage', TokenStorageInterface::class); + $this->container->register('security.authentication.trust_resolver', AuthenticationTrustResolverInterface::class); + $this->container->register('security.role_hierarchy', RoleHierarchy::class); + + $this->compilerPass->process($this->container); + } + + /** + * @expectedException \Symfony\Component\DependencyInjection\Exception\LogicException + * @expectedExceptionMessage The "security.authentication.trust_resolver" service is needed to be able to use the workflow guard listener. + */ + public function testListenersAreRemovedIfTheAuthenticationTrustResolverServiceIsNotPresent() + { + $this->container->setParameter('workflow.has_guard_listeners', array('foo.listener.guard', 'bar.listener.guard')); + $this->container->register('security.token_storage', TokenStorageInterface::class); + $this->container->register('security.authorization_checker', AuthorizationCheckerInterface::class); + $this->container->register('security.role_hierarchy', RoleHierarchy::class); + + $this->compilerPass->process($this->container); + } + + /** + * @expectedException \Symfony\Component\DependencyInjection\Exception\LogicException + * @expectedExceptionMessage The "security.role_hierarchy" service is needed to be able to use the workflow guard listener. + */ + public function testListenersAreRemovedIfTheRoleHierarchyServiceIsNotPresent() + { + $this->container->setParameter('workflow.has_guard_listeners', array('foo.listener.guard', 'bar.listener.guard')); + $this->container->register('security.token_storage', TokenStorageInterface::class); + $this->container->register('security.authorization_checker', AuthorizationCheckerInterface::class); + $this->container->register('security.authentication.trust_resolver', AuthenticationTrustResolverInterface::class); + + $this->compilerPass->process($this->container); + } +} From 9910ba1ad4ec278c7d1099c9f97a8e117a26ef14 Mon Sep 17 00:00:00 2001 From: Amrouche Hamza Date: Fri, 28 Jul 2017 11:47:13 +0200 Subject: [PATCH 0568/1099] [Workflow] feature: add getter in workflow --- .../Workflow/MarkingStore/MultipleStateMarkingStore.php | 8 ++++++++ .../Workflow/MarkingStore/SingleStateMarkingStore.php | 8 ++++++++ .../SupportStrategy/ClassInstanceSupportStrategy.php | 8 ++++++++ src/Symfony/Component/Workflow/Workflow.php | 8 ++++++++ 4 files changed, 32 insertions(+) diff --git a/src/Symfony/Component/Workflow/MarkingStore/MultipleStateMarkingStore.php b/src/Symfony/Component/Workflow/MarkingStore/MultipleStateMarkingStore.php index 874d1fb5134a5..6d2d0884893dc 100644 --- a/src/Symfony/Component/Workflow/MarkingStore/MultipleStateMarkingStore.php +++ b/src/Symfony/Component/Workflow/MarkingStore/MultipleStateMarkingStore.php @@ -54,4 +54,12 @@ public function setMarking($subject, Marking $marking) { $this->propertyAccessor->setValue($subject, $this->property, $marking->getPlaces()); } + + /** + * @return string + */ + public function getProperty() + { + return $this->property; + } } diff --git a/src/Symfony/Component/Workflow/MarkingStore/SingleStateMarkingStore.php b/src/Symfony/Component/Workflow/MarkingStore/SingleStateMarkingStore.php index 99adf1671bab1..d6afc6aeeb764 100644 --- a/src/Symfony/Component/Workflow/MarkingStore/SingleStateMarkingStore.php +++ b/src/Symfony/Component/Workflow/MarkingStore/SingleStateMarkingStore.php @@ -59,4 +59,12 @@ public function setMarking($subject, Marking $marking) { $this->propertyAccessor->setValue($subject, $this->property, key($marking->getPlaces())); } + + /** + * @return string + */ + public function getProperty() + { + return $this->property; + } } diff --git a/src/Symfony/Component/Workflow/SupportStrategy/ClassInstanceSupportStrategy.php b/src/Symfony/Component/Workflow/SupportStrategy/ClassInstanceSupportStrategy.php index c2aaa27212654..8828946dbf543 100644 --- a/src/Symfony/Component/Workflow/SupportStrategy/ClassInstanceSupportStrategy.php +++ b/src/Symfony/Component/Workflow/SupportStrategy/ClassInstanceSupportStrategy.php @@ -26,4 +26,12 @@ public function supports(Workflow $workflow, $subject) { return $subject instanceof $this->className; } + + /** + * @return string + */ + public function getClassName() + { + return $this->className; + } } diff --git a/src/Symfony/Component/Workflow/Workflow.php b/src/Symfony/Component/Workflow/Workflow.php index 617c05b381e09..b7b13c90af41b 100644 --- a/src/Symfony/Component/Workflow/Workflow.php +++ b/src/Symfony/Component/Workflow/Workflow.php @@ -186,6 +186,14 @@ public function getDefinition() return $this->definition; } + /** + * @return MarkingStoreInterface + */ + public function getMarkingStore() + { + return $this->markingStore; + } + private function doCan($subject, Marking $marking, Transition $transition) { foreach ($transition->getFroms() as $place) { From 9815af3810eb4b8d2325baf7ca93a31cd2a62887 Mon Sep 17 00:00:00 2001 From: Guilhem Niot Date: Thu, 25 May 2017 12:16:49 +0200 Subject: [PATCH 0569/1099] [Yaml] Deprecate tags using colon --- UPGRADE-3.4.md | 32 +++++++--- UPGRADE-4.0.md | 28 +++++++-- .../Tests/Fixtures/yaml/services2.yml | 2 +- .../DependencyInjection/composer.json | 4 +- .../Tests/Encoder/YamlEncoderTest.php | 6 +- .../Component/Serializer/composer.json | 4 +- .../Mapping/Loader/mapping-with-constants.yml | 2 +- src/Symfony/Component/Validator/composer.json | 4 +- src/Symfony/Component/Yaml/CHANGELOG.md | 6 ++ src/Symfony/Component/Yaml/Inline.php | 31 +++++++++- src/Symfony/Component/Yaml/Parser.php | 2 +- .../Yaml/Tests/Command/LintCommandTest.php | 2 +- .../Component/Yaml/Tests/DumperTest.php | 4 +- .../Component/Yaml/Tests/InlineTest.php | 23 ++++--- .../Component/Yaml/Tests/ParserTest.php | 60 ++++++++++++++++--- 15 files changed, 166 insertions(+), 44 deletions(-) diff --git a/UPGRADE-3.4.md b/UPGRADE-3.4.md index 1619ec95adf04..7612ab1274306 100644 --- a/UPGRADE-3.4.md +++ b/UPGRADE-3.4.md @@ -37,13 +37,13 @@ FrameworkBundle require symfony/stopwatch` in your `dev` environment. * Using the `KERNEL_DIR` environment variable or the automatic guessing based - on the `phpunit.xml` / `phpunit.xml.dist` file location is deprecated since 3.4. + on the `phpunit.xml` / `phpunit.xml.dist` file location is deprecated since 3.4. Set the `KERNEL_CLASS` environment variable to the fully-qualified class name - of your Kernel instead. Not setting the `KERNEL_CLASS` environment variable - will throw an exception on 4.0 unless you override the `KernelTestCase::createKernel()` + of your Kernel instead. Not setting the `KERNEL_CLASS` environment variable + will throw an exception on 4.0 unless you override the `KernelTestCase::createKernel()` or `KernelTestCase::getKernelClass()` method. - - * The `KernelTestCase::getPhpUnitXmlDir()` and `KernelTestCase::getPhpUnitCliConfigArgument()` + + * The `KernelTestCase::getPhpUnitXmlDir()` and `KernelTestCase::getPhpUnitCliConfigArgument()` methods are deprecated since 3.4 and will be removed in 4.0. * The `--no-prefix` option of the `translation:update` command is deprecated and @@ -90,7 +90,7 @@ TwigBridge * deprecated the `Symfony\Bridge\Twig\Form\TwigRenderer` class, use the `FormRenderer` class from the Form component instead - * deprecated `Symfony\Bridge\Twig\Command\DebugCommand::set/getTwigEnvironment` and the ability + * deprecated `Symfony\Bridge\Twig\Command\DebugCommand::set/getTwigEnvironment` and the ability to pass a command name as first argument * deprecated `Symfony\Bridge\Twig\Command\LintCommand::set/getTwigEnvironment` and the ability @@ -102,7 +102,7 @@ TwigBundle * deprecated the `Symfony\Bundle\TwigBundle\Command\DebugCommand` class, use the `DebugCommand` class from the Twig bridge instead - * deprecated relying on the `ContainerAwareInterface` implementation for + * deprecated relying on the `ContainerAwareInterface` implementation for `Symfony\Bundle\TwigBundle\Command\LintCommand` Validator @@ -114,6 +114,24 @@ Validator Yaml ---- + * using the `!php/object:` tag is deprecated and won't be supported in 4.0. Use + the `!php/object` tag (without the colon) instead. + + * using the `!php/const:` tag is deprecated and won't be supported in 4.0. Use + the `!php/const` tag (without the colon) instead. + + Before: + + ```yml + !php/const:PHP_INT_MAX + ``` + + After: + + ```yml + !php/const PHP_INT_MAX + ``` + * Support for the `!str` tag is deprecated, use the `!!str` tag instead. * Using the non-specific tag `!` is deprecated and will have a different diff --git a/UPGRADE-4.0.md b/UPGRADE-4.0.md index aabaed1c3c18c..769477b0fd7e4 100644 --- a/UPGRADE-4.0.md +++ b/UPGRADE-4.0.md @@ -345,9 +345,9 @@ FrameworkBundle class instead. * Using the `KERNEL_DIR` environment variable and the automatic guessing based - on the `phpunit.xml` file location have been removed from the `KernelTestCase::getKernelClass()` + on the `phpunit.xml` file location have been removed from the `KernelTestCase::getKernelClass()` method implementation. Set the `KERNEL_CLASS` environment variable to the - fully-qualified class name of your Kernel or override the `KernelTestCase::createKernel()` + fully-qualified class name of your Kernel or override the `KernelTestCase::createKernel()` or `KernelTestCase::getKernelClass()` method instead. * The `Symfony\Bundle\FrameworkBundle\Validator\ConstraintValidatorFactory` class has been removed. @@ -356,10 +356,10 @@ FrameworkBundle * The `--no-prefix` option of the `translation:update` command has been removed. - * The `Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\AddCacheClearerPass` class has been removed. + * The `Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\AddCacheClearerPass` class has been removed. Use the `Symfony\Component\HttpKernel\DependencyInjection\AddCacheClearerPass` class instead. - * The `Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\AddCacheWarmerPass` class has been removed. + * The `Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\AddCacheWarmerPass` class has been removed. Use the `Symfony\Component\HttpKernel\DependencyInjection\AddCacheWarmerPass` class instead. * The `Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\TranslationDumperPass` @@ -561,7 +561,7 @@ TwigBridge * The `TwigRendererEngine::setEnvironment()` method has been removed. Pass the Twig Environment as second argument of the constructor instead. - * Removed `Symfony\Bridge\Twig\Command\DebugCommand::set/getTwigEnvironment` and the ability + * Removed `Symfony\Bridge\Twig\Command\DebugCommand::set/getTwigEnvironment` and the ability to pass a command name as first argument. * Removed `Symfony\Bridge\Twig\Command\LintCommand::set/getTwigEnvironment` and the ability @@ -773,3 +773,21 @@ Yaml * The behavior of the non-specific tag `!` is changed and now forces non-evaluating your values. + + * The `!php/object:` tag was removed in favor of the `!php/object` tag (without + the colon). + + * The `!php/const:` tag was removed in favor of the `!php/const` tag (without + the colon). + + Before: + + ```yml + !php/const:PHP_INT_MAX + ``` + + After: + + ```yml + !php/const PHP_INT_MAX + ``` diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services2.yml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services2.yml index 91de818f29242..7ab302bcb9f9a 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services2.yml +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services2.yml @@ -5,7 +5,7 @@ parameters: - false - 0 - 1000.3 - - !php/const:PHP_INT_MAX + - !php/const PHP_INT_MAX bar: foo escape: '@@escapeme' foo_bar: '@foo_bar' diff --git a/src/Symfony/Component/DependencyInjection/composer.json b/src/Symfony/Component/DependencyInjection/composer.json index ba391a2bd9a98..f7bedea506a0e 100644 --- a/src/Symfony/Component/DependencyInjection/composer.json +++ b/src/Symfony/Component/DependencyInjection/composer.json @@ -20,7 +20,7 @@ "psr/container": "^1.0" }, "require-dev": { - "symfony/yaml": "~3.3|~4.0", + "symfony/yaml": "~3.4|~4.0", "symfony/config": "~3.3|~4.0", "symfony/expression-language": "~2.8|~3.0|~4.0" }, @@ -35,7 +35,7 @@ "symfony/config": "<3.3.1", "symfony/finder": "<3.3", "symfony/proxy-manager-bridge": "<3.4", - "symfony/yaml": "<3.3" + "symfony/yaml": "<3.4" }, "provide": { "psr/container-implementation": "1.0" diff --git a/src/Symfony/Component/Serializer/Tests/Encoder/YamlEncoderTest.php b/src/Symfony/Component/Serializer/Tests/Encoder/YamlEncoderTest.php index c602039667394..85f939114c0ba 100644 --- a/src/Symfony/Component/Serializer/Tests/Encoder/YamlEncoderTest.php +++ b/src/Symfony/Component/Serializer/Tests/Encoder/YamlEncoderTest.php @@ -61,9 +61,9 @@ public function testContext() $obj = new \stdClass(); $obj->bar = 2; - $this->assertEquals(" foo: !php/object:O:8:\"stdClass\":1:{s:3:\"bar\";i:2;}\n", $encoder->encode(array('foo' => $obj), 'yaml')); + $this->assertEquals(" foo: !php/object 'O:8:\"stdClass\":1:{s:3:\"bar\";i:2;}'\n", $encoder->encode(array('foo' => $obj), 'yaml')); $this->assertEquals(' { foo: null }', $encoder->encode(array('foo' => $obj), 'yaml', array('yaml_inline' => 0, 'yaml_indent' => 2, 'yaml_flags' => 0))); - $this->assertEquals(array('foo' => $obj), $encoder->decode('foo: !php/object:O:8:"stdClass":1:{s:3:"bar";i:2;}', 'yaml')); - $this->assertEquals(array('foo' => null), $encoder->decode('foo: !php/object:O:8:"stdClass":1:{s:3:"bar";i:2;}', 'yaml', array('yaml_flags' => 0))); + $this->assertEquals(array('foo' => $obj), $encoder->decode("foo: !php/object 'O:8:\"stdClass\":1:{s:3:\"bar\";i:2;}'", 'yaml')); + $this->assertEquals(array('foo' => null), $encoder->decode("foo: !php/object 'O:8:\"stdClass\":1:{s:3:\"bar\";i:2;}'", 'yaml', array('yaml_flags' => 0))); } } diff --git a/src/Symfony/Component/Serializer/composer.json b/src/Symfony/Component/Serializer/composer.json index 3219ac0805483..126068b647487 100644 --- a/src/Symfony/Component/Serializer/composer.json +++ b/src/Symfony/Component/Serializer/composer.json @@ -19,7 +19,7 @@ "php": ">=5.5.9" }, "require-dev": { - "symfony/yaml": "~3.3|~4.0", + "symfony/yaml": "~3.4|~4.0", "symfony/config": "~2.8|~3.0|~4.0", "symfony/property-access": "~2.8|~3.0|~4.0", "symfony/http-foundation": "~2.8|~3.0|~4.0", @@ -34,7 +34,7 @@ "symfony/dependency-injection": "<3.2", "symfony/property-access": ">=3.0,<3.0.4|>=2.8,<2.8.4", "symfony/property-info": "<3.1", - "symfony/yaml": "<3.3" + "symfony/yaml": "<3.4" }, "suggest": { "psr/cache-implementation": "For using the metadata cache.", diff --git a/src/Symfony/Component/Validator/Tests/Mapping/Loader/mapping-with-constants.yml b/src/Symfony/Component/Validator/Tests/Mapping/Loader/mapping-with-constants.yml index 9352fe521e215..32ddcc5b5ea06 100644 --- a/src/Symfony/Component/Validator/Tests/Mapping/Loader/mapping-with-constants.yml +++ b/src/Symfony/Component/Validator/Tests/Mapping/Loader/mapping-with-constants.yml @@ -5,4 +5,4 @@ Symfony\Component\Validator\Tests\Fixtures\Entity: properties: firstName: - Range: - max: !php/const:PHP_INT_MAX + max: !php/const PHP_INT_MAX diff --git a/src/Symfony/Component/Validator/composer.json b/src/Symfony/Component/Validator/composer.json index a050573d82bef..e90b5e882c673 100644 --- a/src/Symfony/Component/Validator/composer.json +++ b/src/Symfony/Component/Validator/composer.json @@ -25,7 +25,7 @@ "symfony/http-kernel": "^3.3.5|~4.0", "symfony/var-dumper": "~3.3|~4.0", "symfony/intl": "^2.8.18|^3.2.5|~4.0", - "symfony/yaml": "~3.3|~4.0", + "symfony/yaml": "~3.4|~4.0", "symfony/config": "~2.8|~3.0|~4.0", "symfony/dependency-injection": "~3.3|~4.0", "symfony/expression-language": "~2.8|~3.0|~4.0", @@ -39,7 +39,7 @@ "phpunit/phpunit": "<4.8.35|<5.4.3,>=5.0", "symfony/dependency-injection": "<3.3", "symfony/http-kernel": "<3.3.5", - "symfony/yaml": "<3.3" + "symfony/yaml": "<3.4" }, "suggest": { "psr/cache-implementation": "For using the metadata cache.", diff --git a/src/Symfony/Component/Yaml/CHANGELOG.md b/src/Symfony/Component/Yaml/CHANGELOG.md index d0c0fdbf671a6..bdbac2b93e917 100644 --- a/src/Symfony/Component/Yaml/CHANGELOG.md +++ b/src/Symfony/Component/Yaml/CHANGELOG.md @@ -4,6 +4,12 @@ CHANGELOG 3.4.0 ----- + * Deprecated the `!php/object:` tag which will be replaced by the + `!php/object` tag (without the colon) in 4.0. + + * Deprecated the `!php/const:` tag which will be replaced by the + `!php/const` tag (without the colon) in 4.0. + * Support for the `!str` tag is deprecated, use the `!!str` tag instead. * Deprecated using the non-specific tag `!` as its behavior will change in 4.0. diff --git a/src/Symfony/Component/Yaml/Inline.php b/src/Symfony/Component/Yaml/Inline.php index 6a911e9090158..0ef96fc547d28 100644 --- a/src/Symfony/Component/Yaml/Inline.php +++ b/src/Symfony/Component/Yaml/Inline.php @@ -170,7 +170,7 @@ public static function dump($value, $flags = 0) } if (Yaml::DUMP_OBJECT & $flags) { - return '!php/object:'.serialize($value); + return '!php/object '.self::dump(serialize($value)); } if (Yaml::DUMP_OBJECT_AS_MAP & $flags && ($value instanceof \stdClass || $value instanceof \ArrayObject)) { @@ -620,6 +620,8 @@ private static function evaluateScalar($scalar, $flags, $references = array()) return (int) self::parseScalar(substr($scalar, 2), $flags); case 0 === strpos($scalar, '!php/object:'): if (self::$objectSupport) { + @trigger_error('The !php/object: tag to indicate dumped PHP objects is deprecated since version 3.4 and will be removed in 4.0. Use the !php/object (without the colon) tag instead.', E_USER_DEPRECATED); + return unserialize(substr($scalar, 12)); } @@ -630,7 +632,7 @@ private static function evaluateScalar($scalar, $flags, $references = array()) return; case 0 === strpos($scalar, '!!php/object:'): if (self::$objectSupport) { - @trigger_error('The !!php/object tag to indicate dumped PHP objects is deprecated since version 3.1 and will be removed in 4.0. Use the !php/object tag instead.', E_USER_DEPRECATED); + @trigger_error('The !!php/object: tag to indicate dumped PHP objects is deprecated since version 3.1 and will be removed in 4.0. Use the !php/object (without the colon) tag instead.', E_USER_DEPRECATED); return unserialize(substr($scalar, 13)); } @@ -639,9 +641,21 @@ private static function evaluateScalar($scalar, $flags, $references = array()) throw new ParseException('Object support when parsing a YAML file has been disabled.'); } + return; + case 0 === strpos($scalar, '!php/object'): + if (self::$objectSupport) { + return unserialize(self::parseScalar(substr($scalar, 12))); + } + + if (self::$exceptionOnInvalidType) { + throw new ParseException('Object support when parsing a YAML file has been disabled.'); + } + return; case 0 === strpos($scalar, '!php/const:'): if (self::$constantSupport) { + @trigger_error('The !php/const: tag to indicate dumped PHP constants is deprecated since version 3.4 and will be removed in 4.0. Use the !php/const (without the colon) tag instead.', E_USER_DEPRECATED); + if (defined($const = substr($scalar, 11))) { return constant($const); } @@ -652,6 +666,19 @@ private static function evaluateScalar($scalar, $flags, $references = array()) throw new ParseException(sprintf('The string "%s" could not be parsed as a constant. Have you forgotten to pass the "Yaml::PARSE_CONSTANT" flag to the parser?', $scalar)); } + return; + case 0 === strpos($scalar, '!php/const'): + if (self::$constantSupport) { + if (defined($const = self::parseScalar(substr($scalar, 11)))) { + return constant($const); + } + + throw new ParseException(sprintf('The constant "%s" is not defined.', $const)); + } + if (self::$exceptionOnInvalidType) { + throw new ParseException(sprintf('The string "%s" could not be parsed as a constant. Have you forgotten to pass the "Yaml::PARSE_CONSTANT" flag to the parser?', $scalar)); + } + return; case 0 === strpos($scalar, '!!float '): return (float) substr($scalar, 8); diff --git a/src/Symfony/Component/Yaml/Parser.php b/src/Symfony/Component/Yaml/Parser.php index 82db443e0583b..1e5ff83ad4d86 100644 --- a/src/Symfony/Component/Yaml/Parser.php +++ b/src/Symfony/Component/Yaml/Parser.php @@ -208,7 +208,7 @@ private function doParse($value, $flags) $this->refs[$isRef] = end($data); } } elseif ( - self::preg_match('#^(?P'.Inline::REGEX_QUOTED_STRING.'|(?:!?!php/const:)?(?:![^\s]++\s++)?[^ \'"\[\{!].*?) *\:(\s++(?P.+))?$#u', rtrim($this->currentLine), $values) + self::preg_match('#^(?P(?:![^\s]++\s++)?(?:'.Inline::REGEX_QUOTED_STRING.'|(?:!?!php/const:)?[^ \'"\[\{!].*?)) *\:(\s++(?P.+))?$#u', rtrim($this->currentLine), $values) && (false === strpos($values['key'], ' #') || in_array($values['key'][0], array('"', "'"))) ) { if ($context && 'sequence' == $context) { diff --git a/src/Symfony/Component/Yaml/Tests/Command/LintCommandTest.php b/src/Symfony/Component/Yaml/Tests/Command/LintCommandTest.php index 75aa067f22890..351724128263d 100644 --- a/src/Symfony/Component/Yaml/Tests/Command/LintCommandTest.php +++ b/src/Symfony/Component/Yaml/Tests/Command/LintCommandTest.php @@ -54,7 +54,7 @@ public function testLintIncorrectFile() public function testConstantAsKey() { $yaml = <<createCommandTester()->execute(array('filename' => $this->createFile($yaml)), array('verbosity' => OutputInterface::VERBOSITY_VERBOSE, 'decorated' => false)); $this->assertSame(0, $ret, 'lint:yaml exits with code 0 in case of success'); diff --git a/src/Symfony/Component/Yaml/Tests/DumperTest.php b/src/Symfony/Component/Yaml/Tests/DumperTest.php index 1c80bec6506c2..3635ba7caa143 100644 --- a/src/Symfony/Component/Yaml/Tests/DumperTest.php +++ b/src/Symfony/Component/Yaml/Tests/DumperTest.php @@ -210,7 +210,7 @@ public function testObjectSupportEnabled() { $dump = $this->dumper->dump(array('foo' => new A(), 'bar' => 1), 0, 0, Yaml::DUMP_OBJECT); - $this->assertEquals('{ foo: !php/object:O:30:"Symfony\Component\Yaml\Tests\A":1:{s:1:"a";s:3:"foo";}, bar: 1 }', $dump, '->dump() is able to dump objects'); + $this->assertEquals('{ foo: !php/object \'O:30:"Symfony\Component\Yaml\Tests\A":1:{s:1:"a";s:3:"foo";}\', bar: 1 }', $dump, '->dump() is able to dump objects'); } /** @@ -220,7 +220,7 @@ public function testObjectSupportEnabledPassingTrue() { $dump = $this->dumper->dump(array('foo' => new A(), 'bar' => 1), 0, 0, false, true); - $this->assertEquals('{ foo: !php/object:O:30:"Symfony\Component\Yaml\Tests\A":1:{s:1:"a";s:3:"foo";}, bar: 1 }', $dump, '->dump() is able to dump objects'); + $this->assertEquals('{ foo: !php/object \'O:30:"Symfony\Component\Yaml\Tests\A":1:{s:1:"a";s:3:"foo";}\', bar: 1 }', $dump, '->dump() is able to dump objects'); } public function testObjectSupportDisabledButNoExceptions() diff --git a/src/Symfony/Component/Yaml/Tests/InlineTest.php b/src/Symfony/Component/Yaml/Tests/InlineTest.php index b48263f8cd6ac..517c0a617edc9 100644 --- a/src/Symfony/Component/Yaml/Tests/InlineTest.php +++ b/src/Symfony/Component/Yaml/Tests/InlineTest.php @@ -49,10 +49,10 @@ public function testParsePhpConstants($yaml, $value) public function getTestsForParsePhpConstants() { return array( - array('!php/const:Symfony\Component\Yaml\Yaml::PARSE_CONSTANT', Yaml::PARSE_CONSTANT), - array('!php/const:PHP_INT_MAX', PHP_INT_MAX), - array('[!php/const:PHP_INT_MAX]', array(PHP_INT_MAX)), - array('{ foo: !php/const:PHP_INT_MAX }', array('foo' => PHP_INT_MAX)), + array('!php/const Symfony\Component\Yaml\Yaml::PARSE_CONSTANT', Yaml::PARSE_CONSTANT), + array('!php/const PHP_INT_MAX', PHP_INT_MAX), + array('[!php/const PHP_INT_MAX]', array(PHP_INT_MAX)), + array('{ foo: !php/const PHP_INT_MAX }', array('foo' => PHP_INT_MAX)), ); } @@ -62,16 +62,25 @@ public function getTestsForParsePhpConstants() */ public function testParsePhpConstantThrowsExceptionWhenUndefined() { - Inline::parse('!php/const:WRONG_CONSTANT', Yaml::PARSE_CONSTANT); + Inline::parse('!php/const WRONG_CONSTANT', Yaml::PARSE_CONSTANT); } /** * @expectedException \Symfony\Component\Yaml\Exception\ParseException - * @expectedExceptionMessageRegExp #The string "!php/const:PHP_INT_MAX" could not be parsed as a constant.*# + * @expectedExceptionMessageRegExp #The string "!php/const PHP_INT_MAX" could not be parsed as a constant.*# */ public function testParsePhpConstantThrowsExceptionOnInvalidType() { - Inline::parse('!php/const:PHP_INT_MAX', Yaml::PARSE_EXCEPTION_ON_INVALID_TYPE); + Inline::parse('!php/const PHP_INT_MAX', Yaml::PARSE_EXCEPTION_ON_INVALID_TYPE); + } + + /** + * @group legacy + * @expectedDeprecation The !php/const: tag to indicate dumped PHP constants is deprecated since version 3.4 and will be removed in 4.0. Use the !php/const (without the colon) tag instead. + */ + public function testDeprecatedConstantTag() + { + Inline::parse('!php/const:PHP_INT_MAX', Yaml::PARSE_CONSTANT); } /** diff --git a/src/Symfony/Component/Yaml/Tests/ParserTest.php b/src/Symfony/Component/Yaml/Tests/ParserTest.php index b75fd1b324b73..717d2c3fd96ee 100644 --- a/src/Symfony/Component/Yaml/Tests/ParserTest.php +++ b/src/Symfony/Component/Yaml/Tests/ParserTest.php @@ -469,7 +469,7 @@ public function testBlockLiteralWithLeadingNewlines() public function testObjectSupportEnabled() { $input = <<<'EOF' -foo: !php/object:O:30:"Symfony\Component\Yaml\Tests\B":1:{s:1:"b";s:3:"foo";} +foo: !php/object O:30:"Symfony\Component\Yaml\Tests\B":1:{s:1:"b";s:3:"foo";} bar: 1 EOF; $this->assertEquals(array('foo' => new B(), 'bar' => 1), $this->parser->parse($input, Yaml::PARSE_OBJECT), '->parse() is able to parse objects'); @@ -489,14 +489,29 @@ public function testObjectSupportEnabledPassingTrue() /** * @group legacy + * @dataProvider deprecatedObjectValueProvider */ - public function testObjectSupportEnabledWithDeprecatedTag() + public function testObjectSupportEnabledWithDeprecatedTag($yaml) { - $input = <<<'EOF' + $this->assertEquals(array('foo' => new B(), 'bar' => 1), $this->parser->parse($yaml, Yaml::PARSE_OBJECT), '->parse() is able to parse objects'); + } + + public function deprecatedObjectValueProvider() + { + return array( + array( + <<assertEquals(array('foo' => new B(), 'bar' => 1), $this->parser->parse($input, Yaml::PARSE_OBJECT), '->parse() is able to parse objects'); +YAML + ), + array( + << array( + 'foo' => array( + 'from' => array( + 'bar', + ), + 'to' => 'baz', + ), + ), + ); + + $this->assertSame($expected, $this->parser->parse($yaml, Yaml::PARSE_CONSTANT)); + } + + /** + * @group legacy + * @expectedDeprecation The !php/const: tag to indicate dumped PHP constants is deprecated since version 3.4 and will be removed in 4.0. Use the !php/const (without the colon) tag instead. + * @expectedDeprecation The !php/const: tag to indicate dumped PHP constants is deprecated since version 3.4 and will be removed in 4.0. Use the !php/const (without the colon) tag instead. + * @expectedDeprecation The !php/const: tag to indicate dumped PHP constants is deprecated since version 3.4 and will be removed in 4.0. Use the !php/const (without the colon) tag instead. + */ + public function testDeprecatedPhpConstantTagMappingKey() + { + $yaml = << array( From 7f6a0d8ef254f3692dff8e04f915d55575ad75aa Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Fri, 4 Aug 2017 17:42:05 +0200 Subject: [PATCH 0570/1099] remove legacy php/const and php/object tag support --- src/Symfony/Component/Yaml/Inline.php | 41 +------------ .../Component/Yaml/Tests/InlineTest.php | 9 --- .../Component/Yaml/Tests/ParserTest.php | 58 +------------------ 3 files changed, 2 insertions(+), 106 deletions(-) diff --git a/src/Symfony/Component/Yaml/Inline.php b/src/Symfony/Component/Yaml/Inline.php index a70fd09beac8e..d2d39b644e07c 100644 --- a/src/Symfony/Component/Yaml/Inline.php +++ b/src/Symfony/Component/Yaml/Inline.php @@ -554,30 +554,6 @@ private static function evaluateScalar($scalar, $flags, $references = array()) return (string) substr($scalar, 6); case 0 === strpos($scalar, '! '): return substr($scalar, 2); - case 0 === strpos($scalar, '!php/object:'): - if (self::$objectSupport) { - @trigger_error('The !php/object: tag to indicate dumped PHP objects is deprecated since version 3.4 and will be removed in 4.0. Use the !php/object (without the colon) tag instead.', E_USER_DEPRECATED); - - return unserialize(substr($scalar, 12)); - } - - if (self::$exceptionOnInvalidType) { - throw new ParseException('Object support when parsing a YAML file has been disabled.'); - } - - return; - case 0 === strpos($scalar, '!!php/object:'): - if (self::$objectSupport) { - @trigger_error('The !!php/object: tag to indicate dumped PHP objects is deprecated since version 3.1 and will be removed in 4.0. Use the !php/object (without the colon) tag instead.', E_USER_DEPRECATED); - - return unserialize(substr($scalar, 13)); - } - - if (self::$exceptionOnInvalidType) { - throw new ParseException('Object support when parsing a YAML file has been disabled.'); - } - - return; case 0 === strpos($scalar, '!php/object'): if (self::$objectSupport) { return unserialize(self::parseScalar(substr($scalar, 12))); @@ -587,21 +563,6 @@ private static function evaluateScalar($scalar, $flags, $references = array()) throw new ParseException('Object support when parsing a YAML file has been disabled.'); } - return; - case 0 === strpos($scalar, '!php/const:'): - if (self::$constantSupport) { - @trigger_error('The !php/const: tag to indicate dumped PHP constants is deprecated since version 3.4 and will be removed in 4.0. Use the !php/const (without the colon) tag instead.', E_USER_DEPRECATED); - - if (defined($const = substr($scalar, 11))) { - return constant($const); - } - - throw new ParseException(sprintf('The constant "%s" is not defined.', $const)); - } - if (self::$exceptionOnInvalidType) { - throw new ParseException(sprintf('The string "%s" could not be parsed as a constant. Have you forgotten to pass the "Yaml::PARSE_CONSTANT" flag to the parser?', $scalar)); - } - return; case 0 === strpos($scalar, '!php/const'): if (self::$constantSupport) { @@ -690,7 +651,7 @@ private static function parseTag($value, &$i, $flags) $nextOffset += strspn($value, ' ', $nextOffset); // Is followed by a scalar and is a built-in tag - if ($tag && (!isset($value[$nextOffset]) || !in_array($value[$nextOffset], array('[', '{'), true)) && ('!' === $tag[0] || 'str' === $tag || 0 === strpos($tag, 'php/const:') || 0 === strpos($tag, 'php/object:'))) { + if ($tag && (!isset($value[$nextOffset]) || !in_array($value[$nextOffset], array('[', '{'), true)) && ('!' === $tag[0] || 'str' === $tag || 'php/const' === $tag || 'php/object' === $tag)) { // Manage in {@link self::evaluateScalar()} return; } diff --git a/src/Symfony/Component/Yaml/Tests/InlineTest.php b/src/Symfony/Component/Yaml/Tests/InlineTest.php index e6a4d9a35d029..b1a4c1ccb5cde 100644 --- a/src/Symfony/Component/Yaml/Tests/InlineTest.php +++ b/src/Symfony/Component/Yaml/Tests/InlineTest.php @@ -74,15 +74,6 @@ public function testParsePhpConstantThrowsExceptionOnInvalidType() Inline::parse('!php/const PHP_INT_MAX', Yaml::PARSE_EXCEPTION_ON_INVALID_TYPE); } - /** - * @group legacy - * @expectedDeprecation The !php/const: tag to indicate dumped PHP constants is deprecated since version 3.4 and will be removed in 4.0. Use the !php/const (without the colon) tag instead. - */ - public function testDeprecatedConstantTag() - { - Inline::parse('!php/const:PHP_INT_MAX', Yaml::PARSE_CONSTANT); - } - /** * @dataProvider getTestsForDump */ diff --git a/src/Symfony/Component/Yaml/Tests/ParserTest.php b/src/Symfony/Component/Yaml/Tests/ParserTest.php index 2f18c2b69b1ac..c8142a46df2ed 100644 --- a/src/Symfony/Component/Yaml/Tests/ParserTest.php +++ b/src/Symfony/Component/Yaml/Tests/ParserTest.php @@ -441,39 +441,12 @@ public function testObjectSupportEnabled() public function testObjectSupportDisabledButNoExceptions() { $input = <<<'EOF' -foo: !php/object:O:30:"Symfony\Tests\Component\Yaml\B":1:{s:1:"b";s:3:"foo";} +foo: !php/object O:30:"Symfony\Tests\Component\Yaml\B":1:{s:1:"b";s:3:"foo";} bar: 1 EOF; $this->assertEquals(array('foo' => null, 'bar' => 1), $this->parser->parse($input), '->parse() does not parse objects'); } - /** - * @group legacy - * @dataProvider deprecatedObjectValueProvider - */ - public function testObjectSupportEnabledWithDeprecatedTag($yaml) - { - $this->assertEquals(array('foo' => new B(), 'bar' => 1), $this->parser->parse($yaml, Yaml::PARSE_OBJECT), '->parse() is able to parse objects'); - } - - public function deprecatedObjectValueProvider() - { - return array( - array( - <<assertSame($expected, $this->parser->parse($yaml, Yaml::PARSE_CONSTANT)); } - - /** - * @group legacy - * @expectedDeprecation The !php/const: tag to indicate dumped PHP constants is deprecated since version 3.4 and will be removed in 4.0. Use the !php/const (without the colon) tag instead. - * @expectedDeprecation The !php/const: tag to indicate dumped PHP constants is deprecated since version 3.4 and will be removed in 4.0. Use the !php/const (without the colon) tag instead. - * @expectedDeprecation The !php/const: tag to indicate dumped PHP constants is deprecated since version 3.4 and will be removed in 4.0. Use the !php/const (without the colon) tag instead. - */ - public function testDeprecatedPhpConstantTagMappingKey() - { - $yaml = << array( - 'foo' => array( - 'from' => array( - 'bar', - ), - 'to' => 'baz', - ), - ), - ); - - $this->assertSame($expected, $this->parser->parse($yaml, Yaml::PARSE_CONSTANT)); - } } class B From 2f3ac8f53ef5eb8fa4a1a207edd1ce4dce4e854c Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Sat, 5 Aug 2017 08:05:00 +0200 Subject: [PATCH 0571/1099] allow phpdocumentor/reflection-docblock >=3.2.1 --- composer.json | 2 +- src/Symfony/Component/PropertyInfo/composer.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/composer.json b/composer.json index faf29256bc0c9..bf18c7b79995f 100644 --- a/composer.json +++ b/composer.json @@ -102,7 +102,7 @@ "sensio/framework-extra-bundle": "^3.0.2" }, "conflict": { - "phpdocumentor/reflection-docblock": "<3.0||>=3.2.0", + "phpdocumentor/reflection-docblock": "<3.0||>=3.2.0,<3.2.1", "phpdocumentor/type-resolver": "<0.2.0", "phpunit/phpunit": "<4.8.35|<5.4.3,>=5.0" }, diff --git a/src/Symfony/Component/PropertyInfo/composer.json b/src/Symfony/Component/PropertyInfo/composer.json index fbc8f06a73a6d..20bdccf00156b 100644 --- a/src/Symfony/Component/PropertyInfo/composer.json +++ b/src/Symfony/Component/PropertyInfo/composer.json @@ -34,7 +34,7 @@ "doctrine/annotations": "~1.0" }, "conflict": { - "phpdocumentor/reflection-docblock": "<3.0||>=3.2.0", + "phpdocumentor/reflection-docblock": "<3.0||>=3.2.0,<3.2.1", "phpdocumentor/type-resolver": "<0.2.0", "symfony/dependency-injection": "<3.3" }, From 6443c963a69cf96fa08937cba55ccbd2d6918a70 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Sat, 5 Aug 2017 08:45:41 +0200 Subject: [PATCH 0572/1099] [Serializer] fix tests for Yaml component 3.4 --- .../Component/Serializer/Tests/Encoder/YamlEncoderTest.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/Serializer/Tests/Encoder/YamlEncoderTest.php b/src/Symfony/Component/Serializer/Tests/Encoder/YamlEncoderTest.php index c602039667394..0e280245ec2ee 100644 --- a/src/Symfony/Component/Serializer/Tests/Encoder/YamlEncoderTest.php +++ b/src/Symfony/Component/Serializer/Tests/Encoder/YamlEncoderTest.php @@ -61,7 +61,9 @@ public function testContext() $obj = new \stdClass(); $obj->bar = 2; - $this->assertEquals(" foo: !php/object:O:8:\"stdClass\":1:{s:3:\"bar\";i:2;}\n", $encoder->encode(array('foo' => $obj), 'yaml')); + $legacyTag = " foo: !php/object:O:8:\"stdClass\":1:{s:3:\"bar\";i:2;}\n"; + $spacedTag = " foo: !php/object 'O:8:\"stdClass\":1:{s:3:\"bar\";i:2;}'\n"; + $this->assertThat($encoder->encode(array('foo' => $obj), 'yaml'), $this->logicalOr($this->equalTo($legacyTag), $this->equalTo($spacedTag))); $this->assertEquals(' { foo: null }', $encoder->encode(array('foo' => $obj), 'yaml', array('yaml_inline' => 0, 'yaml_indent' => 2, 'yaml_flags' => 0))); $this->assertEquals(array('foo' => $obj), $encoder->decode('foo: !php/object:O:8:"stdClass":1:{s:3:"bar";i:2;}', 'yaml')); $this->assertEquals(array('foo' => null), $encoder->decode('foo: !php/object:O:8:"stdClass":1:{s:3:"bar";i:2;}', 'yaml', array('yaml_flags' => 0))); From 94956ebae4c6f47e5525ea1e411211c595771d47 Mon Sep 17 00:00:00 2001 From: Dany Maillard Date: Thu, 3 Aug 2017 18:41:46 +0200 Subject: [PATCH 0573/1099] Remove leading 0 in ms of date caster --- .../Component/VarDumper/Caster/DateCaster.php | 9 +++++++-- .../VarDumper/Tests/Caster/DateCasterTest.php | 17 ++++++++++++----- 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/src/Symfony/Component/VarDumper/Caster/DateCaster.php b/src/Symfony/Component/VarDumper/Caster/DateCaster.php index 5a59ca48e1e7a..17e7f4f929068 100644 --- a/src/Symfony/Component/VarDumper/Caster/DateCaster.php +++ b/src/Symfony/Component/VarDumper/Caster/DateCaster.php @@ -32,7 +32,7 @@ public static function castDateTime(\DateTimeInterface $d, array $a, Stub $stub, ; $a = array(); - $a[$prefix.'date'] = new ConstStub($d->format('Y-m-d H:i:s.u '.($location ? 'e (P)' : 'P')), $title); + $a[$prefix.'date'] = new ConstStub($d->format('Y-m-d H:i:'.self::formatSeconds($d->format('s'), $d->format('u')).($location ? ' e (P)' : ' P')), $title); $stub->class .= $d->format(' @U'); @@ -59,7 +59,7 @@ private static function formatInterval(\DateInterval $i) ; if (\PHP_VERSION_ID >= 70100 && isset($i->f)) { - $format .= $i->h || $i->i || $i->s || $i->f ? '%H:%I:%S.%F' : ''; + $format .= $i->h || $i->i || $i->s || $i->f ? '%H:%I:'.self::formatSeconds($i->s, $i->f) : ''; } else { $format .= $i->h || $i->i || $i->s ? '%H:%I:%S' : ''; } @@ -79,4 +79,9 @@ public static function castTimeZone(\DateTimeZone $timeZone, array $a, Stub $stu return $filter & Caster::EXCLUDE_VERBOSE ? $z : $z + $a; } + + private static function formatSeconds($s, $us) + { + return sprintf('%02d.%s', $s, 0 === ($len = strlen($t = rtrim($us, '0'))) ? '0' : ($len <= 3 ? str_pad($t, 3, '0') : $us)); + } } diff --git a/src/Symfony/Component/VarDumper/Tests/Caster/DateCasterTest.php b/src/Symfony/Component/VarDumper/Tests/Caster/DateCasterTest.php index d470bbc19165f..f1207e30d16fc 100644 --- a/src/Symfony/Component/VarDumper/Tests/Caster/DateCasterTest.php +++ b/src/Symfony/Component/VarDumper/Tests/Caster/DateCasterTest.php @@ -52,7 +52,7 @@ public function testCastDateTime() $xDump = <<<'EODUMP' array:1 [ - "\x00~\x00date" => 2017-08-30 00:00:00.000000 Europe/Zurich (+02:00) + "\x00~\x00date" => 2017-08-30 00:00:00.0 Europe/Zurich (+02:00) ] EODUMP; @@ -61,7 +61,7 @@ public function testCastDateTime() $xDump = <<<'EODUMP' Symfony\Component\VarDumper\Caster\ConstStub { +type: 1 - +class: "2017-08-30 00:00:00.000000 Europe/Zurich (+02:00)" + +class: "2017-08-30 00:00:00.0 Europe/Zurich (+02:00)" +value: """ Wednesday, August 30, 2017\n +%a from now\n @@ -81,8 +81,15 @@ public function testCastDateTime() public function provideDateTimes() { return array( - array('2017-04-30 00:00:00.000000', 'Europe/Zurich', '2017-04-30 00:00:00.000000 Europe/Zurich (+02:00)'), - array('2017-04-30 00:00:00.000000', '+02:00', '2017-04-30 00:00:00.000000 +02:00'), + array('2017-04-30 00:00:00.000000', 'Europe/Zurich', '2017-04-30 00:00:00.0 Europe/Zurich (+02:00)'), + array('2017-04-30 00:00:00.000000', '+02:00', '2017-04-30 00:00:00.0 +02:00'), + + array('2017-04-30 00:00:00.100000', '+02:00', '2017-04-30 00:00:00.100 +02:00'), + array('2017-04-30 00:00:00.120000', '+02:00', '2017-04-30 00:00:00.120 +02:00'), + array('2017-04-30 00:00:00.123000', '+02:00', '2017-04-30 00:00:00.123 +02:00'), + array('2017-04-30 00:00:00.123400', '+02:00', '2017-04-30 00:00:00.123400 +02:00'), + array('2017-04-30 00:00:00.123450', '+02:00', '2017-04-30 00:00:00.123450 +02:00'), + array('2017-04-30 00:00:00.123456', '+02:00', '2017-04-30 00:00:00.123456 +02:00'), ); } @@ -162,7 +169,7 @@ public function testCastInterval($intervalSpec, $invert, $xInterval, $xSeconds) public function provideIntervals() { $i = new \DateInterval('PT0S'); - $ms = \PHP_VERSION_ID >= 70100 && isset($i->f) ? '.000000' : ''; + $ms = \PHP_VERSION_ID >= 70100 && isset($i->f) ? '.0' : ''; return array( array('PT0S', 0, '0s', '0s'), From d40e7e4c2de1c4468714de8006f84aee287aace8 Mon Sep 17 00:00:00 2001 From: Roland Franssen Date: Sun, 30 Oct 2016 08:36:08 +0000 Subject: [PATCH 0574/1099] [Config] Enable cannotBeEmpty along with requiresAtLeastOneElement --- .../Builder/ArrayNodeDefinition.php | 8 +++++- .../Builder/ArrayNodeDefinitionTest.php | 27 +++++++++++++++++++ 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/Config/Definition/Builder/ArrayNodeDefinition.php b/src/Symfony/Component/Config/Definition/Builder/ArrayNodeDefinition.php index 9db0b3676763c..cac53044a9a10 100644 --- a/src/Symfony/Component/Config/Definition/Builder/ArrayNodeDefinition.php +++ b/src/Symfony/Component/Config/Definition/Builder/ArrayNodeDefinition.php @@ -428,7 +428,7 @@ protected function createNode() $node->setKeyAttribute($this->key, $this->removeKeyItem); } - if (true === $this->atLeastOne) { + if (true === $this->atLeastOne || false === $this->allowEmptyValue) { $node->setMinNumberOfElements(1); } @@ -490,6 +490,12 @@ protected function validateConcreteNode(ArrayNode $node) ); } + if (false === $this->allowEmptyValue) { + throw new InvalidDefinitionException( + sprintf('->cannotBeEmpty() is not applicable to concrete nodes at path "%s"', $path) + ); + } + if (true === $this->atLeastOne) { throw new InvalidDefinitionException( sprintf('->requiresAtLeastOneElement() is not applicable to concrete nodes at path "%s"', $path) diff --git a/src/Symfony/Component/Config/Tests/Definition/Builder/ArrayNodeDefinitionTest.php b/src/Symfony/Component/Config/Tests/Definition/Builder/ArrayNodeDefinitionTest.php index f2a32351a84aa..4c2a397cff6df 100644 --- a/src/Symfony/Component/Config/Tests/Definition/Builder/ArrayNodeDefinitionTest.php +++ b/src/Symfony/Component/Config/Tests/Definition/Builder/ArrayNodeDefinitionTest.php @@ -54,6 +54,7 @@ public function providePrototypeNodeSpecificCalls() array('defaultValue', array(array())), array('addDefaultChildrenIfNoneSet', array()), array('requiresAtLeastOneElement', array()), + array('cannotBeEmpty', array()), array('useAttributeAsKey', array('foo')), ); } @@ -285,6 +286,32 @@ public function getEnableableNodeFixtures() ); } + public function testRequiresAtLeastOneElement() + { + $node = new ArrayNodeDefinition('root'); + $node + ->requiresAtLeastOneElement() + ->integerPrototype(); + + $node->getNode()->finalize(array(1)); + + $this->addToAssertionCount(1); + } + + /** + * @expectedException \Symfony\Component\Config\Definition\Exception\InvalidConfigurationException + * @expectedExceptionMessage The path "root" should have at least 1 element(s) defined. + */ + public function testCannotBeEmpty() + { + $node = new ArrayNodeDefinition('root'); + $node + ->cannotBeEmpty() + ->integerPrototype(); + + $node->getNode()->finalize(array()); + } + protected function getField($object, $field) { $reflection = new \ReflectionProperty($object, $field); From 259f9cc4adaf452a1dffc31b9ee9c5bce12cda0b Mon Sep 17 00:00:00 2001 From: Yurii K Date: Sun, 6 Aug 2017 02:56:19 +0300 Subject: [PATCH 0575/1099] Update Container.php: Deprecated -> @deprecated Deprecated -> @deprecated --- src/Symfony/Component/DependencyInjection/Container.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/DependencyInjection/Container.php b/src/Symfony/Component/DependencyInjection/Container.php index f435a99baec0f..379c7f6d0eb76 100644 --- a/src/Symfony/Component/DependencyInjection/Container.php +++ b/src/Symfony/Component/DependencyInjection/Container.php @@ -111,7 +111,7 @@ public function isCompiled() /** * Returns true if the container parameter bag are frozen. * - * Deprecated since 3.3, to be removed in 4.0. + * @deprecated since version 3.3, to be removed in 4.0. * * @return bool true if the container parameter bag are frozen, false otherwise */ From de1dc0b469d1264db26f04c98abe4801abfaa2f6 Mon Sep 17 00:00:00 2001 From: Roland Franssen Date: Sat, 22 Jul 2017 11:58:19 +0200 Subject: [PATCH 0576/1099] [FrameworkBundle] Commands as a service --- .../Bridge/Twig/Command/DebugCommand.php | 2 +- .../Bridge/Twig/Command/LintCommand.php | 2 +- .../FrameworkBundle/Command/AboutCommand.php | 4 +- .../Command/AbstractConfigCommand.php | 4 +- .../Command/AssetsInstallCommand.php | 34 ++++++-- .../Command/CacheClearCommand.php | 62 ++++++++++---- .../Command/CachePoolClearCommand.php | 38 +++++++-- .../Command/CacheWarmupCommand.php | 37 ++++++-- .../Command/ConfigDebugCommand.php | 4 +- .../Command/ConfigDumpReferenceCommand.php | 2 + .../Command/ContainerDebugCommand.php | 2 + .../Command/EventDispatcherDebugCommand.php | 34 +++++++- .../Command/RouterDebugCommand.php | 36 +++++++- .../Command/RouterMatchCommand.php | 37 +++++++- .../Command/TranslationDebugCommand.php | 79 ++++++++++++----- .../Command/TranslationUpdateCommand.php | 64 +++++++++++--- .../Command/WorkflowDumpCommand.php | 9 +- .../Command/XliffLintCommand.php | 2 + .../Command/YamlLintCommand.php | 2 + .../FrameworkExtension.php | 25 ++++-- .../FrameworkBundle/FrameworkBundle.php | 6 ++ .../Resources/config/cache.xml | 5 -- .../Resources/config/console.xml | 84 +++++++++++++++++++ .../Tests/Command/RouterDebugCommandTest.php | 32 +++++-- .../Tests/Command/RouterMatchCommandTest.php | 39 +++++++-- .../Command/TranslationDebugCommandTest.php | 80 +++++++++++++----- .../Command/TranslationUpdateCommandTest.php | 78 ++++++++++++----- .../FrameworkExtensionTest.php | 1 + .../Functional/CachePoolClearCommandTest.php | 24 +++++- .../SecurityBundle/Command/InitAclCommand.php | 2 + .../SecurityBundle/Command/SetAclCommand.php | 2 + .../Command/UserPasswordEncoderCommand.php | 16 +--- .../DependencyInjection/SecurityExtension.php | 3 +- .../Resources/config/console.xml | 10 ++- .../Bundle/SecurityBundle/SecurityBundle.php | 6 ++ .../CompleteConfigurationTest.php | 3 +- .../TwigBundle/Resources/config/console.xml | 9 +- src/Symfony/Bundle/TwigBundle/TwigBundle.php | 6 ++ 38 files changed, 714 insertions(+), 171 deletions(-) diff --git a/src/Symfony/Bridge/Twig/Command/DebugCommand.php b/src/Symfony/Bridge/Twig/Command/DebugCommand.php index a0239b5f42a28..e9519adb66d33 100644 --- a/src/Symfony/Bridge/Twig/Command/DebugCommand.php +++ b/src/Symfony/Bridge/Twig/Command/DebugCommand.php @@ -100,7 +100,7 @@ protected function execute(InputInterface $input, OutputInterface $output) if (__CLASS__ !== get_class($this)) { $r = new \ReflectionMethod($this, 'getTwigEnvironment'); if (__CLASS__ !== $r->getDeclaringClass()->getName()) { - @trigger_error(sprintf('Usage of method "%s" is deprecated since version 3.4 and will no longer be supported in 4.0.', get_class($this).'::getTwigEnvironment'), E_USER_DEPRECATED); + @trigger_error(sprintf('Usage of method "%s" is deprecated since version 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); $this->twig = $this->getTwigEnvironment(); } diff --git a/src/Symfony/Bridge/Twig/Command/LintCommand.php b/src/Symfony/Bridge/Twig/Command/LintCommand.php index c9eac4de6058e..2aae6120d318f 100644 --- a/src/Symfony/Bridge/Twig/Command/LintCommand.php +++ b/src/Symfony/Bridge/Twig/Command/LintCommand.php @@ -105,7 +105,7 @@ protected function execute(InputInterface $input, OutputInterface $output) if (__CLASS__ !== get_class($this)) { $r = new \ReflectionMethod($this, 'getTwigEnvironment'); if (__CLASS__ !== $r->getDeclaringClass()->getName()) { - @trigger_error(sprintf('Usage of method "%s" is deprecated since version 3.4 and will no longer be supported in 4.0.', get_class($this).'::getTwigEnvironment'), E_USER_DEPRECATED); + @trigger_error(sprintf('Usage of method "%s" is deprecated since version 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); $this->twig = $this->getTwigEnvironment(); } diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/AboutCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/AboutCommand.php index 6db6da85e065a..3b9130a8e40a8 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/AboutCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/AboutCommand.php @@ -23,6 +23,8 @@ * A console command to display information about the current installation. * * @author Roland Franssen + * + * @final since version 3.4 */ class AboutCommand extends ContainerAwareCommand { @@ -45,7 +47,7 @@ protected function execute(InputInterface $input, OutputInterface $output) $io = new SymfonyStyle($input, $output); /** @var $kernel KernelInterface */ - $kernel = $this->getContainer()->get('kernel'); + $kernel = $this->getApplication()->getKernel(); $io->table(array(), array( array('Symfony'), diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/AbstractConfigCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/AbstractConfigCommand.php index a0c43cac901ca..5244b7ef331e5 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/AbstractConfigCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/AbstractConfigCommand.php @@ -31,7 +31,7 @@ protected function listBundles($output) $headers = array('Bundle name', 'Extension alias'); $rows = array(); - $bundles = $this->getContainer()->get('kernel')->getBundles(); + $bundles = $this->getApplication()->getKernel()->getBundles(); usort($bundles, function ($bundleA, $bundleB) { return strcmp($bundleA->getName(), $bundleB->getName()); }); @@ -117,7 +117,7 @@ private function initializeBundles() // Re-build bundle manually to initialize DI extensions that can be extended by other bundles in their build() method // as this method is not called when the container is loaded from the cache. $container = $this->getContainerBuilder(); - $bundles = $this->getContainer()->get('kernel')->getBundles(); + $bundles = $this->getApplication()->getKernel()->getBundles(); foreach ($bundles as $bundle) { if ($extension = $bundle->getContainerExtension()) { $container->registerExtension($extension); diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/AssetsInstallCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/AssetsInstallCommand.php index 3e2222f813ec7..b8ad74300d759 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/AssetsInstallCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/AssetsInstallCommand.php @@ -26,6 +26,8 @@ * * @author Fabien Potencier * @author Gábor Egyed + * + * @final since version 3.4 */ class AssetsInstallCommand extends ContainerAwareCommand { @@ -33,10 +35,25 @@ class AssetsInstallCommand extends ContainerAwareCommand const METHOD_ABSOLUTE_SYMLINK = 'absolute symlink'; const METHOD_RELATIVE_SYMLINK = 'relative symlink'; + private $filesystem; + /** - * @var Filesystem + * @param Filesystem $filesystem */ - private $filesystem; + public function __construct($filesystem = null) + { + parent::__construct(); + + if (!$filesystem instanceof Filesystem) { + @trigger_error(sprintf('Passing a command name as the first argument of "%s" is deprecated since version 3.4 and will be removed in 4.0. If the command was registered by convention, make it a service instead.', __METHOD__), E_USER_DEPRECATED); + + $this->setName(null === $filesystem ? 'assets:install' : $filesystem); + + return; + } + + $this->filesystem = $filesystem; + } /** * {@inheritdoc} @@ -79,10 +96,17 @@ protected function configure() */ protected function execute(InputInterface $input, OutputInterface $output) { + // BC to be removed in 4.0 + if (null === $this->filesystem) { + $this->filesystem = $this->getContainer()->get('filesystem'); + $baseDir = $this->getContainer()->getParameter('kernel.project_dir'); + } + + $kernel = $this->getApplication()->getKernel(); $targetArg = rtrim($input->getArgument('target'), '/'); if (!is_dir($targetArg)) { - $targetArg = $this->getContainer()->getParameter('kernel.project_dir').'/'.$targetArg; + $targetArg = (isset($baseDir) ? $baseDir : $kernel->getContainer()->getParameter('kernel.project_dir')).'/'.$targetArg; if (!is_dir($targetArg)) { // deprecated, logic to be removed in 4.0 @@ -95,8 +119,6 @@ protected function execute(InputInterface $input, OutputInterface $output) } } - $this->filesystem = $this->getContainer()->get('filesystem'); - // Create the bundles directory otherwise symlink will fail. $bundlesDir = $targetArg.'/bundles/'; $this->filesystem->mkdir($bundlesDir, 0777); @@ -122,7 +144,7 @@ protected function execute(InputInterface $input, OutputInterface $output) $exitCode = 0; $validAssetDirs = array(); /** @var BundleInterface $bundle */ - foreach ($this->getContainer()->get('kernel')->getBundles() as $bundle) { + foreach ($kernel->getBundles() as $bundle) { if (!is_dir($originDir = $bundle->getPath().'/Resources/public')) { continue; } diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/CacheClearCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/CacheClearCommand.php index 2331afecb4e84..631b31b600a27 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/CacheClearCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/CacheClearCommand.php @@ -15,6 +15,8 @@ use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Style\SymfonyStyle; +use Symfony\Component\Filesystem\Filesystem; +use Symfony\Component\HttpKernel\CacheClearer\CacheClearerInterface; use Symfony\Component\HttpKernel\KernelInterface; use Symfony\Component\Finder\Finder; @@ -23,9 +25,34 @@ * * @author Francis Besset * @author Fabien Potencier + * + * @final since version 3.4 */ class CacheClearCommand extends ContainerAwareCommand { + private $cacheClearer; + private $filesystem; + + /** + * @param CacheClearerInterface $cacheClearer + * @param Filesystem|null $filesystem + */ + public function __construct($cacheClearer = null, Filesystem $filesystem = null) + { + parent::__construct(); + + if (!$cacheClearer instanceof CacheClearerInterface) { + @trigger_error(sprintf('Passing a command name as the first argument of "%s" is deprecated since version 3.4 and will be removed in 4.0. If the command was registered by convention, make it a service instead.', __METHOD__), E_USER_DEPRECATED); + + $this->setName(null === $cacheClearer ? 'cache:clear' : $cacheClearer); + + return; + } + + $this->cacheClearer = $cacheClearer; + $this->filesystem = $filesystem ?: new Filesystem(); + } + /** * {@inheritdoc} */ @@ -54,28 +81,34 @@ protected function configure() */ protected function execute(InputInterface $input, OutputInterface $output) { + // BC to be removed in 4.0 + if (null === $this->cacheClearer) { + $this->cacheClearer = $this->getContainer()->get('cache_clearer'); + $this->filesystem = $this->getContainer()->get('filesystem'); + $realCacheDir = $this->getContainer()->getParameter('kernel.cache_dir'); + } + $io = new SymfonyStyle($input, $output); - $realCacheDir = $this->getContainer()->getParameter('kernel.cache_dir'); + $kernel = $this->getApplication()->getKernel(); + $realCacheDir = isset($realCacheDir) ? $realCacheDir : $kernel->getContainer()->getParameter('kernel.cache_dir'); // the old cache dir name must not be longer than the real one to avoid exceeding // the maximum length of a directory or file path within it (esp. Windows MAX_PATH) $oldCacheDir = substr($realCacheDir, 0, -1).('~' === substr($realCacheDir, -1) ? '+' : '~'); - $filesystem = $this->getContainer()->get('filesystem'); if (!is_writable($realCacheDir)) { throw new \RuntimeException(sprintf('Unable to write in the "%s" directory', $realCacheDir)); } - if ($filesystem->exists($oldCacheDir)) { - $filesystem->remove($oldCacheDir); + if ($this->filesystem->exists($oldCacheDir)) { + $this->filesystem->remove($oldCacheDir); } - $kernel = $this->getContainer()->get('kernel'); $io->comment(sprintf('Clearing the cache for the %s environment with debug %s', $kernel->getEnvironment(), var_export($kernel->isDebug(), true))); - $this->getContainer()->get('cache_clearer')->clear($realCacheDir); + $this->cacheClearer->clear($realCacheDir); if ($input->getOption('no-warmup')) { - $filesystem->rename($realCacheDir, $oldCacheDir); + $this->filesystem->rename($realCacheDir, $oldCacheDir); } else { $warning = 'Calling cache:clear without the --no-warmup option is deprecated since version 3.3. Cache warmup should be done with the cache:warmup command instead.'; @@ -90,7 +123,7 @@ protected function execute(InputInterface $input, OutputInterface $output) $io->comment('Removing old cache directory...'); } - $filesystem->remove($oldCacheDir); + $this->filesystem->remove($oldCacheDir); if ($output->isVerbose()) { $io->comment('Finished'); @@ -101,7 +134,6 @@ protected function execute(InputInterface $input, OutputInterface $output) private function warmupCache(InputInterface $input, OutputInterface $output, $realCacheDir, $oldCacheDir) { - $filesystem = $this->getContainer()->get('filesystem'); $io = new SymfonyStyle($input, $output); // the warmup cache dir name must have the same length than the real one @@ -109,11 +141,11 @@ private function warmupCache(InputInterface $input, OutputInterface $output, $re $realCacheDir = realpath($realCacheDir); $warmupDir = substr($realCacheDir, 0, -1).('_' === substr($realCacheDir, -1) ? '-' : '_'); - if ($filesystem->exists($warmupDir)) { + if ($this->filesystem->exists($warmupDir)) { if ($output->isVerbose()) { $io->comment('Clearing outdated warmup directory...'); } - $filesystem->remove($warmupDir); + $this->filesystem->remove($warmupDir); } if ($output->isVerbose()) { @@ -121,11 +153,11 @@ private function warmupCache(InputInterface $input, OutputInterface $output, $re } $this->warmup($warmupDir, $realCacheDir, !$input->getOption('no-optional-warmers')); - $filesystem->rename($realCacheDir, $oldCacheDir); + $this->filesystem->rename($realCacheDir, $oldCacheDir); if ('\\' === DIRECTORY_SEPARATOR) { sleep(1); // workaround for Windows PHP rename bug } - $filesystem->rename($warmupDir, $realCacheDir); + $this->filesystem->rename($warmupDir, $realCacheDir); } /** @@ -138,7 +170,7 @@ private function warmupCache(InputInterface $input, OutputInterface $output, $re protected function warmup($warmupDir, $realCacheDir, $enableOptionalWarmers = true) { // create a temporary kernel - $realKernel = $this->getContainer()->get('kernel'); + $realKernel = $this->getApplication()->getKernel(); $realKernelClass = get_class($realKernel); $namespace = ''; if (false !== $pos = strrpos($realKernelClass, '\\')) { @@ -274,7 +306,7 @@ protected function buildContainer() } } EOF; - $this->getContainer()->get('filesystem')->mkdir($warmupDir); + $this->filesystem->mkdir($warmupDir); file_put_contents($file = $warmupDir.'/kernel.tmp', $code); require_once $file; $class = "$namespace\\$class"; diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/CachePoolClearCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/CachePoolClearCommand.php index 3ee9f086aedbc..60c42e8729b13 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/CachePoolClearCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/CachePoolClearCommand.php @@ -25,6 +25,26 @@ */ final class CachePoolClearCommand extends ContainerAwareCommand { + private $poolClearer; + + /** + * @param Psr6CacheClearer $poolClearer + */ + public function __construct($poolClearer = null) + { + parent::__construct(); + + if (!$poolClearer instanceof Psr6CacheClearer) { + @trigger_error(sprintf('Passing a command name as the first argument of "%s" is deprecated since version 3.4 and will be removed in 4.0. If the command was registered by convention, make it a service instead.', __METHOD__), E_USER_DEPRECATED); + + $this->setName(null === $poolClearer ? 'cache:pool:clear' : $poolClearer); + + return; + } + + $this->poolClearer = $poolClearer; + } + /** * {@inheritdoc} */ @@ -50,18 +70,22 @@ protected function configure() */ protected function execute(InputInterface $input, OutputInterface $output) { + // BC to be removed in 4.0 + if (null === $this->poolClearer) { + $this->poolClearer = $this->getContainer()->get('cache.global_clearer'); + $cacheDir = $this->getContainer()->getParameter('kernel.cache_dir'); + } + $io = new SymfonyStyle($input, $output); + $kernel = $this->getApplication()->getKernel(); $pools = array(); $clearers = array(); - $container = $this->getContainer(); - $cacheDir = $container->getParameter('kernel.cache_dir'); - $globalClearer = $container->get('cache.global_clearer'); foreach ($input->getArgument('pools') as $id) { - if ($globalClearer->hasPool($id)) { + if ($this->poolClearer->hasPool($id)) { $pools[$id] = $id; } else { - $pool = $container->get($id); + $pool = $kernel->getContainer()->get($id); if ($pool instanceof CacheItemPoolInterface) { $pools[$id] = $pool; @@ -75,7 +99,7 @@ protected function execute(InputInterface $input, OutputInterface $output) foreach ($clearers as $id => $clearer) { $io->comment(sprintf('Calling cache clearer: %s', $id)); - $clearer->clear($cacheDir); + $clearer->clear(isset($cacheDir) ? $cacheDir : $kernel->getContainer()->getParameter('kernel.cache_dir')); } foreach ($pools as $id => $pool) { @@ -84,7 +108,7 @@ protected function execute(InputInterface $input, OutputInterface $output) if ($pool instanceof CacheItemPoolInterface) { $pool->clear(); } else { - $globalClearer->clearPool($id); + $this->poolClearer->clearPool($id); } } diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/CacheWarmupCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/CacheWarmupCommand.php index 1e0c4b6b3a251..0f72db83052e9 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/CacheWarmupCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/CacheWarmupCommand.php @@ -15,14 +15,37 @@ use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Style\SymfonyStyle; +use Symfony\Component\HttpKernel\CacheWarmer\CacheWarmerAggregate; /** * Warmup the cache. * * @author Fabien Potencier + * + * @final since version 3.4 */ class CacheWarmupCommand extends ContainerAwareCommand { + private $cacheWarmer; + + /** + * @param CacheWarmerAggregate $cacheWarmer + */ + public function __construct($cacheWarmer = null) + { + parent::__construct(); + + if (!$cacheWarmer instanceof CacheWarmerAggregate) { + @trigger_error(sprintf('Passing a command name as the first argument of "%s" is deprecated since version 3.4 and will be removed in 4.0. If the command was registered by convention, make it a service instead.', __METHOD__), E_USER_DEPRECATED); + + $this->setName(null === $cacheWarmer ? 'cache:warmup' : $cacheWarmer); + + return; + } + + $this->cacheWarmer = $cacheWarmer; + } + /** * {@inheritdoc} */ @@ -54,18 +77,22 @@ protected function configure() */ protected function execute(InputInterface $input, OutputInterface $output) { + // BC to be removed in 4.0 + if (null === $this->cacheWarmer) { + $this->cacheWarmer = $this->getContainer()->get('cache_warmer'); + $cacheDir = $this->getContainer()->getParameter('kernel.cache_dir'); + } + $io = new SymfonyStyle($input, $output); - $kernel = $this->getContainer()->get('kernel'); + $kernel = $this->getApplication()->getKernel(); $io->comment(sprintf('Warming up the cache for the %s environment with debug %s', $kernel->getEnvironment(), var_export($kernel->isDebug(), true))); - $warmer = $this->getContainer()->get('cache_warmer'); - if (!$input->getOption('no-optional-warmers')) { - $warmer->enableOptionalWarmers(); + $this->cacheWarmer->enableOptionalWarmers(); } - $warmer->warmUp($this->getContainer()->getParameter('kernel.cache_dir')); + $this->cacheWarmer->warmUp(isset($cacheDir) ? $cacheDir : $kernel->getContainer()->getParameter('kernel.cache_dir')); $io->success(sprintf('Cache for the "%s" environment (debug=%s) was successfully warmed.', $kernel->getEnvironment(), var_export($kernel->isDebug(), true))); } diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/ConfigDebugCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/ConfigDebugCommand.php index 924bd8e92f659..f460fd5f09a3f 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/ConfigDebugCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/ConfigDebugCommand.php @@ -23,6 +23,8 @@ * A console command for dumping available configuration reference. * * @author Grégoire Pineau + * + * @final since version 3.4 */ class ConfigDebugCommand extends AbstractConfigCommand { @@ -111,7 +113,7 @@ protected function execute(InputInterface $input, OutputInterface $output) private function compileContainer() { - $kernel = clone $this->getContainer()->get('kernel'); + $kernel = clone $this->getApplication()->getKernel(); $kernel->boot(); $method = new \ReflectionMethod($kernel, 'buildContainer'); diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/ConfigDumpReferenceCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/ConfigDumpReferenceCommand.php index 476813fc3621e..fb51f8c3fcf0c 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/ConfigDumpReferenceCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/ConfigDumpReferenceCommand.php @@ -25,6 +25,8 @@ * @author Kevin Bond * @author Wouter J * @author Grégoire Pineau + * + * @final since version 3.4 */ class ConfigDumpReferenceCommand extends AbstractConfigCommand { diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/ContainerDebugCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/ContainerDebugCommand.php index 891ca9279ed5f..51c04969877e6 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/ContainerDebugCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/ContainerDebugCommand.php @@ -27,6 +27,8 @@ * A console command for retrieving information about services. * * @author Ryan Weaver + * + * @internal since version 3.4 */ class ContainerDebugCommand extends ContainerAwareCommand { diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/EventDispatcherDebugCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/EventDispatcherDebugCommand.php index ef1c3017fca28..d2f8bd77751b5 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/EventDispatcherDebugCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/EventDispatcherDebugCommand.php @@ -23,9 +23,31 @@ * A console command for retrieving information about event dispatcher. * * @author Matthieu Auger + * + * @final since version 3.4 */ class EventDispatcherDebugCommand extends ContainerAwareCommand { + private $dispatcher; + + /** + * @param EventDispatcherInterface $dispatcher + */ + public function __construct($dispatcher = null) + { + parent::__construct(); + + if (!$dispatcher instanceof EventDispatcherInterface) { + @trigger_error(sprintf('Passing a command name as the first argument of "%s" is deprecated since version 3.4 and will be removed in 4.0. If the command was registered by convention, make it a service instead.', __METHOD__), E_USER_DEPRECATED); + + $this->setName(null === $dispatcher ? 'debug:event-dispatcher' : $dispatcher); + + return; + } + + $this->dispatcher = $dispatcher; + } + /** * {@inheritdoc} */ @@ -59,12 +81,16 @@ protected function configure() */ protected function execute(InputInterface $input, OutputInterface $output) { + // BC to be removed in 4.0 + if (null === $this->dispatcher) { + $this->dispatcher = $this->getEventDispatcher(); + } + $io = new SymfonyStyle($input, $output); - $dispatcher = $this->getEventDispatcher(); $options = array(); if ($event = $input->getArgument('event')) { - if (!$dispatcher->hasListeners($event)) { + if (!$this->dispatcher->hasListeners($event)) { $io->getErrorStyle()->warning(sprintf('The event "%s" does not have any registered listeners.', $event)); return; @@ -77,12 +103,14 @@ protected function execute(InputInterface $input, OutputInterface $output) $options['format'] = $input->getOption('format'); $options['raw_text'] = $input->getOption('raw'); $options['output'] = $io; - $helper->describe($io, $dispatcher, $options); + $helper->describe($io, $this->dispatcher, $options); } /** * Loads the Event Dispatcher from the container. * + * BC to removed in 4.0 + * * @return EventDispatcherInterface */ protected function getEventDispatcher() diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/RouterDebugCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/RouterDebugCommand.php index f26fddabb0a93..253f9a13f29a4 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/RouterDebugCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/RouterDebugCommand.php @@ -27,14 +27,41 @@ * * @author Fabien Potencier * @author Tobias Schultze + * + * @final since version 3.4 */ class RouterDebugCommand extends ContainerAwareCommand { + private $router; + + /** + * @param RouterInterface $router + */ + public function __construct($router = null) + { + parent::__construct(); + + if (!$router instanceof RouterInterface) { + @trigger_error(sprintf('Passing a command name as the first argument of "%s" is deprecated since version 3.4 and will be removed in 4.0. If the command was registered by convention, make it a service instead.', __METHOD__), E_USER_DEPRECATED); + + $this->setName(null === $router ? 'debug:router' : $router); + + return; + } + + $this->router = $router; + } + /** * {@inheritdoc} + * + * BC to be removed in 4.0 */ public function isEnabled() { + if (null !== $this->router) { + return parent::isEnabled(); + } if (!$this->getContainer()->has('router')) { return false; } @@ -77,10 +104,15 @@ protected function configure() */ protected function execute(InputInterface $input, OutputInterface $output) { + // BC to be removed in 4.0 + if (null === $this->router) { + $this->router = $this->getContainer()->get('router'); + } + $io = new SymfonyStyle($input, $output); $name = $input->getArgument('name'); $helper = new DescriptorHelper(); - $routes = $this->getContainer()->get('router')->getRouteCollection(); + $routes = $this->router->getRouteCollection(); if ($name) { if (!$route = $routes->get($name)) { @@ -132,7 +164,7 @@ private function extractCallable(Route $route) if (1 === substr_count($controller, ':')) { list($service, $method) = explode(':', $controller); try { - return sprintf('%s::%s', get_class($this->getContainer()->get($service)), $method); + return sprintf('%s::%s', get_class($this->getApplication()->getKernel()->getContainer()->get($service)), $method); } catch (ServiceNotFoundException $e) { } } diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/RouterMatchCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/RouterMatchCommand.php index 2e23ad72c2aef..c6d2bdbf990cf 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/RouterMatchCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/RouterMatchCommand.php @@ -24,14 +24,41 @@ * A console command to test route matching. * * @author Fabien Potencier + * + * @final since version 3.4 */ class RouterMatchCommand extends ContainerAwareCommand { + private $router; + + /** + * @param RouterInterface $router + */ + public function __construct($router = null) + { + parent::__construct(); + + if (!$router instanceof RouterInterface) { + @trigger_error(sprintf('Passing a command name as the first argument of "%s" is deprecated since version 3.4 and will be removed in 4.0. If the command was registered by convention, make it a service instead.', __METHOD__), E_USER_DEPRECATED); + + $this->setName(null === $router ? 'router:match' : $router); + + return; + } + + $this->router = $router; + } + /** * {@inheritdoc} + * + * BC to be removed in 4.0 */ public function isEnabled() { + if (null !== $this->router) { + return parent::isEnabled(); + } if (!$this->getContainer()->has('router')) { return false; } @@ -76,10 +103,14 @@ protected function configure() */ protected function execute(InputInterface $input, OutputInterface $output) { + // BC to be removed in 4.0 + if (null === $this->router) { + $this->router = $this->getContainer()->get('router'); + } + $io = new SymfonyStyle($input, $output); - $router = $this->getContainer()->get('router'); - $context = $router->getContext(); + $context = $this->router->getContext(); if (null !== $method = $input->getOption('method')) { $context->setMethod($method); } @@ -90,7 +121,7 @@ protected function execute(InputInterface $input, OutputInterface $output) $context->setHost($host); } - $matcher = new TraceableUrlMatcher($router->getRouteCollection(), $context); + $matcher = new TraceableUrlMatcher($this->router->getRouteCollection(), $context); $traces = $matcher->getTraces($input->getArgument('path_info')); diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/TranslationDebugCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/TranslationDebugCommand.php index 79b4234d81eb8..44730737bc8a7 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/TranslationDebugCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/TranslationDebugCommand.php @@ -17,25 +17,55 @@ use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\HttpKernel\Kernel; +use Symfony\Component\HttpKernel\KernelInterface; use Symfony\Component\Translation\Catalogue\MergeOperation; +use Symfony\Component\Translation\Extractor\ExtractorInterface; use Symfony\Component\Translation\MessageCatalogue; use Symfony\Component\Translation\Translator; use Symfony\Component\Translation\DataCollectorTranslator; use Symfony\Component\Translation\LoggingTranslator; +use Symfony\Component\Translation\TranslatorInterface; /** * Helps finding unused or missing translation messages in a given locale * and comparing them with the fallback ones. * * @author Florian Voutzinos + * + * @final since version 3.4 */ class TranslationDebugCommand extends ContainerAwareCommand { + private $translator; + private $loader; + private $extractor; + const MESSAGE_MISSING = 0; const MESSAGE_UNUSED = 1; const MESSAGE_EQUALS_FALLBACK = 2; + /** + * @param TranslatorInterface $translator + * @param TranslationLoader $loader + * @param ExtractorInterface $extractor + */ + public function __construct($translator = null, TranslationLoader $loader = null, ExtractorInterface $extractor = null) + { + parent::__construct(); + + if (!$translator instanceof TranslatorInterface) { + @trigger_error(sprintf('Passing a command name as the first argument of "%s" is deprecated since version 3.4 and will be removed in 4.0. If the command was registered by convention, make it a service instead.', __METHOD__), E_USER_DEPRECATED); + + $this->setName(null === $translator ? 'debug:translation' : $translator); + + return; + } + + $this->translator = $translator; + $this->loader = $loader; + $this->extractor = $extractor; + } + /** * {@inheritdoc} */ @@ -88,9 +118,14 @@ protected function configure() /** * {@inheritdoc} + * + * BC to be removed in 4.0 */ public function isEnabled() { + if (null !== $this->translator) { + return parent::isEnabled(); + } if (!class_exists('Symfony\Component\Translation\Translator')) { return false; } @@ -103,14 +138,19 @@ public function isEnabled() */ protected function execute(InputInterface $input, OutputInterface $output) { + // BC to be removed in 4.0 + if (null === $this->translator) { + $this->translator = $this->getContainer()->get('translator'); + $this->loader = $this->getContainer()->get('translation.loader'); + $this->extractor = $this->getContainer()->get('translation.extractor'); + } + $io = new SymfonyStyle($input, $output); $locale = $input->getArgument('locale'); $domain = $input->getOption('domain'); - /** @var TranslationLoader $loader */ - $loader = $this->getContainer()->get('translation.loader'); - /** @var Kernel $kernel */ - $kernel = $this->getContainer()->get('kernel'); + /** @var KernelInterface $kernel */ + $kernel = $this->getApplication()->getKernel(); // Define Root Path to App folder $transPaths = array($kernel->getRootDir().'/Resources/'); @@ -142,7 +182,7 @@ protected function execute(InputInterface $input, OutputInterface $output) $extractedCatalogue = $this->extractMessages($locale, $transPaths); // Load defined messages - $currentCatalogue = $this->loadCurrentMessages($locale, $transPaths, $loader); + $currentCatalogue = $this->loadCurrentMessages($locale, $transPaths); // Merge defined and extracted messages to get all message ids $mergeOperation = new MergeOperation($extractedCatalogue, $currentCatalogue); @@ -165,7 +205,7 @@ protected function execute(InputInterface $input, OutputInterface $output) } // Load the fallback catalogues - $fallbackCatalogues = $this->loadFallbackCatalogues($locale, $transPaths, $loader); + $fallbackCatalogues = $this->loadFallbackCatalogues($locale, $transPaths); // Display header line $headers = array('State', 'Domain', 'Id', sprintf('Message Preview (%s)', $locale)); @@ -271,7 +311,7 @@ private function extractMessages($locale, $transPaths) foreach ($transPaths as $path) { $path = $path.'views'; if (is_dir($path)) { - $this->getContainer()->get('translation.extractor')->extract($path, $extractedCatalogue); + $this->extractor->extract($path, $extractedCatalogue); } } @@ -279,19 +319,18 @@ private function extractMessages($locale, $transPaths) } /** - * @param string $locale - * @param array $transPaths - * @param TranslationLoader $loader + * @param string $locale + * @param array $transPaths * * @return MessageCatalogue */ - private function loadCurrentMessages($locale, $transPaths, TranslationLoader $loader) + private function loadCurrentMessages($locale, $transPaths) { $currentCatalogue = new MessageCatalogue($locale); foreach ($transPaths as $path) { $path = $path.'translations'; if (is_dir($path)) { - $loader->loadMessages($path, $currentCatalogue); + $this->loader->loadMessages($path, $currentCatalogue); } } @@ -299,18 +338,16 @@ private function loadCurrentMessages($locale, $transPaths, TranslationLoader $lo } /** - * @param string $locale - * @param array $transPaths - * @param TranslationLoader $loader + * @param string $locale + * @param array $transPaths * * @return MessageCatalogue[] */ - private function loadFallbackCatalogues($locale, $transPaths, TranslationLoader $loader) + private function loadFallbackCatalogues($locale, $transPaths) { $fallbackCatalogues = array(); - $translator = $this->getContainer()->get('translator'); - if ($translator instanceof Translator || $translator instanceof DataCollectorTranslator || $translator instanceof LoggingTranslator) { - foreach ($translator->getFallbackLocales() as $fallbackLocale) { + if ($this->translator instanceof Translator || $this->translator instanceof DataCollectorTranslator || $this->translator instanceof LoggingTranslator) { + foreach ($this->translator->getFallbackLocales() as $fallbackLocale) { if ($fallbackLocale === $locale) { continue; } @@ -319,7 +356,7 @@ private function loadFallbackCatalogues($locale, $transPaths, TranslationLoader foreach ($transPaths as $path) { $path = $path.'translations'; if (is_dir($path)) { - $loader->loadMessages($path, $fallbackCatalogue); + $this->loader->loadMessages($path, $fallbackCatalogue); } } $fallbackCatalogues[] = $fallbackCatalogue; diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/TranslationUpdateCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/TranslationUpdateCommand.php index 0d5b4fb873612..a02cb23a57547 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/TranslationUpdateCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/TranslationUpdateCommand.php @@ -11,6 +11,7 @@ namespace Symfony\Bundle\FrameworkBundle\Command; +use Symfony\Bundle\FrameworkBundle\Translation\TranslationLoader; use Symfony\Component\Console\Style\SymfonyStyle; use Symfony\Component\Translation\Catalogue\TargetOperation; use Symfony\Component\Translation\Catalogue\MergeOperation; @@ -18,16 +19,49 @@ use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Translation\Extractor\ExtractorInterface; use Symfony\Component\Translation\MessageCatalogue; +use Symfony\Component\Translation\Writer\TranslationWriter; /** * A command that parses templates to extract translation messages and adds them * into the translation files. * * @author Michel Salib + * + * @final since version 3.4 */ class TranslationUpdateCommand extends ContainerAwareCommand { + private $writer; + private $loader; + private $extractor; + private $defaultLocale; + + /** + * @param TranslationWriter $writer + * @param TranslationLoader $loader + * @param ExtractorInterface $extractor + * @param string $defaultLocale + */ + public function __construct($writer = null, TranslationLoader $loader = null, ExtractorInterface $extractor = null, $defaultLocale = null) + { + parent::__construct(); + + if (!$writer instanceof TranslationWriter) { + @trigger_error(sprintf('Passing a command name as the first argument of "%s" is deprecated since version 3.4 and will be removed in 4.0. If the command was registered by convention, make it a service instead.', __METHOD__), E_USER_DEPRECATED); + + $this->setName(null === $writer ? 'translation:update' : $writer); + + return; + } + + $this->writer = $writer; + $this->loader = $loader; + $this->extractor = $extractor; + $this->defaultLocale = $defaultLocale; + } + /** * {@inheritdoc} */ @@ -69,9 +103,14 @@ protected function configure() /** * {@inheritdoc} + * + * BC to be removed in 4.0 */ public function isEnabled() { + if (null !== $this->writer) { + return parent::isEnabled(); + } if (!class_exists('Symfony\Component\Translation\Translator')) { return false; } @@ -84,6 +123,14 @@ public function isEnabled() */ protected function execute(InputInterface $input, OutputInterface $output) { + // BC to be removed in 4.0 + if (null === $this->writer) { + $this->writer = $this->getContainer()->get('translation.writer'); + $this->loader = $this->getContainer()->get('translation.loader'); + $this->extractor = $this->getContainer()->get('translation.extractor'); + $this->defaultLocale = $this->getContainer()->getParameter('kernel.default_locale'); + } + $io = new SymfonyStyle($input, $output); $errorIo = $io->getErrorStyle(); @@ -95,14 +142,13 @@ protected function execute(InputInterface $input, OutputInterface $output) } // check format - $writer = $this->getContainer()->get('translation.writer'); - $supportedFormats = $writer->getFormats(); + $supportedFormats = $this->writer->getFormats(); if (!in_array($input->getOption('output-format'), $supportedFormats)) { $errorIo->error(array('Wrong output format', 'Supported formats are: '.implode(', ', $supportedFormats).'.')); return 1; } - $kernel = $this->getContainer()->get('kernel'); + $kernel = $this->getApplication()->getKernel(); // Define Root Path to App folder $transPaths = array($kernel->getRootDir().'/Resources/'); @@ -134,29 +180,27 @@ protected function execute(InputInterface $input, OutputInterface $output) // load any messages from templates $extractedCatalogue = new MessageCatalogue($input->getArgument('locale')); $errorIo->comment('Parsing templates...'); - $extractor = $this->getContainer()->get('translation.extractor'); $prefix = $input->getOption('prefix'); // @deprecated since version 3.4, to be removed in 4.0 along with the --no-prefix option if ($input->getOption('no-prefix')) { @trigger_error('The "--no-prefix" option is deprecated since version 3.4 and will be removed in 4.0. Use the "--prefix" option with an empty string as value instead.', E_USER_DEPRECATED); $prefix = ''; } - $extractor->setPrefix($prefix); + $this->extractor->setPrefix($prefix); foreach ($transPaths as $path) { $path .= 'views'; if (is_dir($path)) { - $extractor->extract($path, $extractedCatalogue); + $this->extractor->extract($path, $extractedCatalogue); } } // load any existing messages from the translation files $currentCatalogue = new MessageCatalogue($input->getArgument('locale')); $errorIo->comment('Loading translation files...'); - $loader = $this->getContainer()->get('translation.loader'); foreach ($transPaths as $path) { $path .= 'translations'; if (is_dir($path)) { - $loader->loadMessages($path, $currentCatalogue); + $this->loader->loadMessages($path, $currentCatalogue); } } @@ -213,7 +257,7 @@ protected function execute(InputInterface $input, OutputInterface $output) } if ($input->getOption('no-backup') === true) { - $writer->disableBackup(); + $this->writer->disableBackup(); } // save the files @@ -232,7 +276,7 @@ protected function execute(InputInterface $input, OutputInterface $output) $bundleTransPath = end($transPaths).'translations'; } - $writer->writeTranslations($operation->getResult(), $input->getOption('output-format'), array('path' => $bundleTransPath, 'default_locale' => $this->getContainer()->getParameter('kernel.default_locale'))); + $this->writer->writeTranslations($operation->getResult(), $input->getOption('output-format'), array('path' => $bundleTransPath, 'default_locale' => $this->defaultLocale)); if (true === $input->getOption('dump-messages')) { $resultMessage .= ' and translation files were updated'; diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/WorkflowDumpCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/WorkflowDumpCommand.php index 0287f42a8ed4d..27e0f645d8fdf 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/WorkflowDumpCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/WorkflowDumpCommand.php @@ -20,9 +20,16 @@ /** * @author Grégoire Pineau + * + * @final since version 3.4 */ class WorkflowDumpCommand extends ContainerAwareCommand { + /** + * {@inheritdoc} + * + * BC to be removed in 4.0 + */ public function isEnabled() { return $this->getContainer()->has('workflow.registry'); @@ -56,7 +63,7 @@ protected function configure() */ protected function execute(InputInterface $input, OutputInterface $output) { - $container = $this->getContainer(); + $container = $this->getApplication()->getKernel()->getContainer(); $serviceId = $input->getArgument('name'); if ($container->has('workflow.'.$serviceId)) { $workflow = $container->get('workflow.'.$serviceId); diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/XliffLintCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/XliffLintCommand.php index dcc3eb3abe2d5..8f4739a9f8e80 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/XliffLintCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/XliffLintCommand.php @@ -22,6 +22,8 @@ * @author Grégoire Pineau * @author Robin Chalas * @author Javier Eguiluz + * + * @final since version 3.4 */ class XliffLintCommand extends Command { diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/YamlLintCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/YamlLintCommand.php index 41551acc3dc7a..6e8f7dbfaeab8 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/YamlLintCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/YamlLintCommand.php @@ -21,6 +21,8 @@ * * @author Grégoire Pineau * @author Robin Chalas + * + * @final since version 3.4 */ class YamlLintCommand extends Command { diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php index a3c92a026be52..52ad0b1f1f479 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php @@ -13,6 +13,11 @@ use Doctrine\Common\Annotations\Reader; use Symfony\Bridge\Monolog\Processor\DebugProcessor; +use Symfony\Bundle\FrameworkBundle\Command\RouterDebugCommand; +use Symfony\Bundle\FrameworkBundle\Command\RouterMatchCommand; +use Symfony\Bundle\FrameworkBundle\Command\TranslationDebugCommand; +use Symfony\Bundle\FrameworkBundle\Command\TranslationUpdateCommand; +use Symfony\Bundle\FrameworkBundle\Command\WorkflowDumpCommand; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Bundle\FrameworkBundle\Controller\Controller; use Symfony\Bundle\FrameworkBundle\Routing\AnnotatedRouteControllerLoader; @@ -231,11 +236,7 @@ public function load(array $configs, ContainerBuilder $container) $this->registerCacheConfiguration($config['cache'], $container); $this->registerWorkflowConfiguration($config['workflows'], $container, $loader); $this->registerDebugConfiguration($config['php_errors'], $container, $loader); - - if ($this->isConfigEnabled($container, $config['router'])) { - $this->registerRouterConfiguration($config['router'], $container, $loader); - } - + $this->registerRouterConfiguration($config['router'], $container, $loader); $this->registerAnnotationsConfiguration($config['annotations'], $container, $loader); $this->registerPropertyAccessConfiguration($config['property_access'], $container); @@ -519,6 +520,10 @@ private function registerProfilerConfiguration(array $config, ContainerBuilder $ private function registerWorkflowConfiguration(array $workflows, ContainerBuilder $container, XmlFileLoader $loader) { if (!$workflows) { + if (!class_exists(Workflow\Workflow::class)) { + $container->removeDefinition(WorkflowDumpCommand::class); + } + return; } @@ -695,6 +700,13 @@ private function registerDebugConfiguration(array $config, ContainerBuilder $con */ private function registerRouterConfiguration(array $config, ContainerBuilder $container, XmlFileLoader $loader) { + if (!$this->isConfigEnabled($container, $config)) { + $container->removeDefinition(RouterDebugCommand::class); + $container->removeDefinition(RouterMatchCommand::class); + + return; + } + $loader->load('routing.xml'); $container->setParameter('router.resource', $config['resource']); @@ -1028,6 +1040,9 @@ private function createVersion(ContainerBuilder $container, $version, $format, $ private function registerTranslatorConfiguration(array $config, ContainerBuilder $container, LoaderInterface $loader) { if (!$this->isConfigEnabled($container, $config)) { + $container->removeDefinition(TranslationDebugCommand::class); + $container->removeDefinition(TranslationUpdateCommand::class); + return; } diff --git a/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php b/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php index 63017892a73ef..87e5004804424 100644 --- a/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php +++ b/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php @@ -25,6 +25,7 @@ use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\ContainerBuilderDebugDumpPass; use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\UnusedTagsPass; use Symfony\Component\Config\DependencyInjection\ConfigCachePass; +use Symfony\Component\Console\Application; use Symfony\Component\Console\DependencyInjection\AddConsoleCommandPass; use Symfony\Component\HttpKernel\DependencyInjection\AddCacheClearerPass; use Symfony\Component\HttpKernel\DependencyInjection\AddCacheWarmerPass; @@ -129,4 +130,9 @@ private function addCompilerPassIfExists(ContainerBuilder $container, $class, $t $container->addCompilerPass(new $class(), $type, $priority); } } + + public function registerCommands(Application $application) + { + // noop + } } diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/cache.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/cache.xml index 182d07e6b3faf..e0d5788bc4879 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/cache.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/cache.xml @@ -100,11 +100,6 @@ - - - - - diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/console.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/console.xml index 3d9bd1b2489c5..4bdaa85fee4c3 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/console.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/console.xml @@ -12,5 +12,89 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + %kernel.default_locale% + + + + + + + + + + + + + + diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/RouterDebugCommandTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/RouterDebugCommandTest.php index ab96721edd260..c201fe9db7248 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/RouterDebugCommandTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/RouterDebugCommandTest.php @@ -47,20 +47,34 @@ public function testDebugInvalidRoute() $this->createCommandTester()->execute(array('name' => 'test')); } + /** + * @group legacy + * @expectedDeprecation Passing a command name as the first argument of "Symfony\Bundle\FrameworkBundle\Command\RouterDebugCommand::__construct" is deprecated since version 3.4 and will be removed in 4.0. If the command was registered by convention, make it a service instead. + */ + public function testLegacyDebugCommand() + { + $application = new Application($this->getKernel()); + $application->add(new RouterDebugCommand()); + + $tester = new CommandTester($application->find('debug:router')); + + $tester->execute(array()); + + $this->assertRegExp('/foo\s+ANY\s+ANY\s+ANY\s+\\/foo/', $tester->getDisplay()); + } + /** * @return CommandTester */ private function createCommandTester() { $application = new Application($this->getKernel()); - - $command = new RouterDebugCommand(); - $application->add($command); + $application->add(new RouterDebugCommand($this->getRouter())); return new CommandTester($application->find('debug:router')); } - private function getKernel() + private function getRouter() { $routeCollection = new RouteCollection(); $routeCollection->add('foo', new Route('foo')); @@ -68,9 +82,13 @@ private function getKernel() $router ->expects($this->any()) ->method('getRouteCollection') - ->will($this->returnValue($routeCollection)) - ; + ->will($this->returnValue($routeCollection)); + return $router; + } + + private function getKernel() + { $container = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerInterface')->getMock(); $container ->expects($this->atLeastOnce()) @@ -87,7 +105,7 @@ private function getKernel() ->expects($this->any()) ->method('get') ->with('router') - ->willReturn($router) + ->willReturn($this->getRouter()) ; $kernel = $this->getMockBuilder(KernelInterface::class)->getMock(); diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/RouterMatchCommandTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/RouterMatchCommandTest.php index 4e3bcefc58651..2570d41d78745 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/RouterMatchCommandTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/RouterMatchCommandTest.php @@ -42,18 +42,36 @@ public function testWithNotMatchPath() } /** - * @return CommandTester + * @group legacy + * @expectedDeprecation Passing a command name as the first argument of "Symfony\Bundle\FrameworkBundle\Command\RouterMatchCommand::__construct" is deprecated since version 3.4 and will be removed in 4.0. If the command was registered by convention, make it a service instead. + * @expectedDeprecation Passing a command name as the first argument of "Symfony\Bundle\FrameworkBundle\Command\RouterDebugCommand::__construct" is deprecated since version 3.4 and will be removed in 4.0. If the command was registered by convention, make it a service instead. */ - private function createCommandTester() + public function testLegacyMatchCommand() { $application = new Application($this->getKernel()); $application->add(new RouterMatchCommand()); $application->add(new RouterDebugCommand()); + $tester = new CommandTester($application->find('router:match')); + + $tester->execute(array('path_info' => '/')); + + $this->assertContains('None of the routes match the path "/"', $tester->getDisplay()); + } + + /** + * @return CommandTester + */ + private function createCommandTester() + { + $application = new Application($this->getKernel()); + $application->add(new RouterMatchCommand($this->getRouter())); + $application->add(new RouterDebugCommand($this->getRouter())); + return new CommandTester($application->find('router:match')); } - private function getKernel() + private function getRouter() { $routeCollection = new RouteCollection(); $routeCollection->add('foo', new Route('foo')); @@ -62,14 +80,17 @@ private function getKernel() $router ->expects($this->any()) ->method('getRouteCollection') - ->will($this->returnValue($routeCollection)) - ; + ->will($this->returnValue($routeCollection)); $router ->expects($this->any()) ->method('getContext') - ->will($this->returnValue($requestContext)) - ; + ->will($this->returnValue($requestContext)); + return $router; + } + + private function getKernel() + { $container = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerInterface')->getMock(); $container ->expects($this->atLeastOnce()) @@ -85,7 +106,9 @@ private function getKernel() $container ->expects($this->any()) ->method('get') - ->willReturn($router); + ->with('router') + ->willReturn($this->getRouter()) + ; $kernel = $this->getMockBuilder(KernelInterface::class)->getMock(); $kernel diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/TranslationDebugCommandTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/TranslationDebugCommandTest.php index 19c6d70156b19..edf006c86801c 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/TranslationDebugCommandTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/TranslationDebugCommandTest.php @@ -12,7 +12,7 @@ namespace Symfony\Bundle\FrameworkBundle\Tests\Command; use PHPUnit\Framework\TestCase; -use Symfony\Component\Console\Application; +use Symfony\Bundle\FrameworkBundle\Console\Application; use Symfony\Component\Console\Tester\CommandTester; use Symfony\Bundle\FrameworkBundle\Command\TranslationDebugCommand; use Symfony\Component\Filesystem\Filesystem; @@ -24,7 +24,7 @@ class TranslationDebugCommandTest extends TestCase public function testDebugMissingMessages() { - $tester = $this->createCommandTester($this->getContainer(array('foo' => 'foo'))); + $tester = $this->createCommandTester(array('foo' => 'foo')); $tester->execute(array('locale' => 'en', 'bundle' => 'foo')); $this->assertRegExp('/missing/', $tester->getDisplay()); @@ -32,7 +32,7 @@ public function testDebugMissingMessages() public function testDebugUnusedMessages() { - $tester = $this->createCommandTester($this->getContainer(array(), array('foo' => 'foo'))); + $tester = $this->createCommandTester(array(), array('foo' => 'foo')); $tester->execute(array('locale' => 'en', 'bundle' => 'foo')); $this->assertRegExp('/unused/', $tester->getDisplay()); @@ -40,7 +40,7 @@ public function testDebugUnusedMessages() public function testDebugFallbackMessages() { - $tester = $this->createCommandTester($this->getContainer(array(), array('foo' => 'foo'))); + $tester = $this->createCommandTester(array(), array('foo' => 'foo')); $tester->execute(array('locale' => 'fr', 'bundle' => 'foo')); $this->assertRegExp('/fallback/', $tester->getDisplay()); @@ -48,7 +48,7 @@ public function testDebugFallbackMessages() public function testNoDefinedMessages() { - $tester = $this->createCommandTester($this->getContainer()); + $tester = $this->createCommandTester(); $tester->execute(array('locale' => 'fr', 'bundle' => 'test')); $this->assertRegExp('/No defined or extracted messages for locale "fr"/', $tester->getDisplay()); @@ -56,7 +56,7 @@ public function testNoDefinedMessages() public function testDebugDefaultDirectory() { - $tester = $this->createCommandTester($this->getContainer(array('foo' => 'foo'), array('bar' => 'bar'))); + $tester = $this->createCommandTester(array('foo' => 'foo'), array('bar' => 'bar')); $tester->execute(array('locale' => 'en')); $this->assertRegExp('/missing/', $tester->getDisplay()); @@ -71,7 +71,7 @@ public function testDebugCustomDirectory() ->with($this->equalTo($this->translationDir)) ->willThrowException(new \InvalidArgumentException()); - $tester = $this->createCommandTester($this->getContainer(array('foo' => 'foo'), array('bar' => 'bar'), $kernel)); + $tester = $this->createCommandTester(array('foo' => 'foo'), array('bar' => 'bar'), $kernel); $tester->execute(array('locale' => 'en', 'bundle' => $this->translationDir)); $this->assertRegExp('/missing/', $tester->getDisplay()); @@ -89,7 +89,7 @@ public function testDebugInvalidDirectory() ->with($this->equalTo('dir')) ->will($this->throwException(new \InvalidArgumentException())); - $tester = $this->createCommandTester($this->getContainer(array(), array(), $kernel)); + $tester = $this->createCommandTester(array(), array(), $kernel); $tester->execute(array('locale' => 'en', 'bundle' => 'dir')); } @@ -109,18 +109,7 @@ protected function tearDown() /** * @return CommandTester */ - private function createCommandTester($container) - { - $command = new TranslationDebugCommand(); - $command->setContainer($container); - - $application = new Application(); - $application->add($command); - - return new CommandTester($application->find('debug:translation')); - } - - private function getContainer($extractedMessages = array(), $loadedMessages = array(), $kernel = null) + private function createCommandTester($extractedMessages = array(), $loadedMessages = array(), $kernel = null) { $translator = $this->getMockBuilder('Symfony\Component\Translation\Translator') ->disableOriginalConstructor() @@ -167,6 +156,41 @@ private function getContainer($extractedMessages = array(), $loadedMessages = ar ->method('getRootDir') ->will($this->returnValue($this->translationDir)); + $kernel + ->expects($this->any()) + ->method('getBundles') + ->will($this->returnValue(array())); + + $kernel + ->expects($this->any()) + ->method('getContainer') + ->will($this->returnValue($this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerInterface')->getMock())); + + $command = new TranslationDebugCommand($translator, $loader, $extractor); + + $application = new Application($kernel); + $application->add($command); + + return new CommandTester($application->find('debug:translation')); + } + + /** + * @group legacy + * @expectedDeprecation Passing a command name as the first argument of "Symfony\Bundle\FrameworkBundle\Command\TranslationDebugCommand::__construct" is deprecated since version 3.4 and will be removed in 4.0. If the command was registered by convention, make it a service instead. + */ + public function testLegacyDebugCommand() + { + $translator = $this->getMockBuilder('Symfony\Component\Translation\Translator') + ->disableOriginalConstructor() + ->getMock(); + $extractor = $this->getMockBuilder('Symfony\Component\Translation\Extractor\ExtractorInterface')->getMock(); + $loader = $this->getMockBuilder('Symfony\Bundle\FrameworkBundle\Translation\TranslationLoader')->getMock(); + $kernel = $this->getMockBuilder('Symfony\Component\HttpKernel\KernelInterface')->getMock(); + $kernel + ->expects($this->any()) + ->method('getBundles') + ->will($this->returnValue(array())); + $container = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerInterface')->getMock(); $container ->expects($this->any()) @@ -178,7 +202,21 @@ private function getContainer($extractedMessages = array(), $loadedMessages = ar array('kernel', 1, $kernel), ))); - return $container; + $kernel + ->expects($this->any()) + ->method('getContainer') + ->will($this->returnValue($container)); + + $command = new TranslationDebugCommand(); + $command->setContainer($container); + + $application = new Application($kernel); + $application->add($command); + + $tester = new CommandTester($application->find('debug:translation')); + $tester->execute(array('locale' => 'en')); + + $this->assertContains('No defined or extracted', $tester->getDisplay()); } private function getBundle($path) diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/TranslationUpdateCommandTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/TranslationUpdateCommandTest.php index e845619d9a826..db61398b26d9a 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/TranslationUpdateCommandTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/TranslationUpdateCommandTest.php @@ -12,11 +12,10 @@ namespace Symfony\Bundle\FrameworkBundle\Tests\Command; use PHPUnit\Framework\TestCase; -use Symfony\Component\Console\Application; +use Symfony\Bundle\FrameworkBundle\Console\Application; use Symfony\Component\Console\Tester\CommandTester; use Symfony\Bundle\FrameworkBundle\Command\TranslationUpdateCommand; use Symfony\Component\Filesystem\Filesystem; -use Symfony\Component\DependencyInjection; use Symfony\Component\HttpKernel; class TranslationUpdateCommandTest extends TestCase @@ -26,7 +25,7 @@ class TranslationUpdateCommandTest extends TestCase public function testDumpMessagesAndClean() { - $tester = $this->createCommandTester($this->getContainer(array('messages' => array('foo' => 'foo')))); + $tester = $this->createCommandTester(array('messages' => array('foo' => 'foo'))); $tester->execute(array('command' => 'translation:update', 'locale' => 'en', 'bundle' => 'foo', '--dump-messages' => true, '--clean' => true)); $this->assertRegExp('/foo/', $tester->getDisplay()); $this->assertRegExp('/1 message was successfully extracted/', $tester->getDisplay()); @@ -34,7 +33,7 @@ public function testDumpMessagesAndClean() public function testDumpTwoMessagesAndClean() { - $tester = $this->createCommandTester($this->getContainer(array('messages' => array('foo' => 'foo', 'bar' => 'bar')))); + $tester = $this->createCommandTester(array('messages' => array('foo' => 'foo', 'bar' => 'bar'))); $tester->execute(array('command' => 'translation:update', 'locale' => 'en', 'bundle' => 'foo', '--dump-messages' => true, '--clean' => true)); $this->assertRegExp('/foo/', $tester->getDisplay()); $this->assertRegExp('/bar/', $tester->getDisplay()); @@ -43,7 +42,7 @@ public function testDumpTwoMessagesAndClean() public function testDumpMessagesForSpecificDomain() { - $tester = $this->createCommandTester($this->getContainer(array('messages' => array('foo' => 'foo'), 'mydomain' => array('bar' => 'bar')))); + $tester = $this->createCommandTester(array('messages' => array('foo' => 'foo'), 'mydomain' => array('bar' => 'bar'))); $tester->execute(array('command' => 'translation:update', 'locale' => 'en', 'bundle' => 'foo', '--dump-messages' => true, '--clean' => true, '--domain' => 'mydomain')); $this->assertRegExp('/bar/', $tester->getDisplay()); $this->assertRegExp('/1 message was successfully extracted/', $tester->getDisplay()); @@ -51,14 +50,14 @@ public function testDumpMessagesForSpecificDomain() public function testWriteMessages() { - $tester = $this->createCommandTester($this->getContainer(array('messages' => array('foo' => 'foo')))); + $tester = $this->createCommandTester(array('messages' => array('foo' => 'foo'))); $tester->execute(array('command' => 'translation:update', 'locale' => 'en', 'bundle' => 'foo', '--force' => true)); $this->assertRegExp('/Translation files were successfully updated./', $tester->getDisplay()); } public function testWriteMessagesForSpecificDomain() { - $tester = $this->createCommandTester($this->getContainer(array('messages' => array('foo' => 'foo'), 'mydomain' => array('bar' => 'bar')))); + $tester = $this->createCommandTester(array('messages' => array('foo' => 'foo'), 'mydomain' => array('bar' => 'bar'))); $tester->execute(array('command' => 'translation:update', 'locale' => 'en', 'bundle' => 'foo', '--force' => true, '--domain' => 'mydomain')); $this->assertRegExp('/Translation files were successfully updated./', $tester->getDisplay()); } @@ -79,18 +78,7 @@ protected function tearDown() /** * @return CommandTester */ - private function createCommandTester(DependencyInjection\ContainerInterface $container) - { - $command = new TranslationUpdateCommand(); - $command->setContainer($container); - - $application = new Application(); - $application->add($command); - - return new CommandTester($application->find('translation:update')); - } - - private function getContainer($extractedMessages = array(), $loadedMessages = array(), HttpKernel\KernelInterface $kernel = null) + private function createCommandTester($extractedMessages = array(), $loadedMessages = array(), HttpKernel\KernelInterface $kernel = null) { $translator = $this->getMockBuilder('Symfony\Component\Translation\Translator') ->disableOriginalConstructor() @@ -147,6 +135,42 @@ private function getContainer($extractedMessages = array(), $loadedMessages = ar ->method('getRootDir') ->will($this->returnValue($this->translationDir)); + $kernel + ->expects($this->any()) + ->method('getBundles') + ->will($this->returnValue(array())); + + $kernel + ->expects($this->any()) + ->method('getContainer') + ->will($this->returnValue($this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerInterface')->getMock())); + + $command = new TranslationUpdateCommand($writer, $loader, $extractor, 'en'); + + $application = new Application($kernel); + $application->add($command); + + return new CommandTester($application->find('translation:update')); + } + + /** + * @group legacy + * @expectedDeprecation Passing a command name as the first argument of "Symfony\Bundle\FrameworkBundle\Command\TranslationUpdateCommand::__construct" is deprecated since version 3.4 and will be removed in 4.0. If the command was registered by convention, make it a service instead. + */ + public function testLegacyUpdateCommand() + { + $translator = $this->getMockBuilder('Symfony\Component\Translation\Translator') + ->disableOriginalConstructor() + ->getMock(); + $extractor = $this->getMockBuilder('Symfony\Component\Translation\Extractor\ExtractorInterface')->getMock(); + $loader = $this->getMockBuilder('Symfony\Bundle\FrameworkBundle\Translation\TranslationLoader')->getMock(); + $writer = $this->getMockBuilder('Symfony\Component\Translation\Writer\TranslationWriter')->getMock(); + $kernel = $this->getMockBuilder('Symfony\Component\HttpKernel\KernelInterface')->getMock(); + $kernel + ->expects($this->any()) + ->method('getBundles') + ->will($this->returnValue(array())); + $container = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerInterface')->getMock(); $container ->expects($this->any()) @@ -159,7 +183,21 @@ private function getContainer($extractedMessages = array(), $loadedMessages = ar array('kernel', 1, $kernel), ))); - return $container; + $kernel + ->expects($this->any()) + ->method('getContainer') + ->will($this->returnValue($container)); + + $command = new TranslationUpdateCommand(); + $command->setContainer($container); + + $application = new Application($kernel); + $application->add($command); + + $tester = new CommandTester($application->find('translation:update')); + $tester->execute(array('locale' => 'en')); + + $this->assertContains('You must choose one of --force or --dump-messages', $tester->getDisplay()); } private function getBundle($path) diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php index 10fbdbf5363c8..d1ca76f25a4dd 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php @@ -977,6 +977,7 @@ protected function createContainer(array $data = array()) 'kernel.bundles' => array('FrameworkBundle' => 'Symfony\\Bundle\\FrameworkBundle\\FrameworkBundle'), 'kernel.bundles_metadata' => array('FrameworkBundle' => array('namespace' => 'Symfony\\Bundle\\FrameworkBundle', 'path' => __DIR__.'/../..', 'parent' => null)), 'kernel.cache_dir' => __DIR__, + 'kernel.project_dir' => __DIR__, 'kernel.debug' => false, 'kernel.environment' => 'test', 'kernel.name' => 'kernel', diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/CachePoolClearCommandTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/CachePoolClearCommandTest.php index c4ea8e3974e51..9a2d198a72ba2 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/CachePoolClearCommandTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/CachePoolClearCommandTest.php @@ -12,6 +12,7 @@ namespace Symfony\Bundle\FrameworkBundle\Tests\Functional; use Symfony\Bundle\FrameworkBundle\Command\CachePoolClearCommand; +use Symfony\Bundle\FrameworkBundle\Console\Application; use Symfony\Component\Console\Tester\CommandTester; /** @@ -74,11 +75,28 @@ public function testClearUnexistingPool() ->execute(array('pools' => array('unknown_pool')), array('decorated' => false)); } + /** + * @group legacy + * @expectedDeprecation Passing a command name as the first argument of "Symfony\Bundle\FrameworkBundle\Command\CachePoolClearCommand::__construct" is deprecated since version 3.4 and will be removed in 4.0. If the command was registered by convention, make it a service instead. + */ + public function testLegacyClearCommand() + { + $application = new Application(static::$kernel); + $application->add(new CachePoolClearCommand()); + + $tester = new CommandTester($application->find('cache:pool:clear')); + + $tester->execute(array('pools' => array())); + + $this->assertContains('Cache was successfully cleared', $tester->getDisplay()); + } + private function createCommandTester() { - $command = new CachePoolClearCommand(); - $command->setContainer(static::$kernel->getContainer()); + $container = static::$kernel->getContainer(); + $application = new Application(static::$kernel); + $application->add(new CachePoolClearCommand($container->get('cache.global_clearer'))); - return new CommandTester($command); + return new CommandTester($application->find('cache:pool:clear')); } } diff --git a/src/Symfony/Bundle/SecurityBundle/Command/InitAclCommand.php b/src/Symfony/Bundle/SecurityBundle/Command/InitAclCommand.php index e12859661298b..1512e910c9744 100644 --- a/src/Symfony/Bundle/SecurityBundle/Command/InitAclCommand.php +++ b/src/Symfony/Bundle/SecurityBundle/Command/InitAclCommand.php @@ -20,6 +20,8 @@ * Installs the tables required by the ACL system. * * @author Johannes M. Schmitt + * + * @final since version 3.4 */ class InitAclCommand extends ContainerAwareCommand { diff --git a/src/Symfony/Bundle/SecurityBundle/Command/SetAclCommand.php b/src/Symfony/Bundle/SecurityBundle/Command/SetAclCommand.php index ba34782346275..7d0146fdc63de 100644 --- a/src/Symfony/Bundle/SecurityBundle/Command/SetAclCommand.php +++ b/src/Symfony/Bundle/SecurityBundle/Command/SetAclCommand.php @@ -27,6 +27,8 @@ * Sets ACL for objects. * * @author Kévin Dunglas + * + * @final since version 3.4 */ class SetAclCommand extends ContainerAwareCommand { diff --git a/src/Symfony/Bundle/SecurityBundle/Command/UserPasswordEncoderCommand.php b/src/Symfony/Bundle/SecurityBundle/Command/UserPasswordEncoderCommand.php index 2e1fc2ef50103..1f6a5d3c6213b 100644 --- a/src/Symfony/Bundle/SecurityBundle/Command/UserPasswordEncoderCommand.php +++ b/src/Symfony/Bundle/SecurityBundle/Command/UserPasswordEncoderCommand.php @@ -28,6 +28,8 @@ * Encode a user's password. * * @author Sarah Khalil + * + * @final since version 3.4 */ class UserPasswordEncoderCommand extends ContainerAwareCommand { @@ -46,18 +48,6 @@ public function __construct(EncoderFactoryInterface $encoderFactory = null, arra parent::__construct(); } - /** - * {@inheritdoc} - * - * @deprecated since version 3.3, to be removed in 4.0 - */ - protected function getContainer() - { - @trigger_error(sprintf('Method "%s" is deprecated since version 3.3 and "%s" won\'t extend "%s" nor implement "%s" anymore in 4.0.', __METHOD__, __CLASS__, ContainerAwareCommand::class, ContainerAwareInterface::class), E_USER_DEPRECATED); - - return parent::getContainer(); - } - /** * {@inheritdoc} */ @@ -125,7 +115,7 @@ protected function execute(InputInterface $input, OutputInterface $output) $userClass = $this->getUserClass($input, $io); $emptySalt = $input->getOption('empty-salt'); - $encoderFactory = $this->encoderFactory ?: parent::getContainer()->get('security.encoder_factory'); + $encoderFactory = $this->encoderFactory ?: $this->getContainer()->get('security.encoder_factory'); $encoder = $encoderFactory->getEncoder($userClass); $bcryptWithoutEmptySalt = !$emptySalt && $encoder instanceof BCryptPasswordEncoder; diff --git a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php index 226b197a5a15c..ce458de696fac 100644 --- a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php +++ b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php @@ -11,6 +11,7 @@ namespace Symfony\Bundle\SecurityBundle\DependencyInjection; +use Symfony\Bundle\SecurityBundle\Command\UserPasswordEncoderCommand; use Symfony\Bundle\SecurityBundle\DependencyInjection\Security\Factory\SecurityFactoryInterface; use Symfony\Bundle\SecurityBundle\DependencyInjection\Security\UserProvider\UserProviderFactoryInterface; use Symfony\Component\Config\Definition\Exception\InvalidConfigurationException; @@ -107,7 +108,7 @@ public function load(array $configs, ContainerBuilder $container) if (class_exists(Application::class)) { $loader->load('console.xml'); - $container->getDefinition('security.console.user_password_encoder_command')->replaceArgument(1, array_keys($config['encoders'])); + $container->getDefinition(UserPasswordEncoderCommand::class)->replaceArgument(1, array_keys($config['encoders'])); } // load ACL diff --git a/src/Symfony/Bundle/SecurityBundle/Resources/config/console.xml b/src/Symfony/Bundle/SecurityBundle/Resources/config/console.xml index c94c00f75488f..f14b4a5a350dc 100644 --- a/src/Symfony/Bundle/SecurityBundle/Resources/config/console.xml +++ b/src/Symfony/Bundle/SecurityBundle/Resources/config/console.xml @@ -7,7 +7,15 @@ - + + + + + + + + + diff --git a/src/Symfony/Bundle/SecurityBundle/SecurityBundle.php b/src/Symfony/Bundle/SecurityBundle/SecurityBundle.php index c50aab24e12e4..3b8f6dda85580 100644 --- a/src/Symfony/Bundle/SecurityBundle/SecurityBundle.php +++ b/src/Symfony/Bundle/SecurityBundle/SecurityBundle.php @@ -12,6 +12,7 @@ namespace Symfony\Bundle\SecurityBundle; use Symfony\Bundle\SecurityBundle\DependencyInjection\Security\Factory\JsonLoginFactory; +use Symfony\Component\Console\Application; use Symfony\Component\HttpKernel\Bundle\Bundle; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Bundle\SecurityBundle\DependencyInjection\Compiler\AddSecurityVotersPass; @@ -58,4 +59,9 @@ public function build(ContainerBuilder $container) $extension->addUserProviderFactory(new LdapFactory()); $container->addCompilerPass(new AddSecurityVotersPass()); } + + public function registerCommands(Application $application) + { + // noop + } } diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/CompleteConfigurationTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/CompleteConfigurationTest.php index 6bfe37efd777d..d48b16b4af4de 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/CompleteConfigurationTest.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/CompleteConfigurationTest.php @@ -12,6 +12,7 @@ namespace Symfony\Bundle\SecurityBundle\Tests\DependencyInjection; use PHPUnit\Framework\TestCase; +use Symfony\Bundle\SecurityBundle\Command\UserPasswordEncoderCommand; use Symfony\Component\DependencyInjection\Argument\IteratorArgument; use Symfony\Component\DependencyInjection\Reference; use Symfony\Bundle\SecurityBundle\SecurityBundle; @@ -355,7 +356,7 @@ public function testUserCheckerConfigWithNoCheckers() public function testUserPasswordEncoderCommandIsRegistered() { - $this->assertTrue($this->getContainer('remember_me_options')->has('security.console.user_password_encoder_command')); + $this->assertTrue($this->getContainer('remember_me_options')->has(UserPasswordEncoderCommand::class)); } public function testDefaultAccessDecisionManagerStrategyIsAffirmative() diff --git a/src/Symfony/Bundle/TwigBundle/Resources/config/console.xml b/src/Symfony/Bundle/TwigBundle/Resources/config/console.xml index 92347d699c1b1..a8997823749fe 100644 --- a/src/Symfony/Bundle/TwigBundle/Resources/config/console.xml +++ b/src/Symfony/Bundle/TwigBundle/Resources/config/console.xml @@ -7,19 +7,14 @@ - + - + - - - - The "%service_id%" service is deprecated since Symfony 3.4 and will be removed in 4.0. Use "twig.command.debug" instead. - diff --git a/src/Symfony/Bundle/TwigBundle/TwigBundle.php b/src/Symfony/Bundle/TwigBundle/TwigBundle.php index 76d0676409b88..21a39a12373a9 100644 --- a/src/Symfony/Bundle/TwigBundle/TwigBundle.php +++ b/src/Symfony/Bundle/TwigBundle/TwigBundle.php @@ -11,6 +11,7 @@ namespace Symfony\Bundle\TwigBundle; +use Symfony\Component\Console\Application; use Symfony\Component\HttpKernel\Bundle\Bundle; use Symfony\Component\DependencyInjection\Compiler\PassConfig; use Symfony\Component\DependencyInjection\ContainerBuilder; @@ -37,4 +38,9 @@ public function build(ContainerBuilder $container) $container->addCompilerPass(new ExceptionListenerPass()); $container->addCompilerPass(new RuntimeLoaderPass(), PassConfig::TYPE_BEFORE_REMOVING); } + + public function registerCommands(Application $application) + { + // noop + } } From f6c83cf51877151f7eb1ad491f1fb7458733dc27 Mon Sep 17 00:00:00 2001 From: Maxime Steinhausser Date: Sun, 6 Aug 2017 13:40:38 +0200 Subject: [PATCH 0577/1099] [Security] Fix security.interactive_login event const doc block --- src/Symfony/Component/Security/Http/SecurityEvents.php | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/Security/Http/SecurityEvents.php b/src/Symfony/Component/Security/Http/SecurityEvents.php index 46c8257f18e74..3bd80723d1ef5 100644 --- a/src/Symfony/Component/Security/Http/SecurityEvents.php +++ b/src/Symfony/Component/Security/Http/SecurityEvents.php @@ -14,8 +14,11 @@ final class SecurityEvents { /** - * The INTERACTIVE_LOGIN event occurs after a user is logged in - * interactively for authentication based on http, cookies or X509. + * The INTERACTIVE_LOGIN event occurs after a user has actively logged + * into your website. It is important to distinguish this action from + * non-interactive authentication methods, such as: + * - authentication based on your session. + * - authentication using a HTTP basic or HTTP digest header. * * The event listener method receives a * Symfony\Component\Security\Http\Event\InteractiveLoginEvent instance. From e0a601092b71ce30383b78a2189eee340ff3d6e2 Mon Sep 17 00:00:00 2001 From: Maxime Steinhausser Date: Sun, 6 Aug 2017 14:00:34 +0200 Subject: [PATCH 0578/1099] [HttpKernel] Remove isset call used for legacy --- .../Component/HttpKernel/EventListener/ProfilerListener.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Symfony/Component/HttpKernel/EventListener/ProfilerListener.php b/src/Symfony/Component/HttpKernel/EventListener/ProfilerListener.php index c3772b688e548..4fea1168aa47f 100644 --- a/src/Symfony/Component/HttpKernel/EventListener/ProfilerListener.php +++ b/src/Symfony/Component/HttpKernel/EventListener/ProfilerListener.php @@ -107,8 +107,7 @@ public function onKernelTerminate(PostResponseEvent $event) { // attach children to parents foreach ($this->profiles as $request) { - // isset call should be removed when requestStack is required - if (isset($this->parents[$request]) && null !== $parentRequest = $this->parents[$request]) { + if (null !== $parentRequest = $this->parents[$request]) { if (isset($this->profiles[$parentRequest])) { $this->profiles[$parentRequest]->addChild($this->profiles[$request]); } From 30eed995b4482f614b89c34853b82744c88c756b Mon Sep 17 00:00:00 2001 From: Maxime Steinhausser Date: Sun, 6 Aug 2017 14:05:07 +0200 Subject: [PATCH 0579/1099] Github template: Remove EOM 3.2 from branch suggestion --- .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 cb9b8a69c1638..1bad363eca810 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1,6 +1,6 @@ | Q | A | ------------- | --- -| Branch? | 3.4 or master / 2.7, 2.8, 3.2 or 3.3 +| Branch? | 3.4 or master / 2.7, 2.8 or 3.3 | Bug fix? | yes/no | New feature? | yes/no | BC breaks? | yes/no From c35cdba6d2e0b1f0a75908195a34291e302151b1 Mon Sep 17 00:00:00 2001 From: Maxime Steinhausser Date: Sun, 6 Aug 2017 15:12:58 +0200 Subject: [PATCH 0580/1099] [Profiler] Fix request_collector check in main layout --- .../WebProfilerBundle/Resources/views/Profiler/layout.html.twig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/layout.html.twig b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/layout.html.twig index bd097d3cbc49b..822323315e37d 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/layout.html.twig +++ b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/layout.html.twig @@ -20,7 +20,7 @@ {% set request_collector = profile.collectors.request|default(false) %} - {% if request_collector is defined and request_collector.redirect -%} + {% if request_collector and request_collector.redirect -%} {%- set redirect = request_collector.redirect -%} {%- set controller = redirect.controller -%} {%- set redirect_route = '@' ~ redirect.route %} From b31542eb22c499ea3adf519acd89b5044e122bb7 Mon Sep 17 00:00:00 2001 From: Maxime Steinhausser Date: Sun, 6 Aug 2017 20:00:10 +0200 Subject: [PATCH 0581/1099] [FrameworkBundle] Allow micro kernel to subscribe events easily --- .../Kernel/MicroKernelTrait.php | 8 +++++ .../Tests/Kernel/ConcreteMicroKernel.php | 32 ++++++++++++++++++- .../Tests/Kernel/MicroKernelTraitTest.php | 11 +++++++ 3 files changed, 50 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/Kernel/MicroKernelTrait.php b/src/Symfony/Bundle/FrameworkBundle/Kernel/MicroKernelTrait.php index fec5b72a5b3be..ef632ca04cc61 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Kernel/MicroKernelTrait.php +++ b/src/Symfony/Bundle/FrameworkBundle/Kernel/MicroKernelTrait.php @@ -13,6 +13,7 @@ use Symfony\Component\Config\Loader\LoaderInterface; use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\Routing\RouteCollectionBuilder; /** @@ -68,6 +69,13 @@ public function registerContainerConfiguration(LoaderInterface $loader) ), )); + if ($this instanceof EventSubscriberInterface) { + $container->register('kernel', static::class) + ->setSynthetic(true) + ->addTag('kernel.event_subscriber') + ; + } + $this->configureContainer($container, $loader); $container->addObjectResource($this); diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Kernel/ConcreteMicroKernel.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Kernel/ConcreteMicroKernel.php index 02bed823823e4..5337050d0e37c 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Kernel/ConcreteMicroKernel.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Kernel/ConcreteMicroKernel.php @@ -15,22 +15,37 @@ use Symfony\Bundle\FrameworkBundle\FrameworkBundle; use Symfony\Component\Config\Loader\LoaderInterface; use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\Filesystem\Filesystem; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent; use Symfony\Component\HttpKernel\Kernel; +use Symfony\Component\HttpKernel\KernelEvents; use Symfony\Component\Routing\RouteCollectionBuilder; -class ConcreteMicroKernel extends Kernel +class ConcreteMicroKernel extends Kernel implements EventSubscriberInterface { use MicroKernelTrait; private $cacheDir; + public function onKernelException(GetResponseForExceptionEvent $event) + { + if ($event->getException() instanceof Danger) { + $event->setResponse(Response::create('It\'s dangerous to go alone. Take this ⚔')); + } + } + public function halloweenAction() { return new Response('halloween'); } + public function dangerousAction() + { + throw new Danger(); + } + public function registerBundles() { return array( @@ -57,6 +72,7 @@ public function __destruct() protected function configureRoutes(RouteCollectionBuilder $routes) { $routes->add('/', 'kernel:halloweenAction'); + $routes->add('/danger', 'kernel:dangerousAction'); } protected function configureContainer(ContainerBuilder $c, LoaderInterface $loader) @@ -68,4 +84,18 @@ protected function configureContainer(ContainerBuilder $c, LoaderInterface $load $c->setParameter('halloween', 'Have a great day!'); $c->register('halloween', 'stdClass'); } + + /** + * {@inheritdoc} + */ + public static function getSubscribedEvents() + { + return array( + KernelEvents::EXCEPTION => 'onKernelException', + ); + } +} + +class Danger extends \RuntimeException +{ } diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Kernel/MicroKernelTraitTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Kernel/MicroKernelTraitTest.php index 5fde7f27f8c42..2cb1ba8f7d67b 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Kernel/MicroKernelTraitTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Kernel/MicroKernelTraitTest.php @@ -28,4 +28,15 @@ public function test() $this->assertEquals('Have a great day!', $kernel->getContainer()->getParameter('halloween')); $this->assertInstanceOf('stdClass', $kernel->getContainer()->get('halloween')); } + + public function testAsEventSubscriber() + { + $kernel = new ConcreteMicroKernel('test', true); + $kernel->boot(); + + $request = Request::create('/danger'); + $response = $kernel->handle($request); + + $this->assertSame('It\'s dangerous to go alone. Take this ⚔', $response->getContent()); + } } From 5f637c162986535ddf1b7145b080d1a6295649b3 Mon Sep 17 00:00:00 2001 From: Roland Franssen Date: Sun, 6 Aug 2017 12:59:30 +0200 Subject: [PATCH 0582/1099] Continuation of #23624 --- .../Bridge/Twig/Command/DebugCommand.php | 6 +- .../Bridge/Twig/Command/LintCommand.php | 6 +- .../Command/AssetsInstallCommand.php | 6 +- .../Command/CacheClearCommand.php | 6 +- .../Command/CachePoolClearCommand.php | 6 +- .../Command/CacheWarmupCommand.php | 6 +- .../Command/EventDispatcherDebugCommand.php | 6 +- .../Command/RouterDebugCommand.php | 6 +- .../Command/RouterMatchCommand.php | 6 +- .../Command/TranslationDebugCommand.php | 14 ++-- .../Command/TranslationUpdateCommand.php | 6 +- .../Command/XliffLintCommand.php | 68 ++++++++----------- .../Command/YamlLintCommand.php | 68 ++++++++----------- .../FrameworkExtension.php | 11 +++ .../SecurityBundle/Command/InitAclCommand.php | 44 +++++++++--- .../SecurityBundle/Command/SetAclCommand.php | 43 +++++++++--- .../DependencyInjection/SecurityExtension.php | 5 ++ .../Resources/config/console.xml | 3 + .../Tests/Functional/SetAclCommandTest.php | 6 +- 19 files changed, 184 insertions(+), 138 deletions(-) diff --git a/src/Symfony/Bridge/Twig/Command/DebugCommand.php b/src/Symfony/Bridge/Twig/Command/DebugCommand.php index e9519adb66d33..0c68c637f8c52 100644 --- a/src/Symfony/Bridge/Twig/Command/DebugCommand.php +++ b/src/Symfony/Bridge/Twig/Command/DebugCommand.php @@ -33,16 +33,16 @@ class DebugCommand extends Command */ public function __construct($twig = null) { - parent::__construct(); - if (!$twig instanceof Environment) { @trigger_error(sprintf('Passing a command name as the first argument of "%s" is deprecated since version 3.4 and will be removed in 4.0. If the command was registered by convention, make it a service instead.', __METHOD__), E_USER_DEPRECATED); - $this->setName(null === $twig ? 'debug:twig' : $twig); + parent::__construct($twig); return; } + parent::__construct(); + $this->twig = $twig; } diff --git a/src/Symfony/Bridge/Twig/Command/LintCommand.php b/src/Symfony/Bridge/Twig/Command/LintCommand.php index 2aae6120d318f..f96da4d615a29 100644 --- a/src/Symfony/Bridge/Twig/Command/LintCommand.php +++ b/src/Symfony/Bridge/Twig/Command/LintCommand.php @@ -38,16 +38,16 @@ class LintCommand extends Command */ public function __construct($twig = null) { - parent::__construct(); - if (!$twig instanceof Environment) { @trigger_error(sprintf('Passing a command name as the first argument of "%s" is deprecated since version 3.4 and will be removed in 4.0. If the command was registered by convention, make it a service instead.', __METHOD__), E_USER_DEPRECATED); - $this->setName(null === $twig ? 'lint:twig' : $twig); + parent::__construct($twig); return; } + parent::__construct(); + $this->twig = $twig; } diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/AssetsInstallCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/AssetsInstallCommand.php index b8ad74300d759..ffc770c7a5a69 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/AssetsInstallCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/AssetsInstallCommand.php @@ -42,16 +42,16 @@ class AssetsInstallCommand extends ContainerAwareCommand */ public function __construct($filesystem = null) { - parent::__construct(); - if (!$filesystem instanceof Filesystem) { @trigger_error(sprintf('Passing a command name as the first argument of "%s" is deprecated since version 3.4 and will be removed in 4.0. If the command was registered by convention, make it a service instead.', __METHOD__), E_USER_DEPRECATED); - $this->setName(null === $filesystem ? 'assets:install' : $filesystem); + parent::__construct($filesystem); return; } + parent::__construct(); + $this->filesystem = $filesystem; } diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/CacheClearCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/CacheClearCommand.php index 631b31b600a27..c3a7bf450ed0f 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/CacheClearCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/CacheClearCommand.php @@ -39,16 +39,16 @@ class CacheClearCommand extends ContainerAwareCommand */ public function __construct($cacheClearer = null, Filesystem $filesystem = null) { - parent::__construct(); - if (!$cacheClearer instanceof CacheClearerInterface) { @trigger_error(sprintf('Passing a command name as the first argument of "%s" is deprecated since version 3.4 and will be removed in 4.0. If the command was registered by convention, make it a service instead.', __METHOD__), E_USER_DEPRECATED); - $this->setName(null === $cacheClearer ? 'cache:clear' : $cacheClearer); + parent::__construct($cacheClearer); return; } + parent::__construct(); + $this->cacheClearer = $cacheClearer; $this->filesystem = $filesystem ?: new Filesystem(); } diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/CachePoolClearCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/CachePoolClearCommand.php index 60c42e8729b13..fec933f67b9ce 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/CachePoolClearCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/CachePoolClearCommand.php @@ -32,16 +32,16 @@ final class CachePoolClearCommand extends ContainerAwareCommand */ public function __construct($poolClearer = null) { - parent::__construct(); - if (!$poolClearer instanceof Psr6CacheClearer) { @trigger_error(sprintf('Passing a command name as the first argument of "%s" is deprecated since version 3.4 and will be removed in 4.0. If the command was registered by convention, make it a service instead.', __METHOD__), E_USER_DEPRECATED); - $this->setName(null === $poolClearer ? 'cache:pool:clear' : $poolClearer); + parent::__construct($poolClearer); return; } + parent::__construct(); + $this->poolClearer = $poolClearer; } diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/CacheWarmupCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/CacheWarmupCommand.php index 0f72db83052e9..57972782dc771 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/CacheWarmupCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/CacheWarmupCommand.php @@ -33,16 +33,16 @@ class CacheWarmupCommand extends ContainerAwareCommand */ public function __construct($cacheWarmer = null) { - parent::__construct(); - if (!$cacheWarmer instanceof CacheWarmerAggregate) { @trigger_error(sprintf('Passing a command name as the first argument of "%s" is deprecated since version 3.4 and will be removed in 4.0. If the command was registered by convention, make it a service instead.', __METHOD__), E_USER_DEPRECATED); - $this->setName(null === $cacheWarmer ? 'cache:warmup' : $cacheWarmer); + parent::__construct($cacheWarmer); return; } + parent::__construct(); + $this->cacheWarmer = $cacheWarmer; } diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/EventDispatcherDebugCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/EventDispatcherDebugCommand.php index d2f8bd77751b5..18aa08575c4e0 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/EventDispatcherDebugCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/EventDispatcherDebugCommand.php @@ -35,16 +35,16 @@ class EventDispatcherDebugCommand extends ContainerAwareCommand */ public function __construct($dispatcher = null) { - parent::__construct(); - if (!$dispatcher instanceof EventDispatcherInterface) { @trigger_error(sprintf('Passing a command name as the first argument of "%s" is deprecated since version 3.4 and will be removed in 4.0. If the command was registered by convention, make it a service instead.', __METHOD__), E_USER_DEPRECATED); - $this->setName(null === $dispatcher ? 'debug:event-dispatcher' : $dispatcher); + parent::__construct($dispatcher); return; } + parent::__construct(); + $this->dispatcher = $dispatcher; } diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/RouterDebugCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/RouterDebugCommand.php index 253f9a13f29a4..2a005090322dd 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/RouterDebugCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/RouterDebugCommand.php @@ -39,16 +39,16 @@ class RouterDebugCommand extends ContainerAwareCommand */ public function __construct($router = null) { - parent::__construct(); - if (!$router instanceof RouterInterface) { @trigger_error(sprintf('Passing a command name as the first argument of "%s" is deprecated since version 3.4 and will be removed in 4.0. If the command was registered by convention, make it a service instead.', __METHOD__), E_USER_DEPRECATED); - $this->setName(null === $router ? 'debug:router' : $router); + parent::__construct($router); return; } + parent::__construct(); + $this->router = $router; } diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/RouterMatchCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/RouterMatchCommand.php index c6d2bdbf990cf..f88d2a2dfe0c7 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/RouterMatchCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/RouterMatchCommand.php @@ -36,16 +36,16 @@ class RouterMatchCommand extends ContainerAwareCommand */ public function __construct($router = null) { - parent::__construct(); - if (!$router instanceof RouterInterface) { @trigger_error(sprintf('Passing a command name as the first argument of "%s" is deprecated since version 3.4 and will be removed in 4.0. If the command was registered by convention, make it a service instead.', __METHOD__), E_USER_DEPRECATED); - $this->setName(null === $router ? 'router:match' : $router); + parent::__construct($router); return; } + parent::__construct(); + $this->router = $router; } diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/TranslationDebugCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/TranslationDebugCommand.php index 44730737bc8a7..f8e69a3c4a640 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/TranslationDebugCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/TranslationDebugCommand.php @@ -36,14 +36,14 @@ */ class TranslationDebugCommand extends ContainerAwareCommand { - private $translator; - private $loader; - private $extractor; - const MESSAGE_MISSING = 0; const MESSAGE_UNUSED = 1; const MESSAGE_EQUALS_FALLBACK = 2; + private $translator; + private $loader; + private $extractor; + /** * @param TranslatorInterface $translator * @param TranslationLoader $loader @@ -51,16 +51,16 @@ class TranslationDebugCommand extends ContainerAwareCommand */ public function __construct($translator = null, TranslationLoader $loader = null, ExtractorInterface $extractor = null) { - parent::__construct(); - if (!$translator instanceof TranslatorInterface) { @trigger_error(sprintf('Passing a command name as the first argument of "%s" is deprecated since version 3.4 and will be removed in 4.0. If the command was registered by convention, make it a service instead.', __METHOD__), E_USER_DEPRECATED); - $this->setName(null === $translator ? 'debug:translation' : $translator); + parent::__construct($translator); return; } + parent::__construct(); + $this->translator = $translator; $this->loader = $loader; $this->extractor = $extractor; diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/TranslationUpdateCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/TranslationUpdateCommand.php index a02cb23a57547..357902a209305 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/TranslationUpdateCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/TranslationUpdateCommand.php @@ -46,16 +46,16 @@ class TranslationUpdateCommand extends ContainerAwareCommand */ public function __construct($writer = null, TranslationLoader $loader = null, ExtractorInterface $extractor = null, $defaultLocale = null) { - parent::__construct(); - if (!$writer instanceof TranslationWriter) { @trigger_error(sprintf('Passing a command name as the first argument of "%s" is deprecated since version 3.4 and will be removed in 4.0. If the command was registered by convention, make it a service instead.', __METHOD__), E_USER_DEPRECATED); - $this->setName(null === $writer ? 'translation:update' : $writer); + parent::__construct($writer); return; } + parent::__construct(); + $this->writer = $writer; $this->loader = $loader; $this->extractor = $extractor; diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/XliffLintCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/XliffLintCommand.php index 8f4739a9f8e80..36876dee24252 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/XliffLintCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/XliffLintCommand.php @@ -11,9 +11,6 @@ namespace Symfony\Bundle\FrameworkBundle\Command; -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Translation\Command\XliffLintCommand as BaseLintCommand; /** @@ -25,39 +22,41 @@ * * @final since version 3.4 */ -class XliffLintCommand extends Command +class XliffLintCommand extends BaseLintCommand { - private $command; - - /** - * {@inheritdoc} - */ - protected function configure() + public function __construct($name = null, $directoryIteratorProvider = null, $isReadableProvider = null) { - $this->setName('lint:xliff'); - - if (!$this->isEnabled()) { - return; + if (func_num_args()) { + @trigger_error(sprintf('Passing a constructor argument in "%s" is deprecated since version 3.4 and will be removed in 4.0. If the command was registered by convention, make it a service instead.', __METHOD__), E_USER_DEPRECATED); } - $directoryIteratorProvider = function ($directory, $default) { - if (!is_dir($directory)) { - $directory = $this->getApplication()->getKernel()->locateResource($directory); - } + if (null === $directoryIteratorProvider) { + $directoryIteratorProvider = function ($directory, $default) { + if (!is_dir($directory)) { + $directory = $this->getApplication()->getKernel()->locateResource($directory); + } - return $default($directory); - }; + return $default($directory); + }; + } + + if (null === $isReadableProvider) { + $isReadableProvider = function ($fileOrDirectory, $default) { + return 0 === strpos($fileOrDirectory, '@') || $default($fileOrDirectory); + }; + } - $isReadableProvider = function ($fileOrDirectory, $default) { - return 0 === strpos($fileOrDirectory, '@') || $default($fileOrDirectory); - }; + parent::__construct($name, $directoryIteratorProvider, $isReadableProvider); + } - $this->command = new BaseLintCommand(null, $directoryIteratorProvider, $isReadableProvider); + /** + * {@inheritdoc} + */ + protected function configure() + { + parent::configure(); - $this - ->setDescription($this->command->getDescription()) - ->setDefinition($this->command->getDefinition()) - ->setHelp($this->command->getHelp().<<<'EOF' + $this->setHelp($this->getHelp().<<<'EOF' Or find all files in a bundle: @@ -66,17 +65,4 @@ protected function configure() EOF ); } - - /** - * {@inheritdoc} - */ - public function isEnabled() - { - return class_exists(BaseLintCommand::class); - } - - protected function execute(InputInterface $input, OutputInterface $output) - { - return $this->command->execute($input, $output); - } } diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/YamlLintCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/YamlLintCommand.php index 6e8f7dbfaeab8..f6c1a7f85b190 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/YamlLintCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/YamlLintCommand.php @@ -11,9 +11,6 @@ namespace Symfony\Bundle\FrameworkBundle\Command; -use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Yaml\Command\LintCommand as BaseLintCommand; /** @@ -24,39 +21,41 @@ * * @final since version 3.4 */ -class YamlLintCommand extends Command +class YamlLintCommand extends BaseLintCommand { - private $command; - - /** - * {@inheritdoc} - */ - protected function configure() + public function __construct($name = null, $directoryIteratorProvider = null, $isReadableProvider = null) { - $this->setName('lint:yaml'); - - if (!$this->isEnabled()) { - return; + if (func_num_args()) { + @trigger_error(sprintf('Passing a constructor argument in "%s" is deprecated since version 3.4 and will be removed in 4.0. If the command was registered by convention, make it a service instead.', __METHOD__), E_USER_DEPRECATED); } - $directoryIteratorProvider = function ($directory, $default) { - if (!is_dir($directory)) { - $directory = $this->getApplication()->getKernel()->locateResource($directory); - } + if (null === $directoryIteratorProvider) { + $directoryIteratorProvider = function ($directory, $default) { + if (!is_dir($directory)) { + $directory = $this->getApplication()->getKernel()->locateResource($directory); + } - return $default($directory); - }; + return $default($directory); + }; + } + + if (null === $isReadableProvider) { + $isReadableProvider = function ($fileOrDirectory, $default) { + return 0 === strpos($fileOrDirectory, '@') || $default($fileOrDirectory); + }; + } - $isReadableProvider = function ($fileOrDirectory, $default) { - return 0 === strpos($fileOrDirectory, '@') || $default($fileOrDirectory); - }; + parent::__construct($name, $directoryIteratorProvider, $isReadableProvider); + } - $this->command = new BaseLintCommand(null, $directoryIteratorProvider, $isReadableProvider); + /** + * {@inheritdoc} + */ + protected function configure() + { + parent::configure(); - $this - ->setDescription($this->command->getDescription()) - ->setDefinition($this->command->getDefinition()) - ->setHelp($this->command->getHelp().<<<'EOF' + $this->setHelp($this->getHelp().<<<'EOF' Or find all files in a bundle: @@ -65,17 +64,4 @@ protected function configure() EOF ); } - - /** - * {@inheritdoc} - */ - public function isEnabled() - { - return class_exists(BaseLintCommand::class) && parent::isEnabled(); - } - - protected function execute(InputInterface $input, OutputInterface $output) - { - return $this->command->execute($input, $output); - } } diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php index 65b28ec398120..14e6808278d0b 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php @@ -18,6 +18,8 @@ use Symfony\Bundle\FrameworkBundle\Command\TranslationDebugCommand; use Symfony\Bundle\FrameworkBundle\Command\TranslationUpdateCommand; use Symfony\Bundle\FrameworkBundle\Command\WorkflowDumpCommand; +use Symfony\Bundle\FrameworkBundle\Command\XliffLintCommand; +use Symfony\Bundle\FrameworkBundle\Command\YamlLintCommand; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Bundle\FrameworkBundle\Controller\Controller; use Symfony\Bundle\FrameworkBundle\Routing\AnnotatedRouteControllerLoader; @@ -69,10 +71,12 @@ use Symfony\Component\Serializer\Normalizer\JsonSerializableNormalizer; use Symfony\Component\Serializer\Normalizer\NormalizerInterface; use Symfony\Component\Stopwatch\Stopwatch; +use Symfony\Component\Translation\Command\XliffLintCommand as BaseXliffLintCommand; use Symfony\Component\Validator\ConstraintValidatorInterface; use Symfony\Component\Validator\ObjectInitializerInterface; use Symfony\Component\WebLink\HttpHeaderSerializer; use Symfony\Component\Workflow; +use Symfony\Component\Yaml\Command\LintCommand as BaseYamlLintCommand; /** * FrameworkExtension. @@ -128,6 +132,13 @@ public function load(array $configs, ContainerBuilder $container) if (class_exists(Application::class)) { $loader->load('console.xml'); + + if (!class_exists(BaseXliffLintCommand::class)) { + $container->removeDefinition(XliffLintCommand::class); + } + if (!class_exists(BaseYamlLintCommand::class)) { + $container->removeDefinition(YamlLintCommand::class); + } } // Property access is used by both the Form and the Validator component diff --git a/src/Symfony/Bundle/SecurityBundle/Command/InitAclCommand.php b/src/Symfony/Bundle/SecurityBundle/Command/InitAclCommand.php index 1512e910c9744..597df8ceb9de1 100644 --- a/src/Symfony/Bundle/SecurityBundle/Command/InitAclCommand.php +++ b/src/Symfony/Bundle/SecurityBundle/Command/InitAclCommand.php @@ -14,6 +14,8 @@ use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Security\Acl\Dbal\Schema; +use Doctrine\DBAL\Connection; use Doctrine\DBAL\Schema\SchemaException; /** @@ -25,12 +27,37 @@ */ class InitAclCommand extends ContainerAwareCommand { + private $connection; + private $schema; + + /** + * @param Connection $connection + * @param Schema $schema + */ + public function __construct($connection = null, Schema $schema = null) + { + if (!$connection instanceof Connection) { + @trigger_error(sprintf('Passing a command name as the first argument of "%s" is deprecated since version 3.4 and will be removed in 4.0. If the command was registered by convention, make it a service instead.', __METHOD__), E_USER_DEPRECATED); + + parent::__construct($connection); + + return; + } + + parent::__construct(); + + $this->connection = $connection; + $this->schema = $schema; + } + /** * {@inheritdoc} + * + * BC to be removed in 4.0 */ public function isEnabled() { - if (!$this->getContainer()->has('security.acl.dbal.connection')) { + if (!$this->connection && !$this->getContainer()->has('security.acl.dbal.connection')) { return false; } @@ -65,21 +92,22 @@ protected function configure() */ protected function execute(InputInterface $input, OutputInterface $output) { - $container = $this->getContainer(); - - $connection = $container->get('security.acl.dbal.connection'); - $schema = $container->get('security.acl.dbal.schema'); + // BC to be removed in 4.0 + if (null === $this->connection) { + $this->connection = $this->getContainer()->get('security.acl.dbal.connection'); + $this->schema = $this->getContainer()->get('security.acl.dbal.schema'); + } try { - $schema->addToSchema($connection->getSchemaManager()->createSchema()); + $this->schema->addToSchema($this->connection->getSchemaManager()->createSchema()); } catch (SchemaException $e) { $output->writeln('Aborting: '.$e->getMessage()); return 1; } - foreach ($schema->toSql($connection->getDatabasePlatform()) as $sql) { - $connection->exec($sql); + foreach ($this->schema->toSql($this->connection->getDatabasePlatform()) as $sql) { + $this->connection->exec($sql); } $output->writeln('ACL tables have been initialized successfully.'); diff --git a/src/Symfony/Bundle/SecurityBundle/Command/SetAclCommand.php b/src/Symfony/Bundle/SecurityBundle/Command/SetAclCommand.php index 7d0146fdc63de..840e74edfba87 100644 --- a/src/Symfony/Bundle/SecurityBundle/Command/SetAclCommand.php +++ b/src/Symfony/Bundle/SecurityBundle/Command/SetAclCommand.php @@ -32,11 +32,36 @@ */ class SetAclCommand extends ContainerAwareCommand { + private $provider; + + /** + * @param MutableAclProviderInterface $provider + */ + public function __construct($provider = null) + { + if (!$provider instanceof MutableAclProviderInterface) { + @trigger_error(sprintf('Passing a command name as the first argument of "%s" is deprecated since version 3.4 and will be removed in 4.0. If the command was registered by convention, make it a service instead.', __METHOD__), E_USER_DEPRECATED); + + parent::__construct($provider); + + return; + } + + parent::__construct(); + + $this->provider = $provider; + } + /** * {@inheritdoc} + * + * BC to be removed in 4.0 */ public function isEnabled() { + if (null !== $this->provider) { + return parent::isEnabled(); + } if (!$this->getContainer()->has('security.acl.provider')) { return false; } @@ -91,6 +116,11 @@ protected function configure() */ protected function execute(InputInterface $input, OutputInterface $output) { + // BC to be removed in 4.0 + if (null === $this->provider) { + $this->provider = $this->getContainer()->get('security.acl.provider'); + } + // Parse arguments $objectIdentities = array(); $maskBuilder = $this->getMaskBuilder(); @@ -136,20 +166,15 @@ protected function execute(InputInterface $input, OutputInterface $output) } } - /** @var $container \Symfony\Component\DependencyInjection\ContainerInterface */ - $container = $this->getContainer(); - /** @var $aclProvider MutableAclProviderInterface */ - $aclProvider = $container->get('security.acl.provider'); - // Sets ACL foreach ($objectIdentities as $objectIdentity) { // Creates a new ACL if it does not already exist try { - $aclProvider->createAcl($objectIdentity); + $this->provider->createAcl($objectIdentity); } catch (AclAlreadyExistsException $e) { } - $acl = $aclProvider->findAcl($objectIdentity, $securityIdentities); + $acl = $this->provider->findAcl($objectIdentity, $securityIdentities); foreach ($securityIdentities as $securityIdentity) { if ($classScopeOption) { @@ -159,13 +184,15 @@ protected function execute(InputInterface $input, OutputInterface $output) } } - $aclProvider->updateAcl($acl); + $this->provider->updateAcl($acl); } } /** * Gets the mask builder. * + * BC to be removed in 4.0 + * * @return MaskBuilder */ protected function getMaskBuilder() diff --git a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php index 4a77c13b48e76..dffe9d36879b2 100644 --- a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php +++ b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php @@ -11,6 +11,8 @@ namespace Symfony\Bundle\SecurityBundle\DependencyInjection; +use Symfony\Bundle\SecurityBundle\Command\InitAclCommand; +use Symfony\Bundle\SecurityBundle\Command\SetAclCommand; use Symfony\Bundle\SecurityBundle\Command\UserPasswordEncoderCommand; use Symfony\Bundle\SecurityBundle\DependencyInjection\Security\Factory\SecurityFactoryInterface; use Symfony\Bundle\SecurityBundle\DependencyInjection\Security\UserProvider\UserProviderFactoryInterface; @@ -114,6 +116,9 @@ public function load(array $configs, ContainerBuilder $container) // load ACL if (isset($config['acl'])) { $this->aclLoad($config['acl'], $container); + } else { + $container->removeDefinition(InitAclCommand::class); + $container->removeDefinition(SetAclCommand::class); } $container->registerForAutoconfiguration(VoterInterface::class) diff --git a/src/Symfony/Bundle/SecurityBundle/Resources/config/console.xml b/src/Symfony/Bundle/SecurityBundle/Resources/config/console.xml index f14b4a5a350dc..b375d95effe5c 100644 --- a/src/Symfony/Bundle/SecurityBundle/Resources/config/console.xml +++ b/src/Symfony/Bundle/SecurityBundle/Resources/config/console.xml @@ -8,10 +8,13 @@ + + + diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/SetAclCommandTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/SetAclCommandTest.php index 3b060a86fc242..1ceaca1002019 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/SetAclCommandTest.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/SetAclCommandTest.php @@ -96,7 +96,7 @@ public function testSetAclRole() $role = 'ROLE_ADMIN'; $application = $this->getApplication(); - $application->add(new SetAclCommand()); + $application->add(new SetAclCommand($application->getKernel()->getContainer()->get('security.acl.provider'))); $setAclCommand = $application->find('acl:set'); $setAclCommandTester = new CommandTester($setAclCommand); @@ -138,7 +138,7 @@ public function testSetAclClassScope() $role = 'ROLE_USER'; $application = $this->getApplication(); - $application->add(new SetAclCommand()); + $application->add(new SetAclCommand($application->getKernel()->getContainer()->get('security.acl.provider'))); $setAclCommand = $application->find('acl:set'); $setAclCommandTester = new CommandTester($setAclCommand); @@ -170,7 +170,7 @@ private function getApplication() $kernel->boot(); $application = new Application($kernel); - $application->add(new InitAclCommand()); + $application->add(new InitAclCommand($kernel->getContainer()->get('security.acl.dbal.connection'), $kernel->getContainer()->get('security.acl.dbal.schema'))); $initAclCommand = $application->find('init:acl'); $initAclCommandTester = new CommandTester($initAclCommand); From 4037009490a6e584f446a5af542322d2b0f6e493 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Mon, 24 Jul 2017 21:11:47 +0200 Subject: [PATCH 0583/1099] [DI] Generate one file per service factory --- .../Bridge/Doctrine/ManagerRegistry.php | 8 +- .../LazyProxy/PhpDumper/ProxyDumper.php | 17 +- .../Fixtures/php/lazy_service_structure.txt | 11 +- .../LazyProxy/PhpDumper/ProxyDumperTest.php | 20 +- src/Symfony/Bridge/ProxyManager/composer.json | 2 +- .../Command/CacheClearCommand.php | 25 +- .../CacheClearCommandTest.php | 13 +- .../DependencyInjection/Container.php | 80 ++-- .../DependencyInjection/Dumper/PhpDumper.php | 352 ++++++++------ .../Tests/Dumper/PhpDumperTest.php | 12 + .../Tests/Fixtures/containers/container9.php | 1 + .../Tests/Fixtures/graphviz/services9.dot | 1 + .../Tests/Fixtures/php/services9.php | 2 +- .../Tests/Fixtures/php/services9_as_files.txt | 434 ++++++++++++++++++ .../Tests/Fixtures/php/services9_compiled.php | 2 +- .../Tests/Fixtures/xml/services9.xml | 4 +- .../Tests/Fixtures/yaml/services9.yml | 1 + src/Symfony/Component/HttpKernel/Kernel.php | 24 +- .../Component/HttpKernel/composer.json | 4 +- 19 files changed, 778 insertions(+), 235 deletions(-) create mode 100644 src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_as_files.txt diff --git a/src/Symfony/Bridge/Doctrine/ManagerRegistry.php b/src/Symfony/Bridge/Doctrine/ManagerRegistry.php index b30fd0691b1a8..c353e36e66282 100644 --- a/src/Symfony/Bridge/Doctrine/ManagerRegistry.php +++ b/src/Symfony/Bridge/Doctrine/ManagerRegistry.php @@ -59,8 +59,12 @@ function (&$wrappedInstance, LazyLoadingInterface $manager) use ($name) { if (isset($this->aliases[$name])) { $name = $this->aliases[$name]; } - $method = !isset($this->methodMap[$name]) ? 'get'.strtr($name, $this->underscoreMap).'Service' : $this->methodMap[$name]; - $wrappedInstance = $this->{$method}(false); + if (isset($this->fileMap[$name])) { + $wrappedInstance = $this->load($this->fileMap[$name], false); + } else { + $method = !isset($this->methodMap[$name]) ? 'get'.strtr($name, $this->underscoreMap).'Service' : $this->methodMap[$name]; + $wrappedInstance = $this->{$method}(false); + } $manager->setProxyInitializer(null); diff --git a/src/Symfony/Bridge/ProxyManager/LazyProxy/PhpDumper/ProxyDumper.php b/src/Symfony/Bridge/ProxyManager/LazyProxy/PhpDumper/ProxyDumper.php index 29133e762d659..22ed2b05f188e 100644 --- a/src/Symfony/Bridge/ProxyManager/LazyProxy/PhpDumper/ProxyDumper.php +++ b/src/Symfony/Bridge/ProxyManager/LazyProxy/PhpDumper/ProxyDumper.php @@ -81,24 +81,21 @@ public function getProxyFactoryCode(Definition $definition, $id, $factoryCode = } $proxyClass = $this->getProxyClassName($definition); - $generatedClass = $this->generateProxyClass($definition); + $hasStaticConstructor = $this->generateProxyClass($definition)->hasMethod('staticProxyConstructor'); - $constructorCall = $generatedClass->hasMethod('staticProxyConstructor') - ? $proxyClass.'::staticProxyConstructor' - : 'new '.$proxyClass; + $constructorCall = sprintf($hasStaticConstructor ? '%s::staticProxyConstructor' : 'new %s', '\\'.$proxyClass); return <<createProxy('$proxyClass', function () { + return $constructorCall(function (&\$wrappedInstance, \ProxyManager\Proxy\LazyLoadingInterface \$proxy) { \$wrappedInstance = $factoryCode; \$proxy->setProxyInitializer(null); return true; - } - ); + }); + }); } @@ -122,7 +119,7 @@ public function getProxyCode(Definition $definition) */ private function getProxyClassName(Definition $definition) { - return str_replace('\\', '', $definition->getClass()).'_'.spl_object_hash($definition).$this->salt; + return preg_replace('/^.*\\\\/', '', $definition->getClass()).'_'.substr(hash('sha256', spl_object_hash($definition).$this->salt), -7); } /** diff --git a/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/Fixtures/php/lazy_service_structure.txt b/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/Fixtures/php/lazy_service_structure.txt index 88e2933cd9015..574041b89bbb4 100644 --- a/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/Fixtures/php/lazy_service_structure.txt +++ b/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/Fixtures/php/lazy_service_structure.txt @@ -3,19 +3,18 @@ use %a class LazyServiceProjectServiceContainer extends Container {%a - p%s function getFooService($lazyLoad = true) + protected function getFooService($lazyLoad = true) { if ($lazyLoad) { - - return $this->services['foo'] =%sstdClass_%s( - function (&$wrappedInstance, \ProxyManager\Proxy\LazyLoadingInterface $proxy) { + return $this->services['foo'] = $this->createProxy('stdClass_%s', function () { + return %S\stdClass_%s(function (&$wrappedInstance, \ProxyManager\Proxy\LazyLoadingInterface $proxy) { $wrappedInstance = $this->getFooService(false); $proxy->setProxyInitializer(null); return true; - } - ); + }); + }); } return new \stdClass(); diff --git a/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/PhpDumper/ProxyDumperTest.php b/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/PhpDumper/ProxyDumperTest.php index 58de413674fa5..640290e2b45a2 100644 --- a/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/PhpDumper/ProxyDumperTest.php +++ b/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/PhpDumper/ProxyDumperTest.php @@ -55,13 +55,13 @@ public function testGetProxyCode() $code = $this->dumper->getProxyCode($definition); $this->assertStringMatchesFormat( - '%Aclass SymfonyBridgeProxyManagerTestsLazyProxyPhpDumperProxyDumperTest%aextends%w' + '%Aclass ProxyDumperTest%aextends%w' .'\Symfony\Bridge\ProxyManager\Tests\LazyProxy\PhpDumper\ProxyDumperTest%a', $code ); } - public function testGetProxyFactoryCodeWithCustomMethod() + public function testGetProxyFactoryCode() { $definition = new Definition(__CLASS__); @@ -70,19 +70,15 @@ public function testGetProxyFactoryCodeWithCustomMethod() $code = $this->dumper->getProxyFactoryCode($definition, 'foo', '$this->getFoo2Service(false)'); $this->assertStringMatchesFormat( - '%wif ($lazyLoad) {%wreturn $this->services[\'foo\'] =%s' - .'SymfonyBridgeProxyManagerTestsLazyProxyPhpDumperProxyDumperTest_%s(%wfunction ' - .'(&$wrappedInstance, \ProxyManager\Proxy\LazyLoadingInterface $proxy) {' - .'%w$wrappedInstance = $this->getFoo2Service(false);%w$proxy->setProxyInitializer(null);' - .'%wreturn true;%w}%w);%w}%w', - $code + '%A$wrappedInstance = $this->getFoo2Service(false);%w$proxy->setProxyInitializer(null);%A', + $code ); } /** * @group legacy */ - public function testGetProxyFactoryCode() + public function testLegacyGetProxyFactoryCode() { $definition = new Definition(__CLASS__); @@ -91,11 +87,7 @@ public function testGetProxyFactoryCode() $code = $this->dumper->getProxyFactoryCode($definition, 'foo'); $this->assertStringMatchesFormat( - '%wif ($lazyLoad) {%wreturn $this->services[\'foo\'] =%s' - .'SymfonyBridgeProxyManagerTestsLazyProxyPhpDumperProxyDumperTest_%s(%wfunction ' - .'(&$wrappedInstance, \ProxyManager\Proxy\LazyLoadingInterface $proxy) {' - .'%w$wrappedInstance = $this->getFooService(false);%w$proxy->setProxyInitializer(null);' - .'%wreturn true;%w}%w);%w}%w', + '%A$wrappedInstance = $this->getFooService(false);%w$proxy->setProxyInitializer(null);%A', $code ); } diff --git a/src/Symfony/Bridge/ProxyManager/composer.json b/src/Symfony/Bridge/ProxyManager/composer.json index c9fe094094dcb..7e34cd90b5139 100644 --- a/src/Symfony/Bridge/ProxyManager/composer.json +++ b/src/Symfony/Bridge/ProxyManager/composer.json @@ -17,7 +17,7 @@ ], "require": { "php": "^5.5.9|>=7.0.8", - "symfony/dependency-injection": "~2.8|~3.0|~4.0", + "symfony/dependency-injection": "~3.4|~4.0", "ocramius/proxy-manager": "~0.4|~1.0|~2.0" }, "require-dev": { diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/CacheClearCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/CacheClearCommand.php index c3a7bf450ed0f..77ae66867c660 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/CacheClearCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/CacheClearCommand.php @@ -15,6 +15,7 @@ use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Style\SymfonyStyle; +use Symfony\Component\EventDispatcher\EventDispatcher; use Symfony\Component\Filesystem\Filesystem; use Symfony\Component\HttpKernel\CacheClearer\CacheClearerInterface; use Symfony\Component\HttpKernel\KernelInterface; @@ -125,6 +126,9 @@ protected function execute(InputInterface $input, OutputInterface $output) $this->filesystem->remove($oldCacheDir); + // The current event dispatcher is stale, let's not use it anymore + $this->getApplication()->setDispatcher(new EventDispatcher()); + if ($output->isVerbose()) { $io->comment('Finished'); } @@ -213,13 +217,19 @@ protected function warmup($warmupDir, $realCacheDir, $enableOptionalWarmers = tr } // fix references to container's class - $tempContainerClass = get_class($tempKernel->getContainer()); - $realContainerClass = get_class($realKernel->getContainer()); + $tempContainerClass = $tempKernel->getContainerClass(); + $realContainerClass = $tempKernel->getRealContainerClass(); foreach (Finder::create()->files()->depth('<2')->name($tempContainerClass.'*')->in($warmupDir) as $file) { $content = str_replace($tempContainerClass, $realContainerClass, file_get_contents($file)); file_put_contents($file, $content); rename($file, str_replace(DIRECTORY_SEPARATOR.$tempContainerClass, DIRECTORY_SEPARATOR.$realContainerClass, $file)); } + if (is_dir($tempContainerDir = $warmupDir.'/'.get_class($tempKernel->getContainer()))) { + foreach (Finder::create()->files()->in($tempContainerDir) as $file) { + $content = str_replace($tempContainerClass, $realContainerClass, file_get_contents($file)); + file_put_contents($file, $content); + } + } // remove temp kernel file after cache warmed up @unlink($tempKernelFile); @@ -245,7 +255,9 @@ protected function getTempKernel(KernelInterface $parent, $namespace, $parentCla // to avoid the many problems in serialized resources files $class = substr($parentClass, 0, -1).'_'; // the temp container class must be changed too - $containerClass = var_export(substr(get_class($parent->getContainer()), 0, -1).'_', true); + $container = $parent->getContainer(); + $realContainerClass = var_export($container->hasParameter('kernel.container_class') ? $container->getParameter('kernel.container_class') : get_class($parent->getContainer()), true); + $containerClass = substr_replace($realContainerClass, '_', -2, 1); if (method_exists($parent, 'getProjectDir')) { $projectDir = var_export(realpath($parent->getProjectDir()), true); @@ -281,7 +293,12 @@ public function getLogDir() return $logDir; } - protected function getContainerClass() + public function getRealContainerClass() + { + return $realContainerClass; + } + + public function getContainerClass() { return $containerClass; } diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/CacheClearCommand/CacheClearCommandTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/CacheClearCommand/CacheClearCommandTest.php index b9fe63ec5bbab..f3392995ae93d 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/CacheClearCommand/CacheClearCommandTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/CacheClearCommand/CacheClearCommandTest.php @@ -68,8 +68,9 @@ public function testCacheIsFreshAfterCacheClearedWithWarmup() } // check that app kernel file present in meta file of container's cache - $containerRef = new \ReflectionObject($this->kernel->getContainer()); - $containerFile = $containerRef->getFileName(); + $containerClass = $this->kernel->getContainer()->getParameter('kernel.container_class'); + $containerRef = new \ReflectionClass($containerClass); + $containerFile = dirname(dirname($containerRef->getFileName())).'/'.$containerClass.'.php'; $containerMetaFile = $containerFile.'.meta'; $kernelRef = new \ReflectionObject($this->kernel); $kernelFile = $kernelRef->getFileName(); @@ -83,6 +84,12 @@ public function testCacheIsFreshAfterCacheClearedWithWarmup() } } $this->assertTrue($found, 'Kernel file should present as resource'); - $this->assertRegExp(sprintf('/\'kernel.container_class\'\s*=>\s*\'%s\'/', get_class($this->kernel->getContainer())), file_get_contents($containerFile), 'kernel.container_class is properly set on the dumped container'); + + if (defined('HHVM_VERSION')) { + return; + } + $containerRef = new \ReflectionClass(require $containerFile); + $containerFile = str_replace('tes_'.DIRECTORY_SEPARATOR, 'test'.DIRECTORY_SEPARATOR, $containerRef->getFileName()); + $this->assertRegExp(sprintf('/\'kernel.container_class\'\s*=>\s*\'%s\'/', $containerClass), file_get_contents($containerFile), 'kernel.container_class is properly set on the dumped container'); } } diff --git a/src/Symfony/Component/DependencyInjection/Container.php b/src/Symfony/Component/DependencyInjection/Container.php index e3e66308e65cb..187571e9765dd 100644 --- a/src/Symfony/Component/DependencyInjection/Container.php +++ b/src/Symfony/Component/DependencyInjection/Container.php @@ -55,6 +55,7 @@ class Container implements ResettableContainerInterface protected $parameterBag; protected $services = array(); + protected $fileMap = array(); protected $methodMap = array(); protected $aliases = array(); protected $loading = array(); @@ -203,7 +204,7 @@ public function set($id, $service) } else { @trigger_error(sprintf('Setting the "%s" private service is deprecated since Symfony 3.2 and won\'t be supported anymore in Symfony 4.0.', $id), E_USER_DEPRECATED); } - } elseif (isset($this->methodMap[$id])) { + } elseif (isset($this->fileMap[$id]) || isset($this->methodMap[$id])) { if (null === $service) { @trigger_error(sprintf('Unsetting the "%s" pre-defined service is deprecated since Symfony 3.3 and won\'t be supported anymore in Symfony 4.0.', $id), E_USER_DEPRECATED); } else { @@ -235,7 +236,7 @@ public function has($id) return true; } - if (isset($this->methodMap[$id])) { + if (isset($this->fileMap[$id]) || isset($this->methodMap[$id])) { return true; } @@ -299,40 +300,25 @@ public function get($id, $invalidBehavior = self::EXCEPTION_ON_INVALID_REFERENCE throw new ServiceCircularReferenceException($id, array_keys($this->loading)); } - if (isset($this->methodMap[$id])) { - $method = $this->methodMap[$id]; - } elseif (--$i && $id !== $normalizedId = $this->normalizeId($id)) { - $id = $normalizedId; - continue; - } elseif (!$this->methodMap && !$this instanceof ContainerBuilder && __CLASS__ !== static::class && method_exists($this, $method = 'get'.strtr($id, $this->underscoreMap).'Service')) { - // We only check the convention-based factory in a compiled container (i.e. a child class other than a ContainerBuilder, - // and only when the dumper has not generated the method map (otherwise the method map is considered to be fully populated by the dumper) - @trigger_error('Generating a dumped container without populating the method map is deprecated since 3.2 and will be unsupported in 4.0. Update your dumper to generate the method map.', E_USER_DEPRECATED); - // $method is set to the right value, proceed - } else { - if (self::EXCEPTION_ON_INVALID_REFERENCE === $invalidBehavior) { - if (!$id) { - throw new ServiceNotFoundException($id); - } - - $alternatives = array(); - foreach ($this->getServiceIds() as $knownId) { - $lev = levenshtein($id, $knownId); - if ($lev <= strlen($id) / 3 || false !== strpos($knownId, $id)) { - $alternatives[] = $knownId; - } - } - - throw new ServiceNotFoundException($id, null, null, $alternatives); - } - - return; - } - $this->loading[$id] = true; try { - $service = $this->$method(); + if (isset($this->fileMap[$id])) { + return $this->load($this->fileMap[$id]); + } elseif (isset($this->methodMap[$id])) { + return $this->{$this->methodMap[$id]}(); + } elseif (--$i && $id !== $normalizedId = $this->normalizeId($id)) { + $id = $normalizedId; + continue; + } elseif (!$this->methodMap && !$this instanceof ContainerBuilder && __CLASS__ !== static::class && method_exists($this, $method = 'get'.strtr($id, $this->underscoreMap).'Service')) { + // We only check the convention-based factory in a compiled container (i.e. a child class other than a ContainerBuilder, + // and only when the dumper has not generated the method map (otherwise the method map is considered to be fully populated by the dumper) + @trigger_error('Generating a dumped container without populating the method map is deprecated since 3.2 and will be unsupported in 4.0. Update your dumper to generate the method map.', E_USER_DEPRECATED); + + return $this->{$method}(); + } + + break; } catch (\Exception $e) { unset($this->services[$id]); @@ -340,8 +326,22 @@ public function get($id, $invalidBehavior = self::EXCEPTION_ON_INVALID_REFERENCE } finally { unset($this->loading[$id]); } + } + + if (self::EXCEPTION_ON_INVALID_REFERENCE === $invalidBehavior) { + if (!$id) { + throw new ServiceNotFoundException($id); + } + + $alternatives = array(); + foreach ($this->getServiceIds() as $knownId) { + $lev = levenshtein($id, $knownId); + if ($lev <= strlen($id) / 3 || false !== strpos($knownId, $id)) { + $alternatives[] = $knownId; + } + } - return $service; + throw new ServiceNotFoundException($id, null, null, $alternatives); } } @@ -401,7 +401,7 @@ public function getServiceIds() } $ids[] = 'service_container'; - return array_unique(array_merge($ids, array_keys($this->methodMap), array_keys($this->services))); + return array_unique(array_merge($ids, array_keys($this->methodMap), array_keys($this->fileMap), array_keys($this->services))); } /** @@ -428,6 +428,16 @@ public static function underscore($id) return strtolower(preg_replace(array('/([A-Z]+)([A-Z][a-z])/', '/([a-z\d])([A-Z])/'), array('\\1_\\2', '\\1_\\2'), str_replace('_', '.', $id))); } + /** + * Creates a service by requiring its factory file. + * + * @return object The service created by the file + */ + protected function load($file) + { + return require $file; + } + /** * Fetches a variable from the environment. * diff --git a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php index 03d8f9babf100..cdcea02ed19d0 100644 --- a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php +++ b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php @@ -65,6 +65,8 @@ class PhpDumper extends Dumper private $docStar; private $serviceIdToMethodNameMap; private $usedMethodNames; + private $namespace; + private $asFiles; /** * @var \Symfony\Component\DependencyInjection\LazyProxy\PhpDumper\DumperInterface @@ -103,10 +105,11 @@ public function setProxyDumper(ProxyDumper $proxyDumper) * * class: The class name * * base_class: The base class name * * namespace: The class namespace + * * as_files: To split the container in several files * * @param array $options An array of options * - * @return string A PHP class representing of the service container + * @return string|array A PHP class representing the service container or an array of PHP files if the "as_files" option is set * * @throws EnvParameterException When an env var exists but has not been dumped */ @@ -117,9 +120,12 @@ public function dump(array $options = array()) 'class' => 'ProjectServiceContainer', 'base_class' => 'Container', 'namespace' => '', + 'as_files' => false, 'debug' => true, ), $options); + $this->namespace = $options['namespace']; + $this->asFiles = $options['as_files']; $this->initializeMethodNamesMap($options['base_class']); $this->docStar = $options['debug'] ? '*' : ''; @@ -149,22 +155,62 @@ public function dump(array $options = array()) } } - $code = $this->startClass($options['class'], $options['base_class'], $options['namespace']); + $code = + $this->startClass($options['class'], $options['base_class']). + $this->addServices(). + $this->addDefaultParametersMethod(). + $this->endClass() + ; - if ($this->container->isCompiled()) { - $code .= $this->addFrozenConstructor(); - $code .= $this->addFrozenCompile(); - $code .= $this->addFrozenIsCompiled(); + if ($this->asFiles) { + $fileStart = <<generateServiceFiles() as $file => $c) { + $files[$file] = $fileStart.$c; + } + foreach ($this->generateProxyClasses() as $file => $c) { + $files[$file] = " $c) { + $code["Container{$hash}/{$file}"] = $c; + } + array_pop($code); + $code["Container{$hash}/Container.php"] = implode("\nclass Container{$hash}", explode("\nclass {$options['class']}", $files['Container.php'], 2)); + $namespaceLine = $this->namespace ? "\nnamespace {$this->namespace};\n" : ''; + + $code[$options['class'].'.php'] = <<addConstructor(); + foreach ($this->generateProxyClasses() as $c) { + $code .= $c; + } } - $code .= - $this->addServices(). - $this->addDefaultParametersMethod(). - $this->endClass(). - $this->addProxyClasses() - ; $this->targetDirRegex = null; $unusedEnvs = array(); @@ -244,30 +290,27 @@ private function addServiceLocalTempVariables($cId, Definition $definition, arra } /** - * Generates code for the proxies to be attached after the container class. + * Generates code for the proxies. * * @return string */ - private function addProxyClasses() + private function generateProxyClasses() { - /* @var $definitions Definition[] */ - $definitions = array_filter( - $this->container->getDefinitions(), - array($this->getProxyDumper(), 'isProxyCandidate') - ); - $code = ''; + $definitions = $this->container->getDefinitions(); $strip = '' === $this->docStar && method_exists('Symfony\Component\HttpKernel\Kernel', 'stripComments'); - + $proxyDumper = $this->getProxyDumper(); + ksort($definitions); foreach ($definitions as $definition) { - $proxyCode = "\n".$this->getProxyDumper()->getProxyCode($definition); + if (!$proxyDumper->isProxyCandidate($definition)) { + continue; + } + $proxyCode = "\n".$proxyDumper->getProxyCode($definition); if ($strip) { $proxyCode = " $proxyCode; } - - return $code; } /** @@ -364,23 +407,6 @@ private function addServiceInlinedDefinitions($id, array $inlinedDefinitions) return $code; } - /** - * Adds the service return statement. - * - * @param string $id - * @param bool $isSimpleInstance - * - * @return string - */ - private function addServiceReturn($id, $isSimpleInstance) - { - if ($isSimpleInstance) { - return " }\n"; - } - - return "\n return \$instance;\n }\n"; - } - /** * Generates the service instance. * @@ -569,14 +595,12 @@ private function addServiceConfigurator(Definition $definition, $variableName = * * @param string $id * @param Definition $definition + * @param string &$file * * @return string */ - private function addService($id, Definition $definition) + private function addService($id, Definition $definition, &$file = null) { - if ($definition->isSynthetic()) { - return ''; - } $this->definitionVariables = new \SplObjectStorage(); $this->referenceVariables = array(); $this->variableCount = 0; @@ -620,23 +644,29 @@ private function addService($id, Definition $definition) $lazyInitialization = ''; } - // with proxies, for 5.3.3 compatibility, the getter must be public to be accessible to the initializer - $isProxyCandidate = $this->getProxyDumper()->isProxyCandidate($definition); - $visibility = $isProxyCandidate ? 'public' : 'protected'; + $asFile = $this->asFiles && $definition->isShared(); $methodName = $this->generateMethodName($id); - $code = <<docStar} * Gets the $public '$id'$shared$autowired service. * * $return */ - {$visibility} function {$methodName}($lazyInitialization) + protected function {$methodName}($lazyInitialization) { EOF; + } - $code .= $isProxyCandidate ? $this->getProxyDumper()->getProxyFactoryCode($definition, $id, "\$this->$methodName(false)") : ''; + if ($this->getProxyDumper()->isProxyCandidate($definition)) { + $factoryCode = $asFile ? "\$this->load(__DIR__.'/%s.php', false)" : '$this->%s(false)'; + $code .= $this->getProxyDumper()->getProxyFactoryCode($definition, $id, sprintf($factoryCode, $methodName)); + } if ($definition->isDeprecated()) { $code .= sprintf(" @trigger_error(%s, E_USER_DEPRECATED);\n\n", $this->export($definition->getDeprecationMessage($id))); @@ -654,9 +684,15 @@ private function addService($id, Definition $definition) $this->addServiceProperties($definition). $this->addServiceMethodCalls($definition). $this->addServiceConfigurator($definition). - $this->addServiceReturn($id, $isSimpleInstance) + (!$isSimpleInstance ? "\n return \$instance;\n" : '') ; + if ($asFile) { + $code = implode("\n", array_map(function ($line) { return $line ? substr($line, 8) : $line; }, explode("\n", $code))); + } else { + $code .= " }\n"; + } + $this->definitionVariables = null; $this->referenceVariables = null; @@ -674,6 +710,9 @@ private function addServices() $definitions = $this->container->getDefinitions(); ksort($definitions); foreach ($definitions as $id => $definition) { + if ($definition->isSynthetic() || ($this->asFiles && $definition->isShared())) { + continue; + } if ($definition->isPublic()) { $publicServices .= $this->addService($id, $definition); } else { @@ -684,6 +723,18 @@ private function addServices() return $publicServices.$privateServices; } + private function generateServiceFiles() + { + $definitions = $this->container->getDefinitions(); + ksort($definitions); + foreach ($definitions as $id => $definition) { + if (!$definition->isSynthetic() && $definition->isShared()) { + $code = $this->addService($id, $definition, $file); + yield $file => $code; + } + } + } + private function addNewInstance(Definition $definition, $return, $instantiation, $id) { $class = $this->dumpValue($definition->getClass()); @@ -737,16 +788,15 @@ private function addNewInstance(Definition $definition, $return, $instantiation, * * @param string $class Class name * @param string $baseClass The name of the base class - * @param string $namespace The class namespace * * @return string */ - private function startClass($class, $baseClass, $namespace) + private function startClass($class, $baseClass) { $bagClass = $this->container->isCompiled() ? 'use Symfony\Component\DependencyInjection\ParameterBag\FrozenParameterBag;' : 'use Symfony\Component\DependencyInjection\ParameterBag\\ParameterBag;'; - $namespaceLine = $namespace ? "\nnamespace $namespace;\n" : ''; + $namespaceLine = $this->namespace ? "\nnamespace {$this->namespace};\n" : ''; - return <<exportTargetDirs(); - $arguments = $this->container->getParameterBag()->all() ? 'new ParameterBag($this->getDefaultParameters())' : null; - - $code = <<docStar} * Constructor. */ public function __construct() - {{$targetDirs} - parent::__construct($arguments); - -EOF; - - $code .= $this->addNormalizedIds(); - $code .= $this->addMethodMap(); - $code .= $this->addPrivateServices(); - $code .= $this->addAliases(); - - $code .= <<<'EOF' - } - -EOF; - - return $code; - } - - /** - * Adds the constructor for a compiled container. - * - * @return string - */ - private function addFrozenConstructor() { - $targetDirs = $this->exportTargetDirs(); - $code = <<targetDirRegex) { + $dir = $this->asFiles ? '$this->targetDirs[0] = dirname(__DIR__)' : '__DIR__'; + $code .= <<targetDirMaxMatches}; ++\$i) { + \$this->targetDirs[\$i] = \$dir = dirname(\$dir); + } - /*{$this->docStar} - * Constructor. - */ - public function __construct() - {{$targetDirs} EOF; + } - if ($this->container->getParameterBag()->all()) { - $code .= "\n \$this->parameters = \$this->getDefaultParameters();\n"; + if ($this->container->isCompiled()) { + if ($this->container->getParameterBag()->all()) { + $code .= " \$this->parameters = \$this->getDefaultParameters();\n\n"; + } + $code .= " \$this->services = array();\n"; + } else { + $arguments = $this->container->getParameterBag()->all() ? 'new ParameterBag($this->getDefaultParameters())' : null; + $code .= " parent::__construct($arguments);\n"; } - $code .= "\n \$this->services = array();\n"; $code .= $this->addNormalizedIds(); $code .= $this->addMethodMap(); + $code .= $this->asFiles ? $this->addFileMap() : ''; $code .= $this->addPrivateServices(); $code .= $this->addAliases(); - $code .= <<<'EOF' } EOF; - - return $code; - } - - /** - * Adds the compile method for a compiled container. - * - * @return string - */ - private function addFrozenCompile() - { - return <<container->isCompiled()) { + $code .= <<docStar} * {@inheritdoc} @@ -860,18 +868,6 @@ public function compile() throw new LogicException('You cannot compile a dumped container that was already compiled.'); } -EOF; - } - - /** - * Adds the isCompiled method for a compiled container. - * - * @return string - */ - private function addFrozenIsCompiled() - { - return <<docStar} * {@inheritdoc} */ @@ -891,6 +887,49 @@ public function isFrozen() } EOF; + } + + if ($this->asFiles) { + $code .= <<docStar} + * {@inheritdoc} + */ + protected function load(\$file, \$lazyLoad = true) + { + return require \$file; + } + +EOF; + } + + $proxyDumper = $this->getProxyDumper(); + foreach ($this->container->getDefinitions() as $definition) { + if (!$proxyDumper->isProxyCandidate($definition)) { + continue; + } + if ($this->asFiles) { + $proxyLoader = '$this->load(__DIR__."/{$class}.php")'; + } elseif ($this->namespace) { + $proxyLoader = 'class_alias("'.$this->namespace.'\\\\{$class}", $class, false)'; + } else { + $proxyLoader = ''; + } + if ($proxyLoader) { + $proxyLoader = "class_exists(\$class, false) || {$proxyLoader};\n\n "; + } + $code .= <<container->getDefinitions(); - if (!$definitions || !$definitions = array_filter($definitions, function ($def) { return !$def->isSynthetic(); })) { - return ''; + ksort($definitions); + foreach ($definitions as $id => $definition) { + if (!$definition->isSynthetic() && (!$this->asFiles || !$definition->isShared())) { + $code .= ' '.$this->export($id).' => '.$this->export($this->generateMethodName($id)).",\n"; + } } - $code = " \$this->methodMap = array(\n"; + return $code ? " \$this->methodMap = array(\n{$code} );\n" : ''; + } + + /** + * Adds the fileMap property definition. + * + * @return string + */ + private function addFileMap() + { + $code = ''; + $definitions = $this->container->getDefinitions(); ksort($definitions); foreach ($definitions as $id => $definition) { - $code .= ' '.$this->export($id).' => '.$this->export($this->generateMethodName($id)).",\n"; + if (!$definition->isSynthetic() && $definition->isShared()) { + $code .= sprintf(" %s => __DIR__.'/%s.php',\n", $this->export($id), $this->generateMethodName($id)); + } } - return $code." );\n"; + return $code ? " \$this->fileMap = array(\n{$code} );\n" : ''; } /** @@ -1584,7 +1640,13 @@ private function getServiceCall($id, Reference $reference = null) return '$this'; } - if ($this->container->hasDefinition($id) && !$this->container->getDefinition($id)->isPublic()) { + if ($this->asFiles && $this->container->hasDefinition($id)) { + if ($this->container->getDefinition($id)->isShared()) { + $code = sprintf("\$this->load(__DIR__.'/%s.php')", $this->generateMethodName($id)); + } else { + $code = sprintf('$this->%s()', $this->generateMethodName($id)); + } + } elseif ($this->container->hasDefinition($id) && !$this->container->getDefinition($id)->isPublic()) { $code = sprintf('$this->%s()', $this->generateMethodName($id)); } elseif (null !== $reference && ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE !== $reference->getInvalidBehavior()) { $code = sprintf('$this->get(\'%s\', ContainerInterface::NULL_ON_INVALID_REFERENCE)', $id); @@ -1715,17 +1777,6 @@ private function getExpressionLanguage() return $this->expressionLanguage; } - private function exportTargetDirs() - { - return null === $this->targetDirRegex ? '' : <<targetDirMaxMatches}; ++\$i) { - \$this->targetDirs[\$i] = \$dir = dirname(\$dir); - } -EOF; - } - private function export($value) { if (null !== $this->targetDirRegex && is_string($value) && preg_match($this->targetDirRegex, $value, $matches, PREG_OFFSET_CAPTURE)) { @@ -1733,8 +1784,9 @@ private function export($value) $suffix = $matches[0][1] + strlen($matches[0][0]); $suffix = isset($value[$suffix]) ? '.'.$this->doExport(substr($value, $suffix)) : ''; $dirname = '__DIR__'; + $offset = 1 + $this->targetDirMaxMatches - count($matches); - if (0 < $offset = 1 + $this->targetDirMaxMatches - count($matches)) { + if ($this->asFiles || 0 < $offset) { $dirname = sprintf('$this->targetDirs[%d]', $offset); } diff --git a/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php b/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php index 4afb445c68ca8..fc5a950af4709 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php @@ -162,6 +162,18 @@ public function testAddService() } } + public function testDumpAsFiles() + { + $container = include self::$fixturesPath.'/containers/container9.php'; + $container->compile(); + $dumper = new PhpDumper($container); + $dump = print_r($dumper->dump(array('as_files' => true, 'file' => __DIR__)), true); + if ('\\' === DIRECTORY_SEPARATOR) { + $dump = str_replace('\\\\Fixtures\\\\includes\\\\foo.php', '/Fixtures/includes/foo.php', $dump); + } + $this->assertStringMatchesFormatFile(self::$fixturesPath.'/php/services9_as_files.txt', $dump); + } + public function testServicesWithAnonymousFactories() { $container = include self::$fixturesPath.'/containers/container19.php'; diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container9.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container9.php index 13b45fda07a70..6445e0f427e06 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container9.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container9.php @@ -34,6 +34,7 @@ ; $container ->register('foo_bar', '%foo_class%') + ->addArgument(new Reference('deprecated_service')) ->setShared(false) ; $container->getParameterBag()->clear(); diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/graphviz/services9.dot b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/graphviz/services9.dot index b316b93c1576b..df9a1cae7ce73 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/graphviz/services9.dot +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/graphviz/services9.dot @@ -38,6 +38,7 @@ digraph sc { node_foo -> node_foo_baz [label="" style="dashed"]; node_foo -> node_bar [label="setBar()" style="dashed"]; node_bar -> node_foo_baz [label="" style="filled"]; + node_foo_bar -> node_deprecated_service [label="" style="filled"]; node_method_call1 -> node_foo [label="setBar()" style="dashed"]; node_method_call1 -> node_foo2 [label="setBar()" style="dashed"]; node_method_call1 -> node_foo3 [label="setBar()" style="dashed"]; diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9.php index 4998b60f4c719..f1ba88974a66c 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9.php @@ -238,7 +238,7 @@ protected function getFooBarService() { $class = $this->getParameter('foo_class'); - return new $class(); + return new $class(${($_ = isset($this->services['deprecated_service']) ? $this->services['deprecated_service'] : $this->get('deprecated_service')) && false ?: '_'}); } /** diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_as_files.txt b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_as_files.txt new file mode 100644 index 0000000000000..3b80a904d3e9d --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_as_files.txt @@ -0,0 +1,434 @@ +Array +( + [Container%s/getBarService.php] => services['foo.baz']) ? $this->services['foo.baz'] : $this->load(__DIR__.'/getFoo_BazService.php')) && false ?: '_'}; + +$this->services['bar'] = $instance = new \Bar\FooClass('foo', $a, $this->getParameter('foo_bar')); + +$a->configure($instance); + +return $instance; + + [Container%s/getBazService.php] => services['baz'] = $instance = new \Baz(); + +$instance->setFoo(${($_ = isset($this->services['foo_with_inline']) ? $this->services['foo_with_inline'] : $this->load(__DIR__.'/getFooWithInlineService.php')) && false ?: '_'}); + +return $instance; + + [Container%s/getConfiguredServiceService.php] => setFoo(${($_ = isset($this->services['baz']) ? $this->services['baz'] : $this->load(__DIR__.'/getBazService.php')) && false ?: '_'}); + +$this->services['configured_service'] = $instance = new \stdClass(); + +$a->configureStdClass($instance); + +return $instance; + + [Container%s/getConfiguredServiceSimpleService.php] => services['configured_service_simple'] = $instance = new \stdClass(); + +(new \ConfClass('bar'))->configureStdClass($instance); + +return $instance; + + [Container%s/getDecoratorServiceService.php] => services['decorator_service'] = new \stdClass(); + + [Container%s/getDecoratorServiceWithNameService.php] => services['decorator_service_with_name'] = new \stdClass(); + + [Container%s/getDeprecatedServiceService.php] => services['deprecated_service'] = new \stdClass(); + + [Container%s/getFactoryServiceService.php] => services['factory_service'] = ${($_ = isset($this->services['foo.baz']) ? $this->services['foo.baz'] : $this->load(__DIR__.'/getFoo_BazService.php')) && false ?: '_'}->getInstance(); + + [Container%s/getFactoryServiceSimpleService.php] => services['factory_service_simple'] = (new \SimpleFactoryClass('foo'))->getInstance(); + + [Container%s/getFooService.php] => services['foo.baz']) ? $this->services['foo.baz'] : $this->load(__DIR__.'/getFoo_BazService.php')) && false ?: '_'}; + +$this->services['foo'] = $instance = \Bar\FooClass::getInstance('foo', $a, array('bar' => 'foo is bar', 'foobar' => 'bar'), true, $this); + +$instance->foo = 'bar'; +$instance->moo = $a; +$instance->qux = array('bar' => 'foo is bar', 'foobar' => 'bar'); +$instance->setBar(${($_ = isset($this->services['bar']) ? $this->services['bar'] : $this->load(__DIR__.'/getBarService.php')) && false ?: '_'}); +$instance->initialize(); +sc_configure($instance); + +return $instance; + + [Container%s/getFoo_BazService.php] => services['foo.baz'] = $instance = \BazClass::getInstance(); + +\BazClass::configureStatic1($instance); + +return $instance; + + [Container%s/getFooWithInlineService.php] => services['foo_with_inline'] = $instance = new \Foo(); + +$a->pub = 'pub'; +$a->setBaz(${($_ = isset($this->services['baz']) ? $this->services['baz'] : $this->load(__DIR__.'/getBazService.php')) && false ?: '_'}); + +$instance->setBar($a); + +return $instance; + + [Container%s/getLazyContextService.php] => services['lazy_context'] = new \LazyContext(new RewindableGenerator(function () { + yield 'k1' => ${($_ = isset($this->services['foo.baz']) ? $this->services['foo.baz'] : $this->load(__DIR__.'/getFoo_BazService.php')) && false ?: '_'}; + yield 'k2' => $this; +}, 2), new RewindableGenerator(function () { + return new \EmptyIterator(); +}, 0)); + + [Container%s/getLazyContextIgnoreInvalidRefService.php] => services['lazy_context_ignore_invalid_ref'] = new \LazyContext(new RewindableGenerator(function () { + yield 0 => ${($_ = isset($this->services['foo.baz']) ? $this->services['foo.baz'] : $this->load(__DIR__.'/getFoo_BazService.php')) && false ?: '_'}; +}, 1), new RewindableGenerator(function () { + return new \EmptyIterator(); +}, 0)); + + [Container%s/getMethodCall1Service.php] => targetDirs[0].'/Fixtures/includes/foo.php'); + +$this->services['method_call1'] = $instance = new \Bar\FooClass(); + +$instance->setBar(${($_ = isset($this->services['foo']) ? $this->services['foo'] : $this->load(__DIR__.'/getFooService.php')) && false ?: '_'}); +$instance->setBar(NULL); +$instance->setBar((${($_ = isset($this->services['foo']) ? $this->services['foo'] : $this->load(__DIR__.'/getFooService.php')) && false ?: '_'}->foo() . (($this->hasParameter("foo")) ? ($this->getParameter("foo")) : ("default")))); + +return $instance; + + [Container%s/getNewFactoryServiceService.php] => foo = 'bar'; + +$this->services['new_factory_service'] = $instance = $a->getInstance(); + +$instance->foo = 'bar'; + +return $instance; + + [Container%s/getServiceFromStaticMethodService.php] => services['service_from_static_method'] = \Bar\FooClass::getInstance(); + + [Container%s/Container.php] => targetDirs[0] = dirname(__DIR__); + for ($i = 1; $i <= 5; ++$i) { + $this->targetDirs[$i] = $dir = dirname($dir); + } + $this->parameters = $this->getDefaultParameters(); + + $this->services = array(); + $this->methodMap = array( + 'foo_bar' => 'getFooBarService', + ); + $this->fileMap = array( + 'bar' => __DIR__.'/getBarService.php', + 'baz' => __DIR__.'/getBazService.php', + 'configured_service' => __DIR__.'/getConfiguredServiceService.php', + 'configured_service_simple' => __DIR__.'/getConfiguredServiceSimpleService.php', + 'decorator_service' => __DIR__.'/getDecoratorServiceService.php', + 'decorator_service_with_name' => __DIR__.'/getDecoratorServiceWithNameService.php', + 'deprecated_service' => __DIR__.'/getDeprecatedServiceService.php', + 'factory_service' => __DIR__.'/getFactoryServiceService.php', + 'factory_service_simple' => __DIR__.'/getFactoryServiceSimpleService.php', + 'foo' => __DIR__.'/getFooService.php', + 'foo.baz' => __DIR__.'/getFoo_BazService.php', + 'foo_with_inline' => __DIR__.'/getFooWithInlineService.php', + 'lazy_context' => __DIR__.'/getLazyContextService.php', + 'lazy_context_ignore_invalid_ref' => __DIR__.'/getLazyContextIgnoreInvalidRefService.php', + 'method_call1' => __DIR__.'/getMethodCall1Service.php', + 'new_factory_service' => __DIR__.'/getNewFactoryServiceService.php', + 'service_from_static_method' => __DIR__.'/getServiceFromStaticMethodService.php', + ); + $this->aliases = array( + 'alias_for_alias' => 'foo', + 'alias_for_foo' => 'foo', + 'decorated' => 'decorator_service_with_name', + ); + } + + /** + * {@inheritdoc} + */ + public function compile() + { + throw new LogicException('You cannot compile a dumped container that was already compiled.'); + } + + /** + * {@inheritdoc} + */ + public function isCompiled() + { + return true; + } + + /** + * {@inheritdoc} + */ + public function isFrozen() + { + @trigger_error(sprintf('The %s() method is deprecated since version 3.3 and will be removed in 4.0. Use the isCompiled() method instead.', __METHOD__), E_USER_DEPRECATED); + + return true; + } + + /** + * {@inheritdoc} + */ + protected function load($file, $lazyLoad = true) + { + return require $file; + } + + /** + * Gets the public 'foo_bar' service. + * + * @return \Bar\FooClass + */ + protected function getFooBarService() + { + return new \Bar\FooClass(${($_ = isset($this->services['deprecated_service']) ? $this->services['deprecated_service'] : $this->load(__DIR__.'/getDeprecatedServiceService.php')) && false ?: '_'}); + } + + /** + * {@inheritdoc} + */ + public function getParameter($name) + { + if (!(isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters))) { + $name = strtolower($name); + + if (!(isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters))) { + throw new InvalidArgumentException(sprintf('The parameter "%s" must be defined.', $name)); + } + } + if (isset($this->loadedDynamicParameters[$name])) { + return $this->loadedDynamicParameters[$name] ? $this->dynamicParameters[$name] : $this->getDynamicParameter($name); + } + + return $this->parameters[$name]; + } + + /** + * {@inheritdoc} + */ + public function hasParameter($name) + { + $name = strtolower($name); + + return isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters); + } + + /** + * {@inheritdoc} + */ + public function setParameter($name, $value) + { + throw new LogicException('Impossible to call set() on a frozen ParameterBag.'); + } + + /** + * {@inheritdoc} + */ + public function getParameterBag() + { + if (null === $this->parameterBag) { + $parameters = $this->parameters; + foreach ($this->loadedDynamicParameters as $name => $loaded) { + $parameters[$name] = $loaded ? $this->dynamicParameters[$name] : $this->getDynamicParameter($name); + } + $this->parameterBag = new FrozenParameterBag($parameters); + } + + return $this->parameterBag; + } + + private $loadedDynamicParameters = array(); + private $dynamicParameters = array(); + + /** + * Computes a dynamic parameter. + * + * @param string The name of the dynamic parameter to load + * + * @return mixed The value of the dynamic parameter + * + * @throws InvalidArgumentException When the dynamic parameter does not exist + */ + private function getDynamicParameter($name) + { + throw new InvalidArgumentException(sprintf('The dynamic parameter "%s" must be defined.', $name)); + } + + /** + * Gets the default parameters. + * + * @return array An array of the default parameters + */ + protected function getDefaultParameters() + { + return array( + 'baz_class' => 'BazClass', + 'foo_class' => 'Bar\\FooClass', + 'foo' => 'bar', + ); + } +} + + [ProjectServiceContainer.php] => services['deprecated_service']) ? $this->services['deprecated_service'] : $this->get('deprecated_service')) && false ?: '_'}); } /** diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services9.xml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services9.xml index 100a23a9c5b7e..fb2050ab6191f 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services9.xml +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services9.xml @@ -41,7 +41,9 @@ %foo_bar% - + + + %path%foo.php diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services9.yml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services9.yml index a7a9cc28fd61b..984f2136700c0 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services9.yml +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services9.yml @@ -31,6 +31,7 @@ services: foo_bar: class: '%foo_class%' shared: false + arguments: ['@deprecated_service'] method_call1: class: Bar\FooClass file: '%path%foo.php' diff --git a/src/Symfony/Component/HttpKernel/Kernel.php b/src/Symfony/Component/HttpKernel/Kernel.php index 4b065f56a0fc0..a6c31e8a3f821 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -22,6 +22,7 @@ use Symfony\Component\DependencyInjection\Loader\PhpFileLoader; use Symfony\Component\DependencyInjection\Loader\DirectoryLoader; use Symfony\Component\DependencyInjection\Loader\ClosureLoader; +use Symfony\Component\Filesystem\Filesystem; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\Bundle\BundleInterface; @@ -588,9 +589,7 @@ protected function initializeContainer() $fresh = false; } - require_once $cache->getPath(); - - $this->container = new $class(); + $this->container = require $cache->getPath(); $this->container->set('kernel', $this); if (!$fresh && $this->container->has('cache_warmer')) { @@ -757,9 +756,24 @@ protected function dumpContainer(ConfigCache $cache, ContainerBuilder $container $dumper->setProxyDumper(new ProxyDumper(substr(hash('sha256', $cache->getPath()), 0, 7))); } - $content = $dumper->dump(array('class' => $class, 'base_class' => $baseClass, 'file' => $cache->getPath(), 'debug' => $this->debug)); + $content = $dumper->dump(array( + 'class' => $class, + 'base_class' => $baseClass, + 'file' => $cache->getPath(), + 'as_files' => true, + 'debug' => $this->debug, + )); + + $rootCode = array_pop($content); + $dir = dirname($cache->getPath()).'/'; + $fs = new Filesystem(); + + foreach ($content as $file => $code) { + $fs->dumpFile($dir.$file, $code, null); + @chmod($dir.$file, 0666 & ~umask()); + } - $cache->write($content, $container->getResources()); + $cache->write($rootCode, $container->getResources()); } /** diff --git a/src/Symfony/Component/HttpKernel/composer.json b/src/Symfony/Component/HttpKernel/composer.json index 053ea74b27c48..3c051bb5f7b33 100644 --- a/src/Symfony/Component/HttpKernel/composer.json +++ b/src/Symfony/Component/HttpKernel/composer.json @@ -28,7 +28,7 @@ "symfony/config": "~2.8|~3.0|~4.0", "symfony/console": "~2.8|~3.0|~4.0", "symfony/css-selector": "~2.8|~3.0|~4.0", - "symfony/dependency-injection": "~3.3|~4.0", + "symfony/dependency-injection": "~3.4|~4.0", "symfony/dom-crawler": "~2.8|~3.0|~4.0", "symfony/expression-language": "~2.8|~3.0|~4.0", "symfony/finder": "~2.8|~3.0|~4.0", @@ -42,7 +42,7 @@ }, "conflict": { "symfony/config": "<2.8", - "symfony/dependency-injection": "<3.3", + "symfony/dependency-injection": "<3.4", "symfony/var-dumper": "<3.3", "twig/twig": "<1.34|<2.4,>=2" }, From 94b1b12b55f400a9b38e3307375311a06db9fea6 Mon Sep 17 00:00:00 2001 From: Lars Strojny Date: Wed, 2 Aug 2017 15:53:45 +0200 Subject: [PATCH 0584/1099] Hash cache keys on save --- src/Symfony/Component/Cache/Adapter/AbstractAdapter.php | 9 +++++---- .../Cache/Tests/Adapter/PhpArrayAdapterTest.php | 1 + .../Component/Cache/Tests/Simple/PhpArrayCacheTest.php | 3 +++ 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/Symfony/Component/Cache/Adapter/AbstractAdapter.php b/src/Symfony/Component/Cache/Adapter/AbstractAdapter.php index 26b33e683e2ff..9bc05fd2b30fd 100644 --- a/src/Symfony/Component/Cache/Adapter/AbstractAdapter.php +++ b/src/Symfony/Component/Cache/Adapter/AbstractAdapter.php @@ -55,19 +55,20 @@ function ($key, $value, $isHit) use ($defaultLifetime) { null, CacheItem::class ); + $getId = function ($key) { return $this->getId((string) $key); }; $this->mergeByLifetime = \Closure::bind( - function ($deferred, $namespace, &$expiredIds) { + function ($deferred, $namespace, &$expiredIds) use ($getId) { $byLifetime = array(); $now = time(); $expiredIds = array(); foreach ($deferred as $key => $item) { if (null === $item->expiry) { - $byLifetime[0 < $item->defaultLifetime ? $item->defaultLifetime : 0][$namespace.$key] = $item->value; + $byLifetime[0 < $item->defaultLifetime ? $item->defaultLifetime : 0][$getId($key)] = $item->value; } elseif ($item->expiry > $now) { - $byLifetime[$item->expiry - $now][$namespace.$key] = $item->value; + $byLifetime[$item->expiry - $now][$getId($key)] = $item->value; } else { - $expiredIds[] = $namespace.$key; + $expiredIds[] = $getId($key); } } diff --git a/src/Symfony/Component/Cache/Tests/Adapter/PhpArrayAdapterTest.php b/src/Symfony/Component/Cache/Tests/Adapter/PhpArrayAdapterTest.php index ae0edb7d11dd6..134dba7c90444 100644 --- a/src/Symfony/Component/Cache/Tests/Adapter/PhpArrayAdapterTest.php +++ b/src/Symfony/Component/Cache/Tests/Adapter/PhpArrayAdapterTest.php @@ -22,6 +22,7 @@ class PhpArrayAdapterTest extends AdapterTestCase { protected $skippedTests = array( 'testBasicUsage' => 'PhpArrayAdapter is read-only.', + 'testBasicUsageWithLongKey' => 'PhpArrayAdapter is read-only.', 'testClear' => 'PhpArrayAdapter is read-only.', 'testClearWithDeferredItems' => 'PhpArrayAdapter is read-only.', 'testDeleteItem' => 'PhpArrayAdapter is read-only.', diff --git a/src/Symfony/Component/Cache/Tests/Simple/PhpArrayCacheTest.php b/src/Symfony/Component/Cache/Tests/Simple/PhpArrayCacheTest.php index 3016ac560ed06..57361905f8869 100644 --- a/src/Symfony/Component/Cache/Tests/Simple/PhpArrayCacheTest.php +++ b/src/Symfony/Component/Cache/Tests/Simple/PhpArrayCacheTest.php @@ -21,6 +21,8 @@ class PhpArrayCacheTest extends CacheTestCase { protected $skippedTests = array( + 'testBasicUsageWithLongKey' => 'PhpArrayCache does no writes', + 'testDelete' => 'PhpArrayCache does no writes', 'testDeleteMultiple' => 'PhpArrayCache does no writes', 'testDeleteMultipleGenerator' => 'PhpArrayCache does no writes', @@ -57,6 +59,7 @@ protected function tearDown() FilesystemAdapterTest::rmdir(sys_get_temp_dir().'/symfony-cache'); } } + public function createSimpleCache() { return new PhpArrayCacheWrapper(self::$file, new NullCache()); From 29538b621c934358e3cf64a4c181a4d4c4fef6c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9my=20Deruss=C3=A9?= Date: Tue, 1 Aug 2017 22:29:59 +0200 Subject: [PATCH 0585/1099] Ignore memcached missing key error on dession destroy --- .../Session/Storage/Handler/MemcacheSessionHandler.php | 4 +++- .../Session/Storage/Handler/MemcachedSessionHandler.php | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/MemcacheSessionHandler.php b/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/MemcacheSessionHandler.php index 962a3878d9767..4e490a05d4ce0 100644 --- a/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/MemcacheSessionHandler.php +++ b/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/MemcacheSessionHandler.php @@ -95,7 +95,9 @@ public function write($sessionId, $data) */ public function destroy($sessionId) { - return $this->memcache->delete($this->prefix.$sessionId); + $this->memcache->delete($this->prefix.$sessionId); + + return true; } /** diff --git a/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/MemcachedSessionHandler.php b/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/MemcachedSessionHandler.php index 76b08e2db944c..67a49ad6f5e2a 100644 --- a/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/MemcachedSessionHandler.php +++ b/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/MemcachedSessionHandler.php @@ -101,7 +101,9 @@ public function write($sessionId, $data) */ public function destroy($sessionId) { - return $this->memcached->delete($this->prefix.$sessionId); + $result = $this->memcached->delete($this->prefix.$sessionId); + + return $result || $this->memcached->getResultCode() == \Memcached::RES_NOTFOUND; } /** From c254cacdc5b2d16c59396c55b03339f565d816f9 Mon Sep 17 00:00:00 2001 From: izzyp Date: Sun, 30 Apr 2017 16:11:37 +0100 Subject: [PATCH 0586/1099] [Workflow] Added an transition completed event --- src/Symfony/Component/Workflow/CHANGELOG.md | 1 + .../Component/Workflow/Tests/WorkflowTest.php | 3 +++ src/Symfony/Component/Workflow/Workflow.php | 15 +++++++++++++++ 3 files changed, 19 insertions(+) diff --git a/src/Symfony/Component/Workflow/CHANGELOG.md b/src/Symfony/Component/Workflow/CHANGELOG.md index d1b50cb4ef497..02c04f6dc08f6 100644 --- a/src/Symfony/Component/Workflow/CHANGELOG.md +++ b/src/Symfony/Component/Workflow/CHANGELOG.md @@ -5,6 +5,7 @@ CHANGELOG ----- * Added support for `Event::getWorkflowName()` for "announce" events. + * Added `workflow.completed` events which are fired after a transition is completed. 3.3.0 ----- diff --git a/src/Symfony/Component/Workflow/Tests/WorkflowTest.php b/src/Symfony/Component/Workflow/Tests/WorkflowTest.php index 45dcbc73ccb62..547fb03e82cfe 100644 --- a/src/Symfony/Component/Workflow/Tests/WorkflowTest.php +++ b/src/Symfony/Component/Workflow/Tests/WorkflowTest.php @@ -287,6 +287,9 @@ public function testApplyWithEventDispatcher() 'workflow.workflow_name.entered', 'workflow.workflow_name.entered.b', 'workflow.workflow_name.entered.c', + 'workflow.completed', + 'workflow.workflow_name.completed', + 'workflow.workflow_name.completed.t1', // Following events are fired because of announce() method 'workflow.announce', 'workflow.workflow_name.announce', diff --git a/src/Symfony/Component/Workflow/Workflow.php b/src/Symfony/Component/Workflow/Workflow.php index 31c830fcee906..d3d18f03746a7 100644 --- a/src/Symfony/Component/Workflow/Workflow.php +++ b/src/Symfony/Component/Workflow/Workflow.php @@ -151,6 +151,8 @@ public function apply($subject, $transitionName) $this->entered($subject, $transition, $marking); + $this->completed($subject, $transition, $marking); + $this->announce($subject, $transition, $marking); } @@ -309,6 +311,19 @@ private function entered($subject, Transition $transition, Marking $marking) } } + private function completed($subject, Transition $transition, Marking $marking) + { + if (null === $this->dispatcher) { + return; + } + + $event = new Event($subject, $marking, $transition, $this->name); + + $this->dispatcher->dispatch('workflow.completed', $event); + $this->dispatcher->dispatch(sprintf('workflow.%s.completed', $this->name), $event); + $this->dispatcher->dispatch(sprintf('workflow.%s.completed.%s', $this->name, $transition->getName()), $event); + } + private function announce($subject, Transition $initialTransition, Marking $marking) { if (null === $this->dispatcher) { From 3bb0a3f95cf2c359448893c763633e289eae2c13 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Wed, 2 Aug 2017 09:15:14 +0200 Subject: [PATCH 0587/1099] [Yaml] parse inlined tags without values --- src/Symfony/Component/Yaml/Inline.php | 2 +- .../Component/Yaml/Tests/InlineTest.php | 37 +++++++++++++++++++ 2 files changed, 38 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/Yaml/Inline.php b/src/Symfony/Component/Yaml/Inline.php index d2d39b644e07c..3212aeca58963 100644 --- a/src/Symfony/Component/Yaml/Inline.php +++ b/src/Symfony/Component/Yaml/Inline.php @@ -644,7 +644,7 @@ private static function parseTag($value, &$i, $flags) return; } - $tagLength = strcspn($value, " \t\n", $i + 1); + $tagLength = strcspn($value, " \t\n[]{},", $i + 1); $tag = substr($value, $i + 1, $tagLength); $nextOffset = $i + $tagLength + 1; diff --git a/src/Symfony/Component/Yaml/Tests/InlineTest.php b/src/Symfony/Component/Yaml/Tests/InlineTest.php index b1a4c1ccb5cde..784a269182377 100644 --- a/src/Symfony/Component/Yaml/Tests/InlineTest.php +++ b/src/Symfony/Component/Yaml/Tests/InlineTest.php @@ -14,6 +14,7 @@ use PHPUnit\Framework\TestCase; use Symfony\Component\Yaml\Exception\ParseException; use Symfony\Component\Yaml\Inline; +use Symfony\Component\Yaml\Tag\TaggedValue; use Symfony\Component\Yaml\Yaml; class InlineTest extends TestCase @@ -695,4 +696,40 @@ public function getNotPhpCompatibleMappingKeyData() 'float' => array('{0.25: "foo"}', array('0.25' => 'foo')), ); } + + public function testTagWithoutValueInSequence() + { + $value = Inline::parse('[!foo]', Yaml::PARSE_CUSTOM_TAGS); + + $this->assertInstanceOf(TaggedValue::class, $value[0]); + $this->assertSame('foo', $value[0]->getTag()); + $this->assertSame('', $value[0]->getValue()); + } + + public function testTagWithEmptyValueInSequence() + { + $value = Inline::parse('[!foo ""]', Yaml::PARSE_CUSTOM_TAGS); + + $this->assertInstanceOf(TaggedValue::class, $value[0]); + $this->assertSame('foo', $value[0]->getTag()); + $this->assertSame('', $value[0]->getValue()); + } + + public function testTagWithoutValueInMapping() + { + $value = Inline::parse('{foo: !bar}', Yaml::PARSE_CUSTOM_TAGS); + + $this->assertInstanceOf(TaggedValue::class, $value['foo']); + $this->assertSame('bar', $value['foo']->getTag()); + $this->assertSame('', $value['foo']->getValue()); + } + + public function testTagWithEmptyValueInMapping() + { + $value = Inline::parse('{foo: !bar ""}', Yaml::PARSE_CUSTOM_TAGS); + + $this->assertInstanceOf(TaggedValue::class, $value['foo']); + $this->assertSame('bar', $value['foo']->getTag()); + $this->assertSame('', $value['foo']->getValue()); + } } From c9ff0299999a12a801515f9ae3fc55149d8f2fc2 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Mon, 7 Aug 2017 12:35:57 +0200 Subject: [PATCH 0588/1099] remove deprecated code --- .../FrameworkBundle/Command/AboutCommand.php | 3 +- .../Command/AssetsInstallCommand.php | 24 ++------ .../Command/CacheClearCommand.php | 3 +- .../Command/CachePoolClearCommand.php | 24 ++------ .../Command/CacheWarmupCommand.php | 24 ++------ .../Command/ContainerDebugCommand.php | 3 +- .../Command/EventDispatcherDebugCommand.php | 33 +---------- .../Command/RouterDebugCommand.php | 42 +------------- .../Command/RouterMatchCommand.php | 42 +------------- .../Command/TranslationDebugCommand.php | 42 +------------- .../Command/TranslationUpdateCommand.php | 38 +----------- .../Command/WorkflowDumpCommand.php | 13 +---- .../Command/XliffLintCommand.php | 30 ++++------ .../Command/YamlLintCommand.php | 30 ++++------ .../Tests/Command/RouterDebugCommandTest.php | 16 ----- .../Tests/Command/RouterMatchCommandTest.php | 18 ------ .../Command/TranslationDebugCommandTest.php | 45 -------------- .../Command/TranslationUpdateCommandTest.php | 47 --------------- .../Functional/CachePoolClearCommandTest.php | 16 ----- .../SecurityBundle/Command/InitAclCommand.php | 38 +----------- .../SecurityBundle/Command/SetAclCommand.php | 58 ++----------------- .../Tests/Functional/SetAclCommandTest.php | 2 +- .../Bundle/TwigBundle/Command/LintCommand.php | 7 +-- src/Symfony/Component/Yaml/Parser.php | 10 +--- .../Component/Yaml/Tests/ParserTest.php | 10 ---- src/Symfony/Component/Yaml/Yaml.php | 5 -- 26 files changed, 67 insertions(+), 556 deletions(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/AboutCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/AboutCommand.php index 3b9130a8e40a8..e4852da379957 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/AboutCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/AboutCommand.php @@ -11,6 +11,7 @@ namespace Symfony\Bundle\FrameworkBundle\Command; +use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Helper\Helper; use Symfony\Component\Console\Helper\TableSeparator; use Symfony\Component\Console\Input\InputInterface; @@ -26,7 +27,7 @@ * * @final since version 3.4 */ -class AboutCommand extends ContainerAwareCommand +class AboutCommand extends Command { /** * {@inheritdoc} diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/AssetsInstallCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/AssetsInstallCommand.php index 4a31f8090173b..d314748670bad 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/AssetsInstallCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/AssetsInstallCommand.php @@ -11,6 +11,7 @@ namespace Symfony\Bundle\FrameworkBundle\Command; +use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; @@ -29,7 +30,7 @@ * * @final since version 3.4 */ -class AssetsInstallCommand extends ContainerAwareCommand +class AssetsInstallCommand extends Command { const METHOD_COPY = 'copy'; const METHOD_ABSOLUTE_SYMLINK = 'absolute symlink'; @@ -37,19 +38,8 @@ class AssetsInstallCommand extends ContainerAwareCommand private $filesystem; - /** - * @param Filesystem $filesystem - */ - public function __construct($filesystem = null) + public function __construct(Filesystem $filesystem) { - if (!$filesystem instanceof Filesystem) { - @trigger_error(sprintf('Passing a command name as the first argument of "%s" is deprecated since version 3.4 and will be removed in 4.0. If the command was registered by convention, make it a service instead.', __METHOD__), E_USER_DEPRECATED); - - parent::__construct($filesystem); - - return; - } - parent::__construct(); $this->filesystem = $filesystem; @@ -96,17 +86,11 @@ protected function configure() */ protected function execute(InputInterface $input, OutputInterface $output) { - // BC to be removed in 4.0 - if (null === $this->filesystem) { - $this->filesystem = $this->getContainer()->get('filesystem'); - $baseDir = $this->getContainer()->getParameter('kernel.project_dir'); - } - $kernel = $this->getApplication()->getKernel(); $targetArg = rtrim($input->getArgument('target'), '/'); if (!is_dir($targetArg)) { - $targetArg = (isset($baseDir) ? $baseDir : $kernel->getContainer()->getParameter('kernel.project_dir')).'/'.$targetArg; + $targetArg = $kernel->getContainer()->getParameter('kernel.project_dir').'/'.$targetArg; if (!is_dir($targetArg)) { throw new \InvalidArgumentException(sprintf('The target directory "%s" does not exist.', $input->getArgument('target'))); diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/CacheClearCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/CacheClearCommand.php index 9d90c594ec51c..23867b58ff2d5 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/CacheClearCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/CacheClearCommand.php @@ -11,6 +11,7 @@ namespace Symfony\Bundle\FrameworkBundle\Command; +use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; @@ -26,7 +27,7 @@ * * @final since version 3.4 */ -class CacheClearCommand extends ContainerAwareCommand +class CacheClearCommand extends Command { private $cacheClearer; private $filesystem; diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/CachePoolClearCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/CachePoolClearCommand.php index fec933f67b9ce..2bd42e69ec2f6 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/CachePoolClearCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/CachePoolClearCommand.php @@ -12,6 +12,7 @@ namespace Symfony\Bundle\FrameworkBundle\Command; use Psr\Cache\CacheItemPoolInterface; +use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Output\OutputInterface; @@ -23,23 +24,12 @@ * * @author Nicolas Grekas */ -final class CachePoolClearCommand extends ContainerAwareCommand +final class CachePoolClearCommand extends Command { private $poolClearer; - /** - * @param Psr6CacheClearer $poolClearer - */ - public function __construct($poolClearer = null) + public function __construct(Psr6CacheClearer $poolClearer) { - if (!$poolClearer instanceof Psr6CacheClearer) { - @trigger_error(sprintf('Passing a command name as the first argument of "%s" is deprecated since version 3.4 and will be removed in 4.0. If the command was registered by convention, make it a service instead.', __METHOD__), E_USER_DEPRECATED); - - parent::__construct($poolClearer); - - return; - } - parent::__construct(); $this->poolClearer = $poolClearer; @@ -70,12 +60,6 @@ protected function configure() */ protected function execute(InputInterface $input, OutputInterface $output) { - // BC to be removed in 4.0 - if (null === $this->poolClearer) { - $this->poolClearer = $this->getContainer()->get('cache.global_clearer'); - $cacheDir = $this->getContainer()->getParameter('kernel.cache_dir'); - } - $io = new SymfonyStyle($input, $output); $kernel = $this->getApplication()->getKernel(); $pools = array(); @@ -99,7 +83,7 @@ protected function execute(InputInterface $input, OutputInterface $output) foreach ($clearers as $id => $clearer) { $io->comment(sprintf('Calling cache clearer: %s', $id)); - $clearer->clear(isset($cacheDir) ? $cacheDir : $kernel->getContainer()->getParameter('kernel.cache_dir')); + $clearer->clear($kernel->getContainer()->getParameter('kernel.cache_dir')); } foreach ($pools as $id => $pool) { diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/CacheWarmupCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/CacheWarmupCommand.php index 57972782dc771..b890ce8c3f1e2 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/CacheWarmupCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/CacheWarmupCommand.php @@ -11,6 +11,7 @@ namespace Symfony\Bundle\FrameworkBundle\Command; +use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; @@ -24,23 +25,12 @@ * * @final since version 3.4 */ -class CacheWarmupCommand extends ContainerAwareCommand +class CacheWarmupCommand extends Command { private $cacheWarmer; - /** - * @param CacheWarmerAggregate $cacheWarmer - */ - public function __construct($cacheWarmer = null) + public function __construct(CacheWarmerAggregate $cacheWarmer) { - if (!$cacheWarmer instanceof CacheWarmerAggregate) { - @trigger_error(sprintf('Passing a command name as the first argument of "%s" is deprecated since version 3.4 and will be removed in 4.0. If the command was registered by convention, make it a service instead.', __METHOD__), E_USER_DEPRECATED); - - parent::__construct($cacheWarmer); - - return; - } - parent::__construct(); $this->cacheWarmer = $cacheWarmer; @@ -77,12 +67,6 @@ protected function configure() */ protected function execute(InputInterface $input, OutputInterface $output) { - // BC to be removed in 4.0 - if (null === $this->cacheWarmer) { - $this->cacheWarmer = $this->getContainer()->get('cache_warmer'); - $cacheDir = $this->getContainer()->getParameter('kernel.cache_dir'); - } - $io = new SymfonyStyle($input, $output); $kernel = $this->getApplication()->getKernel(); @@ -92,7 +76,7 @@ protected function execute(InputInterface $input, OutputInterface $output) $this->cacheWarmer->enableOptionalWarmers(); } - $this->cacheWarmer->warmUp(isset($cacheDir) ? $cacheDir : $kernel->getContainer()->getParameter('kernel.cache_dir')); + $this->cacheWarmer->warmUp($kernel->getContainer()->getParameter('kernel.cache_dir')); $io->success(sprintf('Cache for the "%s" environment (debug=%s) was successfully warmed.', $kernel->getEnvironment(), var_export($kernel->isDebug(), true))); } diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/ContainerDebugCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/ContainerDebugCommand.php index 51c04969877e6..6ec4f4b8c4b3b 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/ContainerDebugCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/ContainerDebugCommand.php @@ -13,6 +13,7 @@ use Symfony\Bundle\FrameworkBundle\Console\Helper\DescriptorHelper; use Symfony\Component\Config\ConfigCache; +use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Input\InputInterface; @@ -30,7 +31,7 @@ * * @internal since version 3.4 */ -class ContainerDebugCommand extends ContainerAwareCommand +class ContainerDebugCommand extends Command { /** * @var ContainerBuilder|null diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/EventDispatcherDebugCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/EventDispatcherDebugCommand.php index 18aa08575c4e0..69144d300e938 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/EventDispatcherDebugCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/EventDispatcherDebugCommand.php @@ -12,6 +12,7 @@ namespace Symfony\Bundle\FrameworkBundle\Command; use Symfony\Bundle\FrameworkBundle\Console\Helper\DescriptorHelper; +use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Input\InputInterface; @@ -26,23 +27,12 @@ * * @final since version 3.4 */ -class EventDispatcherDebugCommand extends ContainerAwareCommand +class EventDispatcherDebugCommand extends Command { private $dispatcher; - /** - * @param EventDispatcherInterface $dispatcher - */ - public function __construct($dispatcher = null) + public function __construct(EventDispatcherInterface $dispatcher) { - if (!$dispatcher instanceof EventDispatcherInterface) { - @trigger_error(sprintf('Passing a command name as the first argument of "%s" is deprecated since version 3.4 and will be removed in 4.0. If the command was registered by convention, make it a service instead.', __METHOD__), E_USER_DEPRECATED); - - parent::__construct($dispatcher); - - return; - } - parent::__construct(); $this->dispatcher = $dispatcher; @@ -81,11 +71,6 @@ protected function configure() */ protected function execute(InputInterface $input, OutputInterface $output) { - // BC to be removed in 4.0 - if (null === $this->dispatcher) { - $this->dispatcher = $this->getEventDispatcher(); - } - $io = new SymfonyStyle($input, $output); $options = array(); @@ -105,16 +90,4 @@ protected function execute(InputInterface $input, OutputInterface $output) $options['output'] = $io; $helper->describe($io, $this->dispatcher, $options); } - - /** - * Loads the Event Dispatcher from the container. - * - * BC to removed in 4.0 - * - * @return EventDispatcherInterface - */ - protected function getEventDispatcher() - { - return $this->getContainer()->get('event_dispatcher'); - } } diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/RouterDebugCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/RouterDebugCommand.php index 2a005090322dd..61345c0c4968d 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/RouterDebugCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/RouterDebugCommand.php @@ -13,6 +13,7 @@ use Symfony\Bundle\FrameworkBundle\Console\Helper\DescriptorHelper; use Symfony\Bundle\FrameworkBundle\Controller\ControllerNameParser; +use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; @@ -30,49 +31,17 @@ * * @final since version 3.4 */ -class RouterDebugCommand extends ContainerAwareCommand +class RouterDebugCommand extends Command { private $router; - /** - * @param RouterInterface $router - */ - public function __construct($router = null) + public function __construct(RouterInterface $router) { - if (!$router instanceof RouterInterface) { - @trigger_error(sprintf('Passing a command name as the first argument of "%s" is deprecated since version 3.4 and will be removed in 4.0. If the command was registered by convention, make it a service instead.', __METHOD__), E_USER_DEPRECATED); - - parent::__construct($router); - - return; - } - parent::__construct(); $this->router = $router; } - /** - * {@inheritdoc} - * - * BC to be removed in 4.0 - */ - public function isEnabled() - { - if (null !== $this->router) { - return parent::isEnabled(); - } - if (!$this->getContainer()->has('router')) { - return false; - } - $router = $this->getContainer()->get('router'); - if (!$router instanceof RouterInterface) { - return false; - } - - return parent::isEnabled(); - } - /** * {@inheritdoc} */ @@ -104,11 +73,6 @@ protected function configure() */ protected function execute(InputInterface $input, OutputInterface $output) { - // BC to be removed in 4.0 - if (null === $this->router) { - $this->router = $this->getContainer()->get('router'); - } - $io = new SymfonyStyle($input, $output); $name = $input->getArgument('name'); $helper = new DescriptorHelper(); diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/RouterMatchCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/RouterMatchCommand.php index f88d2a2dfe0c7..4c99b9dbe5157 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/RouterMatchCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/RouterMatchCommand.php @@ -11,6 +11,7 @@ namespace Symfony\Bundle\FrameworkBundle\Command; +use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\ArrayInput; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; @@ -27,49 +28,17 @@ * * @final since version 3.4 */ -class RouterMatchCommand extends ContainerAwareCommand +class RouterMatchCommand extends Command { private $router; - /** - * @param RouterInterface $router - */ - public function __construct($router = null) + public function __construct(RouterInterface $router) { - if (!$router instanceof RouterInterface) { - @trigger_error(sprintf('Passing a command name as the first argument of "%s" is deprecated since version 3.4 and will be removed in 4.0. If the command was registered by convention, make it a service instead.', __METHOD__), E_USER_DEPRECATED); - - parent::__construct($router); - - return; - } - parent::__construct(); $this->router = $router; } - /** - * {@inheritdoc} - * - * BC to be removed in 4.0 - */ - public function isEnabled() - { - if (null !== $this->router) { - return parent::isEnabled(); - } - if (!$this->getContainer()->has('router')) { - return false; - } - $router = $this->getContainer()->get('router'); - if (!$router instanceof RouterInterface) { - return false; - } - - return parent::isEnabled(); - } - /** * {@inheritdoc} */ @@ -103,11 +72,6 @@ protected function configure() */ protected function execute(InputInterface $input, OutputInterface $output) { - // BC to be removed in 4.0 - if (null === $this->router) { - $this->router = $this->getContainer()->get('router'); - } - $io = new SymfonyStyle($input, $output); $context = $this->router->getContext(); diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/TranslationDebugCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/TranslationDebugCommand.php index f8e69a3c4a640..933a60a2d0ca9 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/TranslationDebugCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/TranslationDebugCommand.php @@ -12,6 +12,7 @@ namespace Symfony\Bundle\FrameworkBundle\Command; use Symfony\Bundle\FrameworkBundle\Translation\TranslationLoader; +use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Style\SymfonyStyle; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputArgument; @@ -34,7 +35,7 @@ * * @final since version 3.4 */ -class TranslationDebugCommand extends ContainerAwareCommand +class TranslationDebugCommand extends Command { const MESSAGE_MISSING = 0; const MESSAGE_UNUSED = 1; @@ -44,21 +45,8 @@ class TranslationDebugCommand extends ContainerAwareCommand private $loader; private $extractor; - /** - * @param TranslatorInterface $translator - * @param TranslationLoader $loader - * @param ExtractorInterface $extractor - */ - public function __construct($translator = null, TranslationLoader $loader = null, ExtractorInterface $extractor = null) + public function __construct(TranslatorInterface $translator, TranslationLoader $loader, ExtractorInterface $extractor) { - if (!$translator instanceof TranslatorInterface) { - @trigger_error(sprintf('Passing a command name as the first argument of "%s" is deprecated since version 3.4 and will be removed in 4.0. If the command was registered by convention, make it a service instead.', __METHOD__), E_USER_DEPRECATED); - - parent::__construct($translator); - - return; - } - parent::__construct(); $this->translator = $translator; @@ -116,35 +104,11 @@ protected function configure() ; } - /** - * {@inheritdoc} - * - * BC to be removed in 4.0 - */ - public function isEnabled() - { - if (null !== $this->translator) { - return parent::isEnabled(); - } - if (!class_exists('Symfony\Component\Translation\Translator')) { - return false; - } - - return parent::isEnabled(); - } - /** * {@inheritdoc} */ protected function execute(InputInterface $input, OutputInterface $output) { - // BC to be removed in 4.0 - if (null === $this->translator) { - $this->translator = $this->getContainer()->get('translator'); - $this->loader = $this->getContainer()->get('translation.loader'); - $this->extractor = $this->getContainer()->get('translation.extractor'); - } - $io = new SymfonyStyle($input, $output); $locale = $input->getArgument('locale'); diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/TranslationUpdateCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/TranslationUpdateCommand.php index 33adca99f15c2..0f0fc026afc48 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/TranslationUpdateCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/TranslationUpdateCommand.php @@ -12,6 +12,7 @@ namespace Symfony\Bundle\FrameworkBundle\Command; use Symfony\Bundle\FrameworkBundle\Translation\TranslationLoader; +use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Style\SymfonyStyle; use Symfony\Component\Translation\Catalogue\TargetOperation; use Symfony\Component\Translation\Catalogue\MergeOperation; @@ -31,7 +32,7 @@ * * @final since version 3.4 */ -class TranslationUpdateCommand extends ContainerAwareCommand +class TranslationUpdateCommand extends Command { private $writer; private $loader; @@ -44,16 +45,8 @@ class TranslationUpdateCommand extends ContainerAwareCommand * @param ExtractorInterface $extractor * @param string $defaultLocale */ - public function __construct($writer = null, TranslationLoader $loader = null, ExtractorInterface $extractor = null, $defaultLocale = null) + public function __construct(TranslationWriter $writer, TranslationLoader $loader, ExtractorInterface $extractor, $defaultLocale) { - if (!$writer instanceof TranslationWriter) { - @trigger_error(sprintf('Passing a command name as the first argument of "%s" is deprecated since version 3.4 and will be removed in 4.0. If the command was registered by convention, make it a service instead.', __METHOD__), E_USER_DEPRECATED); - - parent::__construct($writer); - - return; - } - parent::__construct(); $this->writer = $writer; @@ -100,36 +93,11 @@ protected function configure() ; } - /** - * {@inheritdoc} - * - * BC to be removed in 4.0 - */ - public function isEnabled() - { - if (null !== $this->writer) { - return parent::isEnabled(); - } - if (!class_exists('Symfony\Component\Translation\Translator')) { - return false; - } - - return parent::isEnabled(); - } - /** * {@inheritdoc} */ protected function execute(InputInterface $input, OutputInterface $output) { - // BC to be removed in 4.0 - if (null === $this->writer) { - $this->writer = $this->getContainer()->get('translation.writer'); - $this->loader = $this->getContainer()->get('translation.loader'); - $this->extractor = $this->getContainer()->get('translation.extractor'); - $this->defaultLocale = $this->getContainer()->getParameter('kernel.default_locale'); - } - $io = new SymfonyStyle($input, $output); $errorIo = $io->getErrorStyle(); diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/WorkflowDumpCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/WorkflowDumpCommand.php index 27e0f645d8fdf..e06547103d684 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/WorkflowDumpCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/WorkflowDumpCommand.php @@ -11,6 +11,7 @@ namespace Symfony\Bundle\FrameworkBundle\Command; +use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; @@ -23,18 +24,8 @@ * * @final since version 3.4 */ -class WorkflowDumpCommand extends ContainerAwareCommand +class WorkflowDumpCommand extends Command { - /** - * {@inheritdoc} - * - * BC to be removed in 4.0 - */ - public function isEnabled() - { - return $this->getContainer()->has('workflow.registry'); - } - /** * {@inheritdoc} */ diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/XliffLintCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/XliffLintCommand.php index 36876dee24252..354d714694844 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/XliffLintCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/XliffLintCommand.php @@ -24,29 +24,21 @@ */ class XliffLintCommand extends BaseLintCommand { - public function __construct($name = null, $directoryIteratorProvider = null, $isReadableProvider = null) + public function __construct() { - if (func_num_args()) { - @trigger_error(sprintf('Passing a constructor argument in "%s" is deprecated since version 3.4 and will be removed in 4.0. If the command was registered by convention, make it a service instead.', __METHOD__), E_USER_DEPRECATED); - } + $directoryIteratorProvider = function ($directory, $default) { + if (!is_dir($directory)) { + $directory = $this->getApplication()->getKernel()->locateResource($directory); + } - if (null === $directoryIteratorProvider) { - $directoryIteratorProvider = function ($directory, $default) { - if (!is_dir($directory)) { - $directory = $this->getApplication()->getKernel()->locateResource($directory); - } + return $default($directory); + }; - return $default($directory); - }; - } + $isReadableProvider = function ($fileOrDirectory, $default) { + return 0 === strpos($fileOrDirectory, '@') || $default($fileOrDirectory); + }; - if (null === $isReadableProvider) { - $isReadableProvider = function ($fileOrDirectory, $default) { - return 0 === strpos($fileOrDirectory, '@') || $default($fileOrDirectory); - }; - } - - parent::__construct($name, $directoryIteratorProvider, $isReadableProvider); + parent::__construct(null, $directoryIteratorProvider, $isReadableProvider); } /** diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/YamlLintCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/YamlLintCommand.php index f6c1a7f85b190..267a57027e85f 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/YamlLintCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/YamlLintCommand.php @@ -23,29 +23,21 @@ */ class YamlLintCommand extends BaseLintCommand { - public function __construct($name = null, $directoryIteratorProvider = null, $isReadableProvider = null) + public function __construct() { - if (func_num_args()) { - @trigger_error(sprintf('Passing a constructor argument in "%s" is deprecated since version 3.4 and will be removed in 4.0. If the command was registered by convention, make it a service instead.', __METHOD__), E_USER_DEPRECATED); - } + $directoryIteratorProvider = function ($directory, $default) { + if (!is_dir($directory)) { + $directory = $this->getApplication()->getKernel()->locateResource($directory); + } - if (null === $directoryIteratorProvider) { - $directoryIteratorProvider = function ($directory, $default) { - if (!is_dir($directory)) { - $directory = $this->getApplication()->getKernel()->locateResource($directory); - } + return $default($directory); + }; - return $default($directory); - }; - } + $isReadableProvider = function ($fileOrDirectory, $default) { + return 0 === strpos($fileOrDirectory, '@') || $default($fileOrDirectory); + }; - if (null === $isReadableProvider) { - $isReadableProvider = function ($fileOrDirectory, $default) { - return 0 === strpos($fileOrDirectory, '@') || $default($fileOrDirectory); - }; - } - - parent::__construct($name, $directoryIteratorProvider, $isReadableProvider); + parent::__construct(null, $directoryIteratorProvider, $isReadableProvider); } /** diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/RouterDebugCommandTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/RouterDebugCommandTest.php index c201fe9db7248..54fb8db8c6bee 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/RouterDebugCommandTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/RouterDebugCommandTest.php @@ -47,22 +47,6 @@ public function testDebugInvalidRoute() $this->createCommandTester()->execute(array('name' => 'test')); } - /** - * @group legacy - * @expectedDeprecation Passing a command name as the first argument of "Symfony\Bundle\FrameworkBundle\Command\RouterDebugCommand::__construct" is deprecated since version 3.4 and will be removed in 4.0. If the command was registered by convention, make it a service instead. - */ - public function testLegacyDebugCommand() - { - $application = new Application($this->getKernel()); - $application->add(new RouterDebugCommand()); - - $tester = new CommandTester($application->find('debug:router')); - - $tester->execute(array()); - - $this->assertRegExp('/foo\s+ANY\s+ANY\s+ANY\s+\\/foo/', $tester->getDisplay()); - } - /** * @return CommandTester */ diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/RouterMatchCommandTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/RouterMatchCommandTest.php index 2570d41d78745..7baa874355df2 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/RouterMatchCommandTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/RouterMatchCommandTest.php @@ -41,24 +41,6 @@ public function testWithNotMatchPath() $this->assertContains('None of the routes match the path "/test"', $tester->getDisplay()); } - /** - * @group legacy - * @expectedDeprecation Passing a command name as the first argument of "Symfony\Bundle\FrameworkBundle\Command\RouterMatchCommand::__construct" is deprecated since version 3.4 and will be removed in 4.0. If the command was registered by convention, make it a service instead. - * @expectedDeprecation Passing a command name as the first argument of "Symfony\Bundle\FrameworkBundle\Command\RouterDebugCommand::__construct" is deprecated since version 3.4 and will be removed in 4.0. If the command was registered by convention, make it a service instead. - */ - public function testLegacyMatchCommand() - { - $application = new Application($this->getKernel()); - $application->add(new RouterMatchCommand()); - $application->add(new RouterDebugCommand()); - - $tester = new CommandTester($application->find('router:match')); - - $tester->execute(array('path_info' => '/')); - - $this->assertContains('None of the routes match the path "/"', $tester->getDisplay()); - } - /** * @return CommandTester */ diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/TranslationDebugCommandTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/TranslationDebugCommandTest.php index edf006c86801c..5926955a37f37 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/TranslationDebugCommandTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/TranslationDebugCommandTest.php @@ -174,51 +174,6 @@ private function createCommandTester($extractedMessages = array(), $loadedMessag return new CommandTester($application->find('debug:translation')); } - /** - * @group legacy - * @expectedDeprecation Passing a command name as the first argument of "Symfony\Bundle\FrameworkBundle\Command\TranslationDebugCommand::__construct" is deprecated since version 3.4 and will be removed in 4.0. If the command was registered by convention, make it a service instead. - */ - public function testLegacyDebugCommand() - { - $translator = $this->getMockBuilder('Symfony\Component\Translation\Translator') - ->disableOriginalConstructor() - ->getMock(); - $extractor = $this->getMockBuilder('Symfony\Component\Translation\Extractor\ExtractorInterface')->getMock(); - $loader = $this->getMockBuilder('Symfony\Bundle\FrameworkBundle\Translation\TranslationLoader')->getMock(); - $kernel = $this->getMockBuilder('Symfony\Component\HttpKernel\KernelInterface')->getMock(); - $kernel - ->expects($this->any()) - ->method('getBundles') - ->will($this->returnValue(array())); - - $container = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerInterface')->getMock(); - $container - ->expects($this->any()) - ->method('get') - ->will($this->returnValueMap(array( - array('translation.extractor', 1, $extractor), - array('translation.loader', 1, $loader), - array('translator', 1, $translator), - array('kernel', 1, $kernel), - ))); - - $kernel - ->expects($this->any()) - ->method('getContainer') - ->will($this->returnValue($container)); - - $command = new TranslationDebugCommand(); - $command->setContainer($container); - - $application = new Application($kernel); - $application->add($command); - - $tester = new CommandTester($application->find('debug:translation')); - $tester->execute(array('locale' => 'en')); - - $this->assertContains('No defined or extracted', $tester->getDisplay()); - } - private function getBundle($path) { $bundle = $this->getMockBuilder('Symfony\Component\HttpKernel\Bundle\BundleInterface')->getMock(); diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/TranslationUpdateCommandTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/TranslationUpdateCommandTest.php index db61398b26d9a..ecdd5bc0a954e 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/TranslationUpdateCommandTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/TranslationUpdateCommandTest.php @@ -153,53 +153,6 @@ private function createCommandTester($extractedMessages = array(), $loadedMessag return new CommandTester($application->find('translation:update')); } - /** - * @group legacy - * @expectedDeprecation Passing a command name as the first argument of "Symfony\Bundle\FrameworkBundle\Command\TranslationUpdateCommand::__construct" is deprecated since version 3.4 and will be removed in 4.0. If the command was registered by convention, make it a service instead. - */ - public function testLegacyUpdateCommand() - { - $translator = $this->getMockBuilder('Symfony\Component\Translation\Translator') - ->disableOriginalConstructor() - ->getMock(); - $extractor = $this->getMockBuilder('Symfony\Component\Translation\Extractor\ExtractorInterface')->getMock(); - $loader = $this->getMockBuilder('Symfony\Bundle\FrameworkBundle\Translation\TranslationLoader')->getMock(); - $writer = $this->getMockBuilder('Symfony\Component\Translation\Writer\TranslationWriter')->getMock(); - $kernel = $this->getMockBuilder('Symfony\Component\HttpKernel\KernelInterface')->getMock(); - $kernel - ->expects($this->any()) - ->method('getBundles') - ->will($this->returnValue(array())); - - $container = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerInterface')->getMock(); - $container - ->expects($this->any()) - ->method('get') - ->will($this->returnValueMap(array( - array('translation.extractor', 1, $extractor), - array('translation.loader', 1, $loader), - array('translation.writer', 1, $writer), - array('translator', 1, $translator), - array('kernel', 1, $kernel), - ))); - - $kernel - ->expects($this->any()) - ->method('getContainer') - ->will($this->returnValue($container)); - - $command = new TranslationUpdateCommand(); - $command->setContainer($container); - - $application = new Application($kernel); - $application->add($command); - - $tester = new CommandTester($application->find('translation:update')); - $tester->execute(array('locale' => 'en')); - - $this->assertContains('You must choose one of --force or --dump-messages', $tester->getDisplay()); - } - private function getBundle($path) { $bundle = $this->getMockBuilder('Symfony\Component\HttpKernel\Bundle\BundleInterface')->getMock(); diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/CachePoolClearCommandTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/CachePoolClearCommandTest.php index 9a2d198a72ba2..a4c945144e585 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/CachePoolClearCommandTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/CachePoolClearCommandTest.php @@ -75,22 +75,6 @@ public function testClearUnexistingPool() ->execute(array('pools' => array('unknown_pool')), array('decorated' => false)); } - /** - * @group legacy - * @expectedDeprecation Passing a command name as the first argument of "Symfony\Bundle\FrameworkBundle\Command\CachePoolClearCommand::__construct" is deprecated since version 3.4 and will be removed in 4.0. If the command was registered by convention, make it a service instead. - */ - public function testLegacyClearCommand() - { - $application = new Application(static::$kernel); - $application->add(new CachePoolClearCommand()); - - $tester = new CommandTester($application->find('cache:pool:clear')); - - $tester->execute(array('pools' => array())); - - $this->assertContains('Cache was successfully cleared', $tester->getDisplay()); - } - private function createCommandTester() { $container = static::$kernel->getContainer(); diff --git a/src/Symfony/Bundle/SecurityBundle/Command/InitAclCommand.php b/src/Symfony/Bundle/SecurityBundle/Command/InitAclCommand.php index 597df8ceb9de1..d79176001a7dd 100644 --- a/src/Symfony/Bundle/SecurityBundle/Command/InitAclCommand.php +++ b/src/Symfony/Bundle/SecurityBundle/Command/InitAclCommand.php @@ -11,7 +11,7 @@ namespace Symfony\Bundle\SecurityBundle\Command; -use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand; +use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Security\Acl\Dbal\Schema; @@ -25,45 +25,19 @@ * * @final since version 3.4 */ -class InitAclCommand extends ContainerAwareCommand +class InitAclCommand extends Command { private $connection; private $schema; - /** - * @param Connection $connection - * @param Schema $schema - */ - public function __construct($connection = null, Schema $schema = null) + public function __construct(Connection $connection, Schema $schema) { - if (!$connection instanceof Connection) { - @trigger_error(sprintf('Passing a command name as the first argument of "%s" is deprecated since version 3.4 and will be removed in 4.0. If the command was registered by convention, make it a service instead.', __METHOD__), E_USER_DEPRECATED); - - parent::__construct($connection); - - return; - } - parent::__construct(); $this->connection = $connection; $this->schema = $schema; } - /** - * {@inheritdoc} - * - * BC to be removed in 4.0 - */ - public function isEnabled() - { - if (!$this->connection && !$this->getContainer()->has('security.acl.dbal.connection')) { - return false; - } - - return parent::isEnabled(); - } - /** * {@inheritdoc} */ @@ -92,12 +66,6 @@ protected function configure() */ protected function execute(InputInterface $input, OutputInterface $output) { - // BC to be removed in 4.0 - if (null === $this->connection) { - $this->connection = $this->getContainer()->get('security.acl.dbal.connection'); - $this->schema = $this->getContainer()->get('security.acl.dbal.schema'); - } - try { $this->schema->addToSchema($this->connection->getSchemaManager()->createSchema()); } catch (SchemaException $e) { diff --git a/src/Symfony/Bundle/SecurityBundle/Command/SetAclCommand.php b/src/Symfony/Bundle/SecurityBundle/Command/SetAclCommand.php index 840e74edfba87..59ecd6b0a0764 100644 --- a/src/Symfony/Bundle/SecurityBundle/Command/SetAclCommand.php +++ b/src/Symfony/Bundle/SecurityBundle/Command/SetAclCommand.php @@ -11,7 +11,7 @@ namespace Symfony\Bundle\SecurityBundle\Command; -use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand; +use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; @@ -30,50 +30,17 @@ * * @final since version 3.4 */ -class SetAclCommand extends ContainerAwareCommand +class SetAclCommand extends Command { private $provider; - /** - * @param MutableAclProviderInterface $provider - */ - public function __construct($provider = null) + public function __construct(MutableAclProviderInterface $provider) { - if (!$provider instanceof MutableAclProviderInterface) { - @trigger_error(sprintf('Passing a command name as the first argument of "%s" is deprecated since version 3.4 and will be removed in 4.0. If the command was registered by convention, make it a service instead.', __METHOD__), E_USER_DEPRECATED); - - parent::__construct($provider); - - return; - } - parent::__construct(); $this->provider = $provider; } - /** - * {@inheritdoc} - * - * BC to be removed in 4.0 - */ - public function isEnabled() - { - if (null !== $this->provider) { - return parent::isEnabled(); - } - if (!$this->getContainer()->has('security.acl.provider')) { - return false; - } - - $provider = $this->getContainer()->get('security.acl.provider'); - if (!$provider instanceof MutableAclProviderInterface) { - return false; - } - - return parent::isEnabled(); - } - /** * {@inheritdoc} */ @@ -116,14 +83,9 @@ protected function configure() */ protected function execute(InputInterface $input, OutputInterface $output) { - // BC to be removed in 4.0 - if (null === $this->provider) { - $this->provider = $this->getContainer()->get('security.acl.provider'); - } - // Parse arguments $objectIdentities = array(); - $maskBuilder = $this->getMaskBuilder(); + $maskBuilder = new MaskBuilder(); foreach ($input->getArgument('arguments') as $argument) { $data = explode(':', $argument, 2); @@ -187,16 +149,4 @@ protected function execute(InputInterface $input, OutputInterface $output) $this->provider->updateAcl($acl); } } - - /** - * Gets the mask builder. - * - * BC to be removed in 4.0 - * - * @return MaskBuilder - */ - protected function getMaskBuilder() - { - return new MaskBuilder(); - } } diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/SetAclCommandTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/SetAclCommandTest.php index 1ceaca1002019..37cbffd9befa6 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/SetAclCommandTest.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/SetAclCommandTest.php @@ -52,7 +52,7 @@ public function testSetAclUser() $grantedPermission2 = 'EDIT'; $application = $this->getApplication(); - $application->add(new SetAclCommand()); + $application->add(new SetAclCommand($application->getKernel()->getContainer()->get('security.acl.provider'))); $setAclCommand = $application->find('acl:set'); $setAclCommandTester = new CommandTester($setAclCommand); diff --git a/src/Symfony/Bundle/TwigBundle/Command/LintCommand.php b/src/Symfony/Bundle/TwigBundle/Command/LintCommand.php index 1474a4de0a3f5..c0b175c3a2ed8 100644 --- a/src/Symfony/Bundle/TwigBundle/Command/LintCommand.php +++ b/src/Symfony/Bundle/TwigBundle/Command/LintCommand.php @@ -12,8 +12,6 @@ namespace Symfony\Bundle\TwigBundle\Command; use Symfony\Bridge\Twig\Command\LintCommand as BaseLintCommand; -use Symfony\Component\DependencyInjection\ContainerAwareInterface; -use Symfony\Component\DependencyInjection\ContainerAwareTrait; use Symfony\Component\Finder\Finder; /** @@ -22,11 +20,8 @@ * @author Marc Weistroff * @author Jérôme Tamarelle */ -final class LintCommand extends BaseLintCommand implements ContainerAwareInterface +final class LintCommand extends BaseLintCommand { - // BC to be removed in 4.0 - use ContainerAwareTrait; - /** * {@inheritdoc} */ diff --git a/src/Symfony/Component/Yaml/Parser.php b/src/Symfony/Component/Yaml/Parser.php index 38dae64f8ad1e..6befb3d0a2f8c 100644 --- a/src/Symfony/Component/Yaml/Parser.php +++ b/src/Symfony/Component/Yaml/Parser.php @@ -181,15 +181,7 @@ private function doParse($value, $flags) Inline::parse(null, $flags, $this->refs); try { Inline::$parsedLineNumber = $this->getRealCurrentLineNb(); - $i = 0; - $evaluateKey = !(Yaml::PARSE_KEYS_AS_STRINGS & $flags); - - // constants in key will be evaluated anyway - if (isset($values['key'][0]) && '!' === $values['key'][0] && Yaml::PARSE_CONSTANT & $flags) { - $evaluateKey = true; - } - - $key = Inline::parseScalar($values['key'], 0, null, $i, $evaluateKey); + $key = Inline::parseScalar($values['key']); } catch (ParseException $e) { $e->setParsedLine($this->getRealCurrentLineNb() + 1); $e->setSnippet($this->currentLine); diff --git a/src/Symfony/Component/Yaml/Tests/ParserTest.php b/src/Symfony/Component/Yaml/Tests/ParserTest.php index c8142a46df2ed..6500d307c02a3 100644 --- a/src/Symfony/Component/Yaml/Tests/ParserTest.php +++ b/src/Symfony/Component/Yaml/Tests/ParserTest.php @@ -45,16 +45,6 @@ public function getDataFormSpecifications() return $this->loadTestsFromFixtureFiles('index.yml'); } - /** - * @group legacy - * @expectedDeprecationMessage Using the Yaml::PARSE_KEYS_AS_STRINGS flag is deprecated since version 3.4 as it will be removed in 4.0. Quote your keys when they are evaluable - * @dataProvider getNonStringMappingKeysData - */ - public function testNonStringMappingKeys($expected, $yaml, $comment) - { - $this->assertSame($expected, var_export($this->parser->parse($yaml, Yaml::PARSE_KEYS_AS_STRINGS), true), $comment); - } - public function getNonStringMappingKeysData() { return $this->loadTestsFromFixtureFiles('nonStringKeys.yml'); diff --git a/src/Symfony/Component/Yaml/Yaml.php b/src/Symfony/Component/Yaml/Yaml.php index f41821bdfe9b9..cd4e356896425 100644 --- a/src/Symfony/Component/Yaml/Yaml.php +++ b/src/Symfony/Component/Yaml/Yaml.php @@ -32,11 +32,6 @@ class Yaml const PARSE_CUSTOM_TAGS = 512; const DUMP_EMPTY_ARRAY_AS_SEQUENCE = 1024; - /** - * @deprecated since version 3.4, to be removed in 4.0. Quote your evaluable keys instead. - */ - const PARSE_KEYS_AS_STRINGS = 2048; - /** * Parses YAML into a PHP value. * From b89ba293dd16d15c61814a2657a1375d85d6e6fa Mon Sep 17 00:00:00 2001 From: Guilhem Niot Date: Sun, 6 Aug 2017 15:38:20 +0200 Subject: [PATCH 0589/1099] [Debug] Trigger a deprecation when using an internal class/trait/interface --- .../Doctrine/Form/ChoiceList/IdReader.php | 2 +- .../Component/Debug/DebugClassLoader.php | 84 +++++++++++-------- .../Debug/Tests/DebugClassLoaderTest.php | 32 ++++--- .../Debug/Tests/Fixtures/InternalClass.php | 11 +++ .../Tests/Fixtures/InternalInterface.php | 10 +++ .../Debug/Tests/Fixtures/InternalTrait.php | 10 +++ .../Debug/Tests/Fixtures/InternalTrait2.php | 10 +++ .../ParserCache/ParserCacheAdapter.php | 2 +- .../Form/ChoiceList/ArrayChoiceList.php | 2 +- .../Factory/CachingFactoryDecorator.php | 4 +- .../Validator/Context/ExecutionContext.php | 3 +- .../Context/ExecutionContextFactory.php | 3 +- .../Violation/ConstraintViolationBuilder.php | 3 +- 13 files changed, 119 insertions(+), 57 deletions(-) create mode 100644 src/Symfony/Component/Debug/Tests/Fixtures/InternalClass.php create mode 100644 src/Symfony/Component/Debug/Tests/Fixtures/InternalInterface.php create mode 100644 src/Symfony/Component/Debug/Tests/Fixtures/InternalTrait.php create mode 100644 src/Symfony/Component/Debug/Tests/Fixtures/InternalTrait2.php diff --git a/src/Symfony/Bridge/Doctrine/Form/ChoiceList/IdReader.php b/src/Symfony/Bridge/Doctrine/Form/ChoiceList/IdReader.php index cd966ea986f79..4140629d934b6 100644 --- a/src/Symfony/Bridge/Doctrine/Form/ChoiceList/IdReader.php +++ b/src/Symfony/Bridge/Doctrine/Form/ChoiceList/IdReader.php @@ -20,7 +20,7 @@ * * @author Bernhard Schussek * - * @internal This class is meant for internal use only. + * @internal */ class IdReader { diff --git a/src/Symfony/Component/Debug/DebugClassLoader.php b/src/Symfony/Component/Debug/DebugClassLoader.php index 2b13c02cf92c5..43ab3a78bf551 100644 --- a/src/Symfony/Component/Debug/DebugClassLoader.php +++ b/src/Symfony/Component/Debug/DebugClassLoader.php @@ -27,6 +27,7 @@ class DebugClassLoader private $classLoader; private $isFinder; private static $caseCheck; + private static $internal = array(); private static $final = array(); private static $finalMethods = array(); private static $deprecated = array(); @@ -166,10 +167,14 @@ public function loadClass($class) } $parent = get_parent_class($class); + $doc = $refl->getDocComment(); + if (preg_match('#\n \* @internal(?:( .+?)\.?)?\r?\n \*(?: @|/$)#s', $doc, $notice)) { + self::$internal[$name] = isset($notice[1]) ? preg_replace('#\s*\r?\n \* +#', ' ', $notice[1]) : ''; + } // Not an interface nor a trait if (class_exists($name, false)) { - if (preg_match('#\n \* @final(?:( .+?)\.?)?\r?\n \*(?: @|/$)#s', $refl->getDocComment(), $notice)) { + if (preg_match('#\n \* @final(?:( .+?)\.?)?\r?\n \*(?: @|/$)#s', $doc, $notice)) { self::$final[$name] = isset($notice[1]) ? preg_replace('#\s*\r?\n \* +#', ' ', $notice[1]) : ''; } @@ -203,50 +208,57 @@ public function loadClass($class) if (in_array(strtolower($refl->getShortName()), self::$php7Reserved)) { @trigger_error(sprintf('The "%s" class uses the reserved name "%s", it will break on PHP 7 and higher', $name, $refl->getShortName()), E_USER_DEPRECATED); - } elseif (preg_match('#\n \* @deprecated (.*?)\r?\n \*(?: @|/$)#s', $refl->getDocComment(), $notice)) { + } + if (preg_match('#\n \* @deprecated (.*?)\r?\n \*(?: @|/$)#s', $refl->getDocComment(), $notice)) { self::$deprecated[$name] = preg_replace('#\s*\r?\n \* +#', ' ', $notice[1]); + } + + // Don't trigger deprecations for classes in the same vendor + if (2 > $len = 1 + (strpos($name, '\\', 1 + strpos($name, '\\')) ?: strpos($name, '_'))) { + $len = 0; + $ns = ''; } else { - // Don't trigger deprecations for classes in the same vendor - if (2 > $len = 1 + (strpos($name, '\\', 1 + strpos($name, '\\')) ?: strpos($name, '_'))) { - $len = 0; - $ns = ''; - } else { - switch ($ns = substr($name, 0, $len)) { - case 'Symfony\Bridge\\': - case 'Symfony\Bundle\\': - case 'Symfony\Component\\': - $ns = 'Symfony\\'; - $len = strlen($ns); - break; - } + switch ($ns = substr($name, 0, $len)) { + case 'Symfony\Bridge\\': + case 'Symfony\Bundle\\': + case 'Symfony\Component\\': + $ns = 'Symfony\\'; + $len = strlen($ns); + break; } + } - if (!$parent || strncmp($ns, $parent, $len)) { - if ($parent && isset(self::$deprecated[$parent]) && strncmp($ns, $parent, $len)) { - @trigger_error(sprintf('The "%s" class extends "%s" that is deprecated %s', $name, $parent, self::$deprecated[$parent]), E_USER_DEPRECATED); - } + foreach (array_merge(array($parent), class_implements($name, false), class_uses($name, false)) as $use) { + if (isset(self::$internal[$use]) && strncmp($ns, $use, $len)) { + @trigger_error(sprintf('The "%s" %s is considered internal%s. It may change without further notice. You should not use it from "%s".', $use, class_exists($use, false) ? 'class' : (interface_exists($use, false) ? 'interface' : 'trait'), self::$internal[$use], $name), E_USER_DEPRECATED); + } + } - $parentInterfaces = array(); - $deprecatedInterfaces = array(); - if ($parent) { - foreach (class_implements($parent) as $interface) { - $parentInterfaces[$interface] = 1; - } + if (!$parent || strncmp($ns, $parent, $len)) { + if ($parent && isset(self::$deprecated[$parent]) && strncmp($ns, $parent, $len)) { + @trigger_error(sprintf('The "%s" class extends "%s" that is deprecated %s', $name, $parent, self::$deprecated[$parent]), E_USER_DEPRECATED); + } + + $parentInterfaces = array(); + $deprecatedInterfaces = array(); + if ($parent) { + foreach (class_implements($parent) as $interface) { + $parentInterfaces[$interface] = 1; } + } - foreach ($refl->getInterfaceNames() as $interface) { - if (isset(self::$deprecated[$interface]) && strncmp($ns, $interface, $len)) { - $deprecatedInterfaces[] = $interface; - } - foreach (class_implements($interface) as $interface) { - $parentInterfaces[$interface] = 1; - } + foreach ($refl->getInterfaceNames() as $interface) { + if (isset(self::$deprecated[$interface]) && strncmp($ns, $interface, $len)) { + $deprecatedInterfaces[] = $interface; + } + foreach (class_implements($interface) as $interface) { + $parentInterfaces[$interface] = 1; } + } - foreach ($deprecatedInterfaces as $interface) { - if (!isset($parentInterfaces[$interface])) { - @trigger_error(sprintf('The "%s" %s "%s" that is deprecated %s', $name, $refl->isInterface() ? 'interface extends' : 'class implements', $interface, self::$deprecated[$interface]), E_USER_DEPRECATED); - } + foreach ($deprecatedInterfaces as $interface) { + if (!isset($parentInterfaces[$interface])) { + @trigger_error(sprintf('The "%s" %s "%s" that is deprecated %s', $name, $refl->isInterface() ? 'interface extends' : 'class implements', $interface, self::$deprecated[$interface]), E_USER_DEPRECATED); } } } diff --git a/src/Symfony/Component/Debug/Tests/DebugClassLoaderTest.php b/src/Symfony/Component/Debug/Tests/DebugClassLoaderTest.php index f1e3fb7c611b5..a53c17b0e4983 100644 --- a/src/Symfony/Component/Debug/Tests/DebugClassLoaderTest.php +++ b/src/Symfony/Component/Debug/Tests/DebugClassLoaderTest.php @@ -312,6 +312,24 @@ class_exists(__NAMESPACE__.'\\Fixtures\\ExtendedFinalMethod', true); $this->assertSame($xError, $lastError); } + + public function testInternalsUse() + { + $deprecations = array(); + set_error_handler(function ($type, $msg) use (&$deprecations) { $deprecations[] = $msg; }); + $e = error_reporting(E_USER_DEPRECATED); + + class_exists('Test\\'.__NAMESPACE__.'\\ExtendsInternals', true); + + error_reporting($e); + restore_error_handler(); + + $this->assertSame($deprecations, array( + 'The "Symfony\Component\Debug\Tests\Fixtures\InternalClass" class is considered internal since version 3.4. It may change without further notice. You should not use it from "Test\Symfony\Component\Debug\Tests\ExtendsInternals".', + 'The "Symfony\Component\Debug\Tests\Fixtures\InternalInterface" interface is considered internal. It may change without further notice. You should not use it from "Test\Symfony\Component\Debug\Tests\ExtendsInternals".', + 'The "Symfony\Component\Debug\Tests\Fixtures\InternalTrait" trait is considered internal. It may change without further notice. You should not use it from "Test\Symfony\Component\Debug\Tests\ExtendsInternals".', + )); + } } class ClassLoader @@ -335,22 +353,12 @@ public function findFile($class) eval('namespace '.__NAMESPACE__.'; class TestingStacking { function foo() {} }'); } elseif (__NAMESPACE__.'\TestingCaseMismatch' === $class) { eval('namespace '.__NAMESPACE__.'; class TestingCaseMisMatch {}'); - } elseif (__NAMESPACE__.'\Fixtures\CaseMismatch' === $class) { - return $fixtureDir.'CaseMismatch.php'; } elseif (__NAMESPACE__.'\Fixtures\Psr4CaseMismatch' === $class) { return $fixtureDir.'psr4'.DIRECTORY_SEPARATOR.'Psr4CaseMismatch.php'; } elseif (__NAMESPACE__.'\Fixtures\NotPSR0' === $class) { return $fixtureDir.'reallyNotPsr0.php'; } elseif (__NAMESPACE__.'\Fixtures\NotPSR0bis' === $class) { return $fixtureDir.'notPsr0Bis.php'; - } elseif (__NAMESPACE__.'\Fixtures\DeprecatedInterface' === $class) { - return $fixtureDir.'DeprecatedInterface.php'; - } elseif (__NAMESPACE__.'\Fixtures\FinalClass' === $class) { - return $fixtureDir.'FinalClass.php'; - } elseif (__NAMESPACE__.'\Fixtures\FinalMethod' === $class) { - return $fixtureDir.'FinalMethod.php'; - } elseif (__NAMESPACE__.'\Fixtures\ExtendedFinalMethod' === $class) { - return $fixtureDir.'ExtendedFinalMethod.php'; } elseif ('Symfony\Bridge\Debug\Tests\Fixtures\ExtendsDeprecatedParent' === $class) { eval('namespace Symfony\Bridge\Debug\Tests\Fixtures; class ExtendsDeprecatedParent extends \\'.__NAMESPACE__.'\Fixtures\DeprecatedClass {}'); } elseif ('Test\\'.__NAMESPACE__.'\DeprecatedParentClass' === $class) { @@ -363,6 +371,10 @@ public function findFile($class) eval('namespace Test\\'.__NAMESPACE__.'; class Float {}'); } elseif ('Test\\'.__NAMESPACE__.'\ExtendsFinalClass' === $class) { eval('namespace Test\\'.__NAMESPACE__.'; class ExtendsFinalClass extends \\'.__NAMESPACE__.'\Fixtures\FinalClass {}'); + } elseif ('Test\\'.__NAMESPACE__.'\ExtendsInternals' === $class) { + eval('namespace Test\\'.__NAMESPACE__.'; class ExtendsInternals extends \\'.__NAMESPACE__.'\Fixtures\InternalClass implements \\'.__NAMESPACE__.'\Fixtures\InternalInterface { + use \\'.__NAMESPACE__.'\Fixtures\InternalTrait; + }'); } } } diff --git a/src/Symfony/Component/Debug/Tests/Fixtures/InternalClass.php b/src/Symfony/Component/Debug/Tests/Fixtures/InternalClass.php new file mode 100644 index 0000000000000..745fa462162f5 --- /dev/null +++ b/src/Symfony/Component/Debug/Tests/Fixtures/InternalClass.php @@ -0,0 +1,11 @@ + * - * @internal This class should be removed in Symfony 4.0. + * @internal and will be removed in Symfony 4.0. */ class ParserCacheAdapter implements CacheItemPoolInterface { diff --git a/src/Symfony/Component/Form/ChoiceList/ArrayChoiceList.php b/src/Symfony/Component/Form/ChoiceList/ArrayChoiceList.php index a7c282849263b..50658c3911f1c 100644 --- a/src/Symfony/Component/Form/ChoiceList/ArrayChoiceList.php +++ b/src/Symfony/Component/Form/ChoiceList/ArrayChoiceList.php @@ -185,7 +185,7 @@ public function getValuesForChoices(array $choices) * corresponding values * @param array $structuredValues The values indexed by the original keys * - * @internal Must not be used by user-land code + * @internal */ protected function flatten(array $choices, $value, &$choicesByValues, &$keysByValues, &$structuredValues) { diff --git a/src/Symfony/Component/Form/ChoiceList/Factory/CachingFactoryDecorator.php b/src/Symfony/Component/Form/ChoiceList/Factory/CachingFactoryDecorator.php index 6580e661d4d66..d3460ecacad94 100644 --- a/src/Symfony/Component/Form/ChoiceList/Factory/CachingFactoryDecorator.php +++ b/src/Symfony/Component/Form/ChoiceList/Factory/CachingFactoryDecorator.php @@ -48,7 +48,7 @@ class CachingFactoryDecorator implements ChoiceListFactoryInterface * * @return string The SHA-256 hash * - * @internal Should not be used by user-land code. + * @internal */ public static function generateHash($value, $namespace = '') { @@ -71,7 +71,7 @@ public static function generateHash($value, $namespace = '') * @param array $array The array to flatten * @param array $output The flattened output * - * @internal Should not be used by user-land code + * @internal */ private static function flatten(array $array, &$output) { diff --git a/src/Symfony/Component/Validator/Context/ExecutionContext.php b/src/Symfony/Component/Validator/Context/ExecutionContext.php index 1dc982c2719ff..9c50a4f0f685b 100644 --- a/src/Symfony/Component/Validator/Context/ExecutionContext.php +++ b/src/Symfony/Component/Validator/Context/ExecutionContext.php @@ -30,8 +30,7 @@ * * @see ExecutionContextInterface * - * @internal You should not instantiate or use this class. Code against - * {@link ExecutionContextInterface} instead. + * @internal since version 2.5. Code against ExecutionContextInterface instead. */ class ExecutionContext implements ExecutionContextInterface { diff --git a/src/Symfony/Component/Validator/Context/ExecutionContextFactory.php b/src/Symfony/Component/Validator/Context/ExecutionContextFactory.php index 8182c41f8c1ca..32f004b5d0e9e 100644 --- a/src/Symfony/Component/Validator/Context/ExecutionContextFactory.php +++ b/src/Symfony/Component/Validator/Context/ExecutionContextFactory.php @@ -19,8 +19,7 @@ * * @author Bernhard Schussek * - * @internal You should not instantiate or use this class. Code against - * {@link ExecutionContextFactoryInterface} instead. + * @internal version 2.5. Code against ExecutionContextFactoryInterface instead. */ class ExecutionContextFactory implements ExecutionContextFactoryInterface { diff --git a/src/Symfony/Component/Validator/Violation/ConstraintViolationBuilder.php b/src/Symfony/Component/Validator/Violation/ConstraintViolationBuilder.php index bf887a08ec2b8..ff4d295cf31ae 100644 --- a/src/Symfony/Component/Validator/Violation/ConstraintViolationBuilder.php +++ b/src/Symfony/Component/Validator/Violation/ConstraintViolationBuilder.php @@ -22,8 +22,7 @@ * * @author Bernhard Schussek * - * @internal You should not instantiate or use this class. Code against - * {@link ConstraintViolationBuilderInterface} instead. + * @internal since version 2.5. Code against ConstraintViolationBuilderInterface instead. */ class ConstraintViolationBuilder implements ConstraintViolationBuilderInterface { From 0a612799d78537d2c4071cb1da466c1ec9351888 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9goire=20Pineau?= Date: Mon, 7 Aug 2017 18:03:37 +0200 Subject: [PATCH 0590/1099] Fixed UPGRADE-4.0 about Container::set --- UPGRADE-4.0.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/UPGRADE-4.0.md b/UPGRADE-4.0.md index 505ed8968a37b..7b3a98abdccd7 100644 --- a/UPGRADE-4.0.md +++ b/UPGRADE-4.0.md @@ -116,8 +116,8 @@ DependencyInjection * Using unsupported options to configure service aliases raises an exception. - * Setting or unsetting a private service with the `Container::set()` method is - no longer supported. Only public services can be set or unset. + * Setting or unsetting a service with the `Container::set()` method is + no longer supported. Only synthetic services can be set or unset. * Checking the existence of a private service with the `Container::has()` method is no longer supported and will return `false`. From 09272ff0f77f8a0bfe95d04c7fb54880e1e4137d Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Mon, 7 Aug 2017 20:29:09 +0200 Subject: [PATCH 0591/1099] fix bad merge --- src/Symfony/Bundle/TwigBundle/composer.json | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Symfony/Bundle/TwigBundle/composer.json b/src/Symfony/Bundle/TwigBundle/composer.json index 21551d7fc1867..27698cdd6d252 100644 --- a/src/Symfony/Bundle/TwigBundle/composer.json +++ b/src/Symfony/Bundle/TwigBundle/composer.json @@ -17,11 +17,11 @@ ], "require": { "php": "^5.5.9|>=7.0.8", - "symfony/config": "~3.2", - "symfony/twig-bridge": "^3.3", - "symfony/http-foundation": "~2.8|~3.0", - "symfony/http-kernel": "^3.3", - "twig/twig": "~1.34|~2.4" + "symfony/config": "~3.2|~4.0", + "symfony/twig-bridge": "^3.3|~4.0", + "symfony/http-foundation": "~2.8|~3.0|~4.0", + "symfony/http-kernel": "^3.3|~4.0", + "twig/twig": "~1.34|~2.4|~4.0" }, "require-dev": { "symfony/asset": "~2.8|~3.0|~4.0", From fea348c7c48a864706e2d838feb388b4d858e575 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Mon, 7 Aug 2017 21:17:34 +0200 Subject: [PATCH 0592/1099] fix typo --- src/Symfony/Bundle/TwigBundle/composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Bundle/TwigBundle/composer.json b/src/Symfony/Bundle/TwigBundle/composer.json index 27698cdd6d252..7ae69bf76df70 100644 --- a/src/Symfony/Bundle/TwigBundle/composer.json +++ b/src/Symfony/Bundle/TwigBundle/composer.json @@ -21,7 +21,7 @@ "symfony/twig-bridge": "^3.3|~4.0", "symfony/http-foundation": "~2.8|~3.0|~4.0", "symfony/http-kernel": "^3.3|~4.0", - "twig/twig": "~1.34|~2.4|~4.0" + "twig/twig": "~1.34|~2.4" }, "require-dev": { "symfony/asset": "~2.8|~3.0|~4.0", From 90099706c635d8672be67c0df4fc321a5e28c4f3 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Tue, 8 Aug 2017 08:40:28 +0200 Subject: [PATCH 0593/1099] Revert "feature #21038 [FrameworkBundle] deprecated cache:clear with warmup (fabpot)" This reverts commit 3495b35e4fcdb2bf90b8aea443c1216c161dd469, reversing changes made to 7f7b897ee275d4cbbd4284dbdd05f1d207699fac. --- UPGRADE-3.3.md | 3 --- UPGRADE-4.0.md | 3 --- src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md | 1 - .../FrameworkBundle/Command/CacheClearCommand.php | 10 ---------- .../CacheClearCommand/CacheClearCommandTest.php | 3 --- 5 files changed, 20 deletions(-) diff --git a/UPGRADE-3.3.md b/UPGRADE-3.3.md index e43c365e6c5b6..3cff95d8506ce 100644 --- a/UPGRADE-3.3.md +++ b/UPGRADE-3.3.md @@ -165,9 +165,6 @@ Form FrameworkBundle --------------- - * The `cache:clear` command should always be called with the `--no-warmup` option. - Warmup should be done via the `cache:warmup` command. - * [BC BREAK] The "framework.trusted_proxies" configuration option and the corresponding "kernel.trusted_proxies" parameter have been removed. Use the Request::setTrustedProxies() method in your front controller instead. diff --git a/UPGRADE-4.0.md b/UPGRADE-4.0.md index 505ed8968a37b..67b2aa788de15 100644 --- a/UPGRADE-4.0.md +++ b/UPGRADE-4.0.md @@ -223,9 +223,6 @@ Form FrameworkBundle --------------- - * The `cache:clear` command does not warmup the cache anymore. Warmup should - be done via the `cache:warmup` command. - * The "framework.trusted_proxies" configuration option and the corresponding "kernel.trusted_proxies" parameter have been removed. Use the `Request::setTrustedProxies()` method in your front controller instead. * The default value of the `framework.workflows.[name].type` configuration options is now `state_machine`. diff --git a/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md b/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md index ba704e00f2a7a..d89c4dc254134 100644 --- a/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md +++ b/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md @@ -14,7 +14,6 @@ CHANGELOG the same helpers as the `Controller` class, but does not allow accessing the dependency injection container, in order to encourage explicit dependency declarations. * Added support for the `controller.service_arguments` tag, for injecting services into controllers' actions - * Deprecated `cache:clear` with warmup (always call it with `--no-warmup`) * Changed default configuration for assets/forms/validation/translation/serialization/csrf from `canBeEnabled()` to `canBeDisabled()` when Flex is used diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/CacheClearCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/CacheClearCommand.php index 2331afecb4e84..b7613f7436b2a 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/CacheClearCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/CacheClearCommand.php @@ -77,12 +77,6 @@ protected function execute(InputInterface $input, OutputInterface $output) if ($input->getOption('no-warmup')) { $filesystem->rename($realCacheDir, $oldCacheDir); } else { - $warning = 'Calling cache:clear without the --no-warmup option is deprecated since version 3.3. Cache warmup should be done with the cache:warmup command instead.'; - - @trigger_error($warning, E_USER_DEPRECATED); - - $io->warning($warning); - $this->warmupCache($input, $output, $realCacheDir, $oldCacheDir); } @@ -132,8 +126,6 @@ private function warmupCache(InputInterface $input, OutputInterface $output, $re * @param string $warmupDir * @param string $realCacheDir * @param bool $enableOptionalWarmers - * - * @internal to be removed in 4.0 */ protected function warmup($warmupDir, $realCacheDir, $enableOptionalWarmers = true) { @@ -200,8 +192,6 @@ protected function warmup($warmupDir, $realCacheDir, $enableOptionalWarmers = tr * @param string $warmupDir * * @return KernelInterface - * - * @internal to be removed in 4.0 */ protected function getTempKernel(KernelInterface $parent, $namespace, $parentClass, $warmupDir) { diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/CacheClearCommand/CacheClearCommandTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/CacheClearCommand/CacheClearCommandTest.php index b9fe63ec5bbab..fd3b611202252 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/CacheClearCommand/CacheClearCommandTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/CacheClearCommand/CacheClearCommandTest.php @@ -43,9 +43,6 @@ protected function tearDown() $this->fs->remove($this->rootDir); } - /** - * @group legacy - */ public function testCacheIsFreshAfterCacheClearedWithWarmup() { $input = new ArrayInput(array('cache:clear')); From cadbed301fc66ab3ada38313f62e112c83d2c97d Mon Sep 17 00:00:00 2001 From: Harold Iedema Date: Tue, 8 Aug 2017 12:48:54 +0200 Subject: [PATCH 0594/1099] [Console] Log exit codes as debug messages instead of errors --- .../Component/Console/EventListener/ErrorListener.php | 4 ++-- .../Console/Tests/EventListener/ErrorListenerTest.php | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Symfony/Component/Console/EventListener/ErrorListener.php b/src/Symfony/Component/Console/EventListener/ErrorListener.php index 8e35d97dfd489..3774f9e6666d4 100644 --- a/src/Symfony/Component/Console/EventListener/ErrorListener.php +++ b/src/Symfony/Component/Console/EventListener/ErrorListener.php @@ -59,10 +59,10 @@ public function onConsoleTerminate(ConsoleTerminateEvent $event) } if (!$inputString = $this->getInputString($event)) { - return $this->logger->error('The console exited with code "{code}"', array('code' => $exitCode)); + return $this->logger->debug('The console exited with code "{code}"', array('code' => $exitCode)); } - $this->logger->error('Command "{command}" exited with code "{code}"', array('command' => $inputString, 'code' => $exitCode)); + $this->logger->debug('Command "{command}" exited with code "{code}"', array('command' => $inputString, 'code' => $exitCode)); } public static function getSubscribedEvents() diff --git a/src/Symfony/Component/Console/Tests/EventListener/ErrorListenerTest.php b/src/Symfony/Component/Console/Tests/EventListener/ErrorListenerTest.php index c857a97d0b9bc..17eaae09084c8 100644 --- a/src/Symfony/Component/Console/Tests/EventListener/ErrorListenerTest.php +++ b/src/Symfony/Component/Console/Tests/EventListener/ErrorListenerTest.php @@ -61,7 +61,7 @@ public function testOnConsoleTerminateForNonZeroExitCodeWritesToLog() $logger = $this->getLogger(); $logger ->expects($this->once()) - ->method('error') + ->method('debug') ->with('Command "{command}" exited with code "{code}"', array('command' => 'test:run', 'code' => 255)) ; @@ -74,7 +74,7 @@ public function testOnConsoleTerminateForZeroExitCodeDoesNotWriteToLog() $logger = $this->getLogger(); $logger ->expects($this->never()) - ->method('error') + ->method('debug') ; $listener = new ErrorListener($logger); @@ -97,7 +97,7 @@ public function testAllKindsOfInputCanBeLogged() $logger = $this->getLogger(); $logger ->expects($this->exactly(3)) - ->method('error') + ->method('debug') ->with('Command "{command}" exited with code "{code}"', array('command' => 'test:run --foo=bar', 'code' => 255)) ; @@ -112,7 +112,7 @@ public function testCommandNameIsDisplayedForNonStringableInput() $logger = $this->getLogger(); $logger ->expects($this->once()) - ->method('error') + ->method('debug') ->with('Command "{command}" exited with code "{code}"', array('command' => 'test:run', 'code' => 255)) ; From cd8af2284df5220b2d7cbd87b8f844d2a7b6b07a Mon Sep 17 00:00:00 2001 From: Javier Eguiluz Date: Tue, 8 Aug 2017 15:39:42 +0200 Subject: [PATCH 0595/1099] Fixed the exception page design in responsive mode --- .../Bundle/TwigBundle/Resources/views/exception.css.twig | 8 ++++---- src/Symfony/Component/Debug/ExceptionHandler.php | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/Symfony/Bundle/TwigBundle/Resources/views/exception.css.twig b/src/Symfony/Bundle/TwigBundle/Resources/views/exception.css.twig index 9d03015f2f04e..84112fad6ed94 100644 --- a/src/Symfony/Bundle/TwigBundle/Resources/views/exception.css.twig +++ b/src/Symfony/Bundle/TwigBundle/Resources/views/exception.css.twig @@ -80,7 +80,7 @@ header .container { display: flex; justify-content: space-between; } .exception-hierarchy .icon svg { height: 13px; width: 13px; vertical-align: -2px; } .exception-without-message .exception-message-wrapper { display: none; } -.exception-message-wrapper .container { display: flex; align-items: flex-start; min-height: 70px; padding: 10px 0 8px; } +.exception-message-wrapper .container { display: flex; align-items: flex-start; min-height: 70px; padding: 10px 15px 8px; } .exception-message { flex-grow: 1; } .exception-message, .exception-message a { color: #FFF; font-size: 21px; font-weight: 400; margin: 0; } .exception-message.long { font-size: 18px; } @@ -107,11 +107,11 @@ header .container { display: flex; justify-content: space-between; } .trace-line .icon svg { height: 16px; width: 16px; } .trace-line-header { padding-left: 36px; } -.trace-file-path, .trace-file-path a { color: #999; color: #795da3; color: #B0413E; color: #222; font-size: 13px; } +.trace-file-path, .trace-file-path a { color: #222; font-size: 13px; } .trace-class { color: #B0413E; } .trace-type { padding: 0 2px; } -.trace-method { color: #B0413E; color: #222; font-weight: bold; color: #B0413E; } -.trace-arguments { color: #222; color: #999; font-weight: normal; color: #795da3; color: #777; padding-left: 2px; } +.trace-method { color: #B0413E; font-weight: bold; } +.trace-arguments { color: #777; font-weight: normal; padding-left: 2px; } .trace-code { background: #FFF; font-size: 12px; margin: 10px 10px 2px 10px; padding: 10px; overflow-x: auto; white-space: nowrap; } .trace-code ol { margin: 0; float: left; } diff --git a/src/Symfony/Component/Debug/ExceptionHandler.php b/src/Symfony/Component/Debug/ExceptionHandler.php index d84cfdd496d38..0ecd2a5347f27 100644 --- a/src/Symfony/Component/Debug/ExceptionHandler.php +++ b/src/Symfony/Component/Debug/ExceptionHandler.php @@ -320,11 +320,11 @@ public function getStylesheet(FlattenException $exception) .trace-message { font-size: 14px; font-weight: normal; margin: .5em 0 0; } - .trace-file-path, .trace-file-path a { margin-top: 3px; color: #999; color: #795da3; color: #B0413E; color: #222; font-size: 13px; } + .trace-file-path, .trace-file-path a { color: #222; margin-top: 3px; font-size: 13px; } .trace-class { color: #B0413E; } .trace-type { padding: 0 2px; } - .trace-method { color: #B0413E; color: #222; font-weight: bold; color: #B0413E; } - .trace-arguments { color: #222; color: #999; font-weight: normal; color: #795da3; color: #777; padding-left: 2px; } + .trace-method { color: #B0413E; font-weight: bold; } + .trace-arguments { color: #777; font-weight: normal; padding-left: 2px; } @media (min-width: 575px) { .hidden-xs-down { display: initial; } From a22e839592c4c5a4579d54b837f026f159c0b7ae Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Tue, 8 Aug 2017 19:53:57 +0200 Subject: [PATCH 0596/1099] [DI] Fix some docblocks --- .../Component/DependencyInjection/ChildDefinition.php | 4 ++-- .../Component/DependencyInjection/Definition.php | 10 +++++++++- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Component/DependencyInjection/ChildDefinition.php b/src/Symfony/Component/DependencyInjection/ChildDefinition.php index 5701caa474e57..862be880badfb 100644 --- a/src/Symfony/Component/DependencyInjection/ChildDefinition.php +++ b/src/Symfony/Component/DependencyInjection/ChildDefinition.php @@ -33,7 +33,7 @@ public function __construct($parent) } /** - * Returns the Definition being decorated. + * Returns the Definition to inherit from. * * @return string */ @@ -43,7 +43,7 @@ public function getParent() } /** - * Sets the Definition being decorated. + * Sets the Definition to inherit from. * * @param string $parent * diff --git a/src/Symfony/Component/DependencyInjection/Definition.php b/src/Symfony/Component/DependencyInjection/Definition.php index 68b3368da2ecc..fc3cfb2943d8d 100644 --- a/src/Symfony/Component/DependencyInjection/Definition.php +++ b/src/Symfony/Component/DependencyInjection/Definition.php @@ -250,6 +250,14 @@ public function replaceArgument($index, $argument) return $this; } + /** + * Sets a specific argument. + * + * @param int|string $key + * @param mixed $value + * + * @return $this + */ public function setArgument($key, $value) { $this->arguments[$key] = $value; @@ -778,7 +786,7 @@ public function isAutowired() } /** - * Sets autowired. + * Enables/disables autowiring. * * @param bool $autowired * From dd8622915d1decc1fdf52aad8d45ff9ff513ec5c Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Tue, 8 Aug 2017 19:11:20 +0200 Subject: [PATCH 0597/1099] [DI] Fix some docblocks --- .../DependencyInjection/ContainerBuilder.php | 4 ++-- .../DependencyInjection/Definition.php | 22 ++++++++++++++++++- 2 files changed, 23 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Component/DependencyInjection/ContainerBuilder.php b/src/Symfony/Component/DependencyInjection/ContainerBuilder.php index 5bafa94398e61..c1a2ee85c42c5 100644 --- a/src/Symfony/Component/DependencyInjection/ContainerBuilder.php +++ b/src/Symfony/Component/DependencyInjection/ContainerBuilder.php @@ -710,8 +710,8 @@ public function getAlias($id) * This methods allows for simple registration of service definition * with a fluid interface. * - * @param string $id The service identifier - * @param string $class The service class + * @param string $id The service identifier + * @param string $class|null The service class * * @return Definition A Definition instance */ diff --git a/src/Symfony/Component/DependencyInjection/Definition.php b/src/Symfony/Component/DependencyInjection/Definition.php index aa76c96805a86..cad6398f7fb8e 100644 --- a/src/Symfony/Component/DependencyInjection/Definition.php +++ b/src/Symfony/Component/DependencyInjection/Definition.php @@ -257,6 +257,13 @@ public function setArguments(array $arguments) return $this; } + /** + * Sets the properties to define when creating the service. + * + * @param array $properties + * + * @return $this + */ public function setProperties(array $properties) { $this->properties = $properties; @@ -264,11 +271,24 @@ public function setProperties(array $properties) return $this; } + /** + * Gets the properties to define when creating the service. + * + * @return array + */ public function getProperties() { return $this->properties; } + /** + * Sets a specific property. + * + * @param string $name + * @param mixed $value + * + * @return $this + */ public function setProperty($name, $value) { $this->properties[$name] = $value; @@ -291,7 +311,7 @@ public function addArgument($argument) } /** - * Sets a specific argument. + * Replaces a specific argument. * * @param int $index * @param mixed $argument From e6406d21cdab883e53fcf24bea3daee47702b542 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Wed, 9 Aug 2017 07:21:07 +0200 Subject: [PATCH 0598/1099] [HttpFoundation] Remove length limit on ETag --- src/Symfony/Component/HttpFoundation/BinaryFileResponse.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/HttpFoundation/BinaryFileResponse.php b/src/Symfony/Component/HttpFoundation/BinaryFileResponse.php index 7ffa984017180..3c32871c4d663 100644 --- a/src/Symfony/Component/HttpFoundation/BinaryFileResponse.php +++ b/src/Symfony/Component/HttpFoundation/BinaryFileResponse.php @@ -141,7 +141,7 @@ public function setAutoLastModified() */ public function setAutoEtag() { - $this->setEtag(substr(base64_encode(hash_file('sha256', $this->file->getPathname(), true)), 0, 32)); + $this->setEtag(base64_encode(hash_file('sha256', $this->file->getPathname(), true))); return $this; } From 81f26523719635cadc6439ef6f8b2fdaa4b3a803 Mon Sep 17 00:00:00 2001 From: Guilhem Niot Date: Mon, 27 Mar 2017 20:16:27 +0200 Subject: [PATCH 0599/1099] [DependencyInjection] Support local binding --- .../Argument/BoundArgument.php | 46 ++++++ .../DependencyInjection/ChildDefinition.php | 8 + .../Compiler/AbstractRecursivePass.php | 1 + .../Compiler/PassConfig.php | 1 + .../Compiler/ResolveBindingsPass.php | 154 ++++++++++++++++++ .../ResolveDefinitionTemplatesPass.php | 2 + .../Compiler/ResolveNamedArgumentsPass.php | 25 ++- .../DependencyInjection/Definition.php | 36 ++++ .../Loader/XmlFileLoader.php | 21 ++- .../Loader/YamlFileLoader.php | 70 +++++--- .../schema/dic/services/services-1.0.xsd | 15 ++ .../Compiler/ResolveBindingsPassTest.php | 82 ++++++++++ .../ResolveNamedArgumentsPassTest.php | 14 ++ .../Tests/Fixtures/Bar.php | 23 +++ .../Tests/Fixtures/BarInterface.php | 16 ++ .../Tests/Fixtures/NamedArgumentsDummy.php | 4 + .../Tests/Fixtures/xml/services_bindings.xml | 21 +++ .../Fixtures/xml/services_instanceof.xml | 5 +- .../Fixtures/xml/services_named_args.xml | 2 +- .../Tests/Fixtures/yaml/services_bindings.yml | 16 ++ .../Fixtures/yaml/services_instanceof.yml | 5 +- .../Fixtures/yaml/services_named_args.yml | 2 +- .../Tests/Loader/XmlFileLoaderTest.php | 42 ++++- .../Tests/Loader/YamlFileLoaderTest.php | 44 ++++- ...RegisterControllerArgumentLocatorsPass.php | 12 ++ ...sterControllerArgumentLocatorsPassTest.php | 29 ++++ .../Component/HttpKernel/composer.json | 4 +- 27 files changed, 651 insertions(+), 49 deletions(-) create mode 100644 src/Symfony/Component/DependencyInjection/Argument/BoundArgument.php create mode 100644 src/Symfony/Component/DependencyInjection/Compiler/ResolveBindingsPass.php create mode 100644 src/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveBindingsPassTest.php create mode 100644 src/Symfony/Component/DependencyInjection/Tests/Fixtures/Bar.php create mode 100644 src/Symfony/Component/DependencyInjection/Tests/Fixtures/BarInterface.php create mode 100644 src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services_bindings.xml create mode 100644 src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services_bindings.yml diff --git a/src/Symfony/Component/DependencyInjection/Argument/BoundArgument.php b/src/Symfony/Component/DependencyInjection/Argument/BoundArgument.php new file mode 100644 index 0000000000000..f72f2110744c1 --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Argument/BoundArgument.php @@ -0,0 +1,46 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Argument; + +/** + * @author Guilhem Niot + */ +final class BoundArgument implements ArgumentInterface +{ + private static $sequence = 0; + + private $value; + private $identifier; + private $used; + + public function __construct($value) + { + $this->value = $value; + $this->identifier = ++self::$sequence; + } + + /** + * {@inheritdoc} + */ + public function getValues() + { + return array($this->value, $this->identifier, $this->used); + } + + /** + * {@inheritdoc} + */ + public function setValues(array $values) + { + list($this->value, $this->identifier, $this->used) = $values; + } +} diff --git a/src/Symfony/Component/DependencyInjection/ChildDefinition.php b/src/Symfony/Component/DependencyInjection/ChildDefinition.php index 5701caa474e57..d2a268aa60865 100644 --- a/src/Symfony/Component/DependencyInjection/ChildDefinition.php +++ b/src/Symfony/Component/DependencyInjection/ChildDefinition.php @@ -120,6 +120,14 @@ public function setInstanceofConditionals(array $instanceof) { throw new BadMethodCallException('A ChildDefinition cannot have instanceof conditionals set on it.'); } + + /** + * @internal + */ + public function setBindings(array $bindings) + { + throw new BadMethodCallException('A ChildDefinition cannot have bindings set on it.'); + } } class_alias(ChildDefinition::class, DefinitionDecorator::class); diff --git a/src/Symfony/Component/DependencyInjection/Compiler/AbstractRecursivePass.php b/src/Symfony/Component/DependencyInjection/Compiler/AbstractRecursivePass.php index 8ded4ba6d1cdf..bbe869b935e5c 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/AbstractRecursivePass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/AbstractRecursivePass.php @@ -64,6 +64,7 @@ protected function processValue($value, $isRoot = false) $value->setArguments($this->processValue($value->getArguments())); $value->setProperties($this->processValue($value->getProperties())); $value->setMethodCalls($this->processValue($value->getMethodCalls())); + $value->setBindings($this->processValue($value->getBindings())); $changes = $value->getChanges(); if (isset($changes['factory'])) { diff --git a/src/Symfony/Component/DependencyInjection/Compiler/PassConfig.php b/src/Symfony/Component/DependencyInjection/Compiler/PassConfig.php index 57ecc42ea0272..184c7b25a0883 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/PassConfig.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/PassConfig.php @@ -57,6 +57,7 @@ public function __construct() new CheckDefinitionValidityPass(), new RegisterServiceSubscribersPass(), new ResolveNamedArgumentsPass(), + new ResolveBindingsPass(), $autowirePass = new AutowirePass(false), new ResolveServiceSubscribersPass(), new ResolveReferencesToAliasesPass(), diff --git a/src/Symfony/Component/DependencyInjection/Compiler/ResolveBindingsPass.php b/src/Symfony/Component/DependencyInjection/Compiler/ResolveBindingsPass.php new file mode 100644 index 0000000000000..73ca29d35f424 --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Compiler/ResolveBindingsPass.php @@ -0,0 +1,154 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Compiler; + +use Symfony\Component\DependencyInjection\Argument\BoundArgument; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Definition; +use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; +use Symfony\Component\DependencyInjection\LazyProxy\ProxyHelper; +use Symfony\Component\DependencyInjection\TypedReference; +use Symfony\Component\DependencyInjection\Reference; + +/** + * @author Guilhem Niot + */ +class ResolveBindingsPass extends AbstractRecursivePass +{ + private $usedBindings = array(); + private $unusedBindings = array(); + + /** + * {@inheritdoc} + */ + public function process(ContainerBuilder $container) + { + try { + parent::process($container); + + foreach ($this->unusedBindings as list($key, $serviceId)) { + throw new InvalidArgumentException(sprintf('Unused binding "%s" in service "%s".', $key, $serviceId)); + } + } finally { + $this->usedBindings = array(); + $this->unusedBindings = array(); + } + } + + /** + * {@inheritdoc} + */ + protected function processValue($value, $isRoot = false) + { + if ($value instanceof TypedReference && $value->getType() === (string) $value) { + // Already checked + $bindings = $this->container->getDefinition($this->currentId)->getBindings(); + + if (isset($bindings[$value->getType()])) { + return $this->getBindingValue($bindings[$value->getType()]); + } + + return parent::processValue($value, $isRoot); + } + + if (!$value instanceof Definition || !$bindings = $value->getBindings()) { + return parent::processValue($value, $isRoot); + } + + foreach ($bindings as $key => $binding) { + list($bindingValue, $bindingId, $used) = $binding->getValues(); + if ($used) { + $this->usedBindings[$bindingId] = true; + unset($this->unusedBindings[$bindingId]); + } elseif (!isset($this->usedBindings[$bindingId])) { + $this->unusedBindings[$bindingId] = array($key, $this->currentId); + } + + if (isset($key[0]) && '$' === $key[0]) { + continue; + } + + if (null !== $bindingValue && !$bindingValue instanceof Reference && !$bindingValue instanceof Definition) { + throw new InvalidArgumentException(sprintf('Invalid value for binding key "%s" for service "%s": expected null, an instance of %s or an instance of %s, %s given.', $key, $this->currentId, Reference::class, Definition::class, gettype($bindingValue))); + } + } + + if ($value->isAbstract()) { + return parent::processValue($value, $isRoot); + } + + $calls = $value->getMethodCalls(); + + if ($constructor = $this->getConstructor($value, false)) { + $calls[] = array($constructor, $value->getArguments()); + } + + foreach ($calls as $i => $call) { + list($method, $arguments) = $call; + + if ($method instanceof \ReflectionFunctionAbstract) { + $reflectionMethod = $method; + } else { + $reflectionMethod = $this->getReflectionMethod($value, $method); + } + + foreach ($reflectionMethod->getParameters() as $key => $parameter) { + if (array_key_exists($key, $arguments) && '' !== $arguments[$key]) { + continue; + } + + if (array_key_exists('$'.$parameter->name, $bindings)) { + $arguments[$key] = $this->getBindingValue($bindings['$'.$parameter->name]); + + continue; + } + + $typeHint = ProxyHelper::getTypeHint($reflectionMethod, $parameter, true); + + if (!isset($bindings[$typeHint])) { + continue; + } + + $arguments[$key] = $this->getBindingValue($bindings[$typeHint]); + } + + if ($arguments !== $call[1]) { + ksort($arguments); + $calls[$i][1] = $arguments; + } + } + + if ($constructor) { + list(, $arguments) = array_pop($calls); + + if ($arguments !== $value->getArguments()) { + $value->setArguments($arguments); + } + } + + if ($calls !== $value->getMethodCalls()) { + $value->setMethodCalls($calls); + } + + return parent::processValue($value, $isRoot); + } + + private function getBindingValue(BoundArgument $binding) + { + list($bindingValue, $bindingId) = $binding->getValues(); + + $this->usedBindings[$bindingId] = true; + unset($this->unusedBindings[$bindingId]); + + return $bindingValue; + } +} diff --git a/src/Symfony/Component/DependencyInjection/Compiler/ResolveDefinitionTemplatesPass.php b/src/Symfony/Component/DependencyInjection/Compiler/ResolveDefinitionTemplatesPass.php index dfceb6a920832..89ca74c459b48 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/ResolveDefinitionTemplatesPass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/ResolveDefinitionTemplatesPass.php @@ -103,6 +103,8 @@ private function doResolveDefinition(ChildDefinition $definition) $def->setAutowired($parentDef->isAutowired()); $def->setChanges($parentDef->getChanges()); + $def->setBindings($parentDef->getBindings()); + // overwrite with values specified in the decorator $changes = $definition->getChanges(); if (isset($changes['class'])) { diff --git a/src/Symfony/Component/DependencyInjection/Compiler/ResolveNamedArgumentsPass.php b/src/Symfony/Component/DependencyInjection/Compiler/ResolveNamedArgumentsPass.php index 861e029ebfec0..e4d592d0c6473 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/ResolveNamedArgumentsPass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/ResolveNamedArgumentsPass.php @@ -13,6 +13,8 @@ use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; +use Symfony\Component\DependencyInjection\LazyProxy\ProxyHelper; +use Symfony\Component\DependencyInjection\Reference; /** * Resolves named arguments to their corresponding numeric index. @@ -43,9 +45,6 @@ protected function processValue($value, $isRoot = false) $resolvedArguments[$key] = $argument; continue; } - if ('' === $key || '$' !== $key[0]) { - throw new InvalidArgumentException(sprintf('Invalid key "%s" found in arguments of method "%s()" for service "%s": only integer or $named arguments are allowed.', $key, $method, $this->currentId)); - } if (null === $parameters) { $r = $this->getReflectionMethod($value, $method); @@ -53,15 +52,31 @@ protected function processValue($value, $isRoot = false) $parameters = $r->getParameters(); } + if (isset($key[0]) && '$' === $key[0]) { + foreach ($parameters as $j => $p) { + if ($key === '$'.$p->name) { + $resolvedArguments[$j] = $argument; + + continue 2; + } + } + + throw new InvalidArgumentException(sprintf('Unable to resolve service "%s": method "%s()" has no argument named "%s". Check your service definition.', $this->currentId, $class !== $this->currentId ? $class.'::'.$method : $method, $key)); + } + + if (null !== $argument && !$argument instanceof Reference && !$argument instanceof Definition) { + throw new InvalidArgumentException(sprintf('Unable to resolve service "%s": the value of argument "%s" of method "%s()" must be null, an instance of %s or an instance of %s, %s given.', $this->currentId, $key, $class !== $this->currentId ? $class.'::'.$method : $method, Reference::class, Definition::class, gettype($argument))); + } + foreach ($parameters as $j => $p) { - if ($key === '$'.$p->name) { + if (ProxyHelper::getTypeHint($r, $p, true) === $key) { $resolvedArguments[$j] = $argument; continue 2; } } - throw new InvalidArgumentException(sprintf('Unable to resolve service "%s": method "%s()" has no argument named "%s". Check your service definition.', $this->currentId, $class !== $this->currentId ? $class.'::'.$method : $method, $key)); + throw new InvalidArgumentException(sprintf('Unable to resolve service "%s": method "%s()" has no argument type-hinted as "%s". Check your service definition.', $this->currentId, $class !== $this->currentId ? $class.'::'.$method : $method, $key)); } if ($resolvedArguments !== $call[1]) { diff --git a/src/Symfony/Component/DependencyInjection/Definition.php b/src/Symfony/Component/DependencyInjection/Definition.php index 68b3368da2ecc..acb798fa45071 100644 --- a/src/Symfony/Component/DependencyInjection/Definition.php +++ b/src/Symfony/Component/DependencyInjection/Definition.php @@ -11,6 +11,7 @@ namespace Symfony\Component\DependencyInjection; +use Symfony\Component\DependencyInjection\Argument\BoundArgument; use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; use Symfony\Component\DependencyInjection\Exception\OutOfBoundsException; @@ -41,6 +42,7 @@ class Definition private $autowired = false; private $autowiringTypes = array(); private $changes = array(); + private $bindings = array(); protected $arguments = array(); @@ -860,4 +862,38 @@ public function hasAutowiringType($type) return isset($this->autowiringTypes[$type]); } + + /** + * Gets bindings. + * + * @return array + */ + public function getBindings() + { + return $this->bindings; + } + + /** + * Sets bindings. + * + * Bindings map $named or FQCN arguments to values that should be + * injected in the matching parameters (of the constructor, of methods + * called and of controller actions). + * + * @param array $bindings + * + * @return $this + */ + public function setBindings(array $bindings) + { + foreach ($bindings as $key => $binding) { + if (!$binding instanceof BoundArgument) { + $bindings[$key] = new BoundArgument($binding); + } + } + + $this->bindings = $bindings; + + return $this; + } } diff --git a/src/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php b/src/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php index fa4c33d51459a..2315b529824df 100644 --- a/src/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php +++ b/src/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php @@ -14,6 +14,7 @@ use Symfony\Component\Config\Util\XmlUtils; use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\DependencyInjection\Alias; +use Symfony\Component\DependencyInjection\Argument\BoundArgument; use Symfony\Component\DependencyInjection\Argument\IteratorArgument; use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\DependencyInjection\ChildDefinition; @@ -165,6 +166,7 @@ private function getServiceDefaults(\DOMDocument $xml, $file) } $defaults = array( 'tags' => $this->getChildren($defaultsNode, 'tag'), + 'bind' => array_map(function ($v) { return new BoundArgument($v); }, $this->getArgumentsAsPhp($defaultsNode, 'bind', $file)), ); foreach ($defaults['tags'] as $tag) { @@ -172,6 +174,7 @@ private function getServiceDefaults(\DOMDocument $xml, $file) throw new InvalidArgumentException(sprintf('The tag name for tag "" in %s must be a non-empty string.', $file)); } } + if ($defaultsNode->hasAttribute('autowire')) { $defaults['autowire'] = XmlUtils::phpize($defaultsNode->getAttribute('autowire')); } @@ -223,6 +226,13 @@ private function parseDefinition(\DOMElement $service, $file, array $defaults) // thus we can safely add them as defaults to ChildDefinition continue; } + if ('bind' === $k) { + if ($defaults['bind']) { + throw new InvalidArgumentException(sprintf('Bound values on service "%s" cannot be inherited from "defaults" when a "parent" is set. Move your child definitions to a separate file.', $k, $service->getAttribute('id'))); + } + + continue; + } if (!$service->hasAttribute($k)) { throw new InvalidArgumentException(sprintf('Attribute "%s" on service "%s" cannot be inherited from "defaults" when a "parent" is set. Move your child definitions to a separate file or define this attribute explicitly.', $k, $service->getAttribute('id'))); } @@ -344,6 +354,15 @@ private function parseDefinition(\DOMElement $service, $file, array $defaults) $definition->addAutowiringType($type->textContent); } + $bindings = $this->getArgumentsAsPhp($service, 'bind', $file); + if (isset($defaults['bind'])) { + // deep clone, to avoid multiple process of the same instance in the passes + $bindings = array_merge(unserialize(serialize($defaults['bind'])), $bindings); + } + if ($bindings) { + $definition->setBindings($bindings); + } + if ($value = $service->getAttribute('decorates')) { $renameId = $service->hasAttribute('decoration-inner-name') ? $service->getAttribute('decoration-inner-name') : null; $priority = $service->hasAttribute('decoration-priority') ? $service->getAttribute('decoration-priority') : 0; @@ -391,7 +410,7 @@ private function processAnonymousServices(\DOMDocument $xml, $file, $defaults) $xpath->registerNamespace('container', self::NS); // anonymous services as arguments/properties - if (false !== $nodes = $xpath->query('//container:argument[@type="service"][not(@id)]|//container:property[@type="service"][not(@id)]|//container:factory[not(@service)]|//container:configurator[not(@service)]')) { + if (false !== $nodes = $xpath->query('//container:argument[@type="service"][not(@id)]|//container:property[@type="service"][not(@id)]|//container:bind[not(@id)]|//container:factory[not(@service)]|//container:configurator[not(@service)]')) { foreach ($nodes as $node) { if ($services = $this->getChildren($node, 'service')) { // give it a unique name diff --git a/src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php b/src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php index 221a218cc32c3..51bf209780687 100644 --- a/src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php +++ b/src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php @@ -13,6 +13,7 @@ use Symfony\Component\DependencyInjection\Alias; use Symfony\Component\DependencyInjection\Argument\ArgumentInterface; +use Symfony\Component\DependencyInjection\Argument\BoundArgument; use Symfony\Component\DependencyInjection\Argument\IteratorArgument; use Symfony\Component\DependencyInjection\ChildDefinition; use Symfony\Component\DependencyInjection\ContainerInterface; @@ -56,6 +57,7 @@ class YamlFileLoader extends FileLoader 'autowire' => 'autowire', 'autowiring_types' => 'autowiring_types', 'autoconfigure' => 'autoconfigure', + 'bind' => 'bind', ); private static $prototypeKeywords = array( @@ -75,6 +77,7 @@ class YamlFileLoader extends FileLoader 'tags' => 'tags', 'autowire' => 'autowire', 'autoconfigure' => 'autoconfigure', + 'bind' => 'bind', ); private static $instanceofKeywords = array( @@ -93,6 +96,7 @@ class YamlFileLoader extends FileLoader 'tags' => 'tags', 'autowire' => 'autowire', 'autoconfigure' => 'autoconfigure', + 'bind' => 'bind', ); private $yamlParser; @@ -256,33 +260,41 @@ private function parseDefaults(array &$content, $file) throw new InvalidArgumentException(sprintf('The configuration key "%s" cannot be used to define a default value in "%s". Allowed keys are "%s".', $key, $file, implode('", "', self::$defaultsKeywords))); } } - if (!isset($defaults['tags'])) { - return $defaults; - } - if (!is_array($tags = $defaults['tags'])) { - throw new InvalidArgumentException(sprintf('Parameter "tags" in "_defaults" must be an array in %s. Check your YAML syntax.', $file)); - } - foreach ($tags as $tag) { - if (!is_array($tag)) { - $tag = array('name' => $tag); + if (isset($defaults['tags'])) { + if (!is_array($tags = $defaults['tags'])) { + throw new InvalidArgumentException(sprintf('Parameter "tags" in "_defaults" must be an array in %s. Check your YAML syntax.', $file)); } - if (!isset($tag['name'])) { - throw new InvalidArgumentException(sprintf('A "tags" entry in "_defaults" is missing a "name" key in %s.', $file)); - } - $name = $tag['name']; - unset($tag['name']); + foreach ($tags as $tag) { + if (!is_array($tag)) { + $tag = array('name' => $tag); + } - if (!is_string($name) || '' === $name) { - throw new InvalidArgumentException(sprintf('The tag name in "_defaults" must be a non-empty string in %s.', $file)); - } + if (!isset($tag['name'])) { + throw new InvalidArgumentException(sprintf('A "tags" entry in "_defaults" is missing a "name" key in %s.', $file)); + } + $name = $tag['name']; + unset($tag['name']); - foreach ($tag as $attribute => $value) { - if (!is_scalar($value) && null !== $value) { - throw new InvalidArgumentException(sprintf('Tag "%s", attribute "%s" in "_defaults" must be of a scalar-type in %s. Check your YAML syntax.', $name, $attribute, $file)); + if (!is_string($name) || '' === $name) { + throw new InvalidArgumentException(sprintf('The tag name in "_defaults" must be a non-empty string in %s.', $file)); } + + foreach ($tag as $attribute => $value) { + if (!is_scalar($value) && null !== $value) { + throw new InvalidArgumentException(sprintf('Tag "%s", attribute "%s" in "_defaults" must be of a scalar-type in %s. Check your YAML syntax.', $name, $attribute, $file)); + } + } + } + } + + if (isset($defaults['bind'])) { + if (!is_array($defaults['bind'])) { + throw new InvalidArgumentException(sprintf('Parameter "bind" in "_defaults" must be an array in %s. Check your YAML syntax.', $file)); } + + $defaults['bind'] = array_map(function ($v) { return new BoundArgument($v); }, $this->resolveServices($defaults['bind'], $file)); } return $defaults; @@ -366,6 +378,9 @@ private function parseDefinition($id, $service, $file, array $defaults) // thus we can safely add them as defaults to ChildDefinition continue; } + if ('bind' === $k) { + throw new InvalidArgumentException(sprintf('Attribute "bind" on service "%s" cannot be inherited from "_defaults" when a "parent" is set. Move your child definitions to a separate file.', $id)); + } if (!isset($service[$k])) { throw new InvalidArgumentException(sprintf('Attribute "%s" on service "%s" cannot be inherited from "_defaults" when a "parent" is set. Move your child definitions to a separate file or define this attribute explicitly.', $k, $id)); } @@ -519,6 +534,21 @@ private function parseDefinition($id, $service, $file, array $defaults) } } + if (isset($defaults['bind']) || isset($service['bind'])) { + // deep clone, to avoid multiple process of the same instance in the passes + $bindings = isset($defaults['bind']) ? unserialize(serialize($defaults['bind'])) : array(); + + if (isset($service['bind'])) { + if (!is_array($service['bind'])) { + throw new InvalidArgumentException(sprintf('Parameter "bind" must be an array for service "%s" in %s. Check your YAML syntax.', $id, $file)); + } + + $bindings = array_merge($bindings, $this->resolveServices($service['bind'], $file)); + } + + $definition->setBindings($bindings); + } + if (isset($service['autoconfigure'])) { if (!$definition instanceof ChildDefinition) { $definition->setAutoconfigured($service['autoconfigure']); diff --git a/src/Symfony/Component/DependencyInjection/Loader/schema/dic/services/services-1.0.xsd b/src/Symfony/Component/DependencyInjection/Loader/schema/dic/services/services-1.0.xsd index 6f5c8ccc543d3..aad40ac63138d 100644 --- a/src/Symfony/Component/DependencyInjection/Loader/schema/dic/services/services-1.0.xsd +++ b/src/Symfony/Component/DependencyInjection/Loader/schema/dic/services/services-1.0.xsd @@ -100,6 +100,7 @@ + @@ -117,6 +118,7 @@ + @@ -158,6 +160,7 @@ + @@ -207,6 +210,18 @@ + + + + + + + + + + + + diff --git a/src/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveBindingsPassTest.php b/src/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveBindingsPassTest.php new file mode 100644 index 0000000000000..f7e29d2110ff1 --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveBindingsPassTest.php @@ -0,0 +1,82 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Tests\Compiler; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\DependencyInjection\Argument\BoundArgument; +use Symfony\Component\DependencyInjection\Compiler\ResolveBindingsPass; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Reference; +use Symfony\Component\DependencyInjection\Tests\Fixtures\NamedArgumentsDummy; +use Symfony\Component\DependencyInjection\Tests\Fixtures\CaseSensitiveClass; +use Symfony\Component\DependencyInjection\TypedReference; + +class ResolveBindingsPassTest extends TestCase +{ + public function testProcess() + { + $container = new ContainerBuilder(); + + $bindings = array(CaseSensitiveClass::class => new BoundArgument(new Reference('foo'))); + + $definition = $container->register(NamedArgumentsDummy::class, NamedArgumentsDummy::class); + $definition->setArguments(array(1 => '123')); + $definition->addMethodCall('setSensitiveClass'); + $definition->setBindings($bindings); + + $container->register('foo', CaseSensitiveClass::class) + ->setBindings($bindings); + + $pass = new ResolveBindingsPass(); + $pass->process($container); + + $this->assertEquals(array(new Reference('foo'), '123'), $definition->getArguments()); + $this->assertEquals(array(array('setSensitiveClass', array(new Reference('foo')))), $definition->getMethodCalls()); + } + + /** + * @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException + * @expectedExceptionMessage Unused binding "$quz" in service "Symfony\Component\DependencyInjection\Tests\Fixtures\NamedArgumentsDummy". + */ + public function testUnusedBinding() + { + $container = new ContainerBuilder(); + + $definition = $container->register(NamedArgumentsDummy::class, NamedArgumentsDummy::class); + $definition->setBindings(array('$quz' => '123')); + + $pass = new ResolveBindingsPass(); + $pass->process($container); + } + + public function testTypedReferenceSupport() + { + $container = new ContainerBuilder(); + + $bindings = array(CaseSensitiveClass::class => new BoundArgument(new Reference('foo'))); + + // Explicit service id + $definition1 = $container->register('def1', NamedArgumentsDummy::class); + $definition1->addArgument($typedRef = new TypedReference('bar', CaseSensitiveClass::class)); + $definition1->setBindings($bindings); + + $definition2 = $container->register('def2', NamedArgumentsDummy::class); + $definition2->addArgument(new TypedReference(CaseSensitiveClass::class, CaseSensitiveClass::class)); + $definition2->setBindings($bindings); + + $pass = new ResolveBindingsPass(); + $pass->process($container); + + $this->assertEquals(array($typedRef), $container->getDefinition('def1')->getArguments()); + $this->assertEquals(array(new Reference('foo')), $container->getDefinition('def2')->getArguments()); + } +} diff --git a/src/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveNamedArgumentsPassTest.php b/src/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveNamedArgumentsPassTest.php index 8a214cd52da98..fac05f070b05c 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveNamedArgumentsPassTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveNamedArgumentsPassTest.php @@ -15,6 +15,7 @@ use Symfony\Component\DependencyInjection\Compiler\ResolveNamedArgumentsPass; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Reference; +use Symfony\Component\DependencyInjection\Tests\Fixtures\CaseSensitiveClass; use Symfony\Component\DependencyInjection\Tests\Fixtures\NamedArgumentsDummy; /** @@ -111,6 +112,19 @@ public function testArgumentNotFound() $pass = new ResolveNamedArgumentsPass(); $pass->process($container); } + + public function testTypedArgument() + { + $container = new ContainerBuilder(); + + $definition = $container->register(NamedArgumentsDummy::class, NamedArgumentsDummy::class); + $definition->setArguments(array('$apiKey' => '123', CaseSensitiveClass::class => new Reference('foo'))); + + $pass = new ResolveNamedArgumentsPass(); + $pass->process($container); + + $this->assertEquals(array(new Reference('foo'), '123'), $definition->getArguments()); + } } class NoConstructor diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/Bar.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/Bar.php new file mode 100644 index 0000000000000..d243866d36ef9 --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/Bar.php @@ -0,0 +1,23 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Tests\Fixtures; + +class Bar implements BarInterface +{ + public function __construct($quz = null, \NonExistent $nonExistent = null, BarInterface $decorated = null, array $foo = array()) + { + } + + public static function create(\NonExistent $nonExistent = null, $factory = null) + { + } +} diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/BarInterface.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/BarInterface.php new file mode 100644 index 0000000000000..dc81f33f5d950 --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/BarInterface.php @@ -0,0 +1,16 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Tests\Fixtures; + +interface BarInterface +{ +} diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/NamedArgumentsDummy.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/NamedArgumentsDummy.php index 65c4847bbdef5..09d907dfae769 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/NamedArgumentsDummy.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/NamedArgumentsDummy.php @@ -14,4 +14,8 @@ public function __construct(CaseSensitiveClass $c, $apiKey, $hostName) public function setApiKey($apiKey) { } + + public function setSensitiveClass(CaseSensitiveClass $c) + { + } } diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services_bindings.xml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services_bindings.xml new file mode 100644 index 0000000000000..408bca5f75346 --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services_bindings.xml @@ -0,0 +1,21 @@ + + + + + null + quz + factory + + + + + + null + + + + + + + + diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services_instanceof.xml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services_instanceof.xml index 75318aa0e520a..839776a3fed97 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services_instanceof.xml +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services_instanceof.xml @@ -1,11 +1,12 @@ - + - + + diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services_named_args.xml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services_named_args.xml index 7862d36390ce5..95dabde9c4b6b 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services_named_args.xml +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services_named_args.xml @@ -2,8 +2,8 @@ - ABCD + null 123 diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services_bindings.yml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services_bindings.yml new file mode 100644 index 0000000000000..48ad040406219 --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services_bindings.yml @@ -0,0 +1,16 @@ +services: + _defaults: + bind: + NonExistent: ~ + $quz: quz + $factory: factory + + bar: + class: Symfony\Component\DependencyInjection\Tests\Fixtures\Bar + autowire: true + bind: + Symfony\Component\DependencyInjection\Tests\Fixtures\BarInterface: '@Symfony\Component\DependencyInjection\Tests\Fixtures\Bar' + $foo: [ ~ ] + + Symfony\Component\DependencyInjection\Tests\Fixtures\Bar: + factory: [ ~, 'create' ] diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services_instanceof.yml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services_instanceof.yml index f0612c6d0a684..a58cc079e455f 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services_instanceof.yml +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services_instanceof.yml @@ -1,10 +1,11 @@ services: _instanceof: - Symfony\Component\DependencyInjection\Tests\Loader\FooInterface: + Symfony\Component\DependencyInjection\Tests\Fixtures\BarInterface: autowire: true lazy: true tags: - { name: foo } - { name: bar } - Symfony\Component\DependencyInjection\Tests\Loader\Foo: ~ + Symfony\Component\DependencyInjection\Tests\Fixtures\Bar: ~ + Symfony\Component\DependencyInjection\Tests\Fixtures\BarInterface: '@Symfony\Component\DependencyInjection\Tests\Fixtures\Bar' diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services_named_args.yml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services_named_args.yml index 3d2cb6920b2da..97e310148df04 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services_named_args.yml +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services_named_args.yml @@ -4,7 +4,7 @@ services: another_one: class: Symfony\Component\DependencyInjection\Tests\Fixtures\NamedArgumentsDummy arguments: - 0: ~ $apiKey: ABCD + Symfony\Component\DependencyInjection\Tests\Fixtures\CaseSensitiveClass: ~ calls: - ['setApiKey', { $apiKey: '123' }] diff --git a/src/Symfony/Component/DependencyInjection/Tests/Loader/XmlFileLoaderTest.php b/src/Symfony/Component/DependencyInjection/Tests/Loader/XmlFileLoaderTest.php index 9ffe5793e4764..8f6467c05eb76 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Loader/XmlFileLoaderTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Loader/XmlFileLoaderTest.php @@ -22,6 +22,8 @@ use Symfony\Component\Config\FileLocator; use Symfony\Component\Config\Resource\FileResource; use Symfony\Component\Config\Resource\GlobResource; +use Symfony\Component\DependencyInjection\Tests\Fixtures\Bar; +use Symfony\Component\DependencyInjection\Tests\Fixtures\BarInterface; use Symfony\Component\DependencyInjection\Tests\Fixtures\CaseSensitiveClass; use Symfony\Component\DependencyInjection\Tests\Fixtures\Prototype; use Symfony\Component\DependencyInjection\Tests\Fixtures\NamedArgumentsDummy; @@ -702,7 +704,7 @@ public function testNamedArguments() $loader = new XmlFileLoader($container, new FileLocator(self::$fixturesPath.'/xml')); $loader->load('services_named_args.xml'); - $this->assertEquals(array(null, '$apiKey' => 'ABCD'), $container->getDefinition(NamedArgumentsDummy::class)->getArguments()); + $this->assertEquals(array('$apiKey' => 'ABCD', CaseSensitiveClass::class => null), $container->getDefinition(NamedArgumentsDummy::class)->getArguments()); $container->compile(); @@ -768,12 +770,38 @@ public function testAutoConfigureInstanceof() $this->assertTrue($container->getDefinition('use_defaults_settings')->isAutoconfigured()); $this->assertFalse($container->getDefinition('override_defaults_settings_to_false')->isAutoconfigured()); } -} -interface BarInterface -{ -} + public function testBindings() + { + $container = new ContainerBuilder(); + $loader = new XmlFileLoader($container, new FileLocator(self::$fixturesPath.'/xml')); + $loader->load('services_bindings.xml'); + $container->compile(); -class Bar implements BarInterface -{ + $definition = $container->getDefinition('bar'); + $this->assertEquals(array( + 'NonExistent' => null, + BarInterface::class => new Reference(Bar::class), + '$foo' => array(null), + '$quz' => 'quz', + '$factory' => 'factory', + ), array_map(function ($v) { return $v->getValues()[0]; }, $definition->getBindings())); + $this->assertEquals(array( + 'quz', + null, + new Reference(Bar::class), + array(null), + ), $definition->getArguments()); + + $definition = $container->getDefinition(Bar::class); + $this->assertEquals(array( + null, + 'factory', + ), $definition->getArguments()); + $this->assertEquals(array( + 'NonExistent' => null, + '$quz' => 'quz', + '$factory' => 'factory', + ), array_map(function ($v) { return $v->getValues()[0]; }, $definition->getBindings())); + } } diff --git a/src/Symfony/Component/DependencyInjection/Tests/Loader/YamlFileLoaderTest.php b/src/Symfony/Component/DependencyInjection/Tests/Loader/YamlFileLoaderTest.php index b8ac2fc0e9296..1229e5a50b466 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Loader/YamlFileLoaderTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Loader/YamlFileLoaderTest.php @@ -23,6 +23,8 @@ use Symfony\Component\Config\FileLocator; use Symfony\Component\Config\Resource\FileResource; use Symfony\Component\Config\Resource\GlobResource; +use Symfony\Component\DependencyInjection\Tests\Fixtures\Bar; +use Symfony\Component\DependencyInjection\Tests\Fixtures\BarInterface; use Symfony\Component\DependencyInjection\Tests\Fixtures\CaseSensitiveClass; use Symfony\Component\DependencyInjection\Tests\Fixtures\Prototype; use Symfony\Component\DependencyInjection\Tests\Fixtures\NamedArgumentsDummy; @@ -431,7 +433,7 @@ public function testNamedArguments() $loader->load('services_named_args.yml'); $this->assertEquals(array(null, '$apiKey' => 'ABCD'), $container->getDefinition(NamedArgumentsDummy::class)->getArguments()); - $this->assertEquals(array(null, '$apiKey' => 'ABCD'), $container->getDefinition('another_one')->getArguments()); + $this->assertEquals(array('$apiKey' => 'ABCD', CaseSensitiveClass::class => null), $container->getDefinition('another_one')->getArguments()); $container->compile(); @@ -447,7 +449,7 @@ public function testInstanceof() $loader->load('services_instanceof.yml'); $container->compile(); - $definition = $container->getDefinition(Foo::class); + $definition = $container->getDefinition(Bar::class); $this->assertTrue($definition->isAutowired()); $this->assertTrue($definition->isLazy()); $this->assertSame(array('foo' => array(array()), 'bar' => array(array())), $definition->getTags()); @@ -646,12 +648,38 @@ public function testEmptyInstanceofThrowsClearException() $loader = new YamlFileLoader($container, new FileLocator(self::$fixturesPath.'/yaml')); $loader->load('bad_empty_instanceof.yml'); } -} -interface FooInterface -{ -} + public function testBindings() + { + $container = new ContainerBuilder(); + $loader = new YamlFileLoader($container, new FileLocator(self::$fixturesPath.'/yaml')); + $loader->load('services_bindings.yml'); + $container->compile(); -class Foo implements FooInterface -{ + $definition = $container->getDefinition('bar'); + $this->assertEquals(array( + 'NonExistent' => null, + BarInterface::class => new Reference(Bar::class), + '$foo' => array(null), + '$quz' => 'quz', + '$factory' => 'factory', + ), array_map(function ($v) { return $v->getValues()[0]; }, $definition->getBindings())); + $this->assertEquals(array( + 'quz', + null, + new Reference(Bar::class), + array(null), + ), $definition->getArguments()); + + $definition = $container->getDefinition(Bar::class); + $this->assertEquals(array( + null, + 'factory', + ), $definition->getArguments()); + $this->assertEquals(array( + 'NonExistent' => null, + '$quz' => 'quz', + '$factory' => 'factory', + ), array_map(function ($v) { return $v->getValues()[0]; }, $definition->getBindings())); + } } diff --git a/src/Symfony/Component/HttpKernel/DependencyInjection/RegisterControllerArgumentLocatorsPass.php b/src/Symfony/Component/HttpKernel/DependencyInjection/RegisterControllerArgumentLocatorsPass.php index 222185f52766f..4a9b4a6812219 100644 --- a/src/Symfony/Component/HttpKernel/DependencyInjection/RegisterControllerArgumentLocatorsPass.php +++ b/src/Symfony/Component/HttpKernel/DependencyInjection/RegisterControllerArgumentLocatorsPass.php @@ -14,6 +14,7 @@ use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\DependencyInjection\ChildDefinition; use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; +use Symfony\Component\DependencyInjection\Compiler\ResolveBindingsPass; use Symfony\Component\DependencyInjection\Compiler\ServiceLocatorTagPass; use Symfony\Component\DependencyInjection\ContainerAwareInterface; use Symfony\Component\DependencyInjection\ContainerBuilder; @@ -109,6 +110,9 @@ public function process(ContainerBuilder $container) } } + // not validated, they are later in ResolveBindingsPass + $bindings = $def->getBindings(); + foreach ($methods as list($r, $parameters)) { /** @var \ReflectionMethod $r */ @@ -128,6 +132,14 @@ public function process(ContainerBuilder $container) } elseif ($p->allowsNull() && !$p->isOptional()) { $invalidBehavior = ContainerInterface::NULL_ON_INVALID_REFERENCE; } + } elseif (isset($bindings[$bindingName = '$'.$p->name]) || isset($bindings[$bindingName = $type])) { + $binding = $bindings[$bindingName]; + + list($bindingValue, $bindingId) = $binding->getValues(); + $binding->setValues(array($bindingValue, $bindingId, true)); + $args[$p->name] = $bindingValue; + + continue; } elseif (!$type || !$autowire) { continue; } diff --git a/src/Symfony/Component/HttpKernel/Tests/DependencyInjection/RegisterControllerArgumentLocatorsPassTest.php b/src/Symfony/Component/HttpKernel/Tests/DependencyInjection/RegisterControllerArgumentLocatorsPassTest.php index 0542698d694ef..c098f8e87b88e 100644 --- a/src/Symfony/Component/HttpKernel/Tests/DependencyInjection/RegisterControllerArgumentLocatorsPassTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/DependencyInjection/RegisterControllerArgumentLocatorsPassTest.php @@ -19,6 +19,7 @@ use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\DependencyInjection\ServiceLocator; use Symfony\Component\DependencyInjection\TypedReference; +use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\HttpKernel\DependencyInjection\RegisterControllerArgumentLocatorsPass; class RegisterControllerArgumentLocatorsPassTest extends TestCase @@ -266,6 +267,34 @@ public function testArgumentWithNoTypeHintIsOk() $locator = $container->getDefinition((string) $resolver->getArgument(0))->getArgument(0); $this->assertEmpty(array_keys($locator)); } + + /** + * @dataProvider provideBindings + */ + public function testBindings($bindingName) + { + $container = new ContainerBuilder(); + $resolver = $container->register('argument_resolver.service')->addArgument(array()); + + $container->register('foo', RegisterTestController::class) + ->setBindings(array($bindingName => new Reference('foo'))) + ->addTag('controller.service_arguments'); + + $pass = new RegisterControllerArgumentLocatorsPass(); + $pass->process($container); + + $locator = $container->getDefinition((string) $resolver->getArgument(0))->getArgument(0); + + $locator = $container->getDefinition((string) $locator['foo:fooAction']->getValues()[0]); + + $expected = array('bar' => new ServiceClosureArgument(new Reference('foo'))); + $this->assertEquals($expected, $locator->getArgument(0)); + } + + public function provideBindings() + { + return array(array(ControllerDummy::class), array('$bar')); + } } class RegisterTestController diff --git a/src/Symfony/Component/HttpKernel/composer.json b/src/Symfony/Component/HttpKernel/composer.json index 976d34da15a54..18653653e5488 100644 --- a/src/Symfony/Component/HttpKernel/composer.json +++ b/src/Symfony/Component/HttpKernel/composer.json @@ -28,7 +28,7 @@ "symfony/config": "~2.8|~3.0|~4.0", "symfony/console": "~2.8|~3.0|~4.0", "symfony/css-selector": "~2.8|~3.0|~4.0", - "symfony/dependency-injection": "~3.3|~4.0", + "symfony/dependency-injection": "~3.4|~4.0", "symfony/dom-crawler": "~2.8|~3.0|~4.0", "symfony/expression-language": "~2.8|~3.0|~4.0", "symfony/finder": "~2.8|~3.0|~4.0", @@ -42,7 +42,7 @@ }, "conflict": { "symfony/config": "<2.8", - "symfony/dependency-injection": "<3.3", + "symfony/dependency-injection": "<3.4", "symfony/var-dumper": "<3.3", "twig/twig": "<1.34|<2.4,>=2" }, From 6727d41fd3c84da572a00f2e162556d93348bfaa Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Wed, 9 Aug 2017 12:12:24 +0200 Subject: [PATCH 0600/1099] updated CHANGELOG --- src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md b/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md index a06afaae0a726..08a93bdd33b49 100644 --- a/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md +++ b/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md @@ -4,6 +4,7 @@ CHANGELOG 3.4.0 ----- + * Added support for `EventSubscriberInterface` on `MicroKernelTrait` * Removed `doctrine/cache` from the list of required dependencies in `composer.json` * Deprecated `validator.mapping.cache.doctrine.apc` service * The `symfony/stopwatch` dependency has been removed, require it via `composer From f876fd925374ad84c6284e9066f72b5544c33df7 Mon Sep 17 00:00:00 2001 From: Maxime Steinhausser Date: Wed, 9 Aug 2017 12:24:19 +0200 Subject: [PATCH 0601/1099] [DebugBundle] Reword an outdated comment about var dumper wiring --- src/Symfony/Bundle/DebugBundle/DebugBundle.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Bundle/DebugBundle/DebugBundle.php b/src/Symfony/Bundle/DebugBundle/DebugBundle.php index 335ec5abd2541..b00c06af78289 100644 --- a/src/Symfony/Bundle/DebugBundle/DebugBundle.php +++ b/src/Symfony/Bundle/DebugBundle/DebugBundle.php @@ -27,8 +27,10 @@ public function boot() $container = $this->container; // This code is here to lazy load the dump stack. This default - // configuration for CLI mode is overridden in HTTP mode on - // 'kernel.request' event + // configuration is overridden in CLI mode on 'console.command' event. + // The dump data collector is used by default, so dump output is sent to + // the WDT. In a CLI context, if dump is used too soon, the data collector + // will buffer it, and release it at the end of the script. VarDumper::setHandler(function ($var) use ($container) { $dumper = $container->get('data_collector.dump'); $cloner = $container->get('var_dumper.cloner'); From b622d26978a31d7c3ba08a315e3ffd1210967a1f Mon Sep 17 00:00:00 2001 From: Maxime Steinhausser Date: Wed, 9 Aug 2017 15:44:44 +0200 Subject: [PATCH 0602/1099] [Profiler] Make the validator toolbar item consistent with the form one --- .../Resources/views/Collector/validator.html.twig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/validator.html.twig b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/validator.html.twig index 6b8ba44dac940..6153637026261 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/validator.html.twig +++ b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/validator.html.twig @@ -6,7 +6,7 @@ {% set icon %} {{ include('@WebProfiler/Icon/validator.svg') }} - {{ collector.violationsCount }} + {{ collector.violationsCount ?: collector.calls|length }} {% endset %} From 16eeabfdef79bcdf6c1ab0b137c794a146352588 Mon Sep 17 00:00:00 2001 From: Guilhem Niot Date: Mon, 7 Aug 2017 14:16:05 +0200 Subject: [PATCH 0603/1099] [Debug] Detect internal and deprecated methods --- .../Component/Debug/DebugClassLoader.php | 161 +++++++++++------- .../Debug/Tests/DebugClassLoaderTest.php | 31 +++- .../Debug/Tests/Fixtures/AnnotatedClass.php | 13 ++ .../Debug/Tests/Fixtures/InternalClass.php | 4 + .../Debug/Tests/Fixtures/InternalTrait2.php | 13 ++ 5 files changed, 155 insertions(+), 67 deletions(-) create mode 100644 src/Symfony/Component/Debug/Tests/Fixtures/AnnotatedClass.php diff --git a/src/Symfony/Component/Debug/DebugClassLoader.php b/src/Symfony/Component/Debug/DebugClassLoader.php index 43ab3a78bf551..3605868c50000 100644 --- a/src/Symfony/Component/Debug/DebugClassLoader.php +++ b/src/Symfony/Component/Debug/DebugClassLoader.php @@ -27,10 +27,12 @@ class DebugClassLoader private $classLoader; private $isFinder; private static $caseCheck; - private static $internal = array(); private static $final = array(); private static $finalMethods = array(); private static $deprecated = array(); + private static $deprecatedMethods = array(); + private static $internal = array(); + private static $internalMethods = array(); private static $php7Reserved = array('int', 'float', 'bool', 'string', 'true', 'false', 'null'); private static $darwinCache = array('/' => array('/', array())); @@ -166,53 +168,6 @@ public function loadClass($class) throw new \RuntimeException(sprintf('Case mismatch between loaded and declared class names: "%s" vs "%s".', $class, $name)); } - $parent = get_parent_class($class); - $doc = $refl->getDocComment(); - if (preg_match('#\n \* @internal(?:( .+?)\.?)?\r?\n \*(?: @|/$)#s', $doc, $notice)) { - self::$internal[$name] = isset($notice[1]) ? preg_replace('#\s*\r?\n \* +#', ' ', $notice[1]) : ''; - } - - // Not an interface nor a trait - if (class_exists($name, false)) { - if (preg_match('#\n \* @final(?:( .+?)\.?)?\r?\n \*(?: @|/$)#s', $doc, $notice)) { - self::$final[$name] = isset($notice[1]) ? preg_replace('#\s*\r?\n \* +#', ' ', $notice[1]) : ''; - } - - if ($parent && isset(self::$final[$parent])) { - @trigger_error(sprintf('The "%s" class is considered final%s. It may change without further notice as of its next major version. You should not extend it from "%s".', $parent, self::$final[$parent], $name), E_USER_DEPRECATED); - } - - // Inherit @final annotations - self::$finalMethods[$name] = $parent && isset(self::$finalMethods[$parent]) ? self::$finalMethods[$parent] : array(); - - foreach ($refl->getMethods(\ReflectionMethod::IS_PUBLIC | \ReflectionMethod::IS_PROTECTED) as $method) { - if ($method->class !== $name) { - continue; - } - - if ($parent && isset(self::$finalMethods[$parent][$method->name])) { - @trigger_error(sprintf('%s It may change without further notice as of its next major version. You should not extend it from "%s".', self::$finalMethods[$parent][$method->name], $name), E_USER_DEPRECATED); - } - - $doc = $method->getDocComment(); - if (false === $doc || false === strpos($doc, '@final')) { - continue; - } - - if (preg_match('#\n\s+\* @final(?:( .+?)\.?)?\r?\n\s+\*(?: @|/$)#s', $doc, $notice)) { - $message = isset($notice[1]) ? preg_replace('#\s*\r?\n \* +#', ' ', $notice[1]) : ''; - self::$finalMethods[$name][$method->name] = sprintf('The "%s::%s()" method is considered final%s.', $name, $method->name, $message); - } - } - } - - if (in_array(strtolower($refl->getShortName()), self::$php7Reserved)) { - @trigger_error(sprintf('The "%s" class uses the reserved name "%s", it will break on PHP 7 and higher', $name, $refl->getShortName()), E_USER_DEPRECATED); - } - if (preg_match('#\n \* @deprecated (.*?)\r?\n \*(?: @|/$)#s', $refl->getDocComment(), $notice)) { - self::$deprecated[$name] = preg_replace('#\s*\r?\n \* +#', ' ', $notice[1]); - } - // Don't trigger deprecations for classes in the same vendor if (2 > $len = 1 + (strpos($name, '\\', 1 + strpos($name, '\\')) ?: strpos($name, '_'))) { $len = 0; @@ -228,40 +183,87 @@ public function loadClass($class) } } - foreach (array_merge(array($parent), class_implements($name, false), class_uses($name, false)) as $use) { + // Detect annotations on the class + if (false !== $doc = $refl->getDocComment()) { + foreach (array('final', 'deprecated', 'internal') as $annotation) { + if (false !== strpos($doc, '@'.$annotation) && preg_match('#\n \* @'.$annotation.'(?:( .+?)\.?)?\r?\n \*(?: @|/$)#s', $doc, $notice)) { + self::${$annotation}[$name] = isset($notice[1]) ? preg_replace('#\s*\r?\n \* +#', ' ', $notice[1]) : ''; + } + } + } + + $parentAndTraits = class_uses($name, false); + if ($parent = get_parent_class($class)) { + $parentAndTraits[] = $parent; + + if (isset(self::$final[$parent])) { + @trigger_error(sprintf('The "%s" class is considered final%s. It may change without further notice as of its next major version. You should not extend it from "%s".', $parent, self::$final[$parent], $name), E_USER_DEPRECATED); + } + } + + // Detect if the parent is annotated + foreach ($parentAndTraits + $this->getOwnInterfaces($name, $parent) as $use) { + if (isset(self::$deprecated[$use]) && strncmp($ns, $use, $len)) { + $type = class_exists($name, false) ? 'class' : (interface_exists($name, false) ? 'interface' : 'trait'); + $verb = class_exists($use, false) || interface_exists($name, false) ? 'extends' : (interface_exists($use, false) ? 'implements' : 'uses'); + + @trigger_error(sprintf('The "%s" %s %s "%s" that is deprecated%s.', $name, $type, $verb, $use, self::$deprecated[$use]), E_USER_DEPRECATED); + } if (isset(self::$internal[$use]) && strncmp($ns, $use, $len)) { @trigger_error(sprintf('The "%s" %s is considered internal%s. It may change without further notice. You should not use it from "%s".', $use, class_exists($use, false) ? 'class' : (interface_exists($use, false) ? 'interface' : 'trait'), self::$internal[$use], $name), E_USER_DEPRECATED); } } - if (!$parent || strncmp($ns, $parent, $len)) { - if ($parent && isset(self::$deprecated[$parent]) && strncmp($ns, $parent, $len)) { - @trigger_error(sprintf('The "%s" class extends "%s" that is deprecated %s', $name, $parent, self::$deprecated[$parent]), E_USER_DEPRECATED); + // Inherit @final and @deprecated annotations for methods + self::$finalMethods[$name] = array(); + self::$deprecatedMethods[$name] = array(); + self::$internalMethods[$name] = array(); + foreach ($parentAndTraits as $use) { + foreach (array('finalMethods', 'deprecatedMethods', 'internalMethods') as $property) { + if (isset(self::${$property}[$use])) { + self::${$property}[$name] = array_merge(self::${$property}[$name], self::${$property}[$use]); + } } + } - $parentInterfaces = array(); - $deprecatedInterfaces = array(); - if ($parent) { - foreach (class_implements($parent) as $interface) { - $parentInterfaces[$interface] = 1; - } + $isClass = class_exists($name, false); + foreach ($refl->getMethods(\ReflectionMethod::IS_PUBLIC | \ReflectionMethod::IS_PROTECTED) as $method) { + if ($method->class !== $name) { + continue; } - foreach ($refl->getInterfaceNames() as $interface) { - if (isset(self::$deprecated[$interface]) && strncmp($ns, $interface, $len)) { - $deprecatedInterfaces[] = $interface; + if ($isClass && $parent && isset(self::$finalMethods[$parent][$method->name])) { + list($methodShortName, $message) = self::$finalMethods[$parent][$method->name]; + @trigger_error(sprintf('The "%s" method is considered final%s. It may change without further notice as of its next major version. You should not extend it from "%s".', $methodShortName, $message, $name), E_USER_DEPRECATED); + } + + foreach ($parentAndTraits as $use) { + if (isset(self::$deprecatedMethods[$use][$method->name]) && strncmp($ns, $use, $len)) { + list($methodShortName, $message) = self::$deprecatedMethods[$use][$method->name]; + @trigger_error(sprintf('The "%s" method is deprecated%s. You should not extend it from "%s".', $methodShortName, $message, $name), E_USER_DEPRECATED); } - foreach (class_implements($interface) as $interface) { - $parentInterfaces[$interface] = 1; + if (isset(self::$internalMethods[$use][$method->name]) && strncmp($ns, $use, $len)) { + list($methodShortName, $message) = self::$internalMethods[$use][$method->name]; + @trigger_error(sprintf('The "%s" method is considered internal%s. It may change without further notice. You should not use it from "%s".', $methodShortName, $message, $name), E_USER_DEPRECATED); } } - foreach ($deprecatedInterfaces as $interface) { - if (!isset($parentInterfaces[$interface])) { - @trigger_error(sprintf('The "%s" %s "%s" that is deprecated %s', $name, $refl->isInterface() ? 'interface extends' : 'class implements', $interface, self::$deprecated[$interface]), E_USER_DEPRECATED); + // Detect method annotations + if (false === $doc = $method->getDocComment()) { + continue; + } + + foreach (array('final', 'deprecated', 'internal') as $annotation) { + if (false !== strpos($doc, '@'.$annotation) && preg_match('#\n\s+\* @'.$annotation.'(?:( .+?)\.?)?\r?\n\s+\*(?: @|/$)#s', $doc, $notice)) { + $message = isset($notice[1]) ? preg_replace('#\s*\r?\n \* +#', ' ', $notice[1]) : ''; + self::${$annotation.'Methods'}[$name][$method->name] = array(sprintf('%s::%s()', $name, $method->name), $message); } } } + + if (in_array(strtolower($refl->getShortName()), self::$php7Reserved)) { + @trigger_error(sprintf('The "%s" class uses the reserved name "%s", it will break on PHP 7 and higher', $name, $refl->getShortName()), E_USER_DEPRECATED); + } } if ($file) { @@ -361,4 +363,31 @@ public function loadClass($class) return true; } } + + /** + * `class_implements` includes interfaces from the parents so we have to manually exclude them. + * + * @param string $class + * @param string|false $parent + * + * @return string[] + */ + private function getOwnInterfaces($class, $parent) + { + $ownInterfaces = class_implements($class, false); + + if ($parent) { + foreach (class_implements($parent, false) as $interface) { + unset($ownInterfaces[$interface]); + } + } + + foreach ($ownInterfaces as $interface) { + foreach (class_implements($interface) as $interface) { + unset($ownInterfaces[$interface]); + } + } + + return $ownInterfaces; + } } diff --git a/src/Symfony/Component/Debug/Tests/DebugClassLoaderTest.php b/src/Symfony/Component/Debug/Tests/DebugClassLoaderTest.php index a53c17b0e4983..ba83d4502db7e 100644 --- a/src/Symfony/Component/Debug/Tests/DebugClassLoaderTest.php +++ b/src/Symfony/Component/Debug/Tests/DebugClassLoaderTest.php @@ -313,6 +313,28 @@ class_exists(__NAMESPACE__.'\\Fixtures\\ExtendedFinalMethod', true); $this->assertSame($xError, $lastError); } + public function testExtendedDeprecatedMethod() + { + set_error_handler(function () { return false; }); + $e = error_reporting(0); + trigger_error('', E_USER_NOTICE); + + class_exists('Test\\'.__NAMESPACE__.'\\ExtendsAnnotatedClass', true); + + error_reporting($e); + restore_error_handler(); + + $lastError = error_get_last(); + unset($lastError['file'], $lastError['line']); + + $xError = array( + 'type' => E_USER_DEPRECATED, + 'message' => 'The "Symfony\Component\Debug\Tests\Fixtures\AnnotatedClass::deprecatedMethod()" method is deprecated since version 3.4. You should not extend it from "Test\Symfony\Component\Debug\Tests\ExtendsAnnotatedClass".', + ); + + $this->assertSame($xError, $lastError); + } + public function testInternalsUse() { $deprecations = array(); @@ -325,9 +347,10 @@ class_exists('Test\\'.__NAMESPACE__.'\\ExtendsInternals', true); restore_error_handler(); $this->assertSame($deprecations, array( + 'The "Symfony\Component\Debug\Tests\Fixtures\InternalTrait" trait is considered internal. It may change without further notice. You should not use it from "Test\Symfony\Component\Debug\Tests\ExtendsInternals".', 'The "Symfony\Component\Debug\Tests\Fixtures\InternalClass" class is considered internal since version 3.4. It may change without further notice. You should not use it from "Test\Symfony\Component\Debug\Tests\ExtendsInternals".', 'The "Symfony\Component\Debug\Tests\Fixtures\InternalInterface" interface is considered internal. It may change without further notice. You should not use it from "Test\Symfony\Component\Debug\Tests\ExtendsInternals".', - 'The "Symfony\Component\Debug\Tests\Fixtures\InternalTrait" trait is considered internal. It may change without further notice. You should not use it from "Test\Symfony\Component\Debug\Tests\ExtendsInternals".', + 'The "Symfony\Component\Debug\Tests\Fixtures\InternalClass::internalMethod()" method is considered internal since version 3.4. It may change without further notice. You should not use it from "Test\Symfony\Component\Debug\Tests\ExtendsInternals".', )); } } @@ -371,9 +394,15 @@ public function findFile($class) eval('namespace Test\\'.__NAMESPACE__.'; class Float {}'); } elseif ('Test\\'.__NAMESPACE__.'\ExtendsFinalClass' === $class) { eval('namespace Test\\'.__NAMESPACE__.'; class ExtendsFinalClass extends \\'.__NAMESPACE__.'\Fixtures\FinalClass {}'); + } elseif ('Test\\'.__NAMESPACE__.'\ExtendsAnnotatedClass' === $class) { + eval('namespace Test\\'.__NAMESPACE__.'; class ExtendsAnnotatedClass extends \\'.__NAMESPACE__.'\Fixtures\AnnotatedClass { + public function deprecatedMethod() { } + }'); } elseif ('Test\\'.__NAMESPACE__.'\ExtendsInternals' === $class) { eval('namespace Test\\'.__NAMESPACE__.'; class ExtendsInternals extends \\'.__NAMESPACE__.'\Fixtures\InternalClass implements \\'.__NAMESPACE__.'\Fixtures\InternalInterface { use \\'.__NAMESPACE__.'\Fixtures\InternalTrait; + + public function internalMethod() { } }'); } } diff --git a/src/Symfony/Component/Debug/Tests/Fixtures/AnnotatedClass.php b/src/Symfony/Component/Debug/Tests/Fixtures/AnnotatedClass.php new file mode 100644 index 0000000000000..dff9517d0a046 --- /dev/null +++ b/src/Symfony/Component/Debug/Tests/Fixtures/AnnotatedClass.php @@ -0,0 +1,13 @@ + Date: Wed, 9 Aug 2017 18:38:20 +0200 Subject: [PATCH 0604/1099] [FrameworkBundle] Catch Fatal errors in commands registration --- .../FrameworkBundle/Console/Application.php | 51 ++++++++++++++++++- .../Tests/Console/ApplicationTest.php | 43 ++++++++++++++++ src/Symfony/Component/Console/Application.php | 15 ++++-- 3 files changed, 102 insertions(+), 7 deletions(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/Console/Application.php b/src/Symfony/Bundle/FrameworkBundle/Console/Application.php index b1c893ad0503d..09c61933ee207 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Console/Application.php +++ b/src/Symfony/Bundle/FrameworkBundle/Console/Application.php @@ -11,6 +11,9 @@ namespace Symfony\Bundle\FrameworkBundle\Console; +use Symfony\Component\Console\Output\ConsoleOutputInterface; +use Symfony\Component\Console\Style\SymfonyStyle; +use Symfony\Component\Debug\Exception\FatalThrowableError; use Symfony\Component\DependencyInjection\ContainerAwareInterface; use Symfony\Component\Console\Application as BaseApplication; use Symfony\Component\Console\Command\Command; @@ -30,6 +33,7 @@ class Application extends BaseApplication { private $kernel; private $commandsRegistered = false; + private $registrationErrors = array(); /** * Constructor. @@ -70,9 +74,25 @@ public function doRun(InputInterface $input, OutputInterface $output) $this->setDispatcher($this->kernel->getContainer()->get('event_dispatcher')); + if ($this->registrationErrors) { + $this->renderRegistrationErrors($input, $output); + } + return parent::doRun($input, $output); } + /** + * {@inheritdoc} + */ + protected function doRunCommand(Command $command, InputInterface $input, OutputInterface $output) + { + if ($this->registrationErrors) { + $this->renderRegistrationErrors($input, $output); + } + + return parent::doRunCommand($command, $input, $output); + } + /** * {@inheritdoc} */ @@ -138,7 +158,13 @@ protected function registerCommands() foreach ($this->kernel->getBundles() as $bundle) { if ($bundle instanceof Bundle) { - $bundle->registerCommands($this); + try { + $bundle->registerCommands($this); + } catch (\Exception $e) { + $this->registrationErrors[] = $e; + } catch (\Throwable $e) { + $this->registrationErrors[] = new FatalThrowableError($e); + } } } @@ -149,9 +175,30 @@ protected function registerCommands() if ($container->hasParameter('console.command.ids')) { foreach ($container->getParameter('console.command.ids') as $id) { if (false !== $id) { - $this->add($container->get($id)); + try { + $this->add($container->get($id)); + } catch (\Exception $e) { + $this->registrationErrors[] = $e; + } catch (\Throwable $e) { + $this->registrationErrors[] = new FatalThrowableError($e); + } } } } } + + private function renderRegistrationErrors(InputInterface $input, OutputInterface $output) + { + if ($output instanceof ConsoleOutputInterface) { + $output = $output->getErrorOutput(); + } + + (new SymfonyStyle($input, $output))->warning('Some commands could not be registered.'); + + foreach ($this->registrationErrors as $error) { + $this->doRenderException($error, $output); + } + + $this->registrationErrors = array(); + } } diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Console/ApplicationTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Console/ApplicationTest.php index 25511142c9b54..ce7ebad1f158e 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Console/ApplicationTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Console/ApplicationTest.php @@ -15,8 +15,13 @@ use Symfony\Bundle\FrameworkBundle\Tests\TestCase; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Input\ArrayInput; +use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\NullOutput; +use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Tester\ApplicationTester; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\EventDispatcher\EventDispatcher; +use Symfony\Component\HttpKernel\KernelInterface; class ApplicationTest extends TestCase { @@ -130,6 +135,36 @@ public function testBundleCommandCanOverriddeAPreExistingCommandWithTheSameName( $this->assertSame($newCommand, $application->get('example')); } + public function testRunOnlyWarnsOnUnregistrableCommand() + { + $container = new ContainerBuilder(); + $container->register('event_dispatcher', EventDispatcher::class); + $container->register(ThrowingCommand::class, ThrowingCommand::class); + $container->setParameter('console.command.ids', array(ThrowingCommand::class => ThrowingCommand::class)); + + $kernel = $this->getMockBuilder(KernelInterface::class)->getMock(); + $kernel + ->method('getBundles') + ->willReturn(array($this->createBundleMock( + array((new Command('fine'))->setCode(function (InputInterface $input, OutputInterface $output) { $output->write('fine'); })) + ))); + $kernel + ->method('getContainer') + ->willReturn($container); + + $application = new Application($kernel); + $application->setAutoExit(false); + + $tester = new ApplicationTester($application); + $tester->run(array('command' => 'fine')); + $output = $tester->getDisplay(); + + $this->assertSame(0, $tester->getStatusCode()); + $this->assertContains('Some commands could not be registered.', $output); + $this->assertContains('throwing', $output); + $this->assertContains('fine', $output); + } + private function getKernel(array $bundles, $useDispatcher = false) { $container = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerInterface')->getMock(); @@ -189,3 +224,11 @@ private function createBundleMock(array $commands) return $bundle; } } + +class ThrowingCommand extends Command +{ + public function __construct() + { + throw new \Exception('throwing'); + } +} diff --git a/src/Symfony/Component/Console/Application.php b/src/Symfony/Component/Console/Application.php index 627a2b1db232f..b9669789eae8a 100644 --- a/src/Symfony/Component/Console/Application.php +++ b/src/Symfony/Component/Console/Application.php @@ -706,6 +706,16 @@ public function renderException(\Exception $e, OutputInterface $output) { $output->writeln('', OutputInterface::VERBOSITY_QUIET); + $this->doRenderException($e, $output); + + if (null !== $this->runningCommand) { + $output->writeln(sprintf('%s', sprintf($this->runningCommand->getSynopsis(), $this->getName())), OutputInterface::VERBOSITY_QUIET); + $output->writeln('', OutputInterface::VERBOSITY_QUIET); + } + } + + protected function doRenderException(\Exception $e, OutputInterface $output) + { do { $title = sprintf( ' [%s%s] ', @@ -767,11 +777,6 @@ public function renderException(\Exception $e, OutputInterface $output) $output->writeln('', OutputInterface::VERBOSITY_QUIET); } } while ($e = $e->getPrevious()); - - if (null !== $this->runningCommand) { - $output->writeln(sprintf('%s', sprintf($this->runningCommand->getSynopsis(), $this->getName())), OutputInterface::VERBOSITY_QUIET); - $output->writeln('', OutputInterface::VERBOSITY_QUIET); - } } /** From 9fdb5d4eae26850367944947a098c9fe3f584389 Mon Sep 17 00:00:00 2001 From: Dany Maillard Date: Wed, 9 Aug 2017 11:52:10 +0200 Subject: [PATCH 0605/1099] Fix minors in date caster --- .../Component/VarDumper/Caster/DateCaster.php | 2 +- .../VarDumper/Tests/Caster/DateCasterTest.php | 64 ++++++++++--------- 2 files changed, 35 insertions(+), 31 deletions(-) diff --git a/src/Symfony/Component/VarDumper/Caster/DateCaster.php b/src/Symfony/Component/VarDumper/Caster/DateCaster.php index 17e7f4f929068..904bf6caf6748 100644 --- a/src/Symfony/Component/VarDumper/Caster/DateCaster.php +++ b/src/Symfony/Component/VarDumper/Caster/DateCaster.php @@ -27,7 +27,7 @@ public static function castDateTime(\DateTimeInterface $d, array $a, Stub $stub, $fromNow = (new \DateTime())->diff($d); $title = $d->format('l, F j, Y') - ."\n".$fromNow->format('%R').self::formatInterval($fromNow).' from now' + ."\n".self::formatInterval($fromNow).' from now' .($location ? ($d->format('I') ? "\nDST On" : "\nDST Off") : '') ; diff --git a/src/Symfony/Component/VarDumper/Tests/Caster/DateCasterTest.php b/src/Symfony/Component/VarDumper/Tests/Caster/DateCasterTest.php index f1207e30d16fc..d8e36da3428f1 100644 --- a/src/Symfony/Component/VarDumper/Tests/Caster/DateCasterTest.php +++ b/src/Symfony/Component/VarDumper/Tests/Caster/DateCasterTest.php @@ -27,7 +27,7 @@ class DateCasterTest extends TestCase /** * @dataProvider provideDateTimes */ - public function testDumpDateTime($time, $timezone, $expected) + public function testDumpDateTime($time, $timezone, $xDate, $xTimestamp) { if ((defined('HHVM_VERSION_ID') || PHP_VERSION_ID <= 50509) && preg_match('/[-+]\d{2}:\d{2}/', $timezone)) { $this->markTestSkipped('DateTimeZone GMT offsets are supported since 5.5.10. See https://github.com/facebook/hhvm/issues/5875 for HHVM.'); @@ -36,37 +36,40 @@ public function testDumpDateTime($time, $timezone, $expected) $date = new \DateTime($time, new \DateTimeZone($timezone)); $xDump = <<assertDumpMatchesFormat($xDump, $date); + $this->assertDumpEquals($xDump, $date); } - public function testCastDateTime() + /** + * @dataProvider provideDateTimes + */ + public function testCastDateTime($time, $timezone, $xDate, $xTimestamp, $xInfos) { + if ((defined('HHVM_VERSION_ID') || PHP_VERSION_ID <= 50509) && preg_match('/[-+]\d{2}:\d{2}/', $timezone)) { + $this->markTestSkipped('DateTimeZone GMT offsets are supported since 5.5.10. See https://github.com/facebook/hhvm/issues/5875 for HHVM.'); + } + $stub = new Stub(); - $date = new \DateTime('2017-08-30 00:00:00.000000', new \DateTimeZone('Europe/Zurich')); + $date = new \DateTime($time, new \DateTimeZone($timezone)); $cast = DateCaster::castDateTime($date, array('foo' => 'bar'), $stub, false, 0); - $xDump = <<<'EODUMP' + $xDump = << 2017-08-30 00:00:00.0 Europe/Zurich (+02:00) + "\\x00~\\x00date" => $xDate ] EODUMP; - $this->assertDumpMatchesFormat($xDump, $cast); + $this->assertDumpEquals($xDump, $cast); - $xDump = <<<'EODUMP' + $xDump = <<assertDumpMatchesFormat($xDump, $interval, Caster::EXCLUDE_VERBOSE); + $this->assertDumpEquals($xDump, $interval, Caster::EXCLUDE_VERBOSE); } /** @@ -144,7 +148,7 @@ public function testCastInterval($intervalSpec, $invert, $xInterval, $xSeconds) ] EODUMP; - $this->assertDumpMatchesFormat($xDump, $cast); + $this->assertDumpEquals($xDump, $cast); if (null === $xSeconds) { return; @@ -163,7 +167,7 @@ public function testCastInterval($intervalSpec, $invert, $xInterval, $xSeconds) } EODUMP; - $this->assertDumpMatchesFormat($xDump, $cast["\0~\0interval"]); + $this->assertDumpEquals($xDump, $cast["\0~\0interval"]); } public function provideIntervals() @@ -229,7 +233,7 @@ public function testDumpTimeZoneExcludingVerbosity($timezone, $expected) } EODUMP; - $this->assertDumpMatchesFormat($xDump, $timezone, Caster::EXCLUDE_VERBOSE); + $this->assertDumpEquals($xDump, $timezone, Caster::EXCLUDE_VERBOSE); } /** @@ -252,7 +256,7 @@ public function testCastTimeZone($timezone, $xTimezone, $xRegion) ] EODUMP; - $this->assertDumpMatchesFormat($xDump, $cast); + $this->assertDumpEquals($xDump, $cast); $xDump = << Date: Sun, 6 Aug 2017 14:15:02 +0200 Subject: [PATCH 0606/1099] [HttpKernel] Deprecated commands auto-registration --- UPGRADE-3.4.md | 29 +++++++++++++++++++ UPGRADE-4.0.md | 26 +++++++++++++++++ .../Tests/Functional/app/Acl/doctrine.yml | 5 ++++ .../Tests/Functional/app/AppKernel.php | 6 ++++ .../Component/HttpKernel/Bundle/Bundle.php | 2 ++ src/Symfony/Component/HttpKernel/CHANGELOG.md | 1 + .../HttpKernel/Tests/Bundle/BundleTest.php | 4 +++ 7 files changed, 73 insertions(+) create mode 100644 src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/Acl/doctrine.yml diff --git a/UPGRADE-3.4.md b/UPGRADE-3.4.md index 1f15a45d18ea3..7164e789a808a 100644 --- a/UPGRADE-3.4.md +++ b/UPGRADE-3.4.md @@ -114,6 +114,35 @@ FrameworkBundle class has been deprecated and will be removed in 4.0. Use the `Symfony\Component\Translation\DependencyInjection\TranslatorPass` class instead. +HttpKernel +---------- + + * Relying on convention-based commands discovery has been deprecated and + won't be supported in 4.0. Use PSR-4 based service discovery instead. + + Before: + + ```yml + # app/config/services.yml + services: + # ... + + # implicit registration of all commands in the `Command` folder + ``` + + After: + + ```yml + # app/config/services.yml + services: + # ... + + # explicit commands registration + AppBundle\Command: + resource: '../../src/AppBundle/Command/*' + tags: ['console.command'] + ``` + Process ------- diff --git a/UPGRADE-4.0.md b/UPGRADE-4.0.md index e0fdf18eda5c9..dd18fa57dd454 100644 --- a/UPGRADE-4.0.md +++ b/UPGRADE-4.0.md @@ -452,6 +452,32 @@ HttpFoundation HttpKernel ---------- + * Relying on convention-based commands discovery is not supported anymore. + Use PSR-4 based service discovery instead. + + Before: + + ```yml + # app/config/services.yml + services: + # ... + + # implicit registration of all commands in the `Command` folder + ``` + + After: + + ```yml + # app/config/services.yml + services: + # ... + + # explicit commands registration + AppBundle\Command: + resource: '../../src/AppBundle/Command/*' + tags: ['console.command'] + ``` + * Removed the `kernel.root_dir` parameter. Use the `kernel.project_dir` parameter instead. diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/Acl/doctrine.yml b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/Acl/doctrine.yml new file mode 100644 index 0000000000000..7a12388398f76 --- /dev/null +++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/Acl/doctrine.yml @@ -0,0 +1,5 @@ +# to be removed once https://github.com/doctrine/DoctrineBundle/pull/684 is merged +services: + Doctrine\Bundle\DoctrineBundle\Command\: + resource: "@DoctrineBundle/Command/*" + tags: [console.command] diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/AppKernel.php b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/AppKernel.php index 1aab514f45450..82c8ad4aa6c60 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/AppKernel.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/AppKernel.php @@ -11,6 +11,7 @@ namespace Symfony\Bundle\SecurityBundle\Tests\Functional\app; +use Doctrine\ORM\Version; use Symfony\Component\Config\Loader\LoaderInterface; use Symfony\Component\Filesystem\Filesystem; use Symfony\Component\HttpKernel\Kernel; @@ -82,6 +83,11 @@ public function getLogDir() public function registerContainerConfiguration(LoaderInterface $loader) { $loader->load($this->rootConfig); + + // to be removed once https://github.com/doctrine/DoctrineBundle/pull/684 is merged + if ('Acl' === $this->testCase && class_exists(Version::class)) { + $loader->load(__DIR__.'/Acl/doctrine.yml'); + } } public function serialize() diff --git a/src/Symfony/Component/HttpKernel/Bundle/Bundle.php b/src/Symfony/Component/HttpKernel/Bundle/Bundle.php index 0b0ea088dcc37..d0ea99f5fa95e 100644 --- a/src/Symfony/Component/HttpKernel/Bundle/Bundle.php +++ b/src/Symfony/Component/HttpKernel/Bundle/Bundle.php @@ -191,6 +191,8 @@ public function registerCommands(Application $application) } $r = new \ReflectionClass($class); if ($r->isSubclassOf('Symfony\\Component\\Console\\Command\\Command') && !$r->isAbstract() && !$r->getConstructor()->getNumberOfRequiredParameters()) { + @trigger_error(sprintf('Auto-registration of the command "%s" is deprecated since Symfony 3.4 and won\'t be supported in 4.0. Use PSR-4 based service discovery instead.', $class), E_USER_DEPRECATED); + $application->add($r->newInstance()); } } diff --git a/src/Symfony/Component/HttpKernel/CHANGELOG.md b/src/Symfony/Component/HttpKernel/CHANGELOG.md index 6c21cb722aec3..ca26a6c5bdde6 100644 --- a/src/Symfony/Component/HttpKernel/CHANGELOG.md +++ b/src/Symfony/Component/HttpKernel/CHANGELOG.md @@ -4,6 +4,7 @@ CHANGELOG 3.4.0 ----- + * deprecated commands auto registration * added `AddCacheClearerPass` * added `AddCacheWarmerPass` diff --git a/src/Symfony/Component/HttpKernel/Tests/Bundle/BundleTest.php b/src/Symfony/Component/HttpKernel/Tests/Bundle/BundleTest.php index eeefccab81dd0..8e52b097d6946 100644 --- a/src/Symfony/Component/HttpKernel/Tests/Bundle/BundleTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/Bundle/BundleTest.php @@ -31,6 +31,10 @@ public function testGetContainerExtension() ); } + /** + * @group legacy + * @expectedDeprecation Auto-registration of the command "Symfony\Component\HttpKernel\Tests\Fixtures\ExtensionPresentBundle\Command\FooCommand" is deprecated since Symfony 3.4 and won't be supported in 4.0. Use PSR-4 based service discovery instead. + */ public function testRegisterCommands() { $cmd = new FooCommand(); From 08d352a302ef28b680051a39d51a58831764869e Mon Sep 17 00:00:00 2001 From: Guilhem Niot Date: Wed, 9 Aug 2017 18:49:26 +0200 Subject: [PATCH 0607/1099] [Debug] Correctly detect methods not from the same vendor --- .../Component/Debug/DebugClassLoader.php | 27 ++++++++++++------- .../Debug/Tests/DebugClassLoaderTest.php | 10 ++++--- 2 files changed, 24 insertions(+), 13 deletions(-) diff --git a/src/Symfony/Component/Debug/DebugClassLoader.php b/src/Symfony/Component/Debug/DebugClassLoader.php index 3605868c50000..39b03cf5775da 100644 --- a/src/Symfony/Component/Debug/DebugClassLoader.php +++ b/src/Symfony/Component/Debug/DebugClassLoader.php @@ -232,19 +232,28 @@ public function loadClass($class) continue; } + // Method from a trait + if ($method->getFilename() !== $refl->getFileName()) { + continue; + } + if ($isClass && $parent && isset(self::$finalMethods[$parent][$method->name])) { - list($methodShortName, $message) = self::$finalMethods[$parent][$method->name]; - @trigger_error(sprintf('The "%s" method is considered final%s. It may change without further notice as of its next major version. You should not extend it from "%s".', $methodShortName, $message, $name), E_USER_DEPRECATED); + list($declaringClass, $message) = self::$finalMethods[$parent][$method->name]; + @trigger_error(sprintf('The "%s::%s()" method is considered final%s. It may change without further notice as of its next major version. You should not extend it from "%s".', $declaringClass, $method->name, $message, $name), E_USER_DEPRECATED); } foreach ($parentAndTraits as $use) { - if (isset(self::$deprecatedMethods[$use][$method->name]) && strncmp($ns, $use, $len)) { - list($methodShortName, $message) = self::$deprecatedMethods[$use][$method->name]; - @trigger_error(sprintf('The "%s" method is deprecated%s. You should not extend it from "%s".', $methodShortName, $message, $name), E_USER_DEPRECATED); + if (isset(self::$deprecatedMethods[$use][$method->name])) { + list($declaringClass, $message) = self::$deprecatedMethods[$use][$method->name]; + if (strncmp($ns, $declaringClass, $len)) { + @trigger_error(sprintf('The "%s::%s()" method is deprecated%s. You should not extend it from "%s".', $declaringClass, $method->name, $message, $name), E_USER_DEPRECATED); + } } - if (isset(self::$internalMethods[$use][$method->name]) && strncmp($ns, $use, $len)) { - list($methodShortName, $message) = self::$internalMethods[$use][$method->name]; - @trigger_error(sprintf('The "%s" method is considered internal%s. It may change without further notice. You should not use it from "%s".', $methodShortName, $message, $name), E_USER_DEPRECATED); + if (isset(self::$internalMethods[$use][$method->name])) { + list($declaringClass, $message) = self::$internalMethods[$use][$method->name]; + if (strncmp($ns, $declaringClass, $len)) { + @trigger_error(sprintf('The "%s::%s()" method is considered internal%s. It may change without further notice. You should not extend it from "%s".', $declaringClass, $method->name, $message, $name), E_USER_DEPRECATED); + } } } @@ -256,7 +265,7 @@ public function loadClass($class) foreach (array('final', 'deprecated', 'internal') as $annotation) { if (false !== strpos($doc, '@'.$annotation) && preg_match('#\n\s+\* @'.$annotation.'(?:( .+?)\.?)?\r?\n\s+\*(?: @|/$)#s', $doc, $notice)) { $message = isset($notice[1]) ? preg_replace('#\s*\r?\n \* +#', ' ', $notice[1]) : ''; - self::${$annotation.'Methods'}[$name][$method->name] = array(sprintf('%s::%s()', $name, $method->name), $message); + self::${$annotation.'Methods'}[$name][$method->name] = array($name, $message); } } } diff --git a/src/Symfony/Component/Debug/Tests/DebugClassLoaderTest.php b/src/Symfony/Component/Debug/Tests/DebugClassLoaderTest.php index ba83d4502db7e..e83fcea770b39 100644 --- a/src/Symfony/Component/Debug/Tests/DebugClassLoaderTest.php +++ b/src/Symfony/Component/Debug/Tests/DebugClassLoaderTest.php @@ -347,10 +347,10 @@ class_exists('Test\\'.__NAMESPACE__.'\\ExtendsInternals', true); restore_error_handler(); $this->assertSame($deprecations, array( + 'The "Symfony\Component\Debug\Tests\Fixtures\InternalClass" class is considered internal since version 3.4. It may change without further notice. You should not use it from "Test\Symfony\Component\Debug\Tests\ExtendsInternalsParent".', + 'The "Symfony\Component\Debug\Tests\Fixtures\InternalInterface" interface is considered internal. It may change without further notice. You should not use it from "Test\Symfony\Component\Debug\Tests\ExtendsInternalsParent".', 'The "Symfony\Component\Debug\Tests\Fixtures\InternalTrait" trait is considered internal. It may change without further notice. You should not use it from "Test\Symfony\Component\Debug\Tests\ExtendsInternals".', - 'The "Symfony\Component\Debug\Tests\Fixtures\InternalClass" class is considered internal since version 3.4. It may change without further notice. You should not use it from "Test\Symfony\Component\Debug\Tests\ExtendsInternals".', - 'The "Symfony\Component\Debug\Tests\Fixtures\InternalInterface" interface is considered internal. It may change without further notice. You should not use it from "Test\Symfony\Component\Debug\Tests\ExtendsInternals".', - 'The "Symfony\Component\Debug\Tests\Fixtures\InternalClass::internalMethod()" method is considered internal since version 3.4. It may change without further notice. You should not use it from "Test\Symfony\Component\Debug\Tests\ExtendsInternals".', + 'The "Symfony\Component\Debug\Tests\Fixtures\InternalTrait2::internalMethod()" method is considered internal since version 3.4. It may change without further notice. You should not extend it from "Test\Symfony\Component\Debug\Tests\ExtendsInternals".', )); } } @@ -399,11 +399,13 @@ public function findFile($class) public function deprecatedMethod() { } }'); } elseif ('Test\\'.__NAMESPACE__.'\ExtendsInternals' === $class) { - eval('namespace Test\\'.__NAMESPACE__.'; class ExtendsInternals extends \\'.__NAMESPACE__.'\Fixtures\InternalClass implements \\'.__NAMESPACE__.'\Fixtures\InternalInterface { + eval('namespace Test\\'.__NAMESPACE__.'; class ExtendsInternals extends ExtendsInternalsParent { use \\'.__NAMESPACE__.'\Fixtures\InternalTrait; public function internalMethod() { } }'); + } elseif ('Test\\'.__NAMESPACE__.'\ExtendsInternalsParent' === $class) { + eval('namespace Test\\'.__NAMESPACE__.'; class ExtendsInternalsParent extends \\'.__NAMESPACE__.'\Fixtures\InternalClass implements \\'.__NAMESPACE__.'\Fixtures\InternalInterface { }'); } } } From ff951697b67f71092d6da4b4828cf0e6078306be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9my=20Deruss=C3=A9?= Date: Wed, 9 Aug 2017 22:57:38 +0200 Subject: [PATCH 0608/1099] Fix lock failling test --- .../Tests/Store/BlockingStoreTestTrait.php | 31 ++++++++++++++----- 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/src/Symfony/Component/Lock/Tests/Store/BlockingStoreTestTrait.php b/src/Symfony/Component/Lock/Tests/Store/BlockingStoreTestTrait.php index d95837ff7456d..5d7691fa8c7f2 100644 --- a/src/Symfony/Component/Lock/Tests/Store/BlockingStoreTestTrait.php +++ b/src/Symfony/Component/Lock/Tests/Store/BlockingStoreTestTrait.php @@ -35,7 +35,7 @@ abstract protected function getStore(); public function testBlockingLocks() { // Amount a microsecond used to order async actions - $clockDelay = 200000; + $clockDelay = 50000; if (\PHP_VERSION_ID < 50600 || defined('HHVM_VERSION_ID')) { $this->markTestSkipped('The PHP engine does not keep resource in child forks'); @@ -46,31 +46,46 @@ public function testBlockingLocks() /** @var StoreInterface $store */ $store = $this->getStore(); $key = new Key(uniqid(__METHOD__, true)); + $parentPID = posix_getpid(); - if ($childPID1 = pcntl_fork()) { - // give time to fork to start - usleep(1 * $clockDelay); + // Block SIGHUP signal + pcntl_sigprocmask(SIG_BLOCK, array(SIGHUP)); + + if ($childPID = pcntl_fork()) { + // Wait the start of the child + pcntl_sigwaitinfo(array(SIGHUP), $info); try { - // This call should failed given the lock should already by acquired by the child #1 + // This call should failed given the lock should already by acquired by the child $store->save($key); $this->fail('The store saves a locked key.'); } catch (LockConflictedException $e) { } + // send the ready signal to the child + posix_kill($childPID, SIGHUP); + // This call should be blocked by the child #1 $store->waitAndSave($key); $this->assertTrue($store->exists($key)); $store->delete($key); // Now, assert the child process worked well - pcntl_waitpid($childPID1, $status1); + pcntl_waitpid($childPID, $status1); $this->assertSame(0, pcntl_wexitstatus($status1), 'The child process couldn\'t lock the resource'); } else { + // Block SIGHUP signal + pcntl_sigprocmask(SIG_BLOCK, array(SIGHUP)); try { $store->save($key); - // Wait 2 ClockDelay to let parent process to finish - usleep(2 * $clockDelay); + // send the ready signal to the parent + posix_kill($parentPID, SIGHUP); + + // Wait for the parent to be ready + pcntl_sigwaitinfo(array(SIGHUP), $info); + + // Wait ClockDelay to let parent assert to finish + usleep($clockDelay); $store->delete($key); exit(0); } catch (\Exception $e) { From 2309fd91d882a2570e7caf4a4c5f6bbae898784a Mon Sep 17 00:00:00 2001 From: Sam Partington Date: Tue, 8 Aug 2017 11:23:31 +0100 Subject: [PATCH 0609/1099] [2.8] Modify 2.8 upgrade doc - key option is deprecated. --- UPGRADE-2.8.md | 89 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 89 insertions(+) diff --git a/UPGRADE-2.8.md b/UPGRADE-2.8.md index 1d299af3e63a4..cf3edac756cae 100644 --- a/UPGRADE-2.8.md +++ b/UPGRADE-2.8.md @@ -546,6 +546,95 @@ Security * The `VoterInterface::supportsClass` and `supportsAttribute` methods were deprecated and will be removed from the interface in 3.0. + + * The the `key` setting of `anonymous`, `remember_me` and `http_digest` + is deprecated, and will be removed in 3.0. Use `secret` instead. + + Before: + + ```yaml + security: + # ... + firewalls: + default: + # ... + anonymous: { key: "%secret%" } + remember_me: + key: "%secret%" + http_digest: + key: "%secret%" + ``` + + ```xml + + + + + + + + + + + + + ``` + + ```php + // ... + $container->loadFromExtension('security', array( + // ... + 'firewalls' => array( + // ... + 'anonymous' => array('key' => '%secret%'), + 'remember_me' => array('key' => '%secret%'), + 'http_digest' => array('key' => '%secret%'), + ), + )); + ``` + + After: + + ```yaml + security: + # ... + firewalls: + default: + # ... + anonymous: { secret: "%secret%" } + remember_me: + secret: "%secret%" + http_digest: + secret: "%secret%" + ``` + + ```xml + + + + + + + + + + + + + ``` + + ```php + // ... + $container->loadFromExtension('security', array( + // ... + 'firewalls' => array( + // ... + 'anonymous' => array('secret' => '%secret%'), + 'remember_me' => array('secret' => '%secret%'), + 'http_digest' => array('secret' => '%secret%'), + ), + )); + ``` * The `intention` option is deprecated for all the authentication listeners, and will be removed in 3.0. Use the `csrf_token_id` option instead. From 4879eb4f362fa077e237548dcc55db347a095820 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Thu, 10 Aug 2017 08:50:59 +0200 Subject: [PATCH 0610/1099] fixed CS --- UPGRADE-2.8.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/UPGRADE-2.8.md b/UPGRADE-2.8.md index cf3edac756cae..64a31dde75600 100644 --- a/UPGRADE-2.8.md +++ b/UPGRADE-2.8.md @@ -546,11 +546,11 @@ Security * The `VoterInterface::supportsClass` and `supportsAttribute` methods were deprecated and will be removed from the interface in 3.0. - - * The the `key` setting of `anonymous`, `remember_me` and `http_digest` - is deprecated, and will be removed in 3.0. Use `secret` instead. - - Before: + + * The `key` setting of `anonymous`, `remember_me` and `http_digest` is + deprecated, and will be removed in 3.0. Use `secret` instead. + + Before: ```yaml security: From 27e8cd289cc1f3511ccf77ae30b574ceb524aa51 Mon Sep 17 00:00:00 2001 From: mlazovla Date: Thu, 10 Aug 2017 12:58:49 +0200 Subject: [PATCH 0611/1099] Filtering empty uuids in ORMQueryBuilderLoader. --- .../Form/ChoiceList/ORMQueryBuilderLoader.php | 2 +- .../Doctrine/Tests/Fixtures/GuidIdEntity.php | 28 +++++++++++++ .../Doctrine/Tests/Fixtures/UuidIdEntity.php | 28 +++++++++++++ .../ChoiceList/ORMQueryBuilderLoaderTest.php | 40 +++++++++++++++++++ 4 files changed, 97 insertions(+), 1 deletion(-) create mode 100644 src/Symfony/Bridge/Doctrine/Tests/Fixtures/GuidIdEntity.php create mode 100644 src/Symfony/Bridge/Doctrine/Tests/Fixtures/UuidIdEntity.php diff --git a/src/Symfony/Bridge/Doctrine/Form/ChoiceList/ORMQueryBuilderLoader.php b/src/Symfony/Bridge/Doctrine/Form/ChoiceList/ORMQueryBuilderLoader.php index 8930dc9f27377..297e2ddfe7a43 100644 --- a/src/Symfony/Bridge/Doctrine/Form/ChoiceList/ORMQueryBuilderLoader.php +++ b/src/Symfony/Bridge/Doctrine/Form/ChoiceList/ORMQueryBuilderLoader.php @@ -106,7 +106,7 @@ public function getEntitiesByIds($identifier, array $values) $values = array_values(array_filter($values, function ($v) { return (string) $v === (string) (int) $v || ctype_digit($v); })); - } elseif ('guid' === $metadata->getTypeOfField($identifier)) { + } elseif (in_array($metadata->getTypeOfField($identifier), array('uuid', 'guid'))) { $parameterType = Connection::PARAM_STR_ARRAY; // Like above, but we just filter out empty strings. diff --git a/src/Symfony/Bridge/Doctrine/Tests/Fixtures/GuidIdEntity.php b/src/Symfony/Bridge/Doctrine/Tests/Fixtures/GuidIdEntity.php new file mode 100644 index 0000000000000..517f57495169a --- /dev/null +++ b/src/Symfony/Bridge/Doctrine/Tests/Fixtures/GuidIdEntity.php @@ -0,0 +1,28 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bridge\Doctrine\Tests\Fixtures; + +use Doctrine\ORM\Mapping\Id; +use Doctrine\ORM\Mapping\Column; +use Doctrine\ORM\Mapping\Entity; + +/** @Entity */ +class GuidIdEntity +{ + /** @Id @Column(type="guid") */ + protected $id; + + public function __construct($id) + { + $this->id = $id; + } +} diff --git a/src/Symfony/Bridge/Doctrine/Tests/Fixtures/UuidIdEntity.php b/src/Symfony/Bridge/Doctrine/Tests/Fixtures/UuidIdEntity.php new file mode 100644 index 0000000000000..4998f7d7c5454 --- /dev/null +++ b/src/Symfony/Bridge/Doctrine/Tests/Fixtures/UuidIdEntity.php @@ -0,0 +1,28 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bridge\Doctrine\Tests\Fixtures; + +use Doctrine\ORM\Mapping\Id; +use Doctrine\ORM\Mapping\Column; +use Doctrine\ORM\Mapping\Entity; + +/** @Entity */ +class UuidIdEntity +{ + /** @Id @Column(type="uuid") */ + protected $id; + + public function __construct($id) + { + $this->id = $id; + } +} diff --git a/src/Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/ORMQueryBuilderLoaderTest.php b/src/Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/ORMQueryBuilderLoaderTest.php index b14044fb24804..1db089d5975d3 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/ORMQueryBuilderLoaderTest.php +++ b/src/Symfony/Bridge/Doctrine/Tests/Form/ChoiceList/ORMQueryBuilderLoaderTest.php @@ -107,6 +107,38 @@ public function testFilterNonIntegerValues() $loader->getEntitiesByIds('id', array(1, '', 2, 3, 'foo', '9223372036854775808')); } + /** + * @dataProvider provideGuidEntityClasses + */ + public function testFilterEmptyUuids($entityClass) + { + $em = DoctrineTestHelper::createTestEntityManager(); + + $query = $this->getMockBuilder('QueryMock') + ->setMethods(array('setParameter', 'getResult', 'getSql', '_doExecute')) + ->getMock(); + + $query->expects($this->once()) + ->method('setParameter') + ->with('ORMQueryBuilderLoader_getEntitiesByIds_id', array('71c5fd46-3f16-4abb-bad7-90ac1e654a2d', 'b98e8e11-2897-44df-ad24-d2627eb7f499'), Connection::PARAM_STR_ARRAY) + ->willReturn($query); + + $qb = $this->getMockBuilder('Doctrine\ORM\QueryBuilder') + ->setConstructorArgs(array($em)) + ->setMethods(array('getQuery')) + ->getMock(); + + $qb->expects($this->once()) + ->method('getQuery') + ->willReturn($query); + + $qb->select('e') + ->from($entityClass, 'e'); + + $loader = new ORMQueryBuilderLoader($qb); + $loader->getEntitiesByIds('id', array('71c5fd46-3f16-4abb-bad7-90ac1e654a2d', '', 'b98e8e11-2897-44df-ad24-d2627eb7f499')); + } + public function testEmbeddedIdentifierName() { if (Version::compare('2.5.0') > 0) { @@ -140,4 +172,12 @@ public function testEmbeddedIdentifierName() $loader = new ORMQueryBuilderLoader($qb); $loader->getEntitiesByIds('id.value', array(1, '', 2, 3, 'foo')); } + + public function provideGuidEntityClasses() + { + return array( + array('Symfony\Bridge\Doctrine\Tests\Fixtures\GuidIdEntity'), + array('Symfony\Bridge\Doctrine\Tests\Fixtures\UuidIdEntity'), + ); + } } From 685ff0e2804a2e197ca7d62334f270088d30089d Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Thu, 10 Aug 2017 13:45:16 +0200 Subject: [PATCH 0612/1099] [DI] Fix YamlDumper not dumping abstract and autoconfigure --- .../DependencyInjection/Dumper/YamlDumper.php | 8 ++++++++ .../Tests/Dumper/YamlDumperTest.php | 12 ++++++++++++ .../Tests/Fixtures/yaml/services_dump_load.yml | 14 ++++++++++++++ 3 files changed, 34 insertions(+) create mode 100644 src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services_dump_load.yml diff --git a/src/Symfony/Component/DependencyInjection/Dumper/YamlDumper.php b/src/Symfony/Component/DependencyInjection/Dumper/YamlDumper.php index e71df2af24c14..9567fee56a583 100644 --- a/src/Symfony/Component/DependencyInjection/Dumper/YamlDumper.php +++ b/src/Symfony/Component/DependencyInjection/Dumper/YamlDumper.php @@ -116,6 +116,14 @@ private function addService($id, $definition) $code .= sprintf(" autowiring_types:\n%s", $autowiringTypesCode); } + if ($definition->isAutoconfigured()) { + $code .= " autoconfigure: true\n"; + } + + if ($definition->isAbstract()) { + $code .= " abstract: true\n"; + } + if ($definition->isLazy()) { $code .= " lazy: true\n"; } diff --git a/src/Symfony/Component/DependencyInjection/Tests/Dumper/YamlDumperTest.php b/src/Symfony/Component/DependencyInjection/Tests/Dumper/YamlDumperTest.php index 22277c7b7a85f..eaaad0c75ca58 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Dumper/YamlDumperTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Dumper/YamlDumperTest.php @@ -12,8 +12,10 @@ namespace Symfony\Component\DependencyInjection\Tests\Dumper; use PHPUnit\Framework\TestCase; +use Symfony\Component\Config\FileLocator; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Dumper\YamlDumper; +use Symfony\Component\DependencyInjection\Loader\YamlFileLoader; use Symfony\Component\Yaml\Yaml; use Symfony\Component\Yaml\Parser; @@ -64,6 +66,16 @@ public function testDumpAutowireData() $this->assertStringEqualsFile(self::$fixturesPath.'/yaml/services24.yml', $dumper->dump()); } + public function testDumpLoad() + { + $container = new ContainerBuilder(); + $loader = new YamlFileLoader($container, new FileLocator(self::$fixturesPath.'/yaml')); + $loader->load('services_dump_load.yml'); + + $dumper = new YamlDumper($container); + $this->assertStringEqualsFile(self::$fixturesPath.'/yaml/services_dump_load.yml', $dumper->dump()); + } + private function assertEqualYamlStructure($expected, $yaml, $message = '') { $parser = new Parser(); diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services_dump_load.yml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services_dump_load.yml new file mode 100644 index 0000000000000..43b0c7d58a00f --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services_dump_load.yml @@ -0,0 +1,14 @@ + +services: + service_container: + class: Symfony\Component\DependencyInjection\ContainerInterface + synthetic: true + foo: + autoconfigure: true + abstract: true + Psr\Container\ContainerInterface: + alias: service_container + public: false + Symfony\Component\DependencyInjection\ContainerInterface: + alias: service_container + public: false From e5bbf3f4f3427edc36dcf7df350a94b7e082b1c1 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Thu, 10 Aug 2017 13:54:24 +0200 Subject: [PATCH 0613/1099] [DI] Allow dumping inline services in Yaml --- .../DependencyInjection/Dumper/YamlDumper.php | 4 ++++ .../Tests/Dumper/YamlDumperTest.php | 14 ++++++++++++++ .../Tests/Fixtures/yaml/services_inline.yml | 14 ++++++++++++++ 3 files changed, 32 insertions(+) create mode 100644 src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services_inline.yml diff --git a/src/Symfony/Component/DependencyInjection/Dumper/YamlDumper.php b/src/Symfony/Component/DependencyInjection/Dumper/YamlDumper.php index e71df2af24c14..c03a4cd814b69 100644 --- a/src/Symfony/Component/DependencyInjection/Dumper/YamlDumper.php +++ b/src/Symfony/Component/DependencyInjection/Dumper/YamlDumper.php @@ -12,7 +12,9 @@ namespace Symfony\Component\DependencyInjection\Dumper; use Symfony\Component\Yaml\Dumper as YmlDumper; +use Symfony\Component\Yaml\Parser; use Symfony\Component\Yaml\Tag\TaggedValue; +use Symfony\Component\Yaml\Yaml; use Symfony\Component\DependencyInjection\Alias; use Symfony\Component\DependencyInjection\Argument\ArgumentInterface; use Symfony\Component\DependencyInjection\Argument\IteratorArgument; @@ -275,6 +277,8 @@ private function dumpValue($value) return $this->getParameterCall((string) $value); } elseif ($value instanceof Expression) { return $this->getExpressionCall((string) $value); + } elseif ($value instanceof Definition) { + return new TaggedValue('service', (new Parser())->parse("_:\n".$this->addService('_', $value), Yaml::PARSE_CUSTOM_TAGS)['_']['_']); } elseif (is_object($value) || is_resource($value)) { throw new RuntimeException('Unable to dump a service container if a parameter is an object or a resource.'); } diff --git a/src/Symfony/Component/DependencyInjection/Tests/Dumper/YamlDumperTest.php b/src/Symfony/Component/DependencyInjection/Tests/Dumper/YamlDumperTest.php index 22277c7b7a85f..bae948feee52f 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Dumper/YamlDumperTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Dumper/YamlDumperTest.php @@ -13,6 +13,7 @@ use PHPUnit\Framework\TestCase; use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\DependencyInjection\Dumper\YamlDumper; use Symfony\Component\Yaml\Yaml; use Symfony\Component\Yaml\Parser; @@ -64,6 +65,19 @@ public function testDumpAutowireData() $this->assertStringEqualsFile(self::$fixturesPath.'/yaml/services24.yml', $dumper->dump()); } + public function testInlineServices() + { + $container = new ContainerBuilder(); + $container->register('foo', 'Class1') + ->addArgument((new Definition('Class2')) + ->addArgument(new Definition('Class2')) + ) + ; + + $dumper = new YamlDumper($container); + $this->assertStringEqualsFile(self::$fixturesPath.'/yaml/services_inline.yml', $dumper->dump()); + } + private function assertEqualYamlStructure($expected, $yaml, $message = '') { $parser = new Parser(); diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services_inline.yml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services_inline.yml new file mode 100644 index 0000000000000..14adedf32dde0 --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services_inline.yml @@ -0,0 +1,14 @@ + +services: + service_container: + class: Symfony\Component\DependencyInjection\ContainerInterface + synthetic: true + foo: + class: Class1 + arguments: [!service { class: Class2, arguments: [!service { class: Class2 }] }] + Psr\Container\ContainerInterface: + alias: service_container + public: false + Symfony\Component\DependencyInjection\ContainerInterface: + alias: service_container + public: false From 676012748ab5be2f5a510ee9cfce0bfc03828a80 Mon Sep 17 00:00:00 2001 From: ElectricMaxxx Date: Thu, 10 Aug 2017 09:29:20 +0200 Subject: [PATCH 0614/1099] restrict reflection doc block The version 3.2.0 and 3.2.1 of reflection-docblock is broken and lower version as 3.1 miss some tags --- composer.json | 2 +- .../Tests/Extractors/PhpDocExtractorTest.php | 1 + .../Extractors/ReflectionExtractorTest.php | 81 ++++++++++++------- .../PropertyInfo/Tests/Fixtures/Dummy.php | 7 ++ .../Component/PropertyInfo/composer.json | 2 +- 5 files changed, 64 insertions(+), 29 deletions(-) diff --git a/composer.json b/composer.json index bf18c7b79995f..00faa0845d422 100644 --- a/composer.json +++ b/composer.json @@ -102,7 +102,7 @@ "sensio/framework-extra-bundle": "^3.0.2" }, "conflict": { - "phpdocumentor/reflection-docblock": "<3.0||>=3.2.0,<3.2.1", + "phpdocumentor/reflection-docblock": "<3.0||>=3.2.0,<3.2.2", "phpdocumentor/type-resolver": "<0.2.0", "phpunit/phpunit": "<4.8.35|<5.4.3,>=5.0" }, diff --git a/src/Symfony/Component/PropertyInfo/Tests/Extractors/PhpDocExtractorTest.php b/src/Symfony/Component/PropertyInfo/Tests/Extractors/PhpDocExtractorTest.php index d0eb3eed06c49..f41056050870c 100644 --- a/src/Symfony/Component/PropertyInfo/Tests/Extractors/PhpDocExtractorTest.php +++ b/src/Symfony/Component/PropertyInfo/Tests/Extractors/PhpDocExtractorTest.php @@ -72,6 +72,7 @@ public function typesProvider() array('donotexist', null, null, null), array('staticGetter', null, null, null), array('staticSetter', null, null, null), + array('emptyVar', null, null, null), ); } diff --git a/src/Symfony/Component/PropertyInfo/Tests/Extractors/ReflectionExtractorTest.php b/src/Symfony/Component/PropertyInfo/Tests/Extractors/ReflectionExtractorTest.php index 573528c012f55..905b50d5dff86 100644 --- a/src/Symfony/Component/PropertyInfo/Tests/Extractors/ReflectionExtractorTest.php +++ b/src/Symfony/Component/PropertyInfo/Tests/Extractors/ReflectionExtractorTest.php @@ -41,6 +41,7 @@ public function testGetProperties() 'B', 'Guid', 'g', + 'emptyVar', 'foo', 'foo2', 'foo3', @@ -122,37 +123,63 @@ public function php71TypesProvider() ); } - public function testIsReadable() + /** + * @dataProvider getReadableProperties + */ + public function testIsReadable($property, $expected) + { + $this->assertSame( + $expected, + $this->extractor->isReadable('Symfony\Component\PropertyInfo\Tests\Fixtures\Dummy', $property, array()) + ); + } + + public function getReadableProperties() + { + return array( + array('bar', false), + array('baz', false), + array('parent', true), + array('a', true), + array('b', false), + array('c', true), + array('d', true), + array('e', false), + array('f', false), + array('Id', true), + array('id', true), + array('Guid', true), + array('guid', false), + ); + } + + /** + * @dataProvider getWritableProperties + */ + public function testIsWritable($property, $expected) { - $this->assertFalse($this->extractor->isReadable('Symfony\Component\PropertyInfo\Tests\Fixtures\Dummy', 'bar', array())); - $this->assertFalse($this->extractor->isReadable('Symfony\Component\PropertyInfo\Tests\Fixtures\Dummy', 'baz', array())); - $this->assertTrue($this->extractor->isReadable('Symfony\Component\PropertyInfo\Tests\Fixtures\Dummy', 'parent', array())); - $this->assertTrue($this->extractor->isReadable('Symfony\Component\PropertyInfo\Tests\Fixtures\Dummy', 'a', array())); - $this->assertFalse($this->extractor->isReadable('Symfony\Component\PropertyInfo\Tests\Fixtures\Dummy', 'b', array())); - $this->assertTrue($this->extractor->isReadable('Symfony\Component\PropertyInfo\Tests\Fixtures\Dummy', 'c', array())); - $this->assertTrue($this->extractor->isReadable('Symfony\Component\PropertyInfo\Tests\Fixtures\Dummy', 'd', array())); - $this->assertFalse($this->extractor->isReadable('Symfony\Component\PropertyInfo\Tests\Fixtures\Dummy', 'e', array())); - $this->assertFalse($this->extractor->isReadable('Symfony\Component\PropertyInfo\Tests\Fixtures\Dummy', 'f', array())); - $this->assertTrue($this->extractor->isReadable('Symfony\Component\PropertyInfo\Tests\Fixtures\Dummy', 'Id', array())); - $this->assertTrue($this->extractor->isReadable('Symfony\Component\PropertyInfo\Tests\Fixtures\Dummy', 'id', array())); - $this->assertTrue($this->extractor->isReadable('Symfony\Component\PropertyInfo\Tests\Fixtures\Dummy', 'Guid', array())); - $this->assertFalse($this->extractor->isReadable('Symfony\Component\PropertyInfo\Tests\Fixtures\Dummy', 'guid', array())); + $this->assertSame( + $expected, + $this->extractor->isWritable('Symfony\Component\PropertyInfo\Tests\Fixtures\Dummy', $property, array()) + ); } - public function testIsWritable() + public function getWritableProperties() { - $this->assertFalse($this->extractor->isWritable('Symfony\Component\PropertyInfo\Tests\Fixtures\Dummy', 'bar', array())); - $this->assertFalse($this->extractor->isWritable('Symfony\Component\PropertyInfo\Tests\Fixtures\Dummy', 'baz', array())); - $this->assertTrue($this->extractor->isWritable('Symfony\Component\PropertyInfo\Tests\Fixtures\Dummy', 'parent', array())); - $this->assertFalse($this->extractor->isWritable('Symfony\Component\PropertyInfo\Tests\Fixtures\Dummy', 'a', array())); - $this->assertTrue($this->extractor->isWritable('Symfony\Component\PropertyInfo\Tests\Fixtures\Dummy', 'b', array())); - $this->assertFalse($this->extractor->isWritable('Symfony\Component\PropertyInfo\Tests\Fixtures\Dummy', 'c', array())); - $this->assertFalse($this->extractor->isWritable('Symfony\Component\PropertyInfo\Tests\Fixtures\Dummy', 'd', array())); - $this->assertTrue($this->extractor->isWritable('Symfony\Component\PropertyInfo\Tests\Fixtures\Dummy', 'e', array())); - $this->assertTrue($this->extractor->isWritable('Symfony\Component\PropertyInfo\Tests\Fixtures\Dummy', 'f', array())); - $this->assertFalse($this->extractor->isWritable('Symfony\Component\PropertyInfo\Tests\Fixtures\Dummy', 'Id', array())); - $this->assertTrue($this->extractor->isWritable('Symfony\Component\PropertyInfo\Tests\Fixtures\Dummy', 'Guid', array())); - $this->assertFalse($this->extractor->isWritable('Symfony\Component\PropertyInfo\Tests\Fixtures\Dummy', 'guid', array())); + return array( + array('bar', false), + array('baz', false), + array('parent', true), + array('a', false), + array('b', true), + array('c', false), + array('d', false), + array('e', true), + array('f', true), + array('Id', false), + array('Guid', true), + array('guid', false), + ); } public function testSingularize() diff --git a/src/Symfony/Component/PropertyInfo/Tests/Fixtures/Dummy.php b/src/Symfony/Component/PropertyInfo/Tests/Fixtures/Dummy.php index d358bae13ad61..4e558eca014e5 100644 --- a/src/Symfony/Component/PropertyInfo/Tests/Fixtures/Dummy.php +++ b/src/Symfony/Component/PropertyInfo/Tests/Fixtures/Dummy.php @@ -68,6 +68,13 @@ class Dummy extends ParentDummy */ public $g; + /** + * This should not be removed. + * + * @var + */ + public $emptyVar; + public static function getStatic() { } diff --git a/src/Symfony/Component/PropertyInfo/composer.json b/src/Symfony/Component/PropertyInfo/composer.json index 20bdccf00156b..13aebfbf0e31e 100644 --- a/src/Symfony/Component/PropertyInfo/composer.json +++ b/src/Symfony/Component/PropertyInfo/composer.json @@ -34,7 +34,7 @@ "doctrine/annotations": "~1.0" }, "conflict": { - "phpdocumentor/reflection-docblock": "<3.0||>=3.2.0,<3.2.1", + "phpdocumentor/reflection-docblock": "<3.0||>=3.2.0,<3.2.2", "phpdocumentor/type-resolver": "<0.2.0", "symfony/dependency-injection": "<3.3" }, From c396e8cb9cfa2c5fdd46f4d6c821cd1c462c4cbb Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Thu, 10 Aug 2017 16:37:13 +0200 Subject: [PATCH 0615/1099] [DI] Fix dumping abstract with YamlDumper --- .../DependencyInjection/Dumper/YamlDumper.php | 4 ++++ .../Tests/Dumper/YamlDumperTest.php | 12 ++++++++++++ .../Tests/Fixtures/yaml/services_dump_load.yml | 4 ++++ 3 files changed, 20 insertions(+) create mode 100644 src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services_dump_load.yml diff --git a/src/Symfony/Component/DependencyInjection/Dumper/YamlDumper.php b/src/Symfony/Component/DependencyInjection/Dumper/YamlDumper.php index 810e7539fe1bd..9125a97836b6f 100644 --- a/src/Symfony/Component/DependencyInjection/Dumper/YamlDumper.php +++ b/src/Symfony/Component/DependencyInjection/Dumper/YamlDumper.php @@ -104,6 +104,10 @@ private function addService($id, $definition) $code .= sprintf(" factory_class: %s\n", $this->dumper->dump($definition->getFactoryClass(false))); } + if ($definition->isAbstract()) { + $code .= " abstract: true\n"; + } + if ($definition->isLazy()) { $code .= " lazy: true\n"; } diff --git a/src/Symfony/Component/DependencyInjection/Tests/Dumper/YamlDumperTest.php b/src/Symfony/Component/DependencyInjection/Tests/Dumper/YamlDumperTest.php index f19a2f5cb8346..81bbd5316c444 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Dumper/YamlDumperTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Dumper/YamlDumperTest.php @@ -12,8 +12,10 @@ namespace Symfony\Component\DependencyInjection\Tests\Dumper; use PHPUnit\Framework\TestCase; +use Symfony\Component\Config\FileLocator; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Dumper\YamlDumper; +use Symfony\Component\DependencyInjection\Loader\YamlFileLoader; use Symfony\Component\Yaml\Yaml; class YamlDumperTest extends TestCase @@ -77,6 +79,16 @@ public function testAddService() } } + public function testDumpLoad() + { + $container = new ContainerBuilder(); + $loader = new YamlFileLoader($container, new FileLocator(self::$fixturesPath.'/yaml')); + $loader->load('services_dump_load.yml'); + + $dumper = new YamlDumper($container); + $this->assertStringEqualsFile(self::$fixturesPath.'/yaml/services_dump_load.yml', $dumper->dump()); + } + private function assertEqualYamlStructure($yaml, $expected, $message = '') { $this->assertEquals(Yaml::parse($expected), Yaml::parse($yaml), $message); diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services_dump_load.yml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services_dump_load.yml new file mode 100644 index 0000000000000..bcf8f31b36115 --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services_dump_load.yml @@ -0,0 +1,4 @@ + +services: + foo: + abstract: true From cc1695cbceb7621336fad76eb4aa4ebc9a133aa4 Mon Sep 17 00:00:00 2001 From: Robin Chalas Date: Thu, 10 Aug 2017 18:13:09 +0200 Subject: [PATCH 0616/1099] [HttpKernel] Remove convention based commands registration --- .../Component/HttpKernel/Bundle/Bundle.php | 40 +------------------ src/Symfony/Component/HttpKernel/CHANGELOG.md | 1 + .../HttpKernel/Tests/Bundle/BundleTest.php | 35 ---------------- .../Component/HttpKernel/composer.json | 2 - 4 files changed, 2 insertions(+), 76 deletions(-) diff --git a/src/Symfony/Component/HttpKernel/Bundle/Bundle.php b/src/Symfony/Component/HttpKernel/Bundle/Bundle.php index d0ea99f5fa95e..609b48fd074a2 100644 --- a/src/Symfony/Component/HttpKernel/Bundle/Bundle.php +++ b/src/Symfony/Component/HttpKernel/Bundle/Bundle.php @@ -15,7 +15,6 @@ use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Container; use Symfony\Component\Console\Application; -use Symfony\Component\Finder\Finder; use Symfony\Component\DependencyInjection\Extension\ExtensionInterface; /** @@ -153,49 +152,12 @@ final public function getName() } /** - * Finds and registers Commands. - * - * Override this method if your bundle commands do not follow the conventions: - * - * * Commands are in the 'Command' sub-directory - * * Commands extend Symfony\Component\Console\Command\Command + * Registers console commands. * * @param Application $application An Application instance */ public function registerCommands(Application $application) { - if (!is_dir($dir = $this->getPath().'/Command')) { - return; - } - - if (!class_exists('Symfony\Component\Finder\Finder')) { - throw new \RuntimeException('You need the symfony/finder component to register bundle commands.'); - } - - $finder = new Finder(); - $finder->files()->name('*Command.php')->in($dir); - - $prefix = $this->getNamespace().'\\Command'; - foreach ($finder as $file) { - $ns = $prefix; - if ($relativePath = $file->getRelativePath()) { - $ns .= '\\'.str_replace('/', '\\', $relativePath); - } - $class = $ns.'\\'.$file->getBasename('.php'); - if ($this->container) { - $commandIds = $this->container->hasParameter('console.command.ids') ? $this->container->getParameter('console.command.ids') : array(); - $alias = 'console.command.'.strtolower(str_replace('\\', '_', $class)); - if (isset($commandIds[$alias]) || $this->container->has($alias)) { - continue; - } - } - $r = new \ReflectionClass($class); - if ($r->isSubclassOf('Symfony\\Component\\Console\\Command\\Command') && !$r->isAbstract() && !$r->getConstructor()->getNumberOfRequiredParameters()) { - @trigger_error(sprintf('Auto-registration of the command "%s" is deprecated since Symfony 3.4 and won\'t be supported in 4.0. Use PSR-4 based service discovery instead.', $class), E_USER_DEPRECATED); - - $application->add($r->newInstance()); - } - } } /** diff --git a/src/Symfony/Component/HttpKernel/CHANGELOG.md b/src/Symfony/Component/HttpKernel/CHANGELOG.md index 4f17d3c37cf9a..444bcd161cf0a 100644 --- a/src/Symfony/Component/HttpKernel/CHANGELOG.md +++ b/src/Symfony/Component/HttpKernel/CHANGELOG.md @@ -20,6 +20,7 @@ CHANGELOG * support for the `X-Status-Code` when handling exceptions in the `HttpKernel` has been dropped, use the `HttpKernel::allowCustomResponseCode()` method instead + * removed convention-based commands registration 3.4.0 ----- diff --git a/src/Symfony/Component/HttpKernel/Tests/Bundle/BundleTest.php b/src/Symfony/Component/HttpKernel/Tests/Bundle/BundleTest.php index 8e52b097d6946..394e7ed7c6d51 100644 --- a/src/Symfony/Component/HttpKernel/Tests/Bundle/BundleTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/Bundle/BundleTest.php @@ -12,12 +12,9 @@ namespace Symfony\Component\HttpKernel\Tests\Bundle; use PHPUnit\Framework\TestCase; -use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\HttpKernel\Bundle\Bundle; use Symfony\Component\HttpKernel\Tests\Fixtures\ExtensionNotValidBundle\ExtensionNotValidBundle; use Symfony\Component\HttpKernel\Tests\Fixtures\ExtensionPresentBundle\ExtensionPresentBundle; -use Symfony\Component\HttpKernel\Tests\Fixtures\ExtensionAbsentBundle\ExtensionAbsentBundle; -use Symfony\Component\HttpKernel\Tests\Fixtures\ExtensionPresentBundle\Command\FooCommand; class BundleTest extends TestCase { @@ -31,24 +28,6 @@ public function testGetContainerExtension() ); } - /** - * @group legacy - * @expectedDeprecation Auto-registration of the command "Symfony\Component\HttpKernel\Tests\Fixtures\ExtensionPresentBundle\Command\FooCommand" is deprecated since Symfony 3.4 and won't be supported in 4.0. Use PSR-4 based service discovery instead. - */ - public function testRegisterCommands() - { - $cmd = new FooCommand(); - $app = $this->getMockBuilder('Symfony\Component\Console\Application')->getMock(); - $app->expects($this->once())->method('add')->with($this->equalTo($cmd)); - - $bundle = new ExtensionPresentBundle(); - $bundle->registerCommands($app); - - $bundle2 = new ExtensionAbsentBundle(); - - $this->assertNull($bundle2->registerCommands($app)); - } - /** * @expectedException \LogicException * @expectedExceptionMessage must implement Symfony\Component\DependencyInjection\Extension\ExtensionInterface @@ -59,20 +38,6 @@ public function testGetContainerExtensionWithInvalidClass() $bundle->getContainerExtension(); } - public function testHttpKernelRegisterCommandsIgnoresCommandsThatAreRegisteredAsServices() - { - $container = new ContainerBuilder(); - $container->register('console.command.symfony_component_httpkernel_tests_fixtures_extensionpresentbundle_command_foocommand', 'Symfony\Component\HttpKernel\Tests\Fixtures\ExtensionPresentBundle\Command\FooCommand'); - - $application = $this->getMockBuilder('Symfony\Component\Console\Application')->getMock(); - // add() is never called when the found command classes are already registered as services - $application->expects($this->never())->method('add'); - - $bundle = new ExtensionPresentBundle(); - $bundle->setContainer($container); - $bundle->registerCommands($application); - } - public function testBundleNameIsGuessedFromClass() { $bundle = new GuessedNameBundle(); diff --git a/src/Symfony/Component/HttpKernel/composer.json b/src/Symfony/Component/HttpKernel/composer.json index 6d0ed3cde083b..4fa9a9066c7ce 100644 --- a/src/Symfony/Component/HttpKernel/composer.json +++ b/src/Symfony/Component/HttpKernel/composer.json @@ -31,7 +31,6 @@ "symfony/dependency-injection": "~3.4|~4.0", "symfony/dom-crawler": "~3.4|~4.0", "symfony/expression-language": "~3.4|~4.0", - "symfony/finder": "~3.4|~4.0", "symfony/process": "~3.4|~4.0", "symfony/routing": "~3.4|~4.0", "symfony/stopwatch": "~3.4|~4.0", @@ -51,7 +50,6 @@ "symfony/config": "", "symfony/console": "", "symfony/dependency-injection": "", - "symfony/finder": "", "symfony/var-dumper": "" }, "autoload": { From ce4cd854860554e19828c6ed3dd897acccfa73c9 Mon Sep 17 00:00:00 2001 From: Dany Maillard Date: Thu, 10 Aug 2017 21:17:23 +0200 Subject: [PATCH 0617/1099] Remove hhvm compat/low PHP support in date caster tests --- .../Component/VarDumper/Tests/Caster/DateCasterTest.php | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/Symfony/Component/VarDumper/Tests/Caster/DateCasterTest.php b/src/Symfony/Component/VarDumper/Tests/Caster/DateCasterTest.php index b65376a630586..86cd46060a819 100644 --- a/src/Symfony/Component/VarDumper/Tests/Caster/DateCasterTest.php +++ b/src/Symfony/Component/VarDumper/Tests/Caster/DateCasterTest.php @@ -45,10 +45,6 @@ public function testDumpDateTime($time, $timezone, $xDate, $xTimestamp) */ public function testCastDateTime($time, $timezone, $xDate, $xTimestamp, $xInfos) { - if ((defined('HHVM_VERSION_ID') || PHP_VERSION_ID <= 50509) && preg_match('/[-+]\d{2}:\d{2}/', $timezone)) { - $this->markTestSkipped('DateTimeZone GMT offsets are supported since 5.5.10. See https://github.com/facebook/hhvm/issues/5875 for HHVM.'); - } - $stub = new Stub(); $date = new \DateTime($time, new \DateTimeZone($timezone)); $cast = DateCaster::castDateTime($date, array('foo' => 'bar'), $stub, false, 0); From eeaea83d380abd190a999b3addce784ca177ca7d Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Thu, 10 Aug 2017 21:55:15 +0200 Subject: [PATCH 0618/1099] fix merge --- .../PropertyInfo/Tests/Extractors/ReflectionExtractorTest.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Symfony/Component/PropertyInfo/Tests/Extractors/ReflectionExtractorTest.php b/src/Symfony/Component/PropertyInfo/Tests/Extractors/ReflectionExtractorTest.php index d3a851d58850e..02729b4bf90e4 100644 --- a/src/Symfony/Component/PropertyInfo/Tests/Extractors/ReflectionExtractorTest.php +++ b/src/Symfony/Component/PropertyInfo/Tests/Extractors/ReflectionExtractorTest.php @@ -73,6 +73,7 @@ public function testGetPropertiesWithCustomPrefixes() 'B', 'Guid', 'g', + 'emptyVar', 'foo', 'foo2', 'foo3', @@ -100,6 +101,7 @@ public function testGetPropertiesWithNoPrefixes() 'B', 'Guid', 'g', + 'emptyVar', 'foo', 'foo2', 'foo3', From 9c29f9c19be02839c1780b429283684b9ca0f706 Mon Sep 17 00:00:00 2001 From: Florent Mata Date: Fri, 11 Aug 2017 14:43:59 +0200 Subject: [PATCH 0619/1099] [Workflow] fixed InvalidDefinitionException message for StateMachineValidator --- .../Component/Workflow/Validator/StateMachineValidator.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/Workflow/Validator/StateMachineValidator.php b/src/Symfony/Component/Workflow/Validator/StateMachineValidator.php index 16948f6769b6e..8fe5eecc4a22a 100644 --- a/src/Symfony/Component/Workflow/Validator/StateMachineValidator.php +++ b/src/Symfony/Component/Workflow/Validator/StateMachineValidator.php @@ -31,7 +31,7 @@ public function validate(Definition $definition, $name) // Make sure that each transition has exactly one FROM $froms = $transition->getFroms(); if (1 !== count($froms)) { - throw new InvalidDefinitionException(sprintf('A transition in StateMachine can only have one input. But the transition "%s" in StateMachine "%s" has %d inputs.', $transition->getName(), $name, count($transition->getTos()))); + throw new InvalidDefinitionException(sprintf('A transition in StateMachine can only have one input. But the transition "%s" in StateMachine "%s" has %d inputs.', $transition->getName(), $name, count($froms))); } // Enforcing uniqueness of the names of transitions starting at each node From 04df2832ab05005f7f8bf0576b7c63e7e46b894f Mon Sep 17 00:00:00 2001 From: Thanos Polymeneas Date: Fri, 11 Aug 2017 17:43:53 +0200 Subject: [PATCH 0620/1099] [Console] Added a case-insensitive fallback for console command names --- src/Symfony/Component/Console/Application.php | 7 +++- src/Symfony/Component/Console/CHANGELOG.md | 1 + .../Console/Tests/ApplicationTest.php | 41 ++++++++++++++++++- .../Fixtures/FooSameCaseLowercaseCommand.php | 11 +++++ .../Fixtures/FooSameCaseUppercaseCommand.php | 11 +++++ 5 files changed, 68 insertions(+), 3 deletions(-) create mode 100644 src/Symfony/Component/Console/Tests/Fixtures/FooSameCaseLowercaseCommand.php create mode 100644 src/Symfony/Component/Console/Tests/Fixtures/FooSameCaseUppercaseCommand.php diff --git a/src/Symfony/Component/Console/Application.php b/src/Symfony/Component/Console/Application.php index b9669789eae8a..1eb1fca535fee 100644 --- a/src/Symfony/Component/Console/Application.php +++ b/src/Symfony/Component/Console/Application.php @@ -578,7 +578,12 @@ public function find($name) $expr = preg_replace_callback('{([^:]+|)}', function ($matches) { return preg_quote($matches[1]).'[^:]*'; }, $name); $commands = preg_grep('{^'.$expr.'}', $allCommands); - if (empty($commands) || count(preg_grep('{^'.$expr.'$}', $commands)) < 1) { + if (empty($commands)) { + $commands = preg_grep('{^'.$expr.'}i', $allCommands); + } + + // if no commands matched or we just matched namespaces + if (empty($commands) || count(preg_grep('{^'.$expr.'$}i', $commands)) < 1) { if (false !== $pos = strrpos($name, ':')) { // check if a namespace exists and contains commands $this->findNamespace(substr($name, 0, $pos)); diff --git a/src/Symfony/Component/Console/CHANGELOG.md b/src/Symfony/Component/Console/CHANGELOG.md index 616f70e137c0c..0c147a605ccb2 100644 --- a/src/Symfony/Component/Console/CHANGELOG.md +++ b/src/Symfony/Component/Console/CHANGELOG.md @@ -6,6 +6,7 @@ CHANGELOG * added `CommandLoaderInterface`, `FactoryCommandLoader` and PSR-11 `ContainerCommandLoader` for commands lazy-loading + * added a case-insensitive command name matching fallback 3.3.0 ----- diff --git a/src/Symfony/Component/Console/Tests/ApplicationTest.php b/src/Symfony/Component/Console/Tests/ApplicationTest.php index 724b34f8468ae..5dd1e79b67a8d 100644 --- a/src/Symfony/Component/Console/Tests/ApplicationTest.php +++ b/src/Symfony/Component/Console/Tests/ApplicationTest.php @@ -51,6 +51,8 @@ public static function setUpBeforeClass() require_once self::$fixturesPath.'/Foo3Command.php'; require_once self::$fixturesPath.'/Foo4Command.php'; require_once self::$fixturesPath.'/Foo5Command.php'; + require_once self::$fixturesPath.'/FooSameCaseUppercaseCommand.php'; + require_once self::$fixturesPath.'/FooSameCaseLowercaseCommand.php'; require_once self::$fixturesPath.'/FoobarCommand.php'; require_once self::$fixturesPath.'/BarBucCommand.php'; require_once self::$fixturesPath.'/FooSubnamespaced1Command.php'; @@ -317,6 +319,41 @@ public function testFind() $this->assertInstanceOf('FooCommand', $application->find('a'), '->find() returns a command if the abbreviation exists for an alias'); } + public function testFindCaseSensitiveFirst() + { + $application = new Application(); + $application->add(new \FooSameCaseUppercaseCommand()); + $application->add(new \FooSameCaseLowercaseCommand()); + + $this->assertInstanceOf('FooSameCaseUppercaseCommand', $application->find('f:B'), '->find() returns a command if the abbreviation is the correct case'); + $this->assertInstanceOf('FooSameCaseUppercaseCommand', $application->find('f:BAR'), '->find() returns a command if the abbreviation is the correct case'); + $this->assertInstanceOf('FooSameCaseLowercaseCommand', $application->find('f:b'), '->find() returns a command if the abbreviation is the correct case'); + $this->assertInstanceOf('FooSameCaseLowercaseCommand', $application->find('f:bar'), '->find() returns a command if the abbreviation is the correct case'); + } + + public function testFindCaseInsensitiveAsFallback() + { + $application = new Application(); + $application->add(new \FooSameCaseLowercaseCommand()); + + $this->assertInstanceOf('FooSameCaseLowercaseCommand', $application->find('f:b'), '->find() returns a command if the abbreviation is the correct case'); + $this->assertInstanceOf('FooSameCaseLowercaseCommand', $application->find('f:B'), '->find() will fallback to case insensitivity'); + $this->assertInstanceOf('FooSameCaseLowercaseCommand', $application->find('FoO:BaR'), '->find() will fallback to case insensitivity'); + } + + /** + * @expectedException \Symfony\Component\Console\Exception\CommandNotFoundException + * @expectedExceptionMessage Command "FoO:BaR" is ambiguous + */ + public function testFindCaseInsensitiveSuggestions() + { + $application = new Application(); + $application->add(new \FooSameCaseLowercaseCommand()); + $application->add(new \FooSameCaseUppercaseCommand()); + + $this->assertInstanceOf('FooSameCaseLowercaseCommand', $application->find('FoO:BaR'), '->find() will find two suggestions with case insensitivity'); + } + public function testFindWithCommandLoader() { $application = new Application(); @@ -414,8 +451,8 @@ public function testFindAlternativeExceptionMessageSingle($name) public function provideInvalidCommandNamesSingle() { return array( - array('foo3:baR'), - array('foO3:bar'), + array('foo3:barr'), + array('fooo3:bar'), ); } diff --git a/src/Symfony/Component/Console/Tests/Fixtures/FooSameCaseLowercaseCommand.php b/src/Symfony/Component/Console/Tests/Fixtures/FooSameCaseLowercaseCommand.php new file mode 100644 index 0000000000000..c875be0cd7546 --- /dev/null +++ b/src/Symfony/Component/Console/Tests/Fixtures/FooSameCaseLowercaseCommand.php @@ -0,0 +1,11 @@ +setName('foo:bar')->setDescription('foo:bar command'); + } +} diff --git a/src/Symfony/Component/Console/Tests/Fixtures/FooSameCaseUppercaseCommand.php b/src/Symfony/Component/Console/Tests/Fixtures/FooSameCaseUppercaseCommand.php new file mode 100644 index 0000000000000..75c8d0024e28c --- /dev/null +++ b/src/Symfony/Component/Console/Tests/Fixtures/FooSameCaseUppercaseCommand.php @@ -0,0 +1,11 @@ +setName('foo:BAR')->setDescription('foo:BAR command'); + } +} From 1bea774f4de173de64f63d0d64d83473c706a989 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Sat, 12 Aug 2017 22:32:56 +0200 Subject: [PATCH 0621/1099] [VarDumper] play nice with open_basedir when looking for composer.json --- src/Symfony/Component/VarDumper/Caster/LinkStub.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/VarDumper/Caster/LinkStub.php b/src/Symfony/Component/VarDumper/Caster/LinkStub.php index 1a9aa419d148f..eb9bc85c914f9 100644 --- a/src/Symfony/Component/VarDumper/Caster/LinkStub.php +++ b/src/Symfony/Component/VarDumper/Caster/LinkStub.php @@ -89,7 +89,11 @@ private function getComposerRoot($file, &$inVendor) } $parent = $dir; - while (!file_exists($parent.'/composer.json')) { + while (!@file_exists($parent.'/composer.json')) { + if (!@file_exists($parent)) { + // open_basedir restriction in effect + break; + } if ($parent === dirname($parent)) { return self::$composerRoots[$dir] = false; } From 423656f8eaf85ba09158f6b984b2e758170d8076 Mon Sep 17 00:00:00 2001 From: "Alexander M. Turek" Date: Sun, 13 Aug 2017 23:58:09 +0200 Subject: [PATCH 0622/1099] Fixed some param/return annotations in PHPDOC blocks. --- src/Symfony/Component/DependencyInjection/Container.php | 2 +- src/Symfony/Component/DependencyInjection/Definition.php | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/DependencyInjection/Container.php b/src/Symfony/Component/DependencyInjection/Container.php index 379c7f6d0eb76..3b0a82d80ea10 100644 --- a/src/Symfony/Component/DependencyInjection/Container.php +++ b/src/Symfony/Component/DependencyInjection/Container.php @@ -427,7 +427,7 @@ public static function underscore($id) /** * Fetches a variable from the environment. * - * @param string The name of the environment variable + * @param string $name The name of the environment variable * * @return scalar The value to use for the provided environment variable name * diff --git a/src/Symfony/Component/DependencyInjection/Definition.php b/src/Symfony/Component/DependencyInjection/Definition.php index 173578acd5815..2900ddc24d269 100644 --- a/src/Symfony/Component/DependencyInjection/Definition.php +++ b/src/Symfony/Component/DependencyInjection/Definition.php @@ -71,6 +71,8 @@ public function getChanges() /** * Sets the tracked changes for the Definition object. * + * @param array $changes An array of changes for this Definition + * * @return $this */ public function setChanges(array $changes) @@ -401,6 +403,8 @@ public function getMethodCalls() * Sets the definition templates to conditionally apply on the current definition, keyed by parent interface/class. * * @param $instanceof ChildDefinition[] + * + * @return $this */ public function setInstanceofConditionals(array $instanceof) { From 9b7750a432ae183d1997d67bb88aa72d8e44a7bb Mon Sep 17 00:00:00 2001 From: Javier Eguiluz Date: Thu, 10 Aug 2017 13:07:56 +0200 Subject: [PATCH 0623/1099] Made some SecurityBundle tests case-insensitive to prepare for future Symfony versions --- .../Tests/DependencyInjection/CompleteConfigurationTest.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/CompleteConfigurationTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/CompleteConfigurationTest.php index 87b8e30cbd8ba..4f000d3aee0f8 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/CompleteConfigurationTest.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/CompleteConfigurationTest.php @@ -81,6 +81,11 @@ public function testFirewalls() $configs[] = array_values($configDef->getArguments()); } + // the IDs of the services are case sensitive or insensitive depending on + // the Symfony version. Transform them to lowercase to simplify tests. + $configs[0][2] = strtolower($configs[0][2]); + $configs[2][2] = strtolower($configs[2][2]); + $this->assertEquals(array( array( 'simple', From 339592da14a7daa2ec023ae9aa88a3a68223630b Mon Sep 17 00:00:00 2001 From: Matthieu Mota Date: Thu, 10 Aug 2017 18:24:09 +0200 Subject: [PATCH 0624/1099] Fix testHtml method with regexp --- src/Symfony/Component/DomCrawler/Tests/CrawlerTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/DomCrawler/Tests/CrawlerTest.php b/src/Symfony/Component/DomCrawler/Tests/CrawlerTest.php index bfd9527a05c83..495a4a9d14a34 100644 --- a/src/Symfony/Component/DomCrawler/Tests/CrawlerTest.php +++ b/src/Symfony/Component/DomCrawler/Tests/CrawlerTest.php @@ -353,7 +353,7 @@ public function testText() public function testHtml() { $this->assertEquals('Bar', $this->createTestCrawler()->filterXPath('//a[5]')->html()); - $this->assertEquals('', trim($this->createTestCrawler()->filterXPath('//form[@id="FooFormId"]')->html())); + $this->assertEquals('', trim(preg_replace('~>\s+<~', '><', $this->createTestCrawler()->filterXPath('//form[@id="FooFormId"]')->html()))); try { $this->createTestCrawler()->filterXPath('//ol')->html(); From 8a1d16839e31cf81eef768bd6dd44ab40fd3a5f4 Mon Sep 17 00:00:00 2001 From: Roland Franssen Date: Sat, 12 Aug 2017 11:16:19 +0200 Subject: [PATCH 0625/1099] [DI] Case sensitive parameter names --- .../DependencyInjection/CHANGELOG.md | 1 + .../DependencyInjection/Dumper/PhpDumper.php | 34 +++++++++++++--- .../Loader/XmlFileLoader.php | 5 --- .../EnvPlaceholderParameterBag.php | 2 +- .../ParameterBag/ParameterBag.php | 30 ++++++++++---- .../Tests/ContainerBuilderTest.php | 15 +++++++ .../Tests/ContainerTest.php | 18 +++++++-- .../Tests/Dumper/PhpDumperTest.php | 39 +++++++++++++++++++ .../Tests/Fixtures/containers/container8.php | 2 +- .../Tests/Fixtures/php/services10.php | 20 +++++++++- .../Tests/Fixtures/php/services12.php | 20 +++++++++- .../Tests/Fixtures/php/services26.php | 24 ++++++++++-- .../Tests/Fixtures/php/services8.php | 20 +++++++++- .../Tests/Fixtures/php/services9_as_files.txt | 20 +++++++++- .../Tests/Fixtures/php/services9_compiled.php | 20 +++++++++- .../Fixtures/php/services_array_params.php | 20 +++++++++- .../Tests/Fixtures/xml/services2.xml | 4 +- .../Tests/Fixtures/yaml/services2.yml | 4 +- .../EnvPlaceholderParameterBagTest.php | 12 +++--- .../Tests/ParameterBag/ParameterBagTest.php | 31 +++++++++++---- 20 files changed, 285 insertions(+), 56 deletions(-) diff --git a/src/Symfony/Component/DependencyInjection/CHANGELOG.md b/src/Symfony/Component/DependencyInjection/CHANGELOG.md index 1fc26be27ea14..49e140de11796 100644 --- a/src/Symfony/Component/DependencyInjection/CHANGELOG.md +++ b/src/Symfony/Component/DependencyInjection/CHANGELOG.md @@ -7,6 +7,7 @@ CHANGELOG * deprecated service auto-registration while autowiring * deprecated the ability to check for the initialization of a private service with the `Container::initialized()` method * deprecated support for top-level anonymous services in XML + * deprecated case insensitivity of parameter names 3.3.0 ----- diff --git a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php index cdcea02ed19d0..8a33b698c3bc2 100644 --- a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php +++ b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php @@ -1056,11 +1056,15 @@ private function addDefaultParametersMethod() $php = array(); $dynamicPhp = array(); + $normalizedParams = array(); foreach ($this->container->getParameterBag()->all() as $key => $value) { if ($key !== $resolvedKey = $this->container->resolveEnvPlaceholders($key)) { throw new InvalidArgumentException(sprintf('Parameter name cannot use env parameters: %s.', $resolvedKey)); } + if ($key !== $lcKey = strtolower($key)) { + $normalizedParams[] = sprintf(' %s => %s,', $this->export($lcKey), $this->export($key)); + } $export = $this->exportParameters(array($value)); $export = explode('0 => ', substr(rtrim($export, " )\n"), 7, -1), 2); @@ -1082,7 +1086,7 @@ private function addDefaultParametersMethod() public function getParameter($name) { if (!(isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters))) { - $name = strtolower($name); + $name = $this->normalizeParameterName($name); if (!(isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters))) { throw new InvalidArgumentException(sprintf('The parameter "%s" must be defined.', $name)); @@ -1100,7 +1104,7 @@ public function getParameter($name) */ public function hasParameter($name) { - $name = strtolower($name); + $name = $this->normalizeParameterName($name); return isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters); } @@ -1170,6 +1174,26 @@ private function getDynamicParameter(\$name) {$getDynamicParameter} } + +EOF; + + $code .= ' private $normalizedParameterNames = '.($normalizedParams ? sprintf("array(\n%s\n );", implode("\n", $normalizedParams)) : 'array();')."\n"; + $code .= <<<'EOF' + + private function normalizeParameterName($name) + { + if (isset($this->normalizedParameterNames[$normalizedName = strtolower($name)]) || isset($this->parameters[$normalizedName]) || array_key_exists($normalizedName, $this->parameters)) { + $normalizedName = isset($this->normalizedParameterNames[$normalizedName]) ? $this->normalizedParameterNames[$normalizedName] : $normalizedName; + if ((string) $name !== $normalizedName) { + @trigger_error(sprintf('Parameter names will be made case sensitive in Symfony 4.0. Using "%s" instead of "%s" is deprecated since version 3.4.', $name, $normalizedName), E_USER_DEPRECATED); + } + } else { + $normalizedName = $this->normalizedParameterNames[$normalizedName] = (string) $name; + } + + return $normalizedName; + } + EOF; } elseif ($dynamicPhp) { throw new RuntimeException('You cannot dump a not-frozen container with dynamic parameters.'); @@ -1555,10 +1579,10 @@ private function dumpValue($value, $interpolate = true) if (preg_match('/^%([^%]+)%$/', $value, $match)) { // we do this to deal with non string values (Boolean, integer, ...) // the preg_replace_callback converts them to strings - return $this->dumpParameter(strtolower($match[1])); + return $this->dumpParameter($match[1]); } else { $replaceParameters = function ($match) { - return "'.".$this->dumpParameter(strtolower($match[2])).".'"; + return "'.".$this->dumpParameter($match[2]).".'"; }; $code = str_replace('%%', '%', preg_replace_callback('/(?export($value))); @@ -1604,8 +1628,6 @@ private function dumpLiteralClass($class) */ private function dumpParameter($name) { - $name = strtolower($name); - if ($this->container->isCompiled() && $this->container->hasParameter($name)) { $value = $this->container->getParameter($name); $dumpedValue = $this->dumpValue($value, false); diff --git a/src/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php b/src/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php index ebdc83d733c5f..69411114735f6 100644 --- a/src/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php +++ b/src/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php @@ -486,11 +486,6 @@ private function getArgumentsAsPhp(\DOMElement $node, $name, $file, $lowercase = $key = array_pop($keys); } else { $key = $arg->getAttribute('key'); - - // parameter keys are case insensitive - if ('parameter' == $name && $lowercase) { - $key = strtolower($key); - } } $onInvalid = $arg->getAttribute('on-invalid'); diff --git a/src/Symfony/Component/DependencyInjection/ParameterBag/EnvPlaceholderParameterBag.php b/src/Symfony/Component/DependencyInjection/ParameterBag/EnvPlaceholderParameterBag.php index d20e53531aa3b..fd859068be33c 100644 --- a/src/Symfony/Component/DependencyInjection/ParameterBag/EnvPlaceholderParameterBag.php +++ b/src/Symfony/Component/DependencyInjection/ParameterBag/EnvPlaceholderParameterBag.php @@ -91,7 +91,7 @@ public function resolve() parent::resolve(); foreach ($this->envPlaceholders as $env => $placeholders) { - if (!isset($this->parameters[$name = strtolower("env($env)")])) { + if (!$this->has($name = "env($env)")) { continue; } if (is_numeric($default = $this->parameters[$name])) { diff --git a/src/Symfony/Component/DependencyInjection/ParameterBag/ParameterBag.php b/src/Symfony/Component/DependencyInjection/ParameterBag/ParameterBag.php index 83ba7e7076fc1..1a9ca6fa4d4fb 100644 --- a/src/Symfony/Component/DependencyInjection/ParameterBag/ParameterBag.php +++ b/src/Symfony/Component/DependencyInjection/ParameterBag/ParameterBag.php @@ -25,6 +25,8 @@ class ParameterBag implements ParameterBagInterface protected $parameters = array(); protected $resolved = false; + private $normalizedNames = array(); + /** * @param array $parameters An array of parameters */ @@ -49,7 +51,7 @@ public function clear() public function add(array $parameters) { foreach ($parameters as $key => $value) { - $this->parameters[strtolower($key)] = $value; + $this->set($key, $value); } } @@ -66,7 +68,7 @@ public function all() */ public function get($name) { - $name = strtolower($name); + $name = $this->normalizeName($name); if (!array_key_exists($name, $this->parameters)) { if (!$name) { @@ -111,7 +113,7 @@ public function get($name) */ public function set($name, $value) { - $this->parameters[strtolower($name)] = $value; + $this->parameters[$this->normalizeName($name)] = $value; } /** @@ -119,7 +121,7 @@ public function set($name, $value) */ public function has($name) { - return array_key_exists(strtolower($name), $this->parameters); + return array_key_exists($this->normalizeName($name), $this->parameters); } /** @@ -129,7 +131,7 @@ public function has($name) */ public function remove($name) { - unset($this->parameters[strtolower($name)]); + unset($this->parameters[$this->normalizeName($name)]); } /** @@ -206,7 +208,7 @@ public function resolveString($value, array $resolving = array()) // a non-string in a parameter value if (preg_match('/^%([^%\s]+)%$/', $value, $match)) { $key = $match[1]; - $lcKey = strtolower($key); + $lcKey = strtolower($key); // strtolower() to be removed in 4.0 if (isset($resolving[$lcKey])) { throw new ParameterCircularReferenceException(array_keys($resolving)); @@ -224,7 +226,7 @@ public function resolveString($value, array $resolving = array()) } $key = $match[1]; - $lcKey = strtolower($key); + $lcKey = strtolower($key); // strtolower() to be removed in 4.0 if (isset($resolving[$lcKey])) { throw new ParameterCircularReferenceException(array_keys($resolving)); } @@ -288,4 +290,18 @@ public function unescapeValue($value) return $value; } + + private function normalizeName($name) + { + if (isset($this->normalizedNames[$normalizedName = strtolower($name)])) { + $normalizedName = $this->normalizedNames[$normalizedName]; + if ((string) $name !== $normalizedName) { + @trigger_error(sprintf('Parameter names will be made case sensitive in Symfony 4.0. Using "%s" instead of "%s" is deprecated since version 3.4.', $name, $normalizedName), E_USER_DEPRECATED); + } + } else { + $normalizedName = $this->normalizedNames[$normalizedName] = (string) $name; + } + + return $normalizedName; + } } diff --git a/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php b/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php index 51397309b7dce..e854d394dee8b 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php @@ -1103,6 +1103,21 @@ public function testPrivateServiceTriggersDeprecation() $container->get('bar'); } + + /** + * @group legacy + * @expectedDeprecation Parameter names will be made case sensitive in Symfony 4.0. Using "FOO" instead of "foo" is deprecated since version 3.4. + */ + public function testParameterWithMixedCase() + { + $container = new ContainerBuilder(new ParameterBag(array('foo' => 'bar'))); + $container->register('foo', 'stdClass') + ->setProperty('foo', '%FOO%'); + + $container->compile(); + + $this->assertSame('bar', $container->get('foo')->foo); + } } class FooClass diff --git a/src/Symfony/Component/DependencyInjection/Tests/ContainerTest.php b/src/Symfony/Component/DependencyInjection/Tests/ContainerTest.php index 75435cf5682f3..d49df4ec42975 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/ContainerTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/ContainerTest.php @@ -125,10 +125,6 @@ public function testGetSetParameter() $sc->setParameter('foo', 'baz'); $this->assertEquals('baz', $sc->getParameter('foo'), '->setParameter() overrides previously set parameter'); - $sc->setParameter('Foo', 'baz1'); - $this->assertEquals('baz1', $sc->getParameter('foo'), '->setParameter() converts the key to lowercase'); - $this->assertEquals('baz1', $sc->getParameter('FOO'), '->getParameter() converts the key to lowercase'); - try { $sc->getParameter('baba'); $this->fail('->getParameter() thrown an \InvalidArgumentException if the key does not exist'); @@ -138,6 +134,20 @@ public function testGetSetParameter() } } + /** + * @group legacy + * @expectedDeprecation Parameter names will be made case sensitive in Symfony 4.0. Using "Foo" instead of "foo" is deprecated since version 3.4. + * @expectedDeprecation Parameter names will be made case sensitive in Symfony 4.0. Using "FOO" instead of "foo" is deprecated since version 3.4. + */ + public function testGetSetParameterWithMixedCase() + { + $sc = new Container(new ParameterBag(array('foo' => 'bar'))); + + $sc->setParameter('Foo', 'baz1'); + $this->assertEquals('baz1', $sc->getParameter('foo'), '->setParameter() converts the key to lowercase'); + $this->assertEquals('baz1', $sc->getParameter('FOO'), '->getParameter() converts the key to lowercase'); + } + public function testGetServiceIds() { $sc = new Container(); diff --git a/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php b/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php index fc5a950af4709..495949674bc43 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php @@ -670,4 +670,43 @@ public function testPrivateServiceTriggersDeprecation() $container->get('bar'); } + + /** + * @group legacy + * @expectedDeprecation Parameter names will be made case sensitive in Symfony 4.0. Using "foo" instead of "Foo" is deprecated since version 3.4. + * @expectedDeprecation Parameter names will be made case sensitive in Symfony 4.0. Using "FOO" instead of "Foo" is deprecated since version 3.4. + * @expectedDeprecation Parameter names will be made case sensitive in Symfony 4.0. Using "bar" instead of "BAR" is deprecated since version 3.4. + */ + public function testParameterWithMixedCase() + { + $container = new ContainerBuilder(new ParameterBag(array('Foo' => 'bar', 'BAR' => 'foo'))); + $container->compile(); + + $dumper = new PhpDumper($container); + eval('?>'.$dumper->dump(array('class' => 'Symfony_DI_PhpDumper_Test_Parameter_With_Mixed_Case'))); + + $container = new \Symfony_DI_PhpDumper_Test_Parameter_With_Mixed_Case(); + + $this->assertSame('bar', $container->getParameter('foo')); + $this->assertSame('bar', $container->getParameter('FOO')); + $this->assertSame('foo', $container->getParameter('bar')); + $this->assertSame('foo', $container->getParameter('BAR')); + } + + /** + * @group legacy + * @expectedDeprecation Parameter names will be made case sensitive in Symfony 4.0. Using "FOO" instead of "foo" is deprecated since version 3.4. + */ + public function testParameterWithLowerCase() + { + $container = new ContainerBuilder(new ParameterBag(array('foo' => 'bar'))); + $container->compile(); + + $dumper = new PhpDumper($container); + eval('?>'.$dumper->dump(array('class' => 'Symfony_DI_PhpDumper_Test_Parameter_With_Lower_Case'))); + + $container = new \Symfony_DI_PhpDumper_Test_Parameter_With_Lower_Case(); + + $this->assertSame('bar', $container->getParameter('FOO')); + } } diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container8.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container8.php index f0b4ca9330a38..1a4e5ab5c8d8d 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container8.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container8.php @@ -4,7 +4,7 @@ use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag; $container = new ContainerBuilder(new ParameterBag(array( - 'FOO' => '%baz%', + 'foo' => '%baz%', 'baz' => 'bar', 'bar' => 'foo is %%foo bar', 'escape' => '@escapeme', diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services10.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services10.php index 19fe0206945cc..d8478d677f4ff 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services10.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services10.php @@ -78,7 +78,7 @@ protected function getTestService() public function getParameter($name) { if (!(isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters))) { - $name = strtolower($name); + $name = $this->normalizeParameterName($name); if (!(isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters))) { throw new InvalidArgumentException(sprintf('The parameter "%s" must be defined.', $name)); @@ -96,7 +96,7 @@ public function getParameter($name) */ public function hasParameter($name) { - $name = strtolower($name); + $name = $this->normalizeParameterName($name); return isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters); } @@ -142,6 +142,22 @@ private function getDynamicParameter($name) throw new InvalidArgumentException(sprintf('The dynamic parameter "%s" must be defined.', $name)); } + private $normalizedParameterNames = array(); + + private function normalizeParameterName($name) + { + if (isset($this->normalizedParameterNames[$normalizedName = strtolower($name)]) || isset($this->parameters[$normalizedName]) || array_key_exists($normalizedName, $this->parameters)) { + $normalizedName = isset($this->normalizedParameterNames[$normalizedName]) ? $this->normalizedParameterNames[$normalizedName] : $normalizedName; + if ((string) $name !== $normalizedName) { + @trigger_error(sprintf('Parameter names will be made case sensitive in Symfony 4.0. Using "%s" instead of "%s" is deprecated since version 3.4.', $name, $normalizedName), E_USER_DEPRECATED); + } + } else { + $normalizedName = $this->normalizedParameterNames[$normalizedName] = (string) $name; + } + + return $normalizedName; + } + /** * Gets the default parameters. * diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services12.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services12.php index 77224a5b8f800..976c720768752 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services12.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services12.php @@ -82,7 +82,7 @@ protected function getTestService() public function getParameter($name) { if (!(isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters))) { - $name = strtolower($name); + $name = $this->normalizeParameterName($name); if (!(isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters))) { throw new InvalidArgumentException(sprintf('The parameter "%s" must be defined.', $name)); @@ -100,7 +100,7 @@ public function getParameter($name) */ public function hasParameter($name) { - $name = strtolower($name); + $name = $this->normalizeParameterName($name); return isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters); } @@ -156,6 +156,22 @@ private function getDynamicParameter($name) return $this->dynamicParameters[$name] = $value; } + private $normalizedParameterNames = array(); + + private function normalizeParameterName($name) + { + if (isset($this->normalizedParameterNames[$normalizedName = strtolower($name)]) || isset($this->parameters[$normalizedName]) || array_key_exists($normalizedName, $this->parameters)) { + $normalizedName = isset($this->normalizedParameterNames[$normalizedName]) ? $this->normalizedParameterNames[$normalizedName] : $normalizedName; + if ((string) $name !== $normalizedName) { + @trigger_error(sprintf('Parameter names will be made case sensitive in Symfony 4.0. Using "%s" instead of "%s" is deprecated since version 3.4.', $name, $normalizedName), E_USER_DEPRECATED); + } + } else { + $normalizedName = $this->normalizedParameterNames[$normalizedName] = (string) $name; + } + + return $normalizedName; + } + /** * Gets the default parameters. * diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services26.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services26.php index 5ec14c1026268..0998b23a75b9a 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services26.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services26.php @@ -80,7 +80,7 @@ protected function getTestService() public function getParameter($name) { if (!(isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters))) { - $name = strtolower($name); + $name = $this->normalizeParameterName($name); if (!(isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters))) { throw new InvalidArgumentException(sprintf('The parameter "%s" must be defined.', $name)); @@ -98,7 +98,7 @@ public function getParameter($name) */ public function hasParameter($name) { - $name = strtolower($name); + $name = $this->normalizeParameterName($name); return isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters); } @@ -152,6 +152,24 @@ private function getDynamicParameter($name) return $this->dynamicParameters[$name] = $value; } + private $normalizedParameterNames = array( + 'env(foo)' => 'env(FOO)', + ); + + private function normalizeParameterName($name) + { + if (isset($this->normalizedParameterNames[$normalizedName = strtolower($name)]) || isset($this->parameters[$normalizedName]) || array_key_exists($normalizedName, $this->parameters)) { + $normalizedName = isset($this->normalizedParameterNames[$normalizedName]) ? $this->normalizedParameterNames[$normalizedName] : $normalizedName; + if ((string) $name !== $normalizedName) { + @trigger_error(sprintf('Parameter names will be made case sensitive in Symfony 4.0. Using "%s" instead of "%s" is deprecated since version 3.4.', $name, $normalizedName), E_USER_DEPRECATED); + } + } else { + $normalizedName = $this->normalizedParameterNames[$normalizedName] = (string) $name; + } + + return $normalizedName; + } + /** * Gets the default parameters. * @@ -160,7 +178,7 @@ private function getDynamicParameter($name) protected function getDefaultParameters() { return array( - 'env(foo)' => 'foo', + 'env(FOO)' => 'foo', ); } } diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services8.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services8.php index f85e3251be8bd..1689a9658668a 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services8.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services8.php @@ -65,7 +65,7 @@ public function isFrozen() public function getParameter($name) { if (!(isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters))) { - $name = strtolower($name); + $name = $this->normalizeParameterName($name); if (!(isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters))) { throw new InvalidArgumentException(sprintf('The parameter "%s" must be defined.', $name)); @@ -83,7 +83,7 @@ public function getParameter($name) */ public function hasParameter($name) { - $name = strtolower($name); + $name = $this->normalizeParameterName($name); return isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters); } @@ -129,6 +129,22 @@ private function getDynamicParameter($name) throw new InvalidArgumentException(sprintf('The dynamic parameter "%s" must be defined.', $name)); } + private $normalizedParameterNames = array(); + + private function normalizeParameterName($name) + { + if (isset($this->normalizedParameterNames[$normalizedName = strtolower($name)]) || isset($this->parameters[$normalizedName]) || array_key_exists($normalizedName, $this->parameters)) { + $normalizedName = isset($this->normalizedParameterNames[$normalizedName]) ? $this->normalizedParameterNames[$normalizedName] : $normalizedName; + if ((string) $name !== $normalizedName) { + @trigger_error(sprintf('Parameter names will be made case sensitive in Symfony 4.0. Using "%s" instead of "%s" is deprecated since version 3.4.', $name, $normalizedName), E_USER_DEPRECATED); + } + } else { + $normalizedName = $this->normalizedParameterNames[$normalizedName] = (string) $name; + } + + return $normalizedName; + } + /** * Gets the default parameters. * diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_as_files.txt b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_as_files.txt index 3b80a904d3e9d..2793610bae8ca 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_as_files.txt +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_as_files.txt @@ -338,7 +338,7 @@ class Container%s extends Container public function getParameter($name) { if (!(isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters))) { - $name = strtolower($name); + $name = $this->normalizeParameterName($name); if (!(isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters))) { throw new InvalidArgumentException(sprintf('The parameter "%s" must be defined.', $name)); @@ -356,7 +356,7 @@ class Container%s extends Container */ public function hasParameter($name) { - $name = strtolower($name); + $name = $this->normalizeParameterName($name); return isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters); } @@ -402,6 +402,22 @@ class Container%s extends Container throw new InvalidArgumentException(sprintf('The dynamic parameter "%s" must be defined.', $name)); } + private $normalizedParameterNames = array(); + + private function normalizeParameterName($name) + { + if (isset($this->normalizedParameterNames[$normalizedName = strtolower($name)]) || isset($this->parameters[$normalizedName]) || array_key_exists($normalizedName, $this->parameters)) { + $normalizedName = isset($this->normalizedParameterNames[$normalizedName]) ? $this->normalizedParameterNames[$normalizedName] : $normalizedName; + if ((string) $name !== $normalizedName) { + @trigger_error(sprintf('Parameter names will be made case sensitive in Symfony 4.0. Using "%s" instead of "%s" is deprecated since version 3.4.', $name, $normalizedName), E_USER_DEPRECATED); + } + } else { + $normalizedName = $this->normalizedParameterNames[$normalizedName] = (string) $name; + } + + return $normalizedName; + } + /** * Gets the default parameters. * diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_compiled.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_compiled.php index b01733cabfdd1..e77bc565792a8 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_compiled.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_compiled.php @@ -341,7 +341,7 @@ protected function getServiceFromStaticMethodService() public function getParameter($name) { if (!(isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters))) { - $name = strtolower($name); + $name = $this->normalizeParameterName($name); if (!(isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters))) { throw new InvalidArgumentException(sprintf('The parameter "%s" must be defined.', $name)); @@ -359,7 +359,7 @@ public function getParameter($name) */ public function hasParameter($name) { - $name = strtolower($name); + $name = $this->normalizeParameterName($name); return isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters); } @@ -405,6 +405,22 @@ private function getDynamicParameter($name) throw new InvalidArgumentException(sprintf('The dynamic parameter "%s" must be defined.', $name)); } + private $normalizedParameterNames = array(); + + private function normalizeParameterName($name) + { + if (isset($this->normalizedParameterNames[$normalizedName = strtolower($name)]) || isset($this->parameters[$normalizedName]) || array_key_exists($normalizedName, $this->parameters)) { + $normalizedName = isset($this->normalizedParameterNames[$normalizedName]) ? $this->normalizedParameterNames[$normalizedName] : $normalizedName; + if ((string) $name !== $normalizedName) { + @trigger_error(sprintf('Parameter names will be made case sensitive in Symfony 4.0. Using "%s" instead of "%s" is deprecated since version 3.4.', $name, $normalizedName), E_USER_DEPRECATED); + } + } else { + $normalizedName = $this->normalizedParameterNames[$normalizedName] = (string) $name; + } + + return $normalizedName; + } + /** * Gets the default parameters. * diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_array_params.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_array_params.php index 92db92cc4ef90..9e59a892e350d 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_array_params.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_array_params.php @@ -86,7 +86,7 @@ protected function getBarService() public function getParameter($name) { if (!(isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters))) { - $name = strtolower($name); + $name = $this->normalizeParameterName($name); if (!(isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters))) { throw new InvalidArgumentException(sprintf('The parameter "%s" must be defined.', $name)); @@ -104,7 +104,7 @@ public function getParameter($name) */ public function hasParameter($name) { - $name = strtolower($name); + $name = $this->normalizeParameterName($name); return isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters); } @@ -160,6 +160,22 @@ private function getDynamicParameter($name) return $this->dynamicParameters[$name] = $value; } + private $normalizedParameterNames = array(); + + private function normalizeParameterName($name) + { + if (isset($this->normalizedParameterNames[$normalizedName = strtolower($name)]) || isset($this->parameters[$normalizedName]) || array_key_exists($normalizedName, $this->parameters)) { + $normalizedName = isset($this->normalizedParameterNames[$normalizedName]) ? $this->normalizedParameterNames[$normalizedName] : $normalizedName; + if ((string) $name !== $normalizedName) { + @trigger_error(sprintf('Parameter names will be made case sensitive in Symfony 4.0. Using "%s" instead of "%s" is deprecated since version 3.4.', $name, $normalizedName), E_USER_DEPRECATED); + } + } else { + $normalizedName = $this->normalizedParameterNames[$normalizedName] = (string) $name; + } + + return $normalizedName; + } + /** * Gets the default parameters. * diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services2.xml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services2.xml index f1ac14dd5d343..0d2d6699490ba 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services2.xml +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services2.xml @@ -5,7 +5,7 @@ xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd"> a string - bar + bar 0 4 @@ -23,7 +23,7 @@ bar - + value PHP_EOL diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services2.yml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services2.yml index 7ab302bcb9f9a..e05d69d77e321 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services2.yml +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services2.yml @@ -1,5 +1,5 @@ parameters: - FOO: bar + foo: bar values: - true - false @@ -9,5 +9,5 @@ parameters: bar: foo escape: '@@escapeme' foo_bar: '@foo_bar' - MixedCase: + mixedcase: MixedCaseKey: value diff --git a/src/Symfony/Component/DependencyInjection/Tests/ParameterBag/EnvPlaceholderParameterBagTest.php b/src/Symfony/Component/DependencyInjection/Tests/ParameterBag/EnvPlaceholderParameterBagTest.php index 01fcd2c3ef10b..9abfb45d6ef9d 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/ParameterBag/EnvPlaceholderParameterBagTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/ParameterBag/EnvPlaceholderParameterBagTest.php @@ -115,18 +115,18 @@ public function testResolveEnvCastsIntToString() { $bag = new EnvPlaceholderParameterBag(); $bag->get('env(INT_VAR)'); - $bag->set('env(Int_Var)', 2); + $bag->set('env(INT_VAR)', 2); $bag->resolve(); - $this->assertSame('2', $bag->all()['env(int_var)']); + $this->assertSame('2', $bag->all()['env(INT_VAR)']); } public function testResolveEnvAllowsNull() { $bag = new EnvPlaceholderParameterBag(); $bag->get('env(NULL_VAR)'); - $bag->set('env(Null_Var)', null); + $bag->set('env(NULL_VAR)', null); $bag->resolve(); - $this->assertNull($bag->all()['env(null_var)']); + $this->assertNull($bag->all()['env(NULL_VAR)']); } /** @@ -137,7 +137,7 @@ public function testResolveThrowsOnBadDefaultValue() { $bag = new EnvPlaceholderParameterBag(); $bag->get('env(ARRAY_VAR)'); - $bag->set('env(Array_Var)', array()); + $bag->set('env(ARRAY_VAR)', array()); $bag->resolve(); } @@ -148,7 +148,7 @@ public function testGetEnvAllowsNull() $bag->get('env(NULL_VAR)'); $bag->resolve(); - $this->assertNull($bag->all()['env(null_var)']); + $this->assertNull($bag->all()['env(NULL_VAR)']); } /** diff --git a/src/Symfony/Component/DependencyInjection/Tests/ParameterBag/ParameterBagTest.php b/src/Symfony/Component/DependencyInjection/Tests/ParameterBag/ParameterBagTest.php index 391e0eb3ff7de..3bac9ca64e20d 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/ParameterBag/ParameterBagTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/ParameterBag/ParameterBagTest.php @@ -46,8 +46,6 @@ public function testRemove() )); $bag->remove('foo'); $this->assertEquals(array('bar' => 'bar'), $bag->all(), '->remove() removes a parameter'); - $bag->remove('BAR'); - $this->assertEquals(array(), $bag->all(), '->remove() converts key to lowercase before removing'); } public function testGetSet() @@ -59,10 +57,6 @@ public function testGetSet() $bag->set('foo', 'baz'); $this->assertEquals('baz', $bag->get('foo'), '->set() overrides previously set parameter'); - $bag->set('Foo', 'baz1'); - $this->assertEquals('baz1', $bag->get('foo'), '->set() converts the key to lowercase'); - $this->assertEquals('baz1', $bag->get('FOO'), '->get() converts the key to lowercase'); - try { $bag->get('baba'); $this->fail('->get() throws an Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException if the key does not exist'); @@ -109,10 +103,33 @@ public function testHas() { $bag = new ParameterBag(array('foo' => 'bar')); $this->assertTrue($bag->has('foo'), '->has() returns true if a parameter is defined'); - $this->assertTrue($bag->has('Foo'), '->has() converts the key to lowercase'); $this->assertFalse($bag->has('bar'), '->has() returns false if a parameter is not defined'); } + /** + * @group legacy + * @expectedDeprecation Parameter names will be made case sensitive in Symfony 4.0. Using "BAR" instead of "bar" is deprecated since version 3.4. + * @expectedDeprecation Parameter names will be made case sensitive in Symfony 4.0. Using "Foo" instead of "foo" is deprecated since version 3.4. + * @expectedDeprecation Parameter names will be made case sensitive in Symfony 4.0. Using "FOO" instead of "foo" is deprecated since version 3.4. + * @expectedDeprecation Parameter names will be made case sensitive in Symfony 4.0. Using "Foo" instead of "foo" is deprecated since version 3.4. + */ + public function testMixedCase() + { + $bag = new ParameterBag(array( + 'foo' => 'foo', + 'bar' => 'bar', + )); + + $bag->remove('BAR'); + $this->assertEquals(array('foo' => 'foo'), $bag->all(), '->remove() converts key to lowercase before removing'); + + $bag->set('Foo', 'baz1'); + $this->assertEquals('baz1', $bag->get('foo'), '->set() converts the key to lowercase'); + $this->assertEquals('baz1', $bag->get('FOO'), '->get() converts the key to lowercase'); + + $this->assertTrue($bag->has('Foo'), '->has() converts the key to lowercase'); + } + public function testResolveValue() { $bag = new ParameterBag(array()); From 8cbf0947027211882ba9e29a79b72cbc98b9f4d0 Mon Sep 17 00:00:00 2001 From: Robin Chalas Date: Tue, 15 Aug 2017 11:12:55 +0200 Subject: [PATCH 0626/1099] [Console] Remove useless http-kernel dev dep --- .../Tests/DependencyInjection/AddConsoleCommandPassTest.php | 5 ----- src/Symfony/Component/Console/composer.json | 1 - 2 files changed, 6 deletions(-) diff --git a/src/Symfony/Component/Console/Tests/DependencyInjection/AddConsoleCommandPassTest.php b/src/Symfony/Component/Console/Tests/DependencyInjection/AddConsoleCommandPassTest.php index 0cf4631754522..3423c5d9e92e9 100644 --- a/src/Symfony/Component/Console/Tests/DependencyInjection/AddConsoleCommandPassTest.php +++ b/src/Symfony/Component/Console/Tests/DependencyInjection/AddConsoleCommandPassTest.php @@ -16,7 +16,6 @@ use Symfony\Component\Console\Command\Command; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Definition; -use Symfony\Component\HttpKernel\Bundle\Bundle; class AddConsoleCommandPassTest extends TestCase { @@ -122,7 +121,3 @@ public function testProcessPrivateServicesWithSameCommand() class MyCommand extends Command { } - -class ExtensionPresentBundle extends Bundle -{ -} diff --git a/src/Symfony/Component/Console/composer.json b/src/Symfony/Component/Console/composer.json index d4fef1ea5856c..415b9e096d2ac 100644 --- a/src/Symfony/Component/Console/composer.json +++ b/src/Symfony/Component/Console/composer.json @@ -22,7 +22,6 @@ }, "require-dev": { "symfony/config": "~3.3", - "symfony/http-kernel": "~2.8|~3.0", "symfony/event-dispatcher": "~2.8|~3.0", "symfony/dependency-injection": "~3.3", "symfony/filesystem": "~2.8|~3.0", From 0a3dc11af9dab60754745b6d5ab994151e2f5e52 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Tue, 15 Aug 2017 10:54:46 +0200 Subject: [PATCH 0627/1099] [HttpKernel] Clean test directory on tear down --- src/Symfony/Component/HttpKernel/Tests/KernelTest.php | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/Symfony/Component/HttpKernel/Tests/KernelTest.php b/src/Symfony/Component/HttpKernel/Tests/KernelTest.php index dad52401daf39..a6d6285481015 100644 --- a/src/Symfony/Component/HttpKernel/Tests/KernelTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/KernelTest.php @@ -13,6 +13,7 @@ use PHPUnit\Framework\TestCase; use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\Filesystem\Filesystem; use Symfony\Component\HttpKernel\Bundle\BundleInterface; use Symfony\Component\HttpKernel\Config\EnvParametersResource; use Symfony\Component\HttpKernel\Kernel; @@ -25,6 +26,12 @@ class KernelTest extends TestCase { + public static function tearDownAfterClass() + { + $fs = new Filesystem(); + $fs->remove(__DIR__.'/Fixtures/cache'); + } + public function testConstructor() { $env = 'test_env'; From 22a6642632133d3ee7b288da78199bf9db5ddcf2 Mon Sep 17 00:00:00 2001 From: Johannes Goslar Date: Tue, 15 Aug 2017 14:38:43 +0200 Subject: [PATCH 0628/1099] Update JsonBundleReader.php --- .../Intl/Data/Bundle/Reader/JsonBundleReader.php | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/src/Symfony/Component/Intl/Data/Bundle/Reader/JsonBundleReader.php b/src/Symfony/Component/Intl/Data/Bundle/Reader/JsonBundleReader.php index 84644b9fe7f2c..90012a7ad64ab 100644 --- a/src/Symfony/Component/Intl/Data/Bundle/Reader/JsonBundleReader.php +++ b/src/Symfony/Component/Intl/Data/Bundle/Reader/JsonBundleReader.php @@ -32,17 +32,15 @@ public function read($path, $locale) if (!file_exists($fileName)) { throw new ResourceBundleNotFoundException(sprintf( - 'The resource bundle "%s/%s.json" does not exist.', - $path, - $locale + 'The resource bundle "%s" does not exist.', + $fileName )); } if (!is_file($fileName)) { throw new RuntimeException(sprintf( - 'The resource bundle "%s/%s.json" is not a file.', - $path, - $locale + 'The resource bundle "%s" is not a file.', + $fileName )); } @@ -50,9 +48,8 @@ public function read($path, $locale) if (null === $data) { throw new RuntimeException(sprintf( - 'The resource bundle "%s/%s.json" contains invalid JSON: %s', - $path, - $locale, + 'The resource bundle "%s" contains invalid JSON: %s', + $fileName, self::getLastJsonError() )); } From 1a5fd79c21cf43274e517884fdb5b187038bff64 Mon Sep 17 00:00:00 2001 From: "Alexander M. Turek" Date: Tue, 15 Aug 2017 15:11:19 +0200 Subject: [PATCH 0629/1099] Allow phpdocumentor/reflection-docblock 4. --- composer.json | 2 +- src/Symfony/Bundle/FrameworkBundle/composer.json | 2 +- src/Symfony/Component/PropertyInfo/composer.json | 2 +- src/Symfony/Component/Serializer/composer.json | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/composer.json b/composer.json index 00faa0845d422..ff894a349e227 100644 --- a/composer.json +++ b/composer.json @@ -98,7 +98,7 @@ "symfony/phpunit-bridge": "~3.2", "symfony/polyfill-apcu": "~1.1", "symfony/security-acl": "~2.8|~3.0", - "phpdocumentor/reflection-docblock": "^3.0", + "phpdocumentor/reflection-docblock": "^3.0|^4.0", "sensio/framework-extra-bundle": "^3.0.2" }, "conflict": { diff --git a/src/Symfony/Bundle/FrameworkBundle/composer.json b/src/Symfony/Bundle/FrameworkBundle/composer.json index c605471911974..f542a5a2a8f9a 100644 --- a/src/Symfony/Bundle/FrameworkBundle/composer.json +++ b/src/Symfony/Bundle/FrameworkBundle/composer.json @@ -55,7 +55,7 @@ "symfony/property-info": "~3.3", "symfony/web-link": "~3.3", "doctrine/annotations": "~1.0", - "phpdocumentor/reflection-docblock": "^3.0", + "phpdocumentor/reflection-docblock": "^3.0|^4.0", "twig/twig": "~1.34|~2.4", "sensio/framework-extra-bundle": "^3.0.2" }, diff --git a/src/Symfony/Component/PropertyInfo/composer.json b/src/Symfony/Component/PropertyInfo/composer.json index 13aebfbf0e31e..d068a5ff6a3c3 100644 --- a/src/Symfony/Component/PropertyInfo/composer.json +++ b/src/Symfony/Component/PropertyInfo/composer.json @@ -30,7 +30,7 @@ "symfony/serializer": "~2.8|~3.0", "symfony/cache": "~3.1", "symfony/dependency-injection": "~3.3", - "phpdocumentor/reflection-docblock": "^3.0", + "phpdocumentor/reflection-docblock": "^3.0|^4.0", "doctrine/annotations": "~1.0" }, "conflict": { diff --git a/src/Symfony/Component/Serializer/composer.json b/src/Symfony/Component/Serializer/composer.json index cd9fd883716d7..e4ee63a730bc0 100644 --- a/src/Symfony/Component/Serializer/composer.json +++ b/src/Symfony/Component/Serializer/composer.json @@ -28,7 +28,7 @@ "doctrine/annotations": "~1.0", "symfony/dependency-injection": "~3.2", "doctrine/cache": "~1.0", - "phpdocumentor/reflection-docblock": "~3.0" + "phpdocumentor/reflection-docblock": "^3.0|^4.0" }, "conflict": { "symfony/dependency-injection": "<3.2", From 2e4e6ad62662e309605d930aa58978b1f88a6fe6 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Sat, 12 Aug 2017 11:24:07 +0200 Subject: [PATCH 0630/1099] [HttpKernel] Remove old container files --- src/Symfony/Component/HttpKernel/Kernel.php | 18 ++++++++- .../Component/HttpKernel/Tests/KernelTest.php | 40 +++++++++++++++++-- 2 files changed, 54 insertions(+), 4 deletions(-) diff --git a/src/Symfony/Component/HttpKernel/Kernel.php b/src/Symfony/Component/HttpKernel/Kernel.php index a6c31e8a3f821..8c70005d28577 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -584,6 +584,11 @@ protected function initializeContainer() file_put_contents($this->getCacheDir().'/'.$class.'Compiler.log', null !== $container ? implode("\n", $container->getCompiler()->getLog()) : ''); } } + + if ($oldContainer = file_exists($cache->getPath()) ? @include $cache->getPath() : false) { + $oldContainer = new \ReflectionClass($oldContainer); + } + $this->dumpContainer($cache, $container, $class, $this->getContainerBaseClass()); $fresh = false; @@ -592,7 +597,15 @@ protected function initializeContainer() $this->container = require $cache->getPath(); $this->container->set('kernel', $this); - if (!$fresh && $this->container->has('cache_warmer')) { + if ($fresh) { + return; + } + + if ($oldContainer && get_class($this->container) !== $oldContainer->name) { + (new Filesystem())->remove(dirname($oldContainer->getFileName())); + } + + if ($this->container->has('cache_warmer')) { $this->container->get('cache_warmer')->warmUp($this->container->getParameter('kernel.cache_dir')); } } @@ -773,6 +786,9 @@ protected function dumpContainer(ConfigCache $cache, ContainerBuilder $container @chmod($dir.$file, 0666 & ~umask()); } + // track changes made to the container directory + $container->fileExists(dirname($dir.$file)); + $cache->write($rootCode, $container->getResources()); } diff --git a/src/Symfony/Component/HttpKernel/Tests/KernelTest.php b/src/Symfony/Component/HttpKernel/Tests/KernelTest.php index 052e5766d6c7c..4392e30e652f3 100644 --- a/src/Symfony/Component/HttpKernel/Tests/KernelTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/KernelTest.php @@ -771,13 +771,38 @@ public function testSymfonyEnvironmentVariables() public function testProjectDirExtension() { - $kernel = new CustomProjectDirKernel('test', true); + $kernel = new CustomProjectDirKernel(); $kernel->boot(); $this->assertSame('foo', $kernel->getProjectDir()); $this->assertSame('foo', $kernel->getContainer()->getParameter('kernel.project_dir')); } + public function testKernelReset() + { + (new Filesystem())->remove(__DIR__.'/Fixtures/cache'); + + $kernel = new CustomProjectDirKernel(); + $kernel->boot(); + + $containerClass = get_class($kernel->getContainer()); + $containerFile = (new \ReflectionClass($kernel->getContainer()))->getFileName(); + unlink(__DIR__.'/Fixtures/cache/custom/FixturesCustomDebugProjectContainer.php.meta'); + + $kernel = new CustomProjectDirKernel(); + $kernel->boot(); + + $this->assertSame($containerClass, get_class($kernel->getContainer())); + $this->assertFileExists($containerFile); + unlink(__DIR__.'/Fixtures/cache/custom/FixturesCustomDebugProjectContainer.php.meta'); + + $kernel = new CustomProjectDirKernel(function ($container) { $container->register('foo', 'stdClass'); }); + $kernel->boot(); + + $this->assertTrue(get_class($kernel->getContainer()) !== $containerClass); + $this->assertFileNotExists($containerFile); + } + /** * Returns a mock for the BundleInterface. * @@ -878,12 +903,14 @@ public function handle(Request $request, $type = self::MASTER_REQUEST, $catch = class CustomProjectDirKernel extends Kernel { private $baseDir; + private $buildContainer; - public function __construct() + public function __construct(\Closure $buildContainer = null) { - parent::__construct('test', false); + parent::__construct('custom', true); $this->baseDir = 'foo'; + $this->buildContainer = $buildContainer; } public function registerBundles() @@ -904,4 +931,11 @@ public function getRootDir() { return __DIR__.'/Fixtures'; } + + protected function build(ContainerBuilder $container) + { + if ($build = $this->buildContainer) { + $build($container); + } + } } From adff65a60246817685de0c1a68998364c9d6ffcf Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Wed, 16 Aug 2017 10:13:36 +0200 Subject: [PATCH 0631/1099] [DI] Fix reading env vars from fastcgi params --- .../Compiler/ServiceLocatorTagPass.php | 7 ++--- .../DependencyInjection/Container.php | 5 +++- .../DependencyInjection/ContainerBuilder.php | 15 ++++++----- .../EnvPlaceholderParameterBag.php | 26 +++++++++++++++++++ .../Tests/ContainerBuilderTest.php | 24 +++++++++++------ 5 files changed, 57 insertions(+), 20 deletions(-) diff --git a/src/Symfony/Component/DependencyInjection/Compiler/ServiceLocatorTagPass.php b/src/Symfony/Component/DependencyInjection/Compiler/ServiceLocatorTagPass.php index bf9f83bbe80d0..59c5e390223ca 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/ServiceLocatorTagPass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/ServiceLocatorTagPass.php @@ -54,20 +54,17 @@ protected function processValue($value, $isRoot = false) $value->setArguments($arguments); - if ($public = $value->isPublic()) { - $value->setPublic(false); - } $id = 'service_locator.'.md5(serialize($value)); if ($isRoot) { if ($id !== $this->currentId) { - $this->container->setAlias($id, new Alias($this->currentId, $public)); + $this->container->setAlias($id, new Alias($this->currentId, false)); } return $value; } - $this->container->setDefinition($id, $value); + $this->container->setDefinition($id, $value->setPublic(false)); return new Reference($id); } diff --git a/src/Symfony/Component/DependencyInjection/Container.php b/src/Symfony/Component/DependencyInjection/Container.php index 3b0a82d80ea10..81241e3415cc8 100644 --- a/src/Symfony/Component/DependencyInjection/Container.php +++ b/src/Symfony/Component/DependencyInjection/Container.php @@ -429,7 +429,7 @@ public static function underscore($id) * * @param string $name The name of the environment variable * - * @return scalar The value to use for the provided environment variable name + * @return mixed The value to use for the provided environment variable name * * @throws EnvNotFoundException When the environment variable is not found and has no default value */ @@ -438,6 +438,9 @@ protected function getEnv($name) if (isset($this->envCache[$name]) || array_key_exists($name, $this->envCache)) { return $this->envCache[$name]; } + if (0 !== strpos($name, 'HTTP_') && isset($_SERVER[$name])) { + return $this->envCache[$name] = $_SERVER[$name]; + } if (isset($_ENV[$name])) { return $this->envCache[$name] = $_ENV[$name]; } diff --git a/src/Symfony/Component/DependencyInjection/ContainerBuilder.php b/src/Symfony/Component/DependencyInjection/ContainerBuilder.php index 555c3b09734b2..4f86cd046868f 100644 --- a/src/Symfony/Component/DependencyInjection/ContainerBuilder.php +++ b/src/Symfony/Component/DependencyInjection/ContainerBuilder.php @@ -729,9 +729,10 @@ public function compile(/*$resolveEnvPlaceholders = false*/) $bag = $this->getParameterBag(); if ($resolveEnvPlaceholders && $bag instanceof EnvPlaceholderParameterBag) { - $this->parameterBag = new ParameterBag($this->resolveEnvPlaceholders($bag->all(), true)); + $bag->resolveEnvReferences(); + $this->parameterBag = new ParameterBag($bag->all()); $this->envPlaceholders = $bag->getEnvPlaceholders(); - $this->parameterBag = $bag = new ParameterBag($this->resolveEnvPlaceholders($this->parameterBag->all())); + $this->parameterBag = $bag = new ParameterBag($this->resolveEnvPlaceholders($bag->all(), true)); } $compiler->compile($this); @@ -746,7 +747,9 @@ public function compile(/*$resolveEnvPlaceholders = false*/) parent::compile(); - $this->envPlaceholders = $bag instanceof EnvPlaceholderParameterBag ? $bag->getEnvPlaceholders() : array(); + if ($bag instanceof EnvPlaceholderParameterBag) { + $this->envPlaceholders = $bag->getEnvPlaceholders(); + } } /** @@ -1311,10 +1314,10 @@ public function resolveEnvPlaceholders($value, $format = null, array &$usedEnvs foreach ($envPlaceholders as $env => $placeholders) { foreach ($placeholders as $placeholder) { if (false !== stripos($value, $placeholder)) { - if (true === $format) { - $resolved = $bag->escapeValue($this->getEnv($env)); - } else { + if (true !== $format) { $resolved = sprintf($format, $env); + } elseif ($placeholder === $resolved = $bag->escapeValue($this->getEnv($env))) { + $resolved = $bag->all()[strtolower("env($env)")]; } $value = str_ireplace($placeholder, $resolved, $value); $usedEnvs[$env] = $env; diff --git a/src/Symfony/Component/DependencyInjection/ParameterBag/EnvPlaceholderParameterBag.php b/src/Symfony/Component/DependencyInjection/ParameterBag/EnvPlaceholderParameterBag.php index d20e53531aa3b..34f79477fa034 100644 --- a/src/Symfony/Component/DependencyInjection/ParameterBag/EnvPlaceholderParameterBag.php +++ b/src/Symfony/Component/DependencyInjection/ParameterBag/EnvPlaceholderParameterBag.php @@ -20,6 +20,7 @@ class EnvPlaceholderParameterBag extends ParameterBag { private $envPlaceholders = array(); + private $resolveEnvReferences = false; /** * {@inheritdoc} @@ -101,4 +102,29 @@ public function resolve() } } } + + /** + * Replaces "%env(FOO)%" references by their placeholder, keeping regular "%parameters%" references as is. + */ + public function resolveEnvReferences() + { + $this->resolveEnvReferences = true; + try { + $this->resolve(); + } finally { + $this->resolveEnvReferences = false; + } + } + + /** + * {@inheritdoc} + */ + public function resolveString($value, array $resolving = array()) + { + if ($this->resolveEnvReferences) { + return preg_replace_callback('/%%|%(env\([^%\s]+\))%/', function ($match) { return isset($match[1]) ? $this->get($match[1]) : '%%'; }, $value); + } + + return parent::resolveString($value, $resolving); + } } diff --git a/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php b/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php index 51397309b7dce..7ab2e7c6f6c31 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php @@ -603,29 +603,37 @@ public function testMergeThrowsExceptionForDuplicateAutomaticInstanceofDefinitio public function testResolveEnvValues() { $_ENV['DUMMY_ENV_VAR'] = 'du%%y'; + $_SERVER['DUMMY_SERVER_VAR'] = 'ABC'; + $_SERVER['HTTP_DUMMY_VAR'] = 'DEF'; $container = new ContainerBuilder(); - $container->setParameter('bar', '%% %env(DUMMY_ENV_VAR)%'); + $container->setParameter('bar', '%% %env(DUMMY_ENV_VAR)% %env(DUMMY_SERVER_VAR)% %env(HTTP_DUMMY_VAR)%'); + $container->setParameter('env(HTTP_DUMMY_VAR)', '123'); - $this->assertSame('%% du%%%%y', $container->resolveEnvPlaceholders('%bar%', true)); + $this->assertSame('%% du%%%%y ABC 123', $container->resolveEnvPlaceholders('%bar%', true)); - unset($_ENV['DUMMY_ENV_VAR']); + unset($_ENV['DUMMY_ENV_VAR'], $_SERVER['DUMMY_SERVER_VAR'], $_SERVER['HTTP_DUMMY_VAR']); } public function testCompileWithResolveEnv() { - $_ENV['DUMMY_ENV_VAR'] = 'du%%y'; + putenv('DUMMY_ENV_VAR=du%%y'); + $_SERVER['DUMMY_SERVER_VAR'] = 'ABC'; + $_SERVER['HTTP_DUMMY_VAR'] = 'DEF'; $container = new ContainerBuilder(); $container->setParameter('env(FOO)', 'Foo'); - $container->setParameter('bar', '%% %env(DUMMY_ENV_VAR)%'); + $container->setParameter('bar', '%% %env(DUMMY_ENV_VAR)% %env(DUMMY_SERVER_VAR)% %env(HTTP_DUMMY_VAR)%'); $container->setParameter('foo', '%env(FOO)%'); + $container->setParameter('baz', '%foo%'); + $container->setParameter('env(HTTP_DUMMY_VAR)', '123'); $container->compile(true); - $this->assertSame('% du%%y', $container->getParameter('bar')); - $this->assertSame('Foo', $container->getParameter('foo')); + $this->assertSame('% du%%y ABC 123', $container->getParameter('bar')); + $this->assertSame('Foo', $container->getParameter('baz')); - unset($_ENV['DUMMY_ENV_VAR']); + unset($_SERVER['DUMMY_SERVER_VAR'], $_SERVER['HTTP_DUMMY_VAR']); + putenv('DUMMY_ENV_VAR'); } /** From 046f8c101bdca3b6fc9a1559935e219815d80c77 Mon Sep 17 00:00:00 2001 From: Dany Maillard Date: Sat, 5 Aug 2017 01:29:29 +0200 Subject: [PATCH 0632/1099] [VarDumper] Fix interval caster with PT3600S-like spec --- .../Component/VarDumper/Caster/DateCaster.php | 13 ++++++++----- .../VarDumper/Tests/Caster/DateCasterTest.php | 8 ++++++++ 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/src/Symfony/Component/VarDumper/Caster/DateCaster.php b/src/Symfony/Component/VarDumper/Caster/DateCaster.php index 5a59ca48e1e7a..68290930bfd91 100644 --- a/src/Symfony/Component/VarDumper/Caster/DateCaster.php +++ b/src/Symfony/Component/VarDumper/Caster/DateCaster.php @@ -52,11 +52,14 @@ public static function castInterval(\DateInterval $interval, array $a, Stub $stu private static function formatInterval(\DateInterval $i) { - $format = '%R ' - .($i->y ? '%yy ' : '') - .($i->m ? '%mm ' : '') - .($i->d ? '%dd ' : '') - ; + $format = '%R '; + + if ($i->y === 0 && $i->m === 0 && ($i->h >= 24 || $i->i >= 60 || $i->s >= 60)) { + $i = date_diff($d = new \DateTime(), date_add(clone $d, $i)); // recalculate carry over points + $format .= 0 < $i->days ? '%ad ' : ''; + } else { + $format .= ($i->y ? '%yy ' : '').($i->m ? '%mm ' : '').($i->d ? '%dd ' : ''); + } if (\PHP_VERSION_ID >= 70100 && isset($i->f)) { $format .= $i->h || $i->i || $i->s || $i->f ? '%H:%I:%S.%F' : ''; diff --git a/src/Symfony/Component/VarDumper/Tests/Caster/DateCasterTest.php b/src/Symfony/Component/VarDumper/Tests/Caster/DateCasterTest.php index d470bbc19165f..3f325f5d6ee44 100644 --- a/src/Symfony/Component/VarDumper/Tests/Caster/DateCasterTest.php +++ b/src/Symfony/Component/VarDumper/Tests/Caster/DateCasterTest.php @@ -173,6 +173,10 @@ public function provideIntervals() array('P5M', 0, '+ 5m', null), array('P6Y', 0, '+ 6y', null), array('P1Y2M3DT4H5M6S', 0, '+ 1y 2m 3d 04:05:06'.$ms, null), + array('PT1M60S', 0, '+ 00:02:00'.$ms, null), + array('PT1H60M', 0, '+ 02:00:00'.$ms, null), + array('P1DT24H', 0, '+ 2d', null), + array('P1M32D', 0, '+ 1m 32d', null), array('PT0S', 1, '0s', '0s'), array('PT1S', 1, '- 00:00:01'.$ms, '-1s'), @@ -182,6 +186,10 @@ public function provideIntervals() array('P5M', 1, '- 5m', null), array('P6Y', 1, '- 6y', null), array('P1Y2M3DT4H5M6S', 1, '- 1y 2m 3d 04:05:06'.$ms, null), + array('PT1M60S', 1, '- 00:02:00'.$ms, null), + array('PT1H60M', 1, '- 02:00:00'.$ms, null), + array('P1DT24H', 1, '- 2d', null), + array('P1M32D', 1, '- 1m 32d', null), ); } From 06bbee862f91cd2e6862132cab148b809a5e46d4 Mon Sep 17 00:00:00 2001 From: Oleg Voronkovich Date: Sun, 18 Jun 2017 20:41:58 +0300 Subject: [PATCH 0633/1099] [Routing] Use "controller" keyword for configuring routes controllers --- src/Symfony/Component/Routing/CHANGELOG.md | 1 + .../Routing/Loader/XmlFileLoader.php | 10 +++ .../Routing/Loader/YamlFileLoader.php | 13 +++- .../Loader/schema/routing/routing-1.0.xsd | 2 + .../controller/import__controller.xml | 10 +++ .../controller/import__controller.yml | 4 + .../Fixtures/controller/import_controller.xml | 8 ++ .../Fixtures/controller/import_controller.yml | 3 + .../controller/import_override_defaults.xml | 10 +++ .../controller/import_override_defaults.yml | 5 ++ .../Fixtures/controller/override_defaults.xml | 10 +++ .../Fixtures/controller/override_defaults.yml | 5 ++ .../Tests/Fixtures/controller/routing.xml | 14 ++++ .../Tests/Fixtures/controller/routing.yml | 11 +++ .../Tests/Loader/XmlFileLoaderTest.php | 74 +++++++++++++++++++ .../Tests/Loader/YamlFileLoaderTest.php | 74 +++++++++++++++++++ 16 files changed, 253 insertions(+), 1 deletion(-) create mode 100644 src/Symfony/Component/Routing/Tests/Fixtures/controller/import__controller.xml create mode 100644 src/Symfony/Component/Routing/Tests/Fixtures/controller/import__controller.yml create mode 100644 src/Symfony/Component/Routing/Tests/Fixtures/controller/import_controller.xml create mode 100644 src/Symfony/Component/Routing/Tests/Fixtures/controller/import_controller.yml create mode 100644 src/Symfony/Component/Routing/Tests/Fixtures/controller/import_override_defaults.xml create mode 100644 src/Symfony/Component/Routing/Tests/Fixtures/controller/import_override_defaults.yml create mode 100644 src/Symfony/Component/Routing/Tests/Fixtures/controller/override_defaults.xml create mode 100644 src/Symfony/Component/Routing/Tests/Fixtures/controller/override_defaults.yml create mode 100644 src/Symfony/Component/Routing/Tests/Fixtures/controller/routing.xml create mode 100644 src/Symfony/Component/Routing/Tests/Fixtures/controller/routing.yml diff --git a/src/Symfony/Component/Routing/CHANGELOG.md b/src/Symfony/Component/Routing/CHANGELOG.md index b79318e29a261..33faeb73aa607 100644 --- a/src/Symfony/Component/Routing/CHANGELOG.md +++ b/src/Symfony/Component/Routing/CHANGELOG.md @@ -6,6 +6,7 @@ CHANGELOG * Added support for prioritized routing loaders. * Add matched and default parameters to redirect responses + * Added support for a `controller` keyword for configuring route controllers in YAML and XML configurations. 3.3.0 ----- diff --git a/src/Symfony/Component/Routing/Loader/XmlFileLoader.php b/src/Symfony/Component/Routing/Loader/XmlFileLoader.php index 8a6e8ce35989f..6a3322bb8cebc 100644 --- a/src/Symfony/Component/Routing/Loader/XmlFileLoader.php +++ b/src/Symfony/Component/Routing/Loader/XmlFileLoader.php @@ -229,6 +229,16 @@ private function parseConfigs(\DOMElement $node, $path) } } + if ($controller = $node->getAttribute('controller')) { + if (isset($defaults['_controller'])) { + $name = $node->hasAttribute('id') ? sprintf('"%s"', $node->getAttribute('id')) : sprintf('the "%s" tag', $node->tagName); + + throw new \InvalidArgumentException(sprintf('The routing file "%s" must not specify both the "controller" attribute and the defaults key "_controller" for %s.', $path, $name)); + } + + $defaults['_controller'] = $controller; + } + return array($defaults, $requirements, $options, $condition); } diff --git a/src/Symfony/Component/Routing/Loader/YamlFileLoader.php b/src/Symfony/Component/Routing/Loader/YamlFileLoader.php index 31314011b95b4..5a087513215a6 100644 --- a/src/Symfony/Component/Routing/Loader/YamlFileLoader.php +++ b/src/Symfony/Component/Routing/Loader/YamlFileLoader.php @@ -27,7 +27,7 @@ class YamlFileLoader extends FileLoader { private static $availableKeys = array( - 'resource', 'type', 'prefix', 'path', 'host', 'schemes', 'methods', 'defaults', 'requirements', 'options', 'condition', + 'resource', 'type', 'prefix', 'path', 'host', 'schemes', 'methods', 'defaults', 'requirements', 'options', 'condition', 'controller', ); private $yamlParser; @@ -115,6 +115,10 @@ protected function parseRoute(RouteCollection $collection, $name, array $config, $methods = isset($config['methods']) ? $config['methods'] : array(); $condition = isset($config['condition']) ? $config['condition'] : null; + if (isset($config['controller'])) { + $defaults['_controller'] = $config['controller']; + } + $route = new Route($config['path'], $defaults, $requirements, $options, $host, $schemes, $methods, $condition); $collection->add($name, $route); @@ -140,6 +144,10 @@ protected function parseImport(RouteCollection $collection, array $config, $path $schemes = isset($config['schemes']) ? $config['schemes'] : null; $methods = isset($config['methods']) ? $config['methods'] : null; + if (isset($config['controller'])) { + $defaults['_controller'] = $config['controller']; + } + $this->setCurrentDir(dirname($path)); $subCollection = $this->import($config['resource'], $type, false, $file); @@ -203,5 +211,8 @@ protected function validate($config, $name, $path) $name, $path )); } + if (isset($config['controller']) && isset($config['defaults']['_controller'])) { + throw new \InvalidArgumentException(sprintf('The routing file "%s" must not specify both the "controller" key and the defaults key "_controller" for "%s".', $path, $name)); + } } } diff --git a/src/Symfony/Component/Routing/Loader/schema/routing/routing-1.0.xsd b/src/Symfony/Component/Routing/Loader/schema/routing/routing-1.0.xsd index 92d4ae2078777..a97111aaa55e3 100644 --- a/src/Symfony/Component/Routing/Loader/schema/routing/routing-1.0.xsd +++ b/src/Symfony/Component/Routing/Loader/schema/routing/routing-1.0.xsd @@ -41,6 +41,7 @@ + @@ -52,6 +53,7 @@ + diff --git a/src/Symfony/Component/Routing/Tests/Fixtures/controller/import__controller.xml b/src/Symfony/Component/Routing/Tests/Fixtures/controller/import__controller.xml new file mode 100644 index 0000000000000..bbe727d41be36 --- /dev/null +++ b/src/Symfony/Component/Routing/Tests/Fixtures/controller/import__controller.xml @@ -0,0 +1,10 @@ + + + + + FrameworkBundle:Template:template + + diff --git a/src/Symfony/Component/Routing/Tests/Fixtures/controller/import__controller.yml b/src/Symfony/Component/Routing/Tests/Fixtures/controller/import__controller.yml new file mode 100644 index 0000000000000..4240b74dc6d8f --- /dev/null +++ b/src/Symfony/Component/Routing/Tests/Fixtures/controller/import__controller.yml @@ -0,0 +1,4 @@ +_static: + resource: routing.yml + defaults: + _controller: FrameworkBundle:Template:template diff --git a/src/Symfony/Component/Routing/Tests/Fixtures/controller/import_controller.xml b/src/Symfony/Component/Routing/Tests/Fixtures/controller/import_controller.xml new file mode 100644 index 0000000000000..378b9ca18fa43 --- /dev/null +++ b/src/Symfony/Component/Routing/Tests/Fixtures/controller/import_controller.xml @@ -0,0 +1,8 @@ + + + + + diff --git a/src/Symfony/Component/Routing/Tests/Fixtures/controller/import_controller.yml b/src/Symfony/Component/Routing/Tests/Fixtures/controller/import_controller.yml new file mode 100644 index 0000000000000..1a71c62b275eb --- /dev/null +++ b/src/Symfony/Component/Routing/Tests/Fixtures/controller/import_controller.yml @@ -0,0 +1,3 @@ +_static: + resource: routing.yml + controller: FrameworkBundle:Template:template diff --git a/src/Symfony/Component/Routing/Tests/Fixtures/controller/import_override_defaults.xml b/src/Symfony/Component/Routing/Tests/Fixtures/controller/import_override_defaults.xml new file mode 100644 index 0000000000000..e3c755a40a81c --- /dev/null +++ b/src/Symfony/Component/Routing/Tests/Fixtures/controller/import_override_defaults.xml @@ -0,0 +1,10 @@ + + + + + AppBundle:Blog:index + + diff --git a/src/Symfony/Component/Routing/Tests/Fixtures/controller/import_override_defaults.yml b/src/Symfony/Component/Routing/Tests/Fixtures/controller/import_override_defaults.yml new file mode 100644 index 0000000000000..db1ab3cbedd69 --- /dev/null +++ b/src/Symfony/Component/Routing/Tests/Fixtures/controller/import_override_defaults.yml @@ -0,0 +1,5 @@ +_static: + resource: routing.yml + controller: FrameworkBundle:Template:template + defaults: + _controller: AppBundle:Homepage:show diff --git a/src/Symfony/Component/Routing/Tests/Fixtures/controller/override_defaults.xml b/src/Symfony/Component/Routing/Tests/Fixtures/controller/override_defaults.xml new file mode 100644 index 0000000000000..f47c57b3085a1 --- /dev/null +++ b/src/Symfony/Component/Routing/Tests/Fixtures/controller/override_defaults.xml @@ -0,0 +1,10 @@ + + + + + AppBundle:Blog:index + + diff --git a/src/Symfony/Component/Routing/Tests/Fixtures/controller/override_defaults.yml b/src/Symfony/Component/Routing/Tests/Fixtures/controller/override_defaults.yml new file mode 100644 index 0000000000000..00a2c0e976789 --- /dev/null +++ b/src/Symfony/Component/Routing/Tests/Fixtures/controller/override_defaults.yml @@ -0,0 +1,5 @@ +app_blog: + path: /blog + controller: AppBundle:Homepage:show + defaults: + _controller: AppBundle:Blog:index diff --git a/src/Symfony/Component/Routing/Tests/Fixtures/controller/routing.xml b/src/Symfony/Component/Routing/Tests/Fixtures/controller/routing.xml new file mode 100644 index 0000000000000..6420138a65072 --- /dev/null +++ b/src/Symfony/Component/Routing/Tests/Fixtures/controller/routing.xml @@ -0,0 +1,14 @@ + + + + + + + AppBundle:Blog:list + + + + diff --git a/src/Symfony/Component/Routing/Tests/Fixtures/controller/routing.yml b/src/Symfony/Component/Routing/Tests/Fixtures/controller/routing.yml new file mode 100644 index 0000000000000..cb71ec3b75b79 --- /dev/null +++ b/src/Symfony/Component/Routing/Tests/Fixtures/controller/routing.yml @@ -0,0 +1,11 @@ +app_homepage: + path: / + controller: AppBundle:Homepage:show + +app_blog: + path: /blog + defaults: + _controller: AppBundle:Blog:list + +app_logout: + path: /logout diff --git a/src/Symfony/Component/Routing/Tests/Loader/XmlFileLoaderTest.php b/src/Symfony/Component/Routing/Tests/Loader/XmlFileLoaderTest.php index d24ec79a79c59..221434b0068aa 100644 --- a/src/Symfony/Component/Routing/Tests/Loader/XmlFileLoaderTest.php +++ b/src/Symfony/Component/Routing/Tests/Loader/XmlFileLoaderTest.php @@ -287,4 +287,78 @@ public function testNullValuesInMap() $route->getDefault('map') ); } + + public function testLoadRouteWithControllerAttribute() + { + $loader = new XmlFileLoader(new FileLocator(array(__DIR__.'/../Fixtures/controller'))); + $routeCollection = $loader->load('routing.xml'); + + $route = $routeCollection->get('app_homepage'); + + $this->assertSame('AppBundle:Homepage:show', $route->getDefault('_controller')); + } + + public function testLoadRouteWithoutControllerAttribute() + { + $loader = new XmlFileLoader(new FileLocator(array(__DIR__.'/../Fixtures/controller'))); + $routeCollection = $loader->load('routing.xml'); + + $route = $routeCollection->get('app_logout'); + + $this->assertNull($route->getDefault('_controller')); + } + + public function testLoadRouteWithControllerSetInDefaults() + { + $loader = new XmlFileLoader(new FileLocator(array(__DIR__.'/../Fixtures/controller'))); + $routeCollection = $loader->load('routing.xml'); + + $route = $routeCollection->get('app_blog'); + + $this->assertSame('AppBundle:Blog:list', $route->getDefault('_controller')); + } + + /** + * @expectedException \InvalidArgumentException + * @expectedExceptionMessageRegExp /The routing file "[^"]*" must not specify both the "controller" attribute and the defaults key "_controller" for "app_blog"/ + */ + public function testOverrideControllerInDefaults() + { + $loader = new XmlFileLoader(new FileLocator(array(__DIR__.'/../Fixtures/controller'))); + $loader->load('override_defaults.xml'); + } + + /** + * @dataProvider provideFilesImportingRoutesWithControllers + */ + public function testImportRouteWithController($file) + { + $loader = new XmlFileLoader(new FileLocator(array(__DIR__.'/../Fixtures/controller'))); + $routeCollection = $loader->load($file); + + $route = $routeCollection->get('app_homepage'); + $this->assertSame('FrameworkBundle:Template:template', $route->getDefault('_controller')); + + $route = $routeCollection->get('app_blog'); + $this->assertSame('FrameworkBundle:Template:template', $route->getDefault('_controller')); + + $route = $routeCollection->get('app_logout'); + $this->assertSame('FrameworkBundle:Template:template', $route->getDefault('_controller')); + } + + public function provideFilesImportingRoutesWithControllers() + { + yield array('import_controller.xml'); + yield array('import__controller.xml'); + } + + /** + * @expectedException \InvalidArgumentException + * @expectedExceptionMessageRegExp /The routing file "[^"]*" must not specify both the "controller" attribute and the defaults key "_controller" for the "import" tag/ + */ + public function testImportWithOverriddenController() + { + $loader = new XmlFileLoader(new FileLocator(array(__DIR__.'/../Fixtures/controller'))); + $loader->load('import_override_defaults.xml'); + } } diff --git a/src/Symfony/Component/Routing/Tests/Loader/YamlFileLoaderTest.php b/src/Symfony/Component/Routing/Tests/Loader/YamlFileLoaderTest.php index 8342c266dfa18..1f7fd43897ae3 100644 --- a/src/Symfony/Component/Routing/Tests/Loader/YamlFileLoaderTest.php +++ b/src/Symfony/Component/Routing/Tests/Loader/YamlFileLoaderTest.php @@ -108,4 +108,78 @@ public function testLoadWithResource() $this->assertSame('context.getMethod() == "POST"', $route->getCondition()); } } + + public function testLoadRouteWithControllerAttribute() + { + $loader = new YamlFileLoader(new FileLocator(array(__DIR__.'/../Fixtures/controller'))); + $routeCollection = $loader->load('routing.yml'); + + $route = $routeCollection->get('app_homepage'); + + $this->assertSame('AppBundle:Homepage:show', $route->getDefault('_controller')); + } + + public function testLoadRouteWithoutControllerAttribute() + { + $loader = new YamlFileLoader(new FileLocator(array(__DIR__.'/../Fixtures/controller'))); + $routeCollection = $loader->load('routing.yml'); + + $route = $routeCollection->get('app_logout'); + + $this->assertNull($route->getDefault('_controller')); + } + + public function testLoadRouteWithControllerSetInDefaults() + { + $loader = new YamlFileLoader(new FileLocator(array(__DIR__.'/../Fixtures/controller'))); + $routeCollection = $loader->load('routing.yml'); + + $route = $routeCollection->get('app_blog'); + + $this->assertSame('AppBundle:Blog:list', $route->getDefault('_controller')); + } + + /** + * @expectedException \InvalidArgumentException + * @expectedExceptionMessageRegExp /The routing file "[^"]*" must not specify both the "controller" key and the defaults key "_controller" for "app_blog"/ + */ + public function testOverrideControllerInDefaults() + { + $loader = new YamlFileLoader(new FileLocator(array(__DIR__.'/../Fixtures/controller'))); + $loader->load('override_defaults.yml'); + } + + /** + * @dataProvider provideFilesImportingRoutesWithControllers + */ + public function testImportRouteWithController($file) + { + $loader = new YamlFileLoader(new FileLocator(array(__DIR__.'/../Fixtures/controller'))); + $routeCollection = $loader->load($file); + + $route = $routeCollection->get('app_homepage'); + $this->assertSame('FrameworkBundle:Template:template', $route->getDefault('_controller')); + + $route = $routeCollection->get('app_blog'); + $this->assertSame('FrameworkBundle:Template:template', $route->getDefault('_controller')); + + $route = $routeCollection->get('app_logout'); + $this->assertSame('FrameworkBundle:Template:template', $route->getDefault('_controller')); + } + + public function provideFilesImportingRoutesWithControllers() + { + yield array('import_controller.yml'); + yield array('import__controller.yml'); + } + + /** + * @expectedException \InvalidArgumentException + * @expectedExceptionMessageRegExp /The routing file "[^"]*" must not specify both the "controller" key and the defaults key "_controller" for "_static"/ + */ + public function testImportWithOverriddenController() + { + $loader = new YamlFileLoader(new FileLocator(array(__DIR__.'/../Fixtures/controller'))); + $loader->load('import_override_defaults.yml'); + } } From 5d9ae6b56fe023f0cb3173399e3e92b3353b16c3 Mon Sep 17 00:00:00 2001 From: Robin Chalas Date: Wed, 16 Aug 2017 21:44:58 +0200 Subject: [PATCH 0634/1099] [Console] Allow commands to provide a default name for compile time registration --- src/Symfony/Component/Console/CHANGELOG.md | 1 + .../Command/DefaultNameProviderInterface.php | 26 ++++++++++++ .../AddConsoleCommandPass.php | 5 ++- .../AddConsoleCommandPassTest.php | 41 +++++++++++++++++++ 4 files changed, 71 insertions(+), 2 deletions(-) create mode 100644 src/Symfony/Component/Console/Command/DefaultNameProviderInterface.php diff --git a/src/Symfony/Component/Console/CHANGELOG.md b/src/Symfony/Component/Console/CHANGELOG.md index 0c147a605ccb2..26687bf68dfec 100644 --- a/src/Symfony/Component/Console/CHANGELOG.md +++ b/src/Symfony/Component/Console/CHANGELOG.md @@ -7,6 +7,7 @@ CHANGELOG * added `CommandLoaderInterface`, `FactoryCommandLoader` and PSR-11 `ContainerCommandLoader` for commands lazy-loading * added a case-insensitive command name matching fallback + * added `DefaultNameProviderInterface` 3.3.0 ----- diff --git a/src/Symfony/Component/Console/Command/DefaultNameProviderInterface.php b/src/Symfony/Component/Console/Command/DefaultNameProviderInterface.php new file mode 100644 index 0000000000000..af4403ed27a77 --- /dev/null +++ b/src/Symfony/Component/Console/Command/DefaultNameProviderInterface.php @@ -0,0 +1,26 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Console\Command; + +/** + * Enables lazy-loading capabilities for a Command by exposing its default name. + * + * @author Nicolas Grekas + * @author Robin Chalas + */ +interface DefaultNameProviderInterface +{ + /** + * @return string The name to use by default for calling the Command + */ + public static function getDefaultName(); +} diff --git a/src/Symfony/Component/Console/DependencyInjection/AddConsoleCommandPass.php b/src/Symfony/Component/Console/DependencyInjection/AddConsoleCommandPass.php index 67034098c218a..098057a52b064 100644 --- a/src/Symfony/Component/Console/DependencyInjection/AddConsoleCommandPass.php +++ b/src/Symfony/Component/Console/DependencyInjection/AddConsoleCommandPass.php @@ -12,6 +12,7 @@ namespace Symfony\Component\Console\DependencyInjection; use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Command\DefaultNameProviderInterface; use Symfony\Component\Console\CommandLoader\ContainerCommandLoader; use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; use Symfony\Component\DependencyInjection\Compiler\ServiceLocatorTagPass; @@ -55,7 +56,7 @@ public function process(ContainerBuilder $container) $commandId = 'console.command.'.strtolower(str_replace('\\', '_', $class)); - if (!isset($tags[0]['command'])) { + if (!isset($tags[0]['command']) && !$r->implementsInterface(DefaultNameProviderInterface::class)) { if (isset($serviceIds[$commandId]) || $container->hasAlias($commandId)) { $commandId = $commandId.'_'.$id; } @@ -69,7 +70,7 @@ public function process(ContainerBuilder $container) } $serviceIds[$commandId] = false; - $commandName = $tags[0]['command']; + $commandName = isset($tags[0]['command']) ? $tags[0]['command'] : $class::getDefaultName(); unset($tags[0]); $lazyCommandMap[$commandName] = $id; $lazyCommandRefs[$id] = new TypedReference($id, $class); diff --git a/src/Symfony/Component/Console/Tests/DependencyInjection/AddConsoleCommandPassTest.php b/src/Symfony/Component/Console/Tests/DependencyInjection/AddConsoleCommandPassTest.php index ddcee80145e53..b7fce4a5fb497 100644 --- a/src/Symfony/Component/Console/Tests/DependencyInjection/AddConsoleCommandPassTest.php +++ b/src/Symfony/Component/Console/Tests/DependencyInjection/AddConsoleCommandPassTest.php @@ -12,6 +12,7 @@ namespace Symfony\Component\Console\Tests\DependencyInjection; use PHPUnit\Framework\TestCase; +use Symfony\Component\Console\Command\DefaultNameProviderInterface; use Symfony\Component\Console\CommandLoader\ContainerCommandLoader; use Symfony\Component\Console\DependencyInjection\AddConsoleCommandPass; use Symfony\Component\Console\Command\Command; @@ -77,6 +78,38 @@ public function testProcessRegistersLazyCommands() $this->assertSame(array(array('setName', array('my:command')), array('setAliases', array(array('my:alias')))), $command->getMethodCalls()); } + public function testProcessFallsBackToDefaultName() + { + $container = new ContainerBuilder(); + $container + ->register('with-default-name', NamedCommand::class) + ->setPublic(false) + ->addTag('console.command') + ; + + $pass = new AddConsoleCommandPass(); + $pass->process($container); + + $commandLoader = $container->getDefinition('console.command_loader'); + $commandLocator = $container->getDefinition((string) $commandLoader->getArgument(0)); + + $this->assertSame(ContainerCommandLoader::class, $commandLoader->getClass()); + $this->assertSame(array('default' => 'with-default-name'), $commandLoader->getArgument(1)); + $this->assertEquals(array(array('with-default-name' => new ServiceClosureArgument(new TypedReference('with-default-name', NamedCommand::class)))), $commandLocator->getArguments()); + $this->assertSame(array('console.command.symfony_component_console_tests_dependencyinjection_namedcommand' => false), $container->getParameter('console.command.ids')); + + $container = new ContainerBuilder(); + $container + ->register('with-default-name', NamedCommand::class) + ->setPublic(false) + ->addTag('console.command', array('command' => 'new-name')) + ; + + $pass->process($container); + + $this->assertSame(array('new-name' => 'with-default-name'), $container->getDefinition('console.command_loader')->getArgument(1)); + } + public function visibilityProvider() { return array( @@ -146,3 +179,11 @@ public function testProcessPrivateServicesWithSameCommand() class MyCommand extends Command { } + +class NamedCommand extends Command implements DefaultNameProviderInterface +{ + public static function getDefaultName() + { + return 'default'; + } +} From b044ffb4a23d109d62724e7c62855f4d03d72a32 Mon Sep 17 00:00:00 2001 From: GDIBass Date: Wed, 16 Aug 2017 23:21:24 +0000 Subject: [PATCH 0635/1099] Added support for guards when advancing workflow from a command --- .../Workflow/EventListener/GuardListener.php | 6 ++++++ .../Tests/EventListener/GuardListenerTest.php | 14 ++++++++++++++ 2 files changed, 20 insertions(+) diff --git a/src/Symfony/Component/Workflow/EventListener/GuardListener.php b/src/Symfony/Component/Workflow/EventListener/GuardListener.php index 20ba04c007fc2..d7d9d2edc43a6 100644 --- a/src/Symfony/Component/Workflow/EventListener/GuardListener.php +++ b/src/Symfony/Component/Workflow/EventListener/GuardListener.php @@ -12,6 +12,7 @@ namespace Symfony\Component\Workflow\EventListener; use Symfony\Component\Security\Core\Authentication\AuthenticationTrustResolverInterface; +use Symfony\Component\Security\Core\Authentication\Token\AnonymousToken; use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface; use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface; use Symfony\Component\Security\Core\Role\RoleHierarchyInterface; @@ -55,6 +56,11 @@ private function getVariables(GuardEvent $event) { $token = $this->tokenStorage->getToken(); + if($token == null) { + $token = new AnonymousToken('secret','anon',[]); + $this->tokenStorage->setToken($token); + } + if (null !== $this->roleHierarchy) { $roles = $this->roleHierarchy->getReachableRoles($token->getRoles()); } else { diff --git a/src/Symfony/Component/Workflow/Tests/EventListener/GuardListenerTest.php b/src/Symfony/Component/Workflow/Tests/EventListener/GuardListenerTest.php index b46ee9092c573..50481654e5b51 100644 --- a/src/Symfony/Component/Workflow/Tests/EventListener/GuardListenerTest.php +++ b/src/Symfony/Component/Workflow/Tests/EventListener/GuardListenerTest.php @@ -69,6 +69,20 @@ public function testWithSupportedEventAndAccept() $this->assertTrue($event->isBlocked()); } + public function testWithNoTokenStorage() + { + $event = $this->createEvent(); + $this->tokenStorage = null; + + $this->listener->onTransition($event, 'event_name_a'); + + $this->assertFalse($event->isBlocked()); + + $this->listener->onTransition($event, 'event_name_b'); + + $this->assertTrue($event->isBlocked()); + } + private function createEvent() { $subject = new \stdClass(); From 324c208e129c6d5792486df71df09b8f6f4e8d08 Mon Sep 17 00:00:00 2001 From: GDIBass Date: Wed, 16 Aug 2017 23:27:57 +0000 Subject: [PATCH 0636/1099] Code standards update --- .../Component/Workflow/EventListener/GuardListener.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/Workflow/EventListener/GuardListener.php b/src/Symfony/Component/Workflow/EventListener/GuardListener.php index d7d9d2edc43a6..d78ae47396cf2 100644 --- a/src/Symfony/Component/Workflow/EventListener/GuardListener.php +++ b/src/Symfony/Component/Workflow/EventListener/GuardListener.php @@ -56,8 +56,8 @@ private function getVariables(GuardEvent $event) { $token = $this->tokenStorage->getToken(); - if($token == null) { - $token = new AnonymousToken('secret','anon',[]); + if ($token == null) { + $token = new AnonymousToken('secret', 'anon', array()); $this->tokenStorage->setToken($token); } From b72ced22ad80b335358a312ae82343ef1ad82d25 Mon Sep 17 00:00:00 2001 From: "Issei.M" Date: Thu, 17 Aug 2017 16:14:13 +0900 Subject: [PATCH 0637/1099] [Validator] Add a property tag for File::$maxSize --- src/Symfony/Component/Validator/Constraints/File.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Symfony/Component/Validator/Constraints/File.php b/src/Symfony/Component/Validator/Constraints/File.php index b9c06bfdb142c..7756978b35216 100644 --- a/src/Symfony/Component/Validator/Constraints/File.php +++ b/src/Symfony/Component/Validator/Constraints/File.php @@ -18,6 +18,8 @@ * @Annotation * @Target({"PROPERTY", "METHOD", "ANNOTATION"}) * + * @property int $maxSize + * * @author Bernhard Schussek */ class File extends Constraint From 8ab59cb1c2b579179ef6db318bb2c362b9f613e9 Mon Sep 17 00:00:00 2001 From: GDIBass Date: Thu, 17 Aug 2017 01:27:02 -0700 Subject: [PATCH 0638/1099] Updated if statement --- src/Symfony/Component/Workflow/EventListener/GuardListener.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/Workflow/EventListener/GuardListener.php b/src/Symfony/Component/Workflow/EventListener/GuardListener.php index d78ae47396cf2..e0c29876af0b7 100644 --- a/src/Symfony/Component/Workflow/EventListener/GuardListener.php +++ b/src/Symfony/Component/Workflow/EventListener/GuardListener.php @@ -56,7 +56,7 @@ private function getVariables(GuardEvent $event) { $token = $this->tokenStorage->getToken(); - if ($token == null) { + if (null === $token) { $token = new AnonymousToken('secret', 'anon', array()); $this->tokenStorage->setToken($token); } From 62174fda109e6a6bdd9534eb70139aeea81f4ece Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Thu, 17 Aug 2017 10:01:13 +0200 Subject: [PATCH 0639/1099] [Console] Initialize lazily to render exceptions properly --- src/Symfony/Component/Console/Application.php | 44 +++++++++++++++---- 1 file changed, 35 insertions(+), 9 deletions(-) diff --git a/src/Symfony/Component/Console/Application.php b/src/Symfony/Component/Console/Application.php index 2c57de4af3e9e..873b09e808729 100644 --- a/src/Symfony/Component/Console/Application.php +++ b/src/Symfony/Component/Console/Application.php @@ -72,6 +72,7 @@ class Application private $dispatcher; private $terminalDimensions; private $defaultCommand; + private $initialized; /** * Constructor. @@ -84,12 +85,6 @@ public function __construct($name = 'UNKNOWN', $version = 'UNKNOWN') $this->name = $name; $this->version = $version; $this->defaultCommand = 'list'; - $this->helperSet = $this->getDefaultHelperSet(); - $this->definition = $this->getDefaultInputDefinition(); - - foreach ($this->getDefaultCommands() as $command) { - $this->add($command); - } } public function setDispatcher(EventDispatcherInterface $dispatcher) @@ -189,10 +184,11 @@ public function doRun(InputInterface $input, OutputInterface $output) if (!$name) { $name = $this->defaultCommand; - $this->definition->setArguments(array_merge( - $this->definition->getArguments(), + $definition = $this->getDefinition(); + $definition->setArguments(array_merge( + $definition->getArguments(), array( - 'command' => new InputArgument('command', InputArgument::OPTIONAL, $this->definition->getArgument('command')->getDescription(), $name), + 'command' => new InputArgument('command', InputArgument::OPTIONAL, $definition->getArgument('command')->getDescription(), $name), ) )); } @@ -225,6 +221,10 @@ public function setHelperSet(HelperSet $helperSet) */ public function getHelperSet() { + if (!$this->helperSet) { + $this->helperSet = $this->getDefaultHelperSet(); + } + return $this->helperSet; } @@ -245,6 +245,10 @@ public function setDefinition(InputDefinition $definition) */ public function getDefinition() { + if (!$this->definition) { + $this->definition = $this->getDefaultInputDefinition(); + } + return $this->definition; } @@ -374,6 +378,8 @@ public function addCommands(array $commands) */ public function add(Command $command) { + $this->init(); + $command->setApplication($this); if (!$command->isEnabled()) { @@ -406,6 +412,8 @@ public function add(Command $command) */ public function get($name) { + $this->init(); + if (!isset($this->commands[$name])) { throw new \InvalidArgumentException(sprintf('The command "%s" does not exist.', $name)); } @@ -433,6 +441,8 @@ public function get($name) */ public function has($name) { + $this->init(); + return isset($this->commands[$name]); } @@ -510,6 +520,8 @@ public function findNamespace($namespace) */ public function find($name) { + $this->init(); + $allCommands = array_keys($this->commands); $expr = preg_replace_callback('{([^:]+|)}', function ($matches) { return preg_quote($matches[1]).'[^:]*'; }, $name); $commands = preg_grep('{^'.$expr.'}', $allCommands); @@ -565,6 +577,8 @@ public function find($name) */ public function all($namespace = null) { + $this->init(); + if (null === $namespace) { return $this->commands; } @@ -1151,4 +1165,16 @@ private function extractAllNamespaces($name) return $namespaces; } + + private function init() + { + if ($this->initialized) { + return; + } + $this->initialized = true; + + foreach ($this->getDefaultCommands() as $command) { + $this->add($command); + } + } } From 62c1bb5d3b20c9b1b7904f494c7da4c9cd688241 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Thu, 17 Aug 2017 11:23:46 +0200 Subject: [PATCH 0640/1099] [DI] Rererence parameter arrays when possible --- src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php | 3 +++ .../DependencyInjection/Tests/Dumper/PhpDumperTest.php | 2 +- .../Tests/Fixtures/php/services_array_params.php | 2 +- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php index cdcea02ed19d0..52a9f8aca8071 100644 --- a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php +++ b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php @@ -1430,6 +1430,9 @@ private function hasReference($id, array $arguments, $deep = false, array &$visi private function dumpValue($value, $interpolate = true) { if (is_array($value)) { + if ($value && $interpolate && false !== $param = array_search($value, $this->container->getParameterBag()->all(), true)) { + return $this->dumpValue("%$param%"); + } $code = array(); foreach ($value as $k => $v) { $code[] = sprintf('%s => %s', $this->dumpValue($k, $interpolate), $this->dumpValue($v, $interpolate)); diff --git a/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php b/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php index fc5a950af4709..e60ee91cdd658 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php @@ -607,7 +607,7 @@ public function testArrayParameters() $container->setParameter('array_1', array(123)); $container->setParameter('array_2', array(__DIR__)); $container->register('bar', 'BarClass') - ->addMethodCall('setBaz', array('%array_1%', '%array_2%', '%%array_1%%')); + ->addMethodCall('setBaz', array('%array_1%', '%array_2%', '%%array_1%%', array(123))); $container->compile(); $dumper = new PhpDumper($container); diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_array_params.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_array_params.php index 92db92cc4ef90..b8d52d69f58cc 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_array_params.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_array_params.php @@ -75,7 +75,7 @@ protected function getBarService() { $this->services['bar'] = $instance = new \BarClass(); - $instance->setBaz($this->parameters['array_1'], $this->getParameter('array_2'), '%array_1%'); + $instance->setBaz($this->parameters['array_1'], $this->getParameter('array_2'), '%array_1%', $this->parameters['array_1']); return $instance; } From 4993b1c14c8a299b8e2f92e5ac6bac20f1586216 Mon Sep 17 00:00:00 2001 From: "Konstantin.Myakshin" Date: Thu, 17 Aug 2017 13:33:52 +0300 Subject: [PATCH 0641/1099] Allow to get alternatives when ServiceNotFoundException occurs. --- .../Exception/ServiceNotFoundException.php | 7 +++++++ .../DependencyInjection/Tests/ServiceLocatorTest.php | 11 +++++++++-- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/DependencyInjection/Exception/ServiceNotFoundException.php b/src/Symfony/Component/DependencyInjection/Exception/ServiceNotFoundException.php index 0194c4f372279..5de10d3bcbfc0 100644 --- a/src/Symfony/Component/DependencyInjection/Exception/ServiceNotFoundException.php +++ b/src/Symfony/Component/DependencyInjection/Exception/ServiceNotFoundException.php @@ -22,6 +22,7 @@ class ServiceNotFoundException extends InvalidArgumentException implements NotFo { private $id; private $sourceId; + private $alternatives; public function __construct($id, $sourceId = null, \Exception $previous = null, array $alternatives = array()) { @@ -44,6 +45,7 @@ public function __construct($id, $sourceId = null, \Exception $previous = null, $this->id = $id; $this->sourceId = $sourceId; + $this->alternatives = $alternatives; } public function getId() @@ -55,4 +57,9 @@ public function getSourceId() { return $this->sourceId; } + + public function getAlternatives() + { + return $this->alternatives; + } } diff --git a/src/Symfony/Component/DependencyInjection/Tests/ServiceLocatorTest.php b/src/Symfony/Component/DependencyInjection/Tests/ServiceLocatorTest.php index 6900fd7ea4490..a1e2fff50fdbe 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/ServiceLocatorTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/ServiceLocatorTest.php @@ -12,6 +12,7 @@ namespace Symfony\Component\DependencyInjection\Tests; use PHPUnit\Framework\TestCase; +use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException; use Symfony\Component\DependencyInjection\ServiceLocator; class ServiceLocatorTest extends TestCase @@ -58,7 +59,7 @@ public function testGetDoesNotMemoize() /** * @expectedException \Psr\Container\NotFoundExceptionInterface - * @expectedExceptionMessage You have requested a non-existent service "dummy" + * @expectedExceptionMessage You have requested a non-existent service "dummy". Did you mean one of these: "foo", "bar"? */ public function testGetThrowsOnUndefinedService() { @@ -67,7 +68,13 @@ public function testGetThrowsOnUndefinedService() 'bar' => function () { return 'baz'; }, )); - $locator->get('dummy'); + try { + $locator->get('dummy'); + } catch (ServiceNotFoundException $e) { + $this->assertSame(array('foo', 'bar'), $e->getAlternatives()); + + throw $e; + } } public function testInvoke() From 773f166d5e78b5aaa012580f17a62fb1104407e9 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Thu, 17 Aug 2017 15:29:00 +0200 Subject: [PATCH 0642/1099] [VarDumper] Fix tests with phpredis 3.1.3 --- .../Component/VarDumper/Tests/Caster/RedisCasterTest.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Symfony/Component/VarDumper/Tests/Caster/RedisCasterTest.php b/src/Symfony/Component/VarDumper/Tests/Caster/RedisCasterTest.php index af038192f5c8d..80acdb66798f9 100644 --- a/src/Symfony/Component/VarDumper/Tests/Caster/RedisCasterTest.php +++ b/src/Symfony/Component/VarDumper/Tests/Caster/RedisCasterTest.php @@ -61,8 +61,7 @@ public function testConnected() EODUMP; } else { $xCast = <<<'EODUMP' -Redis { - +"socket": Redis Socket Buffer resource +Redis {%A isConnected: true host: "127.0.0.1" port: 6379 From 22b44e251fdf4c7a41a3ac85f4150addd9e82660 Mon Sep 17 00:00:00 2001 From: GDIBass Date: Thu, 17 Aug 2017 23:37:10 -0700 Subject: [PATCH 0643/1099] Changed automatic token generation to throw an exception instead --- .../Component/Workflow/EventListener/GuardListener.php | 3 +-- .../Workflow/Tests/EventListener/GuardListenerTest.php | 8 ++------ 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/src/Symfony/Component/Workflow/EventListener/GuardListener.php b/src/Symfony/Component/Workflow/EventListener/GuardListener.php index e0c29876af0b7..798af6ae61657 100644 --- a/src/Symfony/Component/Workflow/EventListener/GuardListener.php +++ b/src/Symfony/Component/Workflow/EventListener/GuardListener.php @@ -57,8 +57,7 @@ private function getVariables(GuardEvent $event) $token = $this->tokenStorage->getToken(); if (null === $token) { - $token = new AnonymousToken('secret', 'anon', array()); - $this->tokenStorage->setToken($token); + throw new \Exception("No token is set"); } if (null !== $this->roleHierarchy) { diff --git a/src/Symfony/Component/Workflow/Tests/EventListener/GuardListenerTest.php b/src/Symfony/Component/Workflow/Tests/EventListener/GuardListenerTest.php index 50481654e5b51..d72e31931360f 100644 --- a/src/Symfony/Component/Workflow/Tests/EventListener/GuardListenerTest.php +++ b/src/Symfony/Component/Workflow/Tests/EventListener/GuardListenerTest.php @@ -74,13 +74,9 @@ public function testWithNoTokenStorage() $event = $this->createEvent(); $this->tokenStorage = null; - $this->listener->onTransition($event, 'event_name_a'); - - $this->assertFalse($event->isBlocked()); + $this->expectException(\Exception::class); - $this->listener->onTransition($event, 'event_name_b'); - - $this->assertTrue($event->isBlocked()); + $this->listener->onTransition($event, 'event_name_a'); } private function createEvent() From 3a8b2eded11932f41d617c285ffeb67e5614ccc9 Mon Sep 17 00:00:00 2001 From: GDIBass Date: Thu, 17 Aug 2017 23:45:14 -0700 Subject: [PATCH 0644/1099] Code standard fixes --- src/Symfony/Component/Workflow/EventListener/GuardListener.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Symfony/Component/Workflow/EventListener/GuardListener.php b/src/Symfony/Component/Workflow/EventListener/GuardListener.php index 798af6ae61657..3e402e9280a95 100644 --- a/src/Symfony/Component/Workflow/EventListener/GuardListener.php +++ b/src/Symfony/Component/Workflow/EventListener/GuardListener.php @@ -12,7 +12,6 @@ namespace Symfony\Component\Workflow\EventListener; use Symfony\Component\Security\Core\Authentication\AuthenticationTrustResolverInterface; -use Symfony\Component\Security\Core\Authentication\Token\AnonymousToken; use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface; use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface; use Symfony\Component\Security\Core\Role\RoleHierarchyInterface; @@ -57,7 +56,7 @@ private function getVariables(GuardEvent $event) $token = $this->tokenStorage->getToken(); if (null === $token) { - throw new \Exception("No token is set"); + throw new \Exception('No token is set'); } if (null !== $this->roleHierarchy) { From 00b927322c8b47cd2eaed9a447e0504c1ff519b8 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Wed, 16 Aug 2017 23:15:56 +0200 Subject: [PATCH 0645/1099] [DI] Fix merging of env vars in configs --- .../MergeExtensionConfigurationPass.php | 71 ++++++++++++++++++- .../DependencyInjection/ContainerBuilder.php | 5 +- .../Extension/Extension.php | 16 ++++- .../EnvPlaceholderParameterBag.php | 4 +- .../MergeExtensionConfigurationPassTest.php | 49 +++++++++++-- 5 files changed, 132 insertions(+), 13 deletions(-) diff --git a/src/Symfony/Component/DependencyInjection/Compiler/MergeExtensionConfigurationPass.php b/src/Symfony/Component/DependencyInjection/Compiler/MergeExtensionConfigurationPass.php index 9434ac70b543b..bddfa8b0e6bf4 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/MergeExtensionConfigurationPass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/MergeExtensionConfigurationPass.php @@ -13,7 +13,9 @@ use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Extension\ConfigurationExtensionInterface; +use Symfony\Component\DependencyInjection\Extension\Extension; use Symfony\Component\DependencyInjection\Extension\PrependExtensionInterface; +use Symfony\Component\DependencyInjection\Parameterbag\EnvPlaceholderParameterBag; /** * Merges extension configs into the container builder. @@ -43,7 +45,10 @@ public function process(ContainerBuilder $container) // this extension was not called continue; } - $config = $container->getParameterBag()->resolveValue($config); + // EnvPlaceholderParameterBag tracks env vars when calling resolveValue(). + // Clone so that tracking is done in a dedicated bag. + $resolvingBag = clone $container->getParameterBag(); + $config = $resolvingBag->resolveValue($config); $tmpContainer = new ContainerBuilder($container->getParameterBag()); $tmpContainer->setResourceTracking($container->isTrackingResources()); @@ -58,6 +63,15 @@ public function process(ContainerBuilder $container) $extension->load($config, $tmpContainer); + if ($resolvingBag instanceof EnvPlaceholderParameterBag) { + // $resolvingBag keeps track of env vars encoutered *before* merging configs + if ($extension instanceof Extension) { + // but we don't want to keep track of env vars that are *overridden* when configs are merged + $resolvingBag = new MergeExtensionConfigurationParameterBag($extension, $resolvingBag); + } + $container->getParameterBag()->mergeEnvPlaceholders($resolvingBag); + } + $container->merge($tmpContainer); $container->getParameterBag()->add($parameters); } @@ -66,3 +80,58 @@ public function process(ContainerBuilder $container) $container->addAliases($aliases); } } + +/** + * @internal + */ +class MergeExtensionConfigurationParameterBag extends EnvPlaceholderParameterBag +{ + private $beforeProcessingEnvPlaceholders; + + public function __construct(Extension $extension, parent $resolvingBag) + { + $this->beforeProcessingEnvPlaceholders = $resolvingBag->getEnvPlaceholders(); + $config = $this->resolveEnvPlaceholders($extension->getProcessedConfigs()); + parent::__construct($this->resolveEnvReferences($config)); + } + + /** + * {@inheritdoc} + */ + public function getEnvPlaceholders() + { + // contains the list of env vars that are still used after configs have been merged + $envPlaceholders = parent::getEnvPlaceholders(); + + foreach ($envPlaceholders as $env => $placeholders) { + if (isset($this->beforeProcessingEnvPlaceholders[$env])) { + // for still-used env vars, keep track of their before-processing placeholders + $envPlaceholders[$env] += $this->beforeProcessingEnvPlaceholders[$env]; + } + } + + return $envPlaceholders; + } + + /** + * Replaces-back env placeholders to their original "%env(FOO)%" version. + */ + private function resolveEnvPlaceholders($value) + { + if (is_array($value)) { + foreach ($value as $k => $v) { + $value[$this->resolveEnvPlaceholders($k)] = $this->resolveEnvPlaceholders($v); + } + } elseif (is_string($value)) { + foreach ($this->beforeProcessingEnvPlaceholders as $env => $placeholders) { + foreach ($placeholders as $placeholder) { + if (false !== stripos($value, $placeholder)) { + $value = str_ireplace($placeholder, "%env($env)%", $value); + } + } + } + } + + return $value; + } +} diff --git a/src/Symfony/Component/DependencyInjection/ContainerBuilder.php b/src/Symfony/Component/DependencyInjection/ContainerBuilder.php index 4f86cd046868f..2e14caa1f8349 100644 --- a/src/Symfony/Component/DependencyInjection/ContainerBuilder.php +++ b/src/Symfony/Component/DependencyInjection/ContainerBuilder.php @@ -729,10 +729,9 @@ public function compile(/*$resolveEnvPlaceholders = false*/) $bag = $this->getParameterBag(); if ($resolveEnvPlaceholders && $bag instanceof EnvPlaceholderParameterBag) { - $bag->resolveEnvReferences(); - $this->parameterBag = new ParameterBag($bag->all()); + $this->parameterBag = new ParameterBag($bag->resolveEnvReferences($bag->all())); $this->envPlaceholders = $bag->getEnvPlaceholders(); - $this->parameterBag = $bag = new ParameterBag($this->resolveEnvPlaceholders($bag->all(), true)); + $this->parameterBag = $bag = new ParameterBag($this->resolveEnvPlaceholders($this->parameterBag->all(), true)); } $compiler->compile($this); diff --git a/src/Symfony/Component/DependencyInjection/Extension/Extension.php b/src/Symfony/Component/DependencyInjection/Extension/Extension.php index 117ee58c111f4..d3d382ae449de 100644 --- a/src/Symfony/Component/DependencyInjection/Extension/Extension.php +++ b/src/Symfony/Component/DependencyInjection/Extension/Extension.php @@ -25,6 +25,8 @@ */ abstract class Extension implements ExtensionInterface, ConfigurationExtensionInterface { + private $processedConfigs = array(); + /** * {@inheritdoc} */ @@ -91,7 +93,19 @@ final protected function processConfiguration(ConfigurationInterface $configurat { $processor = new Processor(); - return $processor->processConfiguration($configuration, $configs); + return $this->processedConfigs[] = $processor->processConfiguration($configuration, $configs); + } + + /** + * @internal + */ + final public function getProcessedConfigs() + { + try { + return $this->processedConfigs; + } finally { + $this->processedConfigs = array(); + } } /** diff --git a/src/Symfony/Component/DependencyInjection/ParameterBag/EnvPlaceholderParameterBag.php b/src/Symfony/Component/DependencyInjection/ParameterBag/EnvPlaceholderParameterBag.php index 34f79477fa034..8c80abf26bb76 100644 --- a/src/Symfony/Component/DependencyInjection/ParameterBag/EnvPlaceholderParameterBag.php +++ b/src/Symfony/Component/DependencyInjection/ParameterBag/EnvPlaceholderParameterBag.php @@ -106,11 +106,11 @@ public function resolve() /** * Replaces "%env(FOO)%" references by their placeholder, keeping regular "%parameters%" references as is. */ - public function resolveEnvReferences() + public function resolveEnvReferences(array $value) { $this->resolveEnvReferences = true; try { - $this->resolve(); + return $this->resolveValue($value); } finally { $this->resolveEnvReferences = false; } diff --git a/src/Symfony/Component/DependencyInjection/Tests/Compiler/MergeExtensionConfigurationPassTest.php b/src/Symfony/Component/DependencyInjection/Tests/Compiler/MergeExtensionConfigurationPassTest.php index b35521d206204..3934418474bd6 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Compiler/MergeExtensionConfigurationPassTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Compiler/MergeExtensionConfigurationPassTest.php @@ -17,6 +17,7 @@ use Symfony\Component\Config\Resource\FileResource; use Symfony\Component\DependencyInjection\Compiler\MergeExtensionConfigurationPass; use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Extension\Extension; use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag; class MergeExtensionConfigurationPassTest extends TestCase @@ -55,13 +56,10 @@ public function testExpressionLanguageProviderForwarding() public function testExtensionConfigurationIsTrackedByDefault() { - $extension = $this->getMockBuilder('Symfony\\Component\\DependencyInjection\\Extension\\Extension')->getMock(); - $extension->expects($this->once()) + $extension = $this->getMockBuilder(FooExtension::class)->setMethods(array('getConfiguration'))->getMock(); + $extension->expects($this->exactly(2)) ->method('getConfiguration') ->will($this->returnValue(new FooConfiguration())); - $extension->expects($this->any()) - ->method('getAlias') - ->will($this->returnValue('foo')); $container = new ContainerBuilder(new ParameterBag()); $container->registerExtension($extension); @@ -72,12 +70,51 @@ public function testExtensionConfigurationIsTrackedByDefault() $this->assertContains(new FileResource(__FILE__), $container->getResources(), '', false, false); } + + public function testOverriddenEnvsAreMerged() + { + $container = new ContainerBuilder(); + $container->registerExtension(new FooExtension()); + $container->prependExtensionConfig('foo', array('bar' => '%env(FOO)%')); + $container->prependExtensionConfig('foo', array('bar' => '%env(BAR)%')); + + $pass = new MergeExtensionConfigurationPass(); + $pass->process($container); + + $this->assertSame(array('FOO'), array_keys($container->getParameterBag()->getEnvPlaceholders())); + } } class FooConfiguration implements ConfigurationInterface { public function getConfigTreeBuilder() { - return new TreeBuilder(); + $treeBuilder = new TreeBuilder(); + $rootNode = $treeBuilder->root('foo'); + $rootNode + ->children() + ->scalarNode('bar')->end() + ->end(); + + return $treeBuilder; + } +} + +class FooExtension extends Extension +{ + public function getAlias() + { + return 'foo'; + } + + public function getConfiguration(array $config, ContainerBuilder $container) + { + return new FooConfiguration(); + } + + public function load(array $configs, ContainerBuilder $container) + { + $configuration = $this->getConfiguration($configs, $container); + $config = $this->processConfiguration($configuration, $configs); } } From a4fc49294eb40ae92ea99bede176f0c97086da09 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Fri, 4 Aug 2017 14:41:57 +0200 Subject: [PATCH 0646/1099] [HttpKernel][FrameworkBundle] Add RebootableInterface, fix and un-deprecate cache:clear with warmup --- UPGRADE-3.4.md | 3 + UPGRADE-4.0.md | 3 + .../Command/CacheClearCommand.php | 58 ++++++++++++------- src/Symfony/Component/HttpKernel/CHANGELOG.md | 1 + src/Symfony/Component/HttpKernel/Kernel.php | 36 +++++++----- .../HttpKernel/RebootableInterface.php | 30 ++++++++++ 6 files changed, 98 insertions(+), 33 deletions(-) create mode 100644 src/Symfony/Component/HttpKernel/RebootableInterface.php diff --git a/UPGRADE-3.4.md b/UPGRADE-3.4.md index 7164e789a808a..0c481286db2a9 100644 --- a/UPGRADE-3.4.md +++ b/UPGRADE-3.4.md @@ -143,6 +143,9 @@ HttpKernel tags: ['console.command'] ``` + * The `getCacheDir()` method of your kernel should not be called while building the container. + Use the `%kernel.cache_dir%` parameter instead. Not doing so may break the `cache:clear` command. + Process ------- diff --git a/UPGRADE-4.0.md b/UPGRADE-4.0.md index 218958d1f9688..842dca7b68ca0 100644 --- a/UPGRADE-4.0.md +++ b/UPGRADE-4.0.md @@ -510,6 +510,9 @@ HttpKernel by Symfony. Use the `%env()%` syntax to get the value of any environment variable from configuration files instead. + * The `getCacheDir()` method of your kernel should not be called while building the container. + Use the `%kernel.cache_dir%` parameter instead. Not doing so may break the `cache:clear` command. + Ldap ---- diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/CacheClearCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/CacheClearCommand.php index 3bec217e30afb..3429d99ed1f86 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/CacheClearCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/CacheClearCommand.php @@ -19,6 +19,7 @@ use Symfony\Component\Filesystem\Filesystem; use Symfony\Component\HttpKernel\CacheClearer\CacheClearerInterface; use Symfony\Component\HttpKernel\KernelInterface; +use Symfony\Component\HttpKernel\RebootableInterface; use Symfony\Component\Finder\Finder; /** @@ -33,6 +34,7 @@ class CacheClearCommand extends ContainerAwareCommand { private $cacheClearer; private $filesystem; + private $warning; /** * @param CacheClearerInterface $cacheClearer @@ -112,6 +114,12 @@ protected function execute(InputInterface $input, OutputInterface $output) $this->filesystem->rename($realCacheDir, $oldCacheDir); } else { $this->warmupCache($input, $output, $realCacheDir, $oldCacheDir); + + if ($this->warning) { + @trigger_error($this->warning, E_USER_DEPRECATED); + $io->warning($this->warning); + $this->warning = null; + } } if ($output->isVerbose()) { @@ -167,17 +175,23 @@ protected function warmup($warmupDir, $realCacheDir, $enableOptionalWarmers = tr { // create a temporary kernel $realKernel = $this->getApplication()->getKernel(); - $realKernelClass = get_class($realKernel); - $namespace = ''; - if (false !== $pos = strrpos($realKernelClass, '\\')) { - $namespace = substr($realKernelClass, 0, $pos); - $realKernelClass = substr($realKernelClass, $pos + 1); - } - $tempKernel = $this->getTempKernel($realKernel, $namespace, $realKernelClass, $warmupDir); - $tempKernel->boot(); + if ($realKernel instanceof RebootableInterface) { + $realKernel->reboot($warmupDir); + $tempKernel = $realKernel; + } else { + $this->warning = 'Calling "cache:clear" with a kernel that does not implement "Symfony\Component\HttpKernel\RebootableInterface" is deprecated since version 3.4 and will be unsupported in 4.0.'; + $realKernelClass = get_class($realKernel); + $namespace = ''; + if (false !== $pos = strrpos($realKernelClass, '\\')) { + $namespace = substr($realKernelClass, 0, $pos); + $realKernelClass = substr($realKernelClass, $pos + 1); + } + $tempKernel = $this->getTempKernel($realKernel, $namespace, $realKernelClass, $warmupDir); + $tempKernel->boot(); - $tempKernelReflection = new \ReflectionObject($tempKernel); - $tempKernelFile = $tempKernelReflection->getFileName(); + $tempKernelReflection = new \ReflectionObject($tempKernel); + $tempKernelFile = $tempKernelReflection->getFileName(); + } // warmup temporary dir $warmer = $tempKernel->getContainer()->get('cache_warmer'); @@ -186,6 +200,20 @@ protected function warmup($warmupDir, $realCacheDir, $enableOptionalWarmers = tr } $warmer->warmUp($warmupDir); + // fix references to cached files with the real cache directory name + $search = array($warmupDir, str_replace('\\', '\\\\', $warmupDir)); + $replace = str_replace('\\', '/', $realCacheDir); + foreach (Finder::create()->files()->in($warmupDir) as $file) { + $content = str_replace($search, $replace, file_get_contents($file), $count); + if ($count) { + file_put_contents($file, $content); + } + } + + if ($realKernel instanceof RebootableInterface) { + return; + } + // fix references to the Kernel in .meta files $safeTempKernel = str_replace('\\', '\\\\', get_class($tempKernel)); $realKernelFQN = get_class($realKernel); @@ -198,16 +226,6 @@ protected function warmup($warmupDir, $realCacheDir, $enableOptionalWarmers = tr )); } - // fix references to cached files with the real cache directory name - $search = array($warmupDir, str_replace('\\', '\\\\', $warmupDir)); - $replace = str_replace('\\', '/', $realCacheDir); - foreach (Finder::create()->files()->in($warmupDir) as $file) { - $content = str_replace($search, $replace, file_get_contents($file), $count); - if ($count) { - file_put_contents($file, $content); - } - } - // fix references to container's class $tempContainerClass = $tempKernel->getContainerClass(); $realContainerClass = $tempKernel->getRealContainerClass(); diff --git a/src/Symfony/Component/HttpKernel/CHANGELOG.md b/src/Symfony/Component/HttpKernel/CHANGELOG.md index ca26a6c5bdde6..be467b407b00c 100644 --- a/src/Symfony/Component/HttpKernel/CHANGELOG.md +++ b/src/Symfony/Component/HttpKernel/CHANGELOG.md @@ -4,6 +4,7 @@ CHANGELOG 3.4.0 ----- + * added `RebootableInterface` and implemented it in `Kernel` * deprecated commands auto registration * added `AddCacheClearerPass` * added `AddCacheWarmerPass` diff --git a/src/Symfony/Component/HttpKernel/Kernel.php b/src/Symfony/Component/HttpKernel/Kernel.php index 8c70005d28577..df795fcd33dbd 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -43,7 +43,7 @@ * * @author Fabien Potencier */ -abstract class Kernel implements KernelInterface, TerminableInterface +abstract class Kernel implements KernelInterface, RebootableInterface, TerminableInterface { /** * @var BundleInterface[] @@ -61,6 +61,7 @@ abstract class Kernel implements KernelInterface, TerminableInterface protected $loadClassCache; private $projectDir; + private $warmupDir; const VERSION = '3.4.0-DEV'; const VERSION_ID = 30400; @@ -127,6 +128,16 @@ public function boot() $this->booted = true; } + /** + * {@inheritdoc} + */ + public function reboot($warmupDir) + { + $this->shutdown(); + $this->warmupDir = $warmupDir; + $this->boot(); + } + /** * {@inheritdoc} */ @@ -373,7 +384,7 @@ public function setClassCache(array $classes) @trigger_error(__METHOD__.'() is deprecated since version 3.3, to be removed in 4.0.', E_USER_DEPRECATED); } - file_put_contents($this->getCacheDir().'/classes.map', sprintf('warmupDir ?: $this->getCacheDir()).'/classes.map', sprintf('getCacheDir().'/annotations.map', sprintf('warmupDir ?: $this->getCacheDir()).'/annotations.map', sprintf('= 70000) { @trigger_error(__METHOD__.'() is deprecated since version 3.3, to be removed in 4.0.', E_USER_DEPRECATED); } + $cacheDir = $this->warmupDir ?: $this->getCacheDir(); - if (!$this->booted && is_file($this->getCacheDir().'/classes.map')) { - ClassCollectionLoader::load(include($this->getCacheDir().'/classes.map'), $this->getCacheDir(), $name, $this->debug, false, $extension); + if (!$this->booted && is_file($cacheDir.'/classes.map')) { + ClassCollectionLoader::load(include($cacheDir.'/classes.map'), $cacheDir, $name, $this->debug, false, $extension); } } @@ -536,7 +548,8 @@ protected function getContainerBaseClass() protected function initializeContainer() { $class = $this->getContainerClass(); - $cache = new ConfigCache($this->getCacheDir().'/'.$class.'.php', $this->debug); + $cacheDir = $this->warmupDir ?: $this->getCacheDir(); + $cache = new ConfigCache($cacheDir.'/'.$class.'.php', $this->debug); $fresh = true; if (!$cache->isFresh()) { if ($this->debug) { @@ -580,8 +593,8 @@ protected function initializeContainer() if ($this->debug) { restore_error_handler(); - file_put_contents($this->getCacheDir().'/'.$class.'Deprecations.log', serialize(array_values($collectedLogs))); - file_put_contents($this->getCacheDir().'/'.$class.'Compiler.log', null !== $container ? implode("\n", $container->getCompiler()->getLog()) : ''); + file_put_contents($cacheDir.'/'.$class.'Deprecations.log', serialize(array_values($collectedLogs))); + file_put_contents($cacheDir.'/'.$class.'Compiler.log', null !== $container ? implode("\n", $container->getCompiler()->getLog()) : ''); } } @@ -636,7 +649,7 @@ protected function getKernelParameters() 'kernel.environment' => $this->environment, 'kernel.debug' => $this->debug, 'kernel.name' => $this->name, - 'kernel.cache_dir' => realpath($this->getCacheDir()) ?: $this->getCacheDir(), + 'kernel.cache_dir' => realpath($cacheDir = $this->warmupDir ?: $this->getCacheDir()) ?: $cacheDir, 'kernel.logs_dir' => realpath($this->getLogDir()) ?: $this->getLogDir(), 'kernel.bundles' => $bundles, 'kernel.bundles_metadata' => $bundlesMetadata, @@ -682,7 +695,7 @@ protected function getEnvParameters() */ protected function buildContainer() { - foreach (array('cache' => $this->getCacheDir(), 'logs' => $this->getLogDir()) as $name => $dir) { + foreach (array('cache' => $this->warmupDir ?: $this->getCacheDir(), 'logs' => $this->getLogDir()) as $name => $dir) { if (!is_dir($dir)) { if (false === @mkdir($dir, 0777, true) && !is_dir($dir)) { throw new \RuntimeException(sprintf("Unable to create the %s directory (%s)\n", $name, $dir)); @@ -786,9 +799,6 @@ protected function dumpContainer(ConfigCache $cache, ContainerBuilder $container @chmod($dir.$file, 0666 & ~umask()); } - // track changes made to the container directory - $container->fileExists(dirname($dir.$file)); - $cache->write($rootCode, $container->getResources()); } diff --git a/src/Symfony/Component/HttpKernel/RebootableInterface.php b/src/Symfony/Component/HttpKernel/RebootableInterface.php new file mode 100644 index 0000000000000..58d9ef59e4483 --- /dev/null +++ b/src/Symfony/Component/HttpKernel/RebootableInterface.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\Component\HttpKernel; + +/** + * Allows the Kernel to be rebooted using a temporary cache directory. + * + * @author Nicolas Grekas + */ +interface RebootableInterface +{ + /** + * Reboots a kernel. + * + * The getCacheDir() method of a rebootable kernel should not be called + * while building the container. Use the %kernel.cache_dir% parameter instead. + * + * @param string|null $warmupDir pass null to reboot in the regular cache directory + */ + public function reboot($warmupDir); +} From 1d1085717960e4a4f68eca85ed0bd9da2f533bc1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9goire=20Pineau?= Date: Wed, 26 Jul 2017 10:53:23 +0200 Subject: [PATCH 0647/1099] [WebProfilerBundle] Re add missing link to the controller --- .../Resources/views/Collector/request.html.twig | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/request.html.twig b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/request.html.twig index 4fc6a82c58298..5fe45a0f4ed39 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/request.html.twig +++ b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/request.html.twig @@ -1,21 +1,19 @@ {% extends '@WebProfiler/Profiler/layout.html.twig' %} {% block toolbar %} + {% import _self as helper %} {% set request_handler %} - {% import _self as helper %} {{ helper.set_handler(collector.controller) }} {% endset %} {% if collector.redirect %} {% set redirect_handler %} - {% import _self as helper %} {{ helper.set_handler(collector.redirect.controller, collector.redirect.route, 'GET' != collector.redirect.method ? collector.redirect.method) }} {% endset %} {% endif %} {% if collector.forward|default(false) %} {% set forward_handler %} - {% import _self as helper %} {{ helper.set_handler(collector.forward.controller) }} {% endset %} {% endif %} @@ -108,6 +106,12 @@ {% endblock %} {% block panel %} + {% import _self as helper %} + +

+ {{ helper.set_handler(collector.controller) }} +

+

Request

@@ -268,7 +272,7 @@ {% for child in profile.children %}

- {{- child.getcollector('request').identifier -}} + {{ helper.set_handler(child.getcollector('request').controller) }} (token = {{ child.token }})

From 2ebc71a61671d30142b1f67989c9c48dff5bf425 Mon Sep 17 00:00:00 2001 From: GDIBass Date: Fri, 18 Aug 2017 08:37:36 -0700 Subject: [PATCH 0648/1099] Created new Exception to throw and modified tests --- .../Workflow/EventListener/GuardListener.php | 3 ++- .../InvalidTokenConfigurationException.php | 21 +++++++++++++++++++ .../Tests/EventListener/GuardListenerTest.php | 8 ++++--- 3 files changed, 28 insertions(+), 4 deletions(-) create mode 100644 src/Symfony/Component/Workflow/Exception/InvalidTokenConfigurationException.php diff --git a/src/Symfony/Component/Workflow/EventListener/GuardListener.php b/src/Symfony/Component/Workflow/EventListener/GuardListener.php index 3e402e9280a95..5d10cbcfceee4 100644 --- a/src/Symfony/Component/Workflow/EventListener/GuardListener.php +++ b/src/Symfony/Component/Workflow/EventListener/GuardListener.php @@ -16,6 +16,7 @@ use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface; use Symfony\Component\Security\Core\Role\RoleHierarchyInterface; use Symfony\Component\Workflow\Event\GuardEvent; +use Symfony\Component\Workflow\Exception\InvalidTokenConfigurationException; /** * @author Grégoire Pineau @@ -56,7 +57,7 @@ private function getVariables(GuardEvent $event) $token = $this->tokenStorage->getToken(); if (null === $token) { - throw new \Exception('No token is set'); + throw new InvalidTokenConfigurationException('No token is set'); } if (null !== $this->roleHierarchy) { diff --git a/src/Symfony/Component/Workflow/Exception/InvalidTokenConfigurationException.php b/src/Symfony/Component/Workflow/Exception/InvalidTokenConfigurationException.php new file mode 100644 index 0000000000000..367d4c6eb637f --- /dev/null +++ b/src/Symfony/Component/Workflow/Exception/InvalidTokenConfigurationException.php @@ -0,0 +1,21 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Workflow\Exception; + +/** + * Thrown by GuardListener when there is no token set, but guards are placed on a transition + * + * @author Matt Johnson + */ +class InvalidTokenConfigurationException extends LogicException implements ExceptionInterface +{ +} \ No newline at end of file diff --git a/src/Symfony/Component/Workflow/Tests/EventListener/GuardListenerTest.php b/src/Symfony/Component/Workflow/Tests/EventListener/GuardListenerTest.php index d72e31931360f..c32aec06a45be 100644 --- a/src/Symfony/Component/Workflow/Tests/EventListener/GuardListenerTest.php +++ b/src/Symfony/Component/Workflow/Tests/EventListener/GuardListenerTest.php @@ -69,12 +69,14 @@ public function testWithSupportedEventAndAccept() $this->assertTrue($event->isBlocked()); } + /** + * @expectedException \Symfony\Component\Workflow\Exception\InvalidTokenConfigurationException + * @expectedExceptionMessage No token is set + */ public function testWithNoTokenStorage() { $event = $this->createEvent(); - $this->tokenStorage = null; - - $this->expectException(\Exception::class); + $this->tokenStorage->setToken(null); $this->listener->onTransition($event, 'event_name_a'); } From 92308b4815b6ab2ee7eb018d9c284faf428b2131 Mon Sep 17 00:00:00 2001 From: GDIBass Date: Fri, 18 Aug 2017 08:40:24 -0700 Subject: [PATCH 0649/1099] Created new Exception to throw and modified tests. --- .../Workflow/Exception/InvalidTokenConfigurationException.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/Workflow/Exception/InvalidTokenConfigurationException.php b/src/Symfony/Component/Workflow/Exception/InvalidTokenConfigurationException.php index 367d4c6eb637f..85ada5e78071b 100644 --- a/src/Symfony/Component/Workflow/Exception/InvalidTokenConfigurationException.php +++ b/src/Symfony/Component/Workflow/Exception/InvalidTokenConfigurationException.php @@ -12,7 +12,7 @@ namespace Symfony\Component\Workflow\Exception; /** - * Thrown by GuardListener when there is no token set, but guards are placed on a transition + * Thrown by GuardListener when there is no token set, but guards are placed on a transition. * * @author Matt Johnson */ From 2c9d1e2d426673fe5d5ea568c1794ee5e4bf364c Mon Sep 17 00:00:00 2001 From: GDIBass Date: Fri, 18 Aug 2017 08:42:05 -0700 Subject: [PATCH 0650/1099] Removed newline --- .../Component/Workflow/Exception/InvalidDefinitionException.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/Workflow/Exception/InvalidDefinitionException.php b/src/Symfony/Component/Workflow/Exception/InvalidDefinitionException.php index d41170953564c..4ba9b183192ac 100644 --- a/src/Symfony/Component/Workflow/Exception/InvalidDefinitionException.php +++ b/src/Symfony/Component/Workflow/Exception/InvalidDefinitionException.php @@ -18,4 +18,4 @@ */ class InvalidDefinitionException extends LogicException { -} +} \ No newline at end of file From 49839e3c286d292a7068c9865cd12d884f299b9e Mon Sep 17 00:00:00 2001 From: GDIBass Date: Fri, 18 Aug 2017 08:43:29 -0700 Subject: [PATCH 0651/1099] Ahh, I see. It actually wants a newline! --- .../Component/Workflow/Exception/InvalidDefinitionException.php | 2 +- .../Workflow/Exception/InvalidTokenConfigurationException.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/Workflow/Exception/InvalidDefinitionException.php b/src/Symfony/Component/Workflow/Exception/InvalidDefinitionException.php index 4ba9b183192ac..d41170953564c 100644 --- a/src/Symfony/Component/Workflow/Exception/InvalidDefinitionException.php +++ b/src/Symfony/Component/Workflow/Exception/InvalidDefinitionException.php @@ -18,4 +18,4 @@ */ class InvalidDefinitionException extends LogicException { -} \ No newline at end of file +} diff --git a/src/Symfony/Component/Workflow/Exception/InvalidTokenConfigurationException.php b/src/Symfony/Component/Workflow/Exception/InvalidTokenConfigurationException.php index 85ada5e78071b..681d7a8bba52d 100644 --- a/src/Symfony/Component/Workflow/Exception/InvalidTokenConfigurationException.php +++ b/src/Symfony/Component/Workflow/Exception/InvalidTokenConfigurationException.php @@ -18,4 +18,4 @@ */ class InvalidTokenConfigurationException extends LogicException implements ExceptionInterface { -} \ No newline at end of file +} From ec8f56acd09501ee8ad3ac8538d8e9441b0a4b28 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Fri, 18 Aug 2017 18:00:55 +0200 Subject: [PATCH 0652/1099] [FrameworkBundle] Add soft conflict rule of "cache:clear" + HttpKernel 3.4 --- .../FrameworkBundle/Command/CacheClearCommand.php | 5 +++++ .../CacheClearCommand/CacheClearCommandTest.php | 12 ++++++++++++ 2 files changed, 17 insertions(+) diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/CacheClearCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/CacheClearCommand.php index b7613f7436b2a..ca119f198d5c1 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/CacheClearCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/CacheClearCommand.php @@ -15,6 +15,7 @@ use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Style\SymfonyStyle; +use Symfony\Component\HttpKernel\Kernel; use Symfony\Component\HttpKernel\KernelInterface; use Symfony\Component\Finder\Finder; @@ -56,6 +57,10 @@ protected function execute(InputInterface $input, OutputInterface $output) { $io = new SymfonyStyle($input, $output); + if (Kernel::VERSION_ID >= 30400) { + throw new \LogicException('The "cache:clear" command in Symfony 3.3 is incompatible with HttpKernel 3.4, please upgrade "symfony/framework-bundle" or downgrade "symfony/http-kernel".'); + } + $realCacheDir = $this->getContainer()->getParameter('kernel.cache_dir'); // the old cache dir name must not be longer than the real one to avoid exceeding // the maximum length of a directory or file path within it (esp. Windows MAX_PATH) diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/CacheClearCommand/CacheClearCommandTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/CacheClearCommand/CacheClearCommandTest.php index fd3b611202252..71f2ed551b668 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/CacheClearCommand/CacheClearCommandTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/CacheClearCommand/CacheClearCommandTest.php @@ -20,6 +20,7 @@ use Symfony\Component\Console\Output\NullOutput; use Symfony\Component\Filesystem\Filesystem; use Symfony\Component\Finder\Finder; +use Symfony\Component\HttpKernel\Kernel; class CacheClearCommandTest extends TestCase { @@ -49,6 +50,17 @@ public function testCacheIsFreshAfterCacheClearedWithWarmup() $application = new Application($this->kernel); $application->setCatchExceptions(false); + if (Kernel::VERSION_ID >= 30400) { + $expectedMsg = 'The "cache:clear" command in Symfony 3.3 is incompatible with HttpKernel 3.4, please upgrade "symfony/framework-bundle" or downgrade "symfony/http-kernel".'; + + if (method_exists($this, 'expectException')) { + $this->expectException(\LogicException::class); + $this->expectExceptionMessage($expectedMsg); + } else { + $this->setExpectedException(\LogicException::class, $expectedMsg); + } + } + $application->doRun($input, new NullOutput()); // Ensure that all *.meta files are fresh From a86bf52068f242b7d81587763161e145a13b54c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paulius=20Jarmalavi=C4=8Dius?= Date: Fri, 11 Aug 2017 10:01:09 +0300 Subject: [PATCH 0653/1099] [SecurityBundle] resolve class name parameter inside AddSecurityVotersPass --- .../DependencyInjection/Compiler/AddSecurityVotersPass.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Compiler/AddSecurityVotersPass.php b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Compiler/AddSecurityVotersPass.php index 67d0785b475fa..f75d4be192e71 100644 --- a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Compiler/AddSecurityVotersPass.php +++ b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Compiler/AddSecurityVotersPass.php @@ -42,7 +42,8 @@ public function process(ContainerBuilder $container) } foreach ($voters as $voter) { - $class = $container->getDefinition((string) $voter)->getClass(); + $definition = $container->getDefinition((string) $voter); + $class = $container->getParameterBag()->resolveValue($definition->getClass()); if (!is_a($class, VoterInterface::class, true)) { @trigger_error(sprintf('Using a security.voter tag on a class without implementing the %1$s is deprecated as of 3.4 and will be removed in 4.0. Implement the %1$s instead.', VoterInterface::class), E_USER_DEPRECATED); From 921959422f791fdd36a455d98ca372c48a7f4956 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Fri, 18 Aug 2017 17:51:40 +0200 Subject: [PATCH 0654/1099] [DI] Fix resolving env vars when compiling a ContainerBuilder --- .../MergeExtensionConfigurationPass.php | 10 +++- .../Compiler/ResolveEnvPlaceholdersPass.php | 44 ++++++++++++++++ .../DependencyInjection/ContainerBuilder.php | 50 +++++++++++++++---- .../EnvPlaceholderParameterBag.php | 26 ---------- .../Tests/ContainerBuilderTest.php | 26 ++++++++++ 5 files changed, 120 insertions(+), 36 deletions(-) create mode 100644 src/Symfony/Component/DependencyInjection/Compiler/ResolveEnvPlaceholdersPass.php diff --git a/src/Symfony/Component/DependencyInjection/Compiler/MergeExtensionConfigurationPass.php b/src/Symfony/Component/DependencyInjection/Compiler/MergeExtensionConfigurationPass.php index bddfa8b0e6bf4..2f1b088f92b66 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/MergeExtensionConfigurationPass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/MergeExtensionConfigurationPass.php @@ -92,7 +92,15 @@ public function __construct(Extension $extension, parent $resolvingBag) { $this->beforeProcessingEnvPlaceholders = $resolvingBag->getEnvPlaceholders(); $config = $this->resolveEnvPlaceholders($extension->getProcessedConfigs()); - parent::__construct($this->resolveEnvReferences($config)); + parent::__construct($this->resolveValue($config)); + } + + /** + * {@inheritdoc} + */ + public function get($name) + { + return $this->has($name) || (0 === strpos($name, 'env(') && ')' === substr($name, -1) && 'env()' !== $name) ? parent::get($name) : ''; } /** diff --git a/src/Symfony/Component/DependencyInjection/Compiler/ResolveEnvPlaceholdersPass.php b/src/Symfony/Component/DependencyInjection/Compiler/ResolveEnvPlaceholdersPass.php new file mode 100644 index 0000000000000..8e44008317c27 --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Compiler/ResolveEnvPlaceholdersPass.php @@ -0,0 +1,44 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Compiler; + +use Symfony\Component\DependencyInjection\Definition; + +/** + * Replaces env var placeholders by their current values. + */ +class ResolveEnvPlaceholdersPass extends AbstractRecursivePass +{ + protected function processValue($value, $isRoot = false) + { + if (is_string($value)) { + return $this->container->resolveEnvPlaceholders($value, true); + } + if ($value instanceof Definition) { + $changes = $value->getChanges(); + if (isset($changes['class'])) { + $value->setClass($this->container->resolveEnvPlaceholders($value->getClass(), true)); + } + if (isset($changes['file'])) { + $value->setFile($this->container->resolveEnvPlaceholders($value->getFile(), true)); + } + } + + $value = parent::processValue($value, $isRoot); + + if ($value && is_array($value)) { + $value = array_combine($this->container->resolveEnvPlaceholders(array_keys($value), true), $value); + } + + return $value; + } +} diff --git a/src/Symfony/Component/DependencyInjection/ContainerBuilder.php b/src/Symfony/Component/DependencyInjection/ContainerBuilder.php index 2e14caa1f8349..5a3922264554f 100644 --- a/src/Symfony/Component/DependencyInjection/ContainerBuilder.php +++ b/src/Symfony/Component/DependencyInjection/ContainerBuilder.php @@ -18,6 +18,7 @@ use Symfony\Component\DependencyInjection\Compiler\Compiler; use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; use Symfony\Component\DependencyInjection\Compiler\PassConfig; +use Symfony\Component\DependencyInjection\Compiler\ResolveEnvPlaceholdersPass; use Symfony\Component\DependencyInjection\Exception\BadMethodCallException; use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; use Symfony\Component\DependencyInjection\Exception\LogicException; @@ -729,9 +730,7 @@ public function compile(/*$resolveEnvPlaceholders = false*/) $bag = $this->getParameterBag(); if ($resolveEnvPlaceholders && $bag instanceof EnvPlaceholderParameterBag) { - $this->parameterBag = new ParameterBag($bag->resolveEnvReferences($bag->all())); - $this->envPlaceholders = $bag->getEnvPlaceholders(); - $this->parameterBag = $bag = new ParameterBag($this->resolveEnvPlaceholders($this->parameterBag->all(), true)); + $compiler->addPass(new ResolveEnvPlaceholdersPass(), PassConfig::TYPE_AFTER_REMOVING, -1000); } $compiler->compile($this); @@ -744,11 +743,15 @@ public function compile(/*$resolveEnvPlaceholders = false*/) $this->extensionConfigs = array(); - parent::compile(); - if ($bag instanceof EnvPlaceholderParameterBag) { + if ($resolveEnvPlaceholders) { + $this->parameterBag = new ParameterBag($this->resolveEnvPlaceholders($bag->all(), true)); + } + $this->envPlaceholders = $bag->getEnvPlaceholders(); } + + parent::compile(); } /** @@ -1313,12 +1316,19 @@ public function resolveEnvPlaceholders($value, $format = null, array &$usedEnvs foreach ($envPlaceholders as $env => $placeholders) { foreach ($placeholders as $placeholder) { if (false !== stripos($value, $placeholder)) { - if (true !== $format) { + if (true === $format) { + $resolved = $bag->escapeValue($this->getEnv($env)); + } else { $resolved = sprintf($format, $env); - } elseif ($placeholder === $resolved = $bag->escapeValue($this->getEnv($env))) { - $resolved = $bag->all()[strtolower("env($env)")]; } - $value = str_ireplace($placeholder, $resolved, $value); + if ($placeholder === $value) { + $value = $resolved; + } else { + if (!is_string($resolved) && !is_numeric($resolved)) { + throw new RuntimeException(sprintf('A string value must be composed of strings and/or numbers, but found parameter "env(%s)" of type %s inside string value "%s".', $env, gettype($resolved), $value)); + } + $value = str_ireplace($placeholder, $resolved, $value); + } $usedEnvs[$env] = $env; $this->envCounters[$env] = isset($this->envCounters[$env]) ? 1 + $this->envCounters[$env] : 1; } @@ -1393,6 +1403,28 @@ public static function getServiceConditionals($value) return $services; } + /** + * {@inheritdoc} + */ + protected function getEnv($name) + { + $value = parent::getEnv($name); + + if (!is_string($value) || !$this->getParameterBag() instanceof EnvPlaceholderParameterBag) { + return $value; + } + + foreach ($this->getParameterBag()->getEnvPlaceholders() as $env => $placeholders) { + if (isset($placeholders[$value])) { + $bag = new ParameterBag($this->getParameterBag()->all()); + + return $bag->unescapeValue($bag->get("env($name)")); + } + } + + return $value; + } + /** * Retrieves the currently set proxy instantiator or instantiates one. * diff --git a/src/Symfony/Component/DependencyInjection/ParameterBag/EnvPlaceholderParameterBag.php b/src/Symfony/Component/DependencyInjection/ParameterBag/EnvPlaceholderParameterBag.php index 8c80abf26bb76..d20e53531aa3b 100644 --- a/src/Symfony/Component/DependencyInjection/ParameterBag/EnvPlaceholderParameterBag.php +++ b/src/Symfony/Component/DependencyInjection/ParameterBag/EnvPlaceholderParameterBag.php @@ -20,7 +20,6 @@ class EnvPlaceholderParameterBag extends ParameterBag { private $envPlaceholders = array(); - private $resolveEnvReferences = false; /** * {@inheritdoc} @@ -102,29 +101,4 @@ public function resolve() } } } - - /** - * Replaces "%env(FOO)%" references by their placeholder, keeping regular "%parameters%" references as is. - */ - public function resolveEnvReferences(array $value) - { - $this->resolveEnvReferences = true; - try { - return $this->resolveValue($value); - } finally { - $this->resolveEnvReferences = false; - } - } - - /** - * {@inheritdoc} - */ - public function resolveString($value, array $resolving = array()) - { - if ($this->resolveEnvReferences) { - return preg_replace_callback('/%%|%(env\([^%\s]+\))%/', function ($match) { return isset($match[1]) ? $this->get($match[1]) : '%%'; }, $value); - } - - return parent::resolveString($value, $resolving); - } } diff --git a/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php b/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php index 7ab2e7c6f6c31..efe9840e42c40 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php @@ -623,19 +623,37 @@ public function testCompileWithResolveEnv() $container = new ContainerBuilder(); $container->setParameter('env(FOO)', 'Foo'); + $container->setParameter('env(DUMMY_ENV_VAR)', 'GHI'); $container->setParameter('bar', '%% %env(DUMMY_ENV_VAR)% %env(DUMMY_SERVER_VAR)% %env(HTTP_DUMMY_VAR)%'); $container->setParameter('foo', '%env(FOO)%'); $container->setParameter('baz', '%foo%'); $container->setParameter('env(HTTP_DUMMY_VAR)', '123'); + $container->register('teatime', 'stdClass') + ->setProperty('foo', '%env(DUMMY_ENV_VAR)%') + ; $container->compile(true); $this->assertSame('% du%%y ABC 123', $container->getParameter('bar')); $this->assertSame('Foo', $container->getParameter('baz')); + $this->assertSame('du%%y', $container->get('teatime')->foo); unset($_SERVER['DUMMY_SERVER_VAR'], $_SERVER['HTTP_DUMMY_VAR']); putenv('DUMMY_ENV_VAR'); } + /** + * @expectedException \Symfony\Component\DependencyInjection\Exception\RuntimeException + * @expectedExceptionMessage A string value must be composed of strings and/or numbers, but found parameter "env(ARRAY)" of type array inside string value "ABC %env(ARRAY)%". + */ + public function testCompileWithArrayResolveEnv() + { + $bag = new TestingEnvPlaceholderParameterBag(); + $container = new ContainerBuilder($bag); + $container->setParameter('foo', '%env(ARRAY)%'); + $container->setParameter('bar', 'ABC %env(ARRAY)%'); + $container->compile(true); + } + /** * @expectedException \Symfony\Component\DependencyInjection\Exception\EnvNotFoundException * @expectedExceptionMessage Environment variable not found: "FOO". @@ -1127,3 +1145,11 @@ public function __construct(A $a) { } } + +class TestingEnvPlaceholderParameterBag extends EnvPlaceholderParameterBag +{ + public function get($name) + { + return 'env(array)' === strtolower($name) ? array(123) : parent::get($name); + } +} From bdae7f530c923427095834afe410d12b17f6827d Mon Sep 17 00:00:00 2001 From: Oleksii Zhurbytskyi Date: Tue, 22 Aug 2017 13:13:34 +0300 Subject: [PATCH 0655/1099] [Validator] Fix Greek translation --- .../Validator/Resources/translations/validators.el.xlf | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.el.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.el.xlf index 4fa0d42220500..a3199bcc9d79e 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.el.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.el.xlf @@ -100,7 +100,7 @@ This value is not valid. - Αυτή η τιμή δεν είναι έκγυρη. + Αυτή η τιμή δεν είναι έγκυρη. This value is not a valid time. @@ -136,11 +136,11 @@ This is not a valid IP address. - Αυτό δεν είναι μια έκγυρη διεύθυνση IP. + Αυτό δεν είναι μια έγκυρη διεύθυνση IP. This value is not a valid language. - Αυτή η τιμή δεν αντιστοιχεί σε μια έκγυρη γλώσσα. + Αυτή η τιμή δεν αντιστοιχεί σε μια έγκυρη γλώσσα. This value is not a valid locale. @@ -148,7 +148,7 @@ This value is not a valid country. - Αυτή η τιμή δεν αντιστοιχεί σε μια έκγυρη χώρα. + Αυτή η τιμή δεν αντιστοιχεί σε μια έγκυρη χώρα. This value is already used. From 048eb186c7b9f3976567c105de25ad0a1022a6e1 Mon Sep 17 00:00:00 2001 From: Valentin Date: Fri, 11 Aug 2017 22:45:37 +0300 Subject: [PATCH 0656/1099] [DI] Use GlobResource for non-tracked directories --- .../DependencyInjection/FrameworkExtension.php | 2 +- .../TwigBundle/DependencyInjection/TwigExtension.php | 10 +++++++--- .../Component/DependencyInjection/ContainerBuilder.php | 10 +++++++--- 3 files changed, 15 insertions(+), 7 deletions(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php index 2bd54d731197b..d84255d94e3c9 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php @@ -1346,7 +1346,7 @@ private function registerSerializerConfiguration(array $config, ContainerBuilder $fileRecorder('yml', $file); } - if ($container->fileExists($dir = $dirname.'/Resources/config/serialization')) { + if ($container->fileExists($dir = $dirname.'/Resources/config/serialization', '/^$/')) { $this->registerMappingFilesFromDir($dir, $fileRecorder); } } diff --git a/src/Symfony/Bundle/TwigBundle/DependencyInjection/TwigExtension.php b/src/Symfony/Bundle/TwigBundle/DependencyInjection/TwigExtension.php index e8c10786c457d..a1ae0caba145d 100644 --- a/src/Symfony/Bundle/TwigBundle/DependencyInjection/TwigExtension.php +++ b/src/Symfony/Bundle/TwigBundle/DependencyInjection/TwigExtension.php @@ -13,6 +13,7 @@ use Symfony\Bridge\Twig\Extension\WebLinkExtension; use Symfony\Component\Config\FileLocator; +use Symfony\Component\Config\Resource\FileExistenceResource; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\DependencyInjection\Loader\XmlFileLoader; @@ -118,9 +119,10 @@ public function load(array $configs, ContainerBuilder $container) } } - if ($container->fileExists($dir = $container->getParameter('kernel.root_dir').'/Resources/views', false)) { + if (file_exists($dir = $container->getParameter('kernel.root_dir').'/Resources/views')) { $twigFilesystemLoaderDefinition->addMethodCall('addPath', array($dir)); } + $container->addResource(new FileExistenceResource($dir)); if (!empty($config['globals'])) { $def = $container->getDefinition('twig'); @@ -178,13 +180,15 @@ private function getBundleHierarchy(ContainerBuilder $container) ); } - if ($container->fileExists($dir = $container->getParameter('kernel.root_dir').'/Resources/'.$name.'/views', false)) { + if (file_exists($dir = $container->getParameter('kernel.root_dir').'/Resources/'.$name.'/views')) { $bundleHierarchy[$name]['paths'][] = $dir; } + $container->addResource(new FileExistenceResource($dir)); - if ($container->fileExists($dir = $bundle['path'].'/Resources/views', false)) { + if (file_exists($dir = $bundle['path'].'/Resources/views')) { $bundleHierarchy[$name]['paths'][] = $dir; } + $container->addResource(new FileExistenceResource($dir)); if (null === $bundle['parent']) { continue; diff --git a/src/Symfony/Component/DependencyInjection/ContainerBuilder.php b/src/Symfony/Component/DependencyInjection/ContainerBuilder.php index 555c3b09734b2..803e7937b1740 100644 --- a/src/Symfony/Component/DependencyInjection/ContainerBuilder.php +++ b/src/Symfony/Component/DependencyInjection/ContainerBuilder.php @@ -407,9 +407,13 @@ public function fileExists($path, $trackContents = true) return $exists; } - if ($trackContents && is_dir($path)) { - $this->addResource(new DirectoryResource($path, is_string($trackContents) ? $trackContents : null)); - } elseif ($trackContents || is_dir($path)) { + if (is_dir($path)) { + if ($trackContents) { + $this->addResource(new DirectoryResource($path, is_string($trackContents) ? $trackContents : null)); + } else { + $this->addResource(new GlobResource($path, '/*', false)); + } + } elseif ($trackContents) { $this->addResource(new FileResource($path)); } From c4dd11c4e15cb3f4a5e9a7a116a1c04d3279355d Mon Sep 17 00:00:00 2001 From: Tobias Nyholm Date: Mon, 14 Aug 2017 21:56:06 +0200 Subject: [PATCH 0657/1099] [Translation] Adding the ability do dump in xliff2.0 --- .../Component/Translation/CHANGELOG.md | 1 + .../Translation/Dumper/XliffFileDumper.php | 18 ++++++++++++++++- .../Tests/Dumper/XliffFileDumperTest.php | 20 +++++++++++++++++++ .../Tests/fixtures/resources-notes-meta.xlf | 16 +++++++++++++++ 4 files changed, 54 insertions(+), 1 deletion(-) create mode 100644 src/Symfony/Component/Translation/Tests/fixtures/resources-notes-meta.xlf diff --git a/src/Symfony/Component/Translation/CHANGELOG.md b/src/Symfony/Component/Translation/CHANGELOG.md index baa791b0ad174..e8bcb2243ea34 100644 --- a/src/Symfony/Component/Translation/CHANGELOG.md +++ b/src/Symfony/Component/Translation/CHANGELOG.md @@ -7,6 +7,7 @@ CHANGELOG * Added `TranslationDumperPass` * Added `TranslationExtractorPass` * Added `TranslatorPass` + * Added section to the Xliff 2.0 dumper. 3.2.0 ----- diff --git a/src/Symfony/Component/Translation/Dumper/XliffFileDumper.php b/src/Symfony/Component/Translation/Dumper/XliffFileDumper.php index 64588b167991d..d7e5ecc78c120 100644 --- a/src/Symfony/Component/Translation/Dumper/XliffFileDumper.php +++ b/src/Symfony/Component/Translation/Dumper/XliffFileDumper.php @@ -146,6 +146,23 @@ private function dumpXliff2($defaultLocale, MessageCatalogue $messages, $domain, foreach ($messages->all($domain) as $source => $target) { $translation = $dom->createElement('unit'); $translation->setAttribute('id', strtr(substr(base64_encode(hash('sha256', $source, true)), 0, 7), '/+', '._')); + $metadata = $messages->getMetadata($source, $domain); + + // Add notes section + if ($this->hasMetadataArrayInfo('notes', $metadata)) { + $notesElement = $dom->createElement('notes'); + foreach ($metadata['notes'] as $note) { + $n = $dom->createElement('note'); + $n->appendChild($dom->createTextNode(isset($note['content']) ? $note['content'] : '')); + unset($note['content']); + + foreach ($note as $name => $value) { + $n->setAttribute($name, $value); + } + $notesElement->appendChild($n); + } + $translation->appendChild($notesElement); + } $segment = $translation->appendChild($dom->createElement('segment')); @@ -156,7 +173,6 @@ private function dumpXliff2($defaultLocale, MessageCatalogue $messages, $domain, $text = 1 === preg_match('/[&<>]/', $target) ? $dom->createCDATASection($target) : $dom->createTextNode($target); $targetElement = $dom->createElement('target'); - $metadata = $messages->getMetadata($source, $domain); if ($this->hasMetadataArrayInfo('target-attributes', $metadata)) { foreach ($metadata['target-attributes'] as $name => $value) { $targetElement->setAttribute($name, $value); diff --git a/src/Symfony/Component/Translation/Tests/Dumper/XliffFileDumperTest.php b/src/Symfony/Component/Translation/Tests/Dumper/XliffFileDumperTest.php index 5764dff540692..30ca4d3d24868 100644 --- a/src/Symfony/Component/Translation/Tests/Dumper/XliffFileDumperTest.php +++ b/src/Symfony/Component/Translation/Tests/Dumper/XliffFileDumperTest.php @@ -87,4 +87,24 @@ public function testFormatCatalogueWithTargetAttributesMetadata() $dumper->formatCatalogue($catalogue, 'messages', array('default_locale' => 'fr_FR')) ); } + + public function testFormatCatalogueWithNotesMetadata() + { + $catalogue = new MessageCatalogue('en_US'); + $catalogue->add(array( + 'foo' => 'bar', + )); + $catalogue->setMetadata('foo', array('notes' => array( + array('category' => 'state', 'content' => 'new'), + array('category' => 'approved', 'content' => 'true'), + array('category' => 'section', 'content' => 'user login', 'priority' => '1'), + ))); + + $dumper = new XliffFileDumper(); + + $this->assertStringEqualsFile( + __DIR__.'/../fixtures/resources-notes-meta.xlf', + $dumper->formatCatalogue($catalogue, 'messages', array('default_locale' => 'fr_FR', 'xliff_version' => '2.0')) + ); + } } diff --git a/src/Symfony/Component/Translation/Tests/fixtures/resources-notes-meta.xlf b/src/Symfony/Component/Translation/Tests/fixtures/resources-notes-meta.xlf new file mode 100644 index 0000000000000..04f9a0a06e233 --- /dev/null +++ b/src/Symfony/Component/Translation/Tests/fixtures/resources-notes-meta.xlf @@ -0,0 +1,16 @@ + + + + + + new + true + user login + + + foo + bar + + + + From 156cb70edd841aaa347b7273cb03cbc5fa8edecf Mon Sep 17 00:00:00 2001 From: Javier Eguiluz Date: Sat, 5 Aug 2017 20:04:34 +0200 Subject: [PATCH 0658/1099] [DI] Don't force lowercase for hasher values --- src/Symfony/Component/DependencyInjection/ContainerBuilder.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/DependencyInjection/ContainerBuilder.php b/src/Symfony/Component/DependencyInjection/ContainerBuilder.php index ad78df795ca73..c71815c2cbc1c 100644 --- a/src/Symfony/Component/DependencyInjection/ContainerBuilder.php +++ b/src/Symfony/Component/DependencyInjection/ContainerBuilder.php @@ -1328,7 +1328,7 @@ public static function hash($value) { $hash = substr(base64_encode(hash('sha256', serialize($value), true)), 0, 7); - return str_replace(array('/', '+'), array('.', '_'), strtolower($hash)); + return str_replace(array('/', '+'), array('.', '_'), $hash); } /** From c25eafa4f3d334c0b88f37c8f58526b48b8b8ece Mon Sep 17 00:00:00 2001 From: Tobias Nyholm Date: Tue, 25 Jul 2017 19:57:30 +0200 Subject: [PATCH 0659/1099] Create an interface for TranslationWriter --- UPGRADE-3.4.md | 7 ++++ UPGRADE-4.0.md | 3 ++ .../Command/TranslationUpdateCommand.php | 14 ++++---- .../Component/Translation/CHANGELOG.md | 2 ++ .../Tests/Writer/TranslationWriterTest.php | 16 +++++++++ .../Translation/Writer/TranslationWriter.php | 23 +++++++++++-- .../Writer/TranslationWriterInterface.php | 34 +++++++++++++++++++ 7 files changed, 89 insertions(+), 10 deletions(-) create mode 100644 src/Symfony/Component/Translation/Writer/TranslationWriterInterface.php diff --git a/UPGRADE-3.4.md b/UPGRADE-3.4.md index 1f15a45d18ea3..0d5bde4f138ac 100644 --- a/UPGRADE-3.4.md +++ b/UPGRADE-3.4.md @@ -128,6 +128,13 @@ SecurityBundle * `FirewallContext::getListeners()` now returns `\Traversable|array` +Translation +----------- + + * `Symfony\Component\Translation\Writer\TranslationWriter::writeTranslations` has been deprecated + and will be removed in 4.0, use `Symfony\Component\Translation\Writer\TranslationWriter::write` + instead. + TwigBridge ---------- diff --git a/UPGRADE-4.0.md b/UPGRADE-4.0.md index e0fdf18eda5c9..45839be11ef65 100644 --- a/UPGRADE-4.0.md +++ b/UPGRADE-4.0.md @@ -554,6 +554,9 @@ Translation ----------- * Removed the backup feature from the file dumper classes. + + * Removed `Symfony\Component\Translation\Writer\TranslationWriter::writeTranslations`, + use `Symfony\Component\Translation\Writer\TranslationWriter::write` instead. TwigBundle ---------- diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/TranslationUpdateCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/TranslationUpdateCommand.php index 357902a209305..a580315efdaa1 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/TranslationUpdateCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/TranslationUpdateCommand.php @@ -21,7 +21,7 @@ use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Translation\Extractor\ExtractorInterface; use Symfony\Component\Translation\MessageCatalogue; -use Symfony\Component\Translation\Writer\TranslationWriter; +use Symfony\Component\Translation\Writer\TranslationWriterInterface; /** * A command that parses templates to extract translation messages and adds them @@ -39,14 +39,14 @@ class TranslationUpdateCommand extends ContainerAwareCommand private $defaultLocale; /** - * @param TranslationWriter $writer - * @param TranslationLoader $loader - * @param ExtractorInterface $extractor - * @param string $defaultLocale + * @param TranslationWriterInterface $writer + * @param TranslationLoader $loader + * @param ExtractorInterface $extractor + * @param string $defaultLocale */ public function __construct($writer = null, TranslationLoader $loader = null, ExtractorInterface $extractor = null, $defaultLocale = null) { - if (!$writer instanceof TranslationWriter) { + if (!$writer instanceof TranslationWriterInterface) { @trigger_error(sprintf('Passing a command name as the first argument of "%s" is deprecated since version 3.4 and will be removed in 4.0. If the command was registered by convention, make it a service instead.', __METHOD__), E_USER_DEPRECATED); parent::__construct($writer); @@ -276,7 +276,7 @@ protected function execute(InputInterface $input, OutputInterface $output) $bundleTransPath = end($transPaths).'translations'; } - $this->writer->writeTranslations($operation->getResult(), $input->getOption('output-format'), array('path' => $bundleTransPath, 'default_locale' => $this->defaultLocale)); + $this->writer->write($operation->getResult(), $input->getOption('output-format'), array('path' => $bundleTransPath, 'default_locale' => $this->defaultLocale)); if (true === $input->getOption('dump-messages')) { $resultMessage .= ' and translation files were updated'; diff --git a/src/Symfony/Component/Translation/CHANGELOG.md b/src/Symfony/Component/Translation/CHANGELOG.md index baa791b0ad174..ffc5701e64b15 100644 --- a/src/Symfony/Component/Translation/CHANGELOG.md +++ b/src/Symfony/Component/Translation/CHANGELOG.md @@ -7,6 +7,8 @@ CHANGELOG * Added `TranslationDumperPass` * Added `TranslationExtractorPass` * Added `TranslatorPass` + * Added `TranslationWriterInterface` + * Deprecated `TranslationWriter::writeTranslations` in favor of `TranslationWriter::write` 3.2.0 ----- diff --git a/src/Symfony/Component/Translation/Tests/Writer/TranslationWriterTest.php b/src/Symfony/Component/Translation/Tests/Writer/TranslationWriterTest.php index 2d2aec7c8a054..39da3f7c02396 100644 --- a/src/Symfony/Component/Translation/Tests/Writer/TranslationWriterTest.php +++ b/src/Symfony/Component/Translation/Tests/Writer/TranslationWriterTest.php @@ -18,6 +18,10 @@ class TranslationWriterTest extends TestCase { + /** + * @group legacy + * @expectedDeprecation Method Symfony\Component\Translation\Writer\TranslationWriter::writeTranslations() is deprecated since version 3.4 and will be removed in 4.0. Use write() instead. + */ public function testWriteTranslations() { $dumper = $this->getMockBuilder('Symfony\Component\Translation\Dumper\DumperInterface')->getMock(); @@ -30,6 +34,18 @@ public function testWriteTranslations() $writer->writeTranslations(new MessageCatalogue(array()), 'test'); } + public function testWrite() + { + $dumper = $this->getMockBuilder('Symfony\Component\Translation\Dumper\DumperInterface')->getMock(); + $dumper + ->expects($this->once()) + ->method('dump'); + + $writer = new TranslationWriter(); + $writer->addDumper('test', $dumper); + $writer->write(new MessageCatalogue(array()), 'test'); + } + public function testDisableBackup() { $nonBackupDumper = new NonBackupDumper(); diff --git a/src/Symfony/Component/Translation/Writer/TranslationWriter.php b/src/Symfony/Component/Translation/Writer/TranslationWriter.php index 901a8894e1c4c..53bb1cc7a482d 100644 --- a/src/Symfony/Component/Translation/Writer/TranslationWriter.php +++ b/src/Symfony/Component/Translation/Writer/TranslationWriter.php @@ -21,7 +21,7 @@ * * @author Michel Salib */ -class TranslationWriter +class TranslationWriter implements TranslationWriterInterface { /** * Dumpers used for export. @@ -66,13 +66,13 @@ public function getFormats() /** * Writes translation from the catalogue according to the selected format. * - * @param MessageCatalogue $catalogue The message catalogue to dump + * @param MessageCatalogue $catalogue The message catalogue to write * @param string $format The format to use to dump the messages * @param array $options Options that are passed to the dumper * * @throws InvalidArgumentException */ - public function writeTranslations(MessageCatalogue $catalogue, $format, $options = array()) + public function write(MessageCatalogue $catalogue, $format, $options = array()) { if (!isset($this->dumpers[$format])) { throw new InvalidArgumentException(sprintf('There is no dumper associated with format "%s".', $format)); @@ -88,4 +88,21 @@ public function writeTranslations(MessageCatalogue $catalogue, $format, $options // save $dumper->dump($catalogue, $options); } + + /** + * Writes translation from the catalogue according to the selected format. + * + * @param MessageCatalogue $catalogue The message catalogue to write + * @param string $format The format to use to dump the messages + * @param array $options Options that are passed to the dumper + * + * @throws InvalidArgumentException + * + * @deprecated since 3.4 will be removed in 4.0. Use write instead. + */ + public function writeTranslations(MessageCatalogue $catalogue, $format, $options = array()) + { + @trigger_error(sprintf('Method %s() is deprecated since version 3.4 and will be removed in 4.0. Use write() instead.', __METHOD__), E_USER_DEPRECATED); + $this->write($catalogue, $format, $options); + } } diff --git a/src/Symfony/Component/Translation/Writer/TranslationWriterInterface.php b/src/Symfony/Component/Translation/Writer/TranslationWriterInterface.php new file mode 100644 index 0000000000000..992ab769a0d59 --- /dev/null +++ b/src/Symfony/Component/Translation/Writer/TranslationWriterInterface.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\Component\Translation\Writer; + +use Symfony\Component\Translation\Exception\InvalidArgumentException; +use Symfony\Component\Translation\MessageCatalogue; + +/** + * TranslationWriter writes translation messages. + * + * @author Michel Salib + */ +interface TranslationWriterInterface +{ + /** + * Writes translation from the catalogue according to the selected format. + * + * @param MessageCatalogue $catalogue The message catalogue to write + * @param string $format The format to use to dump the messages + * @param array $options Options that are passed to the dumper + * + * @throws InvalidArgumentException + */ + public function write(MessageCatalogue $catalogue, $format, $options = array()); +} From c5a1218555f6aa54110d481e1845a39f021daf92 Mon Sep 17 00:00:00 2001 From: Oleg Voronkovich Date: Sun, 6 Aug 2017 03:05:34 +0300 Subject: [PATCH 0660/1099] [Dotenv][WebServerBundle] Override previously loaded variables --- .../Bundle/WebServerBundle/WebServer.php | 5 ++ src/Symfony/Component/Dotenv/Dotenv.php | 16 +++++- .../Component/Dotenv/Tests/DotenvTest.php | 56 +++++++++++++++++++ 3 files changed, 75 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Bundle/WebServerBundle/WebServer.php b/src/Symfony/Bundle/WebServerBundle/WebServer.php index 8edbe2bf56ec2..e3425ec8bb13a 100644 --- a/src/Symfony/Bundle/WebServerBundle/WebServer.php +++ b/src/Symfony/Bundle/WebServerBundle/WebServer.php @@ -154,6 +154,11 @@ private function createServerProcess(WebServerConfig $config) $process->setWorkingDirectory($config->getDocumentRoot()); $process->setTimeout(null); + if (in_array('APP_ENV', explode(',', getenv('SYMFONY_DOTENV_VARS')))) { + $process->setEnv(array('APP_ENV' => false)); + $process->inheritEnvironmentVariables(); + } + return $process; } diff --git a/src/Symfony/Component/Dotenv/Dotenv.php b/src/Symfony/Component/Dotenv/Dotenv.php index 2e907b8c980b8..0d3c01d93639e 100644 --- a/src/Symfony/Component/Dotenv/Dotenv.php +++ b/src/Symfony/Component/Dotenv/Dotenv.php @@ -60,20 +60,32 @@ public function load($path/*, ...$paths*/) /** * Sets values as environment variables (via putenv, $_ENV, and $_SERVER). * - * Note that existing environment variables are never overridden. + * Note that existing environment variables are not overridden. * * @param array $values An array of env variables */ public function populate($values) { + $loadedVars = array_flip(explode(',', getenv('SYMFONY_DOTENV_VARS'))); + unset($loadedVars['']); + foreach ($values as $name => $value) { - if (isset($_ENV[$name]) || isset($_SERVER[$name]) || false !== getenv($name)) { + if (!isset($loadedVars[$name]) && (isset($_ENV[$name]) || isset($_SERVER[$name]) || false !== getenv($name))) { continue; } putenv("$name=$value"); $_ENV[$name] = $value; $_SERVER[$name] = $value; + + $loadedVars[$name] = true; + } + + if ($loadedVars) { + $loadedVars = implode(',', array_keys($loadedVars)); + putenv("SYMFONY_DOTENV_VARS=$loadedVars"); + $_ENV['SYMFONY_DOTENV_VARS'] = $loadedVars; + $_SERVER['SYMFONY_DOTENV_VARS'] = $loadedVars; } } diff --git a/src/Symfony/Component/Dotenv/Tests/DotenvTest.php b/src/Symfony/Component/Dotenv/Tests/DotenvTest.php index 47598030a87f1..dc1a7b5b2c4a7 100644 --- a/src/Symfony/Component/Dotenv/Tests/DotenvTest.php +++ b/src/Symfony/Component/Dotenv/Tests/DotenvTest.php @@ -214,4 +214,60 @@ public function testEnvVarIsNotOverriden() $this->assertSame('original_value', getenv('TEST_ENV_VAR')); } + + public function testMemorizingLoadedVarsNamesInSpecialVar() + { + // Special variable not exists + unset($_ENV['SYMFONY_DOTENV_VARS']); + unset($_SERVER['SYMFONY_DOTENV_VARS']); + putenv('SYMFONY_DOTENV_VARS'); + + unset($_ENV['APP_DEBUG']); + unset($_SERVER['APP_DEBUG']); + putenv('APP_DEBUG'); + unset($_ENV['DATABASE_URL']); + unset($_SERVER['DATABASE_URL']); + putenv('DATABASE_URL'); + + $dotenv = new DotEnv(); + $dotenv->populate(array('APP_DEBUG' => '1', 'DATABASE_URL' => 'mysql://root@localhost/db')); + + $this->assertSame('APP_DEBUG,DATABASE_URL', getenv('SYMFONY_DOTENV_VARS')); + + // Special variable has a value + $_ENV['SYMFONY_DOTENV_VARS'] = 'APP_ENV'; + $_SERVER['SYMFONY_DOTENV_VARS'] = 'APP_ENV'; + putenv('SYMFONY_DOTENV_VARS=APP_ENV'); + + $_ENV['APP_DEBUG'] = '1'; + $_SERVER['APP_DEBUG'] = '1'; + putenv('APP_DEBUG=1'); + unset($_ENV['DATABASE_URL']); + unset($_SERVER['DATABASE_URL']); + putenv('DATABASE_URL'); + + $dotenv = new DotEnv(); + $dotenv->populate(array('APP_DEBUG' => '0', 'DATABASE_URL' => 'mysql://root@localhost/db')); + $dotenv->populate(array('DATABASE_URL' => 'sqlite:///somedb.sqlite')); + + $this->assertSame('APP_ENV,DATABASE_URL', getenv('SYMFONY_DOTENV_VARS')); + } + + public function testOverridingEnvVarsWithNamesMemorizedInSpecialVar() + { + putenv('SYMFONY_DOTENV_VARS=FOO,BAR,BAZ'); + + putenv('FOO=foo'); + putenv('BAR=bar'); + putenv('BAZ=baz'); + putenv('DOCUMENT_ROOT=/var/www'); + + $dotenv = new DotEnv(); + $dotenv->populate(array('FOO' => 'foo1', 'BAR' => 'bar1', 'BAZ' => 'baz1', 'DOCUMENT_ROOT' => '/boot')); + + $this->assertSame('foo1', getenv('FOO')); + $this->assertSame('bar1', getenv('BAR')); + $this->assertSame('baz1', getenv('BAZ')); + $this->assertSame('/var/www', getenv('DOCUMENT_ROOT')); + } } From f76e420e0959b52e73f1486a7b99771d6553ff01 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Tue, 22 Aug 2017 15:31:38 +0200 Subject: [PATCH 0661/1099] [Dotenv] Get env using $_SERVER to work with fastcgi_param and workaround thread safety issues --- .../DependencyInjection/Container.php | 4 ++-- src/Symfony/Component/Dotenv/Dotenv.php | 18 +++++++++++++++--- .../Component/Dotenv/Tests/DotenvTest.php | 13 +++++++++++++ 3 files changed, 30 insertions(+), 5 deletions(-) diff --git a/src/Symfony/Component/DependencyInjection/Container.php b/src/Symfony/Component/DependencyInjection/Container.php index 81241e3415cc8..6eceb0defeba9 100644 --- a/src/Symfony/Component/DependencyInjection/Container.php +++ b/src/Symfony/Component/DependencyInjection/Container.php @@ -438,13 +438,13 @@ protected function getEnv($name) if (isset($this->envCache[$name]) || array_key_exists($name, $this->envCache)) { return $this->envCache[$name]; } - if (0 !== strpos($name, 'HTTP_') && isset($_SERVER[$name])) { + if (isset($_SERVER[$name]) && 0 !== strpos($name, 'HTTP_')) { return $this->envCache[$name] = $_SERVER[$name]; } if (isset($_ENV[$name])) { return $this->envCache[$name] = $_ENV[$name]; } - if (false !== $env = getenv($name)) { + if (false !== ($env = getenv($name)) && null !== $env) { // null is a possible value because of thread safety issues return $this->envCache[$name] = $env; } if (!$this->hasParameter("env($name)")) { diff --git a/src/Symfony/Component/Dotenv/Dotenv.php b/src/Symfony/Component/Dotenv/Dotenv.php index 0d3c01d93639e..910a1622f303b 100644 --- a/src/Symfony/Component/Dotenv/Dotenv.php +++ b/src/Symfony/Component/Dotenv/Dotenv.php @@ -70,13 +70,17 @@ public function populate($values) unset($loadedVars['']); foreach ($values as $name => $value) { - if (!isset($loadedVars[$name]) && (isset($_ENV[$name]) || isset($_SERVER[$name]) || false !== getenv($name))) { + $notHttpName = 0 !== strpos($name, 'HTTP_'); + // don't check existence with getenv() because of thread safety issues + if (!isset($loadedVars[$name]) && (isset($_ENV[$name]) || (isset($_SERVER[$name]) && $notHttpName))) { continue; } putenv("$name=$value"); $_ENV[$name] = $value; - $_SERVER[$name] = $value; + if ($notHttpName) { + $_SERVER[$name] = $value; + } $loadedVars[$name] = true; } @@ -363,7 +367,15 @@ private function resolveVariables($value) } $name = $matches[3]; - $value = isset($this->values[$name]) ? $this->values[$name] : (isset($_ENV[$name]) ? $_ENV[$name] : (string) getenv($name)); + if (isset($this->values[$name])) { + $value = $this->values[$name]; + } elseif (isset($_SERVER[$name]) && 0 !== strpos($name, 'HTTP_')) { + $value = $_SERVER[$name]; + } elseif (isset($_ENV[$name])) { + $value = $_ENV[$name]; + } else { + $value = (string) getenv($name); + } if (!$matches[2] && isset($matches[4])) { $value .= '}'; diff --git a/src/Symfony/Component/Dotenv/Tests/DotenvTest.php b/src/Symfony/Component/Dotenv/Tests/DotenvTest.php index dc1a7b5b2c4a7..ce7d3a93396b2 100644 --- a/src/Symfony/Component/Dotenv/Tests/DotenvTest.php +++ b/src/Symfony/Component/Dotenv/Tests/DotenvTest.php @@ -208,6 +208,7 @@ public function testServerSuperglobalIsNotOverriden() public function testEnvVarIsNotOverriden() { putenv('TEST_ENV_VAR=original_value'); + $_SERVER['TEST_ENV_VAR'] = 'original_value'; $dotenv = new DotEnv(); $dotenv->populate(array('TEST_ENV_VAR' => 'new_value')); @@ -215,6 +216,18 @@ public function testEnvVarIsNotOverriden() $this->assertSame('original_value', getenv('TEST_ENV_VAR')); } + public function testHttpVarIsPartiallyOverriden() + { + $_SERVER['HTTP_TEST_ENV_VAR'] = 'http_value'; + + $dotenv = new DotEnv(); + $dotenv->populate(array('HTTP_TEST_ENV_VAR' => 'env_value')); + + $this->assertSame('env_value', getenv('HTTP_TEST_ENV_VAR')); + $this->assertSame('env_value', $_ENV['HTTP_TEST_ENV_VAR']); + $this->assertSame('http_value', $_SERVER['HTTP_TEST_ENV_VAR']); + } + public function testMemorizingLoadedVarsNamesInSpecialVar() { // Special variable not exists From ffd25fb9c2fb705d3f7b608f5cf8799b79ba9512 Mon Sep 17 00:00:00 2001 From: Tobias Nyholm Date: Wed, 26 Jul 2017 13:19:59 +0200 Subject: [PATCH 0662/1099] [Webprofiler] Added blocks that allows extension of the profiler page. --- .../views/Collector/translation.html.twig | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/translation.html.twig b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/translation.html.twig index 31881953d8139..f2ecb1113a04b 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/translation.html.twig +++ b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/translation.html.twig @@ -82,6 +82,8 @@

Translation Messages

+ {% block messages %} + {# sort translation messages in groups #} {% set messages_defined, messages_missing, messages_fallback = [], [], [] %} {% for message in collector.messages %} @@ -108,7 +110,9 @@

None of the used translation messages are defined for the given locale.

{% else %} - {{ helper.render_table(messages_defined) }} + {% block defined_messages %} + {{ helper.render_table(messages_defined) }} + {% endblock %} {% endif %}
@@ -127,7 +131,9 @@

No fallback translation messages were used.

{% else %} - {{ helper.render_table(messages_fallback) }} + {% block fallback_messages %} + {{ helper.render_table(messages_fallback) }} + {% endblock %} {% endif %}
@@ -147,11 +153,16 @@

There are no messages of this category.

{% else %} - {{ helper.render_table(messages_missing) }} + {% block missing_messages %} + {{ helper.render_table(messages_missing) }} + {% endblock %} {% endif %} + + {% endblock messages %} + {% endblock %} {% macro render_table(messages) %} From 1b0265417ba343f610b13e919a548cbb363ba8d8 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Sun, 20 Aug 2017 09:36:00 +0200 Subject: [PATCH 0663/1099] removed sf2 references --- src/Symfony/Bundle/TwigBundle/Resources/views/base_js.html.twig | 2 +- .../Resources/views/Profiler/base_js.html.twig | 2 +- .../Component/DependencyInjection/Loader/XmlFileLoader.php | 2 +- .../HttpFoundation/Session/Flash/AutoExpireFlashBag.php | 2 +- src/Symfony/Component/HttpFoundation/Session/Flash/FlashBag.php | 2 +- .../Tests/Session/Flash/AutoExpireFlashBagTest.php | 2 +- .../HttpFoundation/Tests/Session/Flash/FlashBagTest.php | 2 +- src/Symfony/Component/Translation/Loader/XliffFileLoader.php | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/Symfony/Bundle/TwigBundle/Resources/views/base_js.html.twig b/src/Symfony/Bundle/TwigBundle/Resources/views/base_js.html.twig index 036af2b025904..c18dd554ddb99 100644 --- a/src/Symfony/Bundle/TwigBundle/Resources/views/base_js.html.twig +++ b/src/Symfony/Bundle/TwigBundle/Resources/views/base_js.html.twig @@ -24,7 +24,7 @@ var noop = function() {}; - var profilerStorageKey = 'sf2/profiler/'; + var profilerStorageKey = 'symfony/profiler/'; var request = function(url, onSuccess, onError, payload, options) { var xhr = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject('Microsoft.XMLHTTP'); diff --git a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/base_js.html.twig b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/base_js.html.twig index b5f08f869168d..4196196593041 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/base_js.html.twig +++ b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/base_js.html.twig @@ -24,7 +24,7 @@ var noop = function() {}; - var profilerStorageKey = 'sf2/profiler/'; + var profilerStorageKey = 'symfony/profiler/'; var request = function(url, onSuccess, onError, payload, options) { var xhr = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject('Microsoft.XMLHTTP'); diff --git a/src/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php b/src/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php index ebdc83d733c5f..f5433bb6bab6c 100644 --- a/src/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php +++ b/src/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php @@ -597,7 +597,7 @@ public function validateSchema(\DOMDocument $dom) foreach ($schemaLocations as $namespace => $location) { $parts = explode('/', $location); if (0 === stripos($location, 'phar://')) { - $tmpfile = tempnam(sys_get_temp_dir(), 'sf2'); + $tmpfile = tempnam(sys_get_temp_dir(), 'symfony'); if ($tmpfile) { copy($location, $tmpfile); $tmpfiles[] = $tmpfile; diff --git a/src/Symfony/Component/HttpFoundation/Session/Flash/AutoExpireFlashBag.php b/src/Symfony/Component/HttpFoundation/Session/Flash/AutoExpireFlashBag.php index ddd603fdd1efb..138565aa31c73 100644 --- a/src/Symfony/Component/HttpFoundation/Session/Flash/AutoExpireFlashBag.php +++ b/src/Symfony/Component/HttpFoundation/Session/Flash/AutoExpireFlashBag.php @@ -39,7 +39,7 @@ class AutoExpireFlashBag implements FlashBagInterface * * @param string $storageKey The key used to store flashes in the session */ - public function __construct($storageKey = '_sf2_flashes') + public function __construct($storageKey = '_symfony_flashes') { $this->storageKey = $storageKey; } diff --git a/src/Symfony/Component/HttpFoundation/Session/Flash/FlashBag.php b/src/Symfony/Component/HttpFoundation/Session/Flash/FlashBag.php index 85b4f00b00f56..ee6be434cc76a 100644 --- a/src/Symfony/Component/HttpFoundation/Session/Flash/FlashBag.php +++ b/src/Symfony/Component/HttpFoundation/Session/Flash/FlashBag.php @@ -39,7 +39,7 @@ class FlashBag implements FlashBagInterface * * @param string $storageKey The key used to store flashes in the session */ - public function __construct($storageKey = '_sf2_flashes') + public function __construct($storageKey = '_symfony_flashes') { $this->storageKey = $storageKey; } diff --git a/src/Symfony/Component/HttpFoundation/Tests/Session/Flash/AutoExpireFlashBagTest.php b/src/Symfony/Component/HttpFoundation/Tests/Session/Flash/AutoExpireFlashBagTest.php index 4eb200afa3bdf..c25befc4c3fd4 100644 --- a/src/Symfony/Component/HttpFoundation/Tests/Session/Flash/AutoExpireFlashBagTest.php +++ b/src/Symfony/Component/HttpFoundation/Tests/Session/Flash/AutoExpireFlashBagTest.php @@ -62,7 +62,7 @@ public function testInitialize() public function testGetStorageKey() { - $this->assertEquals('_sf2_flashes', $this->bag->getStorageKey()); + $this->assertEquals('_symfony_flashes', $this->bag->getStorageKey()); $attributeBag = new FlashBag('test'); $this->assertEquals('test', $attributeBag->getStorageKey()); } diff --git a/src/Symfony/Component/HttpFoundation/Tests/Session/Flash/FlashBagTest.php b/src/Symfony/Component/HttpFoundation/Tests/Session/Flash/FlashBagTest.php index f0aa6a61577f4..07d17888070bf 100644 --- a/src/Symfony/Component/HttpFoundation/Tests/Session/Flash/FlashBagTest.php +++ b/src/Symfony/Component/HttpFoundation/Tests/Session/Flash/FlashBagTest.php @@ -57,7 +57,7 @@ public function testInitialize() public function testGetStorageKey() { - $this->assertEquals('_sf2_flashes', $this->bag->getStorageKey()); + $this->assertEquals('_symfony_flashes', $this->bag->getStorageKey()); $attributeBag = new FlashBag('test'); $this->assertEquals('test', $attributeBag->getStorageKey()); } diff --git a/src/Symfony/Component/Translation/Loader/XliffFileLoader.php b/src/Symfony/Component/Translation/Loader/XliffFileLoader.php index e3cab65437445..1603dc0b04fdb 100644 --- a/src/Symfony/Component/Translation/Loader/XliffFileLoader.php +++ b/src/Symfony/Component/Translation/Loader/XliffFileLoader.php @@ -222,7 +222,7 @@ private function fixXmlLocation($schemaSource, $xmlUri) $newPath = str_replace('\\', '/', __DIR__).'/schema/dic/xliff-core/xml.xsd'; $parts = explode('/', $newPath); if (0 === stripos($newPath, 'phar://')) { - $tmpfile = tempnam(sys_get_temp_dir(), 'sf2'); + $tmpfile = tempnam(sys_get_temp_dir(), 'symfony'); if ($tmpfile) { copy($newPath, $tmpfile); $parts = explode('/', str_replace('\\', '/', $tmpfile)); From 94d55ca0de7f7752ae18a285f8c62513e27e8575 Mon Sep 17 00:00:00 2001 From: Shawn Iwinski Date: Wed, 23 Aug 2017 16:52:57 -0400 Subject: [PATCH 0664/1099] [Console] Require PHP 7 for ApplicationTest --- .../Component/Console/Tests/ApplicationTest.php | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/Symfony/Component/Console/Tests/ApplicationTest.php b/src/Symfony/Component/Console/Tests/ApplicationTest.php index 6c06025697b2a..f12b1b4e1882c 100644 --- a/src/Symfony/Component/Console/Tests/ApplicationTest.php +++ b/src/Symfony/Component/Console/Tests/ApplicationTest.php @@ -1040,6 +1040,9 @@ public function testRunDispatchesAllEventsWithExceptionInListener() $this->assertContains('before.error.after.', $tester->getDisplay()); } + /** + * @requires PHP 7 + */ public function testRunWithError() { $application = new Application(); @@ -1160,6 +1163,7 @@ public function testErrorIsRethrownIfNotHandledByConsoleErrorEvent() } /** + * @requires PHP 7 * @expectedException \LogicException * @expectedExceptionMessage error */ @@ -1181,6 +1185,9 @@ public function testRunWithErrorAndDispatcher() $this->assertContains('before.dym.error.after.', $tester->getDisplay(), 'The PHP Error did not dispached events'); } + /** + * @requires PHP 7 + */ public function testRunDispatchesAllEventsWithError() { $application = new Application(); @@ -1198,6 +1205,9 @@ public function testRunDispatchesAllEventsWithError() $this->assertContains('before.dym.error.after.', $tester->getDisplay(), 'The PHP Error did not dispached events'); } + /** + * @requires PHP 7 + */ public function testRunWithErrorFailingStatusCode() { $application = new Application(); From 2348d64b86fba16ca631f7fdbdf41ecf02534300 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Thu, 24 Aug 2017 08:50:28 +0200 Subject: [PATCH 0665/1099] [Cache] Fix >30 days expirations with Memcached --- .../Cache/Tests/Adapter/AdapterTestCase.php | 20 +++++++++++++++++++ .../Tests/Adapter/MemcachedAdapterTest.php | 1 - .../Component/Cache/Traits/MemcachedTrait.php | 4 ++++ 3 files changed, 24 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/Cache/Tests/Adapter/AdapterTestCase.php b/src/Symfony/Component/Cache/Tests/Adapter/AdapterTestCase.php index c3cbd3bef7e54..faecda830cd7c 100644 --- a/src/Symfony/Component/Cache/Tests/Adapter/AdapterTestCase.php +++ b/src/Symfony/Component/Cache/Tests/Adapter/AdapterTestCase.php @@ -45,6 +45,26 @@ public function testDefaultLifeTime() $this->assertFalse($item->isHit()); } + public function testExpiration() + { + if (isset($this->skippedTests[__FUNCTION__])) { + $this->markTestSkipped($this->skippedTests[__FUNCTION__]); + } + + $cache = $this->createCachePool(); + $cache->save($cache->getItem('k1')->set('v1')->expiresAfter(2)); + $cache->save($cache->getItem('k2')->set('v2')->expiresAfter(366 * 86400)); + + sleep(3); + $item = $cache->getItem('k1'); + $this->assertFalse($item->isHit()); + $this->assertNull($item->get(), "Item's value must be null when isHit() is false."); + + $item = $cache->getItem('k2'); + $this->assertTrue($item->isHit()); + $this->assertSame('v2', $item->get()); + } + public function testNotUnserializable() { if (isset($this->skippedTests[__FUNCTION__])) { diff --git a/src/Symfony/Component/Cache/Tests/Adapter/MemcachedAdapterTest.php b/src/Symfony/Component/Cache/Tests/Adapter/MemcachedAdapterTest.php index 82b41c3b4d870..00e129398ed9a 100644 --- a/src/Symfony/Component/Cache/Tests/Adapter/MemcachedAdapterTest.php +++ b/src/Symfony/Component/Cache/Tests/Adapter/MemcachedAdapterTest.php @@ -17,7 +17,6 @@ class MemcachedAdapterTest extends AdapterTestCase { protected $skippedTests = array( - 'testExpiration' => 'Testing expiration slows down the test suite', 'testHasItemReturnsFalseWhenDeferredItemIsExpired' => 'Testing expiration slows down the test suite', 'testDefaultLifeTime' => 'Testing expiration slows down the test suite', ); diff --git a/src/Symfony/Component/Cache/Traits/MemcachedTrait.php b/src/Symfony/Component/Cache/Traits/MemcachedTrait.php index c2832946f98c2..9dc44355c042a 100644 --- a/src/Symfony/Component/Cache/Traits/MemcachedTrait.php +++ b/src/Symfony/Component/Cache/Traits/MemcachedTrait.php @@ -187,6 +187,10 @@ public static function createConnection($servers, array $options = array()) */ protected function doSave(array $values, $lifetime) { + if ($lifetime && $lifetime > 30 * 86400) { + $lifetime += time(); + } + return $this->checkResultCode($this->client->setMulti($values, $lifetime)); } From 51d210e2c03fa16af11d9a04c9e8a8ddac7a2f3b Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Thu, 24 Aug 2017 10:32:12 +0200 Subject: [PATCH 0666/1099] [travis] Add timing info --- .travis.yml | 33 ++++++++++++++++++++++++++++----- 1 file changed, 28 insertions(+), 5 deletions(-) diff --git a/.travis.yml b/.travis.yml index af674057da4b8..b7ce58bd8ffbb 100644 --- a/.travis.yml +++ b/.travis.yml @@ -51,15 +51,38 @@ before_install: export PHPUNIT_X="$PHPUNIT --exclude-group tty,benchmark,intl-data" export COMPOSER_UP='composer update --no-progress --no-suggest --ansi' + nanoseconds() { + local cmd="date" + local format="+%s%N" + local os=$(uname) + if hash gdate > /dev/null 2>&1; then + cmd="gdate" + elif [[ "$os" = Darwin ]]; then + format="+%s000000000" + fi + $cmd -u $format + } + export -f nanoseconds + # tfold is a helper to create folded reports tfold () { - title=$1 - fold=$(echo $title | sed -r 's/[^-_A-Za-z\d]+/./g') + local title=$1 + local fold=$(echo $title | sed -r 's/[^-_A-Za-z0-9]+/./g') shift - echo -e "travis_fold:start:$fold\\n\\e[1;34m$title\\e[0m" - bash -xc "$*" 2>&1 && + local id=$(printf %08x $(( RANDOM * RANDOM ))) + local start=$(nanoseconds) + echo -e "travis_fold:start:$fold" + echo -e "travis_time:start:$id" + echo -e "\\e[1;34m$title\\e[0m" + + bash -xc "$*" 2>&1 + local ok=$? + local end=$(nanoseconds) + echo -e "\\ntravis_time:end:$id:start=$start,finish=$end,duration=$(($end-$start))" + (exit $ok) && echo -e "\\e[32mOK\\e[0m $title\\n\\ntravis_fold:end:$fold" || - ( echo -e "\\e[41mKO\\e[0m $title\\n" && exit 1 ) + echo -e "\\e[41mKO\\e[0m $title\\n" + (exit $ok) } export -f tfold From 6dd695e3bcee644ab6d11df5d17f3746b4998aec Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Thu, 24 Aug 2017 13:53:36 +0200 Subject: [PATCH 0667/1099] [VarDumper] Use spl_object_id() with php72 polyfill when needed --- composer.json | 3 +- .../Component/VarDumper/Cloner/VarCloner.php | 46 ++++--------------- src/Symfony/Component/VarDumper/composer.json | 3 +- 3 files changed, 12 insertions(+), 40 deletions(-) diff --git a/composer.json b/composer.json index 71d665efc9447..7c4a3789b3d32 100644 --- a/composer.json +++ b/composer.json @@ -27,7 +27,8 @@ "psr/log": "~1.0", "psr/simple-cache": "^1.0", "symfony/polyfill-intl-icu": "~1.0", - "symfony/polyfill-mbstring": "~1.0" + "symfony/polyfill-mbstring": "~1.0", + "symfony/polyfill-php72": "~1.5" }, "replace": { "symfony/asset": "self.version", diff --git a/src/Symfony/Component/VarDumper/Cloner/VarCloner.php b/src/Symfony/Component/VarDumper/Cloner/VarCloner.php index 057b6b2e269ac..1aedf9251d954 100644 --- a/src/Symfony/Component/VarDumper/Cloner/VarCloner.php +++ b/src/Symfony/Component/VarDumper/Cloner/VarCloner.php @@ -17,8 +17,6 @@ class VarCloner extends AbstractCloner { private static $gid; - private static $hashMask = 0; - private static $hashOffset = 0; private static $arrayCache = array(); /** @@ -31,10 +29,10 @@ protected function doClone($var) $refsCounter = 0; // Hard references counter $queue = array(array($var)); // This breadth-first queue is the return value $indexedArrays = array(); // Map of queue indexes that hold numerically indexed arrays - $hardRefs = array(); // Map of original zval hashes to stub objects + $hardRefs = array(); // Map of original zval ids to stub objects $objRefs = array(); // Map of original object handles to their stub object couterpart $resRefs = array(); // Map of original resource handles to their stub object couterpart - $values = array(); // Map of stub objects' hashes to original values + $values = array(); // Map of stub objects' ids to original values $maxItems = $this->maxItems; $maxString = $this->maxString; $minDepth = $this->minDepth; @@ -46,13 +44,9 @@ protected function doClone($var) $stub = null; // Stub capturing the main properties of an original item value // or null if the original value is used directly - if (!self::$hashMask) { - self::$gid = uniqid(mt_rand(), true); // Unique string used to detect the special $GLOBALS variable - self::initHashMask(); + if (!$gid = self::$gid) { + $gid = self::$gid = uniqid(mt_rand(), true); // Unique string used to detect the special $GLOBALS variable } - $gid = self::$gid; - $hashMask = self::$hashMask; - $hashOffset = self::$hashOffset; $arrayStub = new Stub(); $arrayStub->type = Stub::TYPE_ARRAY; $fromObjCast = false; @@ -89,7 +83,7 @@ protected function doClone($var) if ($zvalIsRef = $vals[$k] === $cookie) { $vals[$k] = &$stub; // Break hard references to make $queue completely unset($stub); // independent from the original structure - if ($v instanceof Stub && isset($hardRefs[\spl_object_hash($v)])) { + if ($v instanceof Stub && isset($hardRefs[\spl_object_id($v)])) { $vals[$k] = $refs[$k] = $v; if ($v->value instanceof Stub && (Stub::TYPE_OBJECT === $v->value->type || Stub::TYPE_RESOURCE === $v->value->type)) { ++$v->value->refCount; @@ -99,7 +93,7 @@ protected function doClone($var) } $refs[$k] = $vals[$k] = new Stub(); $refs[$k]->value = $v; - $h = \spl_object_hash($refs[$k]); + $h = \spl_object_id($refs[$k]); $hardRefs[$h] = &$refs[$k]; $values[$h] = $v; $vals[$k]->handle = ++$refsCounter; @@ -172,7 +166,7 @@ protected function doClone($var) case \is_object($v): case $v instanceof \__PHP_Incomplete_Class: - if (empty($objRefs[$h = $hashMask ^ \hexdec(\substr(\spl_object_hash($v), $hashOffset, \PHP_INT_SIZE))])) { + if (empty($objRefs[$h = \spl_object_id($v)])) { $stub = new Stub(); $stub->type = Stub::TYPE_OBJECT; $stub->class = \get_class($v); @@ -183,8 +177,7 @@ protected function doClone($var) if (Stub::TYPE_OBJECT !== $stub->type || null === $stub->value) { break; } - $h = $hashMask ^ \hexdec(\substr(\spl_object_hash($stub->value), $hashOffset, \PHP_INT_SIZE)); - $stub->handle = $h; + $stub->handle = $h = \spl_object_id($stub->value); } $stub->value = null; if (0 <= $maxItems && $maxItems <= $pos && $minimumDepthReached) { @@ -291,27 +284,4 @@ protected function doClone($var) return $queue; } - - private static function initHashMask() - { - $obj = (object) array(); - self::$hashOffset = 16 - PHP_INT_SIZE; - self::$hashMask = -1; - - // check if we are nested in an output buffering handler to prevent a fatal error with ob_start() below - $obFuncs = array('ob_clean', 'ob_end_clean', 'ob_flush', 'ob_end_flush', 'ob_get_contents', 'ob_get_flush'); - foreach (debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS) as $frame) { - if (isset($frame['function'][0]) && !isset($frame['class']) && 'o' === $frame['function'][0] && in_array($frame['function'], $obFuncs)) { - $frame['line'] = 0; - break; - } - } - if (!empty($frame['line'])) { - ob_start(); - debug_zval_dump($obj); - self::$hashMask = (int) substr(ob_get_clean(), 17); - } - - self::$hashMask ^= hexdec(substr(spl_object_hash($obj), self::$hashOffset, PHP_INT_SIZE)); - } } diff --git a/src/Symfony/Component/VarDumper/composer.json b/src/Symfony/Component/VarDumper/composer.json index 2ebff422dd0ca..df2dc7fa926cc 100644 --- a/src/Symfony/Component/VarDumper/composer.json +++ b/src/Symfony/Component/VarDumper/composer.json @@ -17,7 +17,8 @@ ], "require": { "php": "^7.1.3", - "symfony/polyfill-mbstring": "~1.0" + "symfony/polyfill-mbstring": "~1.0", + "symfony/polyfill-php72": "~1.5" }, "require-dev": { "ext-iconv": "*", From 0e2d2b8c08b1508b03e72d8e0b5b0697d18bc488 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Wed, 23 Aug 2017 23:15:08 +0200 Subject: [PATCH 0668/1099] [VarDumper] add force-collapse/expand + use it for traces --- .../VarDumper/Caster/ExceptionCaster.php | 24 ++++-- .../Component/VarDumper/Caster/LinkStub.php | 6 +- .../VarDumper/Caster/ReflectionCaster.php | 2 +- .../Component/VarDumper/Cloner/Cursor.php | 1 + .../Component/VarDumper/Cloner/Data.php | 8 +- .../Component/VarDumper/Dumper/CliDumper.php | 33 ++++++++- .../Component/VarDumper/Dumper/HtmlDumper.php | 20 +++-- .../Tests/Caster/ExceptionCasterTest.php | 74 ++++++++----------- .../Tests/Caster/ReflectionCasterTest.php | 40 ++++------ .../VarDumper/Tests/Dumper/CliDumperTest.php | 34 +++------ 10 files changed, 133 insertions(+), 109 deletions(-) diff --git a/src/Symfony/Component/VarDumper/Caster/ExceptionCaster.php b/src/Symfony/Component/VarDumper/Caster/ExceptionCaster.php index 6786cf6a11803..df61aefb6f2fc 100644 --- a/src/Symfony/Component/VarDumper/Caster/ExceptionCaster.php +++ b/src/Symfony/Component/VarDumper/Caster/ExceptionCaster.php @@ -127,6 +127,7 @@ public static function castTraceStub(TraceStub $trace, array $a, Stub $stub, $is } $lastCall = isset($frames[$i]['function']) ? (isset($frames[$i]['class']) ? $frames[0]['class'].$frames[$i]['type'] : '').$frames[$i]['function'].'()' : ''; $frames[] = array('function' => ''); + $collapse = false; for ($j += $trace->numberingOffset - $i++; isset($frames[$i]); ++$i, --$j) { $f = $frames[$i]; @@ -145,6 +146,13 @@ public static function castTraceStub(TraceStub $trace, array $a, Stub $stub, $is $f = self::castFrameStub($frame, array(), $frame, true); if (isset($f[$prefix.'src'])) { foreach ($f[$prefix.'src']->value as $label => $frame) { + if (0 === strpos($label, "\0~collapse=0")) { + if ($collapse) { + $label = substr_replace($label, '1', 11, 1); + } else { + $collapse = true; + } + } $label = substr_replace($label, "title=Stack level $j.&", 2, 0); } $f = $frames[$i - 1]; @@ -162,7 +170,7 @@ public static function castTraceStub(TraceStub $trace, array $a, Stub $stub, $is } else { $label = substr_replace($prefix, "title=Stack level $j.", 2, 0).$lastCall; } - $a[$label] = $frame; + $a[substr_replace($label, sprintf('separator=%s&', $frame instanceof EnumStub ? ' ' : ':'), 2, 0)] = $frame; $lastCall = $call; } @@ -197,9 +205,10 @@ public static function castFrameStub(FrameStub $frame, array $a, Stub $stub, $is $caller = isset($f['function']) ? sprintf('in %s() on line %d', (isset($f['class']) ? $f['class'].$f['type'] : '').$f['function'], $f['line']) : null; $src = $f['line']; $srcKey = $f['file']; - $ellipsis = (new LinkStub($srcKey, 0))->attr; - $ellipsisTail = isset($ellipsis['ellipsis-tail']) ? $ellipsis['ellipsis-tail'] : 0; - $ellipsis = isset($ellipsis['ellipsis']) ? $ellipsis['ellipsis'] : 0; + $ellipsis = new LinkStub($srcKey, 0); + $srcAttr = 'collapse='.(int) $ellipsis->inVendor; + $ellipsisTail = isset($ellipsis->attr['ellipsis-tail']) ? $ellipsis->attr['ellipsis-tail'] : 0; + $ellipsis = isset($ellipsis->attr['ellipsis']) ? $ellipsis->attr['ellipsis'] : 0; if (file_exists($f['file']) && 0 <= self::$srcContext) { if (!empty($f['class']) && (is_subclass_of($f['class'], 'Twig\Template') || is_subclass_of($f['class'], 'Twig_Template')) && method_exists($f['class'], 'getDebugInfo')) { @@ -225,8 +234,11 @@ public static function castFrameStub(FrameStub $frame, array $a, Stub $stub, $is $ellipsis += 1 + strlen($f['line']); } } + $srcAttr .= '&separator= '; + } else { + $srcAttr .= '&separator=:'; } - $srcAttr = $ellipsis ? 'ellipsis-type=path&ellipsis='.$ellipsis.'&ellipsis-tail='.$ellipsisTail : ''; + $srcAttr .= $ellipsis ? '&ellipsis-type=path&ellipsis='.$ellipsis.'&ellipsis-tail='.$ellipsisTail : ''; self::$framesCache[$cacheKey] = $a[$prefix.'src'] = new EnumStub(array("\0~$srcAttr\0$srcKey" => $src)); } } @@ -329,7 +341,7 @@ private static function extractSource($srcLines, $line, $srcContext, $title, $la } } $c->attr['lang'] = $lang; - $srcLines[sprintf("\0~%d\0", $i + $line - $srcContext)] = $c; + $srcLines[sprintf("\0~separator=› &%d\0", $i + $line - $srcContext)] = $c; } return new EnumStub($srcLines); diff --git a/src/Symfony/Component/VarDumper/Caster/LinkStub.php b/src/Symfony/Component/VarDumper/Caster/LinkStub.php index eb9bc85c914f9..24f360b8f5553 100644 --- a/src/Symfony/Component/VarDumper/Caster/LinkStub.php +++ b/src/Symfony/Component/VarDumper/Caster/LinkStub.php @@ -18,6 +18,8 @@ */ class LinkStub extends ConstStub { + public $inVendor = false; + private static $vendorRoots; private static $composerRoots; @@ -50,10 +52,10 @@ public function __construct($label, $line = 0, $href = null) if ($label !== $this->attr['file'] = realpath($href) ?: $href) { return; } - if ($composerRoot = $this->getComposerRoot($href, $inVendor)) { + if ($composerRoot = $this->getComposerRoot($href, $this->inVendor)) { $this->attr['ellipsis'] = strlen($href) - strlen($composerRoot) + 1; $this->attr['ellipsis-type'] = 'path'; - $this->attr['ellipsis-tail'] = 1 + ($inVendor ? 2 + strlen(implode(array_slice(explode(DIRECTORY_SEPARATOR, substr($href, 1 - $this->attr['ellipsis'])), 0, 2))) : 0); + $this->attr['ellipsis-tail'] = 1 + ($this->inVendor ? 2 + strlen(implode(array_slice(explode(DIRECTORY_SEPARATOR, substr($href, 1 - $this->attr['ellipsis'])), 0, 2))) : 0); } elseif (3 < count($ellipsis = explode(DIRECTORY_SEPARATOR, $href))) { $this->attr['ellipsis'] = 2 + strlen(implode(array_slice($ellipsis, -2))); $this->attr['ellipsis-type'] = 'path'; diff --git a/src/Symfony/Component/VarDumper/Caster/ReflectionCaster.php b/src/Symfony/Component/VarDumper/Caster/ReflectionCaster.php index 8e86b054c05b0..4634fb915ea62 100644 --- a/src/Symfony/Component/VarDumper/Caster/ReflectionCaster.php +++ b/src/Symfony/Component/VarDumper/Caster/ReflectionCaster.php @@ -122,7 +122,7 @@ public static function castReflectionGenerator(\ReflectionGenerator $c, array $a $function = new FrameStub($frame, false, true); $function = ExceptionCaster::castFrameStub($function, array(), $function, true); $a[$prefix.'executing'] = new EnumStub(array( - $frame['class'].$frame['type'].$frame['function'].'()' => $function[$prefix.'src'], + "\0~separator= \0".$frame['class'].$frame['type'].$frame['function'].'()' => $function[$prefix.'src'], )); } diff --git a/src/Symfony/Component/VarDumper/Cloner/Cursor.php b/src/Symfony/Component/VarDumper/Cloner/Cursor.php index 9db55992e4aa9..888f4f2be33b9 100644 --- a/src/Symfony/Component/VarDumper/Cloner/Cursor.php +++ b/src/Symfony/Component/VarDumper/Cloner/Cursor.php @@ -39,4 +39,5 @@ class Cursor public $hashCut = 0; public $stop = false; public $attr = array(); + public $skipChildren = false; } diff --git a/src/Symfony/Component/VarDumper/Cloner/Data.php b/src/Symfony/Component/VarDumper/Cloner/Data.php index 3de76cdc7da42..81e0477cbd215 100644 --- a/src/Symfony/Component/VarDumper/Cloner/Data.php +++ b/src/Symfony/Component/VarDumper/Cloner/Data.php @@ -355,10 +355,16 @@ private function dumpItem($dumper, $cursor, &$refs, $item) $withChildren = $children && $cursor->depth !== $this->maxDepth && $this->maxItemsPerDepth; $dumper->enterHash($cursor, $item->type, $item->class, $withChildren); if ($withChildren) { - $cut = $this->dumpChildren($dumper, $cursor, $refs, $children, $cut, $item->type, null !== $item->class); + if ($cursor->skipChildren) { + $withChildren = false; + $cut = -1; + } else { + $cut = $this->dumpChildren($dumper, $cursor, $refs, $children, $cut, $item->type, null !== $item->class); + } } elseif ($children && 0 <= $cut) { $cut += count($children); } + $cursor->skipChildren = false; $dumper->leaveHash($cursor, $item->type, $item->class, $withChildren, $cut); break; diff --git a/src/Symfony/Component/VarDumper/Dumper/CliDumper.php b/src/Symfony/Component/VarDumper/Dumper/CliDumper.php index 086b2a2d6cd03..f1ea7fa01d755 100644 --- a/src/Symfony/Component/VarDumper/Dumper/CliDumper.php +++ b/src/Symfony/Component/VarDumper/Dumper/CliDumper.php @@ -51,6 +51,9 @@ class CliDumper extends AbstractDumper "\033" => '\e', ); + protected $collapseNextHash = false; + protected $expandNextHash = false; + /** * {@inheritdoc} */ @@ -253,6 +256,11 @@ public function enterHash(Cursor $cursor, $type, $class, $hasChild) { $this->dumpKey($cursor); + if ($this->collapseNextHash) { + $cursor->skipChildren = true; + $this->collapseNextHash = $hasChild = false; + } + $class = $this->utf8Encode($class); if (Cursor::HASH_OBJECT === $type) { $prefix = $class && 'stdClass' !== $class ? $this->style('note', $class).' {' : '{'; @@ -368,7 +376,15 @@ protected function dumpKey(Cursor $cursor) break; } - $this->line .= $bin.$this->style($style, $key[1], $attr).': '; + if (isset($attr['collapse'])) { + if ($attr['collapse']) { + $this->collapseNextHash = true; + } else { + $this->expandNextHash = true; + } + } + + $this->line .= $bin.$this->style($style, $key[1], $attr).(isset($attr['separator']) ? $attr['separator'] : ': '); } else { // This case should not happen $this->line .= '-'.$bin.'"'.$this->style('private', $key, array('class' => '')).'": '; @@ -397,6 +413,21 @@ protected function style($style, $value, $attr = array()) $this->colors = $this->supportsColors(); } + if (isset($attr['ellipsis'], $attr['ellipsis-type'])) { + $prefix = substr($value, 0, -$attr['ellipsis']); + if ('cli' === PHP_SAPI && 'path' === $attr['ellipsis-type'] && isset($_SERVER[$pwd = '\\' === DIRECTORY_SEPARATOR ? 'CD' : 'PWD']) && 0 === strpos($prefix, $_SERVER[$pwd])) { + $prefix = '.'.substr($prefix, strlen($_SERVER[$pwd])); + } + if (!empty($attr['ellipsis-tail'])) { + $prefix .= substr($value, -$attr['ellipsis'], $attr['ellipsis-tail']); + $value = substr($value, -$attr['ellipsis'] + $attr['ellipsis-tail']); + } else { + $value = substr($value, -$attr['ellipsis']); + } + + return $this->style('default', $prefix).$this->style($style, $value); + } + $style = $this->styles[$style]; $map = static::$controlCharsMap; diff --git a/src/Symfony/Component/VarDumper/Dumper/HtmlDumper.php b/src/Symfony/Component/VarDumper/Dumper/HtmlDumper.php index e57d04065b6be..54d97b175e648 100644 --- a/src/Symfony/Component/VarDumper/Dumper/HtmlDumper.php +++ b/src/Symfony/Component/VarDumper/Dumper/HtmlDumper.php @@ -366,7 +366,6 @@ function xpathString(str) { for (i = 0; i < len; ++i) { elt = t[i]; if ('SAMP' == elt.tagName) { - elt.className = 'sf-dump-expanded'; a = elt.previousSibling || {}; if ('A' != a.tagName) { a = doc.createElement('A'); @@ -383,7 +382,8 @@ function xpathString(str) { x += elt.parentNode.getAttribute('data-depth')/1; } elt.setAttribute('data-depth', x); - if (x > options.maxDepth) { + if (elt.className ? 'sf-dump-expanded' !== elt.className : (x > options.maxDepth)) { + elt.className = 'sf-dump-expanded'; toggle(a); } } else if ('sf-dump-ref' == elt.className && (a = elt.getAttribute('href'))) { @@ -728,15 +728,25 @@ public function enterHash(Cursor $cursor, $type, $class, $hasChild) { parent::enterHash($cursor, $type, $class, false); + if ($cursor->skipChildren) { + $cursor->skipChildren = false; + $eol = ' class=sf-dump-compact>'; + } elseif ($this->expandNextHash) { + $this->expandNextHash = false; + $eol = ' class=sf-dump-expanded>'; + } else { + $eol = '>'; + } + if ($hasChild) { + $this->line .= 'refIndex) { $r = Cursor::HASH_OBJECT !== $type ? 1 - (Cursor::HASH_RESOURCE !== $type) : 2; $r .= $r && 0 < $cursor->softRefHandle ? $cursor->softRefHandle : $cursor->refIndex; - $this->line .= sprintf('', $this->dumpId, $r); - } else { - $this->line .= ''; + $this->line .= sprintf(' id=%s-ref%s', $this->dumpId, $r); } + $this->line .= $eol; $this->dumpLine($cursor->depth); } } diff --git a/src/Symfony/Component/VarDumper/Tests/Caster/ExceptionCasterTest.php b/src/Symfony/Component/VarDumper/Tests/Caster/ExceptionCasterTest.php index 4e1e3682dc9f3..92cf6fb88299c 100644 --- a/src/Symfony/Component/VarDumper/Tests/Caster/ExceptionCasterTest.php +++ b/src/Symfony/Component/VarDumper/Tests/Caster/ExceptionCasterTest.php @@ -46,20 +46,13 @@ public function testDefaultSettings() #file: "%sExceptionCasterTest.php" #line: 28 trace: { - %sExceptionCasterTest.php:28: { - : { - : return new \Exception(''.$msg); - : } - } - %sExceptionCasterTest.php:%d: { - : $ref = array('foo'); - : $e = $this->getTestException('foo', $ref); - : - arguments: { - $msg: "foo" - &$ref: array:1 [ …1] - } + %s%eTests%eCaster%eExceptionCasterTest.php:28 { + › { + › return new \Exception(''.$msg); + › } } + %s%eTests%eCaster%eExceptionCasterTest.php:40 { …} + Symfony\Component\VarDumper\Tests\Caster\ExceptionCasterTest->testDefaultSettings() {} %A EODUMP; @@ -73,19 +66,13 @@ public function testSeek() $expectedDump = <<<'EODUMP' { - %sExceptionCasterTest.php:28: { - : { - : return new \Exception(''.$msg); - : } - } - %sExceptionCasterTest.php:%d: { - : { - : $e = $this->getTestException(2); - : - arguments: { - $msg: 2 - } + %s%eTests%eCaster%eExceptionCasterTest.php:28 { + › { + › return new \Exception(''.$msg); + › } } + %s%eTests%eCaster%eExceptionCasterTest.php:65 { …} + Symfony\Component\VarDumper\Tests\Caster\ExceptionCasterTest->testSeek() {} %A EODUMP; @@ -104,16 +91,13 @@ public function testNoArgs() #file: "%sExceptionCasterTest.php" #line: 28 trace: { - %sExceptionCasterTest.php:28: { - : { - : return new \Exception(''.$msg); - : } - } - %sExceptionCasterTest.php:%d: { - : { - : $e = $this->getTestException(1); - : ExceptionCaster::$traceArgs = false; + %sExceptionCasterTest.php:28 { + › { + › return new \Exception(''.$msg); + › } } + %s%eTests%eCaster%eExceptionCasterTest.php:84 { …} + Symfony\Component\VarDumper\Tests\Caster\ExceptionCasterTest->testNoArgs() {} %A EODUMP; @@ -132,8 +116,8 @@ public function testNoSrcContext() #file: "%sExceptionCasterTest.php" #line: 28 trace: { - %sExceptionCasterTest.php: 28 - %sExceptionCasterTest.php: %d + %s%eTests%eCaster%eExceptionCasterTest.php:28 + %s%eTests%eCaster%eExceptionCasterTest.php:%d %A EODUMP; @@ -161,7 +145,7 @@ public function testHtmlDump() #line: 28 trace: { %s%eVarDumper%eTests%eCaster%eExceptionCasterTest.php: 28 +Stack level %d.">%s%eVarDumper%eTests%eCaster%eExceptionCasterTest.php:28 …%d } } @@ -197,10 +181,10 @@ public function testFrameWithTwig() 0 => { class: "__TwigTemplate_VarDumperFixture_u75a09" src: { - %sTwig.php:1: { - : - : foo bar - : twig source + %sTwig.php:1 { + › + › foo bar + › twig source } } } @@ -210,10 +194,10 @@ class: "__TwigTemplate_VarDumperFixture_u75a09" %A } src: { - %sExceptionCasterTest.php:2: { - : foo bar - : twig source - : + %sExceptionCasterTest.php:2 { + › foo bar + › twig source + › } } } diff --git a/src/Symfony/Component/VarDumper/Tests/Caster/ReflectionCasterTest.php b/src/Symfony/Component/VarDumper/Tests/Caster/ReflectionCasterTest.php index b7080b73eda80..71eecc1aa896d 100644 --- a/src/Symfony/Component/VarDumper/Tests/Caster/ReflectionCasterTest.php +++ b/src/Symfony/Component/VarDumper/Tests/Caster/ReflectionCasterTest.php @@ -174,11 +174,11 @@ public function testGenerator() Generator { this: Symfony\Component\VarDumper\Tests\Fixtures\GeneratorDemo { …} executing: { - Symfony\Component\VarDumper\Tests\Fixtures\GeneratorDemo->baz(): { - %sGeneratorDemo.php:14: { - : { - : yield from bar(); - : } + Symfony\Component\VarDumper\Tests\Fixtures\GeneratorDemo->baz() { + %sGeneratorDemo.php:14 { + › { + › yield from bar(); + › } } } } @@ -197,31 +197,23 @@ public function testGenerator() 0 => ReflectionGenerator { this: Symfony\Component\VarDumper\Tests\Fixtures\GeneratorDemo { …} trace: { - %sGeneratorDemo.php:9: { - : { - : yield 1; - : } - } - %sGeneratorDemo.php:20: { - : { - : yield from GeneratorDemo::foo(); - : } - } - %sGeneratorDemo.php:14: { - : { - : yield from bar(); - : } + %s%eTests%eFixtures%eGeneratorDemo.php:9 { + › { + › yield 1; + › } } + %s%eTests%eFixtures%eGeneratorDemo.php:20 { …} + %s%eTests%eFixtures%eGeneratorDemo.php:14 { …} } closed: false } 1 => Generator { executing: { - Symfony\Component\VarDumper\Tests\Fixtures\GeneratorDemo::foo(): { - %sGeneratorDemo.php:10: { - : yield 1; - : } - : + Symfony\Component\VarDumper\Tests\Fixtures\GeneratorDemo::foo() { + %sGeneratorDemo.php:10 { + › yield 1; + › } + › } } } diff --git a/src/Symfony/Component/VarDumper/Tests/Dumper/CliDumperTest.php b/src/Symfony/Component/VarDumper/Tests/Dumper/CliDumperTest.php index f9a208c6303bf..a496a8c09ff20 100644 --- a/src/Symfony/Component/VarDumper/Tests/Dumper/CliDumperTest.php +++ b/src/Symfony/Component/VarDumper/Tests/Dumper/CliDumperTest.php @@ -86,7 +86,7 @@ class: "Symfony\Component\VarDumper\Tests\Dumper\CliDumperTest" default: null } } - file: "{$var['file']}" + file: "%s%eTests%eFixtures%edumb-var.php" line: "{$var['line']} to {$var['line']}" } "line" => {$var['line']} @@ -361,30 +361,16 @@ public function testThrowingCaster() ⚠: Symfony\Component\VarDumper\Exception\ThrowingCasterException {{$r} #message: "Unexpected Exception thrown from a caster: Foobar" trace: { - %sTwig.php:2: { - : foo bar - : twig source - : + %sTwig.php:2 { + › foo bar + › twig source + › } - %sTemplate.php:%d: { - : try { - : \$this->doDisplay(\$context, \$blocks); - : } catch (Twig%sError \$e) { - } - %sTemplate.php:%d: { - : { - : \$this->displayWithErrorHandling(\$this->env->mergeGlobals(\$context), array_merge(\$this->blocks, \$blocks)); - : } - } - %sTemplate.php:%d: { - : try { - : \$this->display(\$context); - : } catch (%s \$e) { - } - %sCliDumperTest.php:%d: { -%A - } - } + %s%eTemplate.php:%d { …} + %s%eTemplate.php:%d { …} + %s%eTemplate.php:%d { …} + %s%eTests%eDumper%eCliDumperTest.php:%d { …} +%A } } %Awrapper_type: "PHP" stream_type: "MEMORY" From eda7d4295589ed0d6905202bc482a7b0229faae5 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Mon, 21 Aug 2017 10:40:46 +0200 Subject: [PATCH 0669/1099] [Console] Add protected static $defaultName to set the default name of a Command --- .../Bridge/Twig/Command/DebugCommand.php | 3 ++- .../Bridge/Twig/Command/LintCommand.php | 3 ++- src/Symfony/Bridge/Twig/composer.json | 5 ++-- .../FrameworkBundle/Command/AboutCommand.php | 7 +++-- .../Command/AssetsInstallCommand.php | 3 ++- .../Command/CacheClearCommand.php | 3 ++- .../Command/CachePoolClearCommand.php | 3 ++- .../Command/CachePoolPruneCommand.php | 3 ++- .../Command/CacheWarmupCommand.php | 3 ++- .../Command/ConfigDebugCommand.php | 3 ++- .../Command/ConfigDumpReferenceCommand.php | 3 ++- .../Command/ContainerDebugCommand.php | 3 ++- .../Command/EventDispatcherDebugCommand.php | 2 +- .../Command/RouterDebugCommand.php | 2 +- .../Command/RouterMatchCommand.php | 3 ++- .../Command/TranslationDebugCommand.php | 3 ++- .../Command/TranslationUpdateCommand.php | 3 ++- .../Command/WorkflowDumpCommand.php | 3 ++- .../Command/XliffLintCommand.php | 2 ++ .../Command/YamlLintCommand.php | 2 ++ .../SecurityBundle/Command/InitAclCommand.php | 3 ++- .../SecurityBundle/Command/SetAclCommand.php | 3 ++- .../Command/UserPasswordEncoderCommand.php | 4 +-- .../Tests/Functional/SetAclCommandTest.php | 2 -- .../Bundle/SecurityBundle/composer.json | 5 ++-- src/Symfony/Component/Console/CHANGELOG.md | 5 +++- .../Component/Console/Command/Command.php | 18 ++++++++++++- .../Command/DefaultNameProviderInterface.php | 26 ------------------- .../AddConsoleCommandPass.php | 23 +++++++++------- .../AddConsoleCommandPassTest.php | 12 +++------ .../Translation/Command/XliffLintCommand.php | 3 ++- .../Component/Yaml/Command/LintCommand.php | 3 ++- src/Symfony/Component/Yaml/composer.json | 5 +++- 33 files changed, 95 insertions(+), 79 deletions(-) delete mode 100644 src/Symfony/Component/Console/Command/DefaultNameProviderInterface.php diff --git a/src/Symfony/Bridge/Twig/Command/DebugCommand.php b/src/Symfony/Bridge/Twig/Command/DebugCommand.php index 0c68c637f8c52..da98feb7632bb 100644 --- a/src/Symfony/Bridge/Twig/Command/DebugCommand.php +++ b/src/Symfony/Bridge/Twig/Command/DebugCommand.php @@ -26,6 +26,8 @@ */ class DebugCommand extends Command { + protected static $defaultName = 'debug:twig'; + private $twig; /** @@ -66,7 +68,6 @@ protected function getTwigEnvironment() protected function configure() { $this - ->setName('debug:twig') ->setDefinition(array( new InputArgument('filter', InputArgument::OPTIONAL, 'Show details for all entries matching this filter'), new InputOption('format', null, InputOption::VALUE_REQUIRED, 'The output format (text or json)', 'text'), diff --git a/src/Symfony/Bridge/Twig/Command/LintCommand.php b/src/Symfony/Bridge/Twig/Command/LintCommand.php index f96da4d615a29..b747ddaac0254 100644 --- a/src/Symfony/Bridge/Twig/Command/LintCommand.php +++ b/src/Symfony/Bridge/Twig/Command/LintCommand.php @@ -31,6 +31,8 @@ */ class LintCommand extends Command { + protected static $defaultName = 'lint:twig'; + private $twig; /** @@ -71,7 +73,6 @@ protected function getTwigEnvironment() protected function configure() { $this - ->setName('lint:twig') ->setDescription('Lints a template and outputs encountered errors') ->addOption('format', null, InputOption::VALUE_REQUIRED, 'The output format', 'txt') ->addArgument('filename', InputArgument::IS_ARRAY) diff --git a/src/Symfony/Bridge/Twig/composer.json b/src/Symfony/Bridge/Twig/composer.json index e86b4ecddce8f..14f734cdc80ef 100644 --- a/src/Symfony/Bridge/Twig/composer.json +++ b/src/Symfony/Bridge/Twig/composer.json @@ -33,13 +33,14 @@ "symfony/security": "~2.8|~3.0|~4.0", "symfony/security-acl": "~2.8|~3.0", "symfony/stopwatch": "~2.8|~3.0|~4.0", - "symfony/console": "~2.8|~3.0|~4.0", + "symfony/console": "~3.4|~4.0", "symfony/var-dumper": "~2.8.10|~3.1.4|~3.2|~4.0", "symfony/expression-language": "~2.8|~3.0|~4.0", "symfony/web-link": "~3.3|~4.0" }, "conflict": { - "symfony/form": "<3.2.10|~3.3,<3.3.3" + "symfony/form": "<3.2.10|~3.3,<3.3.3", + "symfony/console": "<3.4" }, "suggest": { "symfony/finder": "", diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/AboutCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/AboutCommand.php index 3b9130a8e40a8..4a594d3ae70ce 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/AboutCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/AboutCommand.php @@ -28,15 +28,14 @@ */ class AboutCommand extends ContainerAwareCommand { + protected static $defaultName = 'about'; + /** * {@inheritdoc} */ protected function configure() { - $this - ->setName('about') - ->setDescription('Displays information about the current project') - ; + $this->setDescription('Displays information about the current project'); } /** diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/AssetsInstallCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/AssetsInstallCommand.php index ffc770c7a5a69..e1adbe9e9325a 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/AssetsInstallCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/AssetsInstallCommand.php @@ -35,6 +35,8 @@ class AssetsInstallCommand extends ContainerAwareCommand const METHOD_ABSOLUTE_SYMLINK = 'absolute symlink'; const METHOD_RELATIVE_SYMLINK = 'relative symlink'; + protected static $defaultName = 'assets:install'; + private $filesystem; /** @@ -61,7 +63,6 @@ public function __construct($filesystem = null) protected function configure() { $this - ->setName('assets:install') ->setDefinition(array( new InputArgument('target', InputArgument::OPTIONAL, 'The target directory', 'public'), )) diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/CacheClearCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/CacheClearCommand.php index 77ae66867c660..edb6aaded4f60 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/CacheClearCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/CacheClearCommand.php @@ -31,6 +31,8 @@ */ class CacheClearCommand extends ContainerAwareCommand { + protected static $defaultName = 'cache:clear'; + private $cacheClearer; private $filesystem; @@ -60,7 +62,6 @@ public function __construct($cacheClearer = null, Filesystem $filesystem = null) protected function configure() { $this - ->setName('cache:clear') ->setDefinition(array( new InputOption('no-warmup', '', InputOption::VALUE_NONE, 'Do not warm up the cache'), new InputOption('no-optional-warmers', '', InputOption::VALUE_NONE, 'Skip optional cache warmers (faster)'), diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/CachePoolClearCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/CachePoolClearCommand.php index fec933f67b9ce..dedd61e668116 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/CachePoolClearCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/CachePoolClearCommand.php @@ -25,6 +25,8 @@ */ final class CachePoolClearCommand extends ContainerAwareCommand { + protected static $defaultName = 'cache:pool:clear'; + private $poolClearer; /** @@ -51,7 +53,6 @@ public function __construct($poolClearer = null) protected function configure() { $this - ->setName('cache:pool:clear') ->setDefinition(array( new InputArgument('pools', InputArgument::IS_ARRAY | InputArgument::REQUIRED, 'A list of cache pools or cache pool clearers'), )) diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/CachePoolPruneCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/CachePoolPruneCommand.php index 741979bd4f501..1c9cef9b93eda 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/CachePoolPruneCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/CachePoolPruneCommand.php @@ -24,6 +24,8 @@ */ final class CachePoolPruneCommand extends Command { + protected static $defaultName = 'cache:pool:prune'; + private $pools; /** @@ -42,7 +44,6 @@ public function __construct($pools) protected function configure() { $this - ->setName('cache:pool:prune') ->setDescription('Prune cache pools') ->setHelp(<<<'EOF' The %command.name% command deletes all expired items from all pruneable pools. diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/CacheWarmupCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/CacheWarmupCommand.php index 57972782dc771..1ff474e96939d 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/CacheWarmupCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/CacheWarmupCommand.php @@ -26,6 +26,8 @@ */ class CacheWarmupCommand extends ContainerAwareCommand { + protected static $defaultName = 'cache:warmup'; + private $cacheWarmer; /** @@ -52,7 +54,6 @@ public function __construct($cacheWarmer = null) protected function configure() { $this - ->setName('cache:warmup') ->setDefinition(array( new InputOption('no-optional-warmers', '', InputOption::VALUE_NONE, 'Skip optional cache warmers (faster)'), )) diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/ConfigDebugCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/ConfigDebugCommand.php index f460fd5f09a3f..5a55332b334f3 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/ConfigDebugCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/ConfigDebugCommand.php @@ -28,13 +28,14 @@ */ class ConfigDebugCommand extends AbstractConfigCommand { + protected static $defaultName = 'debug:config'; + /** * {@inheritdoc} */ protected function configure() { $this - ->setName('debug:config') ->setDefinition(array( new InputArgument('name', InputArgument::OPTIONAL, 'The bundle name or the extension alias'), new InputArgument('path', InputArgument::OPTIONAL, 'The configuration option path'), diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/ConfigDumpReferenceCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/ConfigDumpReferenceCommand.php index fb51f8c3fcf0c..62bdfec8c9c99 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/ConfigDumpReferenceCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/ConfigDumpReferenceCommand.php @@ -30,13 +30,14 @@ */ class ConfigDumpReferenceCommand extends AbstractConfigCommand { + protected static $defaultName = 'config:dump-reference'; + /** * {@inheritdoc} */ protected function configure() { $this - ->setName('config:dump-reference') ->setDefinition(array( new InputArgument('name', InputArgument::OPTIONAL, 'The Bundle name or the extension alias'), new InputArgument('path', InputArgument::OPTIONAL, 'The configuration option path'), diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/ContainerDebugCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/ContainerDebugCommand.php index 51c04969877e6..ed859880cb00e 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/ContainerDebugCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/ContainerDebugCommand.php @@ -32,6 +32,8 @@ */ class ContainerDebugCommand extends ContainerAwareCommand { + protected static $defaultName = 'debug:container'; + /** * @var ContainerBuilder|null */ @@ -43,7 +45,6 @@ class ContainerDebugCommand extends ContainerAwareCommand protected function configure() { $this - ->setName('debug:container') ->setDefinition(array( new InputArgument('name', InputArgument::OPTIONAL, 'A service name (foo)'), new InputOption('show-private', null, InputOption::VALUE_NONE, 'Used to show public *and* private services'), diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/EventDispatcherDebugCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/EventDispatcherDebugCommand.php index 18aa08575c4e0..a36878d44533c 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/EventDispatcherDebugCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/EventDispatcherDebugCommand.php @@ -28,6 +28,7 @@ */ class EventDispatcherDebugCommand extends ContainerAwareCommand { + protected static $defaultName = 'debug:event-dispatcher'; private $dispatcher; /** @@ -54,7 +55,6 @@ public function __construct($dispatcher = null) protected function configure() { $this - ->setName('debug:event-dispatcher') ->setDefinition(array( new InputArgument('event', InputArgument::OPTIONAL, 'An event name'), new InputOption('format', null, InputOption::VALUE_REQUIRED, 'The output format (txt, xml, json, or md)', 'txt'), diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/RouterDebugCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/RouterDebugCommand.php index 2a005090322dd..03b227a731ce7 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/RouterDebugCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/RouterDebugCommand.php @@ -32,6 +32,7 @@ */ class RouterDebugCommand extends ContainerAwareCommand { + protected static $defaultName = 'debug:router'; private $router; /** @@ -79,7 +80,6 @@ public function isEnabled() protected function configure() { $this - ->setName('debug:router') ->setDefinition(array( new InputArgument('name', InputArgument::OPTIONAL, 'A route name'), new InputOption('show-controllers', null, InputOption::VALUE_NONE, 'Show assigned controllers in overview'), diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/RouterMatchCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/RouterMatchCommand.php index f88d2a2dfe0c7..ee5c4990a487b 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/RouterMatchCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/RouterMatchCommand.php @@ -29,6 +29,8 @@ */ class RouterMatchCommand extends ContainerAwareCommand { + protected static $defaultName = 'router:match'; + private $router; /** @@ -76,7 +78,6 @@ public function isEnabled() protected function configure() { $this - ->setName('router:match') ->setDefinition(array( new InputArgument('path_info', InputArgument::REQUIRED, 'A path info'), new InputOption('method', null, InputOption::VALUE_REQUIRED, 'Sets the HTTP method'), diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/TranslationDebugCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/TranslationDebugCommand.php index f8e69a3c4a640..cbf6bda5f3fff 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/TranslationDebugCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/TranslationDebugCommand.php @@ -40,6 +40,8 @@ class TranslationDebugCommand extends ContainerAwareCommand const MESSAGE_UNUSED = 1; const MESSAGE_EQUALS_FALLBACK = 2; + protected static $defaultName = 'debug:translation'; + private $translator; private $loader; private $extractor; @@ -72,7 +74,6 @@ public function __construct($translator = null, TranslationLoader $loader = null protected function configure() { $this - ->setName('debug:translation') ->setDefinition(array( new InputArgument('locale', InputArgument::REQUIRED, 'The locale'), new InputArgument('bundle', InputArgument::OPTIONAL, 'The bundle name or directory where to load the messages, defaults to app/Resources folder'), diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/TranslationUpdateCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/TranslationUpdateCommand.php index 357902a209305..20d5ffa8b031b 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/TranslationUpdateCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/TranslationUpdateCommand.php @@ -33,6 +33,8 @@ */ class TranslationUpdateCommand extends ContainerAwareCommand { + protected static $defaultName = 'translation:update'; + private $writer; private $loader; private $extractor; @@ -68,7 +70,6 @@ public function __construct($writer = null, TranslationLoader $loader = null, Ex protected function configure() { $this - ->setName('translation:update') ->setDefinition(array( new InputArgument('locale', InputArgument::REQUIRED, 'The locale'), new InputArgument('bundle', InputArgument::OPTIONAL, 'The bundle name or directory where to load the messages, defaults to app/Resources folder'), diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/WorkflowDumpCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/WorkflowDumpCommand.php index 27e0f645d8fdf..9923f657794f8 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/WorkflowDumpCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/WorkflowDumpCommand.php @@ -25,6 +25,8 @@ */ class WorkflowDumpCommand extends ContainerAwareCommand { + protected static $defaultName = 'workflow:dump'; + /** * {@inheritdoc} * @@ -41,7 +43,6 @@ public function isEnabled() protected function configure() { $this - ->setName('workflow:dump') ->setDefinition(array( new InputArgument('name', InputArgument::REQUIRED, 'A workflow name'), new InputArgument('marking', InputArgument::IS_ARRAY, 'A marking (a list of places)'), diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/XliffLintCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/XliffLintCommand.php index 36876dee24252..2093c3d262302 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/XliffLintCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/XliffLintCommand.php @@ -24,6 +24,8 @@ */ class XliffLintCommand extends BaseLintCommand { + protected static $defaultName = 'lint:xliff'; + public function __construct($name = null, $directoryIteratorProvider = null, $isReadableProvider = null) { if (func_num_args()) { diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/YamlLintCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/YamlLintCommand.php index f6c1a7f85b190..e54a0058cabcc 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/YamlLintCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/YamlLintCommand.php @@ -23,6 +23,8 @@ */ class YamlLintCommand extends BaseLintCommand { + protected static $defaultName = 'lint:yaml'; + public function __construct($name = null, $directoryIteratorProvider = null, $isReadableProvider = null) { if (func_num_args()) { diff --git a/src/Symfony/Bundle/SecurityBundle/Command/InitAclCommand.php b/src/Symfony/Bundle/SecurityBundle/Command/InitAclCommand.php index 597df8ceb9de1..c8ccac32cab5b 100644 --- a/src/Symfony/Bundle/SecurityBundle/Command/InitAclCommand.php +++ b/src/Symfony/Bundle/SecurityBundle/Command/InitAclCommand.php @@ -27,6 +27,8 @@ */ class InitAclCommand extends ContainerAwareCommand { + protected static $defaultName = 'init:acl'; + private $connection; private $schema; @@ -70,7 +72,6 @@ public function isEnabled() protected function configure() { $this - ->setName('init:acl') ->setDescription('Mounts ACL tables in the database') ->setHelp(<<<'EOF' The %command.name% command mounts ACL tables in the database. diff --git a/src/Symfony/Bundle/SecurityBundle/Command/SetAclCommand.php b/src/Symfony/Bundle/SecurityBundle/Command/SetAclCommand.php index 840e74edfba87..bdb293a4ec6fd 100644 --- a/src/Symfony/Bundle/SecurityBundle/Command/SetAclCommand.php +++ b/src/Symfony/Bundle/SecurityBundle/Command/SetAclCommand.php @@ -32,6 +32,8 @@ */ class SetAclCommand extends ContainerAwareCommand { + protected static $defaultName = 'acl:set'; + private $provider; /** @@ -80,7 +82,6 @@ public function isEnabled() protected function configure() { $this - ->setName('acl:set') ->setDescription('Sets ACL for objects') ->setHelp(<<%command.name% command sets ACL. diff --git a/src/Symfony/Bundle/SecurityBundle/Command/UserPasswordEncoderCommand.php b/src/Symfony/Bundle/SecurityBundle/Command/UserPasswordEncoderCommand.php index 1f6a5d3c6213b..c93cb4987f481 100644 --- a/src/Symfony/Bundle/SecurityBundle/Command/UserPasswordEncoderCommand.php +++ b/src/Symfony/Bundle/SecurityBundle/Command/UserPasswordEncoderCommand.php @@ -19,7 +19,6 @@ use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Question\Question; use Symfony\Component\Console\Style\SymfonyStyle; -use Symfony\Component\DependencyInjection\ContainerAwareInterface; use Symfony\Component\Security\Core\Encoder\BCryptPasswordEncoder; use Symfony\Component\Security\Core\Encoder\EncoderFactoryInterface; use Symfony\Component\Security\Core\User\User; @@ -33,6 +32,8 @@ */ class UserPasswordEncoderCommand extends ContainerAwareCommand { + protected static $defaultName = 'security:encode-password'; + private $encoderFactory; private $userClasses; @@ -54,7 +55,6 @@ public function __construct(EncoderFactoryInterface $encoderFactory = null, arra protected function configure() { $this - ->setName('security:encode-password') ->setDescription('Encodes a password.') ->addArgument('password', InputArgument::OPTIONAL, 'The plain password to encode.') ->addArgument('user-class', InputArgument::OPTIONAL, 'The User entity class path associated with the encoder used to encode the password.') diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/SetAclCommandTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/SetAclCommandTest.php index 1ceaca1002019..5ecbf47078afe 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/SetAclCommandTest.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/SetAclCommandTest.php @@ -20,7 +20,6 @@ * file that was distributed with this source code. */ use Symfony\Bundle\FrameworkBundle\Console\Application; -use Symfony\Bundle\SecurityBundle\Command\InitAclCommand; use Symfony\Bundle\SecurityBundle\Command\SetAclCommand; use Symfony\Component\Console\Tester\CommandTester; use Symfony\Component\Security\Acl\Domain\ObjectIdentity; @@ -170,7 +169,6 @@ private function getApplication() $kernel->boot(); $application = new Application($kernel); - $application->add(new InitAclCommand($kernel->getContainer()->get('security.acl.dbal.connection'), $kernel->getContainer()->get('security.acl.dbal.schema'))); $initAclCommand = $application->find('init:acl'); $initAclCommandTester = new CommandTester($initAclCommand); diff --git a/src/Symfony/Bundle/SecurityBundle/composer.json b/src/Symfony/Bundle/SecurityBundle/composer.json index b1421742766de..38bf0220536d5 100644 --- a/src/Symfony/Bundle/SecurityBundle/composer.json +++ b/src/Symfony/Bundle/SecurityBundle/composer.json @@ -26,7 +26,7 @@ "require-dev": { "symfony/asset": "~2.8|~3.0|~4.0", "symfony/browser-kit": "~2.8|~3.0|~4.0", - "symfony/console": "~3.2|~4.0", + "symfony/console": "~3.4|~4.0", "symfony/css-selector": "~2.8|~3.0|~4.0", "symfony/dom-crawler": "~2.8|~3.0|~4.0", "symfony/event-dispatcher": "^3.3.1|~4.0", @@ -47,7 +47,8 @@ }, "conflict": { "symfony/var-dumper": "<3.3", - "symfony/event-dispatcher": "<3.3.1" + "symfony/event-dispatcher": "<3.3.1", + "symfony/console": "<3.4" }, "suggest": { "symfony/security-acl": "For using the ACL functionality of this bundle" diff --git a/src/Symfony/Component/Console/CHANGELOG.md b/src/Symfony/Component/Console/CHANGELOG.md index 26687bf68dfec..24d7ff7af40e0 100644 --- a/src/Symfony/Component/Console/CHANGELOG.md +++ b/src/Symfony/Component/Console/CHANGELOG.md @@ -7,7 +7,10 @@ CHANGELOG * added `CommandLoaderInterface`, `FactoryCommandLoader` and PSR-11 `ContainerCommandLoader` for commands lazy-loading * added a case-insensitive command name matching fallback - * added `DefaultNameProviderInterface` + * added static `Command::$defaultName/getDefaultName()`, allowing for + commands to be registered at compile time in the application command loader. + Setting the `$defaultName` property avoids the need for filling the `command` + attribute on the `console.command` tag when using `AddConsoleCommandPass`. 3.3.0 ----- diff --git a/src/Symfony/Component/Console/Command/Command.php b/src/Symfony/Component/Console/Command/Command.php index 6620ff5718c53..bd7059602d2f8 100644 --- a/src/Symfony/Component/Console/Command/Command.php +++ b/src/Symfony/Component/Console/Command/Command.php @@ -29,6 +29,11 @@ */ class Command { + /** + * @var string|null The default command name + */ + protected static $defaultName; + private $application; private $name; private $processTitle; @@ -45,6 +50,17 @@ class Command private $usages = array(); private $helperSet; + /** + * @return string|null The default command name or null when no default name is set + */ + public static function getDefaultName() + { + $class = get_called_class(); + $r = new \ReflectionProperty($class, 'defaultName'); + + return $class === $r->class ? static::$defaultName : null; + } + /** * Constructor. * @@ -56,7 +72,7 @@ public function __construct($name = null) { $this->definition = new InputDefinition(); - if (null !== $name) { + if (null !== $name || null !== $name = static::getDefaultName()) { $this->setName($name); } diff --git a/src/Symfony/Component/Console/Command/DefaultNameProviderInterface.php b/src/Symfony/Component/Console/Command/DefaultNameProviderInterface.php deleted file mode 100644 index af4403ed27a77..0000000000000 --- a/src/Symfony/Component/Console/Command/DefaultNameProviderInterface.php +++ /dev/null @@ -1,26 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Console\Command; - -/** - * Enables lazy-loading capabilities for a Command by exposing its default name. - * - * @author Nicolas Grekas - * @author Robin Chalas - */ -interface DefaultNameProviderInterface -{ - /** - * @return string The name to use by default for calling the Command - */ - public static function getDefaultName(); -} diff --git a/src/Symfony/Component/Console/DependencyInjection/AddConsoleCommandPass.php b/src/Symfony/Component/Console/DependencyInjection/AddConsoleCommandPass.php index 098057a52b064..add7c5d0df491 100644 --- a/src/Symfony/Component/Console/DependencyInjection/AddConsoleCommandPass.php +++ b/src/Symfony/Component/Console/DependencyInjection/AddConsoleCommandPass.php @@ -12,7 +12,6 @@ namespace Symfony\Component\Console\DependencyInjection; use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Command\DefaultNameProviderInterface; use Symfony\Component\Console\CommandLoader\ContainerCommandLoader; use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; use Symfony\Component\DependencyInjection\Compiler\ServiceLocatorTagPass; @@ -47,16 +46,21 @@ public function process(ContainerBuilder $container) $definition = $container->getDefinition($id); $class = $container->getParameterBag()->resolveValue($definition->getClass()); - if (!$r = $container->getReflectionClass($class)) { - throw new InvalidArgumentException(sprintf('Class "%s" used for service "%s" cannot be found.', $class, $id)); - } - if (!$r->isSubclassOf(Command::class)) { - throw new InvalidArgumentException(sprintf('The service "%s" tagged "%s" must be a subclass of "%s".', $id, $this->commandTag, Command::class)); - } - $commandId = 'console.command.'.strtolower(str_replace('\\', '_', $class)); - if (!isset($tags[0]['command']) && !$r->implementsInterface(DefaultNameProviderInterface::class)) { + if (isset($tags[0]['command'])) { + $commandName = $tags[0]['command']; + } else { + if (!$r = $container->getReflectionClass($class)) { + throw new InvalidArgumentException(sprintf('Class "%s" used for service "%s" cannot be found.', $class, $id)); + } + if (!$r->isSubclassOf(Command::class)) { + throw new InvalidArgumentException(sprintf('The service "%s" tagged "%s" must be a subclass of "%s".', $id, $this->commandTag, Command::class)); + } + $commandName = $class::getDefaultName(); + } + + if (null === $commandName) { if (isset($serviceIds[$commandId]) || $container->hasAlias($commandId)) { $commandId = $commandId.'_'.$id; } @@ -70,7 +74,6 @@ public function process(ContainerBuilder $container) } $serviceIds[$commandId] = false; - $commandName = isset($tags[0]['command']) ? $tags[0]['command'] : $class::getDefaultName(); unset($tags[0]); $lazyCommandMap[$commandName] = $id; $lazyCommandRefs[$id] = new TypedReference($id, $class); diff --git a/src/Symfony/Component/Console/Tests/DependencyInjection/AddConsoleCommandPassTest.php b/src/Symfony/Component/Console/Tests/DependencyInjection/AddConsoleCommandPassTest.php index b7fce4a5fb497..807eb389730fe 100644 --- a/src/Symfony/Component/Console/Tests/DependencyInjection/AddConsoleCommandPassTest.php +++ b/src/Symfony/Component/Console/Tests/DependencyInjection/AddConsoleCommandPassTest.php @@ -12,7 +12,6 @@ namespace Symfony\Component\Console\Tests\DependencyInjection; use PHPUnit\Framework\TestCase; -use Symfony\Component\Console\Command\DefaultNameProviderInterface; use Symfony\Component\Console\CommandLoader\ContainerCommandLoader; use Symfony\Component\Console\DependencyInjection\AddConsoleCommandPass; use Symfony\Component\Console\Command\Command; @@ -129,7 +128,7 @@ public function testProcessThrowAnExceptionIfTheServiceIsAbstract() $container->addCompilerPass(new AddConsoleCommandPass()); $definition = new Definition('Symfony\Component\Console\Tests\DependencyInjection\MyCommand'); - $definition->addTag('console.command', array('command' => 'my:command')); + $definition->addTag('console.command'); $definition->setAbstract(true); $container->setDefinition('my-command', $definition); @@ -147,7 +146,7 @@ public function testProcessThrowAnExceptionIfTheServiceIsNotASubclassOfCommand() $container->addCompilerPass(new AddConsoleCommandPass()); $definition = new Definition('SplObjectStorage'); - $definition->addTag('console.command', array('command' => 'my:command')); + $definition->addTag('console.command'); $container->setDefinition('my-command', $definition); $container->compile(); @@ -180,10 +179,7 @@ class MyCommand extends Command { } -class NamedCommand extends Command implements DefaultNameProviderInterface +class NamedCommand extends Command { - public static function getDefaultName() - { - return 'default'; - } + protected static $defaultName = 'default'; } diff --git a/src/Symfony/Component/Translation/Command/XliffLintCommand.php b/src/Symfony/Component/Translation/Command/XliffLintCommand.php index 80d8bb25dca2b..fead5edcb18bb 100644 --- a/src/Symfony/Component/Translation/Command/XliffLintCommand.php +++ b/src/Symfony/Component/Translation/Command/XliffLintCommand.php @@ -26,6 +26,8 @@ */ class XliffLintCommand extends Command { + protected static $defaultName = 'lint:xliff'; + private $format; private $displayCorrectFiles; private $directoryIteratorProvider; @@ -45,7 +47,6 @@ public function __construct($name = null, $directoryIteratorProvider = null, $is protected function configure() { $this - ->setName('lint:xliff') ->setDescription('Lints a XLIFF file and outputs encountered errors') ->addArgument('filename', null, 'A file or a directory or STDIN') ->addOption('format', null, InputOption::VALUE_REQUIRED, 'The output format', 'txt') diff --git a/src/Symfony/Component/Yaml/Command/LintCommand.php b/src/Symfony/Component/Yaml/Command/LintCommand.php index 36025bdebb8b7..202291551b57f 100644 --- a/src/Symfony/Component/Yaml/Command/LintCommand.php +++ b/src/Symfony/Component/Yaml/Command/LintCommand.php @@ -28,6 +28,8 @@ */ class LintCommand extends Command { + protected static $defaultName = 'lint:yaml'; + private $parser; private $format; private $displayCorrectFiles; @@ -48,7 +50,6 @@ public function __construct($name = null, $directoryIteratorProvider = null, $is protected function configure() { $this - ->setName('lint:yaml') ->setDescription('Lints a file and outputs encountered errors') ->addArgument('filename', null, 'A file or a directory or STDIN') ->addOption('format', null, InputOption::VALUE_REQUIRED, 'The output format', 'txt') diff --git a/src/Symfony/Component/Yaml/composer.json b/src/Symfony/Component/Yaml/composer.json index 41f04fb9f9543..a31a2cef426eb 100644 --- a/src/Symfony/Component/Yaml/composer.json +++ b/src/Symfony/Component/Yaml/composer.json @@ -19,7 +19,10 @@ "php": "^5.5.9|>=7.0.8" }, "require-dev": { - "symfony/console": "~2.8|~3.0|~4.0" + "symfony/console": "~3.4|~4.0" + }, + "conflict": { + "symfony/console": "<3.4" }, "suggest": { "symfony/console": "For validating YAML files using the lint command" From d8c400bf582e3b11f6c78179b1e38fefec3ad8e1 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Thu, 24 Aug 2017 09:48:32 +0200 Subject: [PATCH 0670/1099] [Cache] Fix lazy Memcached connections --- .../Component/Cache/Traits/MemcachedTrait.php | 45 ++++++++++++++----- 1 file changed, 35 insertions(+), 10 deletions(-) diff --git a/src/Symfony/Component/Cache/Traits/MemcachedTrait.php b/src/Symfony/Component/Cache/Traits/MemcachedTrait.php index 9dc44355c042a..8a836bac18c45 100644 --- a/src/Symfony/Component/Cache/Traits/MemcachedTrait.php +++ b/src/Symfony/Component/Cache/Traits/MemcachedTrait.php @@ -30,6 +30,7 @@ trait MemcachedTrait ); private $client; + private $lazyClient; public static function isSupported() { @@ -41,14 +42,18 @@ private function init(\Memcached $client, $namespace, $defaultLifetime) if (!static::isSupported()) { throw new CacheException('Memcached >= 2.2.0 is required'); } - $opt = $client->getOption(\Memcached::OPT_SERIALIZER); - if (\Memcached::SERIALIZER_PHP !== $opt && \Memcached::SERIALIZER_IGBINARY !== $opt) { - throw new CacheException('MemcachedAdapter: "serializer" option must be "php" or "igbinary".'); + if (get_class($client) === 'Memcached') { + $opt = $client->getOption(\Memcached::OPT_SERIALIZER); + if (\Memcached::SERIALIZER_PHP !== $opt && \Memcached::SERIALIZER_IGBINARY !== $opt) { + throw new CacheException('MemcachedAdapter: "serializer" option must be "php" or "igbinary".'); + } + $this->maxIdLength -= strlen($client->getOption(\Memcached::OPT_PREFIX_KEY)); + $this->client = $client; + } else { + $this->lazyClient = $client; } - $this->maxIdLength -= strlen($client->getOption(\Memcached::OPT_PREFIX_KEY)); parent::__construct($namespace, $defaultLifetime); - $this->client = $client; } /** @@ -191,7 +196,7 @@ protected function doSave(array $values, $lifetime) $lifetime += time(); } - return $this->checkResultCode($this->client->setMulti($values, $lifetime)); + return $this->checkResultCode($this->getClient()->setMulti($values, $lifetime)); } /** @@ -201,7 +206,7 @@ protected function doFetch(array $ids) { $unserializeCallbackHandler = ini_set('unserialize_callback_func', __CLASS__.'::handleUnserializeCallback'); try { - return $this->checkResultCode($this->client->getMulti($ids)); + return $this->checkResultCode($this->getClient()->getMulti($ids)); } catch (\Error $e) { throw new \ErrorException($e->getMessage(), $e->getCode(), E_ERROR, $e->getFile(), $e->getLine()); } finally { @@ -214,7 +219,7 @@ protected function doFetch(array $ids) */ protected function doHave($id) { - return false !== $this->client->get($id) || $this->checkResultCode(\Memcached::RES_SUCCESS === $this->client->getResultCode()); + return false !== $this->getClient()->get($id) || $this->checkResultCode(\Memcached::RES_SUCCESS === $this->client->getResultCode()); } /** @@ -223,7 +228,7 @@ protected function doHave($id) protected function doDelete(array $ids) { $ok = true; - foreach ($this->checkResultCode($this->client->deleteMulti($ids)) as $result) { + foreach ($this->checkResultCode($this->getClient()->deleteMulti($ids)) as $result) { if (\Memcached::RES_SUCCESS !== $result && \Memcached::RES_NOTFOUND !== $result) { $ok = false; } @@ -237,7 +242,7 @@ protected function doDelete(array $ids) */ protected function doClear($namespace) { - return $this->checkResultCode($this->client->flush()); + return $this->checkResultCode($this->getClient()->flush()); } private function checkResultCode($result) @@ -250,4 +255,24 @@ private function checkResultCode($result) throw new CacheException(sprintf('MemcachedAdapter client error: %s.', strtolower($this->client->getResultMessage()))); } + + /** + * @return \Memcached + */ + private function getClient() + { + if ($this->client) { + return $this->client; + } + + $opt = $this->lazyClient->getOption(\Memcached::OPT_SERIALIZER); + if (\Memcached::SERIALIZER_PHP !== $opt && \Memcached::SERIALIZER_IGBINARY !== $opt) { + throw new CacheException('MemcachedAdapter: "serializer" option must be "php" or "igbinary".'); + } + if ('' !== $prefix = (string) $this->lazyClient->getOption(\Memcached::OPT_PREFIX_KEY)) { + throw new CacheException(sprintf('MemcachedAdapter: "prefix_key" option must be empty when using proxified connections, "%s" given.', $prefix)); + } + + return $this->client = $this->lazyClient; + } } From 5e05fc958f9d17a23f58b9dba2856b8a7a8a5350 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Fri, 25 Aug 2017 13:47:49 +0200 Subject: [PATCH 0671/1099] [VarDumper] Strengthen dumped JS --- .../Component/VarDumper/Dumper/HtmlDumper.php | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/Symfony/Component/VarDumper/Dumper/HtmlDumper.php b/src/Symfony/Component/VarDumper/Dumper/HtmlDumper.php index cf94b1af93039..02ec543b5a706 100644 --- a/src/Symfony/Component/VarDumper/Dumper/HtmlDumper.php +++ b/src/Symfony/Component/VarDumper/Dumper/HtmlDumper.php @@ -187,7 +187,7 @@ function toggle(a, recursive) { function collapse(a, recursive) { var s = a.nextSibling || {}, oldClass = s.className; - if ('sf-dump-expanded' == oldClass) { + if (/\bsf-dump-expanded\b/.test(oldClass)) { toggle(a, recursive); return true; @@ -199,7 +199,7 @@ function collapse(a, recursive) { function expand(a, recursive) { var s = a.nextSibling || {}, oldClass = s.className; - if ('sf-dump-compact' == oldClass) { + if (/\bsf-dump-compact\b/.test(oldClass)) { toggle(a, recursive); return true; @@ -254,8 +254,8 @@ function highlight(root, activeNode, nodes) { function resetHighlightedNodes(root) { Array.from(root.querySelectorAll('.sf-dump-str, .sf-dump-key, .sf-dump-public, .sf-dump-protected, .sf-dump-private')).forEach(function (strNode) { - strNode.className = strNode.className.replace(/\b sf-dump-highlight\b/, ''); - strNode.className = strNode.className.replace(/\b sf-dump-highlight-active\b/, ''); + strNode.className = strNode.className.replace(/\bsf-dump-highlight\b/, ''); + strNode.className = strNode.className.replace(/\bsf-dump-highlight-active\b/, ''); }); } @@ -352,7 +352,7 @@ function xpathString(str) { } else if (/\bsf-dump-str-toggle\b/.test(a.className)) { e.preventDefault(); e = a.parentNode.parentNode; - e.className = e.className.replace(/sf-dump-str-(expand|collapse)/, a.parentNode.className); + e.className = e.className.replace(/\bsf-dump-str-(expand|collapse)\b/, a.parentNode.className); } }); @@ -518,8 +518,7 @@ function showCurrent(state) Array.from(search.querySelectorAll('.sf-dump-search-input-next, .sf-dump-search-input-previous')).forEach(function (btn) { addEventListener(btn, 'click', function (e) { e.preventDefault(); - var direction = -1 !== e.target.className.indexOf('next') ? 'next' : 'previous'; - 'next' === direction ? state.next() : state.previous(); + -1 !== e.target.className.indexOf('next') ? state.next() : state.previous(); searchInput.focus(); collapseAll(root); showCurrent(state); From 5c1bd1001761d9edcd3aa05a5f64318a74909842 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Fri, 25 Aug 2017 13:47:49 +0200 Subject: [PATCH 0672/1099] [VarDumper] Strengthen dumped JS --- .../Component/VarDumper/Dumper/HtmlDumper.php | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/Symfony/Component/VarDumper/Dumper/HtmlDumper.php b/src/Symfony/Component/VarDumper/Dumper/HtmlDumper.php index 4f572caea3f8c..28596bf83d1ce 100644 --- a/src/Symfony/Component/VarDumper/Dumper/HtmlDumper.php +++ b/src/Symfony/Component/VarDumper/Dumper/HtmlDumper.php @@ -132,10 +132,10 @@ protected function getDumpHeader() function toggle(a, recursive) { var s = a.nextSibling || {}, oldClass = s.className, arrow, newClass; - if ('sf-dump-compact' == oldClass) { + if (/\bsf-dump-compact\b/.test(oldClass)) { arrow = '▼'; newClass = 'sf-dump-expanded'; - } else if ('sf-dump-expanded' == oldClass) { + } else if (/\bsf-dump-expanded\b/.test(oldClass)) { arrow = '▶'; newClass = 'sf-dump-compact'; } else { @@ -143,13 +143,13 @@ function toggle(a, recursive) { } a.lastChild.innerHTML = arrow; - s.className = newClass; + s.className = s.className.replace(/\bsf-dump-(compact|expanded)\b/, newClass); if (recursive) { try { a = s.querySelectorAll('.'+oldClass); for (s = 0; s < a.length; ++s) { - if (a[s].className !== newClass) { + if (-1 == a[s].className.indexOf(newClass)) { a[s].className = newClass; a[s].previousSibling.lastChild.innerHTML = arrow; } @@ -205,7 +205,7 @@ function isCtrlKey(e) { if (f && t && f[0] !== t[0]) { r.innerHTML = r.innerHTML.replace(new RegExp('^'+f[0].replace(rxEsc, '\\$1'), 'mg'), t[0]); } - if ('sf-dump-compact' == r.className) { + if (/\bsf-dump-compact\b/.test(r.className)) { toggle(s, isCtrlKey(e)); } } @@ -255,10 +255,10 @@ function isCtrlKey(e) { a.title = (a.title ? a.title+'\n[' : '[')+keyHint+'+click] Expand all children'; a.innerHTML += ''; a.className += ' sf-dump-toggle'; - if ('sf-dump' != elt.parentNode.className) { + if (!/\bsf-dump\b/.test(elt.parentNode.className)) { toggle(a); } - } else if ("sf-dump-ref" == elt.className && (a = elt.getAttribute('href'))) { + } else if (/\bsf-dump-ref\b/.test(elt.className) && (a = elt.getAttribute('href'))) { a = a.substr(1); elt.className += ' '+a; From 1cab07ebee6dbf2e10d14a3eaebb156b10511f39 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Fri, 25 Aug 2017 17:28:27 +0200 Subject: [PATCH 0673/1099] [Cache] Workaround zend.detect_unicode + zend.multibyte --- .../Component/Cache/Adapter/PhpArrayAdapter.php | 1 + .../Component/Cache/Adapter/PhpFilesAdapter.php | 1 + .../Component/Cache/Simple/PhpArrayCache.php | 1 + .../Component/Cache/Simple/PhpFilesCache.php | 1 + .../Component/Cache/Traits/PhpArrayTrait.php | 14 ++++++++++++-- .../Component/Cache/Traits/PhpFilesTrait.php | 7 +++++++ 6 files changed, 23 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/Cache/Adapter/PhpArrayAdapter.php b/src/Symfony/Component/Cache/Adapter/PhpArrayAdapter.php index ea102ddbf75fb..889a97f80a5fb 100644 --- a/src/Symfony/Component/Cache/Adapter/PhpArrayAdapter.php +++ b/src/Symfony/Component/Cache/Adapter/PhpArrayAdapter.php @@ -38,6 +38,7 @@ public function __construct($file, AdapterInterface $fallbackPool) { $this->file = $file; $this->fallbackPool = $fallbackPool; + $this->zendMultiByte = ini_get('zend.multibyte'); $this->createCacheItem = \Closure::bind( function ($key, $value, $isHit) { $item = new CacheItem(); diff --git a/src/Symfony/Component/Cache/Adapter/PhpFilesAdapter.php b/src/Symfony/Component/Cache/Adapter/PhpFilesAdapter.php index fee500dbfc7e2..75ac9092df024 100644 --- a/src/Symfony/Component/Cache/Adapter/PhpFilesAdapter.php +++ b/src/Symfony/Component/Cache/Adapter/PhpFilesAdapter.php @@ -35,5 +35,6 @@ public function __construct($namespace = '', $defaultLifetime = 0, $directory = $e = new \Exception(); $this->includeHandler = function () use ($e) { throw $e; }; + $this->zendMultiByte = ini_get('zend.multibyte'); } } diff --git a/src/Symfony/Component/Cache/Simple/PhpArrayCache.php b/src/Symfony/Component/Cache/Simple/PhpArrayCache.php index c65b8fffaac41..d4c3926548ca3 100644 --- a/src/Symfony/Component/Cache/Simple/PhpArrayCache.php +++ b/src/Symfony/Component/Cache/Simple/PhpArrayCache.php @@ -34,6 +34,7 @@ public function __construct($file, CacheInterface $fallbackPool) { $this->file = $file; $this->fallbackPool = $fallbackPool; + $this->zendMultiByte = ini_get('zend.multibyte'); } /** diff --git a/src/Symfony/Component/Cache/Simple/PhpFilesCache.php b/src/Symfony/Component/Cache/Simple/PhpFilesCache.php index 810b80f81275c..02273ada7a32a 100644 --- a/src/Symfony/Component/Cache/Simple/PhpFilesCache.php +++ b/src/Symfony/Component/Cache/Simple/PhpFilesCache.php @@ -35,5 +35,6 @@ public function __construct($namespace = '', $defaultLifetime = 0, $directory = $e = new \Exception(); $this->includeHandler = function () use ($e) { throw $e; }; + $this->zendMultiByte = ini_get('zend.multibyte'); } } diff --git a/src/Symfony/Component/Cache/Traits/PhpArrayTrait.php b/src/Symfony/Component/Cache/Traits/PhpArrayTrait.php index 2d2c7db3d014f..b57e4e0b98de3 100644 --- a/src/Symfony/Component/Cache/Traits/PhpArrayTrait.php +++ b/src/Symfony/Component/Cache/Traits/PhpArrayTrait.php @@ -25,6 +25,7 @@ trait PhpArrayTrait private $file; private $values; private $fallbackPool; + private $zendMultiByte; /** * Store an array of cached values. @@ -106,7 +107,7 @@ public function warmUp(array $values) @rename($tmpFile, $this->file); - $this->values = (include $this->file) ?: array(); + $this->initialize(); } /** @@ -126,6 +127,15 @@ public function clear() */ private function initialize() { - $this->values = file_exists($this->file) ? (include $this->file ?: array()) : array(); + if ($this->zendMultiByte) { + $zmb = ini_set('zend.multibyte', 0); + } + try { + $this->values = file_exists($this->file) ? (include $this->file ?: array()) : array(); + } finally { + if ($this->zendMultiByte) { + ini_set('zend.multibyte', $zmb); + } + } } } diff --git a/src/Symfony/Component/Cache/Traits/PhpFilesTrait.php b/src/Symfony/Component/Cache/Traits/PhpFilesTrait.php index 259caf0c74168..d9d976a023a30 100644 --- a/src/Symfony/Component/Cache/Traits/PhpFilesTrait.php +++ b/src/Symfony/Component/Cache/Traits/PhpFilesTrait.php @@ -25,6 +25,7 @@ trait PhpFilesTrait use FilesystemCommonTrait; private $includeHandler; + private $zendMultiByte; public static function isSupported() { @@ -39,6 +40,9 @@ protected function doFetch(array $ids) $values = array(); $now = time(); + if ($this->zendMultiByte) { + $zmb = ini_set('zend.multibyte', 0); + } set_error_handler($this->includeHandler); try { foreach ($ids as $id) { @@ -54,6 +58,9 @@ protected function doFetch(array $ids) } } finally { restore_error_handler(); + if ($this->zendMultiByte) { + ini_set('zend.multibyte', $zmb); + } } foreach ($values as $id => $value) { From c7601cb40ea87a727396ff6d0d05907c16b62abf Mon Sep 17 00:00:00 2001 From: Billie Thompson Date: Fri, 25 Aug 2017 17:06:14 +0100 Subject: [PATCH 0674/1099] Change number PHPDoc type to int|float While number is a valid type inside PHP internally, it's not a part of the PHPDoc standard. This causes IDEs and static analysers to raise errors on this function. The internal PHP type `number` is the same as `int|float`, this changes the type to that. https://php.net/manual/en/language.pseudo-types.php#language.types.number https://github.com/php-fig/fig-standards/blob/master/proposed/phpdoc.md#keyword --- .../Component/Intl/NumberFormatter/NumberFormatter.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Component/Intl/NumberFormatter/NumberFormatter.php b/src/Symfony/Component/Intl/NumberFormatter/NumberFormatter.php index 50ee30a217da1..ce03e9f5d6642 100644 --- a/src/Symfony/Component/Intl/NumberFormatter/NumberFormatter.php +++ b/src/Symfony/Component/Intl/NumberFormatter/NumberFormatter.php @@ -355,9 +355,9 @@ public function formatCurrency($value, $currency) /** * Format a number. * - * @param number $value The value to format - * @param int $type Type of the formatting, one of the format type constants - * Only type NumberFormatter::TYPE_DEFAULT is currently supported. + * @param int|float $value The value to format + * @param int $type Type of the formatting, one of the format type constants + * Only type NumberFormatter::TYPE_DEFAULT is currently supported. * * @return bool|string The formatted value or false on error * From 8f2fa6b047243ed6424e805ee767b6c15eca8fc9 Mon Sep 17 00:00:00 2001 From: GDIBass Date: Fri, 25 Aug 2017 11:25:19 -0700 Subject: [PATCH 0675/1099] changed exception message --- src/Symfony/Component/Workflow/EventListener/GuardListener.php | 2 +- .../Workflow/Exception/InvalidTokenConfigurationException.php | 2 +- .../Workflow/Tests/EventListener/GuardListenerTest.php | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Component/Workflow/EventListener/GuardListener.php b/src/Symfony/Component/Workflow/EventListener/GuardListener.php index 5d10cbcfceee4..8726e4bddca47 100644 --- a/src/Symfony/Component/Workflow/EventListener/GuardListener.php +++ b/src/Symfony/Component/Workflow/EventListener/GuardListener.php @@ -57,7 +57,7 @@ private function getVariables(GuardEvent $event) $token = $this->tokenStorage->getToken(); if (null === $token) { - throw new InvalidTokenConfigurationException('No token is set'); + throw new InvalidTokenConfigurationException(sprintf('There are no token available for workflow %s', $event->getWorkflowName())); } if (null !== $this->roleHierarchy) { diff --git a/src/Symfony/Component/Workflow/Exception/InvalidTokenConfigurationException.php b/src/Symfony/Component/Workflow/Exception/InvalidTokenConfigurationException.php index 681d7a8bba52d..85ada5e78071b 100644 --- a/src/Symfony/Component/Workflow/Exception/InvalidTokenConfigurationException.php +++ b/src/Symfony/Component/Workflow/Exception/InvalidTokenConfigurationException.php @@ -18,4 +18,4 @@ */ class InvalidTokenConfigurationException extends LogicException implements ExceptionInterface { -} +} \ No newline at end of file diff --git a/src/Symfony/Component/Workflow/Tests/EventListener/GuardListenerTest.php b/src/Symfony/Component/Workflow/Tests/EventListener/GuardListenerTest.php index c32aec06a45be..0e2dbc13bc53d 100644 --- a/src/Symfony/Component/Workflow/Tests/EventListener/GuardListenerTest.php +++ b/src/Symfony/Component/Workflow/Tests/EventListener/GuardListenerTest.php @@ -71,7 +71,7 @@ public function testWithSupportedEventAndAccept() /** * @expectedException \Symfony\Component\Workflow\Exception\InvalidTokenConfigurationException - * @expectedExceptionMessage No token is set + * @expectedExceptionMessage There are no token available for workflow unnamed */ public function testWithNoTokenStorage() { From fefc20233b081691b428358d8c05b395ef8cc7af Mon Sep 17 00:00:00 2001 From: GDIBass Date: Fri, 25 Aug 2017 11:26:09 -0700 Subject: [PATCH 0676/1099] newline at end of file --- .../Workflow/Exception/InvalidTokenConfigurationException.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/Workflow/Exception/InvalidTokenConfigurationException.php b/src/Symfony/Component/Workflow/Exception/InvalidTokenConfigurationException.php index 85ada5e78071b..681d7a8bba52d 100644 --- a/src/Symfony/Component/Workflow/Exception/InvalidTokenConfigurationException.php +++ b/src/Symfony/Component/Workflow/Exception/InvalidTokenConfigurationException.php @@ -18,4 +18,4 @@ */ class InvalidTokenConfigurationException extends LogicException implements ExceptionInterface { -} \ No newline at end of file +} From b0cdb53d67035d95875018c7aeab2c158a6b8308 Mon Sep 17 00:00:00 2001 From: Tobias Nyholm Date: Sat, 19 Aug 2017 14:09:44 +0200 Subject: [PATCH 0677/1099] [Translation] Adding the ability do load in xliff2.0 --- .../Component/Translation/CHANGELOG.md | 1 + .../Translation/Loader/XliffFileLoader.php | 15 ++++++- .../Tests/Dumper/XliffFileDumperTest.php | 5 +++ .../Tests/Loader/XliffFileLoaderTest.php | 40 +++++++++++++++++++ .../Tests/fixtures/resources-notes-meta.xlf | 10 +++++ 5 files changed, 70 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/Translation/CHANGELOG.md b/src/Symfony/Component/Translation/CHANGELOG.md index c973ea2a69ef7..3a78140153279 100644 --- a/src/Symfony/Component/Translation/CHANGELOG.md +++ b/src/Symfony/Component/Translation/CHANGELOG.md @@ -8,6 +8,7 @@ CHANGELOG * Added `TranslationExtractorPass` * Added `TranslatorPass` * Added section to the Xliff 2.0 dumper. + * Improved Xliff 2.0 loader to load section. * Added `TranslationWriterInterface` * Deprecated `TranslationWriter::writeTranslations` in favor of `TranslationWriter::write` diff --git a/src/Symfony/Component/Translation/Loader/XliffFileLoader.php b/src/Symfony/Component/Translation/Loader/XliffFileLoader.php index 1603dc0b04fdb..72f7216729c1e 100644 --- a/src/Symfony/Component/Translation/Loader/XliffFileLoader.php +++ b/src/Symfony/Component/Translation/Loader/XliffFileLoader.php @@ -127,7 +127,8 @@ private function extractXliff2(\DOMDocument $dom, MessageCatalogue $catalogue, $ $xml->registerXPathNamespace('xliff', 'urn:oasis:names:tc:xliff:document:2.0'); - foreach ($xml->xpath('//xliff:unit/xliff:segment') as $segment) { + foreach ($xml->xpath('//xliff:unit') as $unit) { + $segment = $unit->segment; $source = $segment->source; // If the xlf file has another encoding specified, try to convert it because @@ -144,6 +145,18 @@ private function extractXliff2(\DOMDocument $dom, MessageCatalogue $catalogue, $ } } + if (isset($unit->notes)) { + $metadata['notes'] = array(); + foreach ($unit->notes->note as $noteNode) { + $note = array(); + foreach ($noteNode->attributes() as $key => $value) { + $note[$key] = (string) $value; + } + $note['content'] = (string) $noteNode; + $metadata['notes'][] = $note; + } + } + $catalogue->setMetadata((string) $source, $metadata, $domain); } } diff --git a/src/Symfony/Component/Translation/Tests/Dumper/XliffFileDumperTest.php b/src/Symfony/Component/Translation/Tests/Dumper/XliffFileDumperTest.php index 30ca4d3d24868..738d4b3b2f1e6 100644 --- a/src/Symfony/Component/Translation/Tests/Dumper/XliffFileDumperTest.php +++ b/src/Symfony/Component/Translation/Tests/Dumper/XliffFileDumperTest.php @@ -93,12 +93,17 @@ public function testFormatCatalogueWithNotesMetadata() $catalogue = new MessageCatalogue('en_US'); $catalogue->add(array( 'foo' => 'bar', + 'baz' => 'biz', )); $catalogue->setMetadata('foo', array('notes' => array( array('category' => 'state', 'content' => 'new'), array('category' => 'approved', 'content' => 'true'), array('category' => 'section', 'content' => 'user login', 'priority' => '1'), ))); + $catalogue->setMetadata('baz', array('notes' => array( + array('id' => 'x', 'content' => 'x_content'), + array('appliesTo' => 'target', 'category' => 'quality', 'content' => 'Fuzzy'), + ))); $dumper = new XliffFileDumper(); diff --git a/src/Symfony/Component/Translation/Tests/Loader/XliffFileLoaderTest.php b/src/Symfony/Component/Translation/Tests/Loader/XliffFileLoaderTest.php index 32351d34e1924..a06b7c0990766 100644 --- a/src/Symfony/Component/Translation/Tests/Loader/XliffFileLoaderTest.php +++ b/src/Symfony/Component/Translation/Tests/Loader/XliffFileLoaderTest.php @@ -188,4 +188,44 @@ public function testLoadVersion2() // target attributes $this->assertEquals(array('target-attributes' => array('order' => 1)), $catalogue->getMetadata('bar', 'domain1')); } + + public function testLoadVersion2WithNoteMeta() + { + $loader = new XliffFileLoader(); + $resource = __DIR__.'/../fixtures/resources-notes-meta.xlf'; + $catalogue = $loader->load($resource, 'en', 'domain1'); + + $this->assertEquals('en', $catalogue->getLocale()); + $this->assertEquals(array(new FileResource($resource)), $catalogue->getResources()); + $this->assertSame(array(), libxml_get_errors()); + + // test for "foo" metadata + $this->assertTrue($catalogue->defines('foo', 'domain1')); + $metadata = $catalogue->getMetadata('foo', 'domain1'); + $this->assertNotEmpty($metadata); + $this->assertCount(3, $metadata['notes']); + + $this->assertEquals('state', $metadata['notes'][0]['category']); + $this->assertEquals('new', $metadata['notes'][0]['content']); + + $this->assertEquals('approved', $metadata['notes'][1]['category']); + $this->assertEquals('true', $metadata['notes'][1]['content']); + + $this->assertEquals('section', $metadata['notes'][2]['category']); + $this->assertEquals('1', $metadata['notes'][2]['priority']); + $this->assertEquals('user login', $metadata['notes'][2]['content']); + + // test for "baz" metadata + $this->assertTrue($catalogue->defines('baz', 'domain1')); + $metadata = $catalogue->getMetadata('baz', 'domain1'); + $this->assertNotEmpty($metadata); + $this->assertCount(2, $metadata['notes']); + + $this->assertEquals('x', $metadata['notes'][0]['id']); + $this->assertEquals('x_content', $metadata['notes'][0]['content']); + + $this->assertEquals('target', $metadata['notes'][1]['appliesTo']); + $this->assertEquals('quality', $metadata['notes'][1]['category']); + $this->assertEquals('Fuzzy', $metadata['notes'][1]['content']); + } } diff --git a/src/Symfony/Component/Translation/Tests/fixtures/resources-notes-meta.xlf b/src/Symfony/Component/Translation/Tests/fixtures/resources-notes-meta.xlf index 04f9a0a06e233..e9995fa8474c0 100644 --- a/src/Symfony/Component/Translation/Tests/fixtures/resources-notes-meta.xlf +++ b/src/Symfony/Component/Translation/Tests/fixtures/resources-notes-meta.xlf @@ -12,5 +12,15 @@ bar + + + x_content + Fuzzy + + + baz + biz + + From 8d7b203d8036f31a9f8d29c639d705dbb74efa39 Mon Sep 17 00:00:00 2001 From: Sergey Linnik Date: Fri, 18 Aug 2017 00:27:11 +0300 Subject: [PATCH 0678/1099] [Validator] Fix use of GroupSequenceProvider in child classes --- .../Validator/Mapping/ClassMetadata.php | 4 ++++ .../GroupSequenceProviderChildEntity.php | 16 ++++++++++++++ .../Tests/Mapping/ClassMetadataTest.php | 22 ++++++++++--------- 3 files changed, 32 insertions(+), 10 deletions(-) create mode 100644 src/Symfony/Component/Validator/Tests/Fixtures/GroupSequenceProviderChildEntity.php diff --git a/src/Symfony/Component/Validator/Mapping/ClassMetadata.php b/src/Symfony/Component/Validator/Mapping/ClassMetadata.php index f895ad40402dc..5b82cf6d5d9d6 100644 --- a/src/Symfony/Component/Validator/Mapping/ClassMetadata.php +++ b/src/Symfony/Component/Validator/Mapping/ClassMetadata.php @@ -381,6 +381,10 @@ public function addGetterMethodConstraints($property, $method, array $constraint */ public function mergeConstraints(ClassMetadata $source) { + if ($source->isGroupSequenceProvider()) { + $this->setGroupSequenceProvider(true); + } + foreach ($source->getConstraints() as $constraint) { $this->addConstraint(clone $constraint); } diff --git a/src/Symfony/Component/Validator/Tests/Fixtures/GroupSequenceProviderChildEntity.php b/src/Symfony/Component/Validator/Tests/Fixtures/GroupSequenceProviderChildEntity.php new file mode 100644 index 0000000000000..be7191f9b6e1d --- /dev/null +++ b/src/Symfony/Component/Validator/Tests/Fixtures/GroupSequenceProviderChildEntity.php @@ -0,0 +1,16 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Validator\Tests\Fixtures; + +class GroupSequenceProviderChildEntity extends GroupSequenceProviderEntity +{ +} diff --git a/src/Symfony/Component/Validator/Tests/Mapping/ClassMetadataTest.php b/src/Symfony/Component/Validator/Tests/Mapping/ClassMetadataTest.php index 9a23e8cf355a0..a3f8a8c1ec8a3 100644 --- a/src/Symfony/Component/Validator/Tests/Mapping/ClassMetadataTest.php +++ b/src/Symfony/Component/Validator/Tests/Mapping/ClassMetadataTest.php @@ -24,6 +24,7 @@ class ClassMetadataTest extends TestCase const CLASSNAME = 'Symfony\Component\Validator\Tests\Fixtures\Entity'; const PARENTCLASS = 'Symfony\Component\Validator\Tests\Fixtures\EntityParent'; const PROVIDERCLASS = 'Symfony\Component\Validator\Tests\Fixtures\GroupSequenceProviderEntity'; + const PROVIDERCHILDCLASS = 'Symfony\Component\Validator\Tests\Fixtures\GroupSequenceProviderChildEntity'; protected $metadata; @@ -301,6 +302,17 @@ public function testGroupSequenceProvider() $this->assertTrue($metadata->isGroupSequenceProvider()); } + public function testMergeConstraintsMergesGroupSequenceProvider() + { + $parent = new ClassMetadata(self::PROVIDERCLASS); + $parent->setGroupSequenceProvider(true); + + $metadata = new ClassMetadata(self::PROVIDERCHILDCLASS); + $metadata->mergeConstraints($parent); + + $this->assertTrue($metadata->isGroupSequenceProvider()); + } + /** * https://github.com/symfony/symfony/issues/11604. */ @@ -309,13 +321,3 @@ public function testGetPropertyMetadataReturnsEmptyArrayWithoutConfiguredMetadat $this->assertCount(0, $this->metadata->getPropertyMetadata('foo'), '->getPropertyMetadata() returns an empty collection if no metadata is configured for the given property'); } } - -class ParentClass -{ - public $example = 0; -} - -class ChildClass extends ParentClass -{ - public $example = 1; // overrides parent property of same name -} From 31d2250f4c7078a6ba69e96f1e7cc54616bbd1f6 Mon Sep 17 00:00:00 2001 From: Sanpi Date: Tue, 11 Apr 2017 21:49:38 +0200 Subject: [PATCH 0679/1099] [config] Add abbitily to deprecate a node --- src/Symfony/Component/Config/CHANGELOG.md | 5 +++ .../Component/Config/Definition/ArrayNode.php | 4 ++ .../Component/Config/Definition/BaseNode.php | 37 +++++++++++++++++++ .../Definition/Builder/NodeDefinition.php | 18 +++++++++ .../Builder/VariableNodeDefinition.php | 1 + .../Definition/Dumper/XmlReferenceDumper.php | 4 ++ .../Definition/Dumper/YamlReferenceDumper.php | 5 +++ .../Dumper/XmlReferenceDumperTest.php | 4 ++ .../Dumper/YamlReferenceDumperTest.php | 2 + .../Configuration/ExampleConfiguration.php | 2 + 10 files changed, 82 insertions(+) diff --git a/src/Symfony/Component/Config/CHANGELOG.md b/src/Symfony/Component/Config/CHANGELOG.md index 4ef4e625ba566..ffa347dbf4976 100644 --- a/src/Symfony/Component/Config/CHANGELOG.md +++ b/src/Symfony/Component/Config/CHANGELOG.md @@ -1,6 +1,11 @@ CHANGELOG ========= +3.4.0 +----- + + * added `setDeprecated()` method to indicate a deprecated node + 3.3.0 ----- diff --git a/src/Symfony/Component/Config/Definition/ArrayNode.php b/src/Symfony/Component/Config/Definition/ArrayNode.php index 457e7a8c92e34..2ffa2a2137fa8 100644 --- a/src/Symfony/Component/Config/Definition/ArrayNode.php +++ b/src/Symfony/Component/Config/Definition/ArrayNode.php @@ -234,6 +234,10 @@ protected function finalizeValue($value) } foreach ($this->children as $name => $child) { + if ($child->isDeprecated()) { + @trigger_error($child->getDeprecationMessage($name, $this->getPath()), E_USER_DEPRECATED); + } + if (!array_key_exists($name, $value)) { if ($child->isRequired()) { $msg = sprintf('The child node "%s" at path "%s" must be configured.', $name, $this->getPath()); diff --git a/src/Symfony/Component/Config/Definition/BaseNode.php b/src/Symfony/Component/Config/Definition/BaseNode.php index dbf36335b69e3..6e6ac1fdb47cf 100644 --- a/src/Symfony/Component/Config/Definition/BaseNode.php +++ b/src/Symfony/Component/Config/Definition/BaseNode.php @@ -29,6 +29,7 @@ abstract class BaseNode implements NodeInterface protected $finalValidationClosures = array(); protected $allowOverwrite = true; protected $required = false; + protected $deprecationMessage = null; protected $equivalentValues = array(); protected $attributes = array(); @@ -141,6 +142,19 @@ public function setRequired($boolean) $this->required = (bool) $boolean; } + /** + * Sets this node as deprecated. + * + * You can use %node% and %path% placeholders in your message to display, + * respectively, the node name and its complete path. + * + * @param string|null $message Deprecated message + */ + public function setDeprecated($message) + { + $this->deprecationMessage = $message; + } + /** * Sets if this node can be overridden. * @@ -181,6 +195,29 @@ public function isRequired() return $this->required; } + /** + * Checks if this node is deprecated. + * + * @return bool + */ + public function isDeprecated() + { + return null !== $this->deprecationMessage; + } + + /** + * Returns the deprecated message. + * + * @param string $node the configuration node name + * @param string $path the path of the node + * + * @return string + */ + public function getDeprecationMessage($node, $path) + { + return strtr($this->deprecationMessage, array('%node%' => $node, '%path%' => $path)); + } + /** * Returns the name of this node. * diff --git a/src/Symfony/Component/Config/Definition/Builder/NodeDefinition.php b/src/Symfony/Component/Config/Definition/Builder/NodeDefinition.php index 1b712a3150bc3..eb212caa44e00 100644 --- a/src/Symfony/Component/Config/Definition/Builder/NodeDefinition.php +++ b/src/Symfony/Component/Config/Definition/Builder/NodeDefinition.php @@ -27,6 +27,7 @@ abstract class NodeDefinition implements NodeParentInterface protected $defaultValue; protected $default = false; protected $required = false; + protected $deprecationMessage = null; protected $merge; protected $allowEmptyValue = true; protected $nullEquivalent; @@ -168,6 +169,23 @@ public function isRequired() return $this; } + /** + * Sets the node as deprecated. + * + * You can use %node% and %path% placeholders in your message to display, + * respectively, the node name and its complete path. + * + * @param string $message Deprecation message + * + * @return $this + */ + public function setDeprecated($message = 'The child node "%node%" at path "%path%" is deprecated.') + { + $this->deprecationMessage = $message; + + return $this; + } + /** * Sets the equivalent value used when the node contains null. * diff --git a/src/Symfony/Component/Config/Definition/Builder/VariableNodeDefinition.php b/src/Symfony/Component/Config/Definition/Builder/VariableNodeDefinition.php index a46b7ea61ded0..26565e1771d84 100644 --- a/src/Symfony/Component/Config/Definition/Builder/VariableNodeDefinition.php +++ b/src/Symfony/Component/Config/Definition/Builder/VariableNodeDefinition.php @@ -54,6 +54,7 @@ protected function createNode() $node->addEquivalentValue(true, $this->trueEquivalent); $node->addEquivalentValue(false, $this->falseEquivalent); $node->setRequired($this->required); + $node->setDeprecated($this->deprecationMessage); if (null !== $this->validation) { $node->setFinalValidationClosures($this->validation->rules); diff --git a/src/Symfony/Component/Config/Definition/Dumper/XmlReferenceDumper.php b/src/Symfony/Component/Config/Definition/Dumper/XmlReferenceDumper.php index ec5460f2f53c7..44cc9ea9ab79b 100644 --- a/src/Symfony/Component/Config/Definition/Dumper/XmlReferenceDumper.php +++ b/src/Symfony/Component/Config/Definition/Dumper/XmlReferenceDumper.php @@ -153,6 +153,10 @@ private function writeNode(NodeInterface $node, $depth = 0, $root = false, $name $comments[] = 'Required'; } + if ($child->isDeprecated()) { + $comments[] = sprintf('Deprecated (%s)', $child->getDeprecationMessage($child->getName(), $child->getPath())); + } + if ($child instanceof EnumNode) { $comments[] = 'One of '.implode('; ', array_map('json_encode', $child->getValues())); } diff --git a/src/Symfony/Component/Config/Definition/Dumper/YamlReferenceDumper.php b/src/Symfony/Component/Config/Definition/Dumper/YamlReferenceDumper.php index 16076354db515..a470e5f9fba67 100644 --- a/src/Symfony/Component/Config/Definition/Dumper/YamlReferenceDumper.php +++ b/src/Symfony/Component/Config/Definition/Dumper/YamlReferenceDumper.php @@ -123,6 +123,11 @@ private function writeNode(NodeInterface $node, $depth = 0, $prototypedArray = f $comments[] = 'Required'; } + // deprecated? + if ($node->isDeprecated()) { + $comments[] = sprintf('Deprecated (%s)', $node->getDeprecationMessage($node->getName(), $node->getPath())); + } + // example if ($example && !is_array($example)) { $comments[] = 'Example: '.$example; diff --git a/src/Symfony/Component/Config/Tests/Definition/Dumper/XmlReferenceDumperTest.php b/src/Symfony/Component/Config/Tests/Definition/Dumper/XmlReferenceDumperTest.php index fd5f9c8cde841..3123c9740a24c 100644 --- a/src/Symfony/Component/Config/Tests/Definition/Dumper/XmlReferenceDumperTest.php +++ b/src/Symfony/Component/Config/Tests/Definition/Dumper/XmlReferenceDumperTest.php @@ -38,6 +38,8 @@ private function getConfigurationAsString() return str_replace("\n", PHP_EOL, <<<'EOL' + + scalarNode('scalar_array_empty')->defaultValue(array())->end() ->scalarNode('scalar_array_defaults')->defaultValue(array('elem1', 'elem2'))->end() ->scalarNode('scalar_required')->isRequired()->end() + ->scalarNode('scalar_deprecated')->setDeprecated()->end() + ->scalarNode('scalar_deprecated_with_message')->setDeprecated('Deprecation custom message for "%node%" at "%path%"')->end() ->scalarNode('node_with_a_looong_name')->end() ->enumNode('enum_with_default')->values(array('this', 'that'))->defaultValue('this')->end() ->enumNode('enum')->values(array('this', 'that'))->end() From f8a75180e0b098c97a55ba21200ed3a2e95b798b Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Thu, 24 Aug 2017 08:39:03 +0200 Subject: [PATCH 0680/1099] [Cache] Use namespace versioning for backends that dont support clearing by keys --- .../Cache/Adapter/AbstractAdapter.php | 2 +- .../Component/Cache/Adapter/ProxyAdapter.php | 2 +- src/Symfony/Component/Cache/CacheItem.php | 4 ++ .../Component/Cache/Simple/AbstractCache.php | 2 +- .../Component/Cache/Tests/CacheItemTest.php | 2 +- .../Component/Cache/Traits/AbstractTrait.php | 46 +++++++++++++++++-- .../Component/Cache/Traits/MemcachedTrait.php | 3 +- .../Component/Cache/Traits/RedisTrait.php | 8 ++-- 8 files changed, 57 insertions(+), 12 deletions(-) diff --git a/src/Symfony/Component/Cache/Adapter/AbstractAdapter.php b/src/Symfony/Component/Cache/Adapter/AbstractAdapter.php index 9bc05fd2b30fd..6b38991b77e1e 100644 --- a/src/Symfony/Component/Cache/Adapter/AbstractAdapter.php +++ b/src/Symfony/Component/Cache/Adapter/AbstractAdapter.php @@ -38,7 +38,7 @@ abstract class AbstractAdapter implements AdapterInterface, LoggerAwareInterface */ protected function __construct($namespace = '', $defaultLifetime = 0) { - $this->namespace = '' === $namespace ? '' : $this->getId($namespace).':'; + $this->namespace = '' === $namespace ? '' : CacheItem::validateKey($namespace).':'; if (null !== $this->maxIdLength && strlen($namespace) > $this->maxIdLength - 24) { throw new InvalidArgumentException(sprintf('Namespace must be %d chars max, %d given ("%s")', $this->maxIdLength - 24, strlen($namespace), $namespace)); } diff --git a/src/Symfony/Component/Cache/Adapter/ProxyAdapter.php b/src/Symfony/Component/Cache/Adapter/ProxyAdapter.php index 4f37ffd731931..cd310be062069 100644 --- a/src/Symfony/Component/Cache/Adapter/ProxyAdapter.php +++ b/src/Symfony/Component/Cache/Adapter/ProxyAdapter.php @@ -35,7 +35,7 @@ public function __construct(CacheItemPoolInterface $pool, $namespace = '', $defa { $this->pool = $pool; $this->poolHash = $poolHash = spl_object_hash($pool); - $this->namespace = '' === $namespace ? '' : $this->getId($namespace); + $this->namespace = '' === $namespace ? '' : CacheItem::validateKey($namespace); $this->namespaceLen = strlen($namespace); $this->createCacheItem = \Closure::bind( function ($key, $innerItem) use ($defaultLifetime, $poolHash) { diff --git a/src/Symfony/Component/Cache/CacheItem.php b/src/Symfony/Component/Cache/CacheItem.php index 55e25de9a9513..d6f629b2abc70 100644 --- a/src/Symfony/Component/Cache/CacheItem.php +++ b/src/Symfony/Component/Cache/CacheItem.php @@ -148,6 +148,8 @@ public function getPreviousTags() * * @param string $key The key to validate * + * @return string + * * @throws InvalidArgumentException When $key is not valid */ public static function validateKey($key) @@ -161,6 +163,8 @@ public static function validateKey($key) if (false !== strpbrk($key, '{}()/\@:')) { throw new InvalidArgumentException(sprintf('Cache key "%s" contains reserved characters {}()/\@:', $key)); } + + return $key; } /** diff --git a/src/Symfony/Component/Cache/Simple/AbstractCache.php b/src/Symfony/Component/Cache/Simple/AbstractCache.php index e4046463f1609..264eb60653339 100644 --- a/src/Symfony/Component/Cache/Simple/AbstractCache.php +++ b/src/Symfony/Component/Cache/Simple/AbstractCache.php @@ -37,7 +37,7 @@ abstract class AbstractCache implements CacheInterface, LoggerAwareInterface protected function __construct($namespace = '', $defaultLifetime = 0) { $this->defaultLifetime = max(0, (int) $defaultLifetime); - $this->namespace = '' === $namespace ? '' : $this->getId($namespace).':'; + $this->namespace = '' === $namespace ? '' : CacheItem::validateKey($namespace).':'; if (null !== $this->maxIdLength && strlen($namespace) > $this->maxIdLength - 24) { throw new InvalidArgumentException(sprintf('Namespace must be %d chars max, %d given ("%s")', $this->maxIdLength - 24, strlen($namespace), $namespace)); } diff --git a/src/Symfony/Component/Cache/Tests/CacheItemTest.php b/src/Symfony/Component/Cache/Tests/CacheItemTest.php index 4e455c64a48cc..daca925fd5b78 100644 --- a/src/Symfony/Component/Cache/Tests/CacheItemTest.php +++ b/src/Symfony/Component/Cache/Tests/CacheItemTest.php @@ -18,7 +18,7 @@ class CacheItemTest extends TestCase { public function testValidKey() { - $this->assertNull(CacheItem::validateKey('foo')); + $this->assertSame('foo', CacheItem::validateKey('foo')); } /** diff --git a/src/Symfony/Component/Cache/Traits/AbstractTrait.php b/src/Symfony/Component/Cache/Traits/AbstractTrait.php index 375ccf7620d83..108ac67c8e12f 100644 --- a/src/Symfony/Component/Cache/Traits/AbstractTrait.php +++ b/src/Symfony/Component/Cache/Traits/AbstractTrait.php @@ -24,6 +24,8 @@ trait AbstractTrait use LoggerAwareTrait; private $namespace; + private $namespaceVersion = ''; + private $versioningIsEnabled = false; private $deferred = array(); /** @@ -102,10 +104,18 @@ public function hasItem($key) */ public function clear() { + if ($cleared = $this->versioningIsEnabled) { + $this->namespaceVersion = 2; + foreach ($this->doFetch(array('@'.$this->namespace)) as $v) { + $this->namespaceVersion = 1 + (int) $v; + } + $this->namespaceVersion .= ':'; + $cleared = $this->doSave(array('@'.$this->namespace => $this->namespaceVersion), 0); + } $this->deferred = array(); try { - return $this->doClear($this->namespace); + return $this->doClear($this->namespace) || $cleared; } catch (\Exception $e) { CacheItem::log($this->logger, 'Failed to clear the cache', array('exception' => $e)); @@ -158,6 +168,27 @@ public function deleteItems(array $keys) return $ok; } + /** + * Enables/disables versioning of items. + * + * When versioning is enabled, clearing the cache is atomic and doesn't require listing existing keys to proceed, + * but old keys may need garbage collection and extra round-trips to the back-end are required. + * + * Calling this method also clears the memoized namespace version and thus forces a resynchonization of it. + * + * @param bool $enable + * + * @return bool the previous state of versioning + */ + public function enableVersioning($enable = true) + { + $wasEnabled = $this->versioningIsEnabled; + $this->versioningIsEnabled = (bool) $enable; + $this->namespaceVersion = ''; + + return $wasEnabled; + } + /** * Like the native unserialize() function but throws an exception if anything goes wrong. * @@ -189,11 +220,18 @@ private function getId($key) { CacheItem::validateKey($key); + if ($this->versioningIsEnabled && '' === $this->namespaceVersion) { + $this->namespaceVersion = '1:'; + foreach ($this->doFetch(array('@'.$this->namespace)) as $v) { + $this->namespaceVersion = $v; + } + } + if (null === $this->maxIdLength) { - return $this->namespace.$key; + return $this->namespace.$this->namespaceVersion.$key; } - if (strlen($id = $this->namespace.$key) > $this->maxIdLength) { - $id = $this->namespace.substr_replace(base64_encode(hash('sha256', $key, true)), ':', -22); + if (strlen($id = $this->namespace.$this->namespaceVersion.$key) > $this->maxIdLength) { + $id = $this->namespace.$this->namespaceVersion.substr_replace(base64_encode(hash('sha256', $key, true)), ':', -22); } return $id; diff --git a/src/Symfony/Component/Cache/Traits/MemcachedTrait.php b/src/Symfony/Component/Cache/Traits/MemcachedTrait.php index 8a836bac18c45..6dc46e9dd8da2 100644 --- a/src/Symfony/Component/Cache/Traits/MemcachedTrait.php +++ b/src/Symfony/Component/Cache/Traits/MemcachedTrait.php @@ -54,6 +54,7 @@ private function init(\Memcached $client, $namespace, $defaultLifetime) } parent::__construct($namespace, $defaultLifetime); + $this->enableVersioning(); } /** @@ -242,7 +243,7 @@ protected function doDelete(array $ids) */ protected function doClear($namespace) { - return $this->checkResultCode($this->getClient()->flush()); + return false; } private function checkResultCode($result) diff --git a/src/Symfony/Component/Cache/Traits/RedisTrait.php b/src/Symfony/Component/Cache/Traits/RedisTrait.php index b45d65adc8530..6202051a8de5d 100644 --- a/src/Symfony/Component/Cache/Traits/RedisTrait.php +++ b/src/Symfony/Component/Cache/Traits/RedisTrait.php @@ -46,7 +46,9 @@ public function init($redisClient, $namespace = '', $defaultLifetime = 0) if (preg_match('#[^-+_.A-Za-z0-9]#', $namespace, $match)) { throw new InvalidArgumentException(sprintf('RedisAdapter namespace contains "%s" but only characters in [-+_.A-Za-z0-9] are allowed.', $match[0])); } - if (!$redisClient instanceof \Redis && !$redisClient instanceof \RedisArray && !$redisClient instanceof \RedisCluster && !$redisClient instanceof \Predis\Client) { + if ($redisClient instanceof \RedisCluster) { + $this->enableversioning(); + } elseif (!$redisClient instanceof \Redis && !$redisClient instanceof \RedisArray && !$redisClient instanceof \Predis\Client) { throw new InvalidArgumentException(sprintf('%s() expects parameter 1 to be Redis, RedisArray, RedisCluster or Predis\Client, %s given', __METHOD__, is_object($redisClient) ? get_class($redisClient) : gettype($redisClient))); } $this->redis = $redisClient; @@ -171,8 +173,8 @@ protected function doHave($id) */ protected function doClear($namespace) { - // When using a native Redis cluster, clearing the cache cannot work and always returns false. - // Clearing the cache should then be done by any other means (e.g. by restarting the cluster). + // When using a native Redis cluster, clearing the cache is done by versioning in AbstractTrait::clear(). + // This means old keys are not really removed until they expire and may need gargage collection. $cleared = true; $hosts = array($this->redis); From 466da3fd6372904da4f71ab06db01df67b92e739 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Fri, 25 Aug 2017 19:21:35 +0200 Subject: [PATCH 0681/1099] [Debug] Remove false-positive check in DebugClassLoader --- .../Component/Debug/DebugClassLoader.php | 6 ++++-- .../Debug/Tests/DebugClassLoaderTest.php | 19 +++++++++++++++++++ .../Debug/Tests/Fixtures/Throwing.php | 3 +++ 3 files changed, 26 insertions(+), 2 deletions(-) create mode 100644 src/Symfony/Component/Debug/Tests/Fixtures/Throwing.php diff --git a/src/Symfony/Component/Debug/DebugClassLoader.php b/src/Symfony/Component/Debug/DebugClassLoader.php index 8ca836bd74a2d..2094a85c4cd6a 100644 --- a/src/Symfony/Component/Debug/DebugClassLoader.php +++ b/src/Symfony/Component/Debug/DebugClassLoader.php @@ -26,6 +26,7 @@ class DebugClassLoader { private $classLoader; private $isFinder; + private $loaded = array(); private $wasFinder; private static $caseCheck; private static $deprecated = array(); @@ -164,9 +165,10 @@ public function loadClass($class) ErrorHandler::stackErrors(); try { - if ($this->isFinder) { + if ($this->isFinder && !isset($this->loaded[$class])) { + $this->loaded[$class] = true; if ($file = $this->classLoader[0]->findFile($class)) { - require_once $file; + require $file; } } else { call_user_func($this->classLoader, $class); diff --git a/src/Symfony/Component/Debug/Tests/DebugClassLoaderTest.php b/src/Symfony/Component/Debug/Tests/DebugClassLoaderTest.php index 133ca28e546b7..1843418e919c9 100644 --- a/src/Symfony/Component/Debug/Tests/DebugClassLoaderTest.php +++ b/src/Symfony/Component/Debug/Tests/DebugClassLoaderTest.php @@ -59,6 +59,23 @@ public function testIdempotence() $this->fail('DebugClassLoader did not register'); } + /** + * @expectedException \Exception + * @expectedExceptionMessage boo + */ + public function testThrowingClass() + { + try { + class_exists(__NAMESPACE__.'\Fixtures\Throwing'); + $this->fail('Exception expected'); + } catch (\Exception $e) { + $this->assertSame('boo', $e->getMessage()); + } + + // the second call also should throw + class_exists(__NAMESPACE__.'\Fixtures\Throwing'); + } + public function testUnsilencing() { if (\PHP_VERSION_ID >= 70000) { @@ -128,6 +145,7 @@ class ChildTestingStacking extends TestingStacking { function foo($bar) {} } /** * @expectedException \RuntimeException + * @expectedExceptionMessage Case mismatch between loaded and declared class names */ public function testNameCaseMismatch() { @@ -149,6 +167,7 @@ class_exists(__NAMESPACE__.'\Fixtures\CaseMismatch', true); /** * @expectedException \RuntimeException + * @expectedExceptionMessage Case mismatch between loaded and declared class names */ public function testPsr4CaseMismatch() { diff --git a/src/Symfony/Component/Debug/Tests/Fixtures/Throwing.php b/src/Symfony/Component/Debug/Tests/Fixtures/Throwing.php new file mode 100644 index 0000000000000..21e0aba17d358 --- /dev/null +++ b/src/Symfony/Component/Debug/Tests/Fixtures/Throwing.php @@ -0,0 +1,3 @@ + Date: Sun, 27 Aug 2017 10:38:05 +0200 Subject: [PATCH 0682/1099] [VarDumper] Enhance docblock to tell about AbstractDumper::dumpLine(-1) --- src/Symfony/Component/VarDumper/Dumper/AbstractDumper.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/VarDumper/Dumper/AbstractDumper.php b/src/Symfony/Component/VarDumper/Dumper/AbstractDumper.php index abbe9629540ba..cd892a9687e0c 100644 --- a/src/Symfony/Component/VarDumper/Dumper/AbstractDumper.php +++ b/src/Symfony/Component/VarDumper/Dumper/AbstractDumper.php @@ -160,7 +160,8 @@ public function dump(Data $data, $output = null) /** * Dumps the current line. * - * @param int $depth The recursive depth in the dumped structure for the line being dumped + * @param int $depth The recursive depth in the dumped structure for the line being dumped, + * or -1 to signal the end-of-dump to the line dumper callable */ protected function dumpLine($depth) { From cc9fd5967d4b56e500f0928e19df3322fb468dbc Mon Sep 17 00:00:00 2001 From: Maxime Steinhausser Date: Sun, 27 Aug 2017 10:55:51 +0200 Subject: [PATCH 0683/1099] [Translation] Fix is interpreted as a tag in CHANGELOG --- src/Symfony/Component/Translation/CHANGELOG.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/Translation/CHANGELOG.md b/src/Symfony/Component/Translation/CHANGELOG.md index 3a78140153279..65fae7eda8508 100644 --- a/src/Symfony/Component/Translation/CHANGELOG.md +++ b/src/Symfony/Component/Translation/CHANGELOG.md @@ -7,8 +7,8 @@ CHANGELOG * Added `TranslationDumperPass` * Added `TranslationExtractorPass` * Added `TranslatorPass` - * Added section to the Xliff 2.0 dumper. - * Improved Xliff 2.0 loader to load section. + * Added `` section to the Xliff 2.0 dumper. + * Improved Xliff 2.0 loader to load `` section. * Added `TranslationWriterInterface` * Deprecated `TranslationWriter::writeTranslations` in favor of `TranslationWriter::write` From 6fe9072c42c3b3e3467a196491d2c4165f9decc7 Mon Sep 17 00:00:00 2001 From: Phil Taylor Date: Sun, 27 Aug 2017 14:23:17 +0100 Subject: [PATCH 0684/1099] Fix case sensitive typo in use class name closes #24001 Simple typo fix --- .../Compiler/MergeExtensionConfigurationPass.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/DependencyInjection/Compiler/MergeExtensionConfigurationPass.php b/src/Symfony/Component/DependencyInjection/Compiler/MergeExtensionConfigurationPass.php index 2f1b088f92b66..041d2215bad1f 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/MergeExtensionConfigurationPass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/MergeExtensionConfigurationPass.php @@ -15,7 +15,7 @@ use Symfony\Component\DependencyInjection\Extension\ConfigurationExtensionInterface; use Symfony\Component\DependencyInjection\Extension\Extension; use Symfony\Component\DependencyInjection\Extension\PrependExtensionInterface; -use Symfony\Component\DependencyInjection\Parameterbag\EnvPlaceholderParameterBag; +use Symfony\Component\DependencyInjection\ParameterBag\EnvPlaceholderParameterBag; /** * Merges extension configs into the container builder. From e600cd8647e68e631dfb2a0179afd248ec070d68 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Mon, 28 Aug 2017 10:20:24 +0200 Subject: [PATCH 0685/1099] [Cache] Use zend.detect_unicode instead of zend.multibyte --- .../Component/Cache/Adapter/PhpArrayAdapter.php | 2 +- .../Component/Cache/Adapter/PhpFilesAdapter.php | 2 +- src/Symfony/Component/Cache/Simple/PhpArrayCache.php | 2 +- src/Symfony/Component/Cache/Simple/PhpFilesCache.php | 2 +- src/Symfony/Component/Cache/Traits/PhpArrayTrait.php | 10 +++++----- src/Symfony/Component/Cache/Traits/PhpFilesTrait.php | 10 +++++----- 6 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/Symfony/Component/Cache/Adapter/PhpArrayAdapter.php b/src/Symfony/Component/Cache/Adapter/PhpArrayAdapter.php index 889a97f80a5fb..7e9686a01855e 100644 --- a/src/Symfony/Component/Cache/Adapter/PhpArrayAdapter.php +++ b/src/Symfony/Component/Cache/Adapter/PhpArrayAdapter.php @@ -38,7 +38,7 @@ public function __construct($file, AdapterInterface $fallbackPool) { $this->file = $file; $this->fallbackPool = $fallbackPool; - $this->zendMultiByte = ini_get('zend.multibyte'); + $this->zendDetectUnicode = ini_get('zend.detect_unicode'); $this->createCacheItem = \Closure::bind( function ($key, $value, $isHit) { $item = new CacheItem(); diff --git a/src/Symfony/Component/Cache/Adapter/PhpFilesAdapter.php b/src/Symfony/Component/Cache/Adapter/PhpFilesAdapter.php index 75ac9092df024..96846e69ba29c 100644 --- a/src/Symfony/Component/Cache/Adapter/PhpFilesAdapter.php +++ b/src/Symfony/Component/Cache/Adapter/PhpFilesAdapter.php @@ -35,6 +35,6 @@ public function __construct($namespace = '', $defaultLifetime = 0, $directory = $e = new \Exception(); $this->includeHandler = function () use ($e) { throw $e; }; - $this->zendMultiByte = ini_get('zend.multibyte'); + $this->zendDetectUnicode = ini_get('zend.detect_unicode'); } } diff --git a/src/Symfony/Component/Cache/Simple/PhpArrayCache.php b/src/Symfony/Component/Cache/Simple/PhpArrayCache.php index d4c3926548ca3..92180e63168bc 100644 --- a/src/Symfony/Component/Cache/Simple/PhpArrayCache.php +++ b/src/Symfony/Component/Cache/Simple/PhpArrayCache.php @@ -34,7 +34,7 @@ public function __construct($file, CacheInterface $fallbackPool) { $this->file = $file; $this->fallbackPool = $fallbackPool; - $this->zendMultiByte = ini_get('zend.multibyte'); + $this->zendDetectUnicode = ini_get('zend.detect_unicode'); } /** diff --git a/src/Symfony/Component/Cache/Simple/PhpFilesCache.php b/src/Symfony/Component/Cache/Simple/PhpFilesCache.php index 02273ada7a32a..dd92a8a03bd67 100644 --- a/src/Symfony/Component/Cache/Simple/PhpFilesCache.php +++ b/src/Symfony/Component/Cache/Simple/PhpFilesCache.php @@ -35,6 +35,6 @@ public function __construct($namespace = '', $defaultLifetime = 0, $directory = $e = new \Exception(); $this->includeHandler = function () use ($e) { throw $e; }; - $this->zendMultiByte = ini_get('zend.multibyte'); + $this->zendDetectUnicode = ini_get('zend.detect_unicode'); } } diff --git a/src/Symfony/Component/Cache/Traits/PhpArrayTrait.php b/src/Symfony/Component/Cache/Traits/PhpArrayTrait.php index b57e4e0b98de3..ccc48886d0cc3 100644 --- a/src/Symfony/Component/Cache/Traits/PhpArrayTrait.php +++ b/src/Symfony/Component/Cache/Traits/PhpArrayTrait.php @@ -25,7 +25,7 @@ trait PhpArrayTrait private $file; private $values; private $fallbackPool; - private $zendMultiByte; + private $zendDetectUnicode; /** * Store an array of cached values. @@ -127,14 +127,14 @@ public function clear() */ private function initialize() { - if ($this->zendMultiByte) { - $zmb = ini_set('zend.multibyte', 0); + if ($this->zendDetectUnicode) { + $zmb = ini_set('zend.detect_unicode', 0); } try { $this->values = file_exists($this->file) ? (include $this->file ?: array()) : array(); } finally { - if ($this->zendMultiByte) { - ini_set('zend.multibyte', $zmb); + if ($this->zendDetectUnicode) { + ini_set('zend.detect_unicode', $zmb); } } } diff --git a/src/Symfony/Component/Cache/Traits/PhpFilesTrait.php b/src/Symfony/Component/Cache/Traits/PhpFilesTrait.php index d9d976a023a30..d40a947badd21 100644 --- a/src/Symfony/Component/Cache/Traits/PhpFilesTrait.php +++ b/src/Symfony/Component/Cache/Traits/PhpFilesTrait.php @@ -25,7 +25,7 @@ trait PhpFilesTrait use FilesystemCommonTrait; private $includeHandler; - private $zendMultiByte; + private $zendDetectUnicode; public static function isSupported() { @@ -40,8 +40,8 @@ protected function doFetch(array $ids) $values = array(); $now = time(); - if ($this->zendMultiByte) { - $zmb = ini_set('zend.multibyte', 0); + if ($this->zendDetectUnicode) { + $zmb = ini_set('zend.detect_unicode', 0); } set_error_handler($this->includeHandler); try { @@ -58,8 +58,8 @@ protected function doFetch(array $ids) } } finally { restore_error_handler(); - if ($this->zendMultiByte) { - ini_set('zend.multibyte', $zmb); + if ($this->zendDetectUnicode) { + ini_set('zend.detect_unicode', $zmb); } } From 30336ead94e6a4014d3e21d3148c5ebb4bfe497f Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Tue, 22 Aug 2017 18:43:40 +0200 Subject: [PATCH 0686/1099] install PHPUnit 6 on PHP 7.2 --- src/Symfony/Bridge/PhpUnit/CHANGELOG.md | 5 +++++ src/Symfony/Bridge/PhpUnit/bin/simple-phpunit | 13 +++++++++++-- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Bridge/PhpUnit/CHANGELOG.md b/src/Symfony/Bridge/PhpUnit/CHANGELOG.md index 1cb07da782b6d..7f1ac2e3fa9c3 100644 --- a/src/Symfony/Bridge/PhpUnit/CHANGELOG.md +++ b/src/Symfony/Bridge/PhpUnit/CHANGELOG.md @@ -1,6 +1,11 @@ CHANGELOG ========= +3.4.0 +----- + + * PHPUnit 6 is installed when using PHP 7.2+ + 3.3.0 ----- diff --git a/src/Symfony/Bridge/PhpUnit/bin/simple-phpunit b/src/Symfony/Bridge/PhpUnit/bin/simple-phpunit index 4683682a1bf6e..c19d30f4af9e6 100755 --- a/src/Symfony/Bridge/PhpUnit/bin/simple-phpunit +++ b/src/Symfony/Bridge/PhpUnit/bin/simple-phpunit @@ -15,8 +15,17 @@ error_reporting(-1); -// PHPUnit 4.8 does not support PHP 7, while 5.1 requires PHP 5.6+ -$PHPUNIT_VERSION = PHP_VERSION_ID >= 50600 ? getenv('SYMFONY_PHPUNIT_VERSION') ?: '5.7' : '4.8'; +if (PHP_VERSION_ID >= 70200) { + // PHPUnit 6 is required for PHP 7.2+ + $PHPUNIT_VERSION = getenv('SYMFONY_PHPUNIT_VERSION') ?: '6.3'; +} elseif (PHP_VERSION_ID >= 50600) { + // PHPUnit 4 does not support PHP 7 + $PHPUNIT_VERSION = getenv('SYMFONY_PHPUNIT_VERSION') ?: '5.7'; +} else { + // PHPUnit 5.1 requires PHP 5.6+ + $PHPUNIT_VERSION = '4.8'; +} + $oldPwd = getcwd(); $PHPUNIT_DIR = getenv('SYMFONY_PHPUNIT_DIR') ?: (__DIR__.'/.phpunit'); $PHP = defined('PHP_BINARY') ? PHP_BINARY : 'php'; From 2230e317270db3b77eaeb9552f03dfbc9952adfc Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Mon, 28 Aug 2017 04:33:29 -0700 Subject: [PATCH 0687/1099] removed obsolete comment --- src/Symfony/Bridge/PhpUnit/CHANGELOG.md | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/Symfony/Bridge/PhpUnit/CHANGELOG.md b/src/Symfony/Bridge/PhpUnit/CHANGELOG.md index 7f1ac2e3fa9c3..1cb07da782b6d 100644 --- a/src/Symfony/Bridge/PhpUnit/CHANGELOG.md +++ b/src/Symfony/Bridge/PhpUnit/CHANGELOG.md @@ -1,11 +1,6 @@ CHANGELOG ========= -3.4.0 ------ - - * PHPUnit 6 is installed when using PHP 7.2+ - 3.3.0 ----- From baaff20f4aa3b587617c05e201208527922871fd Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Mon, 28 Aug 2017 17:40:54 +0200 Subject: [PATCH 0688/1099] [DI] Fix tracking env vars when merging configs (bis) --- .../MergeExtensionConfigurationPass.php | 62 +++++++------------ .../DependencyInjection/ContainerBuilder.php | 6 ++ .../MergeExtensionConfigurationPassTest.php | 11 +++- 3 files changed, 38 insertions(+), 41 deletions(-) diff --git a/src/Symfony/Component/DependencyInjection/Compiler/MergeExtensionConfigurationPass.php b/src/Symfony/Component/DependencyInjection/Compiler/MergeExtensionConfigurationPass.php index 041d2215bad1f..3e4acf5664e76 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/MergeExtensionConfigurationPass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/MergeExtensionConfigurationPass.php @@ -45,12 +45,14 @@ public function process(ContainerBuilder $container) // this extension was not called continue; } - // EnvPlaceholderParameterBag tracks env vars when calling resolveValue(). - // Clone so that tracking is done in a dedicated bag. - $resolvingBag = clone $container->getParameterBag(); + $resolvingBag = $container->getParameterBag(); + if ($resolvingBag instanceof EnvPlaceholderParameterBag && $extension instanceof Extension) { + // create a dedicated bag so that we can track env vars per-extension + $resolvingBag = new MergeExtensionConfigurationParameterBag($resolvingBag); + } $config = $resolvingBag->resolveValue($config); - $tmpContainer = new ContainerBuilder($container->getParameterBag()); + $tmpContainer = new ContainerBuilder($resolvingBag); $tmpContainer->setResourceTracking($container->isTrackingResources()); $tmpContainer->addObjectResource($extension); if ($extension instanceof ConfigurationExtensionInterface && null !== $configuration = $extension->getConfiguration($config, $tmpContainer)) { @@ -63,13 +65,9 @@ public function process(ContainerBuilder $container) $extension->load($config, $tmpContainer); - if ($resolvingBag instanceof EnvPlaceholderParameterBag) { - // $resolvingBag keeps track of env vars encoutered *before* merging configs - if ($extension instanceof Extension) { - // but we don't want to keep track of env vars that are *overridden* when configs are merged - $resolvingBag = new MergeExtensionConfigurationParameterBag($extension, $resolvingBag); - } - $container->getParameterBag()->mergeEnvPlaceholders($resolvingBag); + if ($resolvingBag instanceof MergeExtensionConfigurationParameterBag) { + // don't keep track of env vars that are *overridden* when configs are merged + $resolvingBag->freezeAfterProcessing($extension); } $container->merge($tmpContainer); @@ -86,21 +84,18 @@ public function process(ContainerBuilder $container) */ class MergeExtensionConfigurationParameterBag extends EnvPlaceholderParameterBag { - private $beforeProcessingEnvPlaceholders; + private $processedEnvPlaceholders; - public function __construct(Extension $extension, parent $resolvingBag) + public function __construct(parent $parameterBag) { - $this->beforeProcessingEnvPlaceholders = $resolvingBag->getEnvPlaceholders(); - $config = $this->resolveEnvPlaceholders($extension->getProcessedConfigs()); - parent::__construct($this->resolveValue($config)); + parent::__construct($parameterBag->all()); + $this->mergeEnvPlaceholders($parameterBag); } - /** - * {@inheritdoc} - */ - public function get($name) + public function freezeAfterProcessing(Extension $extension) { - return $this->has($name) || (0 === strpos($name, 'env(') && ')' === substr($name, -1) && 'env()' !== $name) ? parent::get($name) : ''; + $this->processedEnvPlaceholders = array(); + $this->processMergedConfig($extension->getProcessedConfigs(), parent::getEnvPlaceholders()); } /** @@ -108,33 +103,22 @@ public function get($name) */ public function getEnvPlaceholders() { - // contains the list of env vars that are still used after configs have been merged - $envPlaceholders = parent::getEnvPlaceholders(); - - foreach ($envPlaceholders as $env => $placeholders) { - if (isset($this->beforeProcessingEnvPlaceholders[$env])) { - // for still-used env vars, keep track of their before-processing placeholders - $envPlaceholders[$env] += $this->beforeProcessingEnvPlaceholders[$env]; - } - } - - return $envPlaceholders; + return null !== $this->processedEnvPlaceholders ? $this->processedEnvPlaceholders : parent::getEnvPlaceholders(); } - /** - * Replaces-back env placeholders to their original "%env(FOO)%" version. - */ - private function resolveEnvPlaceholders($value) + private function processMergedConfig($value, array $envPlaceholders) { if (is_array($value)) { foreach ($value as $k => $v) { - $value[$this->resolveEnvPlaceholders($k)] = $this->resolveEnvPlaceholders($v); + $this->processMergedConfig($k, $envPlaceholders); + $this->processMergedConfig($v, $envPlaceholders); } } elseif (is_string($value)) { - foreach ($this->beforeProcessingEnvPlaceholders as $env => $placeholders) { + foreach ($envPlaceholders as $env => $placeholders) { foreach ($placeholders as $placeholder) { if (false !== stripos($value, $placeholder)) { - $value = str_ireplace($placeholder, "%env($env)%", $value); + $this->processedEnvPlaceholders[$env] = $placeholders; + break; } } } diff --git a/src/Symfony/Component/DependencyInjection/ContainerBuilder.php b/src/Symfony/Component/DependencyInjection/ContainerBuilder.php index 2e8afa6545414..698080b9715e8 100644 --- a/src/Symfony/Component/DependencyInjection/ContainerBuilder.php +++ b/src/Symfony/Component/DependencyInjection/ContainerBuilder.php @@ -641,10 +641,16 @@ public function merge(ContainerBuilder $container) } if ($this->getParameterBag() instanceof EnvPlaceholderParameterBag && $container->getParameterBag() instanceof EnvPlaceholderParameterBag) { + $envPlaceholders = $container->getParameterBag()->getEnvPlaceholders(); $this->getParameterBag()->mergeEnvPlaceholders($container->getParameterBag()); + } else { + $envPlaceholders = array(); } foreach ($container->envCounters as $env => $count) { + if (!$count && !isset($envPlaceholders[$env])) { + continue; + } if (!isset($this->envCounters[$env])) { $this->envCounters[$env] = $count; } else { diff --git a/src/Symfony/Component/DependencyInjection/Tests/Compiler/MergeExtensionConfigurationPassTest.php b/src/Symfony/Component/DependencyInjection/Tests/Compiler/MergeExtensionConfigurationPassTest.php index 3934418474bd6..033e6c00fc342 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Compiler/MergeExtensionConfigurationPassTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Compiler/MergeExtensionConfigurationPassTest.php @@ -76,12 +76,13 @@ public function testOverriddenEnvsAreMerged() $container = new ContainerBuilder(); $container->registerExtension(new FooExtension()); $container->prependExtensionConfig('foo', array('bar' => '%env(FOO)%')); - $container->prependExtensionConfig('foo', array('bar' => '%env(BAR)%')); + $container->prependExtensionConfig('foo', array('bar' => '%env(BAR)%', 'baz' => '%env(BAZ)%')); $pass = new MergeExtensionConfigurationPass(); $pass->process($container); - $this->assertSame(array('FOO'), array_keys($container->getParameterBag()->getEnvPlaceholders())); + $this->assertSame(array('FOO', 'BAZ'), array_keys($container->getParameterBag()->getEnvPlaceholders())); + $this->assertSame(array('BAZ' => 1, 'FOO' => 0), $container->getEnvCounters()); } } @@ -94,6 +95,7 @@ public function getConfigTreeBuilder() $rootNode ->children() ->scalarNode('bar')->end() + ->scalarNode('baz')->end() ->end(); return $treeBuilder; @@ -116,5 +118,10 @@ public function load(array $configs, ContainerBuilder $container) { $configuration = $this->getConfiguration($configs, $container); $config = $this->processConfiguration($configuration, $configs); + + if (isset($config['baz'])) { + $container->getParameterBag()->get('env(BOZ)'); + $container->resolveEnvPlaceholders($config['baz']); + } } } From 00d7f6fa713f72ffb1166ed5faa58241df75ddfb Mon Sep 17 00:00:00 2001 From: Kevin Bond Date: Fri, 25 Aug 2017 13:52:13 -0400 Subject: [PATCH 0689/1099] [DI] improve psr4-based service discovery with namespace option --- .../Loader/YamlFileLoader.php | 10 ++++- .../OtherDir/Component1/Dir1/Service1.php | 7 ++++ .../OtherDir/Component1/Dir2/Service2.php | 8 ++++ .../OtherDir/Component1/Dir3/Service3.php | 8 ++++ .../OtherDir/Component2/Dir1/Service4.php | 7 ++++ .../OtherDir/Component2/Dir2/Service5.php | 8 ++++ .../yaml/services_prototype_namespace.yml | 10 +++++ ...s_prototype_namespace_without_resource.yml | 4 ++ .../Tests/Loader/YamlFileLoaderTest.php | 39 +++++++++++++++++++ 9 files changed, 99 insertions(+), 2 deletions(-) create mode 100644 src/Symfony/Component/DependencyInjection/Tests/Fixtures/Prototype/OtherDir/Component1/Dir1/Service1.php create mode 100644 src/Symfony/Component/DependencyInjection/Tests/Fixtures/Prototype/OtherDir/Component1/Dir2/Service2.php create mode 100644 src/Symfony/Component/DependencyInjection/Tests/Fixtures/Prototype/OtherDir/Component1/Dir3/Service3.php create mode 100644 src/Symfony/Component/DependencyInjection/Tests/Fixtures/Prototype/OtherDir/Component2/Dir1/Service4.php create mode 100644 src/Symfony/Component/DependencyInjection/Tests/Fixtures/Prototype/OtherDir/Component2/Dir2/Service5.php create mode 100644 src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services_prototype_namespace.yml create mode 100644 src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services_prototype_namespace_without_resource.yml diff --git a/src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php b/src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php index 6056d05c101bd..8a1c51f4e6fc1 100644 --- a/src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php +++ b/src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php @@ -63,6 +63,7 @@ class YamlFileLoader extends FileLoader private static $prototypeKeywords = array( 'resource' => 'resource', + 'namespace' => 'namespace', 'exclude' => 'exclude', 'parent' => 'parent', 'shared' => 'shared', @@ -560,12 +561,17 @@ private function parseDefinition($id, $service, $file, array $defaults) } } + if (array_key_exists('namespace', $service) && !array_key_exists('resource', $service)) { + throw new InvalidArgumentException(sprintf('A "resource" attribute must be set when the "namespace" attribute is set for service "%s" in %s. Check your YAML syntax.', $id, $file)); + } + if (array_key_exists('resource', $service)) { if (!is_string($service['resource'])) { throw new InvalidArgumentException(sprintf('A "resource" attribute must be of type string for service "%s" in %s. Check your YAML syntax.', $id, $file)); } $exclude = isset($service['exclude']) ? $service['exclude'] : null; - $this->registerClasses($definition, $id, $service['resource'], $exclude); + $namespace = isset($service['namespace']) ? $service['namespace'] : $id; + $this->registerClasses($definition, $namespace, $service['resource'], $exclude); } else { $this->setDefinition($id, $definition); } @@ -804,7 +810,7 @@ private function checkDefinition($id, array $definition, $file) { if ($throw = $this->isLoadingInstanceof) { $keywords = self::$instanceofKeywords; - } elseif ($throw = isset($definition['resource'])) { + } elseif ($throw = (isset($definition['resource']) || isset($definition['namespace']))) { $keywords = self::$prototypeKeywords; } else { $keywords = self::$serviceKeywords; diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/Prototype/OtherDir/Component1/Dir1/Service1.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/Prototype/OtherDir/Component1/Dir1/Service1.php new file mode 100644 index 0000000000000..ef3f28abb8a05 --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/Prototype/OtherDir/Component1/Dir1/Service1.php @@ -0,0 +1,7 @@ +assertContains('reflection.Symfony\Component\DependencyInjection\Tests\Fixtures\Prototype\Sub\Bar', $resources); } + public function testPrototypeWithNamespace() + { + $container = new ContainerBuilder(); + $loader = new YamlFileLoader($container, new FileLocator(self::$fixturesPath.'/yaml')); + $loader->load('services_prototype_namespace.yml'); + + $ids = array_keys($container->getDefinitions()); + sort($ids); + + $this->assertSame(array( + Prototype\OtherDir\Component1\Dir1\Service1::class, + Prototype\OtherDir\Component1\Dir2\Service2::class, + Prototype\OtherDir\Component2\Dir1\Service4::class, + Prototype\OtherDir\Component2\Dir2\Service5::class, + 'service_container', + ), $ids); + + $this->assertTrue($container->getDefinition(Prototype\OtherDir\Component1\Dir1\Service1::class)->hasTag('foo')); + $this->assertTrue($container->getDefinition(Prototype\OtherDir\Component2\Dir1\Service4::class)->hasTag('foo')); + $this->assertFalse($container->getDefinition(Prototype\OtherDir\Component1\Dir1\Service1::class)->hasTag('bar')); + $this->assertFalse($container->getDefinition(Prototype\OtherDir\Component2\Dir1\Service4::class)->hasTag('bar')); + + $this->assertTrue($container->getDefinition(Prototype\OtherDir\Component1\Dir2\Service2::class)->hasTag('bar')); + $this->assertTrue($container->getDefinition(Prototype\OtherDir\Component2\Dir2\Service5::class)->hasTag('bar')); + $this->assertFalse($container->getDefinition(Prototype\OtherDir\Component1\Dir2\Service2::class)->hasTag('foo')); + $this->assertFalse($container->getDefinition(Prototype\OtherDir\Component2\Dir2\Service5::class)->hasTag('foo')); + } + + /** + * @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException + * @expectedExceptionMessageRegExp /A "resource" attribute must be set when the "namespace" attribute is set for service ".+" in .+/ + */ + public function testPrototypeWithNamespaceAndNoResource() + { + $container = new ContainerBuilder(); + $loader = new YamlFileLoader($container, new FileLocator(self::$fixturesPath.'/yaml')); + $loader->load('services_prototype_namespace_without_resource.yml'); + } + public function testDefaults() { $container = new ContainerBuilder(); From 7229a363a54e86111fc7aa7f1b46967d648d9397 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Mon, 28 Aug 2017 11:40:29 -0700 Subject: [PATCH 0690/1099] updated CHANGELOG for 2.7.34 --- CHANGELOG-2.7.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/CHANGELOG-2.7.md b/CHANGELOG-2.7.md index d08766327bc5e..f742ca8ea0385 100644 --- a/CHANGELOG-2.7.md +++ b/CHANGELOG-2.7.md @@ -7,6 +7,19 @@ in 2.7 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/v2.7.0...v2.7.1 +* 2.7.34 (2017-08-28) + + * bug #23989 [Debug] Remove false-positive check in DebugClassLoader (nicolas-grekas) + * bug #23982 [VarDumper] Strengthen dumped JS (nicolas-grekas) + * bug #23925 [Validator] Fix use of GroupSequenceProvider in child classes (linniksa) + * bug #23945 [Validator] Fix Greek translation (azhurb) + * bug #23909 [Console] Initialize lazily to render exceptions properly (nicolas-grekas) + * bug #23856 [DI] Fix dumping abstract with YamlDumper (nicolas-grekas) + * bug #23752 Ignore memcached missing key error on session destroy (jderusse) + * bug #23658 [HttpFoundation] Generate safe fallback filename for wrongly encoded filename (xelaris) + * bug #23783 Avoid infinite loops when profiler data is malformed (javiereguiluz) + * bug #23729 [Bridge\ProxyManager] Dont call __destruct() on non-instantiated services (nicolas-grekas) + * 2.7.33 (2017-08-01) * bug #22244 [Console] Fix passing options with defaultCommand (Jakub Sacha) From 0978a4c2abcf51d3ac426f467f34e3ca1d429d6c Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Mon, 28 Aug 2017 11:40:34 -0700 Subject: [PATCH 0691/1099] update CONTRIBUTORS for 2.7.34 --- CONTRIBUTORS.md | 44 ++++++++++++++++++++++++++------------------ 1 file changed, 26 insertions(+), 18 deletions(-) diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index 1b059f5012cb7..ced9b18126294 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -7,8 +7,8 @@ Symfony is the result of the work of many people who made the code better - Fabien Potencier (fabpot) - Nicolas Grekas (nicolas-grekas) - Bernhard Schussek (bschussek) - - Tobias Schultze (tobion) - Christian Flothmann (xabbuh) + - Tobias Schultze (tobion) - Christophe Coevoet (stof) - Jordi Boggiano (seldaek) - Victor Berchet (victor) @@ -37,8 +37,8 @@ Symfony is the result of the work of many people who made the code better - Roland Franssen (ro0) - Eriksen Costa (eriksencosta) - Jules Pietri (heah) - - Sarah Khalil (saro0h) - Guilhem Niot (energetick) + - Sarah Khalil (saro0h) - Jonathan Wage (jwage) - Diego Saint Esteben (dosten) - Alexandre Salomé (alexandresalome) @@ -65,20 +65,20 @@ Symfony is the result of the work of many people who made the code better - Michel Weimerskirch (mweimerskirch) - Eric Clemmons (ericclemmons) - Charles Sarrazin (csarrazi) - - Christian Raue - Konstantin Myakshin (koc) + - Christian Raue + - Dany Maillard (maidmaid) - Arnout Boks (aboks) + - Jérémy DERUSSÉ (jderusse) - Deni - Henrik Westphal (snc) - Dariusz Górecki (canni) - Jáchym Toušek (enumag) - Titouan Galopin (tgalopin) - Douglas Greenshields (shieldo) - - Dany Maillard (maidmaid) - Lee McDermott - Brandon Turner - Luis Cordova (cordoval) - - Jérémy DERUSSÉ (jderusse) - Graham Campbell (graham) - Daniel Holmes (dholmes) - Toni Uebernickel (havvg) @@ -87,24 +87,24 @@ Symfony is the result of the work of many people who made the code better - Jérôme Tamarelle (gromnan) - John Wards (johnwards) - Dariusz Ruminski + - Alexander M. Turek (derrabus) - Fran Moreno (franmomu) - Antoine Hérault (herzult) + - Tobias Nyholm (tobias) - Paráda József (paradajozsef) - Issei Murasawa (issei_m) - Arnaud Le Blanc (arnaud-lb) - Maxime STEINHAUSSER - - Alexander M. Turek (derrabus) - Michal Piotrowski (eventhorizon) - - Tim Nagel (merk) - Yonel Ceruto González (yonelceruto) + - Tim Nagel (merk) - Brice BERNARD (brikou) - Baptiste Clavié (talus) - Vladimir Reznichenko (kalessil) - marc.weistroff - lenar - - Tobias Nyholm (tobias) - - Włodzimierz Gajda (gajdaw) - Alexander Schwenn (xelaris) + - Włodzimierz Gajda (gajdaw) - Jacob Dreesen (jdreesen) - Florian Voutzinos (florianv) - Colin Frei @@ -152,7 +152,9 @@ Symfony is the result of the work of many people who made the code better - Rouven Weßling (realityking) - Teoh Han Hui (teohhanhui) - Clemens Tolboom + - Oleg Voronkovich - Helmer Aaviksoo + - Lars Strojny (lstrojny) - Hiromi Hishida (77web) - Matthieu Ouellette-Vachon (maoueh) - Michał Pipa (michal.pipa) @@ -166,7 +168,6 @@ Symfony is the result of the work of many people who made the code better - Warnar Boekkooi (boekkooi) - Dmitrii Chekaliuk (lazyhammer) - Clément JOBEILI (dator) - - Lars Strojny (lstrojny) - Possum - Dorian Villet (gnutix) - Richard Miller (mr_r_miller) @@ -183,7 +184,6 @@ Symfony is the result of the work of many people who made the code better - Daniel Espendiller - sun (sun) - Larry Garfield (crell) - - Oleg Voronkovich - Martin Schuhfuß (usefulthink) - apetitpa - Matthieu Bontemps (mbontemps) @@ -334,9 +334,11 @@ Symfony is the result of the work of many people who made the code better - Damien Alexandre (damienalexandre) - Felix Labrecque - Yaroslav Kiliba + - Amrouche Hamza - Terje Bråten - Robbert Klarenbeek (robbertkl) - Thomas Calvet (fancyweb) + - Valentin Udaltsov (vudaltsov) - Niels Keurentjes (curry684) - JhonnyL - David Badura (davidbadura) @@ -387,6 +389,7 @@ Symfony is the result of the work of many people who made the code better - Karel Souffriau - Christophe L. (christophelau) - Anthon Pang (robocoder) + - Jérôme Parmentier (lctrs) - Emanuele Gaspari (inmarelibero) - Sébastien Santoro (dereckson) - Brian King @@ -421,7 +424,6 @@ Symfony is the result of the work of many people who made the code better - Dirk Pahl (dirkaholic) - cedric lombardot (cedriclombardot) - Jonas Flodén (flojon) - - Amrouche Hamza - Marcin Sikoń (marphi) - Dominik Zogg (dominik.zogg) - Marek Pietrzak @@ -432,6 +434,7 @@ Symfony is the result of the work of many people who made the code better - Zander Baldwin - Adam Harvey - Maxime Veber (nek-) + - Sanpi - Alex Bakhturin - Alexander Obuhovich (aik099) - boombatower @@ -512,6 +515,7 @@ Symfony is the result of the work of many people who made the code better - Dave Hulbert (dave1010) - Ivan Rey (ivanrey) - Marcin Chyłek (songoq) + - Ben Scott - Ned Schwartz - Ziumin - Jeremy Benoist @@ -520,7 +524,6 @@ Symfony is the result of the work of many people who made the code better - Benjamin Laugueux (yzalis) - Zach Badgett (zachbadgett) - Aurélien Fredouelle - - Jérôme Parmentier (lctrs) - Pavel Campr (pcampr) - Johnny Robeson (johnny) - Disquedur @@ -592,7 +595,6 @@ Symfony is the result of the work of many people who made the code better - Ulumuddin Yunus (joenoez) - Luc Vieillescazes (iamluc) - Johann Saunier (prophet777) - - Valentin Udaltsov (vudaltsov) - Michael Devery (mickadoo) - Antoine Corcy - Artur Eshenbrener @@ -671,9 +673,11 @@ Symfony is the result of the work of many people who made the code better - Andrew Hilobok (hilobok) - Noah Heck (myesain) - Christian Soronellas (theunic) + - Adam Szaraniec (mimol) - Yosmany Garcia (yosmanyga) - Wouter de Wild - Degory Valentine + - izzyp - Benoit Lévêque (benoit_leveque) - Jeroen Fiege (fieg) - Krzysiek Łabuś @@ -709,7 +713,6 @@ Symfony is the result of the work of many people who made the code better - Pierre Vanliefland (pvanliefland) - Sofiane HADDAG (sofhad) - frost-nzcr4 - - Sanpi - Abhoryo - Fabian Vogler (fabian) - Korvin Szanto @@ -742,7 +745,6 @@ Symfony is the result of the work of many people who made the code better - Omar Yepez (oyepez003) - mwsaz - Jelle Kapitein - - Ben Scott - Benoît Bourgeois - mantulo - corphi @@ -877,6 +879,7 @@ Symfony is the result of the work of many people who made the code better - Boris Vujicic (boris.vujicic) - Max Beutel - Antanas Arvasevicius + - Maximilian Berghoff (electricmaxxx) - nacho - Piotr Antosik (antek88) - Artem Lopata @@ -910,6 +913,7 @@ Symfony is the result of the work of many people who made the code better - Matteo Giachino (matteosister) - Alex Demchenko (pilot) - Tadas Gliaubicas (tadcka) + - Thanos Polymeneas (thanos) - Benoit Garret - Jakub Sacha - DerManoMann @@ -1098,7 +1102,6 @@ Symfony is the result of the work of many people who made the code better - Tomaz Ahlin - Marcus Stöhr (dafish) - Emmanuel Vella (emmanuel.vella) - - Adam Szaraniec (mimol) - Carsten Nielsen (phreaknerd) - Mathieu Rochette - Jay Severson @@ -1171,6 +1174,7 @@ Symfony is the result of the work of many people who made the code better - César Suárez (csuarez) - Nicolas Badey (nico-b) - Shane Preece (shane) + - Johannes Goslar - Geoff - georaldc - Malte Wunsch @@ -1204,6 +1208,7 @@ Symfony is the result of the work of many people who made the code better - catch - Alexandre Segura - Josef Cech + - Harold Iedema - Arnau González (arnaugm) - Simon Bouland (bouland) - Matthew Foster (mfoster) @@ -1236,7 +1241,6 @@ Symfony is the result of the work of many people who made the code better - Dennis Væversted - nuncanada - flack - - izzyp - František Bereň - Mike Francis - Christoph Nissle (derstoffel) @@ -1477,6 +1481,7 @@ Symfony is the result of the work of many people who made the code better - Ismail Asci (ismailasci) - Simon CONSTANS (kosssi) - Kristof Van Cauwenbergh (kristofvc) + - Paulius Jarmalavičius (pjarmalavicius) - Ramon Henrique Ornelas (ramonornela) - Markus S. (staabm) - Till Klampaeckel (till) @@ -1569,11 +1574,13 @@ Symfony is the result of the work of many people who made the code better - Matt Janssen - Peter Gribanov - Ben Johnson + - Florent Mata - kwiateusz - David Soria Parra - Sergiy Sokolenko - dinitrol - Penny Leach + - Yurii K - Richard Trebichavský - g123456789l - Jonathan Vollebregt @@ -1651,6 +1658,7 @@ Symfony is the result of the work of many people who made the code better - samuel laulhau (lalop) - Laurent Bachelier (laurentb) - Florent Viel (luxifer) + - Matthieu Mota (matthieumota) - Matthieu Moquet (mattketmo) - Moritz Borgmann (mborgmann) - Michal Čihař (mcihar) From 0f45d7963a0df843daab33f986e138732ec7c089 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Mon, 28 Aug 2017 11:40:36 -0700 Subject: [PATCH 0692/1099] updated VERSION for 2.7.34 --- 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 401a3626d84b4..c14964609235c 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -58,12 +58,12 @@ abstract class Kernel implements KernelInterface, TerminableInterface protected $startTime; protected $loadClassCache; - const VERSION = '2.7.34-DEV'; + const VERSION = '2.7.34'; const VERSION_ID = 20734; const MAJOR_VERSION = 2; const MINOR_VERSION = 7; const RELEASE_VERSION = 34; - const EXTRA_VERSION = 'DEV'; + const EXTRA_VERSION = ''; const END_OF_MAINTENANCE = '05/2018'; const END_OF_LIFE = '05/2019'; From 4c4c3987fdfeadfba47a1679f97ee4867f1b2912 Mon Sep 17 00:00:00 2001 From: Dany Maillard Date: Fri, 21 Jul 2017 17:12:27 +0200 Subject: [PATCH 0693/1099] Add period caster --- .../Component/VarDumper/Caster/DateCaster.php | 34 +++++++ .../VarDumper/Cloner/AbstractCloner.php | 1 + .../VarDumper/Tests/Caster/DateCasterTest.php | 93 +++++++++++++++++++ 3 files changed, 128 insertions(+) diff --git a/src/Symfony/Component/VarDumper/Caster/DateCaster.php b/src/Symfony/Component/VarDumper/Caster/DateCaster.php index 17e7f4f929068..a23a5bb25afe9 100644 --- a/src/Symfony/Component/VarDumper/Caster/DateCaster.php +++ b/src/Symfony/Component/VarDumper/Caster/DateCaster.php @@ -80,6 +80,40 @@ public static function castTimeZone(\DateTimeZone $timeZone, array $a, Stub $stu return $filter & Caster::EXCLUDE_VERBOSE ? $z : $z + $a; } + public static function castPeriod(\DatePeriod $p, array $a, Stub $stub, $isNested, $filter) + { + if (defined('HHVM_VERSION_ID') || \PHP_VERSION_ID < 50605) { + return $a; + } + + $dates = array(); + if (\PHP_VERSION_ID >= 70107) { // see https://bugs.php.net/bug.php?id=74639 + foreach (clone $p as $i => $d) { + if (3 === $i) { + $now = new \DateTimeImmutable(); + $dates[] = sprintf('%s more', ($end = $p->getEndDate()) + ? ceil(($end->format('U.u') - $d->format('U.u')) / ($now->add($p->getDateInterval())->format('U.u') - $now->format('U.u'))) + : $p->recurrences - $i + ); + break; + } + $dates[] = sprintf('%s) %s', $i + 1, $d->format('Y-m-d H:i:s')); + } + } + + $period = sprintf( + 'every %s, from %s (%s) %s', + self::formatInterval($p->getDateInterval()), + $p->getStartDate()->format('Y-m-d H:i:s'), + $p->include_start_date ? 'included' : 'excluded', + ($end = $p->getEndDate()) ? 'to '.$end->format('Y-m-d H:i:s') : 'recurring '.$p->recurrences.' time/s' + ); + + $p = array(Caster::PREFIX_VIRTUAL.'period' => new ConstStub($period, implode("\n", $dates))); + + return $filter & Caster::EXCLUDE_VERBOSE ? $p : $p + $a; + } + private static function formatSeconds($s, $us) { return sprintf('%02d.%s', $s, 0 === ($len = strlen($t = rtrim($us, '0'))) ? '0' : ($len <= 3 ? str_pad($t, 3, '0') : $us)); diff --git a/src/Symfony/Component/VarDumper/Cloner/AbstractCloner.php b/src/Symfony/Component/VarDumper/Cloner/AbstractCloner.php index 2c13341f31fd1..5e0a0b1531387 100644 --- a/src/Symfony/Component/VarDumper/Cloner/AbstractCloner.php +++ b/src/Symfony/Component/VarDumper/Cloner/AbstractCloner.php @@ -112,6 +112,7 @@ abstract class AbstractCloner implements ClonerInterface 'DateTimeInterface' => array('Symfony\Component\VarDumper\Caster\DateCaster', 'castDateTime'), 'DateInterval' => array('Symfony\Component\VarDumper\Caster\DateCaster', 'castInterval'), 'DateTimeZone' => array('Symfony\Component\VarDumper\Caster\DateCaster', 'castTimeZone'), + 'DatePeriod' => array('Symfony\Component\VarDumper\Caster\DateCaster', 'castPeriod'), ':curl' => array('Symfony\Component\VarDumper\Caster\ResourceCaster', 'castCurl'), ':dba' => array('Symfony\Component\VarDumper\Caster\ResourceCaster', 'castDba'), diff --git a/src/Symfony/Component/VarDumper/Tests/Caster/DateCasterTest.php b/src/Symfony/Component/VarDumper/Tests/Caster/DateCasterTest.php index f1207e30d16fc..dff66454911f6 100644 --- a/src/Symfony/Component/VarDumper/Tests/Caster/DateCasterTest.php +++ b/src/Symfony/Component/VarDumper/Tests/Caster/DateCasterTest.php @@ -296,4 +296,97 @@ public function provideTimeZones() array('Pacific/Tahiti', 'Pacific/Tahiti (-10:00)', $xRegion), ); } + + /** + * @dataProvider providePeriods + */ + public function testDumpPeriod($start, $interval, $end, $options, $expected) + { + if (defined('HHVM_VERSION_ID') || \PHP_VERSION_ID < 50605) { + $this->markTestSkipped(); + } + + $p = new \DatePeriod(new \DateTime($start), new \DateInterval($interval), is_int($end) ? $end : new \DateTime($end), $options); + + $xDump = <<assertDumpMatchesFormat($xDump, $p); + } + + /** + * @dataProvider providePeriods + */ + public function testCastPeriod($start, $interval, $end, $options, $xPeriod, $xDates) + { + if (defined('HHVM_VERSION_ID') || \PHP_VERSION_ID < 50605) { + $this->markTestSkipped(); + } + + $p = new \DatePeriod(new \DateTime($start), new \DateInterval($interval), is_int($end) ? $end : new \DateTime($end), $options); + $stub = new Stub(); + + $cast = DateCaster::castPeriod($p, array(), $stub, false, 0); + + $xDump = << $xPeriod +] +EODUMP; + + $this->assertDumpMatchesFormat($xDump, $cast); + + $xDump = <<assertDumpMatchesFormat($xDump, $cast["\0~\0period"]); + } + + public function providePeriods() + { + $i = new \DateInterval('PT0S'); + $ms = \PHP_VERSION_ID >= 70100 && isset($i->f) ? '.0' : ''; + + $periods = array( + array('2017-01-01', 'P1D', '2017-01-03', 0, 'every + 1d, from 2017-01-01 00:00:00 (included) to 2017-01-03 00:00:00', '1) 2017-01-01%a2) 2017-01-02'), + array('2017-01-01', 'P1D', 1, 0, 'every + 1d, from 2017-01-01 00:00:00 (included) recurring 2 time/s', '1) 2017-01-01%a2) 2017-01-02'), + + array('2017-01-01', 'P1D', '2017-01-04', 0, 'every + 1d, from 2017-01-01 00:00:00 (included) to 2017-01-04 00:00:00', '1) 2017-01-01%a2) 2017-01-02%a3) 2017-01-03'), + array('2017-01-01', 'P1D', 2, 0, 'every + 1d, from 2017-01-01 00:00:00 (included) recurring 3 time/s', '1) 2017-01-01%a2) 2017-01-02%a3) 2017-01-03'), + + array('2017-01-01', 'P1D', '2017-01-05', 0, 'every + 1d, from 2017-01-01 00:00:00 (included) to 2017-01-05 00:00:00', '1) 2017-01-01%a2) 2017-01-02%a1 more'), + array('2017-01-01', 'P1D', 3, 0, 'every + 1d, from 2017-01-01 00:00:00 (included) recurring 4 time/s', '1) 2017-01-01%a2) 2017-01-02%a3) 2017-01-03%a1 more'), + + array('2017-01-01', 'P1D', '2017-01-21', 0, 'every + 1d, from 2017-01-01 00:00:00 (included) to 2017-01-21 00:00:00', '1) 2017-01-01%a17 more'), + array('2017-01-01', 'P1D', 19, 0, 'every + 1d, from 2017-01-01 00:00:00 (included) recurring 20 time/s', '1) 2017-01-01%a17 more'), + + array('2017-01-01 01:00:00', 'P1D', '2017-01-03 01:00:00', 0, 'every + 1d, from 2017-01-01 01:00:00 (included) to 2017-01-03 01:00:00', '1) 2017-01-01 01:00:00%a2) 2017-01-02 01:00:00'), + array('2017-01-01 01:00:00', 'P1D', 1, 0, 'every + 1d, from 2017-01-01 01:00:00 (included) recurring 2 time/s', '1) 2017-01-01 01:00:00%a2) 2017-01-02 01:00:00'), + + array('2017-01-01', 'P1DT1H', '2017-01-03', 0, "every + 1d 01:00:00$ms, from 2017-01-01 00:00:00 (included) to 2017-01-03 00:00:00", '1) 2017-01-01 00:00:00%a2) 2017-01-02 01:00:00'), + array('2017-01-01', 'P1DT1H', 1, 0, "every + 1d 01:00:00$ms, from 2017-01-01 00:00:00 (included) recurring 2 time/s", '1) 2017-01-01 00:00:00%a2) 2017-01-02 01:00:00'), + + array('2017-01-01', 'P1D', '2017-01-04', \DatePeriod::EXCLUDE_START_DATE, 'every + 1d, from 2017-01-01 00:00:00 (excluded) to 2017-01-04 00:00:00', '1) 2017-01-02%a2) 2017-01-03'), + array('2017-01-01', 'P1D', 2, \DatePeriod::EXCLUDE_START_DATE, 'every + 1d, from 2017-01-01 00:00:00 (excluded) recurring 2 time/s', '1) 2017-01-02%a2) 2017-01-03'), + ); + + if (\PHP_VERSION_ID < 70107) { + array_walk($periods, function (&$i) { $i[5] = ''; }); + } + + return $periods; + } } From bc4e01500b4d0bdf5683ed09b635a85367902307 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Mon, 28 Aug 2017 12:18:16 -0700 Subject: [PATCH 0694/1099] bumped Symfony version to 2.7.35 --- 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 c14964609235c..0fcbbe47fddea 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -58,12 +58,12 @@ abstract class Kernel implements KernelInterface, TerminableInterface protected $startTime; protected $loadClassCache; - const VERSION = '2.7.34'; - const VERSION_ID = 20734; + const VERSION = '2.7.35-DEV'; + const VERSION_ID = 20735; const MAJOR_VERSION = 2; const MINOR_VERSION = 7; - const RELEASE_VERSION = 34; - const EXTRA_VERSION = ''; + const RELEASE_VERSION = 35; + const EXTRA_VERSION = 'DEV'; const END_OF_MAINTENANCE = '05/2018'; const END_OF_LIFE = '05/2019'; From 2bba09c51ebeb119cd154e97899c04fbc9ab45ea Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Mon, 28 Aug 2017 12:21:33 -0700 Subject: [PATCH 0695/1099] updated CHANGELOG for 2.8.27 --- CHANGELOG-2.8.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/CHANGELOG-2.8.md b/CHANGELOG-2.8.md index 5fdc52f111daa..abb1235519a77 100644 --- a/CHANGELOG-2.8.md +++ b/CHANGELOG-2.8.md @@ -7,6 +7,19 @@ in 2.8 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/v2.8.0...v2.8.1 +* 2.8.27 (2017-08-28) + + * bug #23989 [Debug] Remove false-positive check in DebugClassLoader (nicolas-grekas) + * bug #23982 [VarDumper] Strengthen dumped JS (nicolas-grekas) + * bug #23925 [Validator] Fix use of GroupSequenceProvider in child classes (linniksa) + * bug #23945 [Validator] Fix Greek translation (azhurb) + * bug #23909 [Console] Initialize lazily to render exceptions properly (nicolas-grekas) + * bug #23856 [DI] Fix dumping abstract with YamlDumper (nicolas-grekas) + * bug #23752 Ignore memcached missing key error on session destroy (jderusse) + * bug #23658 [HttpFoundation] Generate safe fallback filename for wrongly encoded filename (xelaris) + * bug #23783 Avoid infinite loops when profiler data is malformed (javiereguiluz) + * bug #23729 [Bridge\ProxyManager] Dont call __destruct() on non-instantiated services (nicolas-grekas) + * 2.8.26 (2017-08-01) * bug #22244 [Console] Fix passing options with defaultCommand (Jakub Sacha) From 527e17138377d847a8493ab0b3910e9878612e1c Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Mon, 28 Aug 2017 12:21:40 -0700 Subject: [PATCH 0696/1099] updated VERSION for 2.8.27 --- 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 ff1dc40d15fb8..89aaa72cf9a35 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -59,12 +59,12 @@ abstract class Kernel implements KernelInterface, TerminableInterface protected $startTime; protected $loadClassCache; - const VERSION = '2.8.27-DEV'; + const VERSION = '2.8.27'; const VERSION_ID = 20827; const MAJOR_VERSION = 2; const MINOR_VERSION = 8; const RELEASE_VERSION = 27; - const EXTRA_VERSION = 'DEV'; + const EXTRA_VERSION = ''; const END_OF_MAINTENANCE = '11/2018'; const END_OF_LIFE = '11/2019'; From e313e69e98a1c6f2f960de0b6321bbb43d3c5b85 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Mon, 28 Aug 2017 12:33:37 -0700 Subject: [PATCH 0697/1099] bumped Symfony version to 2.8.28 --- 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 89aaa72cf9a35..4758961c4d9d7 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -59,12 +59,12 @@ abstract class Kernel implements KernelInterface, TerminableInterface protected $startTime; protected $loadClassCache; - const VERSION = '2.8.27'; - const VERSION_ID = 20827; + const VERSION = '2.8.28-DEV'; + const VERSION_ID = 20828; const MAJOR_VERSION = 2; const MINOR_VERSION = 8; - const RELEASE_VERSION = 27; - const EXTRA_VERSION = ''; + const RELEASE_VERSION = 28; + const EXTRA_VERSION = 'DEV'; const END_OF_MAINTENANCE = '11/2018'; const END_OF_LIFE = '11/2019'; From 2a7cf1993cfd9f2a029e690546f932fd47fa2882 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Mon, 28 Aug 2017 12:34:07 -0700 Subject: [PATCH 0698/1099] updated CHANGELOG for 3.3.7 --- CHANGELOG-3.3.md | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/CHANGELOG-3.3.md b/CHANGELOG-3.3.md index e005c1dabe0d0..185d1432cc409 100644 --- a/CHANGELOG-3.3.md +++ b/CHANGELOG-3.3.md @@ -7,6 +7,46 @@ in 3.3 minor versions. To get the diff for a specific change, go to https://github.com/symfony/symfony/commit/XXX where XXX is the change hash To get the diff between two versions, go to https://github.com/symfony/symfony/compare/v3.3.0...v3.3.1 +* 3.3.7 (2017-08-28) + + * bug #24009 [DI] Fix tracking env vars when merging configs (bis) (nicolas-grekas) + * bug #23952 [PhpUnitBridge] install PHPUnit 6 on PHP 7.2 (xabbuh) + * bug #23985 [Cache] Workaround zend.detect_unicode + zend.multibyte (nicolas-grekas) + * bug #23989 [Debug] Remove false-positive check in DebugClassLoader (nicolas-grekas) + * bug #23983 [VarDumper] Strengthen dumped JS (nicolas-grekas) + * bug #23982 [VarDumper] Strengthen dumped JS (nicolas-grekas) + * bug #23925 [Validator] Fix use of GroupSequenceProvider in child classes (linniksa) + * bug #23971 [Cache] Fix lazy Memcached connections (nicolas-grekas) + * bug #23970 [Cache] Fix >30 days expirations with Memcached (nicolas-grekas) + * bug #23949 [Dotenv] Get env using $_SERVER to work with fastcgi_param and workaround thread safety issues (nicolas-grekas) + * bug #23799 [Dotenv][WebServerBundle] Override previously loaded variables (voronkovich) + * bug #23676 [WebProfilerBundle] Re add missing link to the controller (lyrixx) + * bug #23870 [DI] Use GlobResource for non-tracked directories (vudaltsov) + * bug #23945 [Validator] Fix Greek translation (azhurb) + * bug #23940 [DI] Fix resolving env vars when compiling a ContainerBuilder (nicolas-grekas) + * bug #23903 [DI] Fix merging of env vars in configs (nicolas-grekas) + * bug #23825 Revert "feature #21038 [FrameworkBundle] deprecated cache:clear with warmup (fabpot)" (nicolas-grekas) + * bug #23899 [DI] Fix reading env vars from fastcgi params (nicolas-grekas) + * bug #23909 [Console] Initialize lazily to render exceptions properly (nicolas-grekas) + * bug #23878 [VarDumper] play nice with open_basedir when looking for composer.json (nicolas-grekas) + * bug #23897 Allow phpdocumentor/reflection-docblock 4 (derrabus) + * bug #23865 [Workflow] fixed InvalidDefinitionException message for StateMachineValidator (fmata) + * bug #23856 [DI] Fix dumping abstract with YamlDumper (nicolas-grekas) + * bug #23848 restrict reflection doc block (ElectricMaxxx) + * bug #23854 [DI] Fix YamlDumper not dumping abstract and autoconfigure (nicolas-grekas) + * bug #23752 Ignore memcached missing key error on session destroy (jderusse) + * bug #23829 Fixed the exception page design in responsive mode (javiereguiluz) + * bug #23828 [Console] Log exit codes as debug messages instead of errors (haroldiedema) + * bug #23763 [Cache] Hash cache key on save (lstrojny) + * bug #23806 [Profiler] Fix request_collector check in main layout (ogizanagi) + * bug #23658 [HttpFoundation] Generate safe fallback filename for wrongly encoded filename (xelaris) + * bug #23776 [FrameworkBundle] Warmup annotations for bundle-less controllers and entities (nicolas-grekas) + * bug #23783 Avoid infinite loops when profiler data is malformed (javiereguiluz) + * bug #23638 [FrameworkBundle][Workflow] better errors when security deps are missing (xabbuh) + * bug #23729 [Bridge\ProxyManager] Dont call __destruct() on non-instantiated services (nicolas-grekas) + * bug #23703 Bump minimal PHP version to ^5.5.9|>=7.0.8 (nicolas-grekas) + * bug #23755 [Config] Fix checking class existence freshness (nicolas-grekas) + * 3.3.6 (2017-08-01) * bug #22244 [Console] Fix passing options with defaultCommand (Jakub Sacha) From 8a33ecb05842c8db497811df10b8cd93324ca351 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Mon, 28 Aug 2017 12:34:14 -0700 Subject: [PATCH 0699/1099] updated VERSION for 3.3.7 --- 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 f6a62a6341cfa..815841ec6c84f 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -61,12 +61,12 @@ abstract class Kernel implements KernelInterface, TerminableInterface private $projectDir; - const VERSION = '3.3.7-DEV'; + const VERSION = '3.3.7'; const VERSION_ID = 30307; const MAJOR_VERSION = 3; const MINOR_VERSION = 3; const RELEASE_VERSION = 7; - const EXTRA_VERSION = 'DEV'; + const EXTRA_VERSION = ''; const END_OF_MAINTENANCE = '01/2018'; const END_OF_LIFE = '07/2018'; From 0b46166174c18d53d7d5dc4fdf56e3864d674c5b Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Mon, 28 Aug 2017 13:30:14 -0700 Subject: [PATCH 0700/1099] bumped Symfony version to 3.3.8 --- 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 815841ec6c84f..4c333008cd927 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -61,12 +61,12 @@ abstract class Kernel implements KernelInterface, TerminableInterface private $projectDir; - const VERSION = '3.3.7'; - const VERSION_ID = 30307; + const VERSION = '3.3.8-DEV'; + const VERSION_ID = 30308; const MAJOR_VERSION = 3; const MINOR_VERSION = 3; - const RELEASE_VERSION = 7; - const EXTRA_VERSION = ''; + const RELEASE_VERSION = 8; + const EXTRA_VERSION = 'DEV'; const END_OF_MAINTENANCE = '01/2018'; const END_OF_LIFE = '07/2018'; From cce2dd1d5e7c72125140f28ab23d9b045f3bae67 Mon Sep 17 00:00:00 2001 From: Dany Maillard Date: Mon, 28 Aug 2017 22:48:26 +0200 Subject: [PATCH 0701/1099] Remove deprecated feature --- src/Symfony/Component/Translation/CHANGELOG.md | 1 + .../Tests/Writer/TranslationWriterTest.php | 16 ---------------- .../Translation/Writer/TranslationWriter.php | 17 ----------------- 3 files changed, 1 insertion(+), 33 deletions(-) diff --git a/src/Symfony/Component/Translation/CHANGELOG.md b/src/Symfony/Component/Translation/CHANGELOG.md index f9de2dd2f4d50..bf9f223889301 100644 --- a/src/Symfony/Component/Translation/CHANGELOG.md +++ b/src/Symfony/Component/Translation/CHANGELOG.md @@ -5,6 +5,7 @@ CHANGELOG ----- * removed the backup feature of the `FileDumper` class + * removed `TranslationWriter::writeTranslations()` method 3.4.0 ----- diff --git a/src/Symfony/Component/Translation/Tests/Writer/TranslationWriterTest.php b/src/Symfony/Component/Translation/Tests/Writer/TranslationWriterTest.php index 39da3f7c02396..f79c72b1c2152 100644 --- a/src/Symfony/Component/Translation/Tests/Writer/TranslationWriterTest.php +++ b/src/Symfony/Component/Translation/Tests/Writer/TranslationWriterTest.php @@ -18,22 +18,6 @@ class TranslationWriterTest extends TestCase { - /** - * @group legacy - * @expectedDeprecation Method Symfony\Component\Translation\Writer\TranslationWriter::writeTranslations() is deprecated since version 3.4 and will be removed in 4.0. Use write() instead. - */ - public function testWriteTranslations() - { - $dumper = $this->getMockBuilder('Symfony\Component\Translation\Dumper\DumperInterface')->getMock(); - $dumper - ->expects($this->once()) - ->method('dump'); - - $writer = new TranslationWriter(); - $writer->addDumper('test', $dumper); - $writer->writeTranslations(new MessageCatalogue(array()), 'test'); - } - public function testWrite() { $dumper = $this->getMockBuilder('Symfony\Component\Translation\Dumper\DumperInterface')->getMock(); diff --git a/src/Symfony/Component/Translation/Writer/TranslationWriter.php b/src/Symfony/Component/Translation/Writer/TranslationWriter.php index 5e0dfb925f3a6..fa28e739309bd 100644 --- a/src/Symfony/Component/Translation/Writer/TranslationWriter.php +++ b/src/Symfony/Component/Translation/Writer/TranslationWriter.php @@ -89,21 +89,4 @@ public function write(MessageCatalogue $catalogue, $format, $options = array()) // save $dumper->dump($catalogue, $options); } - - /** - * Writes translation from the catalogue according to the selected format. - * - * @param MessageCatalogue $catalogue The message catalogue to write - * @param string $format The format to use to dump the messages - * @param array $options Options that are passed to the dumper - * - * @throws InvalidArgumentException - * - * @deprecated since 3.4 will be removed in 4.0. Use write instead. - */ - public function writeTranslations(MessageCatalogue $catalogue, $format, $options = array()) - { - @trigger_error(sprintf('Method %s() is deprecated since version 3.4 and will be removed in 4.0. Use write() instead.', __METHOD__), E_USER_DEPRECATED); - $this->write($catalogue, $format, $options); - } } From a8397cf1c7dfb1cad42927660a483605b5ae4f86 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Tue, 29 Aug 2017 00:20:37 +0200 Subject: [PATCH 0702/1099] [DI] Fix tracking env var placeholders nested in object graphs --- .../MergeExtensionConfigurationPass.php | 34 +++++++------------ .../MergeExtensionConfigurationPassTest.php | 2 +- 2 files changed, 13 insertions(+), 23 deletions(-) diff --git a/src/Symfony/Component/DependencyInjection/Compiler/MergeExtensionConfigurationPass.php b/src/Symfony/Component/DependencyInjection/Compiler/MergeExtensionConfigurationPass.php index 3e4acf5664e76..853b1fd05e96e 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/MergeExtensionConfigurationPass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/MergeExtensionConfigurationPass.php @@ -95,7 +95,18 @@ public function __construct(parent $parameterBag) public function freezeAfterProcessing(Extension $extension) { $this->processedEnvPlaceholders = array(); - $this->processMergedConfig($extension->getProcessedConfigs(), parent::getEnvPlaceholders()); + + // serialize config to catch env vars nested in object graphs + $config = serialize($extension->getProcessedConfigs()); + + foreach (parent::getEnvPlaceholders() as $env => $placeholders) { + foreach ($placeholders as $placeholder) { + if (false !== stripos($config, $placeholder)) { + $this->processedEnvPlaceholders[$env] = $placeholders; + break; + } + } + } } /** @@ -105,25 +116,4 @@ public function getEnvPlaceholders() { return null !== $this->processedEnvPlaceholders ? $this->processedEnvPlaceholders : parent::getEnvPlaceholders(); } - - private function processMergedConfig($value, array $envPlaceholders) - { - if (is_array($value)) { - foreach ($value as $k => $v) { - $this->processMergedConfig($k, $envPlaceholders); - $this->processMergedConfig($v, $envPlaceholders); - } - } elseif (is_string($value)) { - foreach ($envPlaceholders as $env => $placeholders) { - foreach ($placeholders as $placeholder) { - if (false !== stripos($value, $placeholder)) { - $this->processedEnvPlaceholders[$env] = $placeholders; - break; - } - } - } - } - - return $value; - } } diff --git a/src/Symfony/Component/DependencyInjection/Tests/Compiler/MergeExtensionConfigurationPassTest.php b/src/Symfony/Component/DependencyInjection/Tests/Compiler/MergeExtensionConfigurationPassTest.php index 033e6c00fc342..44d1933a80fa8 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Compiler/MergeExtensionConfigurationPassTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Compiler/MergeExtensionConfigurationPassTest.php @@ -81,7 +81,7 @@ public function testOverriddenEnvsAreMerged() $pass = new MergeExtensionConfigurationPass(); $pass->process($container); - $this->assertSame(array('FOO', 'BAZ'), array_keys($container->getParameterBag()->getEnvPlaceholders())); + $this->assertSame(array('BAZ', 'FOO'), array_keys($container->getParameterBag()->getEnvPlaceholders())); $this->assertSame(array('BAZ' => 1, 'FOO' => 0), $container->getEnvCounters()); } } From 04e7d44d129572cd717f6fc1ed5182f3f0425f78 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Mon, 28 Aug 2017 15:34:58 -0700 Subject: [PATCH 0703/1099] updated CHANGELOG for 3.3.8 --- CHANGELOG-3.3.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG-3.3.md b/CHANGELOG-3.3.md index 185d1432cc409..3331ea2a1d1fa 100644 --- a/CHANGELOG-3.3.md +++ b/CHANGELOG-3.3.md @@ -7,6 +7,10 @@ in 3.3 minor versions. To get the diff for a specific change, go to https://github.com/symfony/symfony/commit/XXX where XXX is the change hash To get the diff between two versions, go to https://github.com/symfony/symfony/compare/v3.3.0...v3.3.1 +* 3.3.8 (2017-08-28) + + * bug #24016 [DI] Fix tracking env var placeholders nested in object graphs (nicolas-grekas) + * 3.3.7 (2017-08-28) * bug #24009 [DI] Fix tracking env vars when merging configs (bis) (nicolas-grekas) From bad5b6293dae27b763c66c1f71ff435b71e06809 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Mon, 28 Aug 2017 15:35:03 -0700 Subject: [PATCH 0704/1099] updated VERSION for 3.3.8 --- src/Symfony/Component/HttpKernel/Kernel.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/HttpKernel/Kernel.php b/src/Symfony/Component/HttpKernel/Kernel.php index 4c333008cd927..0fa9dbd5451b6 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -61,12 +61,12 @@ abstract class Kernel implements KernelInterface, TerminableInterface private $projectDir; - const VERSION = '3.3.8-DEV'; + const VERSION = '3.3.8'; const VERSION_ID = 30308; const MAJOR_VERSION = 3; const MINOR_VERSION = 3; const RELEASE_VERSION = 8; - const EXTRA_VERSION = 'DEV'; + const EXTRA_VERSION = ''; const END_OF_MAINTENANCE = '01/2018'; const END_OF_LIFE = '07/2018'; From 9280ca429ea515c4d49a72ce236872562eb9c4a9 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Mon, 28 Aug 2017 15:49:36 -0700 Subject: [PATCH 0705/1099] bumped Symfony version to 3.3.9 --- src/Symfony/Component/HttpKernel/Kernel.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Symfony/Component/HttpKernel/Kernel.php b/src/Symfony/Component/HttpKernel/Kernel.php index 0fa9dbd5451b6..f8ed2b08b4b63 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -61,12 +61,12 @@ abstract class Kernel implements KernelInterface, TerminableInterface private $projectDir; - const VERSION = '3.3.8'; - const VERSION_ID = 30308; + const VERSION = '3.3.9-DEV'; + const VERSION_ID = 30309; const MAJOR_VERSION = 3; const MINOR_VERSION = 3; - const RELEASE_VERSION = 8; - const EXTRA_VERSION = ''; + const RELEASE_VERSION = 9; + const EXTRA_VERSION = 'DEV'; const END_OF_MAINTENANCE = '01/2018'; const END_OF_LIFE = '07/2018'; From a8e6aac2f58ca3f12c931f20a6de29ef46686dc8 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Tue, 29 Aug 2017 14:43:33 +0200 Subject: [PATCH 0706/1099] [DI] Don't track merged configs when the extension doesn't expose it --- .../Compiler/MergeExtensionConfigurationPass.php | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/Symfony/Component/DependencyInjection/Compiler/MergeExtensionConfigurationPass.php b/src/Symfony/Component/DependencyInjection/Compiler/MergeExtensionConfigurationPass.php index 853b1fd05e96e..c3b4d78dd622d 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/MergeExtensionConfigurationPass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/MergeExtensionConfigurationPass.php @@ -67,7 +67,7 @@ public function process(ContainerBuilder $container) if ($resolvingBag instanceof MergeExtensionConfigurationParameterBag) { // don't keep track of env vars that are *overridden* when configs are merged - $resolvingBag->freezeAfterProcessing($extension); + $resolvingBag->freezeAfterProcessing($extension, $tmpContainer); } $container->merge($tmpContainer); @@ -92,12 +92,16 @@ public function __construct(parent $parameterBag) $this->mergeEnvPlaceholders($parameterBag); } - public function freezeAfterProcessing(Extension $extension) + public function freezeAfterProcessing(Extension $extension, ContainerBuilder $container) { + if (!$config = $extension->getProcessedConfigs()) { + // Extension::processConfiguration() wasn't called, we cannot know how configs were merged + return; + } $this->processedEnvPlaceholders = array(); - // serialize config to catch env vars nested in object graphs - $config = serialize($extension->getProcessedConfigs()); + // serialize config and container to catch env vars nested in object graphs + $config = serialize($config).serialize($container->getDefinitions()).serialize($container->getAliases()).serialize($container->getParameterBag()->all()); foreach (parent::getEnvPlaceholders() as $env => $placeholders) { foreach ($placeholders as $placeholder) { From a8d72e260fe9e5b644f5771ce09cc51e3c734db0 Mon Sep 17 00:00:00 2001 From: Javier Eguiluz Date: Mon, 28 Aug 2017 12:16:53 +0200 Subject: [PATCH 0707/1099] [Lock] Fix some tests that require pcntl_sigwaitinfo() function --- .../Component/Lock/Tests/Store/BlockingStoreTestTrait.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Symfony/Component/Lock/Tests/Store/BlockingStoreTestTrait.php b/src/Symfony/Component/Lock/Tests/Store/BlockingStoreTestTrait.php index 5d7691fa8c7f2..93e5a54793f31 100644 --- a/src/Symfony/Component/Lock/Tests/Store/BlockingStoreTestTrait.php +++ b/src/Symfony/Component/Lock/Tests/Store/BlockingStoreTestTrait.php @@ -31,6 +31,7 @@ abstract protected function getStore(); * This test is time sensible: the $clockDelay could be adjust. * * @requires extension pcntl + * @requires function pcntl_sigwaitinfo */ public function testBlockingLocks() { From 9d444421ea80f43b58a3b254ef78c58b2f1a9f4a Mon Sep 17 00:00:00 2001 From: Guillaume LECERF Date: Mon, 28 Aug 2017 23:40:21 +0200 Subject: [PATCH 0708/1099] Always require symfony/polyfill-apcu to provide APCuIterator everywhere --- composer.json | 2 +- .../Cache/Tests/Adapter/ApcuAdapterTest.php | 25 +++++++++++++++++++ src/Symfony/Component/Cache/composer.json | 6 ++--- 3 files changed, 28 insertions(+), 5 deletions(-) diff --git a/composer.json b/composer.json index ff894a349e227..d55f29f6aaa8a 100644 --- a/composer.json +++ b/composer.json @@ -26,6 +26,7 @@ "psr/link": "^1.0", "psr/log": "~1.0", "psr/simple-cache": "^1.0", + "symfony/polyfill-apcu": "~1.1", "symfony/polyfill-intl-icu": "~1.0", "symfony/polyfill-mbstring": "~1.0", "symfony/polyfill-php56": "~1.0", @@ -96,7 +97,6 @@ "predis/predis": "~1.0", "egulias/email-validator": "~1.2,>=1.2.8|~2.0", "symfony/phpunit-bridge": "~3.2", - "symfony/polyfill-apcu": "~1.1", "symfony/security-acl": "~2.8|~3.0", "phpdocumentor/reflection-docblock": "^3.0|^4.0", "sensio/framework-extra-bundle": "^3.0.2" diff --git a/src/Symfony/Component/Cache/Tests/Adapter/ApcuAdapterTest.php b/src/Symfony/Component/Cache/Tests/Adapter/ApcuAdapterTest.php index 6cad6135cf4a0..75b3fa299ec29 100644 --- a/src/Symfony/Component/Cache/Tests/Adapter/ApcuAdapterTest.php +++ b/src/Symfony/Component/Cache/Tests/Adapter/ApcuAdapterTest.php @@ -77,6 +77,31 @@ public function testVersion() $this->assertNull($item->get()); } + public function testNamespace() + { + $namespace = str_replace('\\', '.', get_class($this)); + + $pool1 = new ApcuAdapter($namespace.'_1', 0, 'p1'); + + $item = $pool1->getItem('foo'); + $this->assertFalse($item->isHit()); + $this->assertTrue($pool1->save($item->set('bar'))); + + $item = $pool1->getItem('foo'); + $this->assertTrue($item->isHit()); + $this->assertSame('bar', $item->get()); + + $pool2 = new ApcuAdapter($namespace.'_2', 0, 'p1'); + + $item = $pool2->getItem('foo'); + $this->assertFalse($item->isHit()); + $this->assertNull($item->get()); + + $item = $pool1->getItem('foo'); + $this->assertTrue($item->isHit()); + $this->assertSame('bar', $item->get()); + } + public function testWithCliSapi() { try { diff --git a/src/Symfony/Component/Cache/composer.json b/src/Symfony/Component/Cache/composer.json index f32117b038479..78f5c026805da 100644 --- a/src/Symfony/Component/Cache/composer.json +++ b/src/Symfony/Component/Cache/composer.json @@ -23,7 +23,8 @@ "php": "^5.5.9|>=7.0.8", "psr/cache": "~1.0", "psr/log": "~1.0", - "psr/simple-cache": "^1.0" + "psr/simple-cache": "^1.0", + "symfony/polyfill-apcu": "~1.1" }, "require-dev": { "cache/integration-tests": "dev-master", @@ -34,9 +35,6 @@ "conflict": { "symfony/var-dumper": "<3.3" }, - "suggest": { - "symfony/polyfill-apcu": "For using ApcuAdapter on HHVM" - }, "autoload": { "psr-4": { "Symfony\\Component\\Cache\\": "" }, "exclude-from-classmap": [ From 5bc50da677ce582ba0c1cc6371af3e753102bd4f Mon Sep 17 00:00:00 2001 From: Tobias Nyholm Date: Tue, 25 Jul 2017 20:07:39 +0200 Subject: [PATCH 0709/1099] Create an interface for TranslationReader and moved TranslationLoader to Translation component --- UPGRADE-3.4.md | 6 ++ UPGRADE-4.0.md | 8 +++ .../Bundle/FrameworkBundle/CHANGELOG.md | 3 + .../Command/TranslationDebugCommand.php | 20 +++--- .../Command/TranslationUpdateCommand.php | 14 ++-- .../FrameworkBundle/FrameworkBundle.php | 5 +- .../Resources/config/translation.xml | 5 +- .../Command/TranslationDebugCommandTest.php | 6 +- .../Command/TranslationUpdateCommandTest.php | 6 +- .../FrameworkExtensionTest.php | 2 +- .../Translation/TranslationLoader.php | 44 ++---------- .../Component/Translation/CHANGELOG.md | 1 + .../DependencyInjection/TranslatorPass.php | 26 +++++-- .../Translation/Reader/TranslationReader.php | 63 +++++++++++++++++ .../Reader/TranslationReaderInterface.php | 30 +++++++++ .../TranslationPassTest.php | 67 +++++++++++++++++-- .../Component/Translation/composer.json | 1 + 17 files changed, 231 insertions(+), 76 deletions(-) create mode 100644 src/Symfony/Component/Translation/Reader/TranslationReader.php create mode 100644 src/Symfony/Component/Translation/Reader/TranslationReaderInterface.php diff --git a/UPGRADE-3.4.md b/UPGRADE-3.4.md index 7ef52c3c44f8b..5408251e98968 100644 --- a/UPGRADE-3.4.md +++ b/UPGRADE-3.4.md @@ -114,6 +114,12 @@ FrameworkBundle class has been deprecated and will be removed in 4.0. Use the `Symfony\Component\Translation\DependencyInjection\TranslatorPass` class instead. + * The `Symfony\Bundle\FrameworkBundle\Translation\TranslationLoader` + class has been deprecated and will be removed in 4.0. Use the + `Symfony\Component\Translation\Reader\TranslationReader` class instead. + + * The `translation.loader` service has been deprecated and will be removed in 4.0. Use the `translation.reader` service instead. + HttpKernel ---------- diff --git a/UPGRADE-4.0.md b/UPGRADE-4.0.md index cad8e7df786cb..0b9a727a17368 100644 --- a/UPGRADE-4.0.md +++ b/UPGRADE-4.0.md @@ -414,7 +414,13 @@ FrameworkBundle * The `Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\TranslatorPass` class has been removed. Use the `Symfony\Component\Translation\DependencyInjection\TranslatorPass` class instead. + + * The `Symfony\Bundle\FrameworkBundle\Translation\TranslationLoader` + class has been deprecated and will be removed in 4.0. Use the + `Symfony\Component\Translation\Reader\TranslationReader` class instead. + * The `translation.loader` service has been deprecated and will be removed in 4.0. Use the `translation.reader` service instead. + HttpFoundation -------------- @@ -581,6 +587,8 @@ Translation * Removed the backup feature from the file dumper classes. + * The default value of the `$readerServiceId` argument of `TranslatorPass::__construct()` has been changed to `"translation.reader"`. + * Removed `Symfony\Component\Translation\Writer\TranslationWriter::writeTranslations`, use `Symfony\Component\Translation\Writer\TranslationWriter::write` instead. diff --git a/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md b/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md index 5bf7ee620957a..4a51222f7e90d 100644 --- a/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md +++ b/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md @@ -23,6 +23,9 @@ CHANGELOG name as value, using it makes the command lazy * Added `cache:pool:prune` command to allow manual stale cache item pruning of supported PSR-6 and PSR-16 cache pool implementations + * Deprecated `Symfony\Bundle\FrameworkBundle\Translation\TranslationLoader`, use + `Symfony\Component\Translation\Reader\TranslationReader` instead + * Deprecated `translation.loader` service, use `translation.reader` instead 3.3.0 ----- diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/TranslationDebugCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/TranslationDebugCommand.php index cbf6bda5f3fff..e4e16960fc577 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/TranslationDebugCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/TranslationDebugCommand.php @@ -11,7 +11,6 @@ namespace Symfony\Bundle\FrameworkBundle\Command; -use Symfony\Bundle\FrameworkBundle\Translation\TranslationLoader; use Symfony\Component\Console\Style\SymfonyStyle; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputArgument; @@ -21,6 +20,7 @@ use Symfony\Component\Translation\Catalogue\MergeOperation; use Symfony\Component\Translation\Extractor\ExtractorInterface; use Symfony\Component\Translation\MessageCatalogue; +use Symfony\Component\Translation\Reader\TranslationReaderInterface; use Symfony\Component\Translation\Translator; use Symfony\Component\Translation\DataCollectorTranslator; use Symfony\Component\Translation\LoggingTranslator; @@ -43,15 +43,15 @@ class TranslationDebugCommand extends ContainerAwareCommand protected static $defaultName = 'debug:translation'; private $translator; - private $loader; + private $reader; private $extractor; /** - * @param TranslatorInterface $translator - * @param TranslationLoader $loader - * @param ExtractorInterface $extractor + * @param TranslatorInterface $translator + * @param TranslationReaderInterface $reader + * @param ExtractorInterface $extractor */ - public function __construct($translator = null, TranslationLoader $loader = null, ExtractorInterface $extractor = null) + public function __construct($translator = null, TranslationReaderInterface $reader = null, ExtractorInterface $extractor = null) { if (!$translator instanceof TranslatorInterface) { @trigger_error(sprintf('Passing a command name as the first argument of "%s" is deprecated since version 3.4 and will be removed in 4.0. If the command was registered by convention, make it a service instead.', __METHOD__), E_USER_DEPRECATED); @@ -64,7 +64,7 @@ public function __construct($translator = null, TranslationLoader $loader = null parent::__construct(); $this->translator = $translator; - $this->loader = $loader; + $this->reader = $reader; $this->extractor = $extractor; } @@ -142,7 +142,7 @@ protected function execute(InputInterface $input, OutputInterface $output) // BC to be removed in 4.0 if (null === $this->translator) { $this->translator = $this->getContainer()->get('translator'); - $this->loader = $this->getContainer()->get('translation.loader'); + $this->reader = $this->getContainer()->get('translation.reader'); $this->extractor = $this->getContainer()->get('translation.extractor'); } @@ -331,7 +331,7 @@ private function loadCurrentMessages($locale, $transPaths) foreach ($transPaths as $path) { $path = $path.'translations'; if (is_dir($path)) { - $this->loader->loadMessages($path, $currentCatalogue); + $this->reader->read($path, $currentCatalogue); } } @@ -357,7 +357,7 @@ private function loadFallbackCatalogues($locale, $transPaths) foreach ($transPaths as $path) { $path = $path.'translations'; if (is_dir($path)) { - $this->loader->loadMessages($path, $fallbackCatalogue); + $this->reader->read($path, $fallbackCatalogue); } } $fallbackCatalogues[] = $fallbackCatalogue; diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/TranslationUpdateCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/TranslationUpdateCommand.php index abbe1e3b5460c..ff35fda56e1ef 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/TranslationUpdateCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/TranslationUpdateCommand.php @@ -11,7 +11,6 @@ namespace Symfony\Bundle\FrameworkBundle\Command; -use Symfony\Bundle\FrameworkBundle\Translation\TranslationLoader; use Symfony\Component\Console\Style\SymfonyStyle; use Symfony\Component\Translation\Catalogue\TargetOperation; use Symfony\Component\Translation\Catalogue\MergeOperation; @@ -21,6 +20,7 @@ use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Translation\Extractor\ExtractorInterface; use Symfony\Component\Translation\MessageCatalogue; +use Symfony\Component\Translation\Reader\TranslationReaderInterface; use Symfony\Component\Translation\Writer\TranslationWriterInterface; /** @@ -36,17 +36,17 @@ class TranslationUpdateCommand extends ContainerAwareCommand protected static $defaultName = 'translation:update'; private $writer; - private $loader; + private $reader; private $extractor; private $defaultLocale; /** * @param TranslationWriterInterface $writer - * @param TranslationLoader $loader + * @param TranslationReaderInterface $reader * @param ExtractorInterface $extractor * @param string $defaultLocale */ - public function __construct($writer = null, TranslationLoader $loader = null, ExtractorInterface $extractor = null, $defaultLocale = null) + public function __construct($writer = null, TranslationReaderInterface $reader = null, ExtractorInterface $extractor = null, $defaultLocale = null) { if (!$writer instanceof TranslationWriterInterface) { @trigger_error(sprintf('Passing a command name as the first argument of "%s" is deprecated since version 3.4 and will be removed in 4.0. If the command was registered by convention, make it a service instead.', __METHOD__), E_USER_DEPRECATED); @@ -59,7 +59,7 @@ public function __construct($writer = null, TranslationLoader $loader = null, Ex parent::__construct(); $this->writer = $writer; - $this->loader = $loader; + $this->reader = $reader; $this->extractor = $extractor; $this->defaultLocale = $defaultLocale; } @@ -127,7 +127,7 @@ protected function execute(InputInterface $input, OutputInterface $output) // BC to be removed in 4.0 if (null === $this->writer) { $this->writer = $this->getContainer()->get('translation.writer'); - $this->loader = $this->getContainer()->get('translation.loader'); + $this->reader = $this->getContainer()->get('translation.reader'); $this->extractor = $this->getContainer()->get('translation.extractor'); $this->defaultLocale = $this->getContainer()->getParameter('kernel.default_locale'); } @@ -201,7 +201,7 @@ protected function execute(InputInterface $input, OutputInterface $output) foreach ($transPaths as $path) { $path .= 'translations'; if (is_dir($path)) { - $this->loader->loadMessages($path, $currentCatalogue); + $this->reader->read($path, $currentCatalogue); } } diff --git a/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php b/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php index c53deb16e2fa4..47129136d7920 100644 --- a/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php +++ b/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php @@ -96,7 +96,10 @@ public function build(ContainerBuilder $container) $container->addCompilerPass(new AddAnnotationsCachedReaderPass(), PassConfig::TYPE_BEFORE_REMOVING); $this->addCompilerPassIfExists($container, AddValidatorInitializersPass::class); $this->addCompilerPassIfExists($container, AddConsoleCommandPass::class); - $this->addCompilerPassIfExists($container, TranslatorPass::class); + if (class_exists(TranslatorPass::class)) { + // Arguments to be removed in 4.0, relying on the default values + $container->addCompilerPass(new TranslatorPass('translator.default', 'translation.loader')); + } $container->addCompilerPass(new LoggingTranslatorPass()); $container->addCompilerPass(new AddCacheWarmerPass()); $container->addCompilerPass(new AddCacheClearerPass()); diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/translation.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/translation.xml index cd0a983010c8a..cfe05f5148fdd 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/translation.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/translation.xml @@ -121,7 +121,10 @@
- + + The "%service_id%" service is deprecated since Symfony 3.4 and will be removed in 4.0. Use "translation.reader" instead. + + diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/TranslationDebugCommandTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/TranslationDebugCommandTest.php index edf006c86801c..ff7cab4589b02 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/TranslationDebugCommandTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/TranslationDebugCommandTest.php @@ -130,10 +130,10 @@ private function createCommandTester($extractedMessages = array(), $loadedMessag }) ); - $loader = $this->getMockBuilder('Symfony\Bundle\FrameworkBundle\Translation\TranslationLoader')->getMock(); + $loader = $this->getMockBuilder('Symfony\Component\Translation\Reader\TranslationReader')->getMock(); $loader ->expects($this->any()) - ->method('loadMessages') + ->method('read') ->will( $this->returnCallback(function ($path, $catalogue) use ($loadedMessages) { $catalogue->add($loadedMessages); @@ -197,7 +197,7 @@ public function testLegacyDebugCommand() ->method('get') ->will($this->returnValueMap(array( array('translation.extractor', 1, $extractor), - array('translation.loader', 1, $loader), + array('translation.reader', 1, $loader), array('translator', 1, $translator), array('kernel', 1, $kernel), ))); diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/TranslationUpdateCommandTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/TranslationUpdateCommandTest.php index db61398b26d9a..b0804503eb79f 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/TranslationUpdateCommandTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/TranslationUpdateCommandTest.php @@ -101,10 +101,10 @@ private function createCommandTester($extractedMessages = array(), $loadedMessag }) ); - $loader = $this->getMockBuilder('Symfony\Bundle\FrameworkBundle\Translation\TranslationLoader')->getMock(); + $loader = $this->getMockBuilder('Symfony\Component\Translation\Reader\TranslationReader')->getMock(); $loader ->expects($this->any()) - ->method('loadMessages') + ->method('read') ->will( $this->returnCallback(function ($path, $catalogue) use ($loadedMessages) { $catalogue->add($loadedMessages); @@ -177,7 +177,7 @@ public function testLegacyUpdateCommand() ->method('get') ->will($this->returnValueMap(array( array('translation.extractor', 1, $extractor), - array('translation.loader', 1, $loader), + array('translation.reader', 1, $loader), array('translation.writer', 1, $writer), array('translator', 1, $translator), array('kernel', 1, $kernel), diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php index b7d261959c57f..d63a74c874f02 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php @@ -1000,7 +1000,7 @@ protected function createContainerFromFile($file, $data = array(), $resetCompile $container->getCompilerPassConfig()->setOptimizationPasses(array()); $container->getCompilerPassConfig()->setRemovingPasses(array()); } - $container->getCompilerPassConfig()->setBeforeRemovingPasses(array(new AddAnnotationsCachedReaderPass(), new AddConstraintValidatorsPass(), new TranslatorPass())); + $container->getCompilerPassConfig()->setBeforeRemovingPasses(array(new AddAnnotationsCachedReaderPass(), new AddConstraintValidatorsPass(), new TranslatorPass('translator.default', 'translation.reader'))); $container->compile(); return self::$containerCache[$cacheKey] = $container; diff --git a/src/Symfony/Bundle/FrameworkBundle/Translation/TranslationLoader.php b/src/Symfony/Bundle/FrameworkBundle/Translation/TranslationLoader.php index b6377863afe48..b125c75c0676c 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Translation/TranslationLoader.php +++ b/src/Symfony/Bundle/FrameworkBundle/Translation/TranslationLoader.php @@ -11,35 +11,16 @@ namespace Symfony\Bundle\FrameworkBundle\Translation; -use Symfony\Component\Finder\Finder; +use Symfony\Component\Translation\Reader\TranslationReader; use Symfony\Component\Translation\MessageCatalogue; -use Symfony\Component\Translation\Loader\LoaderInterface; + +@trigger_error(sprintf('The class "%s" is deprecated since version 3.4 and will be removed in 4.0. Use "%s" instead. ', TranslationLoader::class, TranslationReader::class), E_USER_DEPRECATED); /** - * TranslationLoader loads translation messages from translation files. - * - * @author Michel Salib + * @deprecated since version 3.4 and will be removed in 4.0. Use Symfony\Component\Translation\Reader\TranslationReader instead */ -class TranslationLoader +class TranslationLoader extends TranslationReader { - /** - * Loaders used for import. - * - * @var array - */ - private $loaders = array(); - - /** - * Adds a loader to the translation extractor. - * - * @param string $format The format of the loader - * @param LoaderInterface $loader - */ - public function addLoader($format, LoaderInterface $loader) - { - $this->loaders[$format] = $loader; - } - /** * Loads translation messages from a directory to the catalogue. * @@ -48,19 +29,6 @@ public function addLoader($format, LoaderInterface $loader) */ public function loadMessages($directory, MessageCatalogue $catalogue) { - if (!is_dir($directory)) { - return; - } - - foreach ($this->loaders as $format => $loader) { - // load any existing translation files - $finder = new Finder(); - $extension = $catalogue->getLocale().'.'.$format; - $files = $finder->files()->name('*.'.$extension)->in($directory); - foreach ($files as $file) { - $domain = substr($file->getFilename(), 0, -1 * strlen($extension) - 1); - $catalogue->addCatalogue($loader->load($file->getPathname(), $catalogue->getLocale(), $domain)); - } - } + $this->read($directory, $catalogue); } } diff --git a/src/Symfony/Component/Translation/CHANGELOG.md b/src/Symfony/Component/Translation/CHANGELOG.md index 65fae7eda8508..cdd11cb91be6c 100644 --- a/src/Symfony/Component/Translation/CHANGELOG.md +++ b/src/Symfony/Component/Translation/CHANGELOG.md @@ -7,6 +7,7 @@ CHANGELOG * Added `TranslationDumperPass` * Added `TranslationExtractorPass` * Added `TranslatorPass` + * Added `TranslationReader` and `TranslationReaderInterface` * Added `` section to the Xliff 2.0 dumper. * Improved Xliff 2.0 loader to load `` section. * Added `TranslationWriterInterface` diff --git a/src/Symfony/Component/Translation/DependencyInjection/TranslatorPass.php b/src/Symfony/Component/Translation/DependencyInjection/TranslatorPass.php index e144f6b74ef10..07fc9f68f0152 100644 --- a/src/Symfony/Component/Translation/DependencyInjection/TranslatorPass.php +++ b/src/Symfony/Component/Translation/DependencyInjection/TranslatorPass.php @@ -19,13 +19,17 @@ class TranslatorPass implements CompilerPassInterface { private $translatorServiceId; - private $loaderServiceId; + private $readerServiceId; private $loaderTag; - public function __construct($translatorServiceId = 'translator.default', $loaderServiceId = 'translation.loader', $loaderTag = 'translation.loader') + public function __construct($translatorServiceId = 'translator.default', $readerServiceId = 'translation.loader', $loaderTag = 'translation.loader') { + if ('translation.loader' === $readerServiceId && 2 > func_num_args()) { + @trigger_error('The default value for $readerServiceId will change in 4.0 to "translation.reader".', E_USER_DEPRECATED); + } + $this->translatorServiceId = $translatorServiceId; - $this->loaderServiceId = $loaderServiceId; + $this->readerServiceId = $readerServiceId; $this->loaderTag = $loaderTag; } @@ -45,8 +49,8 @@ public function process(ContainerBuilder $container) } } - if ($container->hasDefinition($this->loaderServiceId)) { - $definition = $container->getDefinition($this->loaderServiceId); + if ($container->hasDefinition($this->readerServiceId)) { + $definition = $container->getDefinition($this->readerServiceId); foreach ($loaders as $id => $formats) { foreach ($formats as $format) { $definition->addMethodCall('addLoader', array($format, $loaderRefs[$id])); @@ -54,6 +58,18 @@ public function process(ContainerBuilder $container) } } + // Duplicated code to support "translation.reader", to be removed in 4.0 + if ('translation.reader' !== $this->readerServiceId) { + if ($container->hasDefinition('translation.reader')) { + $definition = $container->getDefinition('translation.reader'); + foreach ($loaders as $id => $formats) { + foreach ($formats as $format) { + $definition->addMethodCall('addLoader', array($format, $loaderRefs[$id])); + } + } + } + } + $container ->findDefinition($this->translatorServiceId) ->replaceArgument(0, ServiceLocatorTagPass::register($container, $loaderRefs)) diff --git a/src/Symfony/Component/Translation/Reader/TranslationReader.php b/src/Symfony/Component/Translation/Reader/TranslationReader.php new file mode 100644 index 0000000000000..d2ad774e28794 --- /dev/null +++ b/src/Symfony/Component/Translation/Reader/TranslationReader.php @@ -0,0 +1,63 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Reader; + +use Symfony\Component\Finder\Finder; +use Symfony\Component\Translation\Loader\LoaderInterface; +use Symfony\Component\Translation\MessageCatalogue; + +/** + * TranslationReader reads translation messages from translation files. + * + * @author Michel Salib + */ +class TranslationReader implements TranslationReaderInterface +{ + /** + * Loaders used for import. + * + * @var array + */ + private $loaders = array(); + + /** + * Adds a loader to the translation extractor. + * + * @param string $format The format of the loader + * @param LoaderInterface $loader + */ + public function addLoader($format, LoaderInterface $loader) + { + $this->loaders[$format] = $loader; + } + + /** + * {@inheritdoc} + */ + public function read($directory, MessageCatalogue $catalogue) + { + if (!is_dir($directory)) { + return; + } + + foreach ($this->loaders as $format => $loader) { + // load any existing translation files + $finder = new Finder(); + $extension = $catalogue->getLocale().'.'.$format; + $files = $finder->files()->name('*.'.$extension)->in($directory); + foreach ($files as $file) { + $domain = substr($file->getFilename(), 0, -1 * strlen($extension) - 1); + $catalogue->addCatalogue($loader->load($file->getPathname(), $catalogue->getLocale(), $domain)); + } + } + } +} diff --git a/src/Symfony/Component/Translation/Reader/TranslationReaderInterface.php b/src/Symfony/Component/Translation/Reader/TranslationReaderInterface.php new file mode 100644 index 0000000000000..0aa55c6d367dc --- /dev/null +++ b/src/Symfony/Component/Translation/Reader/TranslationReaderInterface.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\Component\Translation\Reader; + +use Symfony\Component\Translation\MessageCatalogue; + +/** + * TranslationReader reads translation messages from translation files. + * + * @author Tobias Nyholm + */ +interface TranslationReaderInterface +{ + /** + * Reads translation messages from a directory to the catalogue. + * + * @param string $directory + * @param MessageCatalogue $catalogue + */ + public function read($directory, MessageCatalogue $catalogue); +} diff --git a/src/Symfony/Component/Translation/Tests/DependencyInjection/TranslationPassTest.php b/src/Symfony/Component/Translation/Tests/DependencyInjection/TranslationPassTest.php index 8a4dff70a7946..c0274738d0f0d 100644 --- a/src/Symfony/Component/Translation/Tests/DependencyInjection/TranslationPassTest.php +++ b/src/Symfony/Component/Translation/Tests/DependencyInjection/TranslationPassTest.php @@ -25,26 +25,79 @@ public function testValidCollector() $loader = (new Definition()) ->addTag('translation.loader', array('alias' => 'xliff', 'legacy-alias' => 'xlf')); + $reader = new Definition(); + $translator = (new Definition()) ->setArguments(array(null, null, null, null)); $container = new ContainerBuilder(); $container->setDefinition('translator.default', $translator); - $container->setDefinition('translation.loader', $loader); + $container->setDefinition('translation.reader', $reader); + $container->setDefinition('translation.xliff_loader', $loader); + + $pass = new TranslatorPass('translator.default', 'translation.reader'); + $pass->process($container); + + $expectedReader = (new Definition()) + ->addMethodCall('addLoader', array('xliff', new Reference('translation.xliff_loader'))) + ->addMethodCall('addLoader', array('xlf', new Reference('translation.xliff_loader'))) + ; + $this->assertEquals($expectedReader, $reader); + + $expectedLoader = (new Definition()) + ->addTag('translation.loader', array('alias' => 'xliff', 'legacy-alias' => 'xlf')) + ; + $this->assertEquals($expectedLoader, $loader); + + $this->assertSame(array('translation.xliff_loader' => array('xliff', 'xlf')), $translator->getArgument(3)); + + $expected = array('translation.xliff_loader' => new ServiceClosureArgument(new Reference('translation.xliff_loader'))); + $this->assertEquals($expected, $container->getDefinition((string) $translator->getArgument(0))->getArgument(0)); + } + + /** + * @group legacy + * @expectedDeprecation The default value for $readerServiceId will change in 4.0 to "translation.reader". + * + * A test that verifies the deprecated "translation.loader" gets the LoaderInterfaces added. + * + * This test should be removed in 4.0. + */ + public function testValidCollectorWithDeprecatedTranslationLoader() + { + $loader = (new Definition()) + ->addTag('translation.loader', array('alias' => 'xliff', 'legacy-alias' => 'xlf')); + + $legacyReader = new Definition(); + $reader = new Definition(); + + $translator = (new Definition()) + ->setArguments(array(null, null, null, null)); + + $container = new ContainerBuilder(); + $container->setDefinition('translator.default', $translator); + $container->setDefinition('translation.loader', $legacyReader); + $container->setDefinition('translation.reader', $reader); + $container->setDefinition('translation.xliff_loader', $loader); $pass = new TranslatorPass(); $pass->process($container); - $expected = (new Definition()) + $expectedReader = (new Definition()) + ->addMethodCall('addLoader', array('xliff', new Reference('translation.xliff_loader'))) + ->addMethodCall('addLoader', array('xlf', new Reference('translation.xliff_loader'))) + ; + $this->assertEquals($expectedReader, $legacyReader); + $this->assertEquals($expectedReader, $reader); + + $expectedLoader = (new Definition()) ->addTag('translation.loader', array('alias' => 'xliff', 'legacy-alias' => 'xlf')) - ->addMethodCall('addLoader', array('xliff', new Reference('translation.loader'))) - ->addMethodCall('addLoader', array('xlf', new Reference('translation.loader'))) ; - $this->assertEquals($expected, $loader); + $this->assertEquals($expectedLoader, $loader); - $this->assertSame(array('translation.loader' => array('xliff', 'xlf')), $translator->getArgument(3)); + $this->assertSame(array('translation.xliff_loader' => array('xliff', 'xlf')), $translator->getArgument(3)); - $expected = array('translation.loader' => new ServiceClosureArgument(new Reference('translation.loader'))); + $expected = array('translation.xliff_loader' => new ServiceClosureArgument(new Reference('translation.xliff_loader'))); $this->assertEquals($expected, $container->getDefinition((string) $translator->getArgument(0))->getArgument(0)); } } diff --git a/src/Symfony/Component/Translation/composer.json b/src/Symfony/Component/Translation/composer.json index 0c4c89dd48a35..48873b98268c4 100644 --- a/src/Symfony/Component/Translation/composer.json +++ b/src/Symfony/Component/Translation/composer.json @@ -24,6 +24,7 @@ "symfony/dependency-injection": "~3.4|~4.0", "symfony/intl": "^2.8.18|^3.2.5|~4.0", "symfony/yaml": "~3.3|~4.0", + "symfony/finder": "~2.8|~3.0|~4.0", "psr/log": "~1.0" }, "conflict": { From d84e9c817136fb9eec09fcc244e0d4b0eac97c57 Mon Sep 17 00:00:00 2001 From: Dany Maillard Date: Tue, 29 Aug 2017 17:25:34 +0200 Subject: [PATCH 0710/1099] Fix segfault in period caster --- src/Symfony/Component/VarDumper/Caster/DateCaster.php | 2 +- src/Symfony/Component/VarDumper/Tests/Caster/DateCasterTest.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/VarDumper/Caster/DateCaster.php b/src/Symfony/Component/VarDumper/Caster/DateCaster.php index 0b6f551e0b57b..11e243a8bc13b 100644 --- a/src/Symfony/Component/VarDumper/Caster/DateCaster.php +++ b/src/Symfony/Component/VarDumper/Caster/DateCaster.php @@ -85,7 +85,7 @@ public static function castTimeZone(\DateTimeZone $timeZone, array $a, Stub $stu public static function castPeriod(\DatePeriod $p, array $a, Stub $stub, $isNested, $filter) { - if (defined('HHVM_VERSION_ID') || \PHP_VERSION_ID < 50605) { + if (defined('HHVM_VERSION_ID') || \PHP_VERSION_ID < 50620 || (\PHP_VERSION_ID >= 70000 && \PHP_VERSION_ID < 70005)) { // see https://bugs.php.net/bug.php?id=71635 return $a; } diff --git a/src/Symfony/Component/VarDumper/Tests/Caster/DateCasterTest.php b/src/Symfony/Component/VarDumper/Tests/Caster/DateCasterTest.php index 2acea527f0dc4..55d84a1add008 100644 --- a/src/Symfony/Component/VarDumper/Tests/Caster/DateCasterTest.php +++ b/src/Symfony/Component/VarDumper/Tests/Caster/DateCasterTest.php @@ -334,7 +334,7 @@ public function testDumpPeriod($start, $interval, $end, $options, $expected) */ public function testCastPeriod($start, $interval, $end, $options, $xPeriod, $xDates) { - if (defined('HHVM_VERSION_ID') || \PHP_VERSION_ID < 50605) { + if (defined('HHVM_VERSION_ID') || \PHP_VERSION_ID < 50620 || (\PHP_VERSION_ID >= 70000 && \PHP_VERSION_ID < 70005)) { $this->markTestSkipped(); } From d4e81669278428eb50b19a54756f18c3f4714165 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Sat, 26 Aug 2017 08:01:55 -0700 Subject: [PATCH 0711/1099] feature #22382 [config] Add abbitily to deprecate a node (Nyholm, fabpot, sanpii) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This PR was merged into the 3.4-dev branch. Discussion ---------- [config] Add abbitily to deprecate a node | Q | A | ------------- | --- | Branch? | 3.4 | Bug fix? | no | New feature? | yes | BC breaks? | maybe | Deprecations? | no | Tests pass? | yes | Fixed tickets | n/a | License | MIT | Doc PR | https://github.com/symfony/symfony-docs/pull/7794 For BC breaks, I don’t know if modifying the Xml and Yaml dumper output is considering as a BC break (it’s just a comment). Commits ------- 31d2250f4c [config] Add abbitily to deprecate a node 3b6442f8b2 feature #23947 [Translation] Adding the ability do load in xliff2.0 (Nyholm) b0cdb53d67 [Translation] Adding the ability do load in xliff2.0 --- src/Symfony/Component/Config/CHANGELOG.md | 5 +++ .../Component/Config/Definition/ArrayNode.php | 4 ++ .../Component/Config/Definition/BaseNode.php | 37 +++++++++++++++++++ .../Definition/Builder/NodeDefinition.php | 18 +++++++++ .../Builder/VariableNodeDefinition.php | 1 + .../Definition/Dumper/XmlReferenceDumper.php | 4 ++ .../Definition/Dumper/YamlReferenceDumper.php | 5 +++ .../Dumper/XmlReferenceDumperTest.php | 4 ++ .../Dumper/YamlReferenceDumperTest.php | 2 + .../Configuration/ExampleConfiguration.php | 2 + 10 files changed, 82 insertions(+) diff --git a/src/Symfony/Component/Config/CHANGELOG.md b/src/Symfony/Component/Config/CHANGELOG.md index 4ef4e625ba566..ffa347dbf4976 100644 --- a/src/Symfony/Component/Config/CHANGELOG.md +++ b/src/Symfony/Component/Config/CHANGELOG.md @@ -1,6 +1,11 @@ CHANGELOG ========= +3.4.0 +----- + + * added `setDeprecated()` method to indicate a deprecated node + 3.3.0 ----- diff --git a/src/Symfony/Component/Config/Definition/ArrayNode.php b/src/Symfony/Component/Config/Definition/ArrayNode.php index 457e7a8c92e34..2ffa2a2137fa8 100644 --- a/src/Symfony/Component/Config/Definition/ArrayNode.php +++ b/src/Symfony/Component/Config/Definition/ArrayNode.php @@ -234,6 +234,10 @@ protected function finalizeValue($value) } foreach ($this->children as $name => $child) { + if ($child->isDeprecated()) { + @trigger_error($child->getDeprecationMessage($name, $this->getPath()), E_USER_DEPRECATED); + } + if (!array_key_exists($name, $value)) { if ($child->isRequired()) { $msg = sprintf('The child node "%s" at path "%s" must be configured.', $name, $this->getPath()); diff --git a/src/Symfony/Component/Config/Definition/BaseNode.php b/src/Symfony/Component/Config/Definition/BaseNode.php index dbf36335b69e3..6e6ac1fdb47cf 100644 --- a/src/Symfony/Component/Config/Definition/BaseNode.php +++ b/src/Symfony/Component/Config/Definition/BaseNode.php @@ -29,6 +29,7 @@ abstract class BaseNode implements NodeInterface protected $finalValidationClosures = array(); protected $allowOverwrite = true; protected $required = false; + protected $deprecationMessage = null; protected $equivalentValues = array(); protected $attributes = array(); @@ -141,6 +142,19 @@ public function setRequired($boolean) $this->required = (bool) $boolean; } + /** + * Sets this node as deprecated. + * + * You can use %node% and %path% placeholders in your message to display, + * respectively, the node name and its complete path. + * + * @param string|null $message Deprecated message + */ + public function setDeprecated($message) + { + $this->deprecationMessage = $message; + } + /** * Sets if this node can be overridden. * @@ -181,6 +195,29 @@ public function isRequired() return $this->required; } + /** + * Checks if this node is deprecated. + * + * @return bool + */ + public function isDeprecated() + { + return null !== $this->deprecationMessage; + } + + /** + * Returns the deprecated message. + * + * @param string $node the configuration node name + * @param string $path the path of the node + * + * @return string + */ + public function getDeprecationMessage($node, $path) + { + return strtr($this->deprecationMessage, array('%node%' => $node, '%path%' => $path)); + } + /** * Returns the name of this node. * diff --git a/src/Symfony/Component/Config/Definition/Builder/NodeDefinition.php b/src/Symfony/Component/Config/Definition/Builder/NodeDefinition.php index 1b712a3150bc3..eb212caa44e00 100644 --- a/src/Symfony/Component/Config/Definition/Builder/NodeDefinition.php +++ b/src/Symfony/Component/Config/Definition/Builder/NodeDefinition.php @@ -27,6 +27,7 @@ abstract class NodeDefinition implements NodeParentInterface protected $defaultValue; protected $default = false; protected $required = false; + protected $deprecationMessage = null; protected $merge; protected $allowEmptyValue = true; protected $nullEquivalent; @@ -168,6 +169,23 @@ public function isRequired() return $this; } + /** + * Sets the node as deprecated. + * + * You can use %node% and %path% placeholders in your message to display, + * respectively, the node name and its complete path. + * + * @param string $message Deprecation message + * + * @return $this + */ + public function setDeprecated($message = 'The child node "%node%" at path "%path%" is deprecated.') + { + $this->deprecationMessage = $message; + + return $this; + } + /** * Sets the equivalent value used when the node contains null. * diff --git a/src/Symfony/Component/Config/Definition/Builder/VariableNodeDefinition.php b/src/Symfony/Component/Config/Definition/Builder/VariableNodeDefinition.php index a46b7ea61ded0..26565e1771d84 100644 --- a/src/Symfony/Component/Config/Definition/Builder/VariableNodeDefinition.php +++ b/src/Symfony/Component/Config/Definition/Builder/VariableNodeDefinition.php @@ -54,6 +54,7 @@ protected function createNode() $node->addEquivalentValue(true, $this->trueEquivalent); $node->addEquivalentValue(false, $this->falseEquivalent); $node->setRequired($this->required); + $node->setDeprecated($this->deprecationMessage); if (null !== $this->validation) { $node->setFinalValidationClosures($this->validation->rules); diff --git a/src/Symfony/Component/Config/Definition/Dumper/XmlReferenceDumper.php b/src/Symfony/Component/Config/Definition/Dumper/XmlReferenceDumper.php index ec5460f2f53c7..44cc9ea9ab79b 100644 --- a/src/Symfony/Component/Config/Definition/Dumper/XmlReferenceDumper.php +++ b/src/Symfony/Component/Config/Definition/Dumper/XmlReferenceDumper.php @@ -153,6 +153,10 @@ private function writeNode(NodeInterface $node, $depth = 0, $root = false, $name $comments[] = 'Required'; } + if ($child->isDeprecated()) { + $comments[] = sprintf('Deprecated (%s)', $child->getDeprecationMessage($child->getName(), $child->getPath())); + } + if ($child instanceof EnumNode) { $comments[] = 'One of '.implode('; ', array_map('json_encode', $child->getValues())); } diff --git a/src/Symfony/Component/Config/Definition/Dumper/YamlReferenceDumper.php b/src/Symfony/Component/Config/Definition/Dumper/YamlReferenceDumper.php index 16076354db515..a470e5f9fba67 100644 --- a/src/Symfony/Component/Config/Definition/Dumper/YamlReferenceDumper.php +++ b/src/Symfony/Component/Config/Definition/Dumper/YamlReferenceDumper.php @@ -123,6 +123,11 @@ private function writeNode(NodeInterface $node, $depth = 0, $prototypedArray = f $comments[] = 'Required'; } + // deprecated? + if ($node->isDeprecated()) { + $comments[] = sprintf('Deprecated (%s)', $node->getDeprecationMessage($node->getName(), $node->getPath())); + } + // example if ($example && !is_array($example)) { $comments[] = 'Example: '.$example; diff --git a/src/Symfony/Component/Config/Tests/Definition/Dumper/XmlReferenceDumperTest.php b/src/Symfony/Component/Config/Tests/Definition/Dumper/XmlReferenceDumperTest.php index fd5f9c8cde841..3123c9740a24c 100644 --- a/src/Symfony/Component/Config/Tests/Definition/Dumper/XmlReferenceDumperTest.php +++ b/src/Symfony/Component/Config/Tests/Definition/Dumper/XmlReferenceDumperTest.php @@ -38,6 +38,8 @@ private function getConfigurationAsString() return str_replace("\n", PHP_EOL, <<<'EOL' + + scalarNode('scalar_array_empty')->defaultValue(array())->end() ->scalarNode('scalar_array_defaults')->defaultValue(array('elem1', 'elem2'))->end() ->scalarNode('scalar_required')->isRequired()->end() + ->scalarNode('scalar_deprecated')->setDeprecated()->end() + ->scalarNode('scalar_deprecated_with_message')->setDeprecated('Deprecation custom message for "%node%" at "%path%"')->end() ->scalarNode('node_with_a_looong_name')->end() ->enumNode('enum_with_default')->values(array('this', 'that'))->defaultValue('this')->end() ->enumNode('enum')->values(array('this', 'that'))->end() From a00a4ffb04f3fb9c2fc158cb688de6eef3724340 Mon Sep 17 00:00:00 2001 From: Sanpi Date: Tue, 11 Apr 2017 21:49:38 +0200 Subject: [PATCH 0712/1099] [config] Add ability to deprecate a node --- src/Symfony/Component/Config/CHANGELOG.md | 5 +++ .../Component/Config/Definition/ArrayNode.php | 4 ++ .../Component/Config/Definition/BaseNode.php | 37 +++++++++++++++++++ .../Definition/Builder/NodeDefinition.php | 18 +++++++++ .../Builder/VariableNodeDefinition.php | 1 + .../Definition/Dumper/XmlReferenceDumper.php | 4 ++ .../Definition/Dumper/YamlReferenceDumper.php | 5 +++ .../Dumper/XmlReferenceDumperTest.php | 4 ++ .../Dumper/YamlReferenceDumperTest.php | 2 + .../Configuration/ExampleConfiguration.php | 2 + 10 files changed, 82 insertions(+) diff --git a/src/Symfony/Component/Config/CHANGELOG.md b/src/Symfony/Component/Config/CHANGELOG.md index 4ef4e625ba566..ffa347dbf4976 100644 --- a/src/Symfony/Component/Config/CHANGELOG.md +++ b/src/Symfony/Component/Config/CHANGELOG.md @@ -1,6 +1,11 @@ CHANGELOG ========= +3.4.0 +----- + + * added `setDeprecated()` method to indicate a deprecated node + 3.3.0 ----- diff --git a/src/Symfony/Component/Config/Definition/ArrayNode.php b/src/Symfony/Component/Config/Definition/ArrayNode.php index 457e7a8c92e34..2ffa2a2137fa8 100644 --- a/src/Symfony/Component/Config/Definition/ArrayNode.php +++ b/src/Symfony/Component/Config/Definition/ArrayNode.php @@ -234,6 +234,10 @@ protected function finalizeValue($value) } foreach ($this->children as $name => $child) { + if ($child->isDeprecated()) { + @trigger_error($child->getDeprecationMessage($name, $this->getPath()), E_USER_DEPRECATED); + } + if (!array_key_exists($name, $value)) { if ($child->isRequired()) { $msg = sprintf('The child node "%s" at path "%s" must be configured.', $name, $this->getPath()); diff --git a/src/Symfony/Component/Config/Definition/BaseNode.php b/src/Symfony/Component/Config/Definition/BaseNode.php index dbf36335b69e3..6e6ac1fdb47cf 100644 --- a/src/Symfony/Component/Config/Definition/BaseNode.php +++ b/src/Symfony/Component/Config/Definition/BaseNode.php @@ -29,6 +29,7 @@ abstract class BaseNode implements NodeInterface protected $finalValidationClosures = array(); protected $allowOverwrite = true; protected $required = false; + protected $deprecationMessage = null; protected $equivalentValues = array(); protected $attributes = array(); @@ -141,6 +142,19 @@ public function setRequired($boolean) $this->required = (bool) $boolean; } + /** + * Sets this node as deprecated. + * + * You can use %node% and %path% placeholders in your message to display, + * respectively, the node name and its complete path. + * + * @param string|null $message Deprecated message + */ + public function setDeprecated($message) + { + $this->deprecationMessage = $message; + } + /** * Sets if this node can be overridden. * @@ -181,6 +195,29 @@ public function isRequired() return $this->required; } + /** + * Checks if this node is deprecated. + * + * @return bool + */ + public function isDeprecated() + { + return null !== $this->deprecationMessage; + } + + /** + * Returns the deprecated message. + * + * @param string $node the configuration node name + * @param string $path the path of the node + * + * @return string + */ + public function getDeprecationMessage($node, $path) + { + return strtr($this->deprecationMessage, array('%node%' => $node, '%path%' => $path)); + } + /** * Returns the name of this node. * diff --git a/src/Symfony/Component/Config/Definition/Builder/NodeDefinition.php b/src/Symfony/Component/Config/Definition/Builder/NodeDefinition.php index 1b712a3150bc3..eb212caa44e00 100644 --- a/src/Symfony/Component/Config/Definition/Builder/NodeDefinition.php +++ b/src/Symfony/Component/Config/Definition/Builder/NodeDefinition.php @@ -27,6 +27,7 @@ abstract class NodeDefinition implements NodeParentInterface protected $defaultValue; protected $default = false; protected $required = false; + protected $deprecationMessage = null; protected $merge; protected $allowEmptyValue = true; protected $nullEquivalent; @@ -168,6 +169,23 @@ public function isRequired() return $this; } + /** + * Sets the node as deprecated. + * + * You can use %node% and %path% placeholders in your message to display, + * respectively, the node name and its complete path. + * + * @param string $message Deprecation message + * + * @return $this + */ + public function setDeprecated($message = 'The child node "%node%" at path "%path%" is deprecated.') + { + $this->deprecationMessage = $message; + + return $this; + } + /** * Sets the equivalent value used when the node contains null. * diff --git a/src/Symfony/Component/Config/Definition/Builder/VariableNodeDefinition.php b/src/Symfony/Component/Config/Definition/Builder/VariableNodeDefinition.php index a46b7ea61ded0..26565e1771d84 100644 --- a/src/Symfony/Component/Config/Definition/Builder/VariableNodeDefinition.php +++ b/src/Symfony/Component/Config/Definition/Builder/VariableNodeDefinition.php @@ -54,6 +54,7 @@ protected function createNode() $node->addEquivalentValue(true, $this->trueEquivalent); $node->addEquivalentValue(false, $this->falseEquivalent); $node->setRequired($this->required); + $node->setDeprecated($this->deprecationMessage); if (null !== $this->validation) { $node->setFinalValidationClosures($this->validation->rules); diff --git a/src/Symfony/Component/Config/Definition/Dumper/XmlReferenceDumper.php b/src/Symfony/Component/Config/Definition/Dumper/XmlReferenceDumper.php index ec5460f2f53c7..44cc9ea9ab79b 100644 --- a/src/Symfony/Component/Config/Definition/Dumper/XmlReferenceDumper.php +++ b/src/Symfony/Component/Config/Definition/Dumper/XmlReferenceDumper.php @@ -153,6 +153,10 @@ private function writeNode(NodeInterface $node, $depth = 0, $root = false, $name $comments[] = 'Required'; } + if ($child->isDeprecated()) { + $comments[] = sprintf('Deprecated (%s)', $child->getDeprecationMessage($child->getName(), $child->getPath())); + } + if ($child instanceof EnumNode) { $comments[] = 'One of '.implode('; ', array_map('json_encode', $child->getValues())); } diff --git a/src/Symfony/Component/Config/Definition/Dumper/YamlReferenceDumper.php b/src/Symfony/Component/Config/Definition/Dumper/YamlReferenceDumper.php index 16076354db515..a470e5f9fba67 100644 --- a/src/Symfony/Component/Config/Definition/Dumper/YamlReferenceDumper.php +++ b/src/Symfony/Component/Config/Definition/Dumper/YamlReferenceDumper.php @@ -123,6 +123,11 @@ private function writeNode(NodeInterface $node, $depth = 0, $prototypedArray = f $comments[] = 'Required'; } + // deprecated? + if ($node->isDeprecated()) { + $comments[] = sprintf('Deprecated (%s)', $node->getDeprecationMessage($node->getName(), $node->getPath())); + } + // example if ($example && !is_array($example)) { $comments[] = 'Example: '.$example; diff --git a/src/Symfony/Component/Config/Tests/Definition/Dumper/XmlReferenceDumperTest.php b/src/Symfony/Component/Config/Tests/Definition/Dumper/XmlReferenceDumperTest.php index fd5f9c8cde841..3123c9740a24c 100644 --- a/src/Symfony/Component/Config/Tests/Definition/Dumper/XmlReferenceDumperTest.php +++ b/src/Symfony/Component/Config/Tests/Definition/Dumper/XmlReferenceDumperTest.php @@ -38,6 +38,8 @@ private function getConfigurationAsString() return str_replace("\n", PHP_EOL, <<<'EOL' + + scalarNode('scalar_array_empty')->defaultValue(array())->end() ->scalarNode('scalar_array_defaults')->defaultValue(array('elem1', 'elem2'))->end() ->scalarNode('scalar_required')->isRequired()->end() + ->scalarNode('scalar_deprecated')->setDeprecated()->end() + ->scalarNode('scalar_deprecated_with_message')->setDeprecated('Deprecation custom message for "%node%" at "%path%"')->end() ->scalarNode('node_with_a_looong_name')->end() ->enumNode('enum_with_default')->values(array('this', 'that'))->defaultValue('this')->end() ->enumNode('enum')->values(array('this', 'that'))->end() From d00ac8adef7939f8f6428bb54ffd745bc9fb01f0 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Tue, 29 Aug 2017 18:16:36 +0200 Subject: [PATCH 0713/1099] [VarDumper] fix DateCasterTest --- src/Symfony/Component/VarDumper/Tests/Caster/DateCasterTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/VarDumper/Tests/Caster/DateCasterTest.php b/src/Symfony/Component/VarDumper/Tests/Caster/DateCasterTest.php index 55d84a1add008..84240479f83b0 100644 --- a/src/Symfony/Component/VarDumper/Tests/Caster/DateCasterTest.php +++ b/src/Symfony/Component/VarDumper/Tests/Caster/DateCasterTest.php @@ -314,7 +314,7 @@ public function provideTimeZones() */ public function testDumpPeriod($start, $interval, $end, $options, $expected) { - if (defined('HHVM_VERSION_ID') || \PHP_VERSION_ID < 50605) { + if (defined('HHVM_VERSION_ID') || \PHP_VERSION_ID < 50620 || (\PHP_VERSION_ID >= 70000 && \PHP_VERSION_ID < 70005)) { $this->markTestSkipped(); } From 4f040d78fe17be03100c86ad032d2bbdafae3abe Mon Sep 17 00:00:00 2001 From: Yonel Ceruto Date: Thu, 27 Jul 2017 09:45:21 -0400 Subject: [PATCH 0714/1099] Add debug:form command --- .../FrameworkExtension.php | 2 + .../Resources/config/console.xml | 6 + .../Bundle/FrameworkBundle/composer.json | 2 +- .../Component/Form/Command/DebugCommand.php | 96 ++++++++++++++ .../Form/Console/Descriptor/Descriptor.php | 122 ++++++++++++++++++ .../Console/Descriptor/JsonDescriptor.php | 68 ++++++++++ .../Console/Descriptor/TextDescriptor.php | 108 ++++++++++++++++ .../Form/Console/Helper/DescriptorHelper.php | 32 +++++ .../Form/DependencyInjection/FormPass.php | 14 +- .../Form/Tests/Command/DebugCommandTest.php | 76 +++++++++++ .../Descriptor/AbstractDescriptorTest.php | 73 +++++++++++ .../Console/Descriptor/JsonDescriptorTest.php | 37 ++++++ .../Console/Descriptor/TextDescriptorTest.php | 37 ++++++ .../DependencyInjection/FormPassTest.php | 45 +++++++ .../Descriptor/resolved_form_type_1.json | 68 ++++++++++ .../Descriptor/resolved_form_type_1.txt | 40 ++++++ .../Form/Util/OptionsResolverWrapper.php | 91 +++++++++++++ src/Symfony/Component/Form/composer.json | 5 +- 18 files changed, 917 insertions(+), 5 deletions(-) create mode 100644 src/Symfony/Component/Form/Command/DebugCommand.php create mode 100644 src/Symfony/Component/Form/Console/Descriptor/Descriptor.php create mode 100644 src/Symfony/Component/Form/Console/Descriptor/JsonDescriptor.php create mode 100644 src/Symfony/Component/Form/Console/Descriptor/TextDescriptor.php create mode 100644 src/Symfony/Component/Form/Console/Helper/DescriptorHelper.php create mode 100644 src/Symfony/Component/Form/Tests/Command/DebugCommandTest.php create mode 100644 src/Symfony/Component/Form/Tests/Console/Descriptor/AbstractDescriptorTest.php create mode 100644 src/Symfony/Component/Form/Tests/Console/Descriptor/JsonDescriptorTest.php create mode 100644 src/Symfony/Component/Form/Tests/Console/Descriptor/TextDescriptorTest.php create mode 100644 src/Symfony/Component/Form/Tests/Fixtures/Descriptor/resolved_form_type_1.json create mode 100644 src/Symfony/Component/Form/Tests/Fixtures/Descriptor/resolved_form_type_1.txt create mode 100644 src/Symfony/Component/Form/Util/OptionsResolverWrapper.php diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php index b386d4c844932..f54b74abb6051 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php @@ -220,6 +220,8 @@ public function load(array $configs, ContainerBuilder $container) if (!class_exists('Symfony\Component\Validator\Validation')) { throw new LogicException('The Validator component is required to use the Form component.'); } + } else { + $container->removeDefinition('Symfony\Component\Form\Command\DebugCommand'); } $this->registerSecurityCsrfConfiguration($config['csrf_protection'], $container, $loader); diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/console.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/console.xml index 4bdaa85fee4c3..80bc32d3ff221 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/console.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/console.xml @@ -96,5 +96,11 @@ + + + + + + diff --git a/src/Symfony/Bundle/FrameworkBundle/composer.json b/src/Symfony/Bundle/FrameworkBundle/composer.json index 7ef0dc842b405..d70292ff7bf6f 100644 --- a/src/Symfony/Bundle/FrameworkBundle/composer.json +++ b/src/Symfony/Bundle/FrameworkBundle/composer.json @@ -40,7 +40,7 @@ "symfony/dom-crawler": "~2.8|~3.0|~4.0", "symfony/polyfill-intl-icu": "~1.0", "symfony/security": "~2.8|~3.0|~4.0", - "symfony/form": "~3.3|~4.0", + "symfony/form": "~3.4|~4.0", "symfony/expression-language": "~2.8|~3.0|~4.0", "symfony/process": "~2.8|~3.0|~4.0", "symfony/security-core": "~3.2|~4.0", diff --git a/src/Symfony/Component/Form/Command/DebugCommand.php b/src/Symfony/Component/Form/Command/DebugCommand.php new file mode 100644 index 0000000000000..3cb4904ab3a7d --- /dev/null +++ b/src/Symfony/Component/Form/Command/DebugCommand.php @@ -0,0 +1,96 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Command; + +use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Style\SymfonyStyle; +use Symfony\Component\Form\Console\Helper\DescriptorHelper; +use Symfony\Component\Form\FormRegistryInterface; + +/** + * A console command for retrieving information about form types. + * + * @author Yonel Ceruto + */ +class DebugCommand extends Command +{ + protected static $defaultName = 'debug:form'; + + private $formRegistry; + private $namespaces; + + public function __construct(FormRegistryInterface $formRegistry, array $namespaces = array('Symfony\Component\Form\Extension\Core\Type')) + { + parent::__construct(); + + $this->formRegistry = $formRegistry; + $this->namespaces = $namespaces; + } + + /** + * {@inheritdoc} + */ + protected function configure() + { + $this + ->setDefinition(array( + new InputArgument('class', InputArgument::REQUIRED, 'The form type class'), + new InputOption('format', null, InputOption::VALUE_REQUIRED, 'The output format (txt or json)', 'txt'), + )) + ->setDescription('Displays form type information') + ; + } + + /** + * {@inheritdoc} + */ + protected function execute(InputInterface $input, OutputInterface $output) + { + $io = new SymfonyStyle($input, $output); + + if (!class_exists($class = $input->getArgument('class'))) { + $class = $this->getFqcnTypeClass($input, $io, $class); + } + + $object = $this->formRegistry->getType($class); + + $helper = new DescriptorHelper(); + $options['format'] = $input->getOption('format'); + $helper->describe($io, $object, $options); + } + + private function getFqcnTypeClass(InputInterface $input, SymfonyStyle $io, $shortClassName) + { + $classes = array(); + foreach ($this->namespaces as $namespace) { + if (class_exists($fqcn = $namespace.'\\'.$shortClassName)) { + $classes[] = $fqcn; + } + } + + if (0 === $count = count($classes)) { + throw new \InvalidArgumentException(sprintf("Could not find type \"%s\" into the following namespaces:\n %s", $shortClassName, implode("\n ", $this->namespaces))); + } + if (1 === $count) { + return $classes[0]; + } + if (!$input->isInteractive()) { + throw new \InvalidArgumentException(sprintf("The type \"%s\" is ambiguous.\nDid you mean one of these?\n %s", $shortClassName, implode("\n ", $classes))); + } + + return $io->choice(sprintf("The type \"%s\" is ambiguous.\n\n Select one of the following form types to display its information:", $shortClassName), $classes, $classes[0]); + } +} diff --git a/src/Symfony/Component/Form/Console/Descriptor/Descriptor.php b/src/Symfony/Component/Form/Console/Descriptor/Descriptor.php new file mode 100644 index 0000000000000..af77f19931244 --- /dev/null +++ b/src/Symfony/Component/Form/Console/Descriptor/Descriptor.php @@ -0,0 +1,122 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Console\Descriptor; + +use Symfony\Component\Console\Descriptor\DescriptorInterface; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Style\SymfonyStyle; +use Symfony\Component\Form\ResolvedFormTypeInterface; +use Symfony\Component\Form\Util\OptionsResolverWrapper; +use Symfony\Component\OptionsResolver\OptionsResolver; + +/** + * @author Yonel Ceruto + * + * @internal + */ +abstract class Descriptor implements DescriptorInterface +{ + /** + * @var SymfonyStyle + */ + protected $output; + protected $type; + protected $ownOptions = array(); + protected $overriddenOptions = array(); + protected $parentOptions = array(); + protected $extensionOptions = array(); + protected $requiredOptions = array(); + protected $parents = array(); + protected $extensions = array(); + + /** + * {@inheritdoc} + */ + public function describe(OutputInterface $output, $object, array $options = array()) + { + $this->output = $output; + + switch (true) { + case $object instanceof ResolvedFormTypeInterface: + $this->describeResolvedFormType($object, $options); + break; + default: + throw new \InvalidArgumentException(sprintf('Object of type "%s" is not describable.', get_class($object))); + } + } + + abstract protected function describeResolvedFormType(ResolvedFormTypeInterface $resolvedFormType, array $options = array()); + + protected function collectOptions(ResolvedFormTypeInterface $type) + { + $this->parents = array(); + $this->extensions = array(); + + if (null !== $type->getParent()) { + $optionsResolver = clone $this->getParentOptionsResolver($type->getParent()); + } else { + $optionsResolver = new OptionsResolver(); + } + + $type->getInnerType()->configureOptions($ownOptionsResolver = new OptionsResolverWrapper()); + $this->ownOptions = array_diff($ownOptionsResolver->getDefinedOptions(), $optionsResolver->getDefinedOptions()); + $overriddenOptions = array_intersect(array_merge($ownOptionsResolver->getDefinedOptions(), $ownOptionsResolver->getUndefinedOptions()), $optionsResolver->getDefinedOptions()); + + $this->parentOptions = array(); + foreach ($this->parents as $class => $parentOptions) { + $this->overriddenOptions[$class] = array_intersect($overriddenOptions, $parentOptions); + $this->parentOptions[$class] = array_diff($parentOptions, $overriddenOptions); + } + + $type->getInnerType()->configureOptions($optionsResolver); + $this->collectTypeExtensionsOptions($type, $optionsResolver); + $this->extensionOptions = array(); + foreach ($this->extensions as $class => $extensionOptions) { + $this->overriddenOptions[$class] = array_intersect($overriddenOptions, $extensionOptions); + $this->extensionOptions[$class] = array_diff($extensionOptions, $overriddenOptions); + } + + $this->overriddenOptions = array_filter($this->overriddenOptions); + $this->requiredOptions = $optionsResolver->getRequiredOptions(); + + $this->parents = array_keys($this->parents); + $this->extensions = array_keys($this->extensions); + } + + private function getParentOptionsResolver(ResolvedFormTypeInterface $type) + { + $this->parents[$class = get_class($type->getInnerType())] = array(); + + if (null !== $type->getParent()) { + $optionsResolver = clone $this->getParentOptionsResolver($type->getParent()); + } else { + $optionsResolver = new OptionsResolver(); + } + + $inheritedOptions = $optionsResolver->getDefinedOptions(); + $type->getInnerType()->configureOptions($optionsResolver); + $this->parents[$class] = array_diff($optionsResolver->getDefinedOptions(), $inheritedOptions); + + $this->collectTypeExtensionsOptions($type, $optionsResolver); + + return $optionsResolver; + } + + private function collectTypeExtensionsOptions(ResolvedFormTypeInterface $type, OptionsResolver $optionsResolver) + { + foreach ($type->getTypeExtensions() as $extension) { + $inheritedOptions = $optionsResolver->getDefinedOptions(); + $extension->configureOptions($optionsResolver); + $this->extensions[get_class($extension)] = array_diff($optionsResolver->getDefinedOptions(), $inheritedOptions); + } + } +} diff --git a/src/Symfony/Component/Form/Console/Descriptor/JsonDescriptor.php b/src/Symfony/Component/Form/Console/Descriptor/JsonDescriptor.php new file mode 100644 index 0000000000000..638ea7a5ff71e --- /dev/null +++ b/src/Symfony/Component/Form/Console/Descriptor/JsonDescriptor.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\Component\Form\Console\Descriptor; + +use Symfony\Component\Form\ResolvedFormTypeInterface; + +/** + * @author Yonel Ceruto + * + * @internal + */ +class JsonDescriptor extends Descriptor +{ + protected function describeResolvedFormType(ResolvedFormTypeInterface $resolvedFormType, array $options = array()) + { + $this->collectOptions($resolvedFormType); + + $formOptions = array( + 'own' => $this->ownOptions, + 'overridden' => $this->overriddenOptions, + 'parent' => $this->parentOptions, + 'extension' => $this->extensionOptions, + 'required' => $this->requiredOptions, + ); + $this->sortOptions($formOptions); + + $data = array( + 'class' => get_class($resolvedFormType->getInnerType()), + 'block_prefix' => $resolvedFormType->getInnerType()->getBlockPrefix(), + 'options' => $formOptions, + 'parent_types' => $this->parents, + 'type_extensions' => $this->extensions, + ); + + $this->writeData($data, $options); + } + + private function writeData(array $data, array $options) + { + $flags = isset($options['json_encoding']) ? $options['json_encoding'] : 0; + $this->output->write(json_encode($data, $flags | JSON_PRETTY_PRINT)."\n"); + } + + private function sortOptions(array &$options) + { + foreach ($options as &$opts) { + $sorted = false; + foreach ($opts as &$opt) { + if (is_array($opt)) { + sort($opt); + $sorted = true; + } + } + if (!$sorted) { + sort($opts); + } + } + } +} diff --git a/src/Symfony/Component/Form/Console/Descriptor/TextDescriptor.php b/src/Symfony/Component/Form/Console/Descriptor/TextDescriptor.php new file mode 100644 index 0000000000000..b12a22bb9e26a --- /dev/null +++ b/src/Symfony/Component/Form/Console/Descriptor/TextDescriptor.php @@ -0,0 +1,108 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Console\Descriptor; + +use Symfony\Component\Console\Helper\TableSeparator; +use Symfony\Component\Form\ResolvedFormTypeInterface; + +/** + * @author Yonel Ceruto + * + * @internal + */ +class TextDescriptor extends Descriptor +{ + protected function describeResolvedFormType(ResolvedFormTypeInterface $resolvedFormType, array $options = array()) + { + $this->collectOptions($resolvedFormType); + + $formOptions = $this->normalizeAndSortOptionsColumns(array_filter(array( + 'own' => $this->ownOptions, + 'overridden' => $this->overriddenOptions, + 'parent' => $this->parentOptions, + 'extension' => $this->extensionOptions, + ))); + + // setting headers and column order + $tableHeaders = array_intersect_key(array( + 'own' => 'Options', + 'overridden' => 'Overridden options', + 'parent' => 'Parent options', + 'extension' => 'Extension options', + ), $formOptions); + + $tableRows = array(); + $count = count(max($formOptions)); + for ($i = 0; $i < $count; ++$i) { + $cells = array(); + foreach (array_keys($tableHeaders) as $group) { + if (isset($formOptions[$group][$i])) { + $option = $formOptions[$group][$i]; + + if (is_string($option) && in_array($option, $this->requiredOptions)) { + $option .= ' (required)'; + } + + $cells[] = $option; + } else { + $cells[] = null; + } + } + $tableRows[] = $cells; + } + + $this->output->title(sprintf('%s (Block prefix: "%s")', get_class($resolvedFormType->getInnerType()), $resolvedFormType->getInnerType()->getBlockPrefix())); + $this->output->table($tableHeaders, $tableRows); + + if ($this->parents) { + $this->output->section('Parent types'); + $this->output->listing($this->parents); + } + + if ($this->extensions) { + $this->output->section('Type extensions'); + $this->output->listing($this->extensions); + } + } + + private function normalizeAndSortOptionsColumns(array $options) + { + foreach ($options as $group => &$opts) { + $sorted = false; + foreach ($opts as $class => $opt) { + if (!is_array($opt) || 0 === count($opt)) { + continue; + } + + unset($opts[$class]); + + if (!$sorted) { + $opts = array(); + } else { + $opts[] = null; + } + $opts[] = sprintf('%s', (new \ReflectionClass($class))->getShortName()); + $opts[] = new TableSeparator(); + + sort($opt); + $sorted = true; + $opts = array_merge($opts, $opt); + } + + if (!$sorted) { + sort($opts); + } + } + + return $options; + } +} diff --git a/src/Symfony/Component/Form/Console/Helper/DescriptorHelper.php b/src/Symfony/Component/Form/Console/Helper/DescriptorHelper.php new file mode 100644 index 0000000000000..e850324c01712 --- /dev/null +++ b/src/Symfony/Component/Form/Console/Helper/DescriptorHelper.php @@ -0,0 +1,32 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Console\Helper; + +use Symfony\Component\Console\Helper\DescriptorHelper as BaseDescriptorHelper; +use Symfony\Component\Form\Console\Descriptor\JsonDescriptor; +use Symfony\Component\Form\Console\Descriptor\TextDescriptor; + +/** + * @author Yonel Ceruto + * + * @internal + */ +class DescriptorHelper extends BaseDescriptorHelper +{ + public function __construct() + { + $this + ->register('txt', new TextDescriptor()) + ->register('json', new JsonDescriptor()) + ; + } +} diff --git a/src/Symfony/Component/Form/DependencyInjection/FormPass.php b/src/Symfony/Component/Form/DependencyInjection/FormPass.php index 88574558b7b7a..ff1ac8af60658 100644 --- a/src/Symfony/Component/Form/DependencyInjection/FormPass.php +++ b/src/Symfony/Component/Form/DependencyInjection/FormPass.php @@ -18,6 +18,7 @@ use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; use Symfony\Component\DependencyInjection\Reference; +use Symfony\Component\Form\Command\DebugCommand; /** * Adds all services with the tags "form.type", "form.type_extension" and @@ -33,13 +34,15 @@ class FormPass implements CompilerPassInterface private $formTypeTag; private $formTypeExtensionTag; private $formTypeGuesserTag; + private $formDebugCommandService; - public function __construct($formExtensionService = 'form.extension', $formTypeTag = 'form.type', $formTypeExtensionTag = 'form.type_extension', $formTypeGuesserTag = 'form.type_guesser') + public function __construct($formExtensionService = 'form.extension', $formTypeTag = 'form.type', $formTypeExtensionTag = 'form.type_extension', $formTypeGuesserTag = 'form.type_guesser', $formDebugCommandService = DebugCommand::class) { $this->formExtensionService = $formExtensionService; $this->formTypeTag = $formTypeTag; $this->formTypeExtensionTag = $formTypeExtensionTag; $this->formTypeGuesserTag = $formTypeGuesserTag; + $this->formDebugCommandService = $formDebugCommandService; } public function process(ContainerBuilder $container) @@ -61,12 +64,19 @@ private function processFormTypes(ContainerBuilder $container) { // Get service locator argument $servicesMap = array(); + $namespaces = array('Symfony\Component\Form\Extension\Core\Type' => true); // Builds an array with fully-qualified type class names as keys and service IDs as values foreach ($container->findTaggedServiceIds($this->formTypeTag, true) as $serviceId => $tag) { // Add form type service to the service locator $serviceDefinition = $container->getDefinition($serviceId); - $servicesMap[$serviceDefinition->getClass()] = new Reference($serviceId); + $servicesMap[$formType = $serviceDefinition->getClass()] = new Reference($serviceId); + $namespaces[substr($formType, 0, strrpos($formType, '\\'))] = true; + } + + if ($container->hasDefinition($this->formDebugCommandService)) { + $commandDefinition = $container->getDefinition($this->formDebugCommandService); + $commandDefinition->setArgument(1, array_keys($namespaces)); } return ServiceLocatorTagPass::register($container, $servicesMap); diff --git a/src/Symfony/Component/Form/Tests/Command/DebugCommandTest.php b/src/Symfony/Component/Form/Tests/Command/DebugCommandTest.php new file mode 100644 index 0000000000000..c2083ea12ce4d --- /dev/null +++ b/src/Symfony/Component/Form/Tests/Command/DebugCommandTest.php @@ -0,0 +1,76 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Tests\Command; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\Console\Application; +use Symfony\Component\Console\Tester\CommandTester; +use Symfony\Component\Form\Command\DebugCommand; +use Symfony\Component\Form\Extension\Core\Type\FormType; +use Symfony\Component\Form\FormRegistryInterface; +use Symfony\Component\Form\ResolvedFormTypeInterface; + +class DebugCommandTest extends TestCase +{ + public function testDebugSingleFormType() + { + $tester = $this->createCommandTester(); + $ret = $tester->execute(array('class' => 'FormType'), array('decorated' => false)); + + $this->assertEquals(0, $ret, 'Returns 0 in case of success'); + $this->assertContains('Symfony\Component\Form\Extension\Core\Type\FormType (Block prefix: "form")', $tester->getDisplay()); + } + + /** + * @expectedException \InvalidArgumentException + */ + public function testDebugInvalidFormType() + { + $this->createCommandTester()->execute(array('class' => 'test')); + } + + /** + * @return CommandTester + */ + private function createCommandTester() + { + $resolvedFormType = $this->getMockBuilder(ResolvedFormTypeInterface::class)->getMock(); + $resolvedFormType + ->expects($this->any()) + ->method('getParent') + ->willReturn(null) + ; + $resolvedFormType + ->expects($this->any()) + ->method('getInnerType') + ->willReturn(new FormType()) + ; + $resolvedFormType + ->expects($this->any()) + ->method('getTypeExtensions') + ->willReturn(array()) + ; + + $formRegistry = $this->getMockBuilder(FormRegistryInterface::class)->getMock(); + $formRegistry + ->expects($this->any()) + ->method('getType') + ->will($this->returnValue($resolvedFormType)) + ; + + $command = new DebugCommand($formRegistry); + $application = new Application(); + $application->add($command); + + return new CommandTester($application->find('debug:form')); + } +} diff --git a/src/Symfony/Component/Form/Tests/Console/Descriptor/AbstractDescriptorTest.php b/src/Symfony/Component/Form/Tests/Console/Descriptor/AbstractDescriptorTest.php new file mode 100644 index 0000000000000..c760e5ecf972c --- /dev/null +++ b/src/Symfony/Component/Form/Tests/Console/Descriptor/AbstractDescriptorTest.php @@ -0,0 +1,73 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Tests\Console\Descriptor; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\Console\Input\ArrayInput; +use Symfony\Component\Console\Output\BufferedOutput; +use Symfony\Component\Console\Style\SymfonyStyle; +use Symfony\Component\Form\Extension\Core\Type\ChoiceType; +use Symfony\Component\Form\Extension\Core\Type\FormType; +use Symfony\Component\Form\Extension\Csrf\Type\FormTypeCsrfExtension; +use Symfony\Component\Form\ResolvedFormType; +use Symfony\Component\Form\ResolvedFormTypeInterface; +use Symfony\Component\Security\Csrf\CsrfTokenManager; + +abstract class AbstractDescriptorTest extends TestCase +{ + /** @dataProvider getDescribeResolvedFormTypeTestData */ + public function testDescribeResolvedFormType(ResolvedFormTypeInterface $type, array $options, $fixtureName) + { + $expectedDescription = $this->getExpectedDescription($fixtureName); + $describedObject = $this->getObjectDescription($type, $options); + + if ('json' === $this->getFormat()) { + $this->assertEquals(json_encode(json_decode($expectedDescription), JSON_PRETTY_PRINT), json_encode(json_decode($describedObject), JSON_PRETTY_PRINT)); + } else { + $this->assertEquals(trim($expectedDescription), trim(str_replace(PHP_EOL, "\n", $describedObject))); + } + } + + public function getDescribeResolvedFormTypeTestData() + { + $typeExtensions = array( + new FormTypeCsrfExtension(new CsrfTokenManager()), + ); + $parent = new ResolvedFormType(new FormType(), $typeExtensions); + + yield array(new ResolvedFormType(new ChoiceType(), array(), $parent), array(), 'resolved_form_type_1'); + } + + abstract protected function getDescriptor(); + + abstract protected function getFormat(); + + private function getObjectDescription($object, array $options = array()) + { + $output = new BufferedOutput(BufferedOutput::VERBOSITY_NORMAL, true); + $io = new SymfonyStyle(new ArrayInput(array()), $output); + + $this->getDescriptor()->describe($io, $object, $options); + + return $output->fetch(); + } + + private function getExpectedDescription($name) + { + return file_get_contents($this->getFixtureFilename($name)); + } + + private function getFixtureFilename($name) + { + return sprintf('%s/../../Fixtures/Descriptor/%s.%s', __DIR__, $name, $this->getFormat()); + } +} diff --git a/src/Symfony/Component/Form/Tests/Console/Descriptor/JsonDescriptorTest.php b/src/Symfony/Component/Form/Tests/Console/Descriptor/JsonDescriptorTest.php new file mode 100644 index 0000000000000..fb339f6b475ed --- /dev/null +++ b/src/Symfony/Component/Form/Tests/Console/Descriptor/JsonDescriptorTest.php @@ -0,0 +1,37 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Tests\Console\Descriptor; + +use Symfony\Component\Form\Console\Descriptor\JsonDescriptor; + +class JsonDescriptorTest extends AbstractDescriptorTest +{ + protected function setUp() + { + putenv('COLUMNS=121'); + } + + protected function tearDown() + { + putenv('COLUMNS'); + } + + protected function getDescriptor() + { + return new JsonDescriptor(); + } + + protected function getFormat() + { + return 'json'; + } +} diff --git a/src/Symfony/Component/Form/Tests/Console/Descriptor/TextDescriptorTest.php b/src/Symfony/Component/Form/Tests/Console/Descriptor/TextDescriptorTest.php new file mode 100644 index 0000000000000..053f7e4512341 --- /dev/null +++ b/src/Symfony/Component/Form/Tests/Console/Descriptor/TextDescriptorTest.php @@ -0,0 +1,37 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Tests\Console\Descriptor; + +use Symfony\Component\Form\Console\Descriptor\TextDescriptor; + +class TextDescriptorTest extends AbstractDescriptorTest +{ + protected function setUp() + { + putenv('COLUMNS=121'); + } + + protected function tearDown() + { + putenv('COLUMNS'); + } + + protected function getDescriptor() + { + return new TextDescriptor(); + } + + protected function getFormat() + { + return 'txt'; + } +} diff --git a/src/Symfony/Component/Form/Tests/DependencyInjection/FormPassTest.php b/src/Symfony/Component/Form/Tests/DependencyInjection/FormPassTest.php index acfed570bce9f..4e9971ea8ccf3 100644 --- a/src/Symfony/Component/Form/Tests/DependencyInjection/FormPassTest.php +++ b/src/Symfony/Component/Form/Tests/DependencyInjection/FormPassTest.php @@ -14,12 +14,14 @@ use PHPUnit\Framework\TestCase; use Symfony\Component\DependencyInjection\Argument\IteratorArgument; use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument; +use Symfony\Component\Form\Command\DebugCommand; use Symfony\Component\Form\DependencyInjection\FormPass; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\DependencyInjection\ServiceLocator; use Symfony\Component\Form\AbstractType; +use Symfony\Component\Form\FormRegistryInterface; /** * @author Bernhard Schussek @@ -35,6 +37,15 @@ public function testDoNothingIfFormExtensionNotLoaded() $this->assertFalse($container->hasDefinition('form.extension')); } + public function testDoNothingIfDebugCommandNotLoaded() + { + $container = $this->createContainerBuilder(); + + $container->compile(); + + $this->assertFalse($container->hasDefinition(DebugCommand::class)); + } + public function testAddTaggedTypes() { $container = $this->createContainerBuilder(); @@ -56,6 +67,28 @@ public function testAddTaggedTypes() ); } + public function testAddTaggedTypesToDebugCommand() + { + $container = $this->createContainerBuilder(); + + $container->setDefinition('form.extension', $this->createExtensionDefinition()); + $container->setDefinition(DebugCommand::class, $this->createDebugCommandDefinition()); + $container->register('my.type1', __CLASS__.'_Type1')->addTag('form.type'); + $container->register('my.type2', __CLASS__.'_Type2')->addTag('form.type'); + + $container->compile(); + + $cmdDefinition = $container->getDefinition(DebugCommand::class); + + $this->assertEquals( + array( + 'Symfony\Component\Form\Extension\Core\Type', + __NAMESPACE__, + ), + $cmdDefinition->getArgument(1) + ); + } + /** * @dataProvider addTaggedTypeExtensionsDataProvider */ @@ -225,6 +258,18 @@ private function createExtensionDefinition() return $definition; } + private function createDebugCommandDefinition() + { + $definition = new Definition('Symfony\Component\Form\Command\DebugCommand'); + $definition->setArguments(array( + $formRegistry = $this->getMockBuilder(FormRegistryInterface::class)->getMock(), + array(), + array('Symfony\Component\Form\Extension\Core\Type'), + )); + + return $definition; + } + private function createContainerBuilder() { $container = new ContainerBuilder(); diff --git a/src/Symfony/Component/Form/Tests/Fixtures/Descriptor/resolved_form_type_1.json b/src/Symfony/Component/Form/Tests/Fixtures/Descriptor/resolved_form_type_1.json new file mode 100644 index 0000000000000..b0c083b5b71dc --- /dev/null +++ b/src/Symfony/Component/Form/Tests/Fixtures/Descriptor/resolved_form_type_1.json @@ -0,0 +1,68 @@ +{ + "class": "Symfony\\Component\\Form\\Extension\\Core\\Type\\ChoiceType", + "block_prefix": "choice", + "options": { + "own": [ + "choice_attr", + "choice_label", + "choice_loader", + "choice_name", + "choice_translation_domain", + "choice_value", + "choices", + "choices_as_values", + "expanded", + "group_by", + "multiple", + "placeholder", + "preferred_choices" + ], + "overridden": { + "Symfony\\Component\\Form\\Extension\\Core\\Type\\FormType": [ + "compound", + "data_class", + "empty_data", + "error_bubbling" + ] + }, + "parent": { + "Symfony\\Component\\Form\\Extension\\Core\\Type\\FormType": [ + "action", + "attr", + "auto_initialize", + "block_name", + "by_reference", + "data", + "disabled", + "inherit_data", + "label", + "label_attr", + "label_format", + "mapped", + "method", + "post_max_size_message", + "property_path", + "required", + "translation_domain", + "trim", + "upload_max_size_message" + ] + }, + "extension": { + "Symfony\\Component\\Form\\Extension\\Csrf\\Type\\FormTypeCsrfExtension": [ + "csrf_field_name", + "csrf_message", + "csrf_protection", + "csrf_token_id", + "csrf_token_manager" + ] + }, + "required": [] + }, + "parent_types": [ + "Symfony\\Component\\Form\\Extension\\Core\\Type\\FormType" + ], + "type_extensions": [ + "Symfony\\Component\\Form\\Extension\\Csrf\\Type\\FormTypeCsrfExtension" + ] +} diff --git a/src/Symfony/Component/Form/Tests/Fixtures/Descriptor/resolved_form_type_1.txt b/src/Symfony/Component/Form/Tests/Fixtures/Descriptor/resolved_form_type_1.txt new file mode 100644 index 0000000000000..5f839b85ac6b0 --- /dev/null +++ b/src/Symfony/Component/Form/Tests/Fixtures/Descriptor/resolved_form_type_1.txt @@ -0,0 +1,40 @@ + +Symfony\Component\Form\Extension\Core\Type\ChoiceType (Block prefix: "choice") +============================================================================== + + --------------------------- -------------------- ------------------------- ----------------------- +  Options   Overridden options   Parent options   Extension options  + --------------------------- -------------------- ------------------------- ----------------------- + choice_attr FormType FormType FormTypeCsrfExtension + choice_label -------------------- ------------------------- ----------------------- + choice_loader compound action csrf_field_name + choice_name data_class attr csrf_message + choice_translation_domain empty_data auto_initialize csrf_protection + choice_value error_bubbling block_name csrf_token_id + choices by_reference csrf_token_manager + choices_as_values data + expanded disabled + group_by inherit_data + multiple label + placeholder label_attr + preferred_choices label_format + mapped + method + post_max_size_message + property_path + required + translation_domain + trim + upload_max_size_message + --------------------------- -------------------- ------------------------- ----------------------- + +Parent types +------------ + + * Symfony\Component\Form\Extension\Core\Type\FormType + +Type extensions +--------------- + + * Symfony\Component\Form\Extension\Csrf\Type\FormTypeCsrfExtension + diff --git a/src/Symfony/Component/Form/Util/OptionsResolverWrapper.php b/src/Symfony/Component/Form/Util/OptionsResolverWrapper.php new file mode 100644 index 0000000000000..94a4fc111abcf --- /dev/null +++ b/src/Symfony/Component/Form/Util/OptionsResolverWrapper.php @@ -0,0 +1,91 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Util; + +use Symfony\Component\OptionsResolver\Exception\AccessException; +use Symfony\Component\OptionsResolver\Exception\UndefinedOptionsException; +use Symfony\Component\OptionsResolver\OptionsResolver; + +/** + * @author Yonel Ceruto + * + * @internal + */ +class OptionsResolverWrapper extends OptionsResolver +{ + private $undefined = array(); + + public function setNormalizer($option, \Closure $normalizer) + { + try { + parent::setNormalizer($option, $normalizer); + } catch (UndefinedOptionsException $e) { + $this->undefined[$option] = true; + } + + return $this; + } + + public function setAllowedValues($option, $allowedValues) + { + try { + parent::setAllowedValues($option, $allowedValues); + } catch (UndefinedOptionsException $e) { + $this->undefined[$option] = true; + } + + return $this; + } + + public function addAllowedValues($option, $allowedValues) + { + try { + parent::addAllowedValues($option, $allowedValues); + } catch (UndefinedOptionsException $e) { + $this->undefined[$option] = true; + } + + return $this; + } + + public function setAllowedTypes($option, $allowedTypes) + { + try { + parent::setAllowedTypes($option, $allowedTypes); + } catch (UndefinedOptionsException $e) { + $this->undefined[$option] = true; + } + + return $this; + } + + public function addAllowedTypes($option, $allowedTypes) + { + try { + parent::addAllowedTypes($option, $allowedTypes); + } catch (UndefinedOptionsException $e) { + $this->undefined[$option] = true; + } + + return $this; + } + + public function resolve(array $options = array()) + { + throw new AccessException('Resolve options is not supported.'); + } + + public function getUndefinedOptions() + { + return array_keys($this->undefined); + } +} diff --git a/src/Symfony/Component/Form/composer.json b/src/Symfony/Component/Form/composer.json index 0bc08d66a7c8a..77fc3e565ffa7 100644 --- a/src/Symfony/Component/Form/composer.json +++ b/src/Symfony/Component/Form/composer.json @@ -19,7 +19,7 @@ "php": "^5.5.9|>=7.0.8", "symfony/event-dispatcher": "~2.8|~3.0|~4.0", "symfony/intl": "^2.8.18|^3.2.5|~4.0", - "symfony/options-resolver": "~2.8|~3.0|~4.0", + "symfony/options-resolver": "~3.4|~4.0", "symfony/polyfill-mbstring": "~1.0", "symfony/property-access": "~2.8|~3.0|~4.0" }, @@ -32,7 +32,8 @@ "symfony/http-kernel": "^3.3.5|~4.0", "symfony/security-csrf": "~2.8|~3.0|~4.0", "symfony/translation": "~2.8|~3.0|~4.0", - "symfony/var-dumper": "~3.3|~4.0" + "symfony/var-dumper": "~3.3|~4.0", + "symfony/console": "~3.4|~4.0" }, "conflict": { "phpunit/phpunit": "<4.8.35|<5.4.3,>=5.0", From d5cb1fe711b7ab87732ebf5c96b58351dbdc3fc0 Mon Sep 17 00:00:00 2001 From: Javier Eguiluz Date: Mon, 31 Jul 2017 16:54:24 +0200 Subject: [PATCH 0715/1099] Fixed the escaping of back slashes and << in console output --- .../Component/Console/Formatter/OutputFormatter.php | 7 ++++--- .../Console/Tests/Formatter/OutputFormatterTest.php | 3 +++ 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Component/Console/Formatter/OutputFormatter.php b/src/Symfony/Component/Console/Formatter/OutputFormatter.php index dc192711e6093..c8a6a780b0580 100644 --- a/src/Symfony/Component/Console/Formatter/OutputFormatter.php +++ b/src/Symfony/Component/Console/Formatter/OutputFormatter.php @@ -50,7 +50,8 @@ public static function escapeTrailingBackslash($text) if ('\\' === substr($text, -1)) { $len = strlen($text); $text = rtrim($text, '\\'); - $text .= str_repeat('<<', $len - strlen($text)); + $text = str_replace("\0", '', $text); + $text .= str_repeat("\0", $len - strlen($text)); } return $text; @@ -165,8 +166,8 @@ public function format($message) $output .= $this->applyCurrentStyle(substr($message, $offset)); - if (false !== strpos($output, '<<')) { - return strtr($output, array('\\<' => '<', '<<' => '\\')); + if (false !== strpos($output, "\0")) { + return strtr($output, array("\0" => '\\', '\\<' => '<')); } return str_replace('\\<', '<', $output); diff --git a/src/Symfony/Component/Console/Tests/Formatter/OutputFormatterTest.php b/src/Symfony/Component/Console/Tests/Formatter/OutputFormatterTest.php index 866c31a443754..00e5231d80498 100644 --- a/src/Symfony/Component/Console/Tests/Formatter/OutputFormatterTest.php +++ b/src/Symfony/Component/Console/Tests/Formatter/OutputFormatterTest.php @@ -28,6 +28,9 @@ public function testLGCharEscaping() $formatter = new OutputFormatter(true); $this->assertEquals('fooformat('foo\\assertEquals('foo << bar', $formatter->format('foo << bar')); + $this->assertEquals('foo << bar \\', $formatter->format('foo << bar \\')); + $this->assertEquals("foo << \033[32mbar \\ baz\033[39m \\", $formatter->format('foo << bar \\ baz \\')); $this->assertEquals('some info', $formatter->format('\\some info\\')); $this->assertEquals('\\some info\\', OutputFormatter::escape('some info')); From 279430800ecf50db35eab566eaa2f5bd596e06d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9my=20Deruss=C3=A9?= Date: Thu, 27 Apr 2017 00:02:52 +0200 Subject: [PATCH 0716/1099] [Lock] Expose an expiringDate and isExpired method in Lock --- src/Symfony/Component/Lock/Key.php | 26 ++++++++++++++++ src/Symfony/Component/Lock/Lock.php | 18 +++++++++++ .../Component/Lock/Store/MemcachedStore.php | 2 ++ .../Component/Lock/Store/RedisStore.php | 8 ++--- src/Symfony/Component/Lock/Tests/LockTest.php | 30 +++++++++++++++++++ .../Lock/Tests/Store/AbstractStoreTest.php | 7 +++-- .../Tests/Store/ExpiringStoreTestTrait.php | 12 ++++++++ 7 files changed, 97 insertions(+), 6 deletions(-) diff --git a/src/Symfony/Component/Lock/Key.php b/src/Symfony/Component/Lock/Key.php index 5b53ae9b6b078..5069901761820 100644 --- a/src/Symfony/Component/Lock/Key.php +++ b/src/Symfony/Component/Lock/Key.php @@ -19,6 +19,7 @@ final class Key { private $resource; + private $expiringDate; private $state = array(); /** @@ -70,4 +71,29 @@ public function getState($stateKey) { return $this->state[$stateKey]; } + + /** + * @param float $ttl The expiration delay of locks in seconds. + */ + public function reduceLifetime($ttl) + { + $newExpiringDate = \DateTimeImmutable::createFromFormat('U.u', (string) (microtime(true) + $ttl)); + + if (null === $this->expiringDate || $newExpiringDate < $this->expiringDate) { + $this->expiringDate = $newExpiringDate; + } + } + + public function resetExpiringDate() + { + $this->expiringDate = null; + } + + /** + * @return \DateTimeImmutable + */ + public function getExpiringDate() + { + return $this->expiringDate; + } } diff --git a/src/Symfony/Component/Lock/Lock.php b/src/Symfony/Component/Lock/Lock.php index 5d5342a528002..c42bd2255cf5f 100644 --- a/src/Symfony/Component/Lock/Lock.php +++ b/src/Symfony/Component/Lock/Lock.php @@ -89,6 +89,7 @@ public function refresh() } try { + $this->key->resetExpiringDate(); $this->store->putOffExpiration($this->key, $this->ttl); $this->logger->info('Expiration defined for "{resource}" lock for "{ttl}" seconds.', array('resource' => $this->key, 'ttl' => $this->ttl)); } catch (LockConflictedException $e) { @@ -120,4 +121,21 @@ public function release() throw new LockReleasingException(sprintf('Failed to release the "%s" lock.', $this->key)); } } + + /** + * @return bool + */ + public function isExpired() + { + if (null === $expireDate = $this->key->getExpiringDate()) { + return false; + } + + return $expireDate <= new \DateTime(); + } + + public function getExpiringDate() + { + return $this->key->getExpiringDate(); + } } diff --git a/src/Symfony/Component/Lock/Store/MemcachedStore.php b/src/Symfony/Component/Lock/Store/MemcachedStore.php index a1e31ee63320f..4f8d6f5ff7159 100644 --- a/src/Symfony/Component/Lock/Store/MemcachedStore.php +++ b/src/Symfony/Component/Lock/Store/MemcachedStore.php @@ -58,6 +58,7 @@ public function save(Key $key) { $token = $this->getToken($key); + $key->reduceLifetime($this->initialTtl); if ($this->memcached->add((string) $key, $token, (int) ceil($this->initialTtl))) { return; } @@ -87,6 +88,7 @@ public function putOffExpiration(Key $key, $ttl) list($value, $cas) = $this->getValueAndCas($key); + $key->reduceLifetime($ttl); // Could happens when we ask a putOff after a timeout but in luck nobody steal the lock if (\Memcached::RES_NOTFOUND === $this->memcached->getResultCode()) { if ($this->memcached->add((string) $key, $token, $ttl)) { diff --git a/src/Symfony/Component/Lock/Store/RedisStore.php b/src/Symfony/Component/Lock/Store/RedisStore.php index b9ea2a5fb80e3..d67120fe0c0c3 100644 --- a/src/Symfony/Component/Lock/Store/RedisStore.php +++ b/src/Symfony/Component/Lock/Store/RedisStore.php @@ -57,8 +57,8 @@ public function save(Key $key) end '; - $expire = (int) ceil($this->initialTtl * 1000); - if (!$this->evaluate($script, (string) $key, array($this->getToken($key), $expire))) { + $key->reduceLifetime($this->initialTtl); + if (!$this->evaluate($script, (string) $key, array($this->getToken($key), (int) ceil($this->initialTtl * 1000)))) { throw new LockConflictedException(); } } @@ -81,8 +81,8 @@ public function putOffExpiration(Key $key, $ttl) end '; - $expire = (int) ceil($ttl * 1000); - if (!$this->evaluate($script, (string) $key, array($this->getToken($key), $expire))) { + $key->reduceLifetime($ttl); + if (!$this->evaluate($script, (string) $key, array($this->getToken($key), (int) ceil($ttl * 1000)))) { throw new LockConflictedException(); } } diff --git a/src/Symfony/Component/Lock/Tests/LockTest.php b/src/Symfony/Component/Lock/Tests/LockTest.php index 58dbdc5820131..fb107232efba6 100644 --- a/src/Symfony/Component/Lock/Tests/LockTest.php +++ b/src/Symfony/Component/Lock/Tests/LockTest.php @@ -153,4 +153,34 @@ public function testReleaseThrowsExceptionIfNotWellDeleted() $lock->release(); } + + /** + * @dataProvider provideExpiredDates + */ + public function testExpiration($ttls, $expected) + { + $key = new Key(uniqid(__METHOD__, true)); + $store = $this->getMockBuilder(StoreInterface::class)->getMock(); + $lock = new Lock($key, $store, 10); + + foreach ($ttls as $ttl) { + if (null === $ttl) { + $key->resetExpiringDate(); + } else { + $key->reduceLifetime($ttl); + } + } + $this->assertSame($expected, $lock->isExpired()); + } + + public function provideExpiredDates() + { + yield array(array(-1.0), true); + yield array(array(1, -1.0), true); + yield array(array(-1.0, 1), true); + + yield array(array(), false); + yield array(array(1), false); + yield array(array(-1.0, null), false); + } } diff --git a/src/Symfony/Component/Lock/Tests/Store/AbstractStoreTest.php b/src/Symfony/Component/Lock/Tests/Store/AbstractStoreTest.php index c0d758744ce1a..630ba743cc4e8 100644 --- a/src/Symfony/Component/Lock/Tests/Store/AbstractStoreTest.php +++ b/src/Symfony/Component/Lock/Tests/Store/AbstractStoreTest.php @@ -49,14 +49,17 @@ public function testSaveWithDifferentResources() $store->save($key1); $this->assertTrue($store->exists($key1)); $this->assertFalse($store->exists($key2)); - $store->save($key2); + $store->save($key2); $this->assertTrue($store->exists($key1)); $this->assertTrue($store->exists($key2)); $store->delete($key1); $this->assertFalse($store->exists($key1)); + $this->assertTrue($store->exists($key2)); + $store->delete($key2); + $this->assertFalse($store->exists($key1)); $this->assertFalse($store->exists($key2)); } @@ -74,7 +77,7 @@ public function testSaveWithDifferentKeysOnSameResources() try { $store->save($key2); - throw new \Exception('The store shouldn\'t save the second key'); + $this->fail('The store shouldn\'t save the second key'); } catch (LockConflictedException $e) { } diff --git a/src/Symfony/Component/Lock/Tests/Store/ExpiringStoreTestTrait.php b/src/Symfony/Component/Lock/Tests/Store/ExpiringStoreTestTrait.php index 0280aa61739ee..f862f0d4aa300 100644 --- a/src/Symfony/Component/Lock/Tests/Store/ExpiringStoreTestTrait.php +++ b/src/Symfony/Component/Lock/Tests/Store/ExpiringStoreTestTrait.php @@ -75,4 +75,16 @@ public function testRefreshLock() usleep(2.1 * $clockDelay); $this->assertFalse($store->exists($key)); } + + public function testSetExpiration() + { + $key = new Key(uniqid(__METHOD__, true)); + + /** @var StoreInterface $store */ + $store = $this->getStore(); + + $store->save($key); + $store->putOffExpiration($key, 1); + $this->assertNotNull($key->getExpiringDate()); + } } From b9fc357d1cdd5ec4a864eb513bd7fede377f9272 Mon Sep 17 00:00:00 2001 From: Robin Chalas Date: Tue, 29 Aug 2017 23:15:51 +0200 Subject: [PATCH 0717/1099] Fix merge --- src/Symfony/Component/Console/Application.php | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/src/Symfony/Component/Console/Application.php b/src/Symfony/Component/Console/Application.php index 96016e3d3935e..c1731843e6eb2 100644 --- a/src/Symfony/Component/Console/Application.php +++ b/src/Symfony/Component/Console/Application.php @@ -505,13 +505,9 @@ public function get($name) */ public function has($name) { -<<<<<<< HEAD - return isset($this->commands[$name]) || ($this->commandLoader && $this->commandLoader->has($name)); -======= $this->init(); - return isset($this->commands[$name]); ->>>>>>> 3.3 + return isset($this->commands[$name]) || ($this->commandLoader && $this->commandLoader->has($name)); } /** @@ -588,13 +584,9 @@ public function findNamespace($namespace) */ public function find($name) { -<<<<<<< HEAD - $allCommands = $this->commandLoader ? array_merge($this->commandLoader->getNames(), array_keys($this->commands)) : array_keys($this->commands); -======= $this->init(); - $allCommands = array_keys($this->commands); ->>>>>>> 3.3 + $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); From 00d959c9339e56b95ea1c2666b0e1e4e3c6c4d4b Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Tue, 29 Aug 2017 14:51:48 -0700 Subject: [PATCH 0718/1099] [Routing] added the possibility to define a prefix for all routes of a controller --- src/Symfony/Component/Routing/CHANGELOG.md | 1 + .../Component/Routing/Loader/AnnotationClassLoader.php | 7 +++++++ .../Routing/Tests/Loader/AnnotationClassLoaderTest.php | 5 +++-- 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/Routing/CHANGELOG.md b/src/Symfony/Component/Routing/CHANGELOG.md index 33faeb73aa607..3785709d42425 100644 --- a/src/Symfony/Component/Routing/CHANGELOG.md +++ b/src/Symfony/Component/Routing/CHANGELOG.md @@ -4,6 +4,7 @@ CHANGELOG 3.4.0 ----- + * Added the possibility to define a prefix for all routes of a controller via @Route(name="prefix_") * Added support for prioritized routing loaders. * Add matched and default parameters to redirect responses * Added support for a `controller` keyword for configuring route controllers in YAML and XML configurations. diff --git a/src/Symfony/Component/Routing/Loader/AnnotationClassLoader.php b/src/Symfony/Component/Routing/Loader/AnnotationClassLoader.php index c91a7f7d5b148..e4e5306dcbb5c 100644 --- a/src/Symfony/Component/Routing/Loader/AnnotationClassLoader.php +++ b/src/Symfony/Component/Routing/Loader/AnnotationClassLoader.php @@ -129,6 +129,7 @@ public function load($class, $type = null) if (0 === $collection->count() && $class->hasMethod('__invoke') && $annot = $this->reader->getClassAnnotation($class, $this->routeAnnotationClass)) { $globals['path'] = ''; + $globals['name'] = ''; $this->addRoute($collection, $annot, $globals, $class, $class->getMethod('__invoke')); } @@ -141,6 +142,7 @@ protected function addRoute(RouteCollection $collection, $annot, $globals, \Refl if (null === $name) { $name = $this->getDefaultRouteName($class, $method); } + $name = $globals['name'].$name; $defaults = array_replace($globals['defaults'], $annot->getDefaults()); foreach ($method->getParameters() as $param) { @@ -222,9 +224,14 @@ protected function getGlobals(\ReflectionClass $class) 'methods' => array(), 'host' => '', 'condition' => '', + 'name' => '', ); if ($annot = $this->reader->getClassAnnotation($class, $this->routeAnnotationClass)) { + if (null !== $annot->getName()) { + $globals['name'] = $annot->getName(); + } + if (null !== $annot->getPath()) { $globals['path'] = $annot->getPath(); } diff --git a/src/Symfony/Component/Routing/Tests/Loader/AnnotationClassLoaderTest.php b/src/Symfony/Component/Routing/Tests/Loader/AnnotationClassLoaderTest.php index bf2ab4ac9cbc5..70db1ccd9ad6a 100644 --- a/src/Symfony/Component/Routing/Tests/Loader/AnnotationClassLoaderTest.php +++ b/src/Symfony/Component/Routing/Tests/Loader/AnnotationClassLoaderTest.php @@ -149,6 +149,7 @@ public function testLoad($className, $routeData = array(), $methodArgs = array() public function testClassRouteLoad() { $classRouteData = array( + 'name' => 'prefix_', 'path' => '/prefix', 'schemes' => array('https'), 'methods' => array('GET'), @@ -173,7 +174,7 @@ public function testClassRouteLoad() ; $routeCollection = $this->loader->load('Symfony\Component\Routing\Tests\Fixtures\AnnotatedClasses\BarClass'); - $route = $routeCollection->get($methodRouteData['name']); + $route = $routeCollection->get($classRouteData['name'].$methodRouteData['name']); $this->assertSame($classRouteData['path'].$methodRouteData['path'], $route->getPath(), '->load concatenates class and method route path'); $this->assertEquals(array_merge($classRouteData['schemes'], $methodRouteData['schemes']), $route->getSchemes(), '->load merges class and method route schemes'); @@ -240,7 +241,7 @@ public function testInvokableClassWithMethodRouteLoad() $this->assertNull($route, '->load ignores class route'); - $route = $routeCollection->get($methodRouteData['name']); + $route = $routeCollection->get($classRouteData['name'].$methodRouteData['name']); $this->assertSame($classRouteData['path'].$methodRouteData['path'], $route->getPath(), '->load concatenates class and method route path'); $this->assertEquals(array_merge($classRouteData['schemes'], $methodRouteData['schemes']), $route->getSchemes(), '->load merges class and method route schemes'); From af2b66b5b7e16012ff68a5ae2dec033edd5bf210 Mon Sep 17 00:00:00 2001 From: Robin Chalas Date: Wed, 30 Aug 2017 01:26:39 +0200 Subject: [PATCH 0719/1099] Remove deprecated translation.loader service (fix merge) --- .../Bundle/FrameworkBundle/Resources/config/translation.xml | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/translation.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/translation.xml index cfe05f5148fdd..be64a84727e56 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/translation.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/translation.xml @@ -121,9 +121,6 @@ - - The "%service_id%" service is deprecated since Symfony 3.4 and will be removed in 4.0. Use "translation.reader" instead. - From a4021e6bb08fa05c0214dde80319c6a4405f08a7 Mon Sep 17 00:00:00 2001 From: Robin Chalas Date: Wed, 30 Aug 2017 01:29:11 +0200 Subject: [PATCH 0720/1099] Remove deprecated TranslationLoader (fix merge) --- .../Translation/TranslationLoader.php | 34 ------------------- 1 file changed, 34 deletions(-) delete mode 100644 src/Symfony/Bundle/FrameworkBundle/Translation/TranslationLoader.php diff --git a/src/Symfony/Bundle/FrameworkBundle/Translation/TranslationLoader.php b/src/Symfony/Bundle/FrameworkBundle/Translation/TranslationLoader.php deleted file mode 100644 index b125c75c0676c..0000000000000 --- a/src/Symfony/Bundle/FrameworkBundle/Translation/TranslationLoader.php +++ /dev/null @@ -1,34 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\FrameworkBundle\Translation; - -use Symfony\Component\Translation\Reader\TranslationReader; -use Symfony\Component\Translation\MessageCatalogue; - -@trigger_error(sprintf('The class "%s" is deprecated since version 3.4 and will be removed in 4.0. Use "%s" instead. ', TranslationLoader::class, TranslationReader::class), E_USER_DEPRECATED); - -/** - * @deprecated since version 3.4 and will be removed in 4.0. Use Symfony\Component\Translation\Reader\TranslationReader instead - */ -class TranslationLoader extends TranslationReader -{ - /** - * Loads translation messages from a directory to the catalogue. - * - * @param string $directory the directory to look into - * @param MessageCatalogue $catalogue the catalogue - */ - public function loadMessages($directory, MessageCatalogue $catalogue) - { - $this->read($directory, $catalogue); - } -} From edb8c33f35b981b72adbe23798753703edfe3819 Mon Sep 17 00:00:00 2001 From: Robin Chalas Date: Wed, 30 Aug 2017 01:36:56 +0200 Subject: [PATCH 0721/1099] Fix merge --- .../Bundle/FrameworkBundle/Resources/config/console.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/console.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/console.xml index 4bdaa85fee4c3..6f5fe05ace272 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/console.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/console.xml @@ -72,14 +72,14 @@ - + - + %kernel.default_locale% From 330c6bf53e21b8c3a33fa3b272cc3b43f8063f02 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Tue, 29 Aug 2017 22:51:11 +0200 Subject: [PATCH 0722/1099] [Yaml] mark some classes as final --- UPGRADE-3.4.md | 2 ++ src/Symfony/Component/Yaml/CHANGELOG.md | 2 ++ src/Symfony/Component/Yaml/Dumper.php | 2 ++ src/Symfony/Component/Yaml/Parser.php | 2 ++ src/Symfony/Component/Yaml/Yaml.php | 2 ++ 5 files changed, 10 insertions(+) diff --git a/UPGRADE-3.4.md b/UPGRADE-3.4.md index 5408251e98968..f72652fbe4715 100644 --- a/UPGRADE-3.4.md +++ b/UPGRADE-3.4.md @@ -203,6 +203,8 @@ Validator Yaml ---- + * the `Dumper`, `Parser`, and `Yaml` classes are marked as final + * using the `!php/object:` tag is deprecated and won't be supported in 4.0. Use the `!php/object` tag (without the colon) instead. diff --git a/src/Symfony/Component/Yaml/CHANGELOG.md b/src/Symfony/Component/Yaml/CHANGELOG.md index bdbac2b93e917..cdd49352d5185 100644 --- a/src/Symfony/Component/Yaml/CHANGELOG.md +++ b/src/Symfony/Component/Yaml/CHANGELOG.md @@ -4,6 +4,8 @@ CHANGELOG 3.4.0 ----- + * the `Dumper`, `Parser`, and `Yaml` classes are marked as final + * Deprecated the `!php/object:` tag which will be replaced by the `!php/object` tag (without the colon) in 4.0. diff --git a/src/Symfony/Component/Yaml/Dumper.php b/src/Symfony/Component/Yaml/Dumper.php index e26a65a5076d7..427f1a7b0f7d6 100644 --- a/src/Symfony/Component/Yaml/Dumper.php +++ b/src/Symfony/Component/Yaml/Dumper.php @@ -15,6 +15,8 @@ * Dumper dumps PHP variables to YAML strings. * * @author Fabien Potencier + * + * @final since version 3.4 */ class Dumper { diff --git a/src/Symfony/Component/Yaml/Parser.php b/src/Symfony/Component/Yaml/Parser.php index 1ebd958482e88..b39512c869d14 100644 --- a/src/Symfony/Component/Yaml/Parser.php +++ b/src/Symfony/Component/Yaml/Parser.php @@ -18,6 +18,8 @@ * Parser parses YAML strings to convert them to PHP arrays. * * @author Fabien Potencier + * + * @final since version 3.4 */ class Parser { diff --git a/src/Symfony/Component/Yaml/Yaml.php b/src/Symfony/Component/Yaml/Yaml.php index 82397fbcb5172..52a064f70b5fb 100644 --- a/src/Symfony/Component/Yaml/Yaml.php +++ b/src/Symfony/Component/Yaml/Yaml.php @@ -17,6 +17,8 @@ * Yaml offers convenience methods to load and dump YAML. * * @author Fabien Potencier + * + * @final since version 3.4 */ class Yaml { From fd7352eb374d97b2aba0a88b223e915e9cb217f1 Mon Sep 17 00:00:00 2001 From: Dany Maillard Date: Wed, 30 Aug 2017 10:17:18 +0200 Subject: [PATCH 0723/1099] Prepare period caster for 4.0 --- .../Component/VarDumper/Caster/DateCaster.php | 8 +++----- .../VarDumper/Tests/Caster/DateCasterTest.php | 15 ++------------- 2 files changed, 5 insertions(+), 18 deletions(-) diff --git a/src/Symfony/Component/VarDumper/Caster/DateCaster.php b/src/Symfony/Component/VarDumper/Caster/DateCaster.php index 2d229078dda48..b39b1f9b05a83 100644 --- a/src/Symfony/Component/VarDumper/Caster/DateCaster.php +++ b/src/Symfony/Component/VarDumper/Caster/DateCaster.php @@ -20,6 +20,8 @@ */ class DateCaster { + private const PERIOD_LIMIT = 3; + public static function castDateTime(\DateTimeInterface $d, array $a, Stub $stub, $isNested, $filter) { $prefix = Caster::PREFIX_VIRTUAL; @@ -80,14 +82,10 @@ public static function castTimeZone(\DateTimeZone $timeZone, array $a, Stub $stu public static function castPeriod(\DatePeriod $p, array $a, Stub $stub, $isNested, $filter) { - if (defined('HHVM_VERSION_ID') || \PHP_VERSION_ID < 50620 || (\PHP_VERSION_ID >= 70000 && \PHP_VERSION_ID < 70005)) { // see https://bugs.php.net/bug.php?id=71635 - return $a; - } - $dates = array(); if (\PHP_VERSION_ID >= 70107) { // see https://bugs.php.net/bug.php?id=74639 foreach (clone $p as $i => $d) { - if (3 === $i) { + if (self::PERIOD_LIMIT === $i) { $now = new \DateTimeImmutable(); $dates[] = sprintf('%s more', ($end = $p->getEndDate()) ? ceil(($end->format('U.u') - $d->format('U.u')) / ($now->add($p->getDateInterval())->format('U.u') - $now->format('U.u'))) diff --git a/src/Symfony/Component/VarDumper/Tests/Caster/DateCasterTest.php b/src/Symfony/Component/VarDumper/Tests/Caster/DateCasterTest.php index 223fa8be376ef..a3bc4867a88e9 100644 --- a/src/Symfony/Component/VarDumper/Tests/Caster/DateCasterTest.php +++ b/src/Symfony/Component/VarDumper/Tests/Caster/DateCasterTest.php @@ -291,10 +291,6 @@ public function provideTimeZones() */ public function testDumpPeriod($start, $interval, $end, $options, $expected) { - if (defined('HHVM_VERSION_ID') || \PHP_VERSION_ID < 50620 || (\PHP_VERSION_ID >= 70000 && \PHP_VERSION_ID < 70005)) { - $this->markTestSkipped(); - } - $p = new \DatePeriod(new \DateTime($start), new \DateInterval($interval), is_int($end) ? $end : new \DateTime($end), $options); $xDump = <<= 70000 && \PHP_VERSION_ID < 70005)) { - $this->markTestSkipped(); - } - $p = new \DatePeriod(new \DateTime($start), new \DateInterval($interval), is_int($end) ? $end : new \DateTime($end), $options); $stub = new Stub(); @@ -346,9 +338,6 @@ public function testCastPeriod($start, $interval, $end, $options, $xPeriod, $xDa public function providePeriods() { - $i = new \DateInterval('PT0S'); - $ms = \PHP_VERSION_ID >= 70100 && isset($i->f) ? '.0' : ''; - $periods = array( array('2017-01-01', 'P1D', '2017-01-03', 0, 'every + 1d, from 2017-01-01 00:00:00 (included) to 2017-01-03 00:00:00', '1) 2017-01-01%a2) 2017-01-02'), array('2017-01-01', 'P1D', 1, 0, 'every + 1d, from 2017-01-01 00:00:00 (included) recurring 2 time/s', '1) 2017-01-01%a2) 2017-01-02'), @@ -365,8 +354,8 @@ public function providePeriods() array('2017-01-01 01:00:00', 'P1D', '2017-01-03 01:00:00', 0, 'every + 1d, from 2017-01-01 01:00:00 (included) to 2017-01-03 01:00:00', '1) 2017-01-01 01:00:00%a2) 2017-01-02 01:00:00'), array('2017-01-01 01:00:00', 'P1D', 1, 0, 'every + 1d, from 2017-01-01 01:00:00 (included) recurring 2 time/s', '1) 2017-01-01 01:00:00%a2) 2017-01-02 01:00:00'), - array('2017-01-01', 'P1DT1H', '2017-01-03', 0, "every + 1d 01:00:00$ms, from 2017-01-01 00:00:00 (included) to 2017-01-03 00:00:00", '1) 2017-01-01 00:00:00%a2) 2017-01-02 01:00:00'), - array('2017-01-01', 'P1DT1H', 1, 0, "every + 1d 01:00:00$ms, from 2017-01-01 00:00:00 (included) recurring 2 time/s", '1) 2017-01-01 00:00:00%a2) 2017-01-02 01:00:00'), + array('2017-01-01', 'P1DT1H', '2017-01-03', 0, 'every + 1d 01:00:00.0, from 2017-01-01 00:00:00 (included) to 2017-01-03 00:00:00', '1) 2017-01-01 00:00:00%a2) 2017-01-02 01:00:00'), + array('2017-01-01', 'P1DT1H', 1, 0, 'every + 1d 01:00:00.0, from 2017-01-01 00:00:00 (included) recurring 2 time/s', '1) 2017-01-01 00:00:00%a2) 2017-01-02 01:00:00'), array('2017-01-01', 'P1D', '2017-01-04', \DatePeriod::EXCLUDE_START_DATE, 'every + 1d, from 2017-01-01 00:00:00 (excluded) to 2017-01-04 00:00:00', '1) 2017-01-02%a2) 2017-01-03'), array('2017-01-01', 'P1D', 2, \DatePeriod::EXCLUDE_START_DATE, 'every + 1d, from 2017-01-01 00:00:00 (excluded) recurring 2 time/s', '1) 2017-01-02%a2) 2017-01-03'), From 03816b78588e4339c5053f2d6c883f31d5dffbbf Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Wed, 30 Aug 2017 15:41:43 +0200 Subject: [PATCH 0724/1099] [TwigBundle] require twig-bridge ~3.4 --- src/Symfony/Bundle/TwigBundle/composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Bundle/TwigBundle/composer.json b/src/Symfony/Bundle/TwigBundle/composer.json index 7ae69bf76df70..3b8ca5b99469b 100644 --- a/src/Symfony/Bundle/TwigBundle/composer.json +++ b/src/Symfony/Bundle/TwigBundle/composer.json @@ -18,7 +18,7 @@ "require": { "php": "^5.5.9|>=7.0.8", "symfony/config": "~3.2|~4.0", - "symfony/twig-bridge": "^3.3|~4.0", + "symfony/twig-bridge": "^3.4|~4.0", "symfony/http-foundation": "~2.8|~3.0|~4.0", "symfony/http-kernel": "^3.3|~4.0", "twig/twig": "~1.34|~2.4" From 8264a9e3983c922126ccfa29c091a8d35f197dda Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Wed, 30 Aug 2017 16:21:48 +0200 Subject: [PATCH 0725/1099] [HttpKernel] Fix loading legacy 3.3 containers in 3.4 context --- src/Symfony/Component/HttpKernel/Kernel.php | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/Symfony/Component/HttpKernel/Kernel.php b/src/Symfony/Component/HttpKernel/Kernel.php index df795fcd33dbd..d20258d4ac389 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -598,9 +598,7 @@ protected function initializeContainer() } } - if ($oldContainer = file_exists($cache->getPath()) ? @include $cache->getPath() : false) { - $oldContainer = new \ReflectionClass($oldContainer); - } + $oldContainer = file_exists($cache->getPath()) && is_object($oldContainer = @include $cache->getPath()) ? new \ReflectionClass($oldContainer) : false; $this->dumpContainer($cache, $container, $class, $this->getContainerBaseClass()); From 7855748c7896e9dd6e4219846a9ead000a6cc913 Mon Sep 17 00:00:00 2001 From: Thomas Perez Date: Mon, 28 Aug 2017 15:57:41 +0200 Subject: [PATCH 0726/1099] Update NoSuchPropertyException message for writeProperty --- src/Symfony/Component/PropertyAccess/PropertyAccessor.php | 2 +- .../PropertyAccess/Tests/PropertyAccessorCollectionTest.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/PropertyAccess/PropertyAccessor.php b/src/Symfony/Component/PropertyAccess/PropertyAccessor.php index d0cadcf65722c..af999153727f0 100644 --- a/src/Symfony/Component/PropertyAccess/PropertyAccessor.php +++ b/src/Symfony/Component/PropertyAccess/PropertyAccessor.php @@ -649,7 +649,7 @@ private function writeProperty($zval, $property, $value) } elseif (self::ACCESS_TYPE_MAGIC === $access[self::ACCESS_TYPE]) { $object->{$access[self::ACCESS_NAME]}($value); } elseif (self::ACCESS_TYPE_NOT_FOUND === $access[self::ACCESS_TYPE]) { - throw new NoSuchPropertyException(sprintf('Could not determine access type for property "%s".', $property)); + throw new NoSuchPropertyException(sprintf('Could not determine access type for property "%s" in class "%s".', $property, get_class($object))); } else { throw new NoSuchPropertyException($access[self::ACCESS_NAME]); } diff --git a/src/Symfony/Component/PropertyAccess/Tests/PropertyAccessorCollectionTest.php b/src/Symfony/Component/PropertyAccess/Tests/PropertyAccessorCollectionTest.php index b4dc05dac323f..1f10262305242 100644 --- a/src/Symfony/Component/PropertyAccess/Tests/PropertyAccessorCollectionTest.php +++ b/src/Symfony/Component/PropertyAccess/Tests/PropertyAccessorCollectionTest.php @@ -148,7 +148,7 @@ public function testSetValueCallsAdderAndRemoverForNestedCollections() /** * @expectedException \Symfony\Component\PropertyAccess\Exception\NoSuchPropertyException - * @expectedExceptionMessage Could not determine access type for property "axes". + * @expectedExceptionMessageRegExp /Could not determine access type for property "axes" in class "Mock_PropertyAccessorCollectionTest_CarNoAdderAndRemover_[^"]*"./ */ public function testSetValueFailsIfNoAdderNorRemoverFound() { From b20a2376b217d2fdcd8db4329833de96aef57579 Mon Sep 17 00:00:00 2001 From: Rob Frawley 2nd Date: Thu, 20 Jul 2017 13:13:39 -0400 Subject: [PATCH 0727/1099] add (pdo|chain) cache (adapter|simple) prune method --- .../Component/Cache/Adapter/ChainAdapter.php | 19 ++++- .../Component/Cache/Adapter/PdoAdapter.php | 3 +- src/Symfony/Component/Cache/CHANGELOG.md | 6 +- .../Component/Cache/PruneableInterface.php | 2 +- .../Component/Cache/Simple/ChainCache.php | 19 ++++- .../Component/Cache/Simple/PdoCache.php | 3 +- .../Cache/Tests/Adapter/AdapterTestCase.php | 14 ++++ .../Cache/Tests/Adapter/ChainAdapterTest.php | 71 ++++++++++++++++++ .../Cache/Tests/Adapter/PdoAdapterTest.php | 3 + .../Tests/Adapter/PdoDbalAdapterTest.php | 3 + .../Cache/Tests/Simple/CacheTestCase.php | 14 ++++ .../Cache/Tests/Simple/ChainCacheTest.php | 73 ++++++++++++++++++- .../Cache/Tests/Simple/PdoCacheTest.php | 3 + .../Cache/Tests/Simple/PdoDbalCacheTest.php | 3 + .../Cache/Tests/Traits/PdoPruneableTrait.php | 34 +++++++++ .../Component/Cache/Traits/PdoTrait.php | 23 ++++++ 16 files changed, 284 insertions(+), 9 deletions(-) create mode 100644 src/Symfony/Component/Cache/Tests/Traits/PdoPruneableTrait.php diff --git a/src/Symfony/Component/Cache/Adapter/ChainAdapter.php b/src/Symfony/Component/Cache/Adapter/ChainAdapter.php index 7512472150631..c38949975d884 100644 --- a/src/Symfony/Component/Cache/Adapter/ChainAdapter.php +++ b/src/Symfony/Component/Cache/Adapter/ChainAdapter.php @@ -15,6 +15,7 @@ use Psr\Cache\CacheItemPoolInterface; use Symfony\Component\Cache\CacheItem; use Symfony\Component\Cache\Exception\InvalidArgumentException; +use Symfony\Component\Cache\PruneableInterface; /** * Chains several adapters together. @@ -24,7 +25,7 @@ * * @author Kévin Dunglas */ -class ChainAdapter implements AdapterInterface +class ChainAdapter implements AdapterInterface, PruneableInterface { private $adapters = array(); private $adapterCount; @@ -231,4 +232,20 @@ public function commit() return $committed; } + + /** + * {@inheritdoc} + */ + public function prune() + { + $pruned = true; + + foreach ($this->adapters as $adapter) { + if ($adapter instanceof PruneableInterface) { + $pruned = $adapter->prune() && $pruned; + } + } + + return $pruned; + } } diff --git a/src/Symfony/Component/Cache/Adapter/PdoAdapter.php b/src/Symfony/Component/Cache/Adapter/PdoAdapter.php index 832185629b053..9db17805628de 100644 --- a/src/Symfony/Component/Cache/Adapter/PdoAdapter.php +++ b/src/Symfony/Component/Cache/Adapter/PdoAdapter.php @@ -11,9 +11,10 @@ namespace Symfony\Component\Cache\Adapter; +use Symfony\Component\Cache\PruneableInterface; use Symfony\Component\Cache\Traits\PdoTrait; -class PdoAdapter extends AbstractAdapter +class PdoAdapter extends AbstractAdapter implements PruneableInterface { use PdoTrait; diff --git a/src/Symfony/Component/Cache/CHANGELOG.md b/src/Symfony/Component/Cache/CHANGELOG.md index e8172d94988d4..bd637f10df0b0 100644 --- a/src/Symfony/Component/Cache/CHANGELOG.md +++ b/src/Symfony/Component/Cache/CHANGELOG.md @@ -5,9 +5,9 @@ CHANGELOG ----- * added PruneableInterface so PSR-6 or PSR-16 cache implementations can declare support for manual stale cache pruning - * added FilesystemTrait::prune() and PhpFilesTrait::prune() implementations - * now FilesystemAdapter, PhpFilesAdapter, FilesystemCache, and PhpFilesCache implement PruneableInterface and support - manual stale cache pruning + * added prune logic to FilesystemTrait, PhpFilesTrait, PdoTrait, and ChainTrait + * now FilesystemAdapter, PhpFilesAdapter, FilesystemCache, PhpFilesCache, PdoAdapter, PdoCache, ChainAdapter, and + ChainCache implement PruneableInterface and support manual stale cache pruning 3.3.0 ----- diff --git a/src/Symfony/Component/Cache/PruneableInterface.php b/src/Symfony/Component/Cache/PruneableInterface.php index cd366adb55290..42615253689fe 100644 --- a/src/Symfony/Component/Cache/PruneableInterface.php +++ b/src/Symfony/Component/Cache/PruneableInterface.php @@ -12,7 +12,7 @@ namespace Symfony\Component\Cache; /** - * Interface for adapters and simple cache implementations that allow pruning expired items. + * Interface extends psr-6 and psr-16 caches to allow for pruning (deletion) of all expired cache items. */ interface PruneableInterface { diff --git a/src/Symfony/Component/Cache/Simple/ChainCache.php b/src/Symfony/Component/Cache/Simple/ChainCache.php index 08bb4881b463f..8bb944fd4773f 100644 --- a/src/Symfony/Component/Cache/Simple/ChainCache.php +++ b/src/Symfony/Component/Cache/Simple/ChainCache.php @@ -13,6 +13,7 @@ use Psr\SimpleCache\CacheInterface; use Symfony\Component\Cache\Exception\InvalidArgumentException; +use Symfony\Component\Cache\PruneableInterface; /** * Chains several caches together. @@ -22,7 +23,7 @@ * * @author Nicolas Grekas */ -class ChainCache implements CacheInterface +class ChainCache implements CacheInterface, PruneableInterface { private $miss; private $caches = array(); @@ -219,4 +220,20 @@ public function setMultiple($values, $ttl = null) return $saved; } + + /** + * {@inheritdoc} + */ + public function prune() + { + $pruned = true; + + foreach ($this->caches as $cache) { + if ($cache instanceof PruneableInterface) { + $pruned = $cache->prune() && $pruned; + } + } + + return $pruned; + } } diff --git a/src/Symfony/Component/Cache/Simple/PdoCache.php b/src/Symfony/Component/Cache/Simple/PdoCache.php index 3e698e2f952c8..41730cec57f47 100644 --- a/src/Symfony/Component/Cache/Simple/PdoCache.php +++ b/src/Symfony/Component/Cache/Simple/PdoCache.php @@ -11,9 +11,10 @@ namespace Symfony\Component\Cache\Simple; +use Symfony\Component\Cache\PruneableInterface; use Symfony\Component\Cache\Traits\PdoTrait; -class PdoCache extends AbstractCache +class PdoCache extends AbstractCache implements PruneableInterface { use PdoTrait; diff --git a/src/Symfony/Component/Cache/Tests/Adapter/AdapterTestCase.php b/src/Symfony/Component/Cache/Tests/Adapter/AdapterTestCase.php index 6ba02b0d158ff..27318a487fc05 100644 --- a/src/Symfony/Component/Cache/Tests/Adapter/AdapterTestCase.php +++ b/src/Symfony/Component/Cache/Tests/Adapter/AdapterTestCase.php @@ -12,6 +12,7 @@ namespace Symfony\Component\Cache\Tests\Adapter; use Cache\IntegrationTests\CachePoolTest; +use Psr\Cache\CacheItemPoolInterface; use Symfony\Component\Cache\PruneableInterface; abstract class AdapterTestCase extends CachePoolTest @@ -83,6 +84,7 @@ public function testPrune() $this->fail('Test classes for pruneable caches must implement `isPruned($cache, $name)` method.'); } + /** @var PruneableInterface|CacheItemPoolInterface $cache */ $cache = $this->createCachePool(); $doSet = function ($name, $value, \DateInterval $expiresAfter = null) use ($cache) { @@ -96,6 +98,18 @@ public function testPrune() $cache->save($item); }; + $doSet('foo', 'foo-val', new \DateInterval('PT05S')); + $doSet('bar', 'bar-val', new \DateInterval('PT10S')); + $doSet('baz', 'baz-val', new \DateInterval('PT15S')); + $doSet('qux', 'qux-val', new \DateInterval('PT20S')); + + sleep(30); + $cache->prune(); + $this->assertTrue($this->isPruned($cache, 'foo')); + $this->assertTrue($this->isPruned($cache, 'bar')); + $this->assertTrue($this->isPruned($cache, 'baz')); + $this->assertTrue($this->isPruned($cache, 'qux')); + $doSet('foo', 'foo-val'); $doSet('bar', 'bar-val', new \DateInterval('PT20S')); $doSet('baz', 'baz-val', new \DateInterval('PT40S')); diff --git a/src/Symfony/Component/Cache/Tests/Adapter/ChainAdapterTest.php b/src/Symfony/Component/Cache/Tests/Adapter/ChainAdapterTest.php index b80913c6e089c..293a90cc86783 100644 --- a/src/Symfony/Component/Cache/Tests/Adapter/ChainAdapterTest.php +++ b/src/Symfony/Component/Cache/Tests/Adapter/ChainAdapterTest.php @@ -11,9 +11,11 @@ namespace Symfony\Component\Cache\Tests\Adapter; +use Symfony\Component\Cache\Adapter\AdapterInterface; use Symfony\Component\Cache\Adapter\FilesystemAdapter; use Symfony\Component\Cache\Adapter\ArrayAdapter; use Symfony\Component\Cache\Adapter\ChainAdapter; +use Symfony\Component\Cache\PruneableInterface; use Symfony\Component\Cache\Tests\Fixtures\ExternalAdapter; /** @@ -44,4 +46,73 @@ public function testInvalidAdapterException() { new ChainAdapter(array(new \stdClass())); } + + public function testPrune() + { + if (isset($this->skippedTests[__FUNCTION__])) { + $this->markTestSkipped($this->skippedTests[__FUNCTION__]); + } + + $cache = new ChainAdapter(array( + $this->getPruneableMock(), + $this->getNonPruneableMock(), + $this->getPruneableMock(), + )); + $this->assertTrue($cache->prune()); + + $cache = new ChainAdapter(array( + $this->getPruneableMock(), + $this->getFailingPruneableMock(), + $this->getPruneableMock(), + )); + $this->assertFalse($cache->prune()); + } + + /** + * @return \PHPUnit_Framework_MockObject_MockObject|PruneableCacheInterface + */ + private function getPruneableMock() + { + $pruneable = $this + ->getMockBuilder(PruneableCacheInterface::class) + ->getMock(); + + $pruneable + ->expects($this->atLeastOnce()) + ->method('prune') + ->will($this->returnValue(true)); + + return $pruneable; + } + + /** + * @return \PHPUnit_Framework_MockObject_MockObject|PruneableCacheInterface + */ + private function getFailingPruneableMock() + { + $pruneable = $this + ->getMockBuilder(PruneableCacheInterface::class) + ->getMock(); + + $pruneable + ->expects($this->atLeastOnce()) + ->method('prune') + ->will($this->returnValue(false)); + + return $pruneable; + } + + /** + * @return \PHPUnit_Framework_MockObject_MockObject|AdapterInterface + */ + private function getNonPruneableMock() + { + return $this + ->getMockBuilder(AdapterInterface::class) + ->getMock(); + } +} + +interface PruneableCacheInterface extends PruneableInterface, AdapterInterface +{ } diff --git a/src/Symfony/Component/Cache/Tests/Adapter/PdoAdapterTest.php b/src/Symfony/Component/Cache/Tests/Adapter/PdoAdapterTest.php index 90c9ece8bcc9d..24e3f9bbc9582 100644 --- a/src/Symfony/Component/Cache/Tests/Adapter/PdoAdapterTest.php +++ b/src/Symfony/Component/Cache/Tests/Adapter/PdoAdapterTest.php @@ -12,12 +12,15 @@ namespace Symfony\Component\Cache\Tests\Adapter; use Symfony\Component\Cache\Adapter\PdoAdapter; +use Symfony\Component\Cache\Tests\Traits\PdoPruneableTrait; /** * @group time-sensitive */ class PdoAdapterTest extends AdapterTestCase { + use PdoPruneableTrait; + protected static $dbFile; public static function setupBeforeClass() diff --git a/src/Symfony/Component/Cache/Tests/Adapter/PdoDbalAdapterTest.php b/src/Symfony/Component/Cache/Tests/Adapter/PdoDbalAdapterTest.php index b9c396fdc59eb..1e8c6155bdd35 100644 --- a/src/Symfony/Component/Cache/Tests/Adapter/PdoDbalAdapterTest.php +++ b/src/Symfony/Component/Cache/Tests/Adapter/PdoDbalAdapterTest.php @@ -13,12 +13,15 @@ use Doctrine\DBAL\DriverManager; use Symfony\Component\Cache\Adapter\PdoAdapter; +use Symfony\Component\Cache\Tests\Traits\PdoPruneableTrait; /** * @group time-sensitive */ class PdoDbalAdapterTest extends AdapterTestCase { + use PdoPruneableTrait; + protected static $dbFile; public static function setupBeforeClass() diff --git a/src/Symfony/Component/Cache/Tests/Simple/CacheTestCase.php b/src/Symfony/Component/Cache/Tests/Simple/CacheTestCase.php index 600cd338be540..48b972824c2c2 100644 --- a/src/Symfony/Component/Cache/Tests/Simple/CacheTestCase.php +++ b/src/Symfony/Component/Cache/Tests/Simple/CacheTestCase.php @@ -12,6 +12,7 @@ namespace Symfony\Component\Cache\Tests\Simple; use Cache\IntegrationTests\SimpleCacheTest; +use Psr\SimpleCache\CacheInterface; use Symfony\Component\Cache\PruneableInterface; abstract class CacheTestCase extends SimpleCacheTest @@ -80,8 +81,21 @@ public function testPrune() $this->fail('Test classes for pruneable caches must implement `isPruned($cache, $name)` method.'); } + /** @var PruneableInterface|CacheInterface $cache */ $cache = $this->createSimpleCache(); + $cache->set('foo', 'foo-val', new \DateInterval('PT05S')); + $cache->set('bar', 'bar-val', new \DateInterval('PT10S')); + $cache->set('baz', 'baz-val', new \DateInterval('PT15S')); + $cache->set('qux', 'qux-val', new \DateInterval('PT20S')); + + sleep(30); + $cache->prune(); + $this->assertTrue($this->isPruned($cache, 'foo')); + $this->assertTrue($this->isPruned($cache, 'bar')); + $this->assertTrue($this->isPruned($cache, 'baz')); + $this->assertTrue($this->isPruned($cache, 'qux')); + $cache->set('foo', 'foo-val'); $cache->set('bar', 'bar-val', new \DateInterval('PT20S')); $cache->set('baz', 'baz-val', new \DateInterval('PT40S')); diff --git a/src/Symfony/Component/Cache/Tests/Simple/ChainCacheTest.php b/src/Symfony/Component/Cache/Tests/Simple/ChainCacheTest.php index 282bb62a6530e..ab28e3bce7b9b 100644 --- a/src/Symfony/Component/Cache/Tests/Simple/ChainCacheTest.php +++ b/src/Symfony/Component/Cache/Tests/Simple/ChainCacheTest.php @@ -11,6 +11,8 @@ namespace Symfony\Component\Cache\Tests\Simple; +use Psr\SimpleCache\CacheInterface; +use Symfony\Component\Cache\PruneableInterface; use Symfony\Component\Cache\Simple\ArrayCache; use Symfony\Component\Cache\Simple\ChainCache; use Symfony\Component\Cache\Simple\FilesystemCache; @@ -40,6 +42,75 @@ public function testEmptyCachesException() */ public function testInvalidCacheException() { - new Chaincache(array(new \stdClass())); + new ChainCache(array(new \stdClass())); } + + public function testPrune() + { + if (isset($this->skippedTests[__FUNCTION__])) { + $this->markTestSkipped($this->skippedTests[__FUNCTION__]); + } + + $cache = new ChainCache(array( + $this->getPruneableMock(), + $this->getNonPruneableMock(), + $this->getPruneableMock(), + )); + $this->assertTrue($cache->prune()); + + $cache = new ChainCache(array( + $this->getPruneableMock(), + $this->getFailingPruneableMock(), + $this->getPruneableMock(), + )); + $this->assertFalse($cache->prune()); + } + + /** + * @return \PHPUnit_Framework_MockObject_MockObject|PruneableCacheInterface + */ + private function getPruneableMock() + { + $pruneable = $this + ->getMockBuilder(PruneableCacheInterface::class) + ->getMock(); + + $pruneable + ->expects($this->atLeastOnce()) + ->method('prune') + ->will($this->returnValue(true)); + + return $pruneable; + } + + /** + * @return \PHPUnit_Framework_MockObject_MockObject|PruneableCacheInterface + */ + private function getFailingPruneableMock() + { + $pruneable = $this + ->getMockBuilder(PruneableCacheInterface::class) + ->getMock(); + + $pruneable + ->expects($this->atLeastOnce()) + ->method('prune') + ->will($this->returnValue(false)); + + return $pruneable; + } + + /** + * @return \PHPUnit_Framework_MockObject_MockObject|CacheInterface + */ + private function getNonPruneableMock() + { + return $this + ->getMockBuilder(CacheInterface::class) + ->getMock(); + } +} + +interface PruneableCacheInterface extends PruneableInterface, CacheInterface +{ } diff --git a/src/Symfony/Component/Cache/Tests/Simple/PdoCacheTest.php b/src/Symfony/Component/Cache/Tests/Simple/PdoCacheTest.php index 47c0ee52d99ac..cf5730952dd84 100644 --- a/src/Symfony/Component/Cache/Tests/Simple/PdoCacheTest.php +++ b/src/Symfony/Component/Cache/Tests/Simple/PdoCacheTest.php @@ -12,12 +12,15 @@ namespace Symfony\Component\Cache\Tests\Simple; use Symfony\Component\Cache\Simple\PdoCache; +use Symfony\Component\Cache\Tests\Traits\PdoPruneableTrait; /** * @group time-sensitive */ class PdoCacheTest extends CacheTestCase { + use PdoPruneableTrait; + protected static $dbFile; public static function setupBeforeClass() diff --git a/src/Symfony/Component/Cache/Tests/Simple/PdoDbalCacheTest.php b/src/Symfony/Component/Cache/Tests/Simple/PdoDbalCacheTest.php index 51a10af30663b..0c40c04a2cae7 100644 --- a/src/Symfony/Component/Cache/Tests/Simple/PdoDbalCacheTest.php +++ b/src/Symfony/Component/Cache/Tests/Simple/PdoDbalCacheTest.php @@ -13,12 +13,15 @@ use Doctrine\DBAL\DriverManager; use Symfony\Component\Cache\Simple\PdoCache; +use Symfony\Component\Cache\Tests\Traits\PdoPruneableTrait; /** * @group time-sensitive */ class PdoDbalCacheTest extends CacheTestCase { + use PdoPruneableTrait; + protected static $dbFile; public static function setupBeforeClass() diff --git a/src/Symfony/Component/Cache/Tests/Traits/PdoPruneableTrait.php b/src/Symfony/Component/Cache/Tests/Traits/PdoPruneableTrait.php new file mode 100644 index 0000000000000..a9c459fb87171 --- /dev/null +++ b/src/Symfony/Component/Cache/Tests/Traits/PdoPruneableTrait.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\Component\Cache\Tests\Traits; + +trait PdoPruneableTrait +{ + protected function isPruned($cache, $name) + { + $o = new \ReflectionObject($cache); + + if (!$o->hasMethod('getConnection')) { + self::fail('Cache does not have "getConnection()" method.'); + } + + $getPdoConn = $o->getMethod('getConnection'); + $getPdoConn->setAccessible(true); + + /** @var \Doctrine\DBAL\Statement $select */ + $select = $getPdoConn->invoke($cache)->prepare('SELECT 1 FROM cache_items WHERE item_id LIKE :id'); + $select->bindValue(':id', sprintf('%%%s', $name)); + $select->execute(); + + return 0 === count($select->fetchAll(\PDO::FETCH_COLUMN)); + } +} diff --git a/src/Symfony/Component/Cache/Traits/PdoTrait.php b/src/Symfony/Component/Cache/Traits/PdoTrait.php index 20d1eee1bd1b6..dd8c97d8ab1b2 100644 --- a/src/Symfony/Component/Cache/Traits/PdoTrait.php +++ b/src/Symfony/Component/Cache/Traits/PdoTrait.php @@ -34,6 +34,7 @@ trait PdoTrait private $username = ''; private $password = ''; private $connectionOptions = array(); + private $namespace; private function init($connOrDsn, $namespace, $defaultLifetime, array $options) { @@ -63,6 +64,7 @@ private function init($connOrDsn, $namespace, $defaultLifetime, array $options) $this->username = isset($options['db_username']) ? $options['db_username'] : $this->username; $this->password = isset($options['db_password']) ? $options['db_password'] : $this->password; $this->connectionOptions = isset($options['db_connection_options']) ? $options['db_connection_options'] : $this->connectionOptions; + $this->namespace = $namespace; parent::__construct($namespace, $defaultLifetime); } @@ -137,6 +139,27 @@ public function createTable() $conn->exec($sql); } + /** + * {@inheritdoc} + */ + public function prune() + { + $deleteSql = "DELETE FROM $this->table WHERE $this->lifetimeCol + $this->timeCol <= :time"; + + if ('' !== $this->namespace) { + $deleteSql .= " AND $this->idCol LIKE :namespace"; + } + + $delete = $this->getConnection()->prepare($deleteSql); + $delete->bindValue(':time', time(), \PDO::PARAM_INT); + + if ('' !== $this->namespace) { + $delete->bindValue(':namespace', sprintf('%s%%', $this->namespace), \PDO::PARAM_STR); + } + + return $delete->execute(); + } + /** * {@inheritdoc} */ From fa3ab1fac857b6723245201253d6cecf34a5cc4a Mon Sep 17 00:00:00 2001 From: Robin Chalas Date: Wed, 30 Aug 2017 23:53:09 +0200 Subject: [PATCH 0728/1099] Remove php <7.1 code --- .../Component/Console/Tests/ApplicationTest.php | 10 ---------- .../PropertyAccess/Tests/PropertyAccessorTest.php | 9 --------- 2 files changed, 19 deletions(-) diff --git a/src/Symfony/Component/Console/Tests/ApplicationTest.php b/src/Symfony/Component/Console/Tests/ApplicationTest.php index 896beb68cd035..840213b042509 100644 --- a/src/Symfony/Component/Console/Tests/ApplicationTest.php +++ b/src/Symfony/Component/Console/Tests/ApplicationTest.php @@ -1137,9 +1137,6 @@ public function testRunDispatchesAllEventsWithExceptionInListener() $this->assertContains('before.error.after.', $tester->getDisplay()); } - /** - * @requires PHP 7 - */ public function testRunWithError() { $application = new Application(); @@ -1230,7 +1227,6 @@ public function testErrorIsRethrownIfNotHandledByConsoleErrorEvent() } /** - * @requires PHP 7 * @expectedException \LogicException * @expectedExceptionMessage error */ @@ -1252,9 +1248,6 @@ public function testRunWithErrorAndDispatcher() $this->assertContains('before.dym.error.after.', $tester->getDisplay(), 'The PHP Error did not dispached events'); } - /** - * @requires PHP 7 - */ public function testRunDispatchesAllEventsWithError() { $application = new Application(); @@ -1272,9 +1265,6 @@ public function testRunDispatchesAllEventsWithError() $this->assertContains('before.dym.error.after.', $tester->getDisplay(), 'The PHP Error did not dispached events'); } - /** - * @requires PHP 7 - */ public function testRunWithErrorFailingStatusCode() { $application = new Application(); diff --git a/src/Symfony/Component/PropertyAccess/Tests/PropertyAccessorTest.php b/src/Symfony/Component/PropertyAccess/Tests/PropertyAccessorTest.php index b8356500a5881..7e8f6cbd82c3c 100644 --- a/src/Symfony/Component/PropertyAccess/Tests/PropertyAccessorTest.php +++ b/src/Symfony/Component/PropertyAccess/Tests/PropertyAccessorTest.php @@ -581,9 +581,6 @@ public function testThrowTypeErrorWithInterface() $this->propertyAccessor->setValue($object, 'countable', 'This is a string, \Countable expected.'); } - /** - * @requires PHP 7.0 - */ public function testAnonymousClassRead() { $value = 'bar'; @@ -595,9 +592,6 @@ public function testAnonymousClassRead() $this->assertEquals($value, $propertyAccessor->getValue($obj, 'foo')); } - /** - * @requires PHP 7.0 - */ public function testAnonymousClassWrite() { $value = 'bar'; @@ -642,7 +636,6 @@ public function setFoo($foo) } /** - * @requires PHP 7.0 * @expectedException \TypeError */ public function testThrowTypeErrorInsideSetterCall() @@ -653,8 +646,6 @@ public function testThrowTypeErrorInsideSetterCall() } /** - * @requires PHP 7 - * * @expectedException \TypeError */ public function testDoNotDiscardReturnTypeError() From 38909963921eb3e33c077281fd396cb74b894dbe Mon Sep 17 00:00:00 2001 From: Roland Franssen Date: Thu, 31 Aug 2017 14:57:27 +0200 Subject: [PATCH 0729/1099] [DI] Add upgrade note about case insenstive params --- UPGRADE-3.4.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/UPGRADE-3.4.md b/UPGRADE-3.4.md index f72652fbe4715..5a677088acd9f 100644 --- a/UPGRADE-3.4.md +++ b/UPGRADE-3.4.md @@ -50,6 +50,8 @@ DependencyInjection * Top-level anonymous services in XML are deprecated and will throw an exception in Symfony 4.0. + * Case insensitivity of parameter names is deprecated and will be removed in 4.0. + Debug ----- From ed3df04da8c3119068a5f5eb0a1d62699ea3908e Mon Sep 17 00:00:00 2001 From: Roland Franssen Date: Thu, 31 Aug 2017 15:22:59 +0200 Subject: [PATCH 0730/1099] [DI] Remove case insensitive parameter names --- UPGRADE-4.0.md | 2 +- .../DependencyInjection/CHANGELOG.md | 1 + .../DependencyInjection/Dumper/PhpDumper.php | 40 +++---------------- .../ParameterBag/ParameterBag.php | 34 ++++------------ .../Tests/ContainerBuilderTest.php | 8 +--- .../Tests/ContainerTest.php | 9 +---- .../Tests/Dumper/PhpDumperTest.php | 27 +------------ .../Tests/Fixtures/php/services10.php | 26 ++---------- .../Tests/Fixtures/php/services12.php | 26 ++---------- .../Tests/Fixtures/php/services26.php | 28 ++----------- .../Tests/Fixtures/php/services8.php | 26 ++---------- .../Tests/Fixtures/php/services9_as_files.txt | 26 ++---------- .../Tests/Fixtures/php/services9_compiled.php | 26 ++---------- .../Fixtures/php/services_array_params.php | 26 ++---------- .../Tests/ParameterBag/ParameterBagTest.php | 16 ++------ 15 files changed, 52 insertions(+), 269 deletions(-) diff --git a/UPGRADE-4.0.md b/UPGRADE-4.0.md index f94259329e5a0..812d2ba5e90fd 100644 --- a/UPGRADE-4.0.md +++ b/UPGRADE-4.0.md @@ -146,7 +146,7 @@ DependencyInjection ``` - * Service identifiers are now case sensitive. + * Service identifiers and parameter names are now case sensitive. * The `Reference` and `Alias` classes do not make service identifiers lowercase anymore. diff --git a/src/Symfony/Component/DependencyInjection/CHANGELOG.md b/src/Symfony/Component/DependencyInjection/CHANGELOG.md index 1e51a5c927f29..26df6aa372f7f 100644 --- a/src/Symfony/Component/DependencyInjection/CHANGELOG.md +++ b/src/Symfony/Component/DependencyInjection/CHANGELOG.md @@ -21,6 +21,7 @@ CHANGELOG * removed silent behavior for unused attributes and elements * removed support for setting and accessing private services in `Container` * removed support for setting pre-defined services in `Container` + * removed support for case insensitivity of parameter names 3.4.0 ----- diff --git a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php index 93a0ccda3eeba..0c955341a46e8 100644 --- a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php +++ b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php @@ -1039,15 +1039,11 @@ private function addDefaultParametersMethod() $php = array(); $dynamicPhp = array(); - $normalizedParams = array(); foreach ($this->container->getParameterBag()->all() as $key => $value) { if ($key !== $resolvedKey = $this->container->resolveEnvPlaceholders($key)) { throw new InvalidArgumentException(sprintf('Parameter name cannot use env parameters: %s.', $resolvedKey)); } - if ($key !== $lcKey = strtolower($key)) { - $normalizedParams[] = sprintf(' %s => %s,', $this->export($lcKey), $this->export($key)); - } $export = $this->exportParameters(array($value)); $export = explode('0 => ', substr(rtrim($export, " )\n"), 7, -1), 2); @@ -1066,12 +1062,10 @@ private function addDefaultParametersMethod() */ public function getParameter($name) { - if (!(isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters))) { - $name = $this->normalizeParameterName($name); + $name = (string) $name; - if (!(isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters))) { - throw new InvalidArgumentException(sprintf('The parameter "%s" must be defined.', $name)); - } + if (!(isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters))) { + throw new InvalidArgumentException(sprintf('The parameter "%s" must be defined.', $name)); } if (isset($this->loadedDynamicParameters[$name])) { return $this->loadedDynamicParameters[$name] ? $this->dynamicParameters[$name] : $this->getDynamicParameter($name); @@ -1085,7 +1079,7 @@ public function getParameter($name) */ public function hasParameter($name) { - $name = $this->normalizeParameterName($name); + $name = (string) $name; return isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters); } @@ -1155,30 +1149,6 @@ private function getDynamicParameter(\$name) {$getDynamicParameter} } - -EOF; - - $code .= ' private $normalizedParameterNames = '.($normalizedParams ? sprintf("array(\n%s\n );", implode("\n", $normalizedParams)) : 'array();')."\n"; - $code .= <<<'EOF' - - private function normalizeParameterName($name) - { - if (isset($this->normalizedParameterNames[$normalizedName = strtolower($name)]) || isset($this->parameters[$normalizedName]) || array_key_exists($normalizedName, $this->parameters)) { - $normalizedName = isset($this->normalizedParameterNames[$normalizedName]) ? $this->normalizedParameterNames[$normalizedName] : $normalizedName; - if ((string) $name !== $normalizedName) { - @trigger_error(sprintf('Parameter names will be made case sensitive in Symfony 4.0. Using "%s" instead of "%s" is deprecated since version 3.4.', $name, $normalizedName), E_USER_DEPRECATED); - } - } else { - $normalizedName = $this->normalizedParameterNames[$normalizedName] = (string) $name; - } - - return $normalizedName; - } - -EOF; - - $code .= <<docStar} * Gets the default parameters. * @@ -1643,7 +1613,7 @@ private function getServiceCall($id, Reference $reference = null) if ('service_container' === $id) { return '$this'; } - + if ($this->container->hasDefinition($id)) { $definition = $this->container->getDefinition($id); diff --git a/src/Symfony/Component/DependencyInjection/ParameterBag/ParameterBag.php b/src/Symfony/Component/DependencyInjection/ParameterBag/ParameterBag.php index 1a9ca6fa4d4fb..d623428ef2abb 100644 --- a/src/Symfony/Component/DependencyInjection/ParameterBag/ParameterBag.php +++ b/src/Symfony/Component/DependencyInjection/ParameterBag/ParameterBag.php @@ -25,8 +25,6 @@ class ParameterBag implements ParameterBagInterface protected $parameters = array(); protected $resolved = false; - private $normalizedNames = array(); - /** * @param array $parameters An array of parameters */ @@ -68,7 +66,7 @@ public function all() */ public function get($name) { - $name = $this->normalizeName($name); + $name = (string) $name; if (!array_key_exists($name, $this->parameters)) { if (!$name) { @@ -113,7 +111,7 @@ public function get($name) */ public function set($name, $value) { - $this->parameters[$this->normalizeName($name)] = $value; + $this->parameters[(string) $name] = $value; } /** @@ -121,7 +119,7 @@ public function set($name, $value) */ public function has($name) { - return array_key_exists($this->normalizeName($name), $this->parameters); + return array_key_exists((string) $name, $this->parameters); } /** @@ -131,7 +129,7 @@ public function has($name) */ public function remove($name) { - unset($this->parameters[$this->normalizeName($name)]); + unset($this->parameters[(string) $name]); } /** @@ -208,13 +206,12 @@ public function resolveString($value, array $resolving = array()) // a non-string in a parameter value if (preg_match('/^%([^%\s]+)%$/', $value, $match)) { $key = $match[1]; - $lcKey = strtolower($key); // strtolower() to be removed in 4.0 - if (isset($resolving[$lcKey])) { + if (isset($resolving[$key])) { throw new ParameterCircularReferenceException(array_keys($resolving)); } - $resolving[$lcKey] = true; + $resolving[$key] = true; return $this->resolved ? $this->get($key) : $this->resolveValue($this->get($key), $resolving); } @@ -226,8 +223,7 @@ public function resolveString($value, array $resolving = array()) } $key = $match[1]; - $lcKey = strtolower($key); // strtolower() to be removed in 4.0 - if (isset($resolving[$lcKey])) { + if (isset($resolving[$key])) { throw new ParameterCircularReferenceException(array_keys($resolving)); } @@ -238,7 +234,7 @@ public function resolveString($value, array $resolving = array()) } $resolved = (string) $resolved; - $resolving[$lcKey] = true; + $resolving[$key] = true; return $this->isResolved() ? $resolved : $this->resolveString($resolved, $resolving); }, $value); @@ -290,18 +286,4 @@ public function unescapeValue($value) return $value; } - - private function normalizeName($name) - { - if (isset($this->normalizedNames[$normalizedName = strtolower($name)])) { - $normalizedName = $this->normalizedNames[$normalizedName]; - if ((string) $name !== $normalizedName) { - @trigger_error(sprintf('Parameter names will be made case sensitive in Symfony 4.0. Using "%s" instead of "%s" is deprecated since version 3.4.', $name, $normalizedName), E_USER_DEPRECATED); - } - } else { - $normalizedName = $this->normalizedNames[$normalizedName] = (string) $name; - } - - return $normalizedName; - } } diff --git a/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php b/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php index d48c2460dc2fc..ba8e28cec3711 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php @@ -1098,19 +1098,15 @@ public function testCaseSensitivity() $this->assertSame($container->get('fOO')->Foo->foo, $container->get('foo'), '->get() returns the service for the given id, case sensitively'); } - /** - * @group legacy - * @expectedDeprecation Parameter names will be made case sensitive in Symfony 4.0. Using "FOO" instead of "foo" is deprecated since version 3.4. - */ public function testParameterWithMixedCase() { - $container = new ContainerBuilder(new ParameterBag(array('foo' => 'bar'))); + $container = new ContainerBuilder(new ParameterBag(array('foo' => 'bar', 'FOO' => 'BAR'))); $container->register('foo', 'stdClass') ->setProperty('foo', '%FOO%'); $container->compile(); - $this->assertSame('bar', $container->get('foo')->foo); + $this->assertSame('BAR', $container->get('foo')->foo); } } diff --git a/src/Symfony/Component/DependencyInjection/Tests/ContainerTest.php b/src/Symfony/Component/DependencyInjection/Tests/ContainerTest.php index 30eefb5546d72..513dff8450779 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/ContainerTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/ContainerTest.php @@ -121,18 +121,13 @@ public function testGetSetParameter() } } - /** - * @group legacy - * @expectedDeprecation Parameter names will be made case sensitive in Symfony 4.0. Using "Foo" instead of "foo" is deprecated since version 3.4. - * @expectedDeprecation Parameter names will be made case sensitive in Symfony 4.0. Using "FOO" instead of "foo" is deprecated since version 3.4. - */ public function testGetSetParameterWithMixedCase() { $sc = new Container(new ParameterBag(array('foo' => 'bar'))); $sc->setParameter('Foo', 'baz1'); - $this->assertEquals('baz1', $sc->getParameter('foo'), '->setParameter() converts the key to lowercase'); - $this->assertEquals('baz1', $sc->getParameter('FOO'), '->getParameter() converts the key to lowercase'); + $this->assertEquals('bar', $sc->getParameter('foo')); + $this->assertEquals('baz1', $sc->getParameter('Foo')); } public function testGetServiceIds() diff --git a/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php b/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php index 47356e2d5c8a8..af60d67ca23e8 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php @@ -651,12 +651,6 @@ public function testPrivateServiceTriggersDeprecation() $container->get('bar'); } - /** - * @group legacy - * @expectedDeprecation Parameter names will be made case sensitive in Symfony 4.0. Using "foo" instead of "Foo" is deprecated since version 3.4. - * @expectedDeprecation Parameter names will be made case sensitive in Symfony 4.0. Using "FOO" instead of "Foo" is deprecated since version 3.4. - * @expectedDeprecation Parameter names will be made case sensitive in Symfony 4.0. Using "bar" instead of "BAR" is deprecated since version 3.4. - */ public function testParameterWithMixedCase() { $container = new ContainerBuilder(new ParameterBag(array('Foo' => 'bar', 'BAR' => 'foo'))); @@ -667,26 +661,7 @@ public function testParameterWithMixedCase() $container = new \Symfony_DI_PhpDumper_Test_Parameter_With_Mixed_Case(); - $this->assertSame('bar', $container->getParameter('foo')); - $this->assertSame('bar', $container->getParameter('FOO')); - $this->assertSame('foo', $container->getParameter('bar')); + $this->assertSame('bar', $container->getParameter('Foo')); $this->assertSame('foo', $container->getParameter('BAR')); } - - /** - * @group legacy - * @expectedDeprecation Parameter names will be made case sensitive in Symfony 4.0. Using "FOO" instead of "foo" is deprecated since version 3.4. - */ - public function testParameterWithLowerCase() - { - $container = new ContainerBuilder(new ParameterBag(array('foo' => 'bar'))); - $container->compile(); - - $dumper = new PhpDumper($container); - eval('?>'.$dumper->dump(array('class' => 'Symfony_DI_PhpDumper_Test_Parameter_With_Lower_Case'))); - - $container = new \Symfony_DI_PhpDumper_Test_Parameter_With_Lower_Case(); - - $this->assertSame('bar', $container->getParameter('FOO')); - } } diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services10.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services10.php index 582472b38bd7a..d914e82378567 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services10.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services10.php @@ -77,12 +77,10 @@ protected function getTestService() */ public function getParameter($name) { - if (!(isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters))) { - $name = $this->normalizeParameterName($name); + $name = (string) $name; - if (!(isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters))) { - throw new InvalidArgumentException(sprintf('The parameter "%s" must be defined.', $name)); - } + if (!(isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters))) { + throw new InvalidArgumentException(sprintf('The parameter "%s" must be defined.', $name)); } if (isset($this->loadedDynamicParameters[$name])) { return $this->loadedDynamicParameters[$name] ? $this->dynamicParameters[$name] : $this->getDynamicParameter($name); @@ -96,7 +94,7 @@ public function getParameter($name) */ public function hasParameter($name) { - $name = $this->normalizeParameterName($name); + $name = (string) $name; return isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters); } @@ -142,22 +140,6 @@ private function getDynamicParameter($name) throw new InvalidArgumentException(sprintf('The dynamic parameter "%s" must be defined.', $name)); } - private $normalizedParameterNames = array(); - - private function normalizeParameterName($name) - { - if (isset($this->normalizedParameterNames[$normalizedName = strtolower($name)]) || isset($this->parameters[$normalizedName]) || array_key_exists($normalizedName, $this->parameters)) { - $normalizedName = isset($this->normalizedParameterNames[$normalizedName]) ? $this->normalizedParameterNames[$normalizedName] : $normalizedName; - if ((string) $name !== $normalizedName) { - @trigger_error(sprintf('Parameter names will be made case sensitive in Symfony 4.0. Using "%s" instead of "%s" is deprecated since version 3.4.', $name, $normalizedName), E_USER_DEPRECATED); - } - } else { - $normalizedName = $this->normalizedParameterNames[$normalizedName] = (string) $name; - } - - return $normalizedName; - } - /** * Gets the default parameters. * diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services12.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services12.php index f5db7d75d4b43..6df51ea0899bb 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services12.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services12.php @@ -81,12 +81,10 @@ protected function getTestService() */ public function getParameter($name) { - if (!(isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters))) { - $name = $this->normalizeParameterName($name); + $name = (string) $name; - if (!(isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters))) { - throw new InvalidArgumentException(sprintf('The parameter "%s" must be defined.', $name)); - } + if (!(isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters))) { + throw new InvalidArgumentException(sprintf('The parameter "%s" must be defined.', $name)); } if (isset($this->loadedDynamicParameters[$name])) { return $this->loadedDynamicParameters[$name] ? $this->dynamicParameters[$name] : $this->getDynamicParameter($name); @@ -100,7 +98,7 @@ public function getParameter($name) */ public function hasParameter($name) { - $name = $this->normalizeParameterName($name); + $name = (string) $name; return isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters); } @@ -156,22 +154,6 @@ private function getDynamicParameter($name) return $this->dynamicParameters[$name] = $value; } - private $normalizedParameterNames = array(); - - private function normalizeParameterName($name) - { - if (isset($this->normalizedParameterNames[$normalizedName = strtolower($name)]) || isset($this->parameters[$normalizedName]) || array_key_exists($normalizedName, $this->parameters)) { - $normalizedName = isset($this->normalizedParameterNames[$normalizedName]) ? $this->normalizedParameterNames[$normalizedName] : $normalizedName; - if ((string) $name !== $normalizedName) { - @trigger_error(sprintf('Parameter names will be made case sensitive in Symfony 4.0. Using "%s" instead of "%s" is deprecated since version 3.4.', $name, $normalizedName), E_USER_DEPRECATED); - } - } else { - $normalizedName = $this->normalizedParameterNames[$normalizedName] = (string) $name; - } - - return $normalizedName; - } - /** * Gets the default parameters. * diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services26.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services26.php index f7eb32e55e75f..5d5978f1fcf45 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services26.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services26.php @@ -79,12 +79,10 @@ protected function getTestService() */ public function getParameter($name) { - if (!(isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters))) { - $name = $this->normalizeParameterName($name); + $name = (string) $name; - if (!(isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters))) { - throw new InvalidArgumentException(sprintf('The parameter "%s" must be defined.', $name)); - } + if (!(isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters))) { + throw new InvalidArgumentException(sprintf('The parameter "%s" must be defined.', $name)); } if (isset($this->loadedDynamicParameters[$name])) { return $this->loadedDynamicParameters[$name] ? $this->dynamicParameters[$name] : $this->getDynamicParameter($name); @@ -98,7 +96,7 @@ public function getParameter($name) */ public function hasParameter($name) { - $name = $this->normalizeParameterName($name); + $name = (string) $name; return isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters); } @@ -152,24 +150,6 @@ private function getDynamicParameter($name) return $this->dynamicParameters[$name] = $value; } - private $normalizedParameterNames = array( - 'env(foo)' => 'env(FOO)', - ); - - private function normalizeParameterName($name) - { - if (isset($this->normalizedParameterNames[$normalizedName = strtolower($name)]) || isset($this->parameters[$normalizedName]) || array_key_exists($normalizedName, $this->parameters)) { - $normalizedName = isset($this->normalizedParameterNames[$normalizedName]) ? $this->normalizedParameterNames[$normalizedName] : $normalizedName; - if ((string) $name !== $normalizedName) { - @trigger_error(sprintf('Parameter names will be made case sensitive in Symfony 4.0. Using "%s" instead of "%s" is deprecated since version 3.4.', $name, $normalizedName), E_USER_DEPRECATED); - } - } else { - $normalizedName = $this->normalizedParameterNames[$normalizedName] = (string) $name; - } - - return $normalizedName; - } - /** * Gets the default parameters. * diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services8.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services8.php index bbd0b34c58f3c..0344b03935341 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services8.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services8.php @@ -64,12 +64,10 @@ public function isCompiled() */ public function getParameter($name) { - if (!(isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters))) { - $name = $this->normalizeParameterName($name); + $name = (string) $name; - if (!(isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters))) { - throw new InvalidArgumentException(sprintf('The parameter "%s" must be defined.', $name)); - } + if (!(isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters))) { + throw new InvalidArgumentException(sprintf('The parameter "%s" must be defined.', $name)); } if (isset($this->loadedDynamicParameters[$name])) { return $this->loadedDynamicParameters[$name] ? $this->dynamicParameters[$name] : $this->getDynamicParameter($name); @@ -83,7 +81,7 @@ public function getParameter($name) */ public function hasParameter($name) { - $name = $this->normalizeParameterName($name); + $name = (string) $name; return isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters); } @@ -129,22 +127,6 @@ private function getDynamicParameter($name) throw new InvalidArgumentException(sprintf('The dynamic parameter "%s" must be defined.', $name)); } - private $normalizedParameterNames = array(); - - private function normalizeParameterName($name) - { - if (isset($this->normalizedParameterNames[$normalizedName = strtolower($name)]) || isset($this->parameters[$normalizedName]) || array_key_exists($normalizedName, $this->parameters)) { - $normalizedName = isset($this->normalizedParameterNames[$normalizedName]) ? $this->normalizedParameterNames[$normalizedName] : $normalizedName; - if ((string) $name !== $normalizedName) { - @trigger_error(sprintf('Parameter names will be made case sensitive in Symfony 4.0. Using "%s" instead of "%s" is deprecated since version 3.4.', $name, $normalizedName), E_USER_DEPRECATED); - } - } else { - $normalizedName = $this->normalizedParameterNames[$normalizedName] = (string) $name; - } - - return $normalizedName; - } - /** * Gets the default parameters. * diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_as_files.txt b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_as_files.txt index d5f8d4f65e0a1..66df2f0e0dcfb 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_as_files.txt +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_as_files.txt @@ -382,12 +382,10 @@ class Container%s extends Container */ public function getParameter($name) { - if (!(isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters))) { - $name = $this->normalizeParameterName($name); + $name = (string) $name; - if (!(isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters))) { - throw new InvalidArgumentException(sprintf('The parameter "%s" must be defined.', $name)); - } + if (!(isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters))) { + throw new InvalidArgumentException(sprintf('The parameter "%s" must be defined.', $name)); } if (isset($this->loadedDynamicParameters[$name])) { return $this->loadedDynamicParameters[$name] ? $this->dynamicParameters[$name] : $this->getDynamicParameter($name); @@ -401,7 +399,7 @@ class Container%s extends Container */ public function hasParameter($name) { - $name = $this->normalizeParameterName($name); + $name = (string) $name; return isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters); } @@ -447,22 +445,6 @@ class Container%s extends Container throw new InvalidArgumentException(sprintf('The dynamic parameter "%s" must be defined.', $name)); } - private $normalizedParameterNames = array(); - - private function normalizeParameterName($name) - { - if (isset($this->normalizedParameterNames[$normalizedName = strtolower($name)]) || isset($this->parameters[$normalizedName]) || array_key_exists($normalizedName, $this->parameters)) { - $normalizedName = isset($this->normalizedParameterNames[$normalizedName]) ? $this->normalizedParameterNames[$normalizedName] : $normalizedName; - if ((string) $name !== $normalizedName) { - @trigger_error(sprintf('Parameter names will be made case sensitive in Symfony 4.0. Using "%s" instead of "%s" is deprecated since version 3.4.', $name, $normalizedName), E_USER_DEPRECATED); - } - } else { - $normalizedName = $this->normalizedParameterNames[$normalizedName] = (string) $name; - } - - return $normalizedName; - } - /** * Gets the default parameters. * diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_compiled.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_compiled.php index 30f58e1d974fd..76470376239f3 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_compiled.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_compiled.php @@ -391,12 +391,10 @@ protected function getFactorySimpleService() */ public function getParameter($name) { - if (!(isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters))) { - $name = $this->normalizeParameterName($name); + $name = (string) $name; - if (!(isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters))) { - throw new InvalidArgumentException(sprintf('The parameter "%s" must be defined.', $name)); - } + if (!(isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters))) { + throw new InvalidArgumentException(sprintf('The parameter "%s" must be defined.', $name)); } if (isset($this->loadedDynamicParameters[$name])) { return $this->loadedDynamicParameters[$name] ? $this->dynamicParameters[$name] : $this->getDynamicParameter($name); @@ -410,7 +408,7 @@ public function getParameter($name) */ public function hasParameter($name) { - $name = $this->normalizeParameterName($name); + $name = (string) $name; return isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters); } @@ -456,22 +454,6 @@ private function getDynamicParameter($name) throw new InvalidArgumentException(sprintf('The dynamic parameter "%s" must be defined.', $name)); } - private $normalizedParameterNames = array(); - - private function normalizeParameterName($name) - { - if (isset($this->normalizedParameterNames[$normalizedName = strtolower($name)]) || isset($this->parameters[$normalizedName]) || array_key_exists($normalizedName, $this->parameters)) { - $normalizedName = isset($this->normalizedParameterNames[$normalizedName]) ? $this->normalizedParameterNames[$normalizedName] : $normalizedName; - if ((string) $name !== $normalizedName) { - @trigger_error(sprintf('Parameter names will be made case sensitive in Symfony 4.0. Using "%s" instead of "%s" is deprecated since version 3.4.', $name, $normalizedName), E_USER_DEPRECATED); - } - } else { - $normalizedName = $this->normalizedParameterNames[$normalizedName] = (string) $name; - } - - return $normalizedName; - } - /** * Gets the default parameters. * diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_array_params.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_array_params.php index bf9e7c1dcfffa..ae3da978af978 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_array_params.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_array_params.php @@ -85,12 +85,10 @@ protected function getBarService() */ public function getParameter($name) { - if (!(isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters))) { - $name = $this->normalizeParameterName($name); + $name = (string) $name; - if (!(isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters))) { - throw new InvalidArgumentException(sprintf('The parameter "%s" must be defined.', $name)); - } + if (!(isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters))) { + throw new InvalidArgumentException(sprintf('The parameter "%s" must be defined.', $name)); } if (isset($this->loadedDynamicParameters[$name])) { return $this->loadedDynamicParameters[$name] ? $this->dynamicParameters[$name] : $this->getDynamicParameter($name); @@ -104,7 +102,7 @@ public function getParameter($name) */ public function hasParameter($name) { - $name = $this->normalizeParameterName($name); + $name = (string) $name; return isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters); } @@ -160,22 +158,6 @@ private function getDynamicParameter($name) return $this->dynamicParameters[$name] = $value; } - private $normalizedParameterNames = array(); - - private function normalizeParameterName($name) - { - if (isset($this->normalizedParameterNames[$normalizedName = strtolower($name)]) || isset($this->parameters[$normalizedName]) || array_key_exists($normalizedName, $this->parameters)) { - $normalizedName = isset($this->normalizedParameterNames[$normalizedName]) ? $this->normalizedParameterNames[$normalizedName] : $normalizedName; - if ((string) $name !== $normalizedName) { - @trigger_error(sprintf('Parameter names will be made case sensitive in Symfony 4.0. Using "%s" instead of "%s" is deprecated since version 3.4.', $name, $normalizedName), E_USER_DEPRECATED); - } - } else { - $normalizedName = $this->normalizedParameterNames[$normalizedName] = (string) $name; - } - - return $normalizedName; - } - /** * Gets the default parameters. * diff --git a/src/Symfony/Component/DependencyInjection/Tests/ParameterBag/ParameterBagTest.php b/src/Symfony/Component/DependencyInjection/Tests/ParameterBag/ParameterBagTest.php index 3bac9ca64e20d..c53decf8f017d 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/ParameterBag/ParameterBagTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/ParameterBag/ParameterBagTest.php @@ -106,28 +106,20 @@ public function testHas() $this->assertFalse($bag->has('bar'), '->has() returns false if a parameter is not defined'); } - /** - * @group legacy - * @expectedDeprecation Parameter names will be made case sensitive in Symfony 4.0. Using "BAR" instead of "bar" is deprecated since version 3.4. - * @expectedDeprecation Parameter names will be made case sensitive in Symfony 4.0. Using "Foo" instead of "foo" is deprecated since version 3.4. - * @expectedDeprecation Parameter names will be made case sensitive in Symfony 4.0. Using "FOO" instead of "foo" is deprecated since version 3.4. - * @expectedDeprecation Parameter names will be made case sensitive in Symfony 4.0. Using "Foo" instead of "foo" is deprecated since version 3.4. - */ public function testMixedCase() { $bag = new ParameterBag(array( 'foo' => 'foo', 'bar' => 'bar', + 'BAR' => 'baz', )); $bag->remove('BAR'); - $this->assertEquals(array('foo' => 'foo'), $bag->all(), '->remove() converts key to lowercase before removing'); + $this->assertEquals(array('foo' => 'foo', 'bar' => 'bar'), $bag->all()); $bag->set('Foo', 'baz1'); - $this->assertEquals('baz1', $bag->get('foo'), '->set() converts the key to lowercase'); - $this->assertEquals('baz1', $bag->get('FOO'), '->get() converts the key to lowercase'); - - $this->assertTrue($bag->has('Foo'), '->has() converts the key to lowercase'); + $this->assertEquals('foo', $bag->get('foo')); + $this->assertEquals('baz1', $bag->get('Foo')); } public function testResolveValue() From c8b65aeb8b7e9c9d835897036854d0a7256804a7 Mon Sep 17 00:00:00 2001 From: Florent Mata Date: Wed, 30 Aug 2017 16:46:23 +0200 Subject: [PATCH 0731/1099] [ExpressionLanguage] throws an exception on calling uncallable method --- .../Component/ExpressionLanguage/Node/GetAttrNode.php | 5 ++++- .../Tests/ExpressionLanguageTest.php | 10 ++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/ExpressionLanguage/Node/GetAttrNode.php b/src/Symfony/Component/ExpressionLanguage/Node/GetAttrNode.php index b3f98bf565f08..23310e3e4abdf 100644 --- a/src/Symfony/Component/ExpressionLanguage/Node/GetAttrNode.php +++ b/src/Symfony/Component/ExpressionLanguage/Node/GetAttrNode.php @@ -77,8 +77,11 @@ public function evaluate($functions, $values) if (!is_object($obj)) { throw new \RuntimeException('Unable to get a property on a non-object.'); } + if (!is_callable($toCall = array($obj, $this->nodes['attribute']->attributes['value']))) { + throw new \RuntimeException(sprintf('Unable to call method "%s" of object "%s".', $this->nodes['attribute']->attributes['value'], get_class($obj))); + } - return call_user_func_array(array($obj, $this->nodes['attribute']->attributes['value']), $this->nodes['arguments']->evaluate($functions, $values)); + return call_user_func_array($toCall, $this->nodes['arguments']->evaluate($functions, $values)); case self::ARRAY_CALL: $array = $this->nodes['node']->evaluate($functions, $values); diff --git a/src/Symfony/Component/ExpressionLanguage/Tests/ExpressionLanguageTest.php b/src/Symfony/Component/ExpressionLanguage/Tests/ExpressionLanguageTest.php index 07f4b1e8a08cb..0ef278c901496 100644 --- a/src/Symfony/Component/ExpressionLanguage/Tests/ExpressionLanguageTest.php +++ b/src/Symfony/Component/ExpressionLanguage/Tests/ExpressionLanguageTest.php @@ -163,6 +163,16 @@ public function testRegisterAfterEval($registerCallback) $registerCallback($el); } + /** + * @expectedException \RuntimeException + * @expectedExceptionMessageRegExp /Unable to call method "\w+" of object "\w+"./ + */ + public function testCallBadCallable() + { + $el = new ExpressionLanguage(); + $el->evaluate('foo.myfunction()', array('foo' => new \stdClass())); + } + /** * @dataProvider getRegisterCallbacks * @expectedException \LogicException From fc44215e7030277e16a21eb7fc00d045557440f4 Mon Sep 17 00:00:00 2001 From: Gregor Harlan Date: Tue, 29 Aug 2017 19:06:07 +0200 Subject: [PATCH 0732/1099] [Security] add impersonator_user to "User was reloaded" log message --- .../Security/Http/Firewall/ContextListener.php | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/Security/Http/Firewall/ContextListener.php b/src/Symfony/Component/Security/Http/Firewall/ContextListener.php index 97abd4dce5622..cd26d83ef7291 100644 --- a/src/Symfony/Component/Security/Http/Firewall/ContextListener.php +++ b/src/Symfony/Component/Security/Http/Firewall/ContextListener.php @@ -23,6 +23,7 @@ use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; use Symfony\Component\Security\Core\Exception\UsernameNotFoundException; use Symfony\Component\Security\Core\Exception\UnsupportedUserException; +use Symfony\Component\Security\Core\Role\SwitchUserRole; use Symfony\Component\Security\Core\User\UserInterface; use Symfony\Component\Security\Core\User\UserProviderInterface; use Symfony\Component\EventDispatcher\EventDispatcherInterface; @@ -91,7 +92,10 @@ public function handle(GetResponseEvent $event) $token = unserialize($token); if (null !== $this->logger) { - $this->logger->debug('Read existing security token from the session.', array('key' => $this->sessionKey)); + $this->logger->debug('Read existing security token from the session.', array( + 'key' => $this->sessionKey, + 'token_class' => is_object($token) ? get_class($token) : null, + )); } if ($token instanceof TokenInterface) { @@ -169,7 +173,16 @@ protected function refreshUser(TokenInterface $token) $token->setUser($refreshedUser); if (null !== $this->logger) { - $this->logger->debug('User was reloaded from a user provider.', array('username' => $refreshedUser->getUsername(), 'provider' => get_class($provider))); + $context = array('provider' => get_class($provider), 'username' => $refreshedUser->getUsername()); + + foreach ($token->getRoles() as $role) { + if ($role instanceof SwitchUserRole) { + $context['impersonator_username'] = $role->getSource()->getUsername(); + break; + } + } + + $this->logger->debug('User was reloaded from a user provider.', $context); } return $token; From e1f9ff6cb51740f3826483f152de3534a4511f06 Mon Sep 17 00:00:00 2001 From: Robin Chalas Date: Thu, 31 Aug 2017 20:33:07 +0200 Subject: [PATCH 0733/1099] [FrameworkBundle] Fix form conflict rule --- 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 d70292ff7bf6f..afe1961d95670 100644 --- a/src/Symfony/Bundle/FrameworkBundle/composer.json +++ b/src/Symfony/Bundle/FrameworkBundle/composer.json @@ -65,7 +65,7 @@ "phpunit/phpunit": "<4.8.35|<5.4.3,>=5.0", "symfony/asset": "<3.3", "symfony/console": "<3.4", - "symfony/form": "<3.3", + "symfony/form": "<3.4", "symfony/property-info": "<3.3", "symfony/serializer": "<3.3", "symfony/translation": "<3.4", From 086e457eebba77d45bd0e69fbf215f629a943cdb Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Thu, 31 Aug 2017 20:43:21 +0200 Subject: [PATCH 0734/1099] fix merge --- src/Symfony/Component/Form/composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/Form/composer.json b/src/Symfony/Component/Form/composer.json index 52b187d746ec9..cf2d7ecbd306e 100644 --- a/src/Symfony/Component/Form/composer.json +++ b/src/Symfony/Component/Form/composer.json @@ -28,12 +28,12 @@ "symfony/validator": "~3.4|~4.0", "symfony/dependency-injection": "~3.4|~4.0", "symfony/config": "~3.4|~4.0", + "symfony/console": "~3.4|~4.0", "symfony/http-foundation": "~3.4|~4.0", "symfony/http-kernel": "~3.4|~4.0", "symfony/security-csrf": "~3.4|~4.0", "symfony/translation": "~3.4|~4.0", "symfony/var-dumper": "~3.4|~4.0" - "symfony/console": "~3.4|~4.0" }, "conflict": { "phpunit/phpunit": "<4.8.35|<5.4.3,>=5.0", From 64b3eeef4141ad5648e0bc564be2e18681702a0b Mon Sep 17 00:00:00 2001 From: Maxime Steinhausser Date: Thu, 31 Aug 2017 21:09:59 +0200 Subject: [PATCH 0735/1099] [Form] Fix Descriptor tests --- .../Fixtures/Descriptor/resolved_form_type_1.json | 1 - .../Fixtures/Descriptor/resolved_form_type_1.txt | 12 ++++++------ 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/src/Symfony/Component/Form/Tests/Fixtures/Descriptor/resolved_form_type_1.json b/src/Symfony/Component/Form/Tests/Fixtures/Descriptor/resolved_form_type_1.json index b0c083b5b71dc..acbb82aa8fe49 100644 --- a/src/Symfony/Component/Form/Tests/Fixtures/Descriptor/resolved_form_type_1.json +++ b/src/Symfony/Component/Form/Tests/Fixtures/Descriptor/resolved_form_type_1.json @@ -10,7 +10,6 @@ "choice_translation_domain", "choice_value", "choices", - "choices_as_values", "expanded", "group_by", "multiple", diff --git a/src/Symfony/Component/Form/Tests/Fixtures/Descriptor/resolved_form_type_1.txt b/src/Symfony/Component/Form/Tests/Fixtures/Descriptor/resolved_form_type_1.txt index 5f839b85ac6b0..9c0dff816b9c6 100644 --- a/src/Symfony/Component/Form/Tests/Fixtures/Descriptor/resolved_form_type_1.txt +++ b/src/Symfony/Component/Form/Tests/Fixtures/Descriptor/resolved_form_type_1.txt @@ -12,12 +12,12 @@ choice_translation_domain empty_data auto_initialize csrf_protection choice_value error_bubbling block_name csrf_token_id choices by_reference csrf_token_manager - choices_as_values data - expanded disabled - group_by inherit_data - multiple label - placeholder label_attr - preferred_choices label_format + expanded data + group_by disabled + multiple inherit_data + placeholder label + preferred_choices label_attr + label_format mapped method post_max_size_message From 6ce70e4bf98a193212d44fba95bbe2e61ad7b019 Mon Sep 17 00:00:00 2001 From: Robin Chalas Date: Sat, 5 Aug 2017 16:43:05 +0200 Subject: [PATCH 0736/1099] Add scalar typehints/return types on final/internal/private code --- .../Doctrine/Form/ChoiceList/IdReader.php | 6 +- .../SecurityBundle/Debug/WrappedListener.php | 4 +- .../Security/FirewallConfig.php | 63 ++----- .../Tests/Security/FirewallMapTest.php | 3 +- .../Component/Config/Loader/FileLoader.php | 6 +- .../Console/Event/ConsoleErrorEvent.php | 39 +--- .../Component/Console/Helper/ProgressBar.php | 172 +++++------------- .../Component/Console/Style/SymfonyStyle.php | 17 +- .../CssSelector/Node/AbstractNode.php | 2 +- .../CssSelector/Node/AttributeNode.php | 4 +- .../Component/CssSelector/Node/ClassNode.php | 4 +- .../CssSelector/Node/CombinedSelectorNode.php | 4 +- .../CssSelector/Node/ElementNode.php | 4 +- .../CssSelector/Node/FunctionNode.php | 4 +- .../Component/CssSelector/Node/HashNode.php | 4 +- .../CssSelector/Node/NegationNode.php | 4 +- .../CssSelector/Node/NodeInterface.php | 21 +-- .../Component/CssSelector/Node/PseudoNode.php | 4 +- .../CssSelector/Node/SelectorNode.php | 4 +- .../CssSelector/Node/Specificity.php | 23 +-- .../Parser/Handler/CommentHandler.php | 2 +- .../Parser/Handler/HandlerInterface.php | 2 +- .../Parser/Handler/HashHandler.php | 2 +- .../Parser/Handler/IdentifierHandler.php | 2 +- .../Parser/Handler/NumberHandler.php | 2 +- .../Parser/Handler/StringHandler.php | 2 +- .../Parser/Handler/WhitespaceHandler.php | 2 +- .../Component/CssSelector/Parser/Parser.php | 43 +---- .../CssSelector/Parser/ParserInterface.php | 2 +- .../Parser/Shortcut/ClassParser.php | 2 +- .../Parser/Shortcut/ElementParser.php | 2 +- .../Parser/Shortcut/EmptyStringParser.php | 2 +- .../Parser/Shortcut/HashParser.php | 2 +- .../Component/CssSelector/Parser/Token.php | 44 +---- .../Parser/Tokenizer/TokenizerEscaping.php | 24 +-- .../XPath/Extension/CombinationExtension.php | 4 +- .../CssSelector/XPath/Translator.php | 72 ++------ .../CssSelector/XPath/TranslatorInterface.php | 4 +- .../Component/CssSelector/XPath/XPathExpr.php | 39 +--- src/Symfony/Component/Dotenv/Dotenv.php | 6 +- .../ExpressionLanguage/ExpressionLanguage.php | 6 +- .../ExpressionLanguage/Node/UnaryNode.php | 4 +- src/Symfony/Component/Form/Forms.php | 4 +- .../Controller/ArgumentResolver.php | 4 +- .../AbstractSurrogateFragmentRenderer.php | 4 +- .../Fragment/HIncludeFragmentRenderer.php | 7 +- .../Component/HttpKernel/HttpKernel.php | 10 +- src/Symfony/Component/Inflector/Inflector.php | 4 +- .../Data/Provider/LanguageDataProvider.php | 2 +- .../DateFormat/AmPmTransformer.php | 6 +- .../DateFormat/DayOfWeekTransformer.php | 6 +- .../DateFormat/DayOfYearTransformer.php | 6 +- .../DateFormat/DayTransformer.php | 6 +- .../DateFormat/Hour1200Transformer.php | 8 +- .../DateFormat/Hour1201Transformer.php | 8 +- .../DateFormat/Hour2400Transformer.php | 8 +- .../DateFormat/Hour2401Transformer.php | 8 +- .../DateFormat/HourTransformer.php | 2 +- .../DateFormat/MinuteTransformer.php | 6 +- .../DateFormat/MonthTransformer.php | 6 +- .../DateFormat/QuarterTransformer.php | 6 +- .../DateFormat/SecondTransformer.php | 6 +- .../DateFormat/TimezoneTransformer.php | 6 +- .../DateFormatter/DateFormat/Transformer.php | 8 +- .../DateFormat/YearTransformer.php | 6 +- src/Symfony/Component/Intl/Locale.php | 8 +- .../Intl/ResourceBundle/LanguageBundle.php | 10 +- src/Symfony/Component/Ldap/Ldap.php | 2 +- src/Symfony/Component/Lock/Key.php | 29 +-- .../PropertyAccess/PropertyAccess.php | 9 +- .../Extractor/ReflectionExtractor.php | 24 ++- .../PropertyInfo/Util/PhpDocTypeHelper.php | 26 +-- .../Routing/Matcher/Dumper/DumperRoute.php | 22 +-- .../Matcher/Dumper/StaticPrefixCollection.php | 20 +- .../Routing/RouteCollectionBuilder.php | 4 +- .../RememberMe/PersistentToken.php | 13 +- .../Http/Firewall/ExceptionListener.php | 17 +- .../Component/Translation/Translator.php | 15 +- .../Component/Validator/Validation.php | 4 +- .../WebLink/HttpHeaderSerializer.php | 2 +- src/Symfony/Component/Workflow/Definition.php | 10 +- .../Workflow/Dumper/GraphvizDumper.php | 4 +- .../Workflow/EventListener/GuardListener.php | 2 +- src/Symfony/Component/Workflow/Registry.php | 2 +- .../ClassInstanceSupportStrategy.php | 5 +- .../Component/Yaml/Tag/TaggedValue.php | 14 +- 86 files changed, 304 insertions(+), 737 deletions(-) diff --git a/src/Symfony/Bridge/Doctrine/Form/ChoiceList/IdReader.php b/src/Symfony/Bridge/Doctrine/Form/ChoiceList/IdReader.php index 4140629d934b6..a04be3a7900a6 100644 --- a/src/Symfony/Bridge/Doctrine/Form/ChoiceList/IdReader.php +++ b/src/Symfony/Bridge/Doctrine/Form/ChoiceList/IdReader.php @@ -82,7 +82,7 @@ public function __construct(ObjectManager $om, ClassMetadata $classMetadata) * @return bool Returns `true` if the class has a single-column ID and * `false` otherwise. */ - public function isSingleId() + public function isSingleId(): bool { return $this->singleId; } @@ -93,7 +93,7 @@ public function isSingleId() * @return bool Returns `true` if the class has a single-column integer ID * and `false` otherwise. */ - public function isIntId() + public function isIntId(): bool { return $this->intId; } @@ -138,7 +138,7 @@ public function getIdValue($object) * * @return string The name of the ID field */ - public function getIdField() + public function getIdField(): string { return $this->idField; } diff --git a/src/Symfony/Bundle/SecurityBundle/Debug/WrappedListener.php b/src/Symfony/Bundle/SecurityBundle/Debug/WrappedListener.php index 435ecc5feb573..85878e2193882 100644 --- a/src/Symfony/Bundle/SecurityBundle/Debug/WrappedListener.php +++ b/src/Symfony/Bundle/SecurityBundle/Debug/WrappedListener.php @@ -56,12 +56,12 @@ public function __call($method, $arguments) return call_user_func_array(array($this->listener, $method), $arguments); } - public function getWrappedListener() + public function getWrappedListener(): ListenerInterface { return $this->listener; } - public function getInfo() + public function getInfo(): array { if (null === $this->stub) { $this->stub = self::$hasVarDumper ? new ClassStub(get_class($this->listener)) : get_class($this->listener); diff --git a/src/Symfony/Bundle/SecurityBundle/Security/FirewallConfig.php b/src/Symfony/Bundle/SecurityBundle/Security/FirewallConfig.php index 62317f625c271..308442810bba8 100644 --- a/src/Symfony/Bundle/SecurityBundle/Security/FirewallConfig.php +++ b/src/Symfony/Bundle/SecurityBundle/Security/FirewallConfig.php @@ -29,21 +29,7 @@ final class FirewallConfig private $listeners; private $switchUser; - /** - * @param string $name - * @param string $userChecker - * @param string|null $requestMatcher - * @param bool $securityEnabled - * @param bool $stateless - * @param string|null $provider - * @param string|null $context - * @param string|null $entryPoint - * @param string|null $accessDeniedHandler - * @param string|null $accessDeniedUrl - * @param string[] $listeners - * @param array|null $switchUser - */ - public function __construct($name, $userChecker, $requestMatcher = null, $securityEnabled = true, $stateless = false, $provider = null, $context = null, $entryPoint = null, $accessDeniedHandler = null, $accessDeniedUrl = null, $listeners = array(), $switchUser = null) + public function __construct(string $name, string $userChecker, string $requestMatcher = null, bool $securityEnabled = true, bool $stateless = false, string $provider = null, string $context = null, string $entryPoint = null, string $accessDeniedHandler = null, string $accessDeniedUrl = null, array $listeners = array(), $switchUser = null) { $this->name = $name; $this->userChecker = $userChecker; @@ -59,7 +45,7 @@ public function __construct($name, $userChecker, $requestMatcher = null, $securi $this->switchUser = $switchUser; } - public function getName() + public function getName(): string { return $this->name; } @@ -68,30 +54,27 @@ public function getName() * @return string|null The request matcher service id or null if neither the request matcher, pattern or host * options were provided */ - public function getRequestMatcher() + public function getRequestMatcher(): ?string { return $this->requestMatcher; } - public function isSecurityEnabled() + public function isSecurityEnabled(): bool { return $this->securityEnabled; } - public function allowsAnonymous() + public function allowsAnonymous(): bool { return in_array('anonymous', $this->listeners, true); } - public function isStateless() + public function isStateless(): bool { return $this->stateless; } - /** - * @return string|null The provider service id - */ - public function getProvider() + public function getProvider(): ?string { return $this->provider; } @@ -99,55 +82,37 @@ public function getProvider() /** * @return string|null The context key (will be null if the firewall is stateless) */ - public function getContext() + public function getContext(): ?string { return $this->context; } - /** - * @return string|null The entry_point service id if configured, null otherwise - */ - public function getEntryPoint() + public function getEntryPoint(): ?string { return $this->entryPoint; } - /** - * @return string The user_checker service id - */ - public function getUserChecker() + public function getUserChecker(): string { return $this->userChecker; } - /** - * @return string|null The access_denied_handler service id if configured, null otherwise - */ - public function getAccessDeniedHandler() + public function getAccessDeniedHandler(): ?string { return $this->accessDeniedHandler; } - /** - * @return string|null The access_denied_handler URL if configured, null otherwise - */ - public function getAccessDeniedUrl() + public function getAccessDeniedUrl(): ?string { return $this->accessDeniedUrl; } - /** - * @return string[] An array of listener keys - */ - public function getListeners() + public function getListeners(): array { return $this->listeners; } - /** - * @return array|null The switch_user parameters if configured, null otherwise - */ - public function getSwitchUser() + public function getSwitchUser(): ?array { return $this->switchUser; } diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Security/FirewallMapTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/Security/FirewallMapTest.php index f9047cfdd233e..3e6f0a1ac74c6 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/Security/FirewallMapTest.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/Security/FirewallMapTest.php @@ -18,7 +18,6 @@ use Symfony\Component\DependencyInjection\Container; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\RequestMatcherInterface; -use Symfony\Component\Security\Core\User\UserCheckerInterface; use Symfony\Component\Security\Http\Firewall\ExceptionListener; use Symfony\Component\Security\Http\Firewall\ListenerInterface; @@ -63,7 +62,7 @@ public function testGetListeners() $firewallContext = $this->getMockBuilder(FirewallContext::class)->disableOriginalConstructor()->getMock(); - $firewallConfig = new FirewallConfig('main', $this->getMockBuilder(UserCheckerInterface::class)->getMock()); + $firewallConfig = new FirewallConfig('main', 'user_checker'); $firewallContext->expects($this->once())->method('getConfig')->willReturn($firewallConfig); $listener = $this->getMockBuilder(ListenerInterface::class)->getMock(); diff --git a/src/Symfony/Component/Config/Loader/FileLoader.php b/src/Symfony/Component/Config/Loader/FileLoader.php index 02aa811fc5497..9fb5faa7a9bcd 100644 --- a/src/Symfony/Component/Config/Loader/FileLoader.php +++ b/src/Symfony/Component/Config/Loader/FileLoader.php @@ -81,7 +81,7 @@ public function getLocator() * @throws FileLoaderImportCircularReferenceException * @throws FileLocatorFileNotFoundException */ - public function import($resource, $type = null, $ignoreErrors = false, $sourceResource = null) + public function import($resource, $type = null, bool $ignoreErrors = false, $sourceResource = null) { if (is_string($resource) && strlen($resource) !== $i = strcspn($resource, '*?{[')) { $ret = array(); @@ -104,7 +104,7 @@ public function import($resource, $type = null, $ignoreErrors = false, $sourceRe /** * @internal */ - protected function glob($pattern, $recursive, &$resource = null, $ignoreErrors = false) + protected function glob(string $pattern, bool $recursive, &$resource = null, bool $ignoreErrors = false) { if (strlen($pattern) === $i = strcspn($pattern, '*?{[')) { $prefix = $pattern; @@ -138,7 +138,7 @@ protected function glob($pattern, $recursive, &$resource = null, $ignoreErrors = } } - private function doImport($resource, $type = null, $ignoreErrors = false, $sourceResource = null) + private function doImport($resource, $type = null, bool $ignoreErrors = false, $sourceResource = null) { try { $loader = $this->resolve($resource, $type); diff --git a/src/Symfony/Component/Console/Event/ConsoleErrorEvent.php b/src/Symfony/Component/Console/Event/ConsoleErrorEvent.php index 49edb723d212d..038d97af8aed7 100644 --- a/src/Symfony/Component/Console/Event/ConsoleErrorEvent.php +++ b/src/Symfony/Component/Console/Event/ConsoleErrorEvent.php @@ -12,7 +12,6 @@ namespace Symfony\Component\Console\Event; use Symfony\Component\Console\Command\Command; -use Symfony\Component\Console\Exception\InvalidArgumentException; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; @@ -26,57 +25,33 @@ final class ConsoleErrorEvent extends ConsoleEvent private $error; private $exitCode; - public function __construct(InputInterface $input, OutputInterface $output, $error, Command $command = null) + public function __construct(InputInterface $input, OutputInterface $output, \Throwable $error, Command $command = null) { parent::__construct($command, $input, $output); - $this->setError($error); + $this->error = $error; } - /** - * Returns the thrown error/exception. - * - * @return \Throwable - */ - public function getError() + public function getError(): \Throwable { return $this->error; } - /** - * Replaces the thrown error/exception. - * - * @param \Throwable $error - */ - public function setError($error) + public function setError(\Throwable $error): void { - if (!$error instanceof \Throwable && !$error instanceof \Exception) { - throw new InvalidArgumentException(sprintf('The error passed to ConsoleErrorEvent must be an instance of \Throwable or \Exception, "%s" was passed instead.', is_object($error) ? get_class($error) : gettype($error))); - } - $this->error = $error; } - /** - * Sets the exit code. - * - * @param int $exitCode The command exit code - */ - public function setExitCode($exitCode) + public function setExitCode(int $exitCode): void { - $this->exitCode = (int) $exitCode; + $this->exitCode = $exitCode; $r = new \ReflectionProperty($this->error, 'code'); $r->setAccessible(true); $r->setValue($this->error, $this->exitCode); } - /** - * Gets the exit code. - * - * @return int The command exit code - */ - public function getExitCode() + public function getExitCode(): int { return null !== $this->exitCode ? $this->exitCode : ($this->error->getCode() ?: 1); } diff --git a/src/Symfony/Component/Console/Helper/ProgressBar.php b/src/Symfony/Component/Console/Helper/ProgressBar.php index 31c49ef730f02..6177a87a8322d 100644 --- a/src/Symfony/Component/Console/Helper/ProgressBar.php +++ b/src/Symfony/Component/Console/Helper/ProgressBar.php @@ -55,7 +55,7 @@ final class ProgressBar * @param OutputInterface $output An OutputInterface instance * @param int $max Maximum steps (0 if unknown) */ - public function __construct(OutputInterface $output, $max = 0) + public function __construct(OutputInterface $output, int $max = 0) { if ($output instanceof ConsoleOutputInterface) { $output = $output->getErrorOutput(); @@ -84,7 +84,7 @@ public function __construct(OutputInterface $output, $max = 0) * @param string $name The placeholder name (including the delimiter char like %) * @param callable $callable A PHP callable */ - public static function setPlaceholderFormatterDefinition($name, callable $callable) + public static function setPlaceholderFormatterDefinition(string $name, callable $callable): void { if (!self::$formatters) { self::$formatters = self::initPlaceholderFormatters(); @@ -100,7 +100,7 @@ public static function setPlaceholderFormatterDefinition($name, callable $callab * * @return callable|null A PHP callable */ - public static function getPlaceholderFormatterDefinition($name) + public static function getPlaceholderFormatterDefinition(string $name): ?callable { if (!self::$formatters) { self::$formatters = self::initPlaceholderFormatters(); @@ -117,7 +117,7 @@ public static function getPlaceholderFormatterDefinition($name) * @param string $name The format name * @param string $format A format string */ - public static function setFormatDefinition($name, $format) + public static function setFormatDefinition(string $name, string $format): void { if (!self::$formats) { self::$formats = self::initFormats(); @@ -133,7 +133,7 @@ public static function setFormatDefinition($name, $format) * * @return string|null A format string */ - public static function getFormatDefinition($name) + public static function getFormatDefinition(string $name): ?string { if (!self::$formats) { self::$formats = self::initFormats(); @@ -152,102 +152,57 @@ public static function getFormatDefinition($name) * @param string $message The text to associate with the placeholder * @param string $name The name of the placeholder */ - public function setMessage($message, $name = 'message') + public function setMessage(string $message, string $name = 'message') { $this->messages[$name] = $message; } - public function getMessage($name = 'message') + public function getMessage(string $name = 'message') { return $this->messages[$name]; } - /** - * Gets the progress bar start time. - * - * @return int The progress bar start time - */ - public function getStartTime() + public function getStartTime(): int { return $this->startTime; } - /** - * Gets the progress bar maximal steps. - * - * @return int The progress bar max steps - */ - public function getMaxSteps() + public function getMaxSteps(): int { return $this->max; } - /** - * Gets the current step position. - * - * @return int The progress bar step - */ - public function getProgress() + public function getProgress(): int { return $this->step; } - /** - * Gets the progress bar step width. - * - * @return int The progress bar step width - */ - private function getStepWidth() + private function getStepWidth(): int { return $this->stepWidth; } - /** - * Gets the current progress bar percent. - * - * @return float The current progress bar percent - */ - public function getProgressPercent() + public function getProgressPercent(): float { return $this->percent; } - /** - * Sets the progress bar width. - * - * @param int $size The progress bar size - */ - public function setBarWidth($size) + public function setBarWidth(int $size) { - $this->barWidth = max(1, (int) $size); + $this->barWidth = max(1, $size); } - /** - * Gets the progress bar width. - * - * @return int The progress bar size - */ - public function getBarWidth() + public function getBarWidth(): int { return $this->barWidth; } - /** - * Sets the bar character. - * - * @param string $char A character - */ - public function setBarCharacter($char) + public function setBarCharacter(string $char) { $this->barChar = $char; } - /** - * Gets the bar character. - * - * @return string A character - */ - public function getBarCharacter() + public function getBarCharacter(): string { if (null === $this->barChar) { return $this->max ? '=' : $this->emptyBarChar; @@ -256,52 +211,27 @@ public function getBarCharacter() return $this->barChar; } - /** - * Sets the empty bar character. - * - * @param string $char A character - */ - public function setEmptyBarCharacter($char) + public function setEmptyBarCharacter(string $char) { $this->emptyBarChar = $char; } - /** - * Gets the empty bar character. - * - * @return string A character - */ - public function getEmptyBarCharacter() + public function getEmptyBarCharacter(): string { return $this->emptyBarChar; } - /** - * Sets the progress bar character. - * - * @param string $char A character - */ - public function setProgressCharacter($char) + public function setProgressCharacter(string $char) { $this->progressChar = $char; } - /** - * Gets the progress bar character. - * - * @return string A character - */ - public function getProgressCharacter() + public function getProgressCharacter(): string { return $this->progressChar; } - /** - * Sets the progress bar format. - * - * @param string $format The format - */ - public function setFormat($format) + public function setFormat(string $format) { $this->format = null; $this->internalFormat = $format; @@ -312,9 +242,9 @@ public function setFormat($format) * * @param int|float $freq The frequency in steps */ - public function setRedrawFrequency($freq) + public function setRedrawFrequency(int $freq) { - $this->redrawFreq = max((int) $freq, 1); + $this->redrawFreq = max($freq, 1); } /** @@ -322,7 +252,7 @@ public function setRedrawFrequency($freq) * * @param int|null $max Number of steps to complete the bar (0 if indeterminate), null to leave unchanged */ - public function start($max = null) + public function start(int $max = null) { $this->startTime = time(); $this->step = 0; @@ -340,7 +270,7 @@ public function start($max = null) * * @param int $step Number of steps to advance */ - public function advance($step = 1) + public function advance(int $step = 1) { $this->setProgress($this->step + $step); } @@ -350,20 +280,13 @@ public function advance($step = 1) * * @param bool $overwrite */ - public function setOverwrite($overwrite) + public function setOverwrite(bool $overwrite) { - $this->overwrite = (bool) $overwrite; + $this->overwrite = $overwrite; } - /** - * Sets the current progress. - * - * @param int $step The current progress - */ - public function setProgress($step) + public function setProgress(int $step) { - $step = (int) $step; - if ($this->max && $step > $this->max) { $this->max = $step; } elseif ($step < 0) { @@ -382,7 +305,7 @@ public function setProgress($step) /** * Finishes the progress output. */ - public function finish() + public function finish(): void { if (!$this->max) { $this->max = $this->step; @@ -399,7 +322,7 @@ public function finish() /** * Outputs the current progress string. */ - public function display() + public function display(): void { if (OutputInterface::VERBOSITY_QUIET === $this->output->getVerbosity()) { return; @@ -419,7 +342,7 @@ public function display() * while a progress bar is running. * Call display() to show the progress bar again. */ - public function clear() + public function clear(): void { if (!$this->overwrite) { return; @@ -432,12 +355,7 @@ public function clear() $this->overwrite(''); } - /** - * Sets the progress bar format. - * - * @param string $format The format - */ - private function setRealFormat($format) + private function setRealFormat(string $format) { // try to use the _nomax variant if available if (!$this->max && null !== self::getFormatDefinition($format.'_nomax')) { @@ -451,15 +369,10 @@ private function setRealFormat($format) $this->formatLineCount = substr_count($this->format, "\n"); } - /** - * Sets the progress bar maximal steps. - * - * @param int $max The progress bar max steps - */ - private function setMaxSteps($max) + private function setMaxSteps(int $max) { - $this->max = max(0, (int) $max); - $this->stepWidth = $this->max ? Helper::strlen($this->max) : 4; + $this->max = max(0, $max); + $this->stepWidth = $this->max ? Helper::strlen((string) $this->max) : 4; } /** @@ -467,7 +380,7 @@ private function setMaxSteps($max) * * @param string $message The message */ - private function overwrite($message) + private function overwrite(string $message): void { if ($this->overwrite) { if (!$this->firstRun) { @@ -491,7 +404,7 @@ private function overwrite($message) $this->output->write($message); } - private function determineBestFormat() + private function determineBestFormat(): string { switch ($this->output->getVerbosity()) { // OutputInterface::VERBOSITY_QUIET: display is disabled anyway @@ -506,7 +419,7 @@ private function determineBestFormat() } } - private static function initPlaceholderFormatters() + private static function initPlaceholderFormatters(): array { return array( 'bar' => function (ProgressBar $bar, OutputInterface $output) { @@ -563,7 +476,7 @@ private static function initPlaceholderFormatters() ); } - private static function initFormats() + private static function initFormats(): array { return array( 'normal' => ' %current%/%max% [%bar%] %percent:3s%%', @@ -580,10 +493,7 @@ private static function initFormats() ); } - /** - * @return string - */ - private function buildLine() + private function buildLine(): string { $regex = "{%([a-z\-_]+)(?:\:([^%]+))?%}i"; $callback = function ($matches) { diff --git a/src/Symfony/Component/Console/Style/SymfonyStyle.php b/src/Symfony/Component/Console/Style/SymfonyStyle.php index a86796176717e..c15ae4660001f 100644 --- a/src/Symfony/Component/Console/Style/SymfonyStyle.php +++ b/src/Symfony/Component/Console/Style/SymfonyStyle.php @@ -344,10 +344,7 @@ public function getErrorStyle() return new self($this->input, $this->getErrorOutput()); } - /** - * @return ProgressBar - */ - private function getProgressBar() + private function getProgressBar(): ProgressBar { if (!$this->progressBar) { throw new RuntimeException('The ProgressBar is not started.'); @@ -356,18 +353,20 @@ private function getProgressBar() return $this->progressBar; } - private function autoPrependBlock() + private function autoPrependBlock(): void { $chars = substr(str_replace(PHP_EOL, "\n", $this->bufferedOutput->fetch()), -2); if (!isset($chars[0])) { - return $this->newLine(); //empty history, so we should start with a new line. + $this->newLine(); //empty history, so we should start with a new line. + + return; } //Prepend new line for each non LF chars (This means no blank line was output before) $this->newLine(2 - substr_count($chars, "\n")); } - private function autoPrependText() + private function autoPrependText(): void { $fetched = $this->bufferedOutput->fetch(); //Prepend new line if last char isn't EOL: @@ -376,7 +375,7 @@ private function autoPrependText() } } - private function reduceBuffer($messages) + private function reduceBuffer($messages): array { // We need to know if the two last chars are PHP_EOL // Preserve the last 4 chars inserted (PHP_EOL on windows is two chars) in the history buffer @@ -385,7 +384,7 @@ private function reduceBuffer($messages) }, array_merge(array($this->bufferedOutput->fetch()), (array) $messages)); } - private function createBlock($messages, $type = null, $style = null, $prefix = ' ', $padding = false, $escape = false) + private function createBlock(iterable $messages, string $type = null, string $style = null, string $prefix = ' ', bool $padding = false, bool $escape = false) { $indentLength = 0; $prefixLength = Helper::strlenWithoutDecoration($this->getFormatter(), $prefix); diff --git a/src/Symfony/Component/CssSelector/Node/AbstractNode.php b/src/Symfony/Component/CssSelector/Node/AbstractNode.php index 7477e9119df32..123ef1b117a67 100644 --- a/src/Symfony/Component/CssSelector/Node/AbstractNode.php +++ b/src/Symfony/Component/CssSelector/Node/AbstractNode.php @@ -31,7 +31,7 @@ abstract class AbstractNode implements NodeInterface /** * @return string */ - public function getNodeName() + public function getNodeName(): string { if (null === $this->nodeName) { $this->nodeName = preg_replace('~.*\\\\([^\\\\]+)Node$~', '$1', get_called_class()); diff --git a/src/Symfony/Component/CssSelector/Node/AttributeNode.php b/src/Symfony/Component/CssSelector/Node/AttributeNode.php index af872b79e9f2d..0db22c009589b 100644 --- a/src/Symfony/Component/CssSelector/Node/AttributeNode.php +++ b/src/Symfony/Component/CssSelector/Node/AttributeNode.php @@ -107,7 +107,7 @@ public function getValue() /** * {@inheritdoc} */ - public function getSpecificity() + public function getSpecificity(): Specificity { return $this->selector->getSpecificity()->plus(new Specificity(0, 1, 0)); } @@ -115,7 +115,7 @@ public function getSpecificity() /** * {@inheritdoc} */ - public function __toString() + public function __toString(): string { $attribute = $this->namespace ? $this->namespace.'|'.$this->attribute : $this->attribute; diff --git a/src/Symfony/Component/CssSelector/Node/ClassNode.php b/src/Symfony/Component/CssSelector/Node/ClassNode.php index f965e7773e89a..f036c41c157be 100644 --- a/src/Symfony/Component/CssSelector/Node/ClassNode.php +++ b/src/Symfony/Component/CssSelector/Node/ClassNode.php @@ -62,7 +62,7 @@ public function getName() /** * {@inheritdoc} */ - public function getSpecificity() + public function getSpecificity(): Specificity { return $this->selector->getSpecificity()->plus(new Specificity(0, 1, 0)); } @@ -70,7 +70,7 @@ public function getSpecificity() /** * {@inheritdoc} */ - public function __toString() + public function __toString(): string { return sprintf('%s[%s.%s]', $this->getNodeName(), $this->selector, $this->name); } diff --git a/src/Symfony/Component/CssSelector/Node/CombinedSelectorNode.php b/src/Symfony/Component/CssSelector/Node/CombinedSelectorNode.php index 39f659977779c..97a122cb2ae82 100644 --- a/src/Symfony/Component/CssSelector/Node/CombinedSelectorNode.php +++ b/src/Symfony/Component/CssSelector/Node/CombinedSelectorNode.php @@ -77,7 +77,7 @@ public function getSubSelector() /** * {@inheritdoc} */ - public function getSpecificity() + public function getSpecificity(): Specificity { return $this->selector->getSpecificity()->plus($this->subSelector->getSpecificity()); } @@ -85,7 +85,7 @@ public function getSpecificity() /** * {@inheritdoc} */ - public function __toString() + public function __toString(): string { $combinator = ' ' === $this->combinator ? '' : $this->combinator; diff --git a/src/Symfony/Component/CssSelector/Node/ElementNode.php b/src/Symfony/Component/CssSelector/Node/ElementNode.php index 06e343e969c11..5b57a3a4f08a2 100644 --- a/src/Symfony/Component/CssSelector/Node/ElementNode.php +++ b/src/Symfony/Component/CssSelector/Node/ElementNode.php @@ -62,7 +62,7 @@ public function getElement() /** * {@inheritdoc} */ - public function getSpecificity() + public function getSpecificity(): Specificity { return new Specificity(0, 0, $this->element ? 1 : 0); } @@ -70,7 +70,7 @@ public function getSpecificity() /** * {@inheritdoc} */ - public function __toString() + public function __toString(): string { $element = $this->element ?: '*'; diff --git a/src/Symfony/Component/CssSelector/Node/FunctionNode.php b/src/Symfony/Component/CssSelector/Node/FunctionNode.php index 612f348c5e419..ba2434c062816 100644 --- a/src/Symfony/Component/CssSelector/Node/FunctionNode.php +++ b/src/Symfony/Component/CssSelector/Node/FunctionNode.php @@ -79,7 +79,7 @@ public function getArguments() /** * {@inheritdoc} */ - public function getSpecificity() + public function getSpecificity(): Specificity { return $this->selector->getSpecificity()->plus(new Specificity(0, 1, 0)); } @@ -87,7 +87,7 @@ public function getSpecificity() /** * {@inheritdoc} */ - public function __toString() + public function __toString(): string { $arguments = implode(', ', array_map(function (Token $token) { return "'".$token->getValue()."'"; diff --git a/src/Symfony/Component/CssSelector/Node/HashNode.php b/src/Symfony/Component/CssSelector/Node/HashNode.php index 20db465162806..50e6d09ff7def 100644 --- a/src/Symfony/Component/CssSelector/Node/HashNode.php +++ b/src/Symfony/Component/CssSelector/Node/HashNode.php @@ -62,7 +62,7 @@ public function getId() /** * {@inheritdoc} */ - public function getSpecificity() + public function getSpecificity(): Specificity { return $this->selector->getSpecificity()->plus(new Specificity(1, 0, 0)); } @@ -70,7 +70,7 @@ public function getSpecificity() /** * {@inheritdoc} */ - public function __toString() + public function __toString(): string { return sprintf('%s[%s#%s]', $this->getNodeName(), $this->selector, $this->id); } diff --git a/src/Symfony/Component/CssSelector/Node/NegationNode.php b/src/Symfony/Component/CssSelector/Node/NegationNode.php index 4b5aa2260d005..e481b52861a57 100644 --- a/src/Symfony/Component/CssSelector/Node/NegationNode.php +++ b/src/Symfony/Component/CssSelector/Node/NegationNode.php @@ -62,7 +62,7 @@ public function getSubSelector() /** * {@inheritdoc} */ - public function getSpecificity() + public function getSpecificity(): Specificity { return $this->selector->getSpecificity()->plus($this->subSelector->getSpecificity()); } @@ -70,7 +70,7 @@ public function getSpecificity() /** * {@inheritdoc} */ - public function __toString() + public function __toString(): string { return sprintf('%s[%s:not(%s)]', $this->getNodeName(), $this->selector, $this->subSelector); } diff --git a/src/Symfony/Component/CssSelector/Node/NodeInterface.php b/src/Symfony/Component/CssSelector/Node/NodeInterface.php index d919e20c7107a..b078d26d4de31 100644 --- a/src/Symfony/Component/CssSelector/Node/NodeInterface.php +++ b/src/Symfony/Component/CssSelector/Node/NodeInterface.php @@ -23,24 +23,9 @@ */ interface NodeInterface { - /** - * Returns node's name. - * - * @return string - */ - public function getNodeName(); + public function getNodeName(): string; - /** - * Returns node's specificity. - * - * @return Specificity - */ - public function getSpecificity(); + public function getSpecificity(): Specificity; - /** - * Returns node's string representation. - * - * @return string - */ - public function __toString(); + public function __toString(): string; } diff --git a/src/Symfony/Component/CssSelector/Node/PseudoNode.php b/src/Symfony/Component/CssSelector/Node/PseudoNode.php index c23ddd5912a66..25aa9e2b2799f 100644 --- a/src/Symfony/Component/CssSelector/Node/PseudoNode.php +++ b/src/Symfony/Component/CssSelector/Node/PseudoNode.php @@ -62,7 +62,7 @@ public function getIdentifier() /** * {@inheritdoc} */ - public function getSpecificity() + public function getSpecificity(): Specificity { return $this->selector->getSpecificity()->plus(new Specificity(0, 1, 0)); } @@ -70,7 +70,7 @@ public function getSpecificity() /** * {@inheritdoc} */ - public function __toString() + public function __toString(): string { return sprintf('%s[%s:%s]', $this->getNodeName(), $this->selector, $this->identifier); } diff --git a/src/Symfony/Component/CssSelector/Node/SelectorNode.php b/src/Symfony/Component/CssSelector/Node/SelectorNode.php index 729e0911b3c76..34c323b17cf6d 100644 --- a/src/Symfony/Component/CssSelector/Node/SelectorNode.php +++ b/src/Symfony/Component/CssSelector/Node/SelectorNode.php @@ -62,7 +62,7 @@ public function getPseudoElement() /** * {@inheritdoc} */ - public function getSpecificity() + public function getSpecificity(): Specificity { return $this->tree->getSpecificity()->plus(new Specificity(0, 0, $this->pseudoElement ? 1 : 0)); } @@ -70,7 +70,7 @@ public function getSpecificity() /** * {@inheritdoc} */ - public function __toString() + public function __toString(): string { return sprintf('%s[%s%s]', $this->getNodeName(), $this->tree, $this->pseudoElement ? '::'.$this->pseudoElement : ''); } diff --git a/src/Symfony/Component/CssSelector/Node/Specificity.php b/src/Symfony/Component/CssSelector/Node/Specificity.php index d09eaca77ef45..be8a0e01144cf 100644 --- a/src/Symfony/Component/CssSelector/Node/Specificity.php +++ b/src/Symfony/Component/CssSelector/Node/Specificity.php @@ -44,36 +44,19 @@ class Specificity */ private $c; - /** - * Constructor. - * - * @param int $a - * @param int $b - * @param int $c - */ - public function __construct($a, $b, $c) + public function __construct(int $a, int $b, int $c) { $this->a = $a; $this->b = $b; $this->c = $c; } - /** - * @param Specificity $specificity - * - * @return self - */ - public function plus(Specificity $specificity) + public function plus(Specificity $specificity): Specificity { return new self($this->a + $specificity->a, $this->b + $specificity->b, $this->c + $specificity->c); } - /** - * Returns global specificity value. - * - * @return int - */ - public function getValue() + public function getValue(): int { return $this->a * self::A_FACTOR + $this->b * self::B_FACTOR + $this->c * self::C_FACTOR; } diff --git a/src/Symfony/Component/CssSelector/Parser/Handler/CommentHandler.php b/src/Symfony/Component/CssSelector/Parser/Handler/CommentHandler.php index a29775cab370f..93f318844a5bd 100644 --- a/src/Symfony/Component/CssSelector/Parser/Handler/CommentHandler.php +++ b/src/Symfony/Component/CssSelector/Parser/Handler/CommentHandler.php @@ -29,7 +29,7 @@ class CommentHandler implements HandlerInterface /** * {@inheritdoc} */ - public function handle(Reader $reader, TokenStream $stream) + public function handle(Reader $reader, TokenStream $stream): bool { if ('/*' !== $reader->getSubstring(2)) { return false; diff --git a/src/Symfony/Component/CssSelector/Parser/Handler/HandlerInterface.php b/src/Symfony/Component/CssSelector/Parser/Handler/HandlerInterface.php index a1297c80c089b..10e20ac711cdb 100644 --- a/src/Symfony/Component/CssSelector/Parser/Handler/HandlerInterface.php +++ b/src/Symfony/Component/CssSelector/Parser/Handler/HandlerInterface.php @@ -32,5 +32,5 @@ interface HandlerInterface * * @return bool */ - public function handle(Reader $reader, TokenStream $stream); + public function handle(Reader $reader, TokenStream $stream): bool; } diff --git a/src/Symfony/Component/CssSelector/Parser/Handler/HashHandler.php b/src/Symfony/Component/CssSelector/Parser/Handler/HashHandler.php index f74bda51262ac..145fe5925f384 100644 --- a/src/Symfony/Component/CssSelector/Parser/Handler/HashHandler.php +++ b/src/Symfony/Component/CssSelector/Parser/Handler/HashHandler.php @@ -52,7 +52,7 @@ public function __construct(TokenizerPatterns $patterns, TokenizerEscaping $esca /** * {@inheritdoc} */ - public function handle(Reader $reader, TokenStream $stream) + public function handle(Reader $reader, TokenStream $stream): bool { $match = $reader->findPattern($this->patterns->getHashPattern()); diff --git a/src/Symfony/Component/CssSelector/Parser/Handler/IdentifierHandler.php b/src/Symfony/Component/CssSelector/Parser/Handler/IdentifierHandler.php index 358c7c14ad28a..704f939d618e2 100644 --- a/src/Symfony/Component/CssSelector/Parser/Handler/IdentifierHandler.php +++ b/src/Symfony/Component/CssSelector/Parser/Handler/IdentifierHandler.php @@ -52,7 +52,7 @@ public function __construct(TokenizerPatterns $patterns, TokenizerEscaping $esca /** * {@inheritdoc} */ - public function handle(Reader $reader, TokenStream $stream) + public function handle(Reader $reader, TokenStream $stream): bool { $match = $reader->findPattern($this->patterns->getIdentifierPattern()); diff --git a/src/Symfony/Component/CssSelector/Parser/Handler/NumberHandler.php b/src/Symfony/Component/CssSelector/Parser/Handler/NumberHandler.php index 4ea5c484b26fb..7ef2fe3171ce2 100644 --- a/src/Symfony/Component/CssSelector/Parser/Handler/NumberHandler.php +++ b/src/Symfony/Component/CssSelector/Parser/Handler/NumberHandler.php @@ -44,7 +44,7 @@ public function __construct(TokenizerPatterns $patterns) /** * {@inheritdoc} */ - public function handle(Reader $reader, TokenStream $stream) + public function handle(Reader $reader, TokenStream $stream): bool { $match = $reader->findPattern($this->patterns->getNumberPattern()); diff --git a/src/Symfony/Component/CssSelector/Parser/Handler/StringHandler.php b/src/Symfony/Component/CssSelector/Parser/Handler/StringHandler.php index 420529601609d..18a88acbc3146 100644 --- a/src/Symfony/Component/CssSelector/Parser/Handler/StringHandler.php +++ b/src/Symfony/Component/CssSelector/Parser/Handler/StringHandler.php @@ -54,7 +54,7 @@ public function __construct(TokenizerPatterns $patterns, TokenizerEscaping $esca /** * {@inheritdoc} */ - public function handle(Reader $reader, TokenStream $stream) + public function handle(Reader $reader, TokenStream $stream): bool { $quote = $reader->getSubstring(1); diff --git a/src/Symfony/Component/CssSelector/Parser/Handler/WhitespaceHandler.php b/src/Symfony/Component/CssSelector/Parser/Handler/WhitespaceHandler.php index 4c2d3354fb83e..ebf8a19fe2605 100644 --- a/src/Symfony/Component/CssSelector/Parser/Handler/WhitespaceHandler.php +++ b/src/Symfony/Component/CssSelector/Parser/Handler/WhitespaceHandler.php @@ -30,7 +30,7 @@ class WhitespaceHandler implements HandlerInterface /** * {@inheritdoc} */ - public function handle(Reader $reader, TokenStream $stream) + public function handle(Reader $reader, TokenStream $stream): bool { $match = $reader->findPattern('~^[ \t\r\n\f]+~'); diff --git a/src/Symfony/Component/CssSelector/Parser/Parser.php b/src/Symfony/Component/CssSelector/Parser/Parser.php index 3c5b2dd264b50..aefb84386dddb 100644 --- a/src/Symfony/Component/CssSelector/Parser/Parser.php +++ b/src/Symfony/Component/CssSelector/Parser/Parser.php @@ -45,7 +45,7 @@ public function __construct(Tokenizer $tokenizer = null) /** * {@inheritdoc} */ - public function parse($source) + public function parse(string $source): array { $reader = new Reader($source); $stream = $this->tokenizer->tokenize($reader); @@ -102,14 +102,7 @@ public static function parseSeries(array $tokens) ); } - /** - * Parses selector nodes. - * - * @param TokenStream $stream - * - * @return array - */ - private function parseSelectorList(TokenStream $stream) + private function parseSelectorList(TokenStream $stream): array { $stream->skipWhitespace(); $selectors = array(); @@ -128,16 +121,7 @@ private function parseSelectorList(TokenStream $stream) return $selectors; } - /** - * Parses next selector or combined node. - * - * @param TokenStream $stream - * - * @return Node\SelectorNode - * - * @throws SyntaxErrorException - */ - private function parserSelectorNode(TokenStream $stream) + private function parserSelectorNode(TokenStream $stream): Node\SelectorNode { list($result, $pseudoElement) = $this->parseSimpleSelector($stream); @@ -291,14 +275,7 @@ private function parseSimpleSelector(TokenStream $stream, $insideNegation = fals return array($result, $pseudoElement); } - /** - * Parses next element node. - * - * @param TokenStream $stream - * - * @return Node\ElementNode - */ - private function parseElementNode(TokenStream $stream) + private function parseElementNode(TokenStream $stream): Node\ElementNode { $peek = $stream->getPeek(); @@ -324,17 +301,7 @@ private function parseElementNode(TokenStream $stream) return new Node\ElementNode($namespace, $element); } - /** - * Parses next attribute node. - * - * @param Node\NodeInterface $selector - * @param TokenStream $stream - * - * @return Node\AttributeNode - * - * @throws SyntaxErrorException - */ - private function parseAttributeNode(Node\NodeInterface $selector, TokenStream $stream) + private function parseAttributeNode(Node\NodeInterface $selector, TokenStream $stream): Node\AttributeNode { $stream->skipWhitespace(); $attribute = $stream->getNextIdentifierOrStar(); diff --git a/src/Symfony/Component/CssSelector/Parser/ParserInterface.php b/src/Symfony/Component/CssSelector/Parser/ParserInterface.php index c5af20367de8c..88c8879e0b6e8 100644 --- a/src/Symfony/Component/CssSelector/Parser/ParserInterface.php +++ b/src/Symfony/Component/CssSelector/Parser/ParserInterface.php @@ -32,5 +32,5 @@ interface ParserInterface * * @return SelectorNode[] */ - public function parse($source); + public function parse(string $source): array; } diff --git a/src/Symfony/Component/CssSelector/Parser/Shortcut/ClassParser.php b/src/Symfony/Component/CssSelector/Parser/Shortcut/ClassParser.php index c513de5ff12ee..ce7b20ef2e768 100644 --- a/src/Symfony/Component/CssSelector/Parser/Shortcut/ClassParser.php +++ b/src/Symfony/Component/CssSelector/Parser/Shortcut/ClassParser.php @@ -31,7 +31,7 @@ class ClassParser implements ParserInterface /** * {@inheritdoc} */ - public function parse($source) + public function parse(string $source): array { // Matches an optional namespace, optional element, and required class // $source = 'test|input.ab6bd_field'; diff --git a/src/Symfony/Component/CssSelector/Parser/Shortcut/ElementParser.php b/src/Symfony/Component/CssSelector/Parser/Shortcut/ElementParser.php index c29f5e442e739..3b93f0068f5d4 100644 --- a/src/Symfony/Component/CssSelector/Parser/Shortcut/ElementParser.php +++ b/src/Symfony/Component/CssSelector/Parser/Shortcut/ElementParser.php @@ -30,7 +30,7 @@ class ElementParser implements ParserInterface /** * {@inheritdoc} */ - public function parse($source) + public function parse(string $source): array { // Matches an optional namespace, required element or `*` // $source = 'testns|testel'; diff --git a/src/Symfony/Component/CssSelector/Parser/Shortcut/EmptyStringParser.php b/src/Symfony/Component/CssSelector/Parser/Shortcut/EmptyStringParser.php index 016cf0a848207..0c366cc4e0897 100644 --- a/src/Symfony/Component/CssSelector/Parser/Shortcut/EmptyStringParser.php +++ b/src/Symfony/Component/CssSelector/Parser/Shortcut/EmptyStringParser.php @@ -34,7 +34,7 @@ class EmptyStringParser implements ParserInterface /** * {@inheritdoc} */ - public function parse($source) + public function parse(string $source): array { // Matches an empty string if ($source == '') { diff --git a/src/Symfony/Component/CssSelector/Parser/Shortcut/HashParser.php b/src/Symfony/Component/CssSelector/Parser/Shortcut/HashParser.php index 3f3883bb8d2e9..e94ce0a46afd4 100644 --- a/src/Symfony/Component/CssSelector/Parser/Shortcut/HashParser.php +++ b/src/Symfony/Component/CssSelector/Parser/Shortcut/HashParser.php @@ -31,7 +31,7 @@ class HashParser implements ParserInterface /** * {@inheritdoc} */ - public function parse($source) + public function parse(string $source): array { // Matches an optional namespace, optional element, and required id // $source = 'test|input#ab6bd_field'; diff --git a/src/Symfony/Component/CssSelector/Parser/Token.php b/src/Symfony/Component/CssSelector/Parser/Token.php index 68fac59b03a32..43cabb5e92cb2 100644 --- a/src/Symfony/Component/CssSelector/Parser/Token.php +++ b/src/Symfony/Component/CssSelector/Parser/Token.php @@ -47,7 +47,7 @@ class Token private $position; /** - * @param int $type + * @param string $type * @param string $value * @param int $position */ @@ -82,20 +82,12 @@ public function getPosition() return $this->position; } - /** - * @return bool - */ - public function isFileEnd() + public function isFileEnd(): bool { return self::TYPE_FILE_END === $this->type; } - /** - * @param array $values - * - * @return bool - */ - public function isDelimiter(array $values = array()) + public function isDelimiter(array $values = array()): bool { if (self::TYPE_DELIMITER !== $this->type) { return false; @@ -108,50 +100,32 @@ public function isDelimiter(array $values = array()) return in_array($this->value, $values); } - /** - * @return bool - */ - public function isWhitespace() + public function isWhitespace(): bool { return self::TYPE_WHITESPACE === $this->type; } - /** - * @return bool - */ - public function isIdentifier() + public function isIdentifier(): bool { return self::TYPE_IDENTIFIER === $this->type; } - /** - * @return bool - */ - public function isHash() + public function isHash(): bool { return self::TYPE_HASH === $this->type; } - /** - * @return bool - */ - public function isNumber() + public function isNumber(): bool { return self::TYPE_NUMBER === $this->type; } - /** - * @return bool - */ - public function isString() + public function isString(): bool { return self::TYPE_STRING === $this->type; } - /** - * @return string - */ - public function __toString() + public function __toString(): string { if ($this->value) { return sprintf('<%s "%s" at %s>', $this->type, $this->value, $this->position); diff --git a/src/Symfony/Component/CssSelector/Parser/Tokenizer/TokenizerEscaping.php b/src/Symfony/Component/CssSelector/Parser/Tokenizer/TokenizerEscaping.php index af4c31e5b09b8..2ca10f3a13199 100644 --- a/src/Symfony/Component/CssSelector/Parser/Tokenizer/TokenizerEscaping.php +++ b/src/Symfony/Component/CssSelector/Parser/Tokenizer/TokenizerEscaping.php @@ -28,44 +28,26 @@ class TokenizerEscaping */ private $patterns; - /** - * @param TokenizerPatterns $patterns - */ public function __construct(TokenizerPatterns $patterns) { $this->patterns = $patterns; } - /** - * @param string $value - * - * @return string - */ - public function escapeUnicode($value) + public function escapeUnicode(string $value): string { $value = $this->replaceUnicodeSequences($value); return preg_replace($this->patterns->getSimpleEscapePattern(), '$1', $value); } - /** - * @param string $value - * - * @return string - */ - public function escapeUnicodeAndNewLine($value) + public function escapeUnicodeAndNewLine(string $value): string { $value = preg_replace($this->patterns->getNewLineEscapePattern(), '', $value); return $this->escapeUnicode($value); } - /** - * @param string $value - * - * @return string - */ - private function replaceUnicodeSequences($value) + private function replaceUnicodeSequences(string $value): string { return preg_replace_callback($this->patterns->getUnicodeEscapePattern(), function ($match) { $c = hexdec($match[1]); diff --git a/src/Symfony/Component/CssSelector/XPath/Extension/CombinationExtension.php b/src/Symfony/Component/CssSelector/XPath/Extension/CombinationExtension.php index 0d2d658b65c64..a13ea32e5b71c 100644 --- a/src/Symfony/Component/CssSelector/XPath/Extension/CombinationExtension.php +++ b/src/Symfony/Component/CssSelector/XPath/Extension/CombinationExtension.php @@ -28,7 +28,7 @@ class CombinationExtension extends AbstractExtension /** * {@inheritdoc} */ - public function getCombinationTranslators() + public function getCombinationTranslators(): array { return array( ' ' => array($this, 'translateDescendant'), @@ -44,7 +44,7 @@ public function getCombinationTranslators() * * @return XPathExpr */ - public function translateDescendant(XPathExpr $xpath, XPathExpr $combinedXpath) + public function translateDescendant(XPathExpr $xpath, XPathExpr $combinedXpath): XPathExpr { return $xpath->join('/descendant-or-self::*/', $combinedXpath); } diff --git a/src/Symfony/Component/CssSelector/XPath/Translator.php b/src/Symfony/Component/CssSelector/XPath/Translator.php index 2b01fc8e52526..4c43f3c9ebdfa 100644 --- a/src/Symfony/Component/CssSelector/XPath/Translator.php +++ b/src/Symfony/Component/CssSelector/XPath/Translator.php @@ -83,12 +83,7 @@ public function __construct(ParserInterface $parser = null) ; } - /** - * @param string $element - * - * @return string - */ - public static function getXpathLiteral($element) + public static function getXpathLiteral(string $element): string { if (false === strpos($element, "'")) { return "'".$element."'"; @@ -117,7 +112,7 @@ public static function getXpathLiteral($element) /** * {@inheritdoc} */ - public function cssToXPath($cssExpr, $prefix = 'descendant-or-self::') + public function cssToXPath(string $cssExpr, string $prefix = 'descendant-or-self::'): string { $selectors = $this->parseSelectors($cssExpr); @@ -136,19 +131,12 @@ public function cssToXPath($cssExpr, $prefix = 'descendant-or-self::') /** * {@inheritdoc} */ - public function selectorToXPath(SelectorNode $selector, $prefix = 'descendant-or-self::') + public function selectorToXPath(SelectorNode $selector, string $prefix = 'descendant-or-self::'): string { return ($prefix ?: '').$this->nodeToXPath($selector); } - /** - * Registers an extension. - * - * @param Extension\ExtensionInterface $extension - * - * @return $this - */ - public function registerExtension(Extension\ExtensionInterface $extension) + public function registerExtension(Extension\ExtensionInterface $extension): Translator { $this->extensions[$extension->getName()] = $extension; @@ -162,13 +150,9 @@ public function registerExtension(Extension\ExtensionInterface $extension) } /** - * @param string $name - * - * @return Extension\ExtensionInterface - * * @throws ExpressionErrorException */ - public function getExtension($name) + public function getExtension(string $name): Extension\ExtensionInterface { if (!isset($this->extensions[$name])) { throw new ExpressionErrorException(sprintf('Extension "%s" not registered.', $name)); @@ -177,14 +161,7 @@ public function getExtension($name) return $this->extensions[$name]; } - /** - * Registers a shortcut parser. - * - * @param ParserInterface $shortcut - * - * @return $this - */ - public function registerParserShortcut(ParserInterface $shortcut) + public function registerParserShortcut(ParserInterface $shortcut): Translator { $this->shortcutParsers[] = $shortcut; @@ -192,13 +169,9 @@ public function registerParserShortcut(ParserInterface $shortcut) } /** - * @param NodeInterface $node - * - * @return XPathExpr - * * @throws ExpressionErrorException */ - public function nodeToXPath(NodeInterface $node) + public function nodeToXPath(NodeInterface $node): XPathExpr { if (!isset($this->nodeTranslators[$node->getNodeName()])) { throw new ExpressionErrorException(sprintf('Node "%s" not supported.', $node->getNodeName())); @@ -208,15 +181,9 @@ public function nodeToXPath(NodeInterface $node) } /** - * @param string $combiner - * @param NodeInterface $xpath - * @param NodeInterface $combinedXpath - * - * @return XPathExpr - * * @throws ExpressionErrorException */ - public function addCombination($combiner, NodeInterface $xpath, NodeInterface $combinedXpath) + public function addCombination(string $combiner, NodeInterface $xpath, NodeInterface $combinedXpath): XPathExpr { if (!isset($this->combinationTranslators[$combiner])) { throw new ExpressionErrorException(sprintf('Combiner "%s" not supported.', $combiner)); @@ -226,14 +193,9 @@ public function addCombination($combiner, NodeInterface $xpath, NodeInterface $c } /** - * @param XPathExpr $xpath - * @param FunctionNode $function - * - * @return XPathExpr - * * @throws ExpressionErrorException */ - public function addFunction(XPathExpr $xpath, FunctionNode $function) + public function addFunction(XPathExpr $xpath, FunctionNode $function): XPathExpr { if (!isset($this->functionTranslators[$function->getName()])) { throw new ExpressionErrorException(sprintf('Function "%s" not supported.', $function->getName())); @@ -243,14 +205,9 @@ public function addFunction(XPathExpr $xpath, FunctionNode $function) } /** - * @param XPathExpr $xpath - * @param string $pseudoClass - * - * @return XPathExpr - * * @throws ExpressionErrorException */ - public function addPseudoClass(XPathExpr $xpath, $pseudoClass) + public function addPseudoClass(XPathExpr $xpath, string $pseudoClass): XPathExpr { if (!isset($this->pseudoClassTranslators[$pseudoClass])) { throw new ExpressionErrorException(sprintf('Pseudo-class "%s" not supported.', $pseudoClass)); @@ -260,16 +217,9 @@ public function addPseudoClass(XPathExpr $xpath, $pseudoClass) } /** - * @param XPathExpr $xpath - * @param string $operator - * @param string $attribute - * @param string $value - * - * @return XPathExpr - * * @throws ExpressionErrorException */ - public function addAttributeMatching(XPathExpr $xpath, $operator, $attribute, $value) + public function addAttributeMatching(XPathExpr $xpath, string $operator, string $attribute, $value): XPathExpr { if (!isset($this->attributeMatchingTranslators[$operator])) { throw new ExpressionErrorException(sprintf('Attribute matcher operator "%s" not supported.', $operator)); diff --git a/src/Symfony/Component/CssSelector/XPath/TranslatorInterface.php b/src/Symfony/Component/CssSelector/XPath/TranslatorInterface.php index 0b5de83d57124..3224859559470 100644 --- a/src/Symfony/Component/CssSelector/XPath/TranslatorInterface.php +++ b/src/Symfony/Component/CssSelector/XPath/TranslatorInterface.php @@ -33,7 +33,7 @@ interface TranslatorInterface * * @return string */ - public function cssToXPath($cssExpr, $prefix = 'descendant-or-self::'); + public function cssToXPath(string $cssExpr, string $prefix = 'descendant-or-self::'): string; /** * Translates a parsed selector node to an XPath expression. @@ -43,5 +43,5 @@ public function cssToXPath($cssExpr, $prefix = 'descendant-or-self::'); * * @return string */ - public function selectorToXPath(SelectorNode $selector, $prefix = 'descendant-or-self::'); + public function selectorToXPath(SelectorNode $selector, string $prefix = 'descendant-or-self::'): string; } diff --git a/src/Symfony/Component/CssSelector/XPath/XPathExpr.php b/src/Symfony/Component/CssSelector/XPath/XPathExpr.php index 38ca295540071..093cfaf32f967 100644 --- a/src/Symfony/Component/CssSelector/XPath/XPathExpr.php +++ b/src/Symfony/Component/CssSelector/XPath/XPathExpr.php @@ -38,13 +38,7 @@ class XPathExpr */ private $condition; - /** - * @param string $path - * @param string $element - * @param string $condition - * @param bool $starPrefix - */ - public function __construct($path = '', $element = '*', $condition = '', $starPrefix = false) + public function __construct(string $path = '', string $element = '*', string $condition = '', bool $starPrefix = false) { $this->path = $path; $this->element = $element; @@ -55,20 +49,12 @@ public function __construct($path = '', $element = '*', $condition = '', $starPr } } - /** - * @return string - */ - public function getElement() + public function getElement(): string { return $this->element; } - /** - * @param $condition - * - * @return $this - */ - public function addCondition($condition) + public function addCondition(string $condition): XPathExpr { $this->condition = $this->condition ? sprintf('%s and (%s)', $this->condition, $condition) : $condition; @@ -78,15 +64,12 @@ public function addCondition($condition) /** * @return string */ - public function getCondition() + public function getCondition(): string { return $this->condition; } - /** - * @return $this - */ - public function addNameTest() + public function addNameTest(): XPathExpr { if ('*' !== $this->element) { $this->addCondition('name() = '.Translator::getXpathLiteral($this->element)); @@ -96,10 +79,7 @@ public function addNameTest() return $this; } - /** - * @return $this - */ - public function addStarPrefix() + public function addStarPrefix(): XPathExpr { $this->path .= '*/'; @@ -114,7 +94,7 @@ public function addStarPrefix() * * @return $this */ - public function join($combiner, XPathExpr $expr) + public function join(string $combiner, XPathExpr $expr): XPathExpr { $path = $this->__toString().$combiner; @@ -129,10 +109,7 @@ public function join($combiner, XPathExpr $expr) return $this; } - /** - * @return string - */ - public function __toString() + public function __toString(): string { $path = $this->path.$this->element; $condition = null === $this->condition || '' === $this->condition ? '' : '['.$this->condition.']'; diff --git a/src/Symfony/Component/Dotenv/Dotenv.php b/src/Symfony/Component/Dotenv/Dotenv.php index 630e6f79c7043..c5f28d6e697fc 100644 --- a/src/Symfony/Component/Dotenv/Dotenv.php +++ b/src/Symfony/Component/Dotenv/Dotenv.php @@ -45,7 +45,7 @@ final class Dotenv * @throws FormatException when a file has a syntax error * @throws PathException when a file does not exist or is not readable */ - public function load($path, ...$paths) + public function load(string $path, string ...$paths): void { array_unshift($paths, $path); @@ -65,7 +65,7 @@ public function load($path, ...$paths) * * @param array $values An array of env variables */ - public function populate($values) + public function populate(array $values): void { $loadedVars = array_flip(explode(',', getenv('SYMFONY_DOTENV_VARS'))); unset($loadedVars['']); @@ -104,7 +104,7 @@ public function populate($values) * * @throws FormatException when a file has a syntax error */ - public function parse($data, $path = '.env') + public function parse(string $data, string $path = '.env'): array { $this->path = $path; $this->data = str_replace(array("\r\n", "\r"), "\n", $data); diff --git a/src/Symfony/Component/ExpressionLanguage/ExpressionLanguage.php b/src/Symfony/Component/ExpressionLanguage/ExpressionLanguage.php index 64f4dd17371d5..c011b0c27058e 100644 --- a/src/Symfony/Component/ExpressionLanguage/ExpressionLanguage.php +++ b/src/Symfony/Component/ExpressionLanguage/ExpressionLanguage.php @@ -141,7 +141,7 @@ protected function registerFunctions() $this->addFunction(ExpressionFunction::fromPhp('constant')); } - private function getLexer() + private function getLexer(): Lexer { if (null === $this->lexer) { $this->lexer = new Lexer(); @@ -150,7 +150,7 @@ private function getLexer() return $this->lexer; } - private function getParser() + private function getParser(): Parser { if (null === $this->parser) { $this->parser = new Parser($this->functions); @@ -159,7 +159,7 @@ private function getParser() return $this->parser; } - private function getCompiler() + private function getCompiler(): Compiler { if (null === $this->compiler) { $this->compiler = new Compiler($this->functions); diff --git a/src/Symfony/Component/ExpressionLanguage/Node/UnaryNode.php b/src/Symfony/Component/ExpressionLanguage/Node/UnaryNode.php index 583103217a626..4a18e83a5d0b9 100644 --- a/src/Symfony/Component/ExpressionLanguage/Node/UnaryNode.php +++ b/src/Symfony/Component/ExpressionLanguage/Node/UnaryNode.php @@ -27,7 +27,7 @@ class UnaryNode extends Node '-' => '-', ); - public function __construct($operator, Node $node) + public function __construct(string $operator, Node $node) { parent::__construct( array('node' => $node), @@ -59,7 +59,7 @@ public function evaluate($functions, $values) return $value; } - public function toArray() + public function toArray(): array { return array('(', $this->attributes['operator'].' ', $this->nodes['node'], ')'); } diff --git a/src/Symfony/Component/Form/Forms.php b/src/Symfony/Component/Form/Forms.php index e84fcd0ab0048..061e98e170589 100644 --- a/src/Symfony/Component/Form/Forms.php +++ b/src/Symfony/Component/Form/Forms.php @@ -105,7 +105,7 @@ final class Forms * * @return FormFactoryInterface The form factory */ - public static function createFormFactory() + public static function createFormFactory(): FormFactoryInterface { return self::createFormFactoryBuilder()->getFormFactory(); } @@ -115,7 +115,7 @@ public static function createFormFactory() * * @return FormFactoryBuilderInterface The form factory builder */ - public static function createFormFactoryBuilder() + public static function createFormFactoryBuilder(): FormFactoryBuilderInterface { $builder = new FormFactoryBuilder(); $builder->addExtension(new CoreExtension()); diff --git a/src/Symfony/Component/HttpKernel/Controller/ArgumentResolver.php b/src/Symfony/Component/HttpKernel/Controller/ArgumentResolver.php index 2c17125c5aca1..186007ebe49c9 100644 --- a/src/Symfony/Component/HttpKernel/Controller/ArgumentResolver.php +++ b/src/Symfony/Component/HttpKernel/Controller/ArgumentResolver.php @@ -34,7 +34,7 @@ final class ArgumentResolver implements ArgumentResolverInterface */ private $argumentValueResolvers; - public function __construct(ArgumentMetadataFactoryInterface $argumentMetadataFactory = null, $argumentValueResolvers = array()) + public function __construct(ArgumentMetadataFactoryInterface $argumentMetadataFactory = null, iterable $argumentValueResolvers = array()) { $this->argumentMetadataFactory = $argumentMetadataFactory ?: new ArgumentMetadataFactory(); $this->argumentValueResolvers = $argumentValueResolvers ?: self::getDefaultArgumentValueResolvers(); @@ -81,7 +81,7 @@ public function getArguments(Request $request, $controller) return $arguments; } - public static function getDefaultArgumentValueResolvers() + public static function getDefaultArgumentValueResolvers(): iterable { return array( new RequestAttributeValueResolver(), diff --git a/src/Symfony/Component/HttpKernel/Fragment/AbstractSurrogateFragmentRenderer.php b/src/Symfony/Component/HttpKernel/Fragment/AbstractSurrogateFragmentRenderer.php index 07ab304e93ef1..74a0a7ca69981 100644 --- a/src/Symfony/Component/HttpKernel/Fragment/AbstractSurrogateFragmentRenderer.php +++ b/src/Symfony/Component/HttpKernel/Fragment/AbstractSurrogateFragmentRenderer.php @@ -85,7 +85,7 @@ public function render($uri, Request $request, array $options = array()) return new Response($tag); } - private function generateSignedFragmentUri($uri, Request $request) + private function generateSignedFragmentUri($uri, Request $request): string { if (null === $this->signer) { throw new \LogicException('You must use a URI when using the ESI rendering strategy or set a URL signer.'); @@ -97,7 +97,7 @@ private function generateSignedFragmentUri($uri, Request $request) return substr($fragmentUri, strlen($request->getSchemeAndHttpHost())); } - private function containsNonScalars(array $values) + private function containsNonScalars(array $values): bool { foreach ($values as $value) { if (is_array($value) && $this->containsNonScalars($value)) { diff --git a/src/Symfony/Component/HttpKernel/Fragment/HIncludeFragmentRenderer.php b/src/Symfony/Component/HttpKernel/Fragment/HIncludeFragmentRenderer.php index ec2a40716ab72..632da8f8a565f 100644 --- a/src/Symfony/Component/HttpKernel/Fragment/HIncludeFragmentRenderer.php +++ b/src/Symfony/Component/HttpKernel/Fragment/HIncludeFragmentRenderer.php @@ -123,12 +123,7 @@ public function render($uri, Request $request, array $options = array()) return new Response(sprintf('%s', $uri, $renderedAttributes, $content)); } - /** - * @param string $template - * - * @return bool - */ - private function templateExists($template) + private function templateExists(string $template): bool { if ($this->templating instanceof EngineInterface) { try { diff --git a/src/Symfony/Component/HttpKernel/HttpKernel.php b/src/Symfony/Component/HttpKernel/HttpKernel.php index 4a35a9990b761..394147fc3fdc5 100644 --- a/src/Symfony/Component/HttpKernel/HttpKernel.php +++ b/src/Symfony/Component/HttpKernel/HttpKernel.php @@ -118,7 +118,7 @@ public function terminateWithException(\Exception $exception) * @throws \LogicException If one of the listener does not behave as expected * @throws NotFoundHttpException When controller cannot be found */ - private function handleRaw(Request $request, $type = self::MASTER_REQUEST) + private function handleRaw(Request $request, int $type = self::MASTER_REQUEST) { $this->requestStack->push($request); @@ -184,7 +184,7 @@ private function handleRaw(Request $request, $type = self::MASTER_REQUEST) * * @throws \RuntimeException if the passed object is not a Response instance */ - private function filterResponse(Response $response, Request $request, $type) + private function filterResponse(Response $response, Request $request, int $type) { $event = new FilterResponseEvent($this, $request, $type, $response); @@ -205,7 +205,7 @@ private function filterResponse(Response $response, Request $request, $type) * @param Request $request * @param int $type */ - private function finishRequest(Request $request, $type) + private function finishRequest(Request $request, int $type) { $this->dispatcher->dispatch(KernelEvents::FINISH_REQUEST, new FinishRequestEvent($this, $request, $type)); $this->requestStack->pop(); @@ -222,7 +222,7 @@ private function finishRequest(Request $request, $type) * * @throws \Exception */ - private function handleException(\Exception $e, $request, $type) + private function handleException(\Exception $e, Request $request, int $type) { $event = new GetResponseForExceptionEvent($this, $request, $type, $e); $this->dispatcher->dispatch(KernelEvents::EXCEPTION, $event); @@ -257,7 +257,7 @@ private function handleException(\Exception $e, $request, $type) } } - private function varToString($var) + private function varToString($var): string { if (is_object($var)) { return sprintf('Object(%s)', get_class($var)); diff --git a/src/Symfony/Component/Inflector/Inflector.php b/src/Symfony/Component/Inflector/Inflector.php index fbe8cc8a45c72..cf685159a7f41 100644 --- a/src/Symfony/Component/Inflector/Inflector.php +++ b/src/Symfony/Component/Inflector/Inflector.php @@ -91,7 +91,7 @@ final class Inflector // accesses (access), addresses (address), kisses (kiss) array('sess', 4, true, false, 'ss'), - // analyses (analysis), ellipses (ellipsis), funguses (fungus), + // analyses (analysis), ellipses (ellipsis), fungi (fungus), // neuroses (neurosis), theses (thesis), emphases (emphasis), // oases (oasis), crises (crisis), houses (house), bases (base), // atlases (atlas) @@ -159,7 +159,7 @@ private function __construct() * * @internal */ - public static function singularize($plural) + public static function singularize(string $plural) { $pluralRev = strrev($plural); $lowerPluralRev = strtolower($pluralRev); diff --git a/src/Symfony/Component/Intl/Data/Provider/LanguageDataProvider.php b/src/Symfony/Component/Intl/Data/Provider/LanguageDataProvider.php index b601c91405b2c..c9256ccc58a8a 100644 --- a/src/Symfony/Component/Intl/Data/Provider/LanguageDataProvider.php +++ b/src/Symfony/Component/Intl/Data/Provider/LanguageDataProvider.php @@ -41,7 +41,7 @@ class LanguageDataProvider * @param BundleEntryReaderInterface $reader The reader for reading the .res * files. */ - public function __construct($path, BundleEntryReaderInterface $reader) + public function __construct(string $path, BundleEntryReaderInterface $reader) { $this->path = $path; $this->reader = $reader; diff --git a/src/Symfony/Component/Intl/DateFormatter/DateFormat/AmPmTransformer.php b/src/Symfony/Component/Intl/DateFormatter/DateFormat/AmPmTransformer.php index 66376475c666b..69d8a03a3aa9f 100644 --- a/src/Symfony/Component/Intl/DateFormatter/DateFormat/AmPmTransformer.php +++ b/src/Symfony/Component/Intl/DateFormatter/DateFormat/AmPmTransformer.php @@ -23,7 +23,7 @@ class AmPmTransformer extends Transformer /** * {@inheritdoc} */ - public function format(\DateTime $dateTime, $length) + public function format(\DateTime $dateTime, int $length): string { return $dateTime->format('A'); } @@ -31,7 +31,7 @@ public function format(\DateTime $dateTime, $length) /** * {@inheritdoc} */ - public function getReverseMatchingRegExp($length) + public function getReverseMatchingRegExp(int $length): string { return 'AM|PM'; } @@ -39,7 +39,7 @@ public function getReverseMatchingRegExp($length) /** * {@inheritdoc} */ - public function extractDateOptions($matched, $length) + public function extractDateOptions(string $matched, int $length): array { return array( 'marker' => $matched, diff --git a/src/Symfony/Component/Intl/DateFormatter/DateFormat/DayOfWeekTransformer.php b/src/Symfony/Component/Intl/DateFormatter/DateFormat/DayOfWeekTransformer.php index a174fdcabc570..0bbc5cb44f47d 100644 --- a/src/Symfony/Component/Intl/DateFormatter/DateFormat/DayOfWeekTransformer.php +++ b/src/Symfony/Component/Intl/DateFormatter/DateFormat/DayOfWeekTransformer.php @@ -23,7 +23,7 @@ class DayOfWeekTransformer extends Transformer /** * {@inheritdoc} */ - public function format(\DateTime $dateTime, $length) + public function format(\DateTime $dateTime, int $length): string { $dayOfWeek = $dateTime->format('l'); switch ($length) { @@ -41,7 +41,7 @@ public function format(\DateTime $dateTime, $length) /** * {@inheritdoc} */ - public function getReverseMatchingRegExp($length) + public function getReverseMatchingRegExp(int $length): string { switch ($length) { case 4: @@ -58,7 +58,7 @@ public function getReverseMatchingRegExp($length) /** * {@inheritdoc} */ - public function extractDateOptions($matched, $length) + public function extractDateOptions(string $matched, int $length): array { return array(); } diff --git a/src/Symfony/Component/Intl/DateFormatter/DateFormat/DayOfYearTransformer.php b/src/Symfony/Component/Intl/DateFormatter/DateFormat/DayOfYearTransformer.php index 5af6dd724336b..23000311c7eb0 100644 --- a/src/Symfony/Component/Intl/DateFormatter/DateFormat/DayOfYearTransformer.php +++ b/src/Symfony/Component/Intl/DateFormatter/DateFormat/DayOfYearTransformer.php @@ -23,7 +23,7 @@ class DayOfYearTransformer extends Transformer /** * {@inheritdoc} */ - public function format(\DateTime $dateTime, $length) + public function format(\DateTime $dateTime, int $length): string { $dayOfYear = $dateTime->format('z') + 1; @@ -33,7 +33,7 @@ public function format(\DateTime $dateTime, $length) /** * {@inheritdoc} */ - public function getReverseMatchingRegExp($length) + public function getReverseMatchingRegExp(int $length): string { return '\d{'.$length.'}'; } @@ -41,7 +41,7 @@ public function getReverseMatchingRegExp($length) /** * {@inheritdoc} */ - public function extractDateOptions($matched, $length) + public function extractDateOptions(string $matched, int $length): array { return array(); } diff --git a/src/Symfony/Component/Intl/DateFormatter/DateFormat/DayTransformer.php b/src/Symfony/Component/Intl/DateFormatter/DateFormat/DayTransformer.php index f0ded907c33c5..f05157f40269e 100644 --- a/src/Symfony/Component/Intl/DateFormatter/DateFormat/DayTransformer.php +++ b/src/Symfony/Component/Intl/DateFormatter/DateFormat/DayTransformer.php @@ -23,7 +23,7 @@ class DayTransformer extends Transformer /** * {@inheritdoc} */ - public function format(\DateTime $dateTime, $length) + public function format(\DateTime $dateTime, int $length): string { return $this->padLeft($dateTime->format('j'), $length); } @@ -31,7 +31,7 @@ public function format(\DateTime $dateTime, $length) /** * {@inheritdoc} */ - public function getReverseMatchingRegExp($length) + public function getReverseMatchingRegExp(int $length): string { return 1 === $length ? '\d{1,2}' : '\d{'.$length.'}'; } @@ -39,7 +39,7 @@ public function getReverseMatchingRegExp($length) /** * {@inheritdoc} */ - public function extractDateOptions($matched, $length) + public function extractDateOptions(string $matched, int $length): array { return array( 'day' => (int) $matched, diff --git a/src/Symfony/Component/Intl/DateFormatter/DateFormat/Hour1200Transformer.php b/src/Symfony/Component/Intl/DateFormatter/DateFormat/Hour1200Transformer.php index 948e3450443ef..dd3a1a8e71368 100644 --- a/src/Symfony/Component/Intl/DateFormatter/DateFormat/Hour1200Transformer.php +++ b/src/Symfony/Component/Intl/DateFormatter/DateFormat/Hour1200Transformer.php @@ -23,7 +23,7 @@ class Hour1200Transformer extends HourTransformer /** * {@inheritdoc} */ - public function format(\DateTime $dateTime, $length) + public function format(\DateTime $dateTime, int $length): string { $hourOfDay = $dateTime->format('g'); $hourOfDay = '12' == $hourOfDay ? '0' : $hourOfDay; @@ -34,7 +34,7 @@ public function format(\DateTime $dateTime, $length) /** * {@inheritdoc} */ - public function normalizeHour($hour, $marker = null) + public function normalizeHour(int $hour, string $marker = null): int { if ('PM' === $marker) { $hour += 12; @@ -46,7 +46,7 @@ public function normalizeHour($hour, $marker = null) /** * {@inheritdoc} */ - public function getReverseMatchingRegExp($length) + public function getReverseMatchingRegExp(int $length): string { return '\d{1,2}'; } @@ -54,7 +54,7 @@ public function getReverseMatchingRegExp($length) /** * {@inheritdoc} */ - public function extractDateOptions($matched, $length) + public function extractDateOptions(string $matched, int $length): array { return array( 'hour' => (int) $matched, diff --git a/src/Symfony/Component/Intl/DateFormatter/DateFormat/Hour1201Transformer.php b/src/Symfony/Component/Intl/DateFormatter/DateFormat/Hour1201Transformer.php index 19c4d203abe09..63aea50498ec0 100644 --- a/src/Symfony/Component/Intl/DateFormatter/DateFormat/Hour1201Transformer.php +++ b/src/Symfony/Component/Intl/DateFormatter/DateFormat/Hour1201Transformer.php @@ -23,7 +23,7 @@ class Hour1201Transformer extends HourTransformer /** * {@inheritdoc} */ - public function format(\DateTime $dateTime, $length) + public function format(\DateTime $dateTime, int $length): string { return $this->padLeft($dateTime->format('g'), $length); } @@ -31,7 +31,7 @@ public function format(\DateTime $dateTime, $length) /** * {@inheritdoc} */ - public function normalizeHour($hour, $marker = null) + public function normalizeHour(int $hour, string $marker = null): int { if ('PM' !== $marker && 12 === $hour) { $hour = 0; @@ -46,7 +46,7 @@ public function normalizeHour($hour, $marker = null) /** * {@inheritdoc} */ - public function getReverseMatchingRegExp($length) + public function getReverseMatchingRegExp(int $length): string { return '\d{1,2}'; } @@ -54,7 +54,7 @@ public function getReverseMatchingRegExp($length) /** * {@inheritdoc} */ - public function extractDateOptions($matched, $length) + public function extractDateOptions(string $matched, int $length): array { return array( 'hour' => (int) $matched, diff --git a/src/Symfony/Component/Intl/DateFormatter/DateFormat/Hour2400Transformer.php b/src/Symfony/Component/Intl/DateFormatter/DateFormat/Hour2400Transformer.php index e43d0ee8b2aec..78233f3d3806d 100644 --- a/src/Symfony/Component/Intl/DateFormatter/DateFormat/Hour2400Transformer.php +++ b/src/Symfony/Component/Intl/DateFormatter/DateFormat/Hour2400Transformer.php @@ -23,7 +23,7 @@ class Hour2400Transformer extends HourTransformer /** * {@inheritdoc} */ - public function format(\DateTime $dateTime, $length) + public function format(\DateTime $dateTime, int $length): string { return $this->padLeft($dateTime->format('G'), $length); } @@ -31,7 +31,7 @@ public function format(\DateTime $dateTime, $length) /** * {@inheritdoc} */ - public function normalizeHour($hour, $marker = null) + public function normalizeHour(int $hour, string $marker = null): int { if ('AM' == $marker) { $hour = 0; @@ -45,7 +45,7 @@ public function normalizeHour($hour, $marker = null) /** * {@inheritdoc} */ - public function getReverseMatchingRegExp($length) + public function getReverseMatchingRegExp(int $length): string { return '\d{1,2}'; } @@ -53,7 +53,7 @@ public function getReverseMatchingRegExp($length) /** * {@inheritdoc} */ - public function extractDateOptions($matched, $length) + public function extractDateOptions(string $matched, int $length): array { return array( 'hour' => (int) $matched, diff --git a/src/Symfony/Component/Intl/DateFormatter/DateFormat/Hour2401Transformer.php b/src/Symfony/Component/Intl/DateFormatter/DateFormat/Hour2401Transformer.php index df4e671aaf02b..e82c04da95314 100644 --- a/src/Symfony/Component/Intl/DateFormatter/DateFormat/Hour2401Transformer.php +++ b/src/Symfony/Component/Intl/DateFormatter/DateFormat/Hour2401Transformer.php @@ -23,7 +23,7 @@ class Hour2401Transformer extends HourTransformer /** * {@inheritdoc} */ - public function format(\DateTime $dateTime, $length) + public function format(\DateTime $dateTime, int $length): string { $hourOfDay = $dateTime->format('G'); $hourOfDay = ('0' == $hourOfDay) ? '24' : $hourOfDay; @@ -34,7 +34,7 @@ public function format(\DateTime $dateTime, $length) /** * {@inheritdoc} */ - public function normalizeHour($hour, $marker = null) + public function normalizeHour(int $hour, string $marker = null): int { if ((null === $marker && 24 === $hour) || 'AM' == $marker) { $hour = 0; @@ -48,7 +48,7 @@ public function normalizeHour($hour, $marker = null) /** * {@inheritdoc} */ - public function getReverseMatchingRegExp($length) + public function getReverseMatchingRegExp(int $length): string { return '\d{1,2}'; } @@ -56,7 +56,7 @@ public function getReverseMatchingRegExp($length) /** * {@inheritdoc} */ - public function extractDateOptions($matched, $length) + public function extractDateOptions(string $matched, int $length): array { return array( 'hour' => (int) $matched, diff --git a/src/Symfony/Component/Intl/DateFormatter/DateFormat/HourTransformer.php b/src/Symfony/Component/Intl/DateFormatter/DateFormat/HourTransformer.php index 349d8e29ae7a9..349cd794de3ae 100644 --- a/src/Symfony/Component/Intl/DateFormatter/DateFormat/HourTransformer.php +++ b/src/Symfony/Component/Intl/DateFormatter/DateFormat/HourTransformer.php @@ -28,5 +28,5 @@ abstract class HourTransformer extends Transformer * * @return int The normalized hour value */ - abstract public function normalizeHour($hour, $marker = null); + abstract public function normalizeHour(int $hour, string $marker = null): int; } diff --git a/src/Symfony/Component/Intl/DateFormatter/DateFormat/MinuteTransformer.php b/src/Symfony/Component/Intl/DateFormatter/DateFormat/MinuteTransformer.php index 08b5356e3fbd9..1f4dec8d1a161 100644 --- a/src/Symfony/Component/Intl/DateFormatter/DateFormat/MinuteTransformer.php +++ b/src/Symfony/Component/Intl/DateFormatter/DateFormat/MinuteTransformer.php @@ -23,7 +23,7 @@ class MinuteTransformer extends Transformer /** * {@inheritdoc} */ - public function format(\DateTime $dateTime, $length) + public function format(\DateTime $dateTime, int $length): string { $minuteOfHour = (int) $dateTime->format('i'); @@ -33,7 +33,7 @@ public function format(\DateTime $dateTime, $length) /** * {@inheritdoc} */ - public function getReverseMatchingRegExp($length) + public function getReverseMatchingRegExp(int $length): string { return 1 === $length ? '\d{1,2}' : '\d{'.$length.'}'; } @@ -41,7 +41,7 @@ public function getReverseMatchingRegExp($length) /** * {@inheritdoc} */ - public function extractDateOptions($matched, $length) + public function extractDateOptions(string $matched, int $length): array { return array( 'minute' => (int) $matched, diff --git a/src/Symfony/Component/Intl/DateFormatter/DateFormat/MonthTransformer.php b/src/Symfony/Component/Intl/DateFormatter/DateFormat/MonthTransformer.php index 6d7c819800339..75ca2d897c100 100644 --- a/src/Symfony/Component/Intl/DateFormatter/DateFormat/MonthTransformer.php +++ b/src/Symfony/Component/Intl/DateFormatter/DateFormat/MonthTransformer.php @@ -77,7 +77,7 @@ public function __construct() /** * {@inheritdoc} */ - public function format(\DateTime $dateTime, $length) + public function format(\DateTime $dateTime, int $length): string { $matchLengthMap = array( 1 => 'n', @@ -100,7 +100,7 @@ public function format(\DateTime $dateTime, $length) /** * {@inheritdoc} */ - public function getReverseMatchingRegExp($length) + public function getReverseMatchingRegExp(int $length): string { switch ($length) { case 1: @@ -126,7 +126,7 @@ public function getReverseMatchingRegExp($length) /** * {@inheritdoc} */ - public function extractDateOptions($matched, $length) + public function extractDateOptions(string $matched, int $length): array { if (!is_numeric($matched)) { if (3 === $length) { diff --git a/src/Symfony/Component/Intl/DateFormatter/DateFormat/QuarterTransformer.php b/src/Symfony/Component/Intl/DateFormatter/DateFormat/QuarterTransformer.php index fa7e91d038f8c..ec02e7f3059ba 100644 --- a/src/Symfony/Component/Intl/DateFormatter/DateFormat/QuarterTransformer.php +++ b/src/Symfony/Component/Intl/DateFormatter/DateFormat/QuarterTransformer.php @@ -23,7 +23,7 @@ class QuarterTransformer extends Transformer /** * {@inheritdoc} */ - public function format(\DateTime $dateTime, $length) + public function format(\DateTime $dateTime, int $length): string { $month = (int) $dateTime->format('n'); $quarter = (int) floor(($month - 1) / 3) + 1; @@ -43,7 +43,7 @@ public function format(\DateTime $dateTime, $length) /** * {@inheritdoc} */ - public function getReverseMatchingRegExp($length) + public function getReverseMatchingRegExp(int $length): string { switch ($length) { case 1: @@ -59,7 +59,7 @@ public function getReverseMatchingRegExp($length) /** * {@inheritdoc} */ - public function extractDateOptions($matched, $length) + public function extractDateOptions(string $matched, int $length): array { return array(); } diff --git a/src/Symfony/Component/Intl/DateFormatter/DateFormat/SecondTransformer.php b/src/Symfony/Component/Intl/DateFormatter/DateFormat/SecondTransformer.php index dd2e7bd9f9bb5..6b1ffd0ce15d2 100644 --- a/src/Symfony/Component/Intl/DateFormatter/DateFormat/SecondTransformer.php +++ b/src/Symfony/Component/Intl/DateFormatter/DateFormat/SecondTransformer.php @@ -23,7 +23,7 @@ class SecondTransformer extends Transformer /** * {@inheritdoc} */ - public function format(\DateTime $dateTime, $length) + public function format(\DateTime $dateTime, int $length): string { $secondOfMinute = (int) $dateTime->format('s'); @@ -33,7 +33,7 @@ public function format(\DateTime $dateTime, $length) /** * {@inheritdoc} */ - public function getReverseMatchingRegExp($length) + public function getReverseMatchingRegExp(int $length): string { return 1 === $length ? '\d{1,2}' : '\d{'.$length.'}'; } @@ -41,7 +41,7 @@ public function getReverseMatchingRegExp($length) /** * {@inheritdoc} */ - public function extractDateOptions($matched, $length) + public function extractDateOptions(string $matched, int $length): array { return array( 'second' => (int) $matched, diff --git a/src/Symfony/Component/Intl/DateFormatter/DateFormat/TimezoneTransformer.php b/src/Symfony/Component/Intl/DateFormatter/DateFormat/TimezoneTransformer.php index 1cfcc9bdea021..03026a46a1ecb 100644 --- a/src/Symfony/Component/Intl/DateFormatter/DateFormat/TimezoneTransformer.php +++ b/src/Symfony/Component/Intl/DateFormatter/DateFormat/TimezoneTransformer.php @@ -27,7 +27,7 @@ class TimezoneTransformer extends Transformer * * @throws NotImplementedException When time zone is different than UTC or GMT (Etc/GMT) */ - public function format(\DateTime $dateTime, $length) + public function format(\DateTime $dateTime, int $length): string { $timeZone = substr($dateTime->getTimezone()->getName(), 0, 3); @@ -63,7 +63,7 @@ public function format(\DateTime $dateTime, $length) /** * {@inheritdoc} */ - public function getReverseMatchingRegExp($length) + public function getReverseMatchingRegExp(int $length): string { return 'GMT[+-]\d{2}:?\d{2}'; } @@ -71,7 +71,7 @@ public function getReverseMatchingRegExp($length) /** * {@inheritdoc} */ - public function extractDateOptions($matched, $length) + public function extractDateOptions(string $matched, int $length): array { return array( 'timezone' => self::getEtcTimeZoneId($matched), diff --git a/src/Symfony/Component/Intl/DateFormatter/DateFormat/Transformer.php b/src/Symfony/Component/Intl/DateFormatter/DateFormat/Transformer.php index 26a25db355ca9..5bdb7267afd97 100644 --- a/src/Symfony/Component/Intl/DateFormatter/DateFormat/Transformer.php +++ b/src/Symfony/Component/Intl/DateFormatter/DateFormat/Transformer.php @@ -29,7 +29,7 @@ abstract class Transformer * * @return string The formatted value */ - abstract public function format(\DateTime $dateTime, $length); + abstract public function format(\DateTime $dateTime, int $length): string; /** * Returns a reverse matching regular expression of a string generated by format(). @@ -38,7 +38,7 @@ abstract public function format(\DateTime $dateTime, $length); * * @return string The reverse matching regular expression */ - abstract public function getReverseMatchingRegExp($length); + abstract public function getReverseMatchingRegExp(int $length): string; /** * Extract date options from a matched value returned by the processing of the reverse matching @@ -49,7 +49,7 @@ abstract public function getReverseMatchingRegExp($length); * * @return array An associative array */ - abstract public function extractDateOptions($matched, $length); + abstract public function extractDateOptions(string $matched, int $length): array; /** * Pad a string with zeros to the left. @@ -59,7 +59,7 @@ abstract public function extractDateOptions($matched, $length); * * @return string The padded string */ - protected function padLeft($value, $length) + protected function padLeft(string $value, int $length): string { return str_pad($value, $length, '0', STR_PAD_LEFT); } diff --git a/src/Symfony/Component/Intl/DateFormatter/DateFormat/YearTransformer.php b/src/Symfony/Component/Intl/DateFormatter/DateFormat/YearTransformer.php index 0b546b774a40c..b41420b722179 100644 --- a/src/Symfony/Component/Intl/DateFormatter/DateFormat/YearTransformer.php +++ b/src/Symfony/Component/Intl/DateFormatter/DateFormat/YearTransformer.php @@ -23,7 +23,7 @@ class YearTransformer extends Transformer /** * {@inheritdoc} */ - public function format(\DateTime $dateTime, $length) + public function format(\DateTime $dateTime, int $length): string { if (2 === $length) { return $dateTime->format('y'); @@ -35,7 +35,7 @@ public function format(\DateTime $dateTime, $length) /** * {@inheritdoc} */ - public function getReverseMatchingRegExp($length) + public function getReverseMatchingRegExp(int $length): string { return 2 === $length ? '\d{2}' : '\d{4}'; } @@ -43,7 +43,7 @@ public function getReverseMatchingRegExp($length) /** * {@inheritdoc} */ - public function extractDateOptions($matched, $length) + public function extractDateOptions(string $matched, int $length): array { return array( 'year' => (int) $matched, diff --git a/src/Symfony/Component/Intl/Locale.php b/src/Symfony/Component/Intl/Locale.php index ee09bd263cd42..3dfeacf3f314f 100644 --- a/src/Symfony/Component/Intl/Locale.php +++ b/src/Symfony/Component/Intl/Locale.php @@ -35,7 +35,7 @@ final class Locale extends \Locale * * @see getFallback() */ - public static function setDefaultFallback($locale) + public static function setDefaultFallback(string $locale) { self::$defaultFallback = $locale; } @@ -48,7 +48,7 @@ public static function setDefaultFallback($locale) * @see setDefaultFallback() * @see getFallback() */ - public static function getDefaultFallback() + public static function getDefaultFallback(): string { return self::$defaultFallback; } @@ -65,7 +65,7 @@ public static function getDefaultFallback() * @return string|null The ICU locale code of the fallback locale, or null * if no fallback exists */ - public static function getFallback($locale) + public static function getFallback($locale): ?string { if (false === $pos = strrpos($locale, '_')) { if (self::$defaultFallback === $locale) { @@ -78,7 +78,7 @@ public static function getFallback($locale) return self::$defaultFallback; } - return; + return null; } return substr($locale, 0, $pos); diff --git a/src/Symfony/Component/Intl/ResourceBundle/LanguageBundle.php b/src/Symfony/Component/Intl/ResourceBundle/LanguageBundle.php index d12b892a10dcb..84c676c742b5c 100644 --- a/src/Symfony/Component/Intl/ResourceBundle/LanguageBundle.php +++ b/src/Symfony/Component/Intl/ResourceBundle/LanguageBundle.php @@ -36,15 +36,7 @@ class LanguageBundle extends LanguageDataProvider implements LanguageBundleInter */ private $scriptProvider; - /** - * Creates a new language bundle. - * - * @param string $path - * @param BundleEntryReaderInterface $reader - * @param LocaleDataProvider $localeProvider - * @param ScriptDataProvider $scriptProvider - */ - public function __construct($path, BundleEntryReaderInterface $reader, LocaleDataProvider $localeProvider, ScriptDataProvider $scriptProvider) + public function __construct(string $path, BundleEntryReaderInterface $reader, LocaleDataProvider $localeProvider, ScriptDataProvider $scriptProvider) { parent::__construct($path, $reader); diff --git a/src/Symfony/Component/Ldap/Ldap.php b/src/Symfony/Component/Ldap/Ldap.php index 514f51d22c21a..26fd4f946ccc9 100644 --- a/src/Symfony/Component/Ldap/Ldap.php +++ b/src/Symfony/Component/Ldap/Ldap.php @@ -70,7 +70,7 @@ public function escape($subject, $ignore = '', $flags = 0) * * @return static */ - public static function create($adapter, array $config = array()) + public static function create($adapter, array $config = array()): Ldap { if (!isset(self::$adapterMap[$adapter])) { throw new DriverNotFoundException(sprintf( diff --git a/src/Symfony/Component/Lock/Key.php b/src/Symfony/Component/Lock/Key.php index 5069901761820..95936a3e89f38 100644 --- a/src/Symfony/Component/Lock/Key.php +++ b/src/Symfony/Component/Lock/Key.php @@ -25,9 +25,9 @@ final class Key /** * @param string $resource */ - public function __construct($resource) + public function __construct(string $resource) { - $this->resource = (string) $resource; + $this->resource = $resource; } public function __toString() @@ -35,39 +35,22 @@ public function __toString() return $this->resource; } - /** - * @param string $stateKey - * - * @return bool - */ - public function hasState($stateKey) + public function hasState(string $stateKey): bool { return isset($this->state[$stateKey]); } - /** - * @param string $stateKey - * @param mixed $state - */ - public function setState($stateKey, $state) + public function setState(string $stateKey, $state): void { $this->state[$stateKey] = $state; } - /** - * @param string $stateKey - */ - public function removeState($stateKey) + public function removeState(string $stateKey): void { unset($this->state[$stateKey]); } - /** - * @param $stateKey - * - * @return mixed - */ - public function getState($stateKey) + public function getState(string $stateKey) { return $this->state[$stateKey]; } diff --git a/src/Symfony/Component/PropertyAccess/PropertyAccess.php b/src/Symfony/Component/PropertyAccess/PropertyAccess.php index 3c8dc1c56cc18..e929347e6536c 100644 --- a/src/Symfony/Component/PropertyAccess/PropertyAccess.php +++ b/src/Symfony/Component/PropertyAccess/PropertyAccess.php @@ -23,17 +23,12 @@ final class PropertyAccess * * @return PropertyAccessor */ - public static function createPropertyAccessor() + public static function createPropertyAccessor(): PropertyAccessor { return self::createPropertyAccessorBuilder()->getPropertyAccessor(); } - /** - * Creates a property accessor builder. - * - * @return PropertyAccessorBuilder - */ - public static function createPropertyAccessorBuilder() + public static function createPropertyAccessorBuilder(): PropertyAccessorBuilder { return new PropertyAccessorBuilder(); } diff --git a/src/Symfony/Component/PropertyInfo/Extractor/ReflectionExtractor.php b/src/Symfony/Component/PropertyInfo/Extractor/ReflectionExtractor.php index 838fb9c4177f4..68506c4eb4da5 100644 --- a/src/Symfony/Component/PropertyInfo/Extractor/ReflectionExtractor.php +++ b/src/Symfony/Component/PropertyInfo/Extractor/ReflectionExtractor.php @@ -162,18 +162,18 @@ public function isWritable($class, $property, array $context = array()) * * @return Type[]|null */ - private function extractFromMutator($class, $property) + private function extractFromMutator(string $class, string $property): ?array { list($reflectionMethod, $prefix) = $this->getMutatorMethod($class, $property); if (null === $reflectionMethod) { - return; + return null; } $reflectionParameters = $reflectionMethod->getParameters(); $reflectionParameter = $reflectionParameters[0]; if (!$reflectionType = $reflectionParameter->getType()) { - return; + return null; } $type = $this->extractFromReflectionType($reflectionType); @@ -192,11 +192,11 @@ private function extractFromMutator($class, $property) * * @return Type[]|null */ - private function extractFromAccessor($class, $property) + private function extractFromAccessor(string $class, string $property): ?array { list($reflectionMethod, $prefix) = $this->getAccessorMethod($class, $property); if (null === $reflectionMethod) { - return; + return null; } if ($reflectionType = $reflectionMethod->getReturnType()) { @@ -206,6 +206,8 @@ private function extractFromAccessor($class, $property) if (in_array($prefix, array('is', 'can'))) { return array(new Type(Type::BUILTIN_TYPE_BOOL)); } + + return null; } /** @@ -215,7 +217,7 @@ private function extractFromAccessor($class, $property) * * @return Type */ - private function extractFromReflectionType(\ReflectionType $reflectionType) + private function extractFromReflectionType(\ReflectionType $reflectionType): Type { $phpTypeOrClass = $reflectionType->getName(); $nullable = $reflectionType->allowsNull(); @@ -241,7 +243,7 @@ private function extractFromReflectionType(\ReflectionType $reflectionType) * * @return bool */ - private function isPublicProperty($class, $property) + private function isPublicProperty(string $class, string $property): bool { try { $reflectionProperty = new \ReflectionProperty($class, $property); @@ -265,7 +267,7 @@ private function isPublicProperty($class, $property) * * @return array|null */ - private function getAccessorMethod($class, $property) + private function getAccessorMethod(string $class, string $property): ?array { $ucProperty = ucfirst($property); @@ -283,6 +285,8 @@ private function getAccessorMethod($class, $property) // Return null if the property doesn't exist } } + + return null; } /** @@ -296,7 +300,7 @@ private function getAccessorMethod($class, $property) * * @return array */ - private function getMutatorMethod($class, $property) + private function getMutatorMethod(string $class, string $property) { $ucProperty = ucfirst($property); $ucSingulars = (array) Inflector::singularize($ucProperty); @@ -333,7 +337,7 @@ private function getMutatorMethod($class, $property) * * @return string */ - private function getPropertyName($methodName, array $reflectionProperties) + private function getPropertyName(string $methodName, array $reflectionProperties) { $pattern = implode('|', array_merge($this->accessorPrefixes, $this->mutatorPrefixes)); diff --git a/src/Symfony/Component/PropertyInfo/Util/PhpDocTypeHelper.php b/src/Symfony/Component/PropertyInfo/Util/PhpDocTypeHelper.php index bc14cd8b69b1b..9c8fc8d3f676f 100644 --- a/src/Symfony/Component/PropertyInfo/Util/PhpDocTypeHelper.php +++ b/src/Symfony/Component/PropertyInfo/Util/PhpDocTypeHelper.php @@ -27,9 +27,9 @@ final class PhpDocTypeHelper /** * Creates a {@see Type} from a PHPDoc type. * - * @return Type + * @return Type[] */ - public function getTypes(DocType $varType) + public function getTypes(DocType $varType): array { $types = array(); $nullable = false; @@ -79,11 +79,11 @@ public function getTypes(DocType $varType) * * @return Type|null */ - private function createType($docType, $nullable) + private function createType(string $docType, bool $nullable): ?Type { // Cannot guess if (!$docType || 'mixed' === $docType) { - return; + return null; } if ($collection = '[]' === substr($docType, -2)) { @@ -110,14 +110,7 @@ private function createType($docType, $nullable) return new Type($phpType, $nullable, $class); } - /** - * Normalizes the type. - * - * @param string $docType - * - * @return string - */ - private function normalizeType($docType) + private function normalizeType(string $docType): string { switch ($docType) { case 'integer': @@ -141,14 +134,7 @@ private function normalizeType($docType) } } - /** - * Gets an array containing the PHP type and the class. - * - * @param string $docType - * - * @return array - */ - private function getPhpTypeAndClass($docType) + private function getPhpTypeAndClass(string $docType): array { if (in_array($docType, Type::$builtinTypes)) { return array($docType, null); diff --git a/src/Symfony/Component/Routing/Matcher/Dumper/DumperRoute.php b/src/Symfony/Component/Routing/Matcher/Dumper/DumperRoute.php index 3ad08c2006f24..9895de9110879 100644 --- a/src/Symfony/Component/Routing/Matcher/Dumper/DumperRoute.php +++ b/src/Symfony/Component/Routing/Matcher/Dumper/DumperRoute.php @@ -32,34 +32,18 @@ class DumperRoute */ private $route; - /** - * Constructor. - * - * @param string $name The route name - * @param Route $route The route - */ - public function __construct($name, Route $route) + public function __construct(string $name, Route $route) { $this->name = $name; $this->route = $route; } - /** - * Returns the route name. - * - * @return string The route name - */ - public function getName() + public function getName(): string { return $this->name; } - /** - * Returns the route. - * - * @return Route The route - */ - public function getRoute() + public function getRoute(): Route { return $this->route; } diff --git a/src/Symfony/Component/Routing/Matcher/Dumper/StaticPrefixCollection.php b/src/Symfony/Component/Routing/Matcher/Dumper/StaticPrefixCollection.php index b2bfa343764cc..675dab9193262 100644 --- a/src/Symfony/Component/Routing/Matcher/Dumper/StaticPrefixCollection.php +++ b/src/Symfony/Component/Routing/Matcher/Dumper/StaticPrefixCollection.php @@ -35,12 +35,12 @@ class StaticPrefixCollection */ private $matchStart = 0; - public function __construct($prefix = '') + public function __construct(string $prefix = '') { $this->prefix = $prefix; } - public function getPrefix() + public function getPrefix(): string { return $this->prefix; } @@ -48,7 +48,7 @@ public function getPrefix() /** * @return mixed[]|StaticPrefixCollection[] */ - public function getItems() + public function getItems(): array { return $this->items; } @@ -59,7 +59,7 @@ public function getItems() * @param string $prefix * @param mixed $route */ - public function addRoute($prefix, $route) + public function addRoute(string $prefix, $route) { $prefix = '/' === $prefix ? $prefix : rtrim($prefix, '/'); $this->guardAgainstAddingNotAcceptedRoutes($prefix); @@ -108,7 +108,7 @@ public function addRoute($prefix, $route) * * @return null|StaticPrefixCollection */ - private function groupWithItem($item, $prefix, $route) + private function groupWithItem($item, string $prefix, $route) { $itemPrefix = $item instanceof self ? $item->prefix : $item[0]; $commonPrefix = $this->detectCommonPrefix($prefix, $itemPrefix); @@ -137,7 +137,7 @@ private function groupWithItem($item, $prefix, $route) * * @return bool Whether a prefix could belong in a given group */ - private function accepts($prefix) + private function accepts(string $prefix): bool { return '' === $this->prefix || strpos($prefix, $this->prefix) === 0; } @@ -150,7 +150,7 @@ private function accepts($prefix) * * @return false|string A common prefix, longer than the base/group prefix, or false when none available */ - private function detectCommonPrefix($prefix, $anotherPrefix) + private function detectCommonPrefix(string $prefix, string $anotherPrefix) { $baseLength = strlen($this->prefix); $commonLength = $baseLength; @@ -176,7 +176,7 @@ private function detectCommonPrefix($prefix, $anotherPrefix) /** * Optimizes the tree by inlining items from groups with less than 3 items. */ - public function optimizeGroups() + public function optimizeGroups(): void { $index = -1; @@ -199,7 +199,7 @@ public function optimizeGroups() } } - private function shouldBeInlined() + private function shouldBeInlined(): bool { if (count($this->items) >= 3) { return false; @@ -227,7 +227,7 @@ private function shouldBeInlined() * * @throws \LogicException When a prefix does not belong in a group. */ - private function guardAgainstAddingNotAcceptedRoutes($prefix) + private function guardAgainstAddingNotAcceptedRoutes(string $prefix) { if (!$this->accepts($prefix)) { $message = sprintf('Could not add route with prefix %s to collection with prefix %s', $prefix, $this->prefix); diff --git a/src/Symfony/Component/Routing/RouteCollectionBuilder.php b/src/Symfony/Component/Routing/RouteCollectionBuilder.php index 3998ce1ededd4..6044ca99d3d1f 100644 --- a/src/Symfony/Component/Routing/RouteCollectionBuilder.php +++ b/src/Symfony/Component/Routing/RouteCollectionBuilder.php @@ -258,7 +258,7 @@ public function setMethods($methods) * * @return $this */ - private function addResource(ResourceInterface $resource) + private function addResource(ResourceInterface $resource): RouteCollectionBuilder { $this->resources[] = $resource; @@ -356,7 +356,7 @@ private function generateRouteName(Route $route) * * @throws FileLoaderLoadException If no loader is found */ - private function load($resource, $type = null) + private function load($resource, string $type = null): array { if (null === $this->loader) { throw new \BadMethodCallException('Cannot import other routing resources: you must pass a LoaderInterface when constructing RouteCollectionBuilder.'); diff --git a/src/Symfony/Component/Security/Core/Authentication/RememberMe/PersistentToken.php b/src/Symfony/Component/Security/Core/Authentication/RememberMe/PersistentToken.php index 76873fc603cd7..996ad285fdab0 100644 --- a/src/Symfony/Component/Security/Core/Authentication/RememberMe/PersistentToken.php +++ b/src/Symfony/Component/Security/Core/Authentication/RememberMe/PersistentToken.php @@ -24,18 +24,7 @@ final class PersistentToken implements PersistentTokenInterface private $tokenValue; private $lastUsed; - /** - * Constructor. - * - * @param string $class - * @param string $username - * @param string $series - * @param string $tokenValue - * @param \DateTime $lastUsed - * - * @throws \InvalidArgumentException - */ - public function __construct($class, $username, $series, $tokenValue, \DateTime $lastUsed) + public function __construct(string $class, string $username, string $series, string $tokenValue, \DateTime $lastUsed) { if (empty($class)) { throw new \InvalidArgumentException('$class must not be empty.'); diff --git a/src/Symfony/Component/Security/Http/Firewall/ExceptionListener.php b/src/Symfony/Component/Security/Http/Firewall/ExceptionListener.php index fc279c0b3ab96..2091c84f60ebe 100644 --- a/src/Symfony/Component/Security/Http/Firewall/ExceptionListener.php +++ b/src/Symfony/Component/Security/Http/Firewall/ExceptionListener.php @@ -104,7 +104,7 @@ public function onKernelException(GetResponseForExceptionEvent $event) } while (null !== $exception = $exception->getPrevious()); } - private function handleAuthenticationException(GetResponseForExceptionEvent $event, AuthenticationException $exception) + private function handleAuthenticationException(GetResponseForExceptionEvent $event, AuthenticationException $exception): void { if (null !== $this->logger) { $this->logger->info('An AuthenticationException was thrown; redirecting to authentication entry point.', array('exception' => $exception)); @@ -167,22 +167,14 @@ private function handleAccessDeniedException(GetResponseForExceptionEvent $event } } - private function handleLogoutException(LogoutException $exception) + private function handleLogoutException(LogoutException $exception): void { if (null !== $this->logger) { $this->logger->info('A LogoutException was thrown.', array('exception' => $exception)); } } - /** - * @param Request $request - * @param AuthenticationException $authException - * - * @return Response - * - * @throws AuthenticationException - */ - private function startAuthentication(Request $request, AuthenticationException $authException) + private function startAuthentication(Request $request, AuthenticationException $authException): Response { if (null === $this->authenticationEntryPoint) { throw $authException; @@ -216,9 +208,6 @@ private function startAuthentication(Request $request, AuthenticationException $ return $response; } - /** - * @param Request $request - */ protected function setTargetPath(Request $request) { // session isn't required when using HTTP basic authentication mechanism for example diff --git a/src/Symfony/Component/Translation/Translator.php b/src/Symfony/Component/Translation/Translator.php index 897aced2717b5..c877e43ba2e65 100644 --- a/src/Symfony/Component/Translation/Translator.php +++ b/src/Symfony/Component/Translation/Translator.php @@ -280,10 +280,7 @@ protected function initializeCatalogue($locale) $this->loadFallbackCatalogues($locale); } - /** - * @param string $locale - */ - private function initializeCacheCatalogue($locale) + private function initializeCacheCatalogue(string $locale): void { if (isset($this->catalogues[$locale])) { /* Catalogue already initialized. */ @@ -306,7 +303,7 @@ function (ConfigCacheInterface $cache) use ($locale) { $this->catalogues[$locale] = include $cache->getPath(); } - private function dumpCatalogue($locale, ConfigCacheInterface $cache) + private function dumpCatalogue($locale, ConfigCacheInterface $cache): void { $this->initializeCatalogue($locale); $fallbackContent = $this->getFallbackContent($this->catalogues[$locale]); @@ -331,7 +328,7 @@ private function dumpCatalogue($locale, ConfigCacheInterface $cache) $cache->write($content, $this->catalogues[$locale]->getResources()); } - private function getFallbackContent(MessageCatalogue $catalogue) + private function getFallbackContent(MessageCatalogue $catalogue): string { $fallbackContent = ''; $current = ''; @@ -366,7 +363,7 @@ private function getCatalogueCachePath($locale) return $this->cacheDir.'/catalogue.'.$locale.'.'.strtr(substr(base64_encode(hash('sha256', serialize($this->fallbackLocales), true)), 0, 7), '/', '_').'.php'; } - private function doLoadCatalogue($locale) + private function doLoadCatalogue($locale): void { $this->catalogues[$locale] = new MessageCatalogue($locale); @@ -380,7 +377,7 @@ private function doLoadCatalogue($locale) } } - private function loadFallbackCatalogues($locale) + private function loadFallbackCatalogues($locale): void { $current = $this->catalogues[$locale]; @@ -436,7 +433,7 @@ protected function assertValidLocale($locale) * * @return ConfigCacheFactoryInterface $configCacheFactory */ - private function getConfigCacheFactory() + private function getConfigCacheFactory(): ConfigCacheFactoryInterface { if (!$this->configCacheFactory) { $this->configCacheFactory = new ConfigCacheFactory($this->debug); diff --git a/src/Symfony/Component/Validator/Validation.php b/src/Symfony/Component/Validator/Validation.php index 950efb6cce267..71edfedb1839a 100644 --- a/src/Symfony/Component/Validator/Validation.php +++ b/src/Symfony/Component/Validator/Validation.php @@ -28,7 +28,7 @@ final class Validation * * @return ValidatorInterface The new validator */ - public static function createValidator() + public static function createValidator(): ValidatorInterface { return self::createValidatorBuilder()->getValidator(); } @@ -38,7 +38,7 @@ public static function createValidator() * * @return ValidatorBuilderInterface The new builder */ - public static function createValidatorBuilder() + public static function createValidatorBuilder(): ValidatorBuilder { return new ValidatorBuilder(); } diff --git a/src/Symfony/Component/WebLink/HttpHeaderSerializer.php b/src/Symfony/Component/WebLink/HttpHeaderSerializer.php index 66bfa55ab4a8b..01bb9f154b82d 100644 --- a/src/Symfony/Component/WebLink/HttpHeaderSerializer.php +++ b/src/Symfony/Component/WebLink/HttpHeaderSerializer.php @@ -29,7 +29,7 @@ final class HttpHeaderSerializer * * @return string|null */ - public function serialize($links) + public function serialize(iterable $links) { $elements = array(); foreach ($links as $link) { diff --git a/src/Symfony/Component/Workflow/Definition.php b/src/Symfony/Component/Workflow/Definition.php index 5f8571b329a09..a8bc0806e2906 100644 --- a/src/Symfony/Component/Workflow/Definition.php +++ b/src/Symfony/Component/Workflow/Definition.php @@ -30,7 +30,7 @@ final class Definition * @param Transition[] $transitions * @param string|null $initialPlace */ - public function __construct(array $places, array $transitions, $initialPlace = null) + public function __construct(array $places, array $transitions, string $initialPlace = null) { foreach ($places as $place) { $this->addPlace($place); @@ -54,7 +54,7 @@ public function getInitialPlace() /** * @return string[] */ - public function getPlaces() + public function getPlaces(): array { return $this->places; } @@ -62,12 +62,12 @@ public function getPlaces() /** * @return Transition[] */ - public function getTransitions() + public function getTransitions(): array { return $this->transitions; } - private function setInitialPlace($place) + private function setInitialPlace(string $place = null) { if (null === $place) { return; @@ -80,7 +80,7 @@ private function setInitialPlace($place) $this->initialPlace = $place; } - private function addPlace($place) + private function addPlace(string $place) { if (!preg_match('{^[\w\d_-]+$}', $place)) { throw new InvalidArgumentException(sprintf('The place "%s" contains invalid characters.', $place)); diff --git a/src/Symfony/Component/Workflow/Dumper/GraphvizDumper.php b/src/Symfony/Component/Workflow/Dumper/GraphvizDumper.php index 3681b6f1391a8..1344980bee711 100644 --- a/src/Symfony/Component/Workflow/Dumper/GraphvizDumper.php +++ b/src/Symfony/Component/Workflow/Dumper/GraphvizDumper.php @@ -201,7 +201,7 @@ protected function dotize($id) return strtolower(preg_replace('/[^\w]/i', '_', $id)); } - private function addAttributes(array $attributes) + private function addAttributes(array $attributes): string { $code = array(); @@ -212,7 +212,7 @@ private function addAttributes(array $attributes) return $code ? ', '.implode(', ', $code) : ''; } - private function addOptions(array $options) + private function addOptions(array $options): string { $code = array(); diff --git a/src/Symfony/Component/Workflow/EventListener/GuardListener.php b/src/Symfony/Component/Workflow/EventListener/GuardListener.php index 20ba04c007fc2..ad281f0fb8f4c 100644 --- a/src/Symfony/Component/Workflow/EventListener/GuardListener.php +++ b/src/Symfony/Component/Workflow/EventListener/GuardListener.php @@ -51,7 +51,7 @@ public function onTransition(GuardEvent $event, $eventName) } // code should be sync with Symfony\Component\Security\Core\Authorization\Voter\ExpressionVoter - private function getVariables(GuardEvent $event) + private function getVariables(GuardEvent $event): array { $token = $this->tokenStorage->getToken(); diff --git a/src/Symfony/Component/Workflow/Registry.php b/src/Symfony/Component/Workflow/Registry.php index b10af2fbbc0a4..2430dcb34ceaf 100644 --- a/src/Symfony/Component/Workflow/Registry.php +++ b/src/Symfony/Component/Workflow/Registry.php @@ -61,7 +61,7 @@ public function get($subject, $workflowName = null) return $matched; } - private function supports(Workflow $workflow, SupportStrategyInterface $supportStrategy, $subject, $workflowName) + private function supports(Workflow $workflow, SupportStrategyInterface $supportStrategy, $subject, $workflowName): bool { if (null !== $workflowName && $workflowName !== $workflow->getName()) { return false; diff --git a/src/Symfony/Component/Workflow/SupportStrategy/ClassInstanceSupportStrategy.php b/src/Symfony/Component/Workflow/SupportStrategy/ClassInstanceSupportStrategy.php index 8828946dbf543..ed4cd4e6ab189 100644 --- a/src/Symfony/Component/Workflow/SupportStrategy/ClassInstanceSupportStrategy.php +++ b/src/Symfony/Component/Workflow/SupportStrategy/ClassInstanceSupportStrategy.php @@ -11,10 +11,7 @@ final class ClassInstanceSupportStrategy implements SupportStrategyInterface { private $className; - /** - * @param string $className a FQCN - */ - public function __construct($className) + public function __construct(string $className) { $this->className = $className; } diff --git a/src/Symfony/Component/Yaml/Tag/TaggedValue.php b/src/Symfony/Component/Yaml/Tag/TaggedValue.php index 000c1d992cdee..4ea3406135999 100644 --- a/src/Symfony/Component/Yaml/Tag/TaggedValue.php +++ b/src/Symfony/Component/Yaml/Tag/TaggedValue.php @@ -20,27 +20,17 @@ final class TaggedValue private $tag; private $value; - /** - * @param string $tag - * @param mixed $value - */ - public function __construct($tag, $value) + public function __construct(string $tag, $value) { $this->tag = $tag; $this->value = $value; } - /** - * @return string - */ - public function getTag() + public function getTag(): string { return $this->tag; } - /** - * @return mixed - */ public function getValue() { return $this->value; From 0db3358ddb27918d0faa84fdd453e74257e9132f Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Wed, 30 Aug 2017 09:27:55 +0200 Subject: [PATCH 0737/1099] [DI] Add ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE --- .../DependencyInjection/CHANGELOG.md | 1 + .../Compiler/AnalyzeServiceReferencesPass.php | 4 +- ...xceptionOnInvalidReferenceBehaviorPass.php | 17 ++- .../Compiler/InlineServiceDefinitionsPass.php | 3 + .../RegisterServiceSubscribersPass.php | 3 + .../Compiler/RemoveUnusedDefinitionsPass.php | 3 + .../Compiler/ServiceReferenceGraph.php | 21 +-- .../Compiler/ServiceReferenceGraphEdge.php | 15 +- .../DependencyInjection/Container.php | 23 +-- .../DependencyInjection/ContainerBuilder.php | 48 +++++- .../ContainerInterface.php | 1 + .../DependencyInjection/Dumper/PhpDumper.php | 22 +-- .../DependencyInjection/Dumper/XmlDumper.php | 2 + .../DependencyInjection/Dumper/YamlDumper.php | 8 +- .../Loader/XmlFileLoader.php | 2 + .../Loader/YamlFileLoader.php | 3 + .../schema/dic/services/services-1.0.xsd | 1 + ...tionOnInvalidReferenceBehaviorPassTest.php | 21 +++ .../Tests/ContainerBuilderTest.php | 32 ++++ .../Tests/Dumper/PhpDumperTest.php | 38 +++++ .../Tests/Dumper/XmlDumperTest.php | 16 ++ .../Tests/Dumper/YamlDumperTest.php | 4 + .../container_uninitialized_ref.php | 46 ++++++ .../php/services_uninitialized_ref.php | 138 ++++++++++++++++++ .../Tests/Fixtures/xml/services_dump_load.xml | 11 ++ .../Fixtures/yaml/services_dump_load.yml | 1 + 26 files changed, 431 insertions(+), 53 deletions(-) create mode 100644 src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container_uninitialized_ref.php create mode 100644 src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_uninitialized_ref.php create mode 100644 src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services_dump_load.xml diff --git a/src/Symfony/Component/DependencyInjection/CHANGELOG.md b/src/Symfony/Component/DependencyInjection/CHANGELOG.md index 49e140de11796..4232369e2e007 100644 --- a/src/Symfony/Component/DependencyInjection/CHANGELOG.md +++ b/src/Symfony/Component/DependencyInjection/CHANGELOG.md @@ -4,6 +4,7 @@ CHANGELOG 3.4.0 ----- + * added support for ignore-on-uninitialized references * deprecated service auto-registration while autowiring * deprecated the ability to check for the initialization of a private service with the `Container::initialized()` method * deprecated support for top-level anonymous services in XML diff --git a/src/Symfony/Component/DependencyInjection/Compiler/AnalyzeServiceReferencesPass.php b/src/Symfony/Component/DependencyInjection/Compiler/AnalyzeServiceReferencesPass.php index 3a375f351652d..99eed81fcc4dd 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/AnalyzeServiceReferencesPass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/AnalyzeServiceReferencesPass.php @@ -12,6 +12,7 @@ namespace Symfony\Component\DependencyInjection\Compiler; use Symfony\Component\DependencyInjection\Argument\ArgumentInterface; +use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\DependencyInjection\ExpressionLanguage; use Symfony\Component\DependencyInjection\Reference; @@ -96,7 +97,8 @@ protected function processValue($value, $isRoot = false) $this->getDefinitionId((string) $value), $targetDefinition, $value, - $this->lazy || ($targetDefinition && $targetDefinition->isLazy()) + $this->lazy || ($targetDefinition && $targetDefinition->isLazy()), + ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE === $value->getInvalidBehavior() ); return $value; diff --git a/src/Symfony/Component/DependencyInjection/Compiler/CheckExceptionOnInvalidReferenceBehaviorPass.php b/src/Symfony/Component/DependencyInjection/Compiler/CheckExceptionOnInvalidReferenceBehaviorPass.php index 35fb325e74964..7ffedd3dc0523 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/CheckExceptionOnInvalidReferenceBehaviorPass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/CheckExceptionOnInvalidReferenceBehaviorPass.php @@ -11,6 +11,7 @@ namespace Symfony\Component\DependencyInjection\Compiler; +use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException; use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\DependencyInjection\Reference; @@ -24,14 +25,16 @@ class CheckExceptionOnInvalidReferenceBehaviorPass extends AbstractRecursivePass { protected function processValue($value, $isRoot = false) { - if ($value instanceof Reference && ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE === $value->getInvalidBehavior()) { - $destId = (string) $value; - - if (!$this->container->has($destId)) { - throw new ServiceNotFoundException($destId, $this->currentId); - } + if (!$value instanceof Reference) { + return parent::processValue($value, $isRoot); + } + if (ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE === $value->getInvalidBehavior() && !$this->container->has($id = (string) $value)) { + throw new ServiceNotFoundException($id, $this->currentId); + } + if (ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE === $value->getInvalidBehavior() && $this->container->has($id = (string) $value) && !$this->container->findDefinition($id)->isShared()) { + throw new InvalidArgumentException(sprintf('Invalid ignore-on-uninitialized reference found in service "%s": target service "%s" is not shared.', $this->currentId, $id)); } - return parent::processValue($value, $isRoot); + return $value; } } diff --git a/src/Symfony/Component/DependencyInjection/Compiler/InlineServiceDefinitionsPass.php b/src/Symfony/Component/DependencyInjection/Compiler/InlineServiceDefinitionsPass.php index f2ef363c837cc..240e1ab65527f 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/InlineServiceDefinitionsPass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/InlineServiceDefinitionsPass.php @@ -96,6 +96,9 @@ private function isInlineableDefinition($id, Definition $definition, ServiceRefe $ids = array(); foreach ($graph->getNode($id)->getInEdges() as $edge) { + if ($edge->isWeak()) { + return false; + } $ids[] = $edge->getSourceNode()->getId(); } diff --git a/src/Symfony/Component/DependencyInjection/Compiler/RegisterServiceSubscribersPass.php b/src/Symfony/Component/DependencyInjection/Compiler/RegisterServiceSubscribersPass.php index f8dba86a0b547..8c81452b315a6 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/RegisterServiceSubscribersPass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/RegisterServiceSubscribersPass.php @@ -74,6 +74,9 @@ protected function processValue($value, $isRoot = false) if ($optionalBehavior = '?' === $type[0]) { $type = substr($type, 1); $optionalBehavior = ContainerInterface::IGNORE_ON_INVALID_REFERENCE; + } elseif ($optionalBehavior = '!' === $type[0]) { + $type = substr($type, 1); + $optionalBehavior = ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE; } if (is_int($key)) { $key = $type; diff --git a/src/Symfony/Component/DependencyInjection/Compiler/RemoveUnusedDefinitionsPass.php b/src/Symfony/Component/DependencyInjection/Compiler/RemoveUnusedDefinitionsPass.php index 79a2600d8f785..a8a01be6d5291 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/RemoveUnusedDefinitionsPass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/RemoveUnusedDefinitionsPass.php @@ -50,6 +50,9 @@ public function process(ContainerBuilder $container) $referencingAliases = array(); $sourceIds = array(); foreach ($edges as $edge) { + if ($edge->isWeak()) { + continue; + } $node = $edge->getSourceNode(); $sourceIds[] = $node->getId(); diff --git a/src/Symfony/Component/DependencyInjection/Compiler/ServiceReferenceGraph.php b/src/Symfony/Component/DependencyInjection/Compiler/ServiceReferenceGraph.php index 193a37e20b0f6..3a6f03ee6d862 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/ServiceReferenceGraph.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/ServiceReferenceGraph.php @@ -20,6 +20,8 @@ * it themselves which improves performance quite a lot. * * @author Johannes M. Schmitt + * + * @final since version 3.4 */ class ServiceReferenceGraph { @@ -85,23 +87,16 @@ public function clear() * @param string $destValue * @param string $reference * @param bool $lazy + * @param bool $weak */ - public function connect($sourceId, $sourceValue, $destId, $destValue = null, $reference = null/*, bool $lazy = false*/) + public function connect($sourceId, $sourceValue, $destId, $destValue = null, $reference = null/*, bool $lazy = false, bool $weak = false*/) { - if (func_num_args() >= 6) { - $lazy = func_get_arg(5); - } else { - if (__CLASS__ !== get_class($this)) { - $r = new \ReflectionMethod($this, __FUNCTION__); - if (__CLASS__ !== $r->getDeclaringClass()->getName()) { - @trigger_error(sprintf('Method %s() will have a 6th `bool $lazy = false` argument in version 4.0. Not defining it is deprecated since 3.3.', __METHOD__), E_USER_DEPRECATED); - } - } - $lazy = false; - } + $lazy = func_num_args() >= 6 ? func_get_arg(5) : false; + $weak = func_num_args() >= 7 ? func_get_arg(6) : false; + $sourceNode = $this->createNode($sourceId, $sourceValue); $destNode = $this->createNode($destId, $destValue); - $edge = new ServiceReferenceGraphEdge($sourceNode, $destNode, $reference, $lazy); + $edge = new ServiceReferenceGraphEdge($sourceNode, $destNode, $reference, $lazy, $weak); $sourceNode->addOutEdge($edge); $destNode->addInEdge($edge); diff --git a/src/Symfony/Component/DependencyInjection/Compiler/ServiceReferenceGraphEdge.php b/src/Symfony/Component/DependencyInjection/Compiler/ServiceReferenceGraphEdge.php index 17dd5d9559f9d..5b8256977f8e4 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/ServiceReferenceGraphEdge.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/ServiceReferenceGraphEdge.php @@ -24,19 +24,22 @@ class ServiceReferenceGraphEdge private $destNode; private $value; private $lazy; + private $weak; /** * @param ServiceReferenceGraphNode $sourceNode * @param ServiceReferenceGraphNode $destNode * @param string $value * @param bool $lazy + * @param bool $weak */ - public function __construct(ServiceReferenceGraphNode $sourceNode, ServiceReferenceGraphNode $destNode, $value = null, $lazy = false) + public function __construct(ServiceReferenceGraphNode $sourceNode, ServiceReferenceGraphNode $destNode, $value = null, $lazy = false, $weak = false) { $this->sourceNode = $sourceNode; $this->destNode = $destNode; $this->value = $value; $this->lazy = $lazy; + $this->weak = $weak; } /** @@ -78,4 +81,14 @@ public function isLazy() { return $this->lazy; } + + /** + * Returns true if the edge is weak, meaning it shouldn't prevent removing the target service. + * + * @return bool + */ + public function isWeak() + { + return $this->weak; + } } diff --git a/src/Symfony/Component/DependencyInjection/Container.php b/src/Symfony/Component/DependencyInjection/Container.php index 30bf1a0a6ccea..ac423bd4a4739 100644 --- a/src/Symfony/Component/DependencyInjection/Container.php +++ b/src/Symfony/Component/DependencyInjection/Container.php @@ -23,26 +23,15 @@ * Container is a dependency injection container. * * It gives access to object instances (services). - * * Services and parameters are simple key/pair stores. - * - * Parameter and service keys are case insensitive. - * - * A service can also be defined by creating a method named - * getXXXService(), where XXX is the camelized version of the id: - * - *
    - *
  • request -> getRequestService()
  • - *
  • mysql_session_storage -> getMysqlSessionStorageService()
  • - *
  • symfony.mysql_session_storage -> getSymfony_MysqlSessionStorageService()
  • - *
- * - * The container can have three possible behaviors when a service does not exist: + * The container can have four possible behaviors when a service + * does not exist (or is not initialized for the last case): * * * EXCEPTION_ON_INVALID_REFERENCE: Throws an exception (the default) * * NULL_ON_INVALID_REFERENCE: Returns null * * IGNORE_ON_INVALID_REFERENCE: Ignores the wrapping command asking for the reference * (for instance, ignore a setter if the service does not exist) + * * IGNORE_ON_UNINITIALIZED_REFERENCE: Ignores/returns null for uninitialized services or invalid references * * @author Fabien Potencier * @author Johannes M. Schmitt @@ -304,9 +293,9 @@ public function get($id, $invalidBehavior = self::EXCEPTION_ON_INVALID_REFERENCE try { if (isset($this->fileMap[$id])) { - return $this->load($this->fileMap[$id]); + return self::IGNORE_ON_UNINITIALIZED_REFERENCE === $invalidBehavior ? null : $this->load($this->fileMap[$id]); } elseif (isset($this->methodMap[$id])) { - return $this->{$this->methodMap[$id]}(); + return self::IGNORE_ON_UNINITIALIZED_REFERENCE === $invalidBehavior ? null : $this->{$this->methodMap[$id]}(); } elseif (--$i && $id !== $normalizedId = $this->normalizeId($id)) { $id = $normalizedId; continue; @@ -315,7 +304,7 @@ public function get($id, $invalidBehavior = self::EXCEPTION_ON_INVALID_REFERENCE // and only when the dumper has not generated the method map (otherwise the method map is considered to be fully populated by the dumper) @trigger_error('Generating a dumped container without populating the method map is deprecated since 3.2 and will be unsupported in 4.0. Update your dumper to generate the method map.', E_USER_DEPRECATED); - return $this->{$method}(); + return self::IGNORE_ON_UNINITIALIZED_REFERENCE === $invalidBehavior ? null : $this->{$method}(); } break; diff --git a/src/Symfony/Component/DependencyInjection/ContainerBuilder.php b/src/Symfony/Component/DependencyInjection/ContainerBuilder.php index 683f8777e5c7e..2b8dfd6a3e520 100644 --- a/src/Symfony/Component/DependencyInjection/ContainerBuilder.php +++ b/src/Symfony/Component/DependencyInjection/ContainerBuilder.php @@ -565,6 +565,9 @@ public function get($id, $invalidBehavior = ContainerInterface::EXCEPTION_ON_INV { $id = $this->normalizeId($id); + if (ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE === $invalidBehavior) { + return parent::get($id, $invalidBehavior); + } if ($service = parent::get($id, ContainerInterface::NULL_ON_INVALID_REFERENCE)) { return $service; } @@ -1160,6 +1163,11 @@ public function resolveServices($value) continue 2; } } + foreach (self::getInitializedConditionals($v) as $s) { + if (!$this->get($s, ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE)) { + continue 2; + } + } yield $k => $this->resolveServices($v); } @@ -1171,6 +1179,11 @@ public function resolveServices($value) continue 2; } } + foreach (self::getInitializedConditionals($v) as $s) { + if (!$this->get($s, ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE)) { + continue 2; + } + } ++$count; } @@ -1397,6 +1410,8 @@ public function log(CompilerPassInterface $pass, $message) * @param mixed $value An array of conditionals to return * * @return array An array of Service conditionals + * + * @internal since version 3.4 */ public static function getServiceConditionals($value) { @@ -1413,6 +1428,30 @@ public static function getServiceConditionals($value) return $services; } + /** + * Returns the initialized conditionals. + * + * @param mixed $value An array of conditionals to return + * + * @return array An array of uninitialized conditionals + * + * @internal + */ + public static function getInitializedConditionals($value) + { + $services = array(); + + if (is_array($value)) { + foreach ($value as $v) { + $services = array_unique(array_merge($services, self::getInitializedConditionals($v))); + } + } elseif ($value instanceof Reference && $value->getInvalidBehavior() === ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE) { + $services[] = (string) $value; + } + + return $services; + } + /** * Computes a reasonably unique hash of a value. * @@ -1465,13 +1504,16 @@ private function getProxyInstantiator() private function callMethod($service, $call) { - $services = self::getServiceConditionals($call[1]); - - foreach ($services as $s) { + foreach (self::getServiceConditionals($call[1]) as $s) { if (!$this->has($s)) { return; } } + foreach (self::getInitializedConditionals($call[1]) as $s) { + if (!$this->get($s, ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE)) { + return; + } + } call_user_func_array(array($service, $call[0]), $this->resolveServices($this->getParameterBag()->unescapeValue($this->getParameterBag()->resolveValue($call[1])))); } diff --git a/src/Symfony/Component/DependencyInjection/ContainerInterface.php b/src/Symfony/Component/DependencyInjection/ContainerInterface.php index cfbc828722d8a..2274ec7bb3266 100644 --- a/src/Symfony/Component/DependencyInjection/ContainerInterface.php +++ b/src/Symfony/Component/DependencyInjection/ContainerInterface.php @@ -27,6 +27,7 @@ interface ContainerInterface extends PsrContainerInterface const EXCEPTION_ON_INVALID_REFERENCE = 1; const NULL_ON_INVALID_REFERENCE = 2; const IGNORE_ON_INVALID_REFERENCE = 3; + const IGNORE_ON_UNINITIALIZED_REFERENCE = 4; /** * Sets a service. diff --git a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php index 49cd09f02a0c3..49e90a4115cce 100644 --- a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php +++ b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php @@ -277,7 +277,7 @@ private function addServiceLocalTempVariables($cId, Definition $definition, arra if (ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE === $behavior[$id]) { $code .= sprintf($template, $name, $this->getServiceCall($id)); } else { - $code .= sprintf($template, $name, $this->getServiceCall($id, new Reference($id, ContainerInterface::NULL_ON_INVALID_REFERENCE))); + $code .= sprintf($template, $name, $this->getServiceCall($id, new Reference($id, $behavior[$id]))); } } } @@ -1295,12 +1295,14 @@ private function wrapServiceConditionals($value, $code) */ private function getServiceConditionals($value) { - if (!$services = ContainerBuilder::getServiceConditionals($value)) { - return null; - } - $conditions = array(); - foreach ($services as $service) { + foreach (ContainerBuilder::getInitializedConditionals($value) as $service) { + if (!$this->container->hasDefinition($service)) { + return 'false'; + } + $conditions[] = sprintf("isset(\$this->services['%s'])", $service); + } + foreach (ContainerBuilder::getServiceConditionals($value) as $service) { if ($this->container->hasDefinition($service) && !$this->container->getDefinition($service)->isPublic()) { continue; } @@ -1335,8 +1337,8 @@ private function getServiceCallsFromArguments(array $arguments, array &$calls, a } if (!isset($behavior[$id])) { $behavior[$id] = $argument->getInvalidBehavior(); - } elseif (ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE !== $behavior[$id]) { - $behavior[$id] = $argument->getInvalidBehavior(); + } else { + $behavior[$id] = min($behavior[$id], $argument->getInvalidBehavior()); } ++$calls[$id]; @@ -1665,7 +1667,9 @@ private function getServiceCall($id, Reference $reference = null) return '$this'; } - if ($this->asFiles && $this->container->hasDefinition($id)) { + if (null !== $reference && ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE === $reference->getInvalidBehavior()) { + $code = 'null'; + } elseif ($this->asFiles && $this->container->hasDefinition($id)) { if ($this->container->getDefinition($id)->isShared()) { $code = sprintf("\$this->load(__DIR__.'/%s.php')", $this->generateMethodName($id)); } else { diff --git a/src/Symfony/Component/DependencyInjection/Dumper/XmlDumper.php b/src/Symfony/Component/DependencyInjection/Dumper/XmlDumper.php index c6b3be06a1402..2bfefeb2d1e23 100644 --- a/src/Symfony/Component/DependencyInjection/Dumper/XmlDumper.php +++ b/src/Symfony/Component/DependencyInjection/Dumper/XmlDumper.php @@ -309,6 +309,8 @@ private function convertParameters(array $parameters, $type, \DOMElement $parent $element->setAttribute('on-invalid', 'null'); } elseif ($behaviour == ContainerInterface::IGNORE_ON_INVALID_REFERENCE) { $element->setAttribute('on-invalid', 'ignore'); + } elseif ($behaviour == ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE) { + $element->setAttribute('on-invalid', 'ignore_uninitialized'); } } elseif ($value instanceof Definition) { $element->setAttribute('type', 'service'); diff --git a/src/Symfony/Component/DependencyInjection/Dumper/YamlDumper.php b/src/Symfony/Component/DependencyInjection/Dumper/YamlDumper.php index 76f97315c793a..d8f07edc08e5c 100644 --- a/src/Symfony/Component/DependencyInjection/Dumper/YamlDumper.php +++ b/src/Symfony/Component/DependencyInjection/Dumper/YamlDumper.php @@ -304,8 +304,12 @@ private function dumpValue($value) */ private function getServiceCall($id, Reference $reference = null) { - if (null !== $reference && ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE !== $reference->getInvalidBehavior()) { - return sprintf('@?%s', $id); + if (null !== $reference) { + switch ($reference->getInvalidBehavior()) { + case ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE: break; + case ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE: return sprintf('@!%s', $id); + default: return sprintf('@?%s', $id); + } } return sprintf('@%s', $id); diff --git a/src/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php b/src/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php index 0a5f9593d4ef0..a5ee960a70170 100644 --- a/src/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php +++ b/src/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php @@ -492,6 +492,8 @@ private function getArgumentsAsPhp(\DOMElement $node, $name, $file, $lowercase = $invalidBehavior = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE; if ('ignore' == $onInvalid) { $invalidBehavior = ContainerInterface::IGNORE_ON_INVALID_REFERENCE; + } elseif ('ignore_uninitialized' == $onInvalid) { + $invalidBehavior = ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE; } elseif ('null' == $onInvalid) { $invalidBehavior = ContainerInterface::NULL_ON_INVALID_REFERENCE; } diff --git a/src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php b/src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php index 8a1c51f4e6fc1..b57ead2c89015 100644 --- a/src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php +++ b/src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php @@ -758,6 +758,9 @@ private function resolveServices($value, $file, $isParameter = false) if (0 === strpos($value, '@@')) { $value = substr($value, 1); $invalidBehavior = null; + } elseif (0 === strpos($value, '@!')) { + $value = substr($value, 2); + $invalidBehavior = ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE; } elseif (0 === strpos($value, '@?')) { $value = substr($value, 2); $invalidBehavior = ContainerInterface::IGNORE_ON_INVALID_REFERENCE; diff --git a/src/Symfony/Component/DependencyInjection/Loader/schema/dic/services/services-1.0.xsd b/src/Symfony/Component/DependencyInjection/Loader/schema/dic/services/services-1.0.xsd index aad40ac63138d..0be8658e3d547 100644 --- a/src/Symfony/Component/DependencyInjection/Loader/schema/dic/services/services-1.0.xsd +++ b/src/Symfony/Component/DependencyInjection/Loader/schema/dic/services/services-1.0.xsd @@ -266,6 +266,7 @@ + diff --git a/src/Symfony/Component/DependencyInjection/Tests/Compiler/CheckExceptionOnInvalidReferenceBehaviorPassTest.php b/src/Symfony/Component/DependencyInjection/Tests/Compiler/CheckExceptionOnInvalidReferenceBehaviorPassTest.php index 65a782a4a83fc..dc20b39bc4dca 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Compiler/CheckExceptionOnInvalidReferenceBehaviorPassTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Compiler/CheckExceptionOnInvalidReferenceBehaviorPassTest.php @@ -67,6 +67,27 @@ public function testProcessThrowsExceptionOnInvalidReferenceFromInlinedDefinitio $this->process($container); } + /** + * @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException + * @expectedExceptionMessage Invalid ignore-on-uninitialized reference found in service + */ + public function testProcessThrowsExceptionOnNonSharedUninitializedReference() + { + $container = new ContainerBuilder(); + + $container + ->register('a', 'stdClass') + ->addArgument(new Reference('b', $container::IGNORE_ON_UNINITIALIZED_REFERENCE)) + ; + + $container + ->register('b', 'stdClass') + ->setShared(false) + ; + + $this->process($container); + } + private function process(ContainerBuilder $container) { $pass = new CheckExceptionOnInvalidReferenceBehaviorPass(); diff --git a/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php b/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php index 895e035185f06..54e3227d23f18 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php @@ -1098,6 +1098,38 @@ public function testServiceLocator() $this->assertSame($container->get('bar_service'), $foo->get('bar')); } + public function testUninitializedReference() + { + $container = include __DIR__.'/Fixtures/containers/container_uninitialized_ref.php'; + $container->compile(); + + $bar = $container->get('bar'); + + $this->assertNull($bar->foo1); + $this->assertNull($bar->foo2); + $this->assertNull($bar->foo3); + $this->assertNull($bar->closures[0]()); + $this->assertNull($bar->closures[1]()); + $this->assertNull($bar->closures[2]()); + $this->assertSame(array(), iterator_to_array($bar->iter)); + + $container = include __DIR__.'/Fixtures/containers/container_uninitialized_ref.php'; + $container->compile(); + + $container->get('foo1'); + $container->get('baz'); + + $bar = $container->get('bar'); + + $this->assertEquals(new \stdClass(), $bar->foo1); + $this->assertNull($bar->foo2); + $this->assertEquals(new \stdClass(), $bar->foo3); + $this->assertEquals(new \stdClass(), $bar->closures[0]()); + $this->assertNull($bar->closures[1]()); + $this->assertEquals(new \stdClass(), $bar->closures[2]()); + $this->assertEquals(array('foo1' => new \stdClass(), 'foo3' => new \stdClass()), iterator_to_array($bar->iter)); + } + public function testRegisterForAutoconfiguration() { $container = new ContainerBuilder(); diff --git a/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php b/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php index 338d7b5bb383b..62213ee2804bc 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php @@ -631,6 +631,44 @@ public function testExpressionReferencingPrivateService() $this->assertStringEqualsFile(self::$fixturesPath.'/php/services_private_in_expression.php', $dumper->dump()); } + public function testUninitializedReference() + { + $container = include self::$fixturesPath.'/containers/container_uninitialized_ref.php'; + $container->compile(); + $dumper = new PhpDumper($container); + + $this->assertStringEqualsFile(self::$fixturesPath.'/php/services_uninitialized_ref.php', $dumper->dump(array('class' => 'Symfony_DI_PhpDumper_Test_Uninitialized_Reference'))); + + require self::$fixturesPath.'/php/services_uninitialized_ref.php'; + + $container = new \Symfony_DI_PhpDumper_Test_Uninitialized_Reference(); + + $bar = $container->get('bar'); + + $this->assertNull($bar->foo1); + $this->assertNull($bar->foo2); + $this->assertNull($bar->foo3); + $this->assertNull($bar->closures[0]()); + $this->assertNull($bar->closures[1]()); + $this->assertNull($bar->closures[2]()); + $this->assertSame(array(), iterator_to_array($bar->iter)); + + $container = new \Symfony_DI_PhpDumper_Test_Uninitialized_Reference(); + + $container->get('foo1'); + $container->get('baz'); + + $bar = $container->get('bar'); + + $this->assertEquals(new \stdClass(), $bar->foo1); + $this->assertNull($bar->foo2); + $this->assertEquals(new \stdClass(), $bar->foo3); + $this->assertEquals(new \stdClass(), $bar->closures[0]()); + $this->assertNull($bar->closures[1]()); + $this->assertEquals(new \stdClass(), $bar->closures[2]()); + $this->assertEquals(array('foo1' => new \stdClass(), 'foo3' => new \stdClass()), iterator_to_array($bar->iter)); + } + public function testDumpHandlesLiteralClassWithRootNamespace() { $container = new ContainerBuilder(); diff --git a/src/Symfony/Component/DependencyInjection/Tests/Dumper/XmlDumperTest.php b/src/Symfony/Component/DependencyInjection/Tests/Dumper/XmlDumperTest.php index 3ac6628b737e6..8a34a2b19a297 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Dumper/XmlDumperTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Dumper/XmlDumperTest.php @@ -12,8 +12,12 @@ namespace Symfony\Component\DependencyInjection\Tests\Dumper; use PHPUnit\Framework\TestCase; +use Symfony\Component\Config\FileLocator; use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\DependencyInjection\Dumper\XmlDumper; +use Symfony\Component\DependencyInjection\Loader\XmlFileLoader; +use Symfony\Component\DependencyInjection\Reference; class XmlDumperTest extends TestCase { @@ -184,6 +188,18 @@ public function testDumpAutowireData() $this->assertEquals(file_get_contents(self::$fixturesPath.'/xml/services24.xml'), $dumper->dump()); } + public function testDumpLoad() + { + $container = new ContainerBuilder(); + $loader = new XmlFileLoader($container, new FileLocator(self::$fixturesPath.'/xml')); + $loader->load('services_dump_load.xml'); + + $this->assertEquals(array(new Reference('bar', ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE)), $container->getDefinition('foo')->getArguments()); + + $dumper = new XmlDumper($container); + $this->assertStringEqualsFile(self::$fixturesPath.'/xml/services_dump_load.xml', $dumper->dump()); + } + public function testDumpAbstractServices() { $container = include self::$fixturesPath.'/containers/container_abstract.php'; diff --git a/src/Symfony/Component/DependencyInjection/Tests/Dumper/YamlDumperTest.php b/src/Symfony/Component/DependencyInjection/Tests/Dumper/YamlDumperTest.php index 968385633b549..85ce181461419 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Dumper/YamlDumperTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Dumper/YamlDumperTest.php @@ -14,9 +14,11 @@ use PHPUnit\Framework\TestCase; use Symfony\Component\Config\FileLocator; use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\DependencyInjection\Dumper\YamlDumper; use Symfony\Component\DependencyInjection\Loader\YamlFileLoader; +use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\Yaml\Yaml; use Symfony\Component\Yaml\Parser; @@ -73,6 +75,8 @@ public function testDumpLoad() $loader = new YamlFileLoader($container, new FileLocator(self::$fixturesPath.'/yaml')); $loader->load('services_dump_load.yml'); + $this->assertEquals(array(new Reference('bar', ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE)), $container->getDefinition('foo')->getArguments()); + $dumper = new YamlDumper($container); $this->assertStringEqualsFile(self::$fixturesPath.'/yaml/services_dump_load.yml', $dumper->dump()); } diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container_uninitialized_ref.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container_uninitialized_ref.php new file mode 100644 index 0000000000000..9ecf7c909f04a --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container_uninitialized_ref.php @@ -0,0 +1,46 @@ +register('foo1', 'stdClass') +; + +$container + ->register('foo2', 'stdClass') + ->setPublic(false) +; + +$container + ->register('foo3', 'stdClass') + ->setPublic(false) +; + +$container + ->register('baz', 'stdClass') + ->setProperty('foo3', new Reference('foo3')) +; + +$container + ->register('bar', 'stdClass') + ->setProperty('foo1', new Reference('foo1', $container::IGNORE_ON_UNINITIALIZED_REFERENCE)) + ->setProperty('foo2', new Reference('foo2', $container::IGNORE_ON_UNINITIALIZED_REFERENCE)) + ->setProperty('foo3', new Reference('foo3', $container::IGNORE_ON_UNINITIALIZED_REFERENCE)) + ->setProperty('closures', array( + new ServiceClosureArgument(new Reference('foo1', $container::IGNORE_ON_UNINITIALIZED_REFERENCE)), + new ServiceClosureArgument(new Reference('foo2', $container::IGNORE_ON_UNINITIALIZED_REFERENCE)), + new ServiceClosureArgument(new Reference('foo3', $container::IGNORE_ON_UNINITIALIZED_REFERENCE)), + )) + ->setProperty('iter', new IteratorArgument(array( + 'foo1' => new Reference('foo1', $container::IGNORE_ON_UNINITIALIZED_REFERENCE), + 'foo2' => new Reference('foo2', $container::IGNORE_ON_UNINITIALIZED_REFERENCE), + 'foo3' => new Reference('foo3', $container::IGNORE_ON_UNINITIALIZED_REFERENCE), + ))) +; + +return $container; diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_uninitialized_ref.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_uninitialized_ref.php new file mode 100644 index 0000000000000..df0d74c07cbeb --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_uninitialized_ref.php @@ -0,0 +1,138 @@ +services = array(); + $this->methodMap = array( + 'bar' => 'getBarService', + 'baz' => 'getBazService', + 'foo1' => 'getFoo1Service', + 'foo3' => 'getFoo3Service', + ); + $this->privates = array( + 'foo3' => true, + ); + + $this->aliases = array(); + } + + /** + * {@inheritdoc} + */ + public function compile() + { + throw new LogicException('You cannot compile a dumped container that was already compiled.'); + } + + /** + * {@inheritdoc} + */ + public function isCompiled() + { + return true; + } + + /** + * {@inheritdoc} + */ + public function isFrozen() + { + @trigger_error(sprintf('The %s() method is deprecated since version 3.3 and will be removed in 4.0. Use the isCompiled() method instead.', __METHOD__), E_USER_DEPRECATED); + + return true; + } + + /** + * Gets the public 'bar' shared service. + * + * @return \stdClass + */ + protected function getBarService() + { + $this->services['bar'] = $instance = new \stdClass(); + + $instance->foo1 = ${($_ = isset($this->services['foo1']) ? $this->services['foo1'] : null) && false ?: '_'}; + $instance->foo2 = null; + $instance->foo3 = ${($_ = isset($this->services['foo3']) ? $this->services['foo3'] : null) && false ?: '_'}; + $instance->closures = array(0 => function () { + return ${($_ = isset($this->services['foo1']) ? $this->services['foo1'] : null) && false ?: '_'}; + }, 1 => function () { + return null; + }, 2 => function () { + return ${($_ = isset($this->services['foo3']) ? $this->services['foo3'] : null) && false ?: '_'}; + }); + $instance->iter = new RewindableGenerator(function () { + if (isset($this->services['foo1'])) { + yield 'foo1' => ${($_ = isset($this->services['foo1']) ? $this->services['foo1'] : null) && false ?: '_'}; + } + if (false) { + yield 'foo2' => null; + } + if (isset($this->services['foo3'])) { + yield 'foo3' => ${($_ = isset($this->services['foo3']) ? $this->services['foo3'] : null) && false ?: '_'}; + } + }, function () { + return 0 + (int) (isset($this->services['foo1'])) + (int) (false) + (int) (isset($this->services['foo3'])); + }); + + return $instance; + } + + /** + * Gets the public 'baz' shared service. + * + * @return \stdClass + */ + protected function getBazService() + { + $this->services['baz'] = $instance = new \stdClass(); + + $instance->foo3 = ${($_ = isset($this->services['foo3']) ? $this->services['foo3'] : $this->getFoo3Service()) && false ?: '_'}; + + return $instance; + } + + /** + * Gets the public 'foo1' shared service. + * + * @return \stdClass + */ + protected function getFoo1Service() + { + return $this->services['foo1'] = new \stdClass(); + } + + /** + * Gets the private 'foo3' shared service. + * + * @return \stdClass + */ + protected function getFoo3Service() + { + return $this->services['foo3'] = new \stdClass(); + } +} diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services_dump_load.xml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services_dump_load.xml new file mode 100644 index 0000000000000..e763aa870a028 --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services_dump_load.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services_dump_load.yml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services_dump_load.yml index 43b0c7d58a00f..8f3e153afcea4 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services_dump_load.yml +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services_dump_load.yml @@ -6,6 +6,7 @@ services: foo: autoconfigure: true abstract: true + arguments: ['@!bar'] Psr\Container\ContainerInterface: alias: service_container public: false From 7b1715b0782af05d5114cb5ad4433ac7e7e45e72 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Mon, 26 Jun 2017 08:08:08 +0200 Subject: [PATCH 0738/1099] [Yaml] use scalar type hints where possible --- src/Symfony/Component/Yaml/Dumper.php | 7 +-- src/Symfony/Component/Yaml/Escaper.php | 8 +-- .../Yaml/Exception/ParseException.php | 2 +- src/Symfony/Component/Yaml/Inline.php | 48 +++++++------- src/Symfony/Component/Yaml/Parser.php | 62 +++++++++---------- src/Symfony/Component/Yaml/Unescaper.php | 8 +-- src/Symfony/Component/Yaml/Yaml.php | 4 +- 7 files changed, 68 insertions(+), 71 deletions(-) diff --git a/src/Symfony/Component/Yaml/Dumper.php b/src/Symfony/Component/Yaml/Dumper.php index 87e06b5255453..92ce4c9d28f3f 100644 --- a/src/Symfony/Component/Yaml/Dumper.php +++ b/src/Symfony/Component/Yaml/Dumper.php @@ -27,10 +27,7 @@ class Dumper */ protected $indentation; - /** - * @param int $indentation - */ - public function __construct($indentation = 4) + public function __construct(int $indentation = 4) { if ($indentation < 1) { throw new \InvalidArgumentException('The indentation must be greater than zero.'); @@ -49,7 +46,7 @@ public function __construct($indentation = 4) * * @return string The YAML representation of the PHP value */ - public function dump($input, $inline = 0, $indent = 0, $flags = 0) + public function dump($input, int $inline = 0, int $indent = 0, int $flags = 0): string { $output = ''; $prefix = $indent ? str_repeat(' ', $indent) : ''; diff --git a/src/Symfony/Component/Yaml/Escaper.php b/src/Symfony/Component/Yaml/Escaper.php index 94bb3924b618b..66e65bc618c24 100644 --- a/src/Symfony/Component/Yaml/Escaper.php +++ b/src/Symfony/Component/Yaml/Escaper.php @@ -50,7 +50,7 @@ class Escaper * * @return bool True if the value would require double quotes */ - public static function requiresDoubleQuoting($value) + public static function requiresDoubleQuoting(string $value): bool { return 0 < preg_match('/'.self::REGEX_CHARACTER_TO_ESCAPE.'/u', $value); } @@ -62,7 +62,7 @@ public static function requiresDoubleQuoting($value) * * @return string The quoted, escaped string */ - public static function escapeWithDoubleQuotes($value) + public static function escapeWithDoubleQuotes(string $value): string { return sprintf('"%s"', str_replace(self::$escapees, self::$escaped, $value)); } @@ -74,7 +74,7 @@ public static function escapeWithDoubleQuotes($value) * * @return bool True if the value would require single quotes */ - public static function requiresSingleQuoting($value) + public static function requiresSingleQuoting(string $value): bool { // Determines if a PHP value is entirely composed of a value that would // require single quoting in YAML. @@ -94,7 +94,7 @@ public static function requiresSingleQuoting($value) * * @return string The quoted, escaped string */ - public static function escapeWithSingleQuotes($value) + public static function escapeWithSingleQuotes(string $value): string { return sprintf("'%s'", str_replace('\'', '\'\'', $value)); } diff --git a/src/Symfony/Component/Yaml/Exception/ParseException.php b/src/Symfony/Component/Yaml/Exception/ParseException.php index 3b38b643964ac..b04cbd69cece6 100644 --- a/src/Symfony/Component/Yaml/Exception/ParseException.php +++ b/src/Symfony/Component/Yaml/Exception/ParseException.php @@ -32,7 +32,7 @@ class ParseException extends RuntimeException * @param string|null $parsedFile The file name where the error occurred * @param \Exception|null $previous The previous exception */ - public function __construct($message, $parsedLine = -1, $snippet = null, $parsedFile = null, \Exception $previous = null) + public function __construct(string $message, int $parsedLine = -1, string $snippet = null, string $parsedFile = null, \Exception $previous = null) { $this->parsedFile = $parsedFile; $this->parsedLine = $parsedLine; diff --git a/src/Symfony/Component/Yaml/Inline.php b/src/Symfony/Component/Yaml/Inline.php index 3212aeca58963..cc7f723726eed 100644 --- a/src/Symfony/Component/Yaml/Inline.php +++ b/src/Symfony/Component/Yaml/Inline.php @@ -44,7 +44,7 @@ class Inline * * @throws ParseException */ - public static function parse($value, $flags = 0, $references = array()) + public static function parse(string $value = null, int $flags = 0, array $references = array()) { self::$exceptionOnInvalidType = (bool) (Yaml::PARSE_EXCEPTION_ON_INVALID_TYPE & $flags); self::$objectSupport = (bool) (Yaml::PARSE_OBJECT & $flags); @@ -103,7 +103,7 @@ public static function parse($value, $flags = 0, $references = array()) * * @throws DumpException When trying to dump PHP resource */ - public static function dump($value, $flags = 0) + public static function dump($value, int $flags = 0): string { switch (true) { case is_resource($value): @@ -124,7 +124,13 @@ public static function dump($value, $flags = 0) } if (Yaml::DUMP_OBJECT_AS_MAP & $flags && ($value instanceof \stdClass || $value instanceof \ArrayObject)) { - return self::dumpArray($value, $flags & ~Yaml::DUMP_EMPTY_ARRAY_AS_SEQUENCE); + $output = array(); + + foreach ($value as $key => $val) { + $output[] = sprintf('%s: %s', self::dump($key, $flags), self::dump($val, $flags)); + } + + return sprintf('{ %s }', implode(', ', $output)); } if (Yaml::DUMP_EXCEPTION_ON_INVALID_TYPE & $flags) { @@ -182,13 +188,11 @@ public static function dump($value, $flags = 0) /** * Check if given array is hash or just normal indexed array. * - * @internal - * * @param array|\ArrayObject|\stdClass $value The PHP array or array-like object to check * * @return bool true if value is hash array, false otherwise */ - public static function isHash($value) + public static function isHash($value): bool { if ($value instanceof \stdClass || $value instanceof \ArrayObject) { return true; @@ -213,7 +217,7 @@ public static function isHash($value) * * @return string The YAML string representing the PHP array */ - private static function dumpArray($value, $flags) + private static function dumpArray(array $value, int $flags): string { // array if (($value || Yaml::DUMP_EMPTY_ARRAY_AS_SEQUENCE & $flags) && !self::isHash($value)) { @@ -244,13 +248,11 @@ private static function dumpArray($value, $flags) * @param bool $evaluate * @param array $references * - * @return string + * @return mixed * * @throws ParseException When malformed inline YAML string is parsed - * - * @internal */ - public static function parseScalar($scalar, $flags = 0, $delimiters = null, &$i = 0, $evaluate = true, $references = array()) + public static function parseScalar(string $scalar, int $flags = 0, array $delimiters = null, int &$i = 0, bool $evaluate = true, array $references = array()) { if (in_array($scalar[$i], array('"', "'"))) { // quoted scalar @@ -302,7 +304,7 @@ public static function parseScalar($scalar, $flags = 0, $delimiters = null, &$i * * @throws ParseException When malformed inline YAML string is parsed */ - private static function parseQuotedScalar($scalar, &$i) + private static function parseQuotedScalar(string $scalar, int &$i): string { if (!Parser::preg_match('/'.self::REGEX_QUOTED_STRING.'/Au', substr($scalar, $i), $match)) { throw new ParseException(sprintf('Malformed inline YAML string: %s.', substr($scalar, $i))); @@ -334,7 +336,7 @@ private static function parseQuotedScalar($scalar, &$i) * * @throws ParseException When malformed inline YAML string is parsed */ - private static function parseSequence($sequence, $flags, &$i = 0, $references = array()) + private static function parseSequence(string $sequence, int $flags, int &$i = 0, array $references = array()): array { $output = array(); $len = strlen($sequence); @@ -403,7 +405,7 @@ private static function parseSequence($sequence, $flags, &$i = 0, $references = * * @throws ParseException When malformed inline YAML string is parsed */ - private static function parseMapping($mapping, $flags, &$i = 0, $references = array()) + private static function parseMapping(string $mapping, int $flags, int &$i = 0, array $references = array()) { $output = array(); $len = strlen($mapping); @@ -515,7 +517,7 @@ private static function parseMapping($mapping, $flags, &$i = 0, $references = ar * * @throws ParseException when object parsing support was disabled and the parser detected a PHP object or when a reference could not be resolved */ - private static function evaluateScalar($scalar, $flags, $references = array()) + private static function evaluateScalar(string $scalar, int $flags, array $references = array()) { $scalar = trim($scalar); $scalarLower = strtolower($scalar); @@ -638,10 +640,10 @@ private static function evaluateScalar($scalar, $flags, $references = array()) * * @return null|string */ - private static function parseTag($value, &$i, $flags) + private static function parseTag(string $value, int &$i, int $flags): ?string { if ('!' !== $value[$i]) { - return; + return null; } $tagLength = strcspn($value, " \t\n[]{},", $i + 1); @@ -653,7 +655,7 @@ private static function parseTag($value, &$i, $flags) // Is followed by a scalar and is a built-in tag if ($tag && (!isset($value[$nextOffset]) || !in_array($value[$nextOffset], array('[', '{'), true)) && ('!' === $tag[0] || 'str' === $tag || 'php/const' === $tag || 'php/object' === $tag)) { // Manage in {@link self::evaluateScalar()} - return; + return null; } $i = $nextOffset; @@ -674,10 +676,8 @@ private static function parseTag($value, &$i, $flags) * @param string $scalar * * @return string - * - * @internal */ - public static function evaluateBinaryScalar($scalar) + public static function evaluateBinaryScalar(string $scalar): string { $parsedBinaryData = self::parseScalar(preg_replace('/\s/', '', $scalar)); @@ -692,7 +692,7 @@ public static function evaluateBinaryScalar($scalar) return base64_decode($parsedBinaryData, true); } - private static function isBinaryString($value) + private static function isBinaryString(string $value) { return !preg_match('//u', $value) || preg_match('/[^\x00\x07-\x0d\x1B\x20-\xff]/', $value); } @@ -704,7 +704,7 @@ private static function isBinaryString($value) * * @see http://www.yaml.org/spec/1.2/spec.html#id2761573 */ - private static function getTimestampRegex() + private static function getTimestampRegex(): string { return <<getRealCurrentLineNb(); } - private function doParse($value, $flags) + private function doParse(string $value, int $flags) { $this->currentLineNb = -1; $this->currentLine = ''; @@ -146,7 +146,7 @@ private function doParse($value, $flags) // array if (!isset($values['value']) || '' == trim($values['value'], ' ') || 0 === strpos(ltrim($values['value'], ' '), '#')) { - $data[] = $this->parseBlock($this->getRealCurrentLineNb() + 1, $this->getNextEmbedBlock(null, true), $flags); + $data[] = $this->parseBlock($this->getRealCurrentLineNb() + 1, $this->getNextEmbedBlock(null, true) ?? '', $flags); } elseif (null !== $subTag = $this->getLineTag(ltrim($values['value'], ' '), $flags)) { $data[] = new TaggedValue( $subTag, @@ -383,7 +383,7 @@ private function doParse($value, $flags) return empty($data) ? null : $data; } - private function parseBlock($offset, $yaml, $flags) + private function parseBlock(int $offset, string $yaml, int $flags) { $skippedLineNumbers = $this->skippedLineNumbers; @@ -411,7 +411,7 @@ private function parseBlock($offset, $yaml, $flags) * * @return int The current line number */ - public function getRealCurrentLineNb() + public function getRealCurrentLineNb(): int { $realCurrentLineNumber = $this->currentLineNb + $this->offset; @@ -431,7 +431,7 @@ public function getRealCurrentLineNb() * * @return int The current line indentation */ - private function getCurrentLineIndentation() + private function getCurrentLineIndentation(): int { return strlen($this->currentLine) - strlen(ltrim($this->currentLine, ' ')); } @@ -439,14 +439,14 @@ private function getCurrentLineIndentation() /** * Returns the next embed block of YAML. * - * @param int $indentation The indent level at which the block is to be read, or null for default - * @param bool $inSequence True if the enclosing data structure is a sequence + * @param int|null $indentation The indent level at which the block is to be read, or null for default + * @param bool $inSequence True if the enclosing data structure is a sequence * * @return string A YAML string * * @throws ParseException When indentation problem are detected */ - private function getNextEmbedBlock($indentation = null, $inSequence = false) + private function getNextEmbedBlock(int $indentation = null, bool $inSequence = false): ?string { $oldLineIndentation = $this->getCurrentLineIndentation(); $blockScalarIndentations = array(); @@ -456,7 +456,7 @@ private function getNextEmbedBlock($indentation = null, $inSequence = false) } if (!$this->moveToNextLine()) { - return; + return null; } if (null === $indentation) { @@ -477,7 +477,7 @@ private function getNextEmbedBlock($indentation = null, $inSequence = false) } else { $this->moveToPreviousLine(); - return; + return null; } if ($inSequence && $oldLineIndentation === $newIndent && isset($data[0][0]) && '-' === $data[0][0]) { @@ -485,7 +485,7 @@ private function getNextEmbedBlock($indentation = null, $inSequence = false) // and therefore no nested list or mapping $this->moveToPreviousLine(); - return; + return null; } $isItUnindentedCollection = $this->isStringUnIndentedCollectionItem(); @@ -556,7 +556,7 @@ private function getNextEmbedBlock($indentation = null, $inSequence = false) * * @return bool */ - private function moveToNextLine() + private function moveToNextLine(): bool { if ($this->currentLineNb >= count($this->lines) - 1) { return false; @@ -572,7 +572,7 @@ private function moveToNextLine() * * @return bool */ - private function moveToPreviousLine() + private function moveToPreviousLine(): bool { if ($this->currentLineNb < 1) { return false; @@ -594,7 +594,7 @@ private function moveToPreviousLine() * * @throws ParseException When reference does not exist */ - private function parseValue($value, $flags, $context) + private function parseValue(string $value, int $flags, string $context) { if (0 === strpos($value, '*')) { if (false !== $pos = strpos($value, '#')) { @@ -675,7 +675,7 @@ private function parseValue($value, $flags, $context) * * @return string The text value */ - private function parseBlockScalar($style, $chomping = '', $indentation = 0) + private function parseBlockScalar(string $style, string $chomping = '', int $indentation = 0): string { $notEOF = $this->moveToNextLine(); if (!$notEOF) { @@ -782,7 +782,7 @@ private function parseBlockScalar($style, $chomping = '', $indentation = 0) * * @return bool Returns true if the next line is indented, false otherwise */ - private function isNextLineIndented() + private function isNextLineIndented(): bool { $currentIndentation = $this->getCurrentLineIndentation(); $EOF = !$this->moveToNextLine(); @@ -807,7 +807,7 @@ private function isNextLineIndented() * * @return bool Returns true if the current line is empty or if it is a comment line, false otherwise */ - private function isCurrentLineEmpty() + private function isCurrentLineEmpty(): bool { return $this->isCurrentLineBlank() || $this->isCurrentLineComment(); } @@ -817,7 +817,7 @@ private function isCurrentLineEmpty() * * @return bool Returns true if the current line is blank, false otherwise */ - private function isCurrentLineBlank() + private function isCurrentLineBlank(): bool { return '' == trim($this->currentLine, ' '); } @@ -827,7 +827,7 @@ private function isCurrentLineBlank() * * @return bool Returns true if the current line is a comment line, false otherwise */ - private function isCurrentLineComment() + private function isCurrentLineComment(): bool { //checking explicitly the first char of the trim is faster than loops or strpos $ltrimmedLine = ltrim($this->currentLine, ' '); @@ -835,7 +835,7 @@ private function isCurrentLineComment() return '' !== $ltrimmedLine && $ltrimmedLine[0] === '#'; } - private function isCurrentLineLastLineInDocument() + private function isCurrentLineLastLineInDocument(): bool { return ($this->offset + $this->currentLineNb) >= ($this->totalNumberOfLines - 1); } @@ -847,7 +847,7 @@ private function isCurrentLineLastLineInDocument() * * @return string A cleaned up YAML string */ - private function cleanup($value) + private function cleanup(string $value): string { $value = str_replace(array("\r\n", "\r"), "\n", $value); @@ -883,7 +883,7 @@ private function cleanup($value) * * @return bool Returns true if the next line starts unindented collection, false otherwise */ - private function isNextLineUnIndentedCollection() + private function isNextLineUnIndentedCollection(): bool { $currentIndentation = $this->getCurrentLineIndentation(); $notEOF = $this->moveToNextLine(); @@ -908,7 +908,7 @@ private function isNextLineUnIndentedCollection() * * @return bool Returns true if the string is un-indented collection item, false otherwise */ - private function isStringUnIndentedCollectionItem() + private function isStringUnIndentedCollectionItem(): bool { return '-' === rtrim($this->currentLine) || 0 === strpos($this->currentLine, '- '); } @@ -918,7 +918,7 @@ private function isStringUnIndentedCollectionItem() * * @return bool */ - private function isBlockScalarHeader() + private function isBlockScalarHeader(): bool { return (bool) self::preg_match('~'.self::BLOCK_SCALAR_HEADER_PATTERN.'$~', $this->currentLine); } @@ -936,7 +936,7 @@ private function isBlockScalarHeader() * * @internal */ - public static function preg_match($pattern, $subject, &$matches = null, $flags = 0, $offset = 0) + public static function preg_match(string $pattern, string $subject, array &$matches = null, int $flags = 0, int $offset = 0): int { if (false === $ret = preg_match($pattern, $subject, $matches, $flags, $offset)) { switch (preg_last_error()) { @@ -971,7 +971,7 @@ public static function preg_match($pattern, $subject, &$matches = null, $flags = * Prevent values such as `!foo {quz: bar}` to be considered as * a mapping block. */ - private function trimTag($value) + private function trimTag(string $value): string { if ('!' === $value[0]) { return ltrim(substr($value, 1, strcspn($value, " \r\n", 1)), ' '); @@ -980,14 +980,14 @@ private function trimTag($value) return $value; } - private function getLineTag($value, $flags, $nextLineCheck = true) + private function getLineTag(string $value, int $flags, bool $nextLineCheck = true): ?string { if ('' === $value || '!' !== $value[0] || 1 !== self::preg_match('/^'.self::TAG_PATTERN.' *( +#.*)?$/', $value, $matches)) { - return; + return null; } if ($nextLineCheck && !$this->isNextLineIndented()) { - return; + return null; } $tag = substr($matches['tag'], 1); diff --git a/src/Symfony/Component/Yaml/Unescaper.php b/src/Symfony/Component/Yaml/Unescaper.php index 6e863e12f2ad4..c9285acb49695 100644 --- a/src/Symfony/Component/Yaml/Unescaper.php +++ b/src/Symfony/Component/Yaml/Unescaper.php @@ -35,7 +35,7 @@ class Unescaper * * @return string The unescaped string */ - public function unescapeSingleQuotedString($value) + public function unescapeSingleQuotedString(string $value): string { return str_replace('\'\'', '\'', $value); } @@ -47,7 +47,7 @@ public function unescapeSingleQuotedString($value) * * @return string The unescaped string */ - public function unescapeDoubleQuotedString($value) + public function unescapeDoubleQuotedString(string $value): string { $callback = function ($match) { return $this->unescapeCharacter($match[0]); @@ -64,7 +64,7 @@ public function unescapeDoubleQuotedString($value) * * @return string The unescaped character */ - private function unescapeCharacter($value) + private function unescapeCharacter(string $value): string { switch ($value[1]) { case '0': @@ -125,7 +125,7 @@ private function unescapeCharacter($value) * * @return string The corresponding UTF-8 character */ - private static function utf8chr($c) + private static function utf8chr(int $c): string { if (0x80 > $c %= 0x200000) { return chr($c); diff --git a/src/Symfony/Component/Yaml/Yaml.php b/src/Symfony/Component/Yaml/Yaml.php index 674982c33e9fb..992aac1ece700 100644 --- a/src/Symfony/Component/Yaml/Yaml.php +++ b/src/Symfony/Component/Yaml/Yaml.php @@ -50,7 +50,7 @@ class Yaml * * @throws ParseException If the YAML is not valid */ - public static function parse($input, $flags = 0) + public static function parse(string $input, int $flags = 0) { $yaml = new Parser(); @@ -70,7 +70,7 @@ public static function parse($input, $flags = 0) * * @return string A YAML string representing the original PHP value */ - public static function dump($input, $inline = 2, $indent = 4, $flags = 0) + public static function dump($input, int $inline = 2, int $indent = 4, int $flags = 0): string { $yaml = new Dumper($indent); From 86f2f2585647f5c178cbfd19a60a412bd657485d Mon Sep 17 00:00:00 2001 From: Dany Maillard Date: Thu, 31 Aug 2017 20:01:53 +0200 Subject: [PATCH 0739/1099] Mark SemaphoreStore::isSupported() as internal --- src/Symfony/Component/Lock/Store/SemaphoreStore.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Symfony/Component/Lock/Store/SemaphoreStore.php b/src/Symfony/Component/Lock/Store/SemaphoreStore.php index 006f6f3f14f80..64123e8a51e2b 100644 --- a/src/Symfony/Component/Lock/Store/SemaphoreStore.php +++ b/src/Symfony/Component/Lock/Store/SemaphoreStore.php @@ -30,6 +30,8 @@ class SemaphoreStore implements StoreInterface * @param bool|null $blocking When not null, checked again the blocking mode. * * @return bool + * + * @internal */ public static function isSupported($blocking = null) { From d817f98004f661967af33821ca9c233ef888f5ef Mon Sep 17 00:00:00 2001 From: Dany Maillard Date: Thu, 31 Aug 2017 15:36:41 +0200 Subject: [PATCH 0740/1099] Remove old version check --- .../Component/Console/Command/LockableTrait.php | 2 +- .../Console/Tests/Command/LockableTraitTest.php | 2 +- .../Component/Lock/Store/SemaphoreStore.php | 15 ++------------- 3 files changed, 4 insertions(+), 15 deletions(-) diff --git a/src/Symfony/Component/Console/Command/LockableTrait.php b/src/Symfony/Component/Console/Command/LockableTrait.php index b521f3b7708b9..de5fb229ff8c1 100644 --- a/src/Symfony/Component/Console/Command/LockableTrait.php +++ b/src/Symfony/Component/Console/Command/LockableTrait.php @@ -43,7 +43,7 @@ private function lock($name = null, $blocking = false) throw new LogicException('A lock is already in place.'); } - if (SemaphoreStore::isSupported($blocking)) { + if (SemaphoreStore::isSupported()) { $store = new SemaphoreStore(); } else { $store = new FlockStore(sys_get_temp_dir()); diff --git a/src/Symfony/Component/Console/Tests/Command/LockableTraitTest.php b/src/Symfony/Component/Console/Tests/Command/LockableTraitTest.php index 401ff823a7761..5deb65d7a74ec 100644 --- a/src/Symfony/Component/Console/Tests/Command/LockableTraitTest.php +++ b/src/Symfony/Component/Console/Tests/Command/LockableTraitTest.php @@ -41,7 +41,7 @@ public function testLockReturnsFalseIfAlreadyLockedByAnotherCommand() { $command = new \FooLockCommand(); - if (SemaphoreStore::isSupported(false)) { + if (SemaphoreStore::isSupported()) { $store = new SemaphoreStore(); } else { $store = new FlockStore(sys_get_temp_dir()); diff --git a/src/Symfony/Component/Lock/Store/SemaphoreStore.php b/src/Symfony/Component/Lock/Store/SemaphoreStore.php index b90da2130f744..c212f59f0fef8 100644 --- a/src/Symfony/Component/Lock/Store/SemaphoreStore.php +++ b/src/Symfony/Component/Lock/Store/SemaphoreStore.php @@ -13,7 +13,6 @@ use Symfony\Component\Lock\Exception\InvalidArgumentException; use Symfony\Component\Lock\Exception\LockConflictedException; -use Symfony\Component\Lock\Exception\NotSupportedException; use Symfony\Component\Lock\Key; use Symfony\Component\Lock\StoreInterface; @@ -27,21 +26,11 @@ class SemaphoreStore implements StoreInterface /** * Returns whether or not the store is supported. * - * @param bool|null $blocking When not null, checked again the blocking mode. - * * @return bool */ - public static function isSupported($blocking = null) + public static function isSupported() { - if (!extension_loaded('sysvsem')) { - return false; - } - - if ($blocking === false && \PHP_VERSION_ID < 50601) { - return false; - } - - return true; + return extension_loaded('sysvsem'); } public function __construct() From 4222d54a53123098e2402836d72e66df8a0f312b Mon Sep 17 00:00:00 2001 From: Hidde Wieringa Date: Fri, 24 Feb 2017 23:34:35 +0100 Subject: [PATCH 0741/1099] Initial commit for Bootstrap 4 form theme, based on Bootstrap 3 form theme Fixed Bootstrap 4 error output Updated form errors to look correctly Cranked Twig Bridge Composer version to ~3.2 Added @ author PHPdoc tag to BS 4 test classes Fixed small items, and added fieldset/legend support - Fixed form class for File type - Added fieldset element for expanded form types - Added legend element as label for expanded form types - Fixed horizontal form classes for labels Added test for legend form label Fixed form label coloring on validation errors Fixed concrete Bootstrap layout test classes to use new code Fixed tests for form-control-label class on form labels Fixed a typo in using old Bootstrap 4 concrete test code Processed proposed changes from stof Processed proposed changes in bootstrap base layout from stof Updated margin-top for error list in the alpha-5 version of BS 4 Fixed {% endblock ... %} and fixed BS error class in test Fixed TwigRenderer => FormRenderer code change Minor fixed for radio/checkboxes and fixed validation feedback Added ~3.4 require of symfony/form (and <3.4 conflict) to Twig Bridge composer.json Updated Boostrap 4 file input to have class .form-control-file --- .../bootstrap_3_horizontal_layout.html.twig | 20 - .../views/Form/bootstrap_3_layout.html.twig | 140 +-- .../bootstrap_4_horizontal_layout.html.twig | 69 ++ .../views/Form/bootstrap_4_layout.html.twig | 132 +++ .../Form/bootstrap_base_layout.html.twig | 183 ++++ .../views/Form/form_div_layout.html.twig | 2 +- .../views/Form/foundation_5_layout.html.twig | 4 +- ...xtensionBootstrap4HorizontalLayoutTest.php | 107 ++ .../FormExtensionBootstrap4LayoutTest.php | 129 +++ src/Symfony/Bridge/Twig/composer.json | 4 +- ...AbstractBootstrap4HorizontalLayoutTest.php | 181 ++++ .../Tests/AbstractBootstrap4LayoutTest.php | 978 ++++++++++++++++++ 12 files changed, 1786 insertions(+), 163 deletions(-) create mode 100644 src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_4_horizontal_layout.html.twig create mode 100644 src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_4_layout.html.twig create mode 100644 src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_base_layout.html.twig create mode 100644 src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionBootstrap4HorizontalLayoutTest.php create mode 100644 src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionBootstrap4LayoutTest.php create mode 100644 src/Symfony/Component/Form/Tests/AbstractBootstrap4HorizontalLayoutTest.php create mode 100644 src/Symfony/Component/Form/Tests/AbstractBootstrap4LayoutTest.php diff --git a/src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_3_horizontal_layout.html.twig b/src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_3_horizontal_layout.html.twig index 5de20b1b8f181..478de622da435 100644 --- a/src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_3_horizontal_layout.html.twig +++ b/src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_3_horizontal_layout.html.twig @@ -34,26 +34,6 @@ col-sm-2 {##} {%- endblock form_row %} -{% block checkbox_row -%} - {{- block('checkbox_radio_row') -}} -{%- endblock checkbox_row %} - -{% block radio_row -%} - {{- block('checkbox_radio_row') -}} -{%- endblock radio_row %} - -{% block checkbox_radio_row -%} -{% spaceless %} -
-
-
- {{ form_widget(form) }} - {{ form_errors(form) }} -
-
-{% endspaceless %} -{%- endblock checkbox_radio_row %} - {% block submit_row -%} {% spaceless %}
diff --git a/src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_3_layout.html.twig b/src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_3_layout.html.twig index f2fe8bf3d2588..b89a788041cae 100644 --- a/src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_3_layout.html.twig +++ b/src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_3_layout.html.twig @@ -1,4 +1,4 @@ -{% use "form_div_layout.html.twig" %} +{% use "bootstrap_base_layout.html.twig" %} {# Widgets #} @@ -9,146 +9,10 @@ {{- parent() -}} {%- endblock form_widget_simple %} -{% block textarea_widget -%} - {% set attr = attr|merge({class: (attr.class|default('') ~ ' form-control')|trim}) %} - {{- parent() -}} -{%- endblock textarea_widget %} - {% block button_widget -%} {% set attr = attr|merge({class: (attr.class|default('btn-default') ~ ' btn')|trim}) %} {{- parent() -}} -{%- endblock %} - -{% block money_widget -%} -
- {% set append = money_pattern starts with '{{' %} - {% if not append %} - {{ money_pattern|replace({ '{{ widget }}':''}) }} - {% endif %} - {{- block('form_widget_simple') -}} - {% if append %} - {{ money_pattern|replace({ '{{ widget }}':''}) }} - {% endif %} -
-{%- endblock money_widget %} - -{% block percent_widget -%} -
- {{- block('form_widget_simple') -}} - % -
-{%- endblock percent_widget %} - -{% block datetime_widget -%} - {% if widget == 'single_text' %} - {{- block('form_widget_simple') -}} - {% else -%} - {% set attr = attr|merge({class: (attr.class|default('') ~ ' form-inline')|trim}) -%} -
- {{- form_errors(form.date) -}} - {{- form_errors(form.time) -}} - {{- form_widget(form.date, { datetime: true } ) -}} - {{- form_widget(form.time, { datetime: true } ) -}} -
- {%- endif %} -{%- endblock datetime_widget %} - -{% block date_widget -%} - {% if widget == 'single_text' %} - {{- block('form_widget_simple') -}} - {% else -%} - {% set attr = attr|merge({class: (attr.class|default('') ~ ' form-inline')|trim}) -%} - {% if datetime is not defined or not datetime -%} -
- {%- endif %} - {{- date_pattern|replace({ - '{{ year }}': form_widget(form.year), - '{{ month }}': form_widget(form.month), - '{{ day }}': form_widget(form.day), - })|raw -}} - {% if datetime is not defined or not datetime -%} -
- {%- endif -%} - {% endif %} -{%- endblock date_widget %} - -{% block time_widget -%} - {% if widget == 'single_text' %} - {{- block('form_widget_simple') -}} - {% else -%} - {% set attr = attr|merge({class: (attr.class|default('') ~ ' form-inline')|trim}) -%} - {% if datetime is not defined or false == datetime -%} -
- {%- endif -%} - {{- form_widget(form.hour) }}{% if with_minutes %}:{{ form_widget(form.minute) }}{% endif %}{% if with_seconds %}:{{ form_widget(form.second) }}{% endif %} - {% if datetime is not defined or false == datetime -%} -
- {%- endif -%} - {% endif %} -{%- endblock time_widget %} - -{%- block dateinterval_widget -%} - {%- if widget == 'single_text' -%} - {{- block('form_widget_simple') -}} - {%- else -%} - {%- set attr = attr|merge({class: (attr.class|default('') ~ ' form-inline')|trim}) -%} -
- {{- form_errors(form) -}} -
- - - - {%- if with_years %}{% endif -%} - {%- if with_months %}{% endif -%} - {%- if with_weeks %}{% endif -%} - {%- if with_days %}{% endif -%} - {%- if with_hours %}{% endif -%} - {%- if with_minutes %}{% endif -%} - {%- if with_seconds %}{% endif -%} - - - - - {%- if with_years %}{% endif -%} - {%- if with_months %}{% endif -%} - {%- if with_weeks %}{% endif -%} - {%- if with_days %}{% endif -%} - {%- if with_hours %}{% endif -%} - {%- if with_minutes %}{% endif -%} - {%- if with_seconds %}{% endif -%} - - -
{{ form_label(form.years) }}{{ form_label(form.months) }}{{ form_label(form.weeks) }}{{ form_label(form.days) }}{{ form_label(form.hours) }}{{ form_label(form.minutes) }}{{ form_label(form.seconds) }}
{{ form_widget(form.years) }}{{ form_widget(form.months) }}{{ form_widget(form.weeks) }}{{ form_widget(form.days) }}{{ form_widget(form.hours) }}{{ form_widget(form.minutes) }}{{ form_widget(form.seconds) }}
-
- {%- if with_invert %}{{ form_widget(form.invert) }}{% endif -%} -
- {%- endif -%} -{%- endblock dateinterval_widget -%} - -{% block choice_widget_collapsed -%} - {% set attr = attr|merge({class: (attr.class|default('') ~ ' form-control')|trim}) %} - {{- parent() -}} -{%- endblock %} - -{% block choice_widget_expanded -%} - {% if '-inline' in label_attr.class|default('') -%} - {%- for child in form %} - {{- form_widget(child, { - parent_label_class: label_attr.class|default(''), - translation_domain: choice_translation_domain, - }) -}} - {% endfor -%} - {%- else -%} -
- {%- for child in form %} - {{- form_widget(child, { - parent_label_class: label_attr.class|default(''), - translation_domain: choice_translation_domain, - }) -}} - {% endfor -%} -
- {%- endif %} -{%- endblock choice_widget_expanded %} +{%- endblock button_widget %} {% block checkbox_widget -%} {%- set parent_label_class = parent_label_class|default(label_attr.class|default('')) -%} diff --git a/src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_4_horizontal_layout.html.twig b/src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_4_horizontal_layout.html.twig new file mode 100644 index 0000000000000..046cf3cdd1703 --- /dev/null +++ b/src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_4_horizontal_layout.html.twig @@ -0,0 +1,69 @@ +{% use "bootstrap_4_layout.html.twig" %} + +{# Labels #} + +{% block form_label -%} + {%- if label is same as(false) -%} +
+ {%- else -%} + {%- if expanded is not defined or not expanded -%} + {%- set label_attr = label_attr|merge({'class': (label_attr.class|default('') ~ ' col-form-label')|trim}) -%} + {%- endif -%} + {%- set label_attr = label_attr|merge({class: (label_attr.class|default('') ~ ' ' ~ block('form_label_class'))|trim}) -%} + {{- parent() -}} + {%- endif -%} +{%- endblock form_label %} + +{% block form_label_class -%} +col-sm-2 +{%- endblock form_label_class %} + +{# Rows #} + +{% block form_row -%} + {%- if expanded is defined and expanded -%} + {{ block('fieldset_form_row') }} + {%- else -%} +
+ {{- form_label(form) -}} +
+ {{- form_widget(form) -}} + {{- form_errors(form) -}} +
+ {##}
+ {%- endif -%} +{%- endblock form_row %} + +{% block fieldset_form_row -%} +
+
+ {{- form_label(form) -}} +
+ {{- form_widget(form) -}} + {{- form_errors(form) -}} +
+
+{##}
+{%- endblock fieldset_form_row %} + +{% block submit_row -%} +
+
+
+ {{- form_widget(form) -}} +
+
+{%- endblock submit_row %} + +{% block reset_row -%} +
+
+
+ {{- form_widget(form) -}} +
+
+{%- endblock reset_row %} + +{% block form_group_class -%} +col-sm-10 +{%- endblock form_group_class %} diff --git a/src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_4_layout.html.twig b/src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_4_layout.html.twig new file mode 100644 index 0000000000000..b3c71a74ea5aa --- /dev/null +++ b/src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_4_layout.html.twig @@ -0,0 +1,132 @@ +{% use "bootstrap_base_layout.html.twig" %} + +{# Widgets #} + +{% block form_widget_simple -%} + {% if type is not defined or type != 'hidden' %} + {%- set attr = attr|merge({class: (attr.class|default('') ~ ' form-control' ~ (type|default('') == 'file' ? '-file' : ''))|trim}) -%} + {% endif %} + {{- parent() -}} +{%- endblock form_widget_simple %} + +{%- block widget_attributes -%} + {%- if not valid %} + {% set attr = attr|merge({class: (attr.class|default('') ~ ' is-invalid')|trim}) %} + {% endif -%} + {{ parent() }} +{%- endblock widget_attributes -%} + +{% block button_widget -%} + {%- set attr = attr|merge({class: (attr.class|default('btn-secondary') ~ ' btn')|trim}) -%} + {{- parent() -}} +{%- endblock button_widget %} + +{% block checkbox_widget -%} + {%- set parent_label_class = parent_label_class|default(label_attr.class|default('')) -%} + {%- set attr = attr|merge({class: attr.class|default('form-check-input')}) -%} + {%- if 'checkbox-inline' in parent_label_class -%} + {{- form_label(form, null, { widget: parent() }) -}} + {%- else -%} +
+ {{- form_label(form, null, { widget: parent() }) -}} +
+ {%- endif -%} +{%- endblock checkbox_widget %} + +{% block radio_widget -%} + {%- set parent_label_class = parent_label_class|default(label_attr.class|default('')) -%} + {%- set attr = attr|merge({class: attr.class|default('form-check-input')}) -%} + {%- if 'radio-inline' in parent_label_class -%} + {{- form_label(form, null, { widget: parent() }) -}} + {%- else -%} +
+ {{- form_label(form, null, { widget: parent() }) -}} +
+ {%- endif -%} +{%- endblock radio_widget %} + +{% block choice_widget_expanded -%} + {% if '-inline' in label_attr.class|default('') -%} + {%- for child in form %} + {{- form_widget(child, { + parent_label_class: label_attr.class|default(''), + translation_domain: choice_translation_domain, + valid: valid, + }) -}} + {% endfor -%} + {%- else -%} +
+ {%- for child in form %} + {{- form_widget(child, { + parent_label_class: label_attr.class|default(''), + translation_domain: choice_translation_domain, + valid: valid, + }) -}} + {% endfor -%} +
+ {%- endif %} +{%- endblock choice_widget_expanded %} + +{# Labels #} + +{% block form_label -%} + {%- if expanded is defined and expanded -%} + {%- set element = 'legend' -%} + {%- set label_attr = label_attr|merge({'class': (label_attr.class|default('') ~ ' col-form-legend')|trim}) -%} + {%- endif -%} + {%- set label_attr = label_attr|merge({'class': (label_attr.class|default('') ~ ' form-control-label')|trim}) -%} + {{- parent() -}} +{%- endblock form_label %} + +{% block checkbox_radio_label -%} + {#- Do not display the label if widget is not defined in order to prevent double label rendering -#} + {%- if widget is defined -%} + {%- set label_attr = label_attr|merge({class: (label_attr.class|default('') ~ ' form-check-label')|trim}) -%} + {%- if required -%} + {%- set label_attr = label_attr|merge({class: (label_attr.class|default('') ~ ' required')|trim}) -%} + {%- endif -%} + {%- if parent_label_class is defined -%} + {%- set label_attr = label_attr|merge({class: (label_attr.class|default('') ~ ' ' ~ parent_label_class)|trim}) -%} + {%- endif -%} + {%- if label is not same as(false) and label is empty -%} + {%- if label_format is not empty -%} + {%- set label = label_format|replace({ + '%name%': name, + '%id%': id, + }) -%} + {%- else -%} + {%- set label = name|humanize -%} + {%- endif -%} + {%- endif -%} + + {{- widget|raw }} {{ label is not same as(false) ? (translation_domain is same as(false) ? label : label|trans({}, translation_domain)) -}} + + {%- endif -%} +{%- endblock checkbox_radio_label %} + +{# Rows #} + +{% block form_row -%} + {%- if expanded is defined and expanded -%} + {%- set element = 'fieldset' -%} + {%- endif -%} + <{{ element|default('div') }} class="form-group"> + {{- form_label(form) -}} + {{- form_widget(form) -}} + {{- form_errors(form) -}} + +{%- endblock form_row %} + +{# Errors #} + +{% block form_errors -%} + {%- if errors|length > 0 -%} +
+
    + {%- for error in errors -%} +
  • {{ error.message }}
  • + {%- endfor -%} +
+
+ {%- endif %} +{%- endblock form_errors %} diff --git a/src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_base_layout.html.twig b/src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_base_layout.html.twig new file mode 100644 index 0000000000000..cdb9dbc88ef96 --- /dev/null +++ b/src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_base_layout.html.twig @@ -0,0 +1,183 @@ +{% use "form_div_layout.html.twig" %} + +{# Widgets #} + +{% block textarea_widget -%} + {% set attr = attr|merge({class: (attr.class|default('') ~ ' form-control')|trim}) %} + {{- parent() -}} +{%- endblock textarea_widget %} + +{% block money_widget -%} +
+ {%- set append = money_pattern starts with '{{' -%} + {%- if not append -%} + {{ money_pattern|replace({ '{{ widget }}':''}) }} + {%- endif -%} + {{- block('form_widget_simple') -}} + {%- if append -%} + {{ money_pattern|replace({ '{{ widget }}':''}) }} + {%- endif -%} +
+{%- endblock money_widget %} + +{% block percent_widget -%} +
+ {{- block('form_widget_simple') -}} + % +
+{%- endblock percent_widget %} + +{% block datetime_widget -%} + {%- if widget == 'single_text' -%} + {{- block('form_widget_simple') -}} + {%- else -%} + {% set attr = attr|merge({class: (attr.class|default('') ~ ' form-inline')|trim}) -%} +
+ {{- form_errors(form.date) -}} + {{- form_errors(form.time) -}} + {{- form_widget(form.date, { datetime: true } ) -}} + {{- form_widget(form.time, { datetime: true } ) -}} +
+ {%- endif -%} +{%- endblock datetime_widget %} + +{% block date_widget -%} + {%- if widget == 'single_text' -%} + {{- block('form_widget_simple') -}} + {%- else -%} + {%- set attr = attr|merge({class: (attr.class|default('') ~ ' form-inline')|trim}) -%} + {%- if datetime is not defined or not datetime -%} +
+ {%- endif %} + {{- date_pattern|replace({ + '{{ year }}': form_widget(form.year), + '{{ month }}': form_widget(form.month), + '{{ day }}': form_widget(form.day), + })|raw -}} + {%- if datetime is not defined or not datetime -%} +
+ {%- endif -%} + {%- endif -%} +{%- endblock date_widget %} + +{% block time_widget -%} + {%- if widget == 'single_text' -%} + {{- block('form_widget_simple') -}} + {%- else -%} + {%- set attr = attr|merge({class: (attr.class|default('') ~ ' form-inline')|trim}) -%} + {%- if datetime is not defined or false == datetime -%} +
+ {%- endif -%} + {{- form_widget(form.hour) }}{% if with_minutes %}:{{ form_widget(form.minute) }}{% endif %}{% if with_seconds %}:{{ form_widget(form.second) }}{% endif %} + {%- if datetime is not defined or false == datetime -%} +
+ {%- endif -%} + {%- endif -%} +{%- endblock time_widget %} + +{%- block dateinterval_widget -%} + {%- if widget == 'single_text' -%} + {{- block('form_widget_simple') -}} + {%- else -%} + {%- set attr = attr|merge({class: (attr.class|default('') ~ ' form-inline')|trim}) -%} +
+ {{- form_errors(form) -}} +
+ + + + {%- if with_years %}{% endif -%} + {%- if with_months %}{% endif -%} + {%- if with_weeks %}{% endif -%} + {%- if with_days %}{% endif -%} + {%- if with_hours %}{% endif -%} + {%- if with_minutes %}{% endif -%} + {%- if with_seconds %}{% endif -%} + + + + + {%- if with_years %}{% endif -%} + {%- if with_months %}{% endif -%} + {%- if with_weeks %}{% endif -%} + {%- if with_days %}{% endif -%} + {%- if with_hours %}{% endif -%} + {%- if with_minutes %}{% endif -%} + {%- if with_seconds %}{% endif -%} + + +
{{ form_label(form.years) }}{{ form_label(form.months) }}{{ form_label(form.weeks) }}{{ form_label(form.days) }}{{ form_label(form.hours) }}{{ form_label(form.minutes) }}{{ form_label(form.seconds) }}
{{ form_widget(form.years) }}{{ form_widget(form.months) }}{{ form_widget(form.weeks) }}{{ form_widget(form.days) }}{{ form_widget(form.hours) }}{{ form_widget(form.minutes) }}{{ form_widget(form.seconds) }}
+
+ {%- if with_invert %}{{ form_widget(form.invert) }}{% endif -%} +
+ {%- endif -%} +{%- endblock dateinterval_widget -%} + +{% block choice_widget_collapsed -%} + {%- set attr = attr|merge({class: (attr.class|default('') ~ ' form-control')|trim}) -%} + {{- parent() -}} +{%- endblock choice_widget_collapsed %} + +{% block choice_widget_expanded -%} + {%- if '-inline' in label_attr.class|default('') -%} + {%- for child in form %} + {{- form_widget(child, { + parent_label_class: label_attr.class|default(''), + translation_domain: choice_translation_domain, + }) -}} + {% endfor -%} + {%- else -%} +
+ {%- for child in form %} + {{- form_widget(child, { + parent_label_class: label_attr.class|default(''), + translation_domain: choice_translation_domain, + }) -}} + {%- endfor -%} +
+ {%- endif -%} +{%- endblock choice_widget_expanded %} + +{# Labels #} + +{% block choice_label -%} + {# remove the checkbox-inline and radio-inline class, it's only useful for embed labels #} + {%- set label_attr = label_attr|merge({class: label_attr.class|default('')|replace({'checkbox-inline': '', 'radio-inline': ''})|trim}) -%} + {{- block('form_label') -}} +{% endblock choice_label %} + +{% block checkbox_label -%} + {{- block('checkbox_radio_label') -}} +{%- endblock checkbox_label %} + +{% block radio_label -%} + {{- block('checkbox_radio_label') -}} +{%- endblock radio_label %} + +{# Rows #} + +{% block button_row -%} +
+ {{- form_widget(form) -}} +
+{%- endblock button_row %} + +{% block choice_row -%} + {%- set force_error = true -%} + {{- block('form_row') -}} +{%- endblock choice_row %} + +{% block date_row -%} + {%- set force_error = true -%} + {{- block('form_row') -}} +{%- endblock date_row %} + +{% block time_row -%} + {%- set force_error = true -%} + {{- block('form_row') -}} +{%- endblock time_row %} + +{% block datetime_row -%} + {%- set force_error = true -%} + {{- block('form_row') -}} +{%- endblock datetime_row %} 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 3d8afe2cba602..20e5de35ee9f8 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 @@ -259,7 +259,7 @@ {% set label = name|humanize %} {%- endif -%} {%- endif -%} - {{ translation_domain is same as(false) ? label : label|trans({}, translation_domain) }} + <{{ element|default('label') }}{% if label_attr %}{% with { attr: label_attr } %}{{ block('attributes') }}{% endwith %}{% endif %}>{{ translation_domain is same as(false) ? label : label|trans({}, translation_domain) }} {%- endif -%} {%- endblock form_label -%} diff --git a/src/Symfony/Bridge/Twig/Resources/views/Form/foundation_5_layout.html.twig b/src/Symfony/Bridge/Twig/Resources/views/Form/foundation_5_layout.html.twig index dc7bec9fb6ccd..d34161ad0c669 100644 --- a/src/Symfony/Bridge/Twig/Resources/views/Form/foundation_5_layout.html.twig +++ b/src/Symfony/Bridge/Twig/Resources/views/Form/foundation_5_layout.html.twig @@ -20,7 +20,7 @@ {% block button_widget -%} {% set attr = attr|merge({class: (attr.class|default('') ~ ' button')|trim}) %} {{- parent() -}} -{%- endblock %} +{%- endblock button_widget %} {% block money_widget -%}
@@ -228,7 +228,7 @@ {# remove the checkbox-inline and radio-inline class, it's only useful for embed labels #} {% set label_attr = label_attr|merge({class: label_attr.class|default('')|replace({'checkbox-inline': '', 'radio-inline': ''})|trim}) %} {{- block('form_label') -}} -{%- endblock %} +{%- endblock choice_label %} {% block checkbox_label -%} {{- block('checkbox_radio_label') -}} diff --git a/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionBootstrap4HorizontalLayoutTest.php b/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionBootstrap4HorizontalLayoutTest.php new file mode 100644 index 0000000000000..842150dc5e0fa --- /dev/null +++ b/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionBootstrap4HorizontalLayoutTest.php @@ -0,0 +1,107 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bridge\Twig\Tests\Extension; + +use Symfony\Bridge\Twig\Extension\FormExtension; +use Symfony\Bridge\Twig\Form\TwigRendererEngine; +use Symfony\Bridge\Twig\Extension\TranslationExtension; +use Symfony\Bridge\Twig\Tests\Extension\Fixtures\StubTranslator; +use Symfony\Bridge\Twig\Tests\Extension\Fixtures\StubFilesystemLoader; +use Symfony\Component\Form\FormRenderer; +use Symfony\Component\Form\FormView; +use Symfony\Component\Form\Tests\AbstractBootstrap4HorizontalLayoutTest; + +/** + * Class providing test cases for the Bootstrap 4 Twig form theme. + * + * @author Hidde Wieringa + */ +class FormExtensionBootstrap4HorizontalLayoutTest extends AbstractBootstrap4HorizontalLayoutTest +{ + use RuntimeLoaderProvider; + + protected $testableFeatures = array( + 'choice_attr', + ); + + private $renderer; + + protected function setUp() + { + parent::setUp(); + + $loader = new StubFilesystemLoader(array( + __DIR__.'/../../Resources/views/Form', + __DIR__.'/Fixtures/templates/form', + )); + + $environment = new \Twig_Environment($loader, array('strict_variables' => true)); + $environment->addExtension(new TranslationExtension(new StubTranslator())); + $environment->addExtension(new FormExtension()); + + $rendererEngine = new TwigRendererEngine(array( + 'bootstrap_4_horizontal_layout.html.twig', + 'custom_widgets.html.twig', + ), $environment); + $this->renderer = new FormRenderer($rendererEngine, $this->getMockBuilder('Symfony\Component\Security\Csrf\CsrfTokenManagerInterface')->getMock()); + $this->registerTwigRuntimeLoader($environment, $this->renderer); + } + + protected function renderForm(FormView $view, array $vars = array()) + { + return (string) $this->renderer->renderBlock($view, 'form', $vars); + } + + protected function renderLabel(FormView $view, $label = null, array $vars = array()) + { + if ($label !== null) { + $vars += array('label' => $label); + } + + return (string) $this->renderer->searchAndRenderBlock($view, 'label', $vars); + } + + protected function renderErrors(FormView $view) + { + return (string) $this->renderer->searchAndRenderBlock($view, 'errors'); + } + + protected function renderWidget(FormView $view, array $vars = array()) + { + return (string) $this->renderer->searchAndRenderBlock($view, 'widget', $vars); + } + + protected function renderRow(FormView $view, array $vars = array()) + { + return (string) $this->renderer->searchAndRenderBlock($view, 'row', $vars); + } + + protected function renderRest(FormView $view, array $vars = array()) + { + return (string) $this->renderer->searchAndRenderBlock($view, 'rest', $vars); + } + + protected function renderStart(FormView $view, array $vars = array()) + { + return (string) $this->renderer->renderBlock($view, 'form_start', $vars); + } + + protected function renderEnd(FormView $view, array $vars = array()) + { + return (string) $this->renderer->renderBlock($view, 'form_end', $vars); + } + + protected function setTheme(FormView $view, array $themes) + { + $this->renderer->setTheme($view, $themes); + } +} diff --git a/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionBootstrap4LayoutTest.php b/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionBootstrap4LayoutTest.php new file mode 100644 index 0000000000000..4650246cda4f7 --- /dev/null +++ b/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionBootstrap4LayoutTest.php @@ -0,0 +1,129 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bridge\Twig\Tests\Extension; + +use Symfony\Bridge\Twig\Extension\FormExtension; +use Symfony\Bridge\Twig\Form\TwigRendererEngine; +use Symfony\Bridge\Twig\Extension\TranslationExtension; +use Symfony\Bridge\Twig\Tests\Extension\Fixtures\StubTranslator; +use Symfony\Bridge\Twig\Tests\Extension\Fixtures\StubFilesystemLoader; +use Symfony\Component\Form\FormRenderer; +use Symfony\Component\Form\FormView; +use Symfony\Component\Form\Tests\AbstractBootstrap4LayoutTest; + +/** + * Class providing test cases for the Bootstrap 4 horizontal Twig form theme. + * + * @author Hidde Wieringa + */ +class FormExtensionBootstrap4LayoutTest extends AbstractBootstrap4LayoutTest +{ + use RuntimeLoaderProvider; + /** + * @var FormRenderer; + */ + private $renderer; + + protected function setUp() + { + parent::setUp(); + + $loader = new StubFilesystemLoader(array( + __DIR__.'/../../Resources/views/Form', + __DIR__.'/Fixtures/templates/form', + )); + + $environment = new \Twig_Environment($loader, array('strict_variables' => true)); + $environment->addExtension(new TranslationExtension(new StubTranslator())); + $environment->addExtension(new FormExtension()); + + $rendererEngine = new TwigRendererEngine(array( + 'bootstrap_4_layout.html.twig', + 'custom_widgets.html.twig', + ), $environment); + $this->renderer = new FormRenderer($rendererEngine, $this->getMockBuilder('Symfony\Component\Security\Csrf\CsrfTokenManagerInterface')->getMock()); + $this->registerTwigRuntimeLoader($environment, $this->renderer); + } + + public function testStartTagHasNoActionAttributeWhenActionIsEmpty() + { + $form = $this->factory->create('Symfony\Component\Form\Extension\Core\Type\FormType', null, array( + 'method' => 'get', + 'action' => '', + )); + + $html = $this->renderStart($form->createView()); + + $this->assertSame('
', $html); + } + + public function testStartTagHasActionAttributeWhenActionIsZero() + { + $form = $this->factory->create('Symfony\Component\Form\Extension\Core\Type\FormType', null, array( + 'method' => 'get', + 'action' => '0', + )); + + $html = $this->renderStart($form->createView()); + + $this->assertSame('', $html); + } + + protected function renderForm(FormView $view, array $vars = array()) + { + return (string) $this->renderer->renderBlock($view, 'form', $vars); + } + + protected function renderLabel(FormView $view, $label = null, array $vars = array()) + { + if ($label !== null) { + $vars += array('label' => $label); + } + + return (string) $this->renderer->searchAndRenderBlock($view, 'label', $vars); + } + + protected function renderErrors(FormView $view) + { + return (string) $this->renderer->searchAndRenderBlock($view, 'errors'); + } + + protected function renderWidget(FormView $view, array $vars = array()) + { + return (string) $this->renderer->searchAndRenderBlock($view, 'widget', $vars); + } + + protected function renderRow(FormView $view, array $vars = array()) + { + return (string) $this->renderer->searchAndRenderBlock($view, 'row', $vars); + } + + protected function renderRest(FormView $view, array $vars = array()) + { + return (string) $this->renderer->searchAndRenderBlock($view, 'rest', $vars); + } + + protected function renderStart(FormView $view, array $vars = array()) + { + return (string) $this->renderer->renderBlock($view, 'form_start', $vars); + } + + protected function renderEnd(FormView $view, array $vars = array()) + { + return (string) $this->renderer->renderBlock($view, 'form_end', $vars); + } + + protected function setTheme(FormView $view, array $themes) + { + $this->renderer->setTheme($view, $themes); + } +} diff --git a/src/Symfony/Bridge/Twig/composer.json b/src/Symfony/Bridge/Twig/composer.json index 14f734cdc80ef..e1e86408cff33 100644 --- a/src/Symfony/Bridge/Twig/composer.json +++ b/src/Symfony/Bridge/Twig/composer.json @@ -23,7 +23,7 @@ "fig/link-util": "^1.0", "symfony/asset": "~2.8|~3.0|~4.0", "symfony/finder": "~2.8|~3.0|~4.0", - "symfony/form": "^3.2.10|^3.3.3|~4.0", + "symfony/form": "~3.4|~4.0", "symfony/http-kernel": "~3.2|~4.0", "symfony/polyfill-intl-icu": "~1.0", "symfony/routing": "~2.8|~3.0|~4.0", @@ -39,7 +39,7 @@ "symfony/web-link": "~3.3|~4.0" }, "conflict": { - "symfony/form": "<3.2.10|~3.3,<3.3.3", + "symfony/form": "<3.4", "symfony/console": "<3.4" }, "suggest": { diff --git a/src/Symfony/Component/Form/Tests/AbstractBootstrap4HorizontalLayoutTest.php b/src/Symfony/Component/Form/Tests/AbstractBootstrap4HorizontalLayoutTest.php new file mode 100644 index 0000000000000..990fffbe94689 --- /dev/null +++ b/src/Symfony/Component/Form/Tests/AbstractBootstrap4HorizontalLayoutTest.php @@ -0,0 +1,181 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Tests; + +/** + * Abstract class providing test cases for the Bootstrap 4 horizontal Twig form theme. + * + * @author Hidde Wieringa + */ +abstract class AbstractBootstrap4HorizontalLayoutTest extends AbstractBootstrap4LayoutTest +{ + public function testLabelOnForm() + { + $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\DateType'); + $view = $form->createView(); + $this->renderWidget($view, array('label' => 'foo')); + $html = $this->renderLabel($view); + + $this->assertMatchesXpath($html, +'/label + [@class="col-form-label col-sm-2 form-control-label required"] + [.="[trans]Name[/trans]"] +' + ); + } + + public function testLabelDoesNotRenderFieldAttributes() + { + $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\TextType'); + $html = $this->renderLabel($form->createView(), null, array( + 'attr' => array( + 'class' => 'my&class', + ), + )); + + $this->assertMatchesXpath($html, +'/label + [@for="name"] + [@class="col-form-label col-sm-2 form-control-label required"] +' + ); + } + + public function testLabelWithCustomAttributesPassedDirectly() + { + $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\TextType'); + $html = $this->renderLabel($form->createView(), null, array( + 'label_attr' => array( + 'class' => 'my&class', + ), + )); + + $this->assertMatchesXpath($html, +'/label + [@for="name"] + [@class="my&class col-form-label col-sm-2 form-control-label required"] +' + ); + } + + public function testLabelWithCustomTextAndCustomAttributesPassedDirectly() + { + $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\TextType'); + $html = $this->renderLabel($form->createView(), 'Custom label', array( + 'label_attr' => array( + 'class' => 'my&class', + ), + )); + + $this->assertMatchesXpath($html, +'/label + [@for="name"] + [@class="my&class col-form-label col-sm-2 form-control-label required"] + [.="[trans]Custom label[/trans]"] +' + ); + } + + public function testLabelWithCustomTextAsOptionAndCustomAttributesPassedDirectly() + { + $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\TextType', null, array( + 'label' => 'Custom label', + )); + $html = $this->renderLabel($form->createView(), null, array( + 'label_attr' => array( + 'class' => 'my&class', + ), + )); + + $this->assertMatchesXpath($html, +'/label + [@for="name"] + [@class="my&class col-form-label col-sm-2 form-control-label required"] + [.="[trans]Custom label[/trans]"] +' + ); + } + + public function testLegendOnExpandedType() + { + $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\ChoiceType', null, array( + 'label' => 'Custom label', + 'expanded' => true, + 'choices' => array('Choice&A' => '&a', 'Choice&B' => '&b'), + )); + $view = $form->createView(); + $this->renderWidget($view); + $html = $this->renderLabel($view); + + $this->assertMatchesXpath($html, +'/legend + [@class="col-sm-2 col-form-legend form-control-label required"] + [.="[trans]Custom label[/trans]"] +' + ); + } + + public function testStartTag() + { + $form = $this->factory->create('Symfony\Component\Form\Extension\Core\Type\FormType', null, array( + 'method' => 'get', + 'action' => 'http://example.com/directory', + )); + + $html = $this->renderStart($form->createView()); + + $this->assertSame('', $html); + } + + public function testStartTagWithOverriddenVars() + { + $form = $this->factory->create('Symfony\Component\Form\Extension\Core\Type\FormType', null, array( + 'method' => 'put', + 'action' => 'http://example.com/directory', + )); + + $html = $this->renderStart($form->createView(), array( + 'method' => 'post', + 'action' => 'http://foo.com/directory', + )); + + $this->assertSame('', $html); + } + + public function testStartTagForMultipartForm() + { + $form = $this->factory->createBuilder('Symfony\Component\Form\Extension\Core\Type\FormType', null, array( + 'method' => 'get', + 'action' => 'http://example.com/directory', + )) + ->add('file', 'Symfony\Component\Form\Extension\Core\Type\FileType') + ->getForm(); + + $html = $this->renderStart($form->createView()); + + $this->assertSame('', $html); + } + + public function testStartTagWithExtraAttributes() + { + $form = $this->factory->create('Symfony\Component\Form\Extension\Core\Type\FormType', null, array( + 'method' => 'get', + 'action' => 'http://example.com/directory', + )); + + $html = $this->renderStart($form->createView(), array( + 'attr' => array('class' => 'foobar'), + )); + + $this->assertSame('', $html); + } +} diff --git a/src/Symfony/Component/Form/Tests/AbstractBootstrap4LayoutTest.php b/src/Symfony/Component/Form/Tests/AbstractBootstrap4LayoutTest.php new file mode 100644 index 0000000000000..35bd1203b3f80 --- /dev/null +++ b/src/Symfony/Component/Form/Tests/AbstractBootstrap4LayoutTest.php @@ -0,0 +1,978 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Tests; + +use Symfony\Component\Form\FormError; + +/** + * Abstract class providing test cases for the Bootstrap 4 Twig form theme. + * + * @author Hidde Wieringa + */ +abstract class AbstractBootstrap4LayoutTest extends AbstractBootstrap3LayoutTest +{ + public function testLabelOnForm() + { + $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\DateType'); + $view = $form->createView(); + $this->renderWidget($view, array('label' => 'foo')); + $html = $this->renderLabel($view); + + $this->assertMatchesXpath($html, +'/label + [@class="form-control-label required"] + [.="[trans]Name[/trans]"] +' + ); + } + + public function testLabelDoesNotRenderFieldAttributes() + { + $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\TextType'); + $html = $this->renderLabel($form->createView(), null, array( + 'attr' => array( + 'class' => 'my&class', + ), + )); + + $this->assertMatchesXpath($html, +'/label + [@for="name"] + [@class="form-control-label required"] +' + ); + } + + public function testLabelWithCustomAttributesPassedDirectly() + { + $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\TextType'); + $html = $this->renderLabel($form->createView(), null, array( + 'label_attr' => array( + 'class' => 'my&class', + ), + )); + + $this->assertMatchesXpath($html, +'/label + [@for="name"] + [@class="my&class form-control-label required"] +' + ); + } + + public function testLabelWithCustomTextAndCustomAttributesPassedDirectly() + { + $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\TextType'); + $html = $this->renderLabel($form->createView(), 'Custom label', array( + 'label_attr' => array( + 'class' => 'my&class', + ), + )); + + $this->assertMatchesXpath($html, +'/label + [@for="name"] + [@class="my&class form-control-label required"] + [.="[trans]Custom label[/trans]"] +' + ); + } + + public function testLabelWithCustomTextAsOptionAndCustomAttributesPassedDirectly() + { + $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\TextType', null, array( + 'label' => 'Custom label', + )); + $html = $this->renderLabel($form->createView(), null, array( + 'label_attr' => array( + 'class' => 'my&class', + ), + )); + + $this->assertMatchesXpath($html, +'/label + [@for="name"] + [@class="my&class form-control-label required"] + [.="[trans]Custom label[/trans]"] +' + ); + } + + public function testLegendOnExpandedType() + { + $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\ChoiceType', null, array( + 'label' => 'Custom label', + 'expanded' => true, + 'choices' => array('Choice&A' => '&a', 'Choice&B' => '&b'), + )); + $view = $form->createView(); + $this->renderWidget($view); + $html = $this->renderLabel($view); + + $this->assertMatchesXpath($html, +'/legend + [@class="col-form-legend form-control-label required"] + [.="[trans]Custom label[/trans]"] +' + ); + } + + public function testErrors() + { + $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\TextType'); + $form->addError(new FormError('[trans]Error 1[/trans]')); + $form->addError(new FormError('[trans]Error 2[/trans]')); + $view = $form->createView(); + $html = $this->renderErrors($view); + + $this->assertMatchesXpath($html, +'/div + [@class="alert alert-danger"] + [ + ./ul + [@class="list-unstyled mb-0"] + [ + ./li + [.="[trans]Error 1[/trans]"] + /following-sibling::li + [.="[trans]Error 2[/trans]"] + ] + [count(./li)=2] + ] +' + ); + } + + public function testCheckedCheckbox() + { + $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\CheckboxType', true); + + $this->assertWidgetMatchesXpath($form->createView(), array('id' => 'my&id', 'attr' => array('class' => 'my&class')), +'/div + [@class="form-check"] + [ + ./label + [.=" [trans]Name[/trans]"] + [@class="form-check-label required"] + [ + ./input[@type="checkbox"][@name="name"][@id="my&id"][@class="my&class"][@checked="checked"][@value="1"] + ] + ] +' + ); + } + + public function testSingleChoiceAttributesWithMainAttributes() + { + $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\ChoiceType', '&a', array( + 'choices' => array('Choice&A' => '&a', 'Choice&B' => '&b'), + 'multiple' => false, + 'expanded' => false, + 'attr' => array('class' => 'bar&baz'), + )); + + $this->assertWidgetMatchesXpath($form->createView(), array('attr' => array('class' => 'bar&baz')), +'/select + [@name="name"] + [@class="bar&baz form-control"] + [not(@required)] + [ + ./option[@value="&a"][@selected="selected"][.="[trans]Choice&A[/trans]"] + /following-sibling::option[@value="&b"][not(@selected)][.="[trans]Choice&B[/trans]"] + ] + [count(./option)=2] +' + ); + } + + public function testSingleExpandedChoiceAttributesWithMainAttributes() + { + $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\ChoiceType', '&a', array( + 'choices' => array('Choice&A' => '&a', 'Choice&B' => '&b'), + 'multiple' => false, + 'expanded' => true, + 'attr' => array('class' => 'bar&baz'), + )); + + $this->assertWidgetMatchesXpath($form->createView(), array('attr' => array('class' => 'bar&baz')), +'/div + [@class="bar&baz"] + [ + ./div + [@class="form-check"] + [ + ./label + [.=" [trans]Choice&A[/trans]"] + [ + ./input[@type="radio"][@name="name"][@id="name_0"][@value="&a"][@checked] + ] + ] + /following-sibling::div + [@class="form-check"] + [ + ./label + [.=" [trans]Choice&B[/trans]"] + [ + ./input[@type="radio"][@name="name"][@id="name_1"][@value="&b"][not(@checked)] + ] + ] + /following-sibling::input[@type="hidden"][@id="name__token"] + ] +' + ); + } + + public function testUncheckedCheckbox() + { + $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\CheckboxType', false); + + $this->assertWidgetMatchesXpath($form->createView(), array('id' => 'my&id', 'attr' => array('class' => 'my&class')), +'/div + [@class="form-check"] + [ + ./label + [.=" [trans]Name[/trans]"] + [ + ./input[@type="checkbox"][@name="name"][@id="my&id"][@class="my&class"][not(@checked)] + ] + ] +' + ); + } + + public function testCheckboxWithValue() + { + $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\CheckboxType', false, array( + 'value' => 'foo&bar', + )); + + $this->assertWidgetMatchesXpath($form->createView(), array('id' => 'my&id', 'attr' => array('class' => 'my&class')), +'/div + [@class="form-check"] + [ + ./label + [.=" [trans]Name[/trans]"] + [ + ./input[@type="checkbox"][@name="name"][@id="my&id"][@class="my&class"][@value="foo&bar"] + ] + ] +' + ); + } + + public function testSingleChoiceExpanded() + { + $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\ChoiceType', '&a', array( + 'choices' => array('Choice&A' => '&a', 'Choice&B' => '&b'), + 'multiple' => false, + 'expanded' => true, + )); + + $this->assertWidgetMatchesXpath($form->createView(), array(), +'/div + [ + ./div + [@class="form-check"] + [ + ./label + [.=" [trans]Choice&A[/trans]"] + [ + ./input[@type="radio"][@name="name"][@id="name_0"][@value="&a"][@checked] + ] + ] + /following-sibling::div + [@class="form-check"] + [ + ./label + [.=" [trans]Choice&B[/trans]"] + [ + ./input[@type="radio"][@name="name"][@id="name_1"][@value="&b"][not(@checked)] + ] + ] + /following-sibling::input[@type="hidden"][@id="name__token"] + ] +' + ); + } + + public function testSingleChoiceExpandedWithLabelsAsFalse() + { + $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\ChoiceType', '&a', array( + 'choices' => array('Choice&A' => '&a', 'Choice&B' => '&b'), + 'choice_label' => false, + 'multiple' => false, + 'expanded' => true, + )); + + $this->assertWidgetMatchesXpath($form->createView(), array(), +'/div + [ + ./div + [@class="form-check"] + [ + ./label + [ + ./input[@type="radio"][@name="name"][@id="name_0"][@value="&a"][@checked] + ] + ] + /following-sibling::div + [@class="form-check"] + [ + ./label + [ + ./input[@type="radio"][@name="name"][@id="name_1"][@value="&b"][not(@checked)] + ] + ] + /following-sibling::input[@type="hidden"][@id="name__token"] + ] +' + ); + } + + public function testSingleChoiceExpandedWithLabelsSetByCallable() + { + $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\ChoiceType', '&a', array( + 'choices' => array('Choice&A' => '&a', 'Choice&B' => '&b', 'Choice&C' => '&c'), + 'choice_label' => function ($choice, $label, $value) { + if ('&b' === $choice) { + return false; + } + + return 'label.'.$value; + }, + 'multiple' => false, + 'expanded' => true, + )); + + $this->assertWidgetMatchesXpath($form->createView(), array(), +'/div + [ + ./div + [@class="form-check"] + [ + ./label + [.=" [trans]label.&a[/trans]"] + [ + ./input[@type="radio"][@name="name"][@id="name_0"][@value="&a"][@checked] + ] + ] + /following-sibling::div + [@class="form-check"] + [ + ./label + [ + ./input[@type="radio"][@name="name"][@id="name_1"][@value="&b"][not(@checked)] + ] + ] + /following-sibling::div + [@class="form-check"] + [ + ./label + [.=" [trans]label.&c[/trans]"] + [ + ./input[@type="radio"][@name="name"][@id="name_2"][@value="&c"][not(@checked)] + ] + ] + /following-sibling::input[@type="hidden"][@id="name__token"] + ] +' + ); + } + + public function testSingleChoiceExpandedWithLabelsSetFalseByCallable() + { + $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\ChoiceType', '&a', array( + 'choices' => array('Choice&A' => '&a', 'Choice&B' => '&b'), + 'choice_label' => function () { + return false; + }, + 'multiple' => false, + 'expanded' => true, + )); + + $this->assertWidgetMatchesXpath($form->createView(), array(), +'/div + [ + ./div + [@class="form-check"] + [ + ./label + [ + ./input[@type="radio"][@name="name"][@id="name_0"][@value="&a"][@checked] + ] + ] + /following-sibling::div + [@class="form-check"] + [ + ./label + [ + ./input[@type="radio"][@name="name"][@id="name_1"][@value="&b"][not(@checked)] + ] + ] + /following-sibling::input[@type="hidden"][@id="name__token"] + ] +' + ); + } + + public function testSingleChoiceExpandedWithoutTranslation() + { + $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\ChoiceType', '&a', array( + 'choices' => array('Choice&A' => '&a', 'Choice&B' => '&b'), + 'multiple' => false, + 'expanded' => true, + 'choice_translation_domain' => false, + )); + + $this->assertWidgetMatchesXpath($form->createView(), array(), +'/div + [ + ./div + [@class="form-check"] + [ + ./label + [.=" Choice&A"] + [ + ./input[@type="radio"][@name="name"][@id="name_0"][@value="&a"][@checked] + ] + ] + /following-sibling::div + [@class="form-check"] + [ + ./label + [.=" Choice&B"] + [ + ./input[@type="radio"][@name="name"][@id="name_1"][@value="&b"][not(@checked)] + ] + ] + /following-sibling::input[@type="hidden"][@id="name__token"] + ] +' + ); + } + + public function testSingleChoiceExpandedAttributes() + { + $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\ChoiceType', '&a', array( + 'choices' => array('Choice&A' => '&a', 'Choice&B' => '&b'), + 'choice_attr' => array('Choice&B' => array('class' => 'foo&bar')), + 'multiple' => false, + 'expanded' => true, + )); + + $this->assertWidgetMatchesXpath($form->createView(), array(), +'/div + [ + ./div + [@class="form-check"] + [ + ./label + [.=" [trans]Choice&A[/trans]"] + [ + ./input[@type="radio"][@name="name"][@id="name_0"][@value="&a"][@checked] + ] + ] + /following-sibling::div + [@class="form-check"] + [ + ./label + [.=" [trans]Choice&B[/trans]"] + [ + ./input[@type="radio"][@name="name"][@id="name_1"][@value="&b"][not(@checked)][@class="foo&bar"] + ] + ] + /following-sibling::input[@type="hidden"][@id="name__token"] + ] +' + ); + } + + public function testSingleChoiceExpandedWithPlaceholder() + { + $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\ChoiceType', '&a', array( + 'choices' => array('Choice&A' => '&a', 'Choice&B' => '&b'), + 'multiple' => false, + 'expanded' => true, + 'placeholder' => 'Test&Me', + 'required' => false, + )); + + $this->assertWidgetMatchesXpath($form->createView(), array(), +'/div + [ + ./div + [@class="form-check"] + [ + ./label + [.=" [trans]Test&Me[/trans]"] + [ + ./input[@type="radio"][@name="name"][@id="name_placeholder"][not(@checked)] + ] + ] + /following-sibling::div + [@class="form-check"] + [ + ./label + [.=" [trans]Choice&A[/trans]"] + [ + ./input[@type="radio"][@name="name"][@id="name_0"][@checked] + ] + ] + /following-sibling::div + [@class="form-check"] + [ + ./label + [.=" [trans]Choice&B[/trans]"] + [ + ./input[@type="radio"][@name="name"][@id="name_1"][not(@checked)] + ] + ] + /following-sibling::input[@type="hidden"][@id="name__token"] + ] +' + ); + } + + public function testSingleChoiceExpandedWithPlaceholderWithoutTranslation() + { + $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\ChoiceType', '&a', array( + 'choices' => array('Choice&A' => '&a', 'Choice&B' => '&b'), + 'multiple' => false, + 'expanded' => true, + 'required' => false, + 'choice_translation_domain' => false, + 'placeholder' => 'Placeholder&Not&Translated', + )); + + $this->assertWidgetMatchesXpath($form->createView(), array(), +'/div + [ + ./div + [@class="form-check"] + [ + ./label + [.=" Placeholder&Not&Translated"] + [ + ./input[@type="radio"][@name="name"][@id="name_placeholder"][not(@checked)] + ] + ] + /following-sibling::div + [@class="form-check"] + [ + ./label + [.=" Choice&A"] + [ + ./input[@type="radio"][@name="name"][@id="name_0"][@checked] + ] + ] + /following-sibling::div + [@class="form-check"] + [ + ./label + [.=" Choice&B"] + [ + ./input[@type="radio"][@name="name"][@id="name_1"][not(@checked)] + ] + ] + /following-sibling::input[@type="hidden"][@id="name__token"] + ] +' + ); + } + + public function testSingleChoiceExpandedWithBooleanValue() + { + $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\ChoiceType', true, array( + 'choices' => array('Choice&A' => '1', 'Choice&B' => '0'), + 'multiple' => false, + 'expanded' => true, + )); + + $this->assertWidgetMatchesXpath($form->createView(), array(), +'/div + [ + ./div + [@class="form-check"] + [ + ./label + [.=" [trans]Choice&A[/trans]"] + [ + ./input[@type="radio"][@name="name"][@id="name_0"][@checked] + ] + ] + /following-sibling::div + [@class="form-check"] + [ + ./label + [.=" [trans]Choice&B[/trans]"] + [ + ./input[@type="radio"][@name="name"][@id="name_1"][not(@checked)] + ] + ] + /following-sibling::input[@type="hidden"][@id="name__token"] + ] +' + ); + } + + public function testMultipleChoiceExpanded() + { + $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\ChoiceType', array('&a', '&c'), array( + 'choices' => array('Choice&A' => '&a', 'Choice&B' => '&b', 'Choice&C' => '&c'), + 'multiple' => true, + 'expanded' => true, + 'required' => true, + )); + + $this->assertWidgetMatchesXpath($form->createView(), array(), +'/div + [ + ./div + [@class="form-check"] + [ + ./label + [.=" [trans]Choice&A[/trans]"] + [ + ./input[@type="checkbox"][@name="name[]"][@id="name_0"][@checked][not(@required)] + ] + ] + /following-sibling::div + [@class="form-check"] + [ + ./label + [.=" [trans]Choice&B[/trans]"] + [ + ./input[@type="checkbox"][@name="name[]"][@id="name_1"][not(@checked)][not(@required)] + ] + ] + /following-sibling::div + [@class="form-check"] + [ + ./label + [.=" [trans]Choice&C[/trans]"] + [ + ./input[@type="checkbox"][@name="name[]"][@id="name_2"][@checked][not(@required)] + ] + ] + /following-sibling::input[@type="hidden"][@id="name__token"] + ] +' + ); + } + + public function testMultipleChoiceExpandedWithLabelsAsFalse() + { + $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\ChoiceType', array('&a'), array( + 'choices' => array('Choice&A' => '&a', 'Choice&B' => '&b'), + 'choice_label' => false, + 'multiple' => true, + 'expanded' => true, + )); + + $this->assertWidgetMatchesXpath($form->createView(), array(), +'/div + [ + ./div + [@class="form-check"] + [ + ./label + [ + ./input[@type="checkbox"][@name="name[]"][@id="name_0"][@value="&a"][@checked] + ] + ] + /following-sibling::div + [@class="form-check"] + [ + ./label + [ + ./input[@type="checkbox"][@name="name[]"][@id="name_1"][@value="&b"][not(@checked)] + ] + ] + /following-sibling::input[@type="hidden"][@id="name__token"] + ] +' + ); + } + + public function testMultipleChoiceExpandedWithLabelsSetByCallable() + { + $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\ChoiceType', array('&a'), array( + 'choices' => array('Choice&A' => '&a', 'Choice&B' => '&b', 'Choice&C' => '&c'), + 'choice_label' => function ($choice, $label, $value) { + if ('&b' === $choice) { + return false; + } + + return 'label.'.$value; + }, + 'multiple' => true, + 'expanded' => true, + )); + + $this->assertWidgetMatchesXpath($form->createView(), array(), + '/div + [ + ./div + [@class="form-check"] + [ + ./label + [.=" [trans]label.&a[/trans]"] + [ + ./input[@type="checkbox"][@name="name[]"][@id="name_0"][@value="&a"][@checked] + ] + ] + /following-sibling::div + [@class="form-check"] + [ + ./label + [ + ./input[@type="checkbox"][@name="name[]"][@id="name_1"][@value="&b"][not(@checked)] + ] + ] + /following-sibling::div + [@class="form-check"] + [ + ./label + [.=" [trans]label.&c[/trans]"] + [ + ./input[@type="checkbox"][@name="name[]"][@id="name_2"][@value="&c"][not(@checked)] + ] + ] + /following-sibling::input[@type="hidden"][@id="name__token"] + ] +' + ); + } + + public function testMultipleChoiceExpandedWithLabelsSetFalseByCallable() + { + $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\ChoiceType', array('&a'), array( + 'choices' => array('Choice&A' => '&a', 'Choice&B' => '&b'), + 'choice_label' => function () { + return false; + }, + 'multiple' => true, + 'expanded' => true, + )); + + $this->assertWidgetMatchesXpath($form->createView(), array(), +'/div + [ + ./div + [@class="form-check"] + [ + ./label + [ + ./input[@type="checkbox"][@name="name[]"][@id="name_0"][@value="&a"][@checked] + ] + ] + /following-sibling::div + [@class="form-check"] + [ + ./label + [ + ./input[@type="checkbox"][@name="name[]"][@id="name_1"][@value="&b"][not(@checked)] + ] + ] + /following-sibling::input[@type="hidden"][@id="name__token"] + ] +' + ); + } + + public function testMultipleChoiceExpandedWithoutTranslation() + { + $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\ChoiceType', array('&a', '&c'), array( + 'choices' => array('Choice&A' => '&a', 'Choice&B' => '&b', 'Choice&C' => '&c'), + 'multiple' => true, + 'expanded' => true, + 'required' => true, + 'choice_translation_domain' => false, + )); + + $this->assertWidgetMatchesXpath($form->createView(), array(), +'/div + [ + ./div + [@class="form-check"] + [ + ./label + [.=" Choice&A"] + [ + ./input[@type="checkbox"][@name="name[]"][@id="name_0"][@checked][not(@required)] + ] + ] + /following-sibling::div + [@class="form-check"] + [ + ./label + [.=" Choice&B"] + [ + ./input[@type="checkbox"][@name="name[]"][@id="name_1"][not(@checked)][not(@required)] + ] + ] + /following-sibling::div + [@class="form-check"] + [ + ./label + [.=" Choice&C"] + [ + ./input[@type="checkbox"][@name="name[]"][@id="name_2"][@checked][not(@required)] + ] + ] + /following-sibling::input[@type="hidden"][@id="name__token"] + ] +' + ); + } + + public function testMultipleChoiceExpandedAttributes() + { + $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\ChoiceType', array('&a', '&c'), array( + 'choices' => array('Choice&A' => '&a', 'Choice&B' => '&b', 'Choice&C' => '&c'), + 'choice_attr' => array('Choice&B' => array('class' => 'foo&bar')), + 'multiple' => true, + 'expanded' => true, + 'required' => true, + )); + + $this->assertWidgetMatchesXpath($form->createView(), array(), +'/div + [ + ./div + [@class="form-check"] + [ + ./label + [.=" [trans]Choice&A[/trans]"] + [ + ./input[@type="checkbox"][@name="name[]"][@id="name_0"][@checked][not(@required)] + ] + ] + /following-sibling::div + [@class="form-check"] + [ + ./label + [.=" [trans]Choice&B[/trans]"] + [ + ./input[@type="checkbox"][@name="name[]"][@id="name_1"][not(@checked)][not(@required)][@class="foo&bar"] + ] + ] + /following-sibling::div + [@class="form-check"] + [ + ./label + [.=" [trans]Choice&C[/trans]"] + [ + ./input[@type="checkbox"][@name="name[]"][@id="name_2"][@checked][not(@required)] + ] + ] + /following-sibling::input[@type="hidden"][@id="name__token"] + ] +' + ); + } + + public function testCheckedRadio() + { + $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\RadioType', true); + + $this->assertWidgetMatchesXpath($form->createView(), array('id' => 'my&id', 'attr' => array('class' => 'my&class')), +'/div + [@class="form-check"] + [ + ./label + [@class="form-check-label required"] + [ + ./input + [@id="my&id"] + [@type="radio"] + [@name="name"] + [@class="my&class"] + [@checked="checked"] + [@value="1"] + ] + ] +' + ); + } + + public function testUncheckedRadio() + { + $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\RadioType', false); + + $this->assertWidgetMatchesXpath($form->createView(), array('id' => 'my&id', 'attr' => array('class' => 'my&class')), +'/div + [@class="form-check"] + [ + ./label + [@class="form-check-label required"] + [ + ./input + [@id="my&id"] + [@type="radio"] + [@name="name"] + [@class="my&class"] + [not(@checked)] + ] + ] +' + ); + } + + public function testRadioWithValue() + { + $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\RadioType', false, array( + 'value' => 'foo&bar', + )); + + $this->assertWidgetMatchesXpath($form->createView(), array('id' => 'my&id', 'attr' => array('class' => 'my&class')), +'/div + [@class="form-check"] + [ + ./label + [@class="form-check-label required"] + [ + ./input + [@id="my&id"] + [@type="radio"] + [@name="name"] + [@class="my&class"] + [@value="foo&bar"] + ] + ] +' + ); + } + + public function testButtonAttributeNameRepeatedIfTrue() + { + $form = $this->factory->createNamed('button', 'Symfony\Component\Form\Extension\Core\Type\ButtonType', null, array( + 'attr' => array('foo' => true), + )); + + $html = $this->renderWidget($form->createView()); + + // foo="foo" + $this->assertSame('', $html); + } + + public function testFile() + { + $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\FileType'); + + $this->assertWidgetMatchesXpath($form->createView(), array('attr' => array('class' => 'my&class form-control-file')), +'/input + [@type="file"] +' + ); + } +} From a2af9a940f24f157bf0256dc4af1af9b9f4516e6 Mon Sep 17 00:00:00 2001 From: Javier Eguiluz Date: Fri, 1 Sep 2017 15:23:39 +0200 Subject: [PATCH 0742/1099] Improved how links are displayed in exception messages --- .../Bundle/TwigBundle/Resources/views/exception.css.twig | 4 ++-- src/Symfony/Component/Debug/ExceptionHandler.php | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Symfony/Bundle/TwigBundle/Resources/views/exception.css.twig b/src/Symfony/Bundle/TwigBundle/Resources/views/exception.css.twig index 84112fad6ed94..9f12edece1e71 100644 --- a/src/Symfony/Bundle/TwigBundle/Resources/views/exception.css.twig +++ b/src/Symfony/Bundle/TwigBundle/Resources/views/exception.css.twig @@ -84,8 +84,8 @@ header .container { display: flex; justify-content: space-between; } .exception-message { flex-grow: 1; } .exception-message, .exception-message a { color: #FFF; font-size: 21px; font-weight: 400; margin: 0; } .exception-message.long { font-size: 18px; } -.exception-message a { text-decoration: none; } -.exception-message a:hover { text-decoration: underline; } +.exception-message a { border-bottom: 1px solid rgba(255, 255, 255, 0.5); font-size: inherit; text-decoration: none; } +.exception-message a:hover { border-bottom-color: #ffffff; } .exception-illustration { flex-basis: 111px; flex-shrink: 0; height: 66px; margin-left: 15px; opacity: .7; } diff --git a/src/Symfony/Component/Debug/ExceptionHandler.php b/src/Symfony/Component/Debug/ExceptionHandler.php index 0ecd2a5347f27..a82a3246d9eaa 100644 --- a/src/Symfony/Component/Debug/ExceptionHandler.php +++ b/src/Symfony/Component/Debug/ExceptionHandler.php @@ -310,8 +310,8 @@ public function getStylesheet(FlattenException $exception) .exception-message { flex-grow: 1; padding: 30px 0; } .exception-message, .exception-message a { color: #FFF; font-size: 21px; font-weight: 400; margin: 0; } .exception-message.long { font-size: 18px; } - .exception-message a { text-decoration: none; } - .exception-message a:hover { text-decoration: underline; } + .exception-message a { border-bottom: 1px solid rgba(255, 255, 255, 0.5); font-size: inherit; text-decoration: none; } + .exception-message a:hover { border-bottom-color: #ffffff; } .exception-illustration { flex-basis: 111px; flex-shrink: 0; height: 66px; margin-left: 15px; opacity: .7; } From fb5135b742c482ca981ade0db56db7440ed224e6 Mon Sep 17 00:00:00 2001 From: Javier Eguiluz Date: Fri, 1 Sep 2017 15:44:20 +0200 Subject: [PATCH 0743/1099] Improved the design of the redirection method in the web toolbar --- .../WebProfilerBundle/Resources/views/Profiler/toolbar.css.twig | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/toolbar.css.twig b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/toolbar.css.twig index 7ef299437bb5f..3a65e1d0537d6 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/toolbar.css.twig +++ b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/toolbar.css.twig @@ -250,6 +250,7 @@ font-size: 12px; height: 17px; line-height: 17px; + margin-right: 5px; } .sf-toolbar-status-green .sf-toolbar-label, From 2f292c247eef1b47dd6d2abc7760ab8a515470d9 Mon Sep 17 00:00:00 2001 From: Oleg Andreyev Date: Thu, 31 Aug 2017 12:18:43 +0300 Subject: [PATCH 0744/1099] #24046 added check for ext-dom to XmlUtil::loadFile --- src/Symfony/Component/Config/Util/XmlUtils.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/Symfony/Component/Config/Util/XmlUtils.php b/src/Symfony/Component/Config/Util/XmlUtils.php index 25d9b0a0abe5d..0f16fc080bf05 100644 --- a/src/Symfony/Component/Config/Util/XmlUtils.php +++ b/src/Symfony/Component/Config/Util/XmlUtils.php @@ -37,9 +37,14 @@ private function __construct() * @return \DOMDocument * * @throws \InvalidArgumentException When loading of XML file returns error + * @throws \RuntimeException When DOM extension is missing */ public static function loadFile($file, $schemaOrCallable = null) { + if (!extension_loaded('dom')) { + throw new \RuntimeException('Extension DOM is required.'); + } + $content = @file_get_contents($file); if ('' === trim($content)) { throw new \InvalidArgumentException(sprintf('File %s does not contain valid XML, it is empty.', $file)); From 26948cf565709d3a5524a52b5d1b5d65b3c88f0f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9my=20Deruss=C3=A9?= Date: Sun, 3 Sep 2017 14:43:23 +0200 Subject: [PATCH 0745/1099] Fix race condition in tests between cache and lock --- .../Component/Cache/Tests/Adapter/AbstractRedisAdapterTest.php | 1 - .../Component/Cache/Tests/Adapter/PredisClusterAdapterTest.php | 1 - .../Component/Cache/Tests/Simple/AbstractRedisCacheTest.php | 1 - 3 files changed, 3 deletions(-) diff --git a/src/Symfony/Component/Cache/Tests/Adapter/AbstractRedisAdapterTest.php b/src/Symfony/Component/Cache/Tests/Adapter/AbstractRedisAdapterTest.php index 86b16d436f23f..d9353821ae6ef 100644 --- a/src/Symfony/Component/Cache/Tests/Adapter/AbstractRedisAdapterTest.php +++ b/src/Symfony/Component/Cache/Tests/Adapter/AbstractRedisAdapterTest.php @@ -41,7 +41,6 @@ public static function setupBeforeClass() public static function tearDownAfterClass() { - self::$redis->flushDB(); self::$redis = null; } } diff --git a/src/Symfony/Component/Cache/Tests/Adapter/PredisClusterAdapterTest.php b/src/Symfony/Component/Cache/Tests/Adapter/PredisClusterAdapterTest.php index 6ed1c7d6a9f3b..38915397da993 100644 --- a/src/Symfony/Component/Cache/Tests/Adapter/PredisClusterAdapterTest.php +++ b/src/Symfony/Component/Cache/Tests/Adapter/PredisClusterAdapterTest.php @@ -21,7 +21,6 @@ public static function setupBeforeClass() public static function tearDownAfterClass() { - self::$redis->getConnection()->getConnectionByKey('foo')->executeCommand(self::$redis->createCommand('FLUSHDB')); self::$redis = null; } } diff --git a/src/Symfony/Component/Cache/Tests/Simple/AbstractRedisCacheTest.php b/src/Symfony/Component/Cache/Tests/Simple/AbstractRedisCacheTest.php index 1d097fff85fcd..f70f49d5dbaa6 100644 --- a/src/Symfony/Component/Cache/Tests/Simple/AbstractRedisCacheTest.php +++ b/src/Symfony/Component/Cache/Tests/Simple/AbstractRedisCacheTest.php @@ -41,7 +41,6 @@ public static function setupBeforeClass() public static function tearDownAfterClass() { - self::$redis->flushDB(); self::$redis = null; } } From f74ef3577812be2fcbb5fe6382186b937bd22ebe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9my=20Deruss=C3=A9?= Date: Wed, 26 Apr 2017 22:57:15 +0200 Subject: [PATCH 0746/1099] [Lock] Check TTL expiration in lock acquisition --- .../Lock/Exception/LockExpiredException.php | 21 ++++++++++++++ src/Symfony/Component/Lock/Key.php | 28 +++++++++++++------ src/Symfony/Component/Lock/Lock.php | 27 ++++++++++++------ .../Component/Lock/Store/CombinedStore.php | 14 +++++++++- .../Component/Lock/Store/MemcachedStore.php | 16 +++++++---- .../Component/Lock/Store/RedisStore.php | 9 ++++++ src/Symfony/Component/Lock/Tests/LockTest.php | 12 ++++---- .../Lock/Tests/Store/CombinedStoreTest.php | 10 +++---- .../Tests/Store/ExpiringStoreTestTrait.php | 23 +++++++++++++-- .../Lock/Tests/Store/MemcachedStoreTest.php | 5 ++++ 10 files changed, 128 insertions(+), 37 deletions(-) create mode 100644 src/Symfony/Component/Lock/Exception/LockExpiredException.php diff --git a/src/Symfony/Component/Lock/Exception/LockExpiredException.php b/src/Symfony/Component/Lock/Exception/LockExpiredException.php new file mode 100644 index 0000000000000..9b712ae0b715b --- /dev/null +++ b/src/Symfony/Component/Lock/Exception/LockExpiredException.php @@ -0,0 +1,21 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Lock\Exception; + +/** + * LockExpiredException is thrown when a lock may conflict due to a TTL expiration. + * + * @author Jérémy Derussé + */ +class LockExpiredException extends \RuntimeException implements ExceptionInterface +{ +} diff --git a/src/Symfony/Component/Lock/Key.php b/src/Symfony/Component/Lock/Key.php index 5069901761820..1f5a7de740ef9 100644 --- a/src/Symfony/Component/Lock/Key.php +++ b/src/Symfony/Component/Lock/Key.php @@ -19,7 +19,7 @@ final class Key { private $resource; - private $expiringDate; + private $expiringTime; private $state = array(); /** @@ -72,28 +72,38 @@ public function getState($stateKey) return $this->state[$stateKey]; } + public function resetLifetime() + { + $this->expiringTime = null; + } + /** * @param float $ttl The expiration delay of locks in seconds. */ public function reduceLifetime($ttl) { - $newExpiringDate = \DateTimeImmutable::createFromFormat('U.u', (string) (microtime(true) + $ttl)); + $newTime = microtime(true) + $ttl; - if (null === $this->expiringDate || $newExpiringDate < $this->expiringDate) { - $this->expiringDate = $newExpiringDate; + if (null === $this->expiringTime || $this->expiringTime > $newTime) { + $this->expiringTime = $newTime; } } - public function resetExpiringDate() + /** + * Returns the remaining lifetime. + * + * @return float|null Remaining lifetime in seconds. Null when the key won't expire. + */ + public function getRemainingLifetime() { - $this->expiringDate = null; + return null === $this->expiringTime ? null : $this->expiringTime - microtime(true); } /** - * @return \DateTimeImmutable + * @return bool */ - public function getExpiringDate() + public function isExpired() { - return $this->expiringDate; + return null !== $this->expiringTime && $this->expiringTime <= microtime(true); } } diff --git a/src/Symfony/Component/Lock/Lock.php b/src/Symfony/Component/Lock/Lock.php index c42bd2255cf5f..d8271569d8c05 100644 --- a/src/Symfony/Component/Lock/Lock.php +++ b/src/Symfony/Component/Lock/Lock.php @@ -17,6 +17,7 @@ use Symfony\Component\Lock\Exception\InvalidArgumentException; use Symfony\Component\Lock\Exception\LockAcquiringException; use Symfony\Component\Lock\Exception\LockConflictedException; +use Symfony\Component\Lock\Exception\LockExpiredException; use Symfony\Component\Lock\Exception\LockReleasingException; /** @@ -64,6 +65,10 @@ public function acquire($blocking = false) $this->refresh(); } + if ($this->key->isExpired()) { + throw new LockExpiredException(sprintf('Failed to store the "%s" lock.', $this->key)); + } + return true; } catch (LockConflictedException $e) { $this->logger->warning('Failed to acquire the "{resource}" lock. Someone else already acquired the lock.', array('resource' => $this->key)); @@ -89,8 +94,13 @@ public function refresh() } try { - $this->key->resetExpiringDate(); + $this->key->resetLifetime(); $this->store->putOffExpiration($this->key, $this->ttl); + + if ($this->key->isExpired()) { + throw new LockExpiredException(sprintf('Failed to put off the expiration of the "%s" lock within the specified time.', $this->key)); + } + $this->logger->info('Expiration defined for "{resource}" lock for "{ttl}" seconds.', array('resource' => $this->key, 'ttl' => $this->ttl)); } catch (LockConflictedException $e) { $this->logger->warning('Failed to define an expiration for the "{resource}" lock, someone else acquired the lock.', array('resource' => $this->key)); @@ -127,15 +137,16 @@ public function release() */ public function isExpired() { - if (null === $expireDate = $this->key->getExpiringDate()) { - return false; - } - - return $expireDate <= new \DateTime(); + return $this->key->isExpired(); } - public function getExpiringDate() + /** + * Returns the remaining lifetime. + * + * @return float|null Remaining lifetime in seconds. Null when the lock won't expire. + */ + public function getRemainingLifetime() { - return $this->key->getExpiringDate(); + return $this->key->getRemainingLifetime(); } } diff --git a/src/Symfony/Component/Lock/Store/CombinedStore.php b/src/Symfony/Component/Lock/Store/CombinedStore.php index 0f5a78cef6455..50258fe694d6d 100644 --- a/src/Symfony/Component/Lock/Store/CombinedStore.php +++ b/src/Symfony/Component/Lock/Store/CombinedStore.php @@ -16,6 +16,7 @@ use Psr\Log\NullLogger; use Symfony\Component\Lock\Exception\InvalidArgumentException; use Symfony\Component\Lock\Exception\LockConflictedException; +use Symfony\Component\Lock\Exception\LockExpiredException; use Symfony\Component\Lock\Exception\NotSupportedException; use Symfony\Component\Lock\Key; use Symfony\Component\Lock\Strategy\StrategyInterface; @@ -102,10 +103,17 @@ public function putOffExpiration(Key $key, $ttl) $successCount = 0; $failureCount = 0; $storesCount = count($this->stores); + $expireAt = microtime(true) + $ttl; foreach ($this->stores as $store) { try { - $store->putOffExpiration($key, $ttl); + if (0.0 >= $adjustedTtl = $expireAt - microtime(true)) { + $this->logger->warning('Stores took to long to put off the expiration of the "{resource}" lock.', array('resource' => $key, 'store' => $store, 'ttl' => $ttl)); + $key->reduceLifetime(0); + break; + } + + $store->putOffExpiration($key, $adjustedTtl); ++$successCount; } catch (\Exception $e) { $this->logger->warning('One store failed to put off the expiration of the "{resource}" lock.', array('resource' => $key, 'store' => $store, 'exception' => $e)); @@ -117,6 +125,10 @@ public function putOffExpiration(Key $key, $ttl) } } + if ($key->isExpired()) { + throw new LockExpiredException(sprintf('Failed to put off the expiration of the "%s" lock within the specified time.', $key)); + } + if ($this->strategy->isMet($successCount, $storesCount)) { return; } diff --git a/src/Symfony/Component/Lock/Store/MemcachedStore.php b/src/Symfony/Component/Lock/Store/MemcachedStore.php index 4f8d6f5ff7159..dc34bdf846695 100644 --- a/src/Symfony/Component/Lock/Store/MemcachedStore.php +++ b/src/Symfony/Component/Lock/Store/MemcachedStore.php @@ -13,6 +13,7 @@ use Symfony\Component\Lock\Exception\InvalidArgumentException; use Symfony\Component\Lock\Exception\LockConflictedException; +use Symfony\Component\Lock\Exception\LockExpiredException; use Symfony\Component\Lock\Key; use Symfony\Component\Lock\StoreInterface; @@ -57,14 +58,15 @@ public function __construct(\Memcached $memcached, $initialTtl = 300) public function save(Key $key) { $token = $this->getToken($key); - $key->reduceLifetime($this->initialTtl); - if ($this->memcached->add((string) $key, $token, (int) ceil($this->initialTtl))) { - return; + if (!$this->memcached->add((string) $key, $token, (int) ceil($this->initialTtl))) { + // the lock is already acquired. It could be us. Let's try to put off. + $this->putOffExpiration($key, $this->initialTtl); } - // the lock is already acquire. It could be us. Let's try to put off. - $this->putOffExpiration($key, $this->initialTtl); + if ($key->isExpired()) { + throw new LockExpiredException(sprintf('Failed to store the "%s" lock.', $key)); + } } public function waitAndSave(Key $key) @@ -107,6 +109,10 @@ public function putOffExpiration(Key $key, $ttl) if (!$this->memcached->cas($cas, (string) $key, $token, $ttl)) { throw new LockConflictedException(); } + + if ($key->isExpired()) { + throw new LockExpiredException(sprintf('Failed to put off the expiration of the "%s" lock within the specified time.', $key)); + } } /** diff --git a/src/Symfony/Component/Lock/Store/RedisStore.php b/src/Symfony/Component/Lock/Store/RedisStore.php index d67120fe0c0c3..88b15938997c9 100644 --- a/src/Symfony/Component/Lock/Store/RedisStore.php +++ b/src/Symfony/Component/Lock/Store/RedisStore.php @@ -13,6 +13,7 @@ use Symfony\Component\Lock\Exception\InvalidArgumentException; use Symfony\Component\Lock\Exception\LockConflictedException; +use Symfony\Component\Lock\Exception\LockExpiredException; use Symfony\Component\Lock\Key; use Symfony\Component\Lock\StoreInterface; @@ -61,6 +62,10 @@ public function save(Key $key) if (!$this->evaluate($script, (string) $key, array($this->getToken($key), (int) ceil($this->initialTtl * 1000)))) { throw new LockConflictedException(); } + + if ($key->isExpired()) { + throw new LockExpiredException(sprintf('Failed to store the "%s" lock.', $key)); + } } public function waitAndSave(Key $key) @@ -85,6 +90,10 @@ public function putOffExpiration(Key $key, $ttl) if (!$this->evaluate($script, (string) $key, array($this->getToken($key), (int) ceil($ttl * 1000)))) { throw new LockConflictedException(); } + + if ($key->isExpired()) { + throw new LockExpiredException(sprintf('Failed to put off the expiration of the "%s" lock within the specified time.', $key)); + } } /** diff --git a/src/Symfony/Component/Lock/Tests/LockTest.php b/src/Symfony/Component/Lock/Tests/LockTest.php index fb107232efba6..97b376621169a 100644 --- a/src/Symfony/Component/Lock/Tests/LockTest.php +++ b/src/Symfony/Component/Lock/Tests/LockTest.php @@ -165,7 +165,7 @@ public function testExpiration($ttls, $expected) foreach ($ttls as $ttl) { if (null === $ttl) { - $key->resetExpiringDate(); + $key->resetLifetime(); } else { $key->reduceLifetime($ttl); } @@ -175,12 +175,12 @@ public function testExpiration($ttls, $expected) public function provideExpiredDates() { - yield array(array(-1.0), true); - yield array(array(1, -1.0), true); - yield array(array(-1.0, 1), true); + yield array(array(-0.1), true); + yield array(array(0.1, -0.1), true); + yield array(array(-0.1, 0.1), true); yield array(array(), false); - yield array(array(1), false); - yield array(array(-1.0, null), false); + yield array(array(0.1), false); + yield array(array(-0.1, null), false); } } diff --git a/src/Symfony/Component/Lock/Tests/Store/CombinedStoreTest.php b/src/Symfony/Component/Lock/Tests/Store/CombinedStoreTest.php index debe06183dc35..c7232d407feee 100644 --- a/src/Symfony/Component/Lock/Tests/Store/CombinedStoreTest.php +++ b/src/Symfony/Component/Lock/Tests/Store/CombinedStoreTest.php @@ -175,12 +175,12 @@ public function testputOffExpirationThrowsExceptionOnFailure() $this->store1 ->expects($this->once()) ->method('putOffExpiration') - ->with($key, $ttl) + ->with($key, $this->lessThanOrEqual($ttl)) ->willThrowException(new LockConflictedException()); $this->store2 ->expects($this->once()) ->method('putOffExpiration') - ->with($key, $ttl) + ->with($key, $this->lessThanOrEqual($ttl)) ->willThrowException(new LockConflictedException()); $this->strategy @@ -203,12 +203,12 @@ public function testputOffExpirationCleanupOnFailure() $this->store1 ->expects($this->once()) ->method('putOffExpiration') - ->with($key, $ttl) + ->with($key, $this->lessThanOrEqual($ttl)) ->willThrowException(new LockConflictedException()); $this->store2 ->expects($this->once()) ->method('putOffExpiration') - ->with($key, $ttl) + ->with($key, $this->lessThanOrEqual($ttl)) ->willThrowException(new LockConflictedException()); $this->store1 @@ -242,7 +242,7 @@ public function testputOffExpirationAbortWhenStrategyCantBeMet() $this->store1 ->expects($this->once()) ->method('putOffExpiration') - ->with($key, $ttl) + ->with($key, $this->lessThanOrEqual($ttl)) ->willThrowException(new LockConflictedException()); $this->store2 ->expects($this->never()) diff --git a/src/Symfony/Component/Lock/Tests/Store/ExpiringStoreTestTrait.php b/src/Symfony/Component/Lock/Tests/Store/ExpiringStoreTestTrait.php index f862f0d4aa300..10b13273870e7 100644 --- a/src/Symfony/Component/Lock/Tests/Store/ExpiringStoreTestTrait.php +++ b/src/Symfony/Component/Lock/Tests/Store/ExpiringStoreTestTrait.php @@ -52,6 +52,22 @@ public function testExpiration() $this->assertFalse($store->exists($key)); } + /** + * Tests the store thrown exception when TTL expires. + * + * @expectedException \Symfony\Component\Lock\Exception\LockExpiredException + */ + public function testAbortAfterExpiration() + { + $key = new Key(uniqid(__METHOD__, true)); + + /** @var StoreInterface $store */ + $store = $this->getStore(); + + $store->save($key); + $store->putOffExpiration($key, 1 / 1000000); + } + /** * Tests the refresh can push the limits to the expiration. * @@ -69,10 +85,10 @@ public function testRefreshLock() $store = $this->getStore(); $store->save($key); - $store->putOffExpiration($key, 1.0 * $clockDelay / 1000000); + $store->putOffExpiration($key, $clockDelay / 1000000); $this->assertTrue($store->exists($key)); - usleep(2.1 * $clockDelay); + usleep(2 * $clockDelay); $this->assertFalse($store->exists($key)); } @@ -85,6 +101,7 @@ public function testSetExpiration() $store->save($key); $store->putOffExpiration($key, 1); - $this->assertNotNull($key->getExpiringDate()); + $this->assertGreaterThanOrEqual(0, $key->getRemainingLifetime()); + $this->assertLessThanOrEqual(1, $key->getRemainingLifetime()); } } diff --git a/src/Symfony/Component/Lock/Tests/Store/MemcachedStoreTest.php b/src/Symfony/Component/Lock/Tests/Store/MemcachedStoreTest.php index 72615baae2ce8..eb030fba0f9de 100644 --- a/src/Symfony/Component/Lock/Tests/Store/MemcachedStoreTest.php +++ b/src/Symfony/Component/Lock/Tests/Store/MemcachedStoreTest.php @@ -49,4 +49,9 @@ public function getStore() return new MemcachedStore($memcached); } + + public function testAbortAfterExpiration() + { + $this->markTestSkipped('Memcached expects a TTL greater than 1 sec. Simulating a slow network is too hard'); + } } From 99e95c3d2dd0fee9f7bed43fa10e786121b92b48 Mon Sep 17 00:00:00 2001 From: Robin Chalas Date: Sun, 3 Sep 2017 01:52:02 +0200 Subject: [PATCH 0747/1099] Fix BC break in console.command.ids parameter --- .../Bundle/FrameworkBundle/Console/Application.php | 3 ++- .../Tests/Console/ApplicationTest.php | 12 ++++++------ .../DependencyInjection/AddConsoleCommandPass.php | 5 ++++- .../AddConsoleCommandPassTest.php | 6 ++++-- 4 files changed, 16 insertions(+), 10 deletions(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/Console/Application.php b/src/Symfony/Bundle/FrameworkBundle/Console/Application.php index 09c61933ee207..7182fc1b934a7 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Console/Application.php +++ b/src/Symfony/Bundle/FrameworkBundle/Console/Application.php @@ -173,8 +173,9 @@ protected function registerCommands() } if ($container->hasParameter('console.command.ids')) { + $lazyCommandIds = $container->hasParameter('console.lazy_command.ids') ? $container->getParameter('console.lazy_command.ids') : array(); foreach ($container->getParameter('console.command.ids') as $id) { - if (false !== $id) { + if (!isset($lazyCommandIds[$id])) { try { $this->add($container->get($id)); } catch (\Exception $e) { diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Console/ApplicationTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Console/ApplicationTest.php index ce7ebad1f158e..9396b68212d9d 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Console/ApplicationTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Console/ApplicationTest.php @@ -183,16 +183,16 @@ private function getKernel(array $bundles, $useDispatcher = false) } $container - ->expects($this->once()) + ->expects($this->exactly(2)) ->method('hasParameter') - ->with($this->equalTo('console.command.ids')) - ->will($this->returnValue(true)) + ->withConsecutive(array('console.command.ids'), array('console.lazy_command.ids')) + ->willReturnOnConsecutiveCalls(true, true) ; $container - ->expects($this->once()) + ->expects($this->exactly(2)) ->method('getParameter') - ->with($this->equalTo('console.command.ids')) - ->will($this->returnValue(array())) + ->withConsecutive(array('console.lazy_command.ids'), array('console.command.ids')) + ->willReturnOnConsecutiveCalls(array(), array()) ; $kernel = $this->getMockBuilder('Symfony\Component\HttpKernel\KernelInterface')->getMock(); diff --git a/src/Symfony/Component/Console/DependencyInjection/AddConsoleCommandPass.php b/src/Symfony/Component/Console/DependencyInjection/AddConsoleCommandPass.php index add7c5d0df491..dcc023cb222da 100644 --- a/src/Symfony/Component/Console/DependencyInjection/AddConsoleCommandPass.php +++ b/src/Symfony/Component/Console/DependencyInjection/AddConsoleCommandPass.php @@ -41,6 +41,7 @@ public function process(ContainerBuilder $container) $lazyCommandMap = array(); $lazyCommandRefs = array(); $serviceIds = array(); + $lazyServiceIds = array(); foreach ($commandServices as $id => $tags) { $definition = $container->getDefinition($id); @@ -73,7 +74,8 @@ public function process(ContainerBuilder $container) continue; } - $serviceIds[$commandId] = false; + $serviceIds[$commandId] = $id; + $lazyServiceIds[$id] = true; unset($tags[0]); $lazyCommandMap[$commandName] = $id; $lazyCommandRefs[$id] = new TypedReference($id, $class); @@ -98,5 +100,6 @@ public function process(ContainerBuilder $container) ->setArguments(array(ServiceLocatorTagPass::register($container, $lazyCommandRefs), $lazyCommandMap)); $container->setParameter('console.command.ids', $serviceIds); + $container->setParameter('console.lazy_command.ids', $lazyServiceIds); } } diff --git a/src/Symfony/Component/Console/Tests/DependencyInjection/AddConsoleCommandPassTest.php b/src/Symfony/Component/Console/Tests/DependencyInjection/AddConsoleCommandPassTest.php index 807eb389730fe..34f648610836a 100644 --- a/src/Symfony/Component/Console/Tests/DependencyInjection/AddConsoleCommandPassTest.php +++ b/src/Symfony/Component/Console/Tests/DependencyInjection/AddConsoleCommandPassTest.php @@ -73,7 +73,8 @@ public function testProcessRegistersLazyCommands() $this->assertSame(ContainerCommandLoader::class, $commandLoader->getClass()); $this->assertSame(array('my:command' => 'my-command', 'my:alias' => 'my-command'), $commandLoader->getArgument(1)); $this->assertEquals(array(array('my-command' => new ServiceClosureArgument(new TypedReference('my-command', MyCommand::class)))), $commandLocator->getArguments()); - $this->assertSame(array('console.command.symfony_component_console_tests_dependencyinjection_mycommand' => false), $container->getParameter('console.command.ids')); + $this->assertSame(array('console.command.symfony_component_console_tests_dependencyinjection_mycommand' => 'my-command'), $container->getParameter('console.command.ids')); + $this->assertSame(array('my-command' => true), $container->getParameter('console.lazy_command.ids')); $this->assertSame(array(array('setName', array('my:command')), array('setAliases', array(array('my:alias')))), $command->getMethodCalls()); } @@ -95,7 +96,8 @@ public function testProcessFallsBackToDefaultName() $this->assertSame(ContainerCommandLoader::class, $commandLoader->getClass()); $this->assertSame(array('default' => 'with-default-name'), $commandLoader->getArgument(1)); $this->assertEquals(array(array('with-default-name' => new ServiceClosureArgument(new TypedReference('with-default-name', NamedCommand::class)))), $commandLocator->getArguments()); - $this->assertSame(array('console.command.symfony_component_console_tests_dependencyinjection_namedcommand' => false), $container->getParameter('console.command.ids')); + $this->assertSame(array('console.command.symfony_component_console_tests_dependencyinjection_namedcommand' => 'with-default-name'), $container->getParameter('console.command.ids')); + $this->assertSame(array('with-default-name' => true), $container->getParameter('console.lazy_command.ids')); $container = new ContainerBuilder(); $container From 46599759441d5c5a32f2735c9f446258f846cf62 Mon Sep 17 00:00:00 2001 From: Robin Chalas Date: Sat, 12 Aug 2017 12:12:58 +0200 Subject: [PATCH 0748/1099] Fix deprecations regarding core commands registered as services --- UPGRADE-3.4.md | 56 ++++++++++++++++++- UPGRADE-4.0.md | 50 +++++++++++++++-- src/Symfony/Bridge/Twig/CHANGELOG.md | 6 +- .../Bundle/FrameworkBundle/CHANGELOG.md | 27 +++++++++ .../Command/AssetsInstallCommand.php | 2 +- .../Command/CacheClearCommand.php | 2 +- .../Command/CachePoolClearCommand.php | 2 +- .../Command/EventDispatcherDebugCommand.php | 2 +- .../Command/RouterDebugCommand.php | 2 +- .../Command/RouterMatchCommand.php | 2 +- .../Command/TranslationDebugCommand.php | 2 +- .../Command/TranslationUpdateCommand.php | 2 +- .../Tests/Command/RouterDebugCommandTest.php | 2 +- .../Tests/Command/RouterMatchCommandTest.php | 4 +- .../Command/TranslationDebugCommandTest.php | 2 +- .../Command/TranslationUpdateCommandTest.php | 2 +- .../Functional/CachePoolClearCommandTest.php | 2 +- .../Bundle/SecurityBundle/CHANGELOG.md | 5 ++ .../SecurityBundle/Command/InitAclCommand.php | 2 +- .../SecurityBundle/Command/SetAclCommand.php | 2 +- 20 files changed, 152 insertions(+), 24 deletions(-) diff --git a/UPGRADE-3.4.md b/UPGRADE-3.4.md index 5a677088acd9f..ea8acec4f5c51 100644 --- a/UPGRADE-3.4.md +++ b/UPGRADE-3.4.md @@ -120,7 +120,52 @@ FrameworkBundle class has been deprecated and will be removed in 4.0. Use the `Symfony\Component\Translation\Reader\TranslationReader` class instead. - * The `translation.loader` service has been deprecated and will be removed in 4.0. Use the `translation.reader` service instead. + * The `translation.loader` service has been deprecated and will be removed in 4.0. + Use the `translation.reader` service instead.. + + * `AssetsInstallCommand::__construct()` now takes an instance of + `Symfony\Component\Filesystem\Filesystem` as first argument. + Not passing it is deprecated and will throw a `TypeError` in 4.0. + + * `CacheClearCommand::__construct()` now takes an instance of + `Symfony\Component\HttpKernel\CacheClearer\CacheClearerInterface` as + first argument. Not passing it is deprecated and will throw + a `TypeError` in 4.0. + + * `CachePoolClearCommand::__construct()` now takes an instance of + `Symfony\Component\HttpKernel\CacheClearer\Psr6CacheClearer` as + first argument. Not passing it is deprecated and will throw + a `TypeError` in 4.0. + + * `EventDispatcherDebugCommand::__construct()` now takes an instance of + `Symfony\Component\EventDispatcher\EventDispatcherInterface` as + first argument. Not passing it is deprecated and will throw + a `TypeError` in 4.0. + + * `RouterDebugCommand::__construct()` now takes an instance of + `Symfony\Component\Routing\RouterInteface` as + first argument. Not passing it is deprecated and will throw + a `TypeError` in 4.0. + + * `RouterMatchCommand::__construct()` now takes an instance of + `Symfony\Component\Routing\RouterInteface` as + first argument. Not passing it is deprecated and will throw + a `TypeError` in 4.0. + + * `TranslationDebugCommand::__construct()` now takes an instance of + `Symfony\Component\Translation\TranslatorInterface` as + first argument. Not passing it is deprecated and will throw + a `TypeError` in 4.0. + + * `TranslationUpdateCommand::__construct()` now takes an instance of + `Symfony\Component\Translation\TranslatorInterface` as + first argument. Not passing it is deprecated and will throw + a `TypeError` in 4.0. + + * `AssetsInstallCommand`, `CacheClearCommand`, `CachePoolClearCommand`, + `EventDispatcherDebugCommand`, `RouterDebugCommand`, `RouterMatchCommand`, + `TranslationDebugCommand`, `TranslationUpdateCommand`, `XliffLintCommand` + and `YamlLintCommand` classes have been marked as final HttpKernel ---------- @@ -168,6 +213,15 @@ SecurityBundle * `FirewallContext::getListeners()` now returns `\Traversable|array` + * `InitAclCommand::__construct()` now takes an instance of + `Doctrine\DBAL\Connection` as first argument. Not passing it is + deprecated and will throw a `TypeError` in 4.0. + + * `SetAclCommand::__construct()` now takes an instance of + `Symfony\Component\Security\Acl\Model\MutableAclProviderInterfaceConnection` + as first argument. Not passing it is deprecated and will throw a `TypeError` + in 4.0. + Translation ----------- diff --git a/UPGRADE-4.0.md b/UPGRADE-4.0.md index 0b9a727a17368..e54f77c228bad 100644 --- a/UPGRADE-4.0.md +++ b/UPGRADE-4.0.md @@ -419,8 +419,40 @@ FrameworkBundle class has been deprecated and will be removed in 4.0. Use the `Symfony\Component\Translation\Reader\TranslationReader` class instead. - * The `translation.loader` service has been deprecated and will be removed in 4.0. Use the `translation.reader` service instead. + * The `translation.loader` service has been removed. + Use the `translation.reader` service instead. + * `AssetsInstallCommand::__construct()` now requires an instance of + `Symfony\Component\Filesystem\Filesystem` as first argument. + + * `CacheClearCommand::__construct()` now requires an instance of + `Symfony\Component\HttpKernel\CacheClearer\CacheClearerInterface` as + first argument. + + * `CachePoolClearCommand::__construct()` now requires an instance of + `Symfony\Component\HttpKernel\CacheClearer\Psr6CacheClearer` as + first argument. + + * `EventDispatcherDebugCommand::__construct()` now requires an instance of + `Symfony\Component\EventDispatcher\EventDispatcherInterface` as + first argument. + + * `RouterDebugCommand::__construct()` now requires an instance of + `Symfony\Component\Routing\RouterInteface` as + first argument. + + * `RouterMatchCommand::__construct()` now requires an instance of + `Symfony\Component\Routing\RouterInteface` as + first argument. + + * `TranslationDebugCommand::__construct()` now requires an instance of + `Symfony\Component\Translation\TranslatorInterface` as + first argument. + + * `TranslationUpdateCommand::__construct()` now requires an instance of + `Symfony\Component\Translation\TranslatorInterface` as + first argument. + HttpFoundation -------------- @@ -568,6 +600,13 @@ SecurityBundle * `UserPasswordEncoderCommand` does not extend `ContainerAwareCommand` nor implement `ContainerAwareInterface` anymore. + * `InitAclCommand::__construct()` now requires an instance of + `Doctrine\DBAL\Connection` as first argument. + + * `SetAclCommand::__construct()` now requires an instance of + `Symfony\Component\Security\Acl\Model\MutableAclProviderInterfaceConnection` + as first argument. + Serializer ---------- @@ -642,11 +681,12 @@ TwigBridge * The `TwigRendererEngine::setEnvironment()` method has been removed. Pass the Twig Environment as second argument of the constructor instead. - * Removed `Symfony\Bridge\Twig\Command\DebugCommand::set/getTwigEnvironment` and the ability - to pass a command name as first argument. + * Removed `DebugCommand::set/getTwigEnvironment`. Pass an instance of + `Twig\Environment` as first argument of the constructor instead. + + * Removed `LintCommand::set/getTwigEnvironment`. Pass an instance of + `Twig\Environment` as first argument of the constructor instead. - * Removed `Symfony\Bridge\Twig\Command\LintCommand::set/getTwigEnvironment` and the ability - to pass a command name as first argument. Validator --------- diff --git a/src/Symfony/Bridge/Twig/CHANGELOG.md b/src/Symfony/Bridge/Twig/CHANGELOG.md index c9cfec886177a..397134150c318 100644 --- a/src/Symfony/Bridge/Twig/CHANGELOG.md +++ b/src/Symfony/Bridge/Twig/CHANGELOG.md @@ -5,8 +5,10 @@ CHANGELOG ----- * deprecated `Symfony\Bridge\Twig\Form\TwigRenderer` - * deprecated `Symfony\Bridge\Twig\Command\DebugCommand::set/getTwigEnvironment` and the ability to pass a command name as first argument - * deprecated `Symfony\Bridge\Twig\Command\LintCommand::set/getTwigEnvironment` and the ability to pass a command name as first argument + * deprecated `DebugCommand::set/getTwigEnvironment`. Pass an instance of + `Twig\Environment` as first argument of the constructor instead + * deprecated `LintCommand::set/getTwigEnvironment`. Pass an instance of + `Twig\Environment` as first argument of the constructor instead 3.3.0 ----- diff --git a/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md b/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md index 4a51222f7e90d..dafd4c46bb0fc 100644 --- a/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md +++ b/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md @@ -26,6 +26,33 @@ CHANGELOG * Deprecated `Symfony\Bundle\FrameworkBundle\Translation\TranslationLoader`, use `Symfony\Component\Translation\Reader\TranslationReader` instead * Deprecated `translation.loader` service, use `translation.reader` instead + * `AssetsInstallCommand::__construct()` now takes an instance of + `Symfony\Component\Filesystem\Filesystem` as first argument + * `CacheClearCommand::__construct()` now takes an instance of + `Symfony\Component\HttpKernel\CacheClearer\CacheClearerInterface` as + first argument + * `CachePoolClearCommand::__construct()` now takes an instance of + `Symfony\Component\HttpKernel\CacheClearer\Psr6CacheClearer` as + first argument + * `EventDispatcherDebugCommand::__construct()` now takes an instance of + `Symfony\Component\EventDispatcher\EventDispatcherInterface` as + first argument + * `RouterDebugCommand::__construct()` now takes an instance of + `Symfony\Component\Routing\RouterInteface` as + first argument + * `RouterMatchCommand::__construct()` now takes an instance of + `Symfony\Component\Routing\RouterInteface` as + first argument + * `TranslationDebugCommand::__construct()` now takes an instance of + `Symfony\Component\Translation\TranslatorInterface` as + first argument + * `TranslationUpdateCommand::__construct()` now takes an instance of + `Symfony\Component\Translation\TranslatorInterface` as + first argument + * `AssetsInstallCommand`, `CacheClearCommand`, `CachePoolClearCommand`, + `EventDispatcherDebugCommand`, `RouterDebugCommand`, `RouterMatchCommand`, + `TranslationDebugCommand`, `TranslationUpdateCommand`, `XliffLintCommand` + and `YamlLintCommand` classes have been marked as final 3.3.0 ----- diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/AssetsInstallCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/AssetsInstallCommand.php index e1adbe9e9325a..1669b3d3addd5 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/AssetsInstallCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/AssetsInstallCommand.php @@ -45,7 +45,7 @@ class AssetsInstallCommand extends ContainerAwareCommand public function __construct($filesystem = null) { if (!$filesystem instanceof Filesystem) { - @trigger_error(sprintf('Passing a command name as the first argument of "%s" is deprecated since version 3.4 and will be removed in 4.0. If the command was registered by convention, make it a service instead.', __METHOD__), E_USER_DEPRECATED); + @trigger_error(sprintf('%s() expects an instance of "%s" as first argument since version 3.4. Not passing it is deprecated and will throw a TypeError in 4.0.', __METHOD__, Filesystem::class), E_USER_DEPRECATED); parent::__construct($filesystem); diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/CacheClearCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/CacheClearCommand.php index 29fa61a5f44af..4080d2a3d2de6 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/CacheClearCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/CacheClearCommand.php @@ -45,7 +45,7 @@ class CacheClearCommand extends ContainerAwareCommand public function __construct($cacheClearer = null, Filesystem $filesystem = null) { if (!$cacheClearer instanceof CacheClearerInterface) { - @trigger_error(sprintf('Passing a command name as the first argument of "%s" is deprecated since version 3.4 and will be removed in 4.0. If the command was registered by convention, make it a service instead.', __METHOD__), E_USER_DEPRECATED); + @trigger_error(sprintf('%s() expects an instance of "%s" as first argument since version 3.4. Not passing it is deprecated and will throw a TypeError in 4.0.', __METHOD__, CacheClearerInterface::class), E_USER_DEPRECATED); parent::__construct($cacheClearer); diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/CachePoolClearCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/CachePoolClearCommand.php index dedd61e668116..04719b75d7fd2 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/CachePoolClearCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/CachePoolClearCommand.php @@ -35,7 +35,7 @@ final class CachePoolClearCommand extends ContainerAwareCommand public function __construct($poolClearer = null) { if (!$poolClearer instanceof Psr6CacheClearer) { - @trigger_error(sprintf('Passing a command name as the first argument of "%s" is deprecated since version 3.4 and will be removed in 4.0. If the command was registered by convention, make it a service instead.', __METHOD__), E_USER_DEPRECATED); + @trigger_error(sprintf('%s() expects an instance of "%s" as first argument since version 3.4. Not passing it is deprecated and will throw a TypeError in 4.0.', __METHOD__, Psr6CacheClearer::class), E_USER_DEPRECATED); parent::__construct($poolClearer); diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/EventDispatcherDebugCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/EventDispatcherDebugCommand.php index a36878d44533c..51f769b21dd3d 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/EventDispatcherDebugCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/EventDispatcherDebugCommand.php @@ -37,7 +37,7 @@ class EventDispatcherDebugCommand extends ContainerAwareCommand public function __construct($dispatcher = null) { if (!$dispatcher instanceof EventDispatcherInterface) { - @trigger_error(sprintf('Passing a command name as the first argument of "%s" is deprecated since version 3.4 and will be removed in 4.0. If the command was registered by convention, make it a service instead.', __METHOD__), E_USER_DEPRECATED); + @trigger_error(sprintf('%s() expects an instance of "%s" as first argument since version 3.4. Not passing it is deprecated and will throw a TypeError in 4.0.', __METHOD__, EventDispatcherInterface::class), E_USER_DEPRECATED); parent::__construct($dispatcher); diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/RouterDebugCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/RouterDebugCommand.php index 03b227a731ce7..929264139a172 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/RouterDebugCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/RouterDebugCommand.php @@ -41,7 +41,7 @@ class RouterDebugCommand extends ContainerAwareCommand public function __construct($router = null) { if (!$router instanceof RouterInterface) { - @trigger_error(sprintf('Passing a command name as the first argument of "%s" is deprecated since version 3.4 and will be removed in 4.0. If the command was registered by convention, make it a service instead.', __METHOD__), E_USER_DEPRECATED); + @trigger_error(sprintf('%s() expects an instance of "%s" as first argument since version 3.4. Not passing it is deprecated and will throw a TypeError in 4.0.', __METHOD__, RouterInterface::class), E_USER_DEPRECATED); parent::__construct($router); diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/RouterMatchCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/RouterMatchCommand.php index ee5c4990a487b..1e2720669fd67 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/RouterMatchCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/RouterMatchCommand.php @@ -39,7 +39,7 @@ class RouterMatchCommand extends ContainerAwareCommand public function __construct($router = null) { if (!$router instanceof RouterInterface) { - @trigger_error(sprintf('Passing a command name as the first argument of "%s" is deprecated since version 3.4 and will be removed in 4.0. If the command was registered by convention, make it a service instead.', __METHOD__), E_USER_DEPRECATED); + @trigger_error(sprintf('%s() expects an instance of "%s" as first argument since version 3.4. Not passing it is deprecated and will throw a TypeError in 4.0.', __METHOD__, RouterInterface::class), E_USER_DEPRECATED); parent::__construct($router); diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/TranslationDebugCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/TranslationDebugCommand.php index e4e16960fc577..d80e2f4de9e69 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/TranslationDebugCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/TranslationDebugCommand.php @@ -54,7 +54,7 @@ class TranslationDebugCommand extends ContainerAwareCommand public function __construct($translator = null, TranslationReaderInterface $reader = null, ExtractorInterface $extractor = null) { if (!$translator instanceof TranslatorInterface) { - @trigger_error(sprintf('Passing a command name as the first argument of "%s" is deprecated since version 3.4 and will be removed in 4.0. If the command was registered by convention, make it a service instead.', __METHOD__), E_USER_DEPRECATED); + @trigger_error(sprintf('%s() expects an instance of "%s" as first argument since version 3.4. Not passing it is deprecated and will throw a TypeError in 4.0.', __METHOD__, TranslatorInterface::class), E_USER_DEPRECATED); parent::__construct($translator); diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/TranslationUpdateCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/TranslationUpdateCommand.php index ff35fda56e1ef..b2f75db5ca19a 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/TranslationUpdateCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/TranslationUpdateCommand.php @@ -49,7 +49,7 @@ class TranslationUpdateCommand extends ContainerAwareCommand public function __construct($writer = null, TranslationReaderInterface $reader = null, ExtractorInterface $extractor = null, $defaultLocale = null) { if (!$writer instanceof TranslationWriterInterface) { - @trigger_error(sprintf('Passing a command name as the first argument of "%s" is deprecated since version 3.4 and will be removed in 4.0. If the command was registered by convention, make it a service instead.', __METHOD__), E_USER_DEPRECATED); + @trigger_error(sprintf('%s() expects an instance of "%s" as first argument since version 3.4. Not passing it is deprecated and will throw a TypeError in 4.0.', __METHOD__, TranslationWriterInterface::class), E_USER_DEPRECATED); parent::__construct($writer); diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/RouterDebugCommandTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/RouterDebugCommandTest.php index c201fe9db7248..1eaca79a8ba72 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/RouterDebugCommandTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/RouterDebugCommandTest.php @@ -49,7 +49,7 @@ public function testDebugInvalidRoute() /** * @group legacy - * @expectedDeprecation Passing a command name as the first argument of "Symfony\Bundle\FrameworkBundle\Command\RouterDebugCommand::__construct" is deprecated since version 3.4 and will be removed in 4.0. If the command was registered by convention, make it a service instead. + * @expectedDeprecation Symfony\Bundle\FrameworkBundle\Command\RouterDebugCommand::__construct() expects an instance of "Symfony\Component\Routing\RouterInterface" as first argument since version 3.4. Not passing it is deprecated and will throw a TypeError in 4.0. */ public function testLegacyDebugCommand() { diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/RouterMatchCommandTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/RouterMatchCommandTest.php index 2570d41d78745..4a4fe29720c6d 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/RouterMatchCommandTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/RouterMatchCommandTest.php @@ -43,8 +43,8 @@ public function testWithNotMatchPath() /** * @group legacy - * @expectedDeprecation Passing a command name as the first argument of "Symfony\Bundle\FrameworkBundle\Command\RouterMatchCommand::__construct" is deprecated since version 3.4 and will be removed in 4.0. If the command was registered by convention, make it a service instead. - * @expectedDeprecation Passing a command name as the first argument of "Symfony\Bundle\FrameworkBundle\Command\RouterDebugCommand::__construct" is deprecated since version 3.4 and will be removed in 4.0. If the command was registered by convention, make it a service instead. + * @expectedDeprecation Symfony\Bundle\FrameworkBundle\Command\RouterMatchCommand::__construct() expects an instance of "Symfony\Component\Routing\RouterInterface" as first argument since version 3.4. Not passing it is deprecated and will throw a TypeError in 4.0. + * @expectedDeprecation Symfony\Bundle\FrameworkBundle\Command\RouterDebugCommand::__construct() expects an instance of "Symfony\Component\Routing\RouterInterface" as first argument since version 3.4. Not passing it is deprecated and will throw a TypeError in 4.0. */ public function testLegacyMatchCommand() { diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/TranslationDebugCommandTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/TranslationDebugCommandTest.php index ff7cab4589b02..55ed4c7449f27 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/TranslationDebugCommandTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/TranslationDebugCommandTest.php @@ -176,7 +176,7 @@ private function createCommandTester($extractedMessages = array(), $loadedMessag /** * @group legacy - * @expectedDeprecation Passing a command name as the first argument of "Symfony\Bundle\FrameworkBundle\Command\TranslationDebugCommand::__construct" is deprecated since version 3.4 and will be removed in 4.0. If the command was registered by convention, make it a service instead. + * @expectedDeprecation Symfony\Bundle\FrameworkBundle\Command\TranslationDebugCommand::__construct() expects an instance of "Symfony\Component\Translation\TranslatorInterface" as first argument since version 3.4. Not passing it is deprecated and will throw a TypeError in 4.0. */ public function testLegacyDebugCommand() { diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/TranslationUpdateCommandTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/TranslationUpdateCommandTest.php index b0804503eb79f..c7c93d533a301 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/TranslationUpdateCommandTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/TranslationUpdateCommandTest.php @@ -155,7 +155,7 @@ private function createCommandTester($extractedMessages = array(), $loadedMessag /** * @group legacy - * @expectedDeprecation Passing a command name as the first argument of "Symfony\Bundle\FrameworkBundle\Command\TranslationUpdateCommand::__construct" is deprecated since version 3.4 and will be removed in 4.0. If the command was registered by convention, make it a service instead. + * @expectedDeprecation Symfony\Bundle\FrameworkBundle\Command\TranslationUpdateCommand::__construct() expects an instance of "Symfony\Component\Translation\Writer\TranslationWriterInterface" as first argument since version 3.4. Not passing it is deprecated and will throw a TypeError in 4.0. */ public function testLegacyUpdateCommand() { diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/CachePoolClearCommandTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/CachePoolClearCommandTest.php index 9a2d198a72ba2..a9a5959848e67 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/CachePoolClearCommandTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/CachePoolClearCommandTest.php @@ -77,7 +77,7 @@ public function testClearUnexistingPool() /** * @group legacy - * @expectedDeprecation Passing a command name as the first argument of "Symfony\Bundle\FrameworkBundle\Command\CachePoolClearCommand::__construct" is deprecated since version 3.4 and will be removed in 4.0. If the command was registered by convention, make it a service instead. + * @expectedDeprecation Symfony\Bundle\FrameworkBundle\Command\CachePoolClearCommand::__construct() expects an instance of "Symfony\Component\HttpKernel\CacheClearer\Psr6CacheClearer" as first argument since version 3.4. Not passing it is deprecated and will throw a TypeError in 4.0. */ public function testLegacyClearCommand() { diff --git a/src/Symfony/Bundle/SecurityBundle/CHANGELOG.md b/src/Symfony/Bundle/SecurityBundle/CHANGELOG.md index 8690a0a13968d..0c62ce6e2aa9e 100644 --- a/src/Symfony/Bundle/SecurityBundle/CHANGELOG.md +++ b/src/Symfony/Bundle/SecurityBundle/CHANGELOG.md @@ -8,6 +8,11 @@ CHANGELOG `VoterInterface` on the class is now deprecated and will be removed in 4.0. * [BC BREAK] `FirewallContext::getListeners()` now returns `\Traversable|array` * added info about called security listeners in profiler + * `InitAclCommand::__construct()` now takes an instance of + `Doctrine\DBAL\Connection` as first argument + * `SetAclCommand::__construct()` now takes an instance of + `Symfony\Component\Security\Acl\Model\MutableAclProviderInterfaceConnection` + as first argument 3.3.0 ----- diff --git a/src/Symfony/Bundle/SecurityBundle/Command/InitAclCommand.php b/src/Symfony/Bundle/SecurityBundle/Command/InitAclCommand.php index c8ccac32cab5b..72e62c3f48d10 100644 --- a/src/Symfony/Bundle/SecurityBundle/Command/InitAclCommand.php +++ b/src/Symfony/Bundle/SecurityBundle/Command/InitAclCommand.php @@ -39,7 +39,7 @@ class InitAclCommand extends ContainerAwareCommand public function __construct($connection = null, Schema $schema = null) { if (!$connection instanceof Connection) { - @trigger_error(sprintf('Passing a command name as the first argument of "%s" is deprecated since version 3.4 and will be removed in 4.0. If the command was registered by convention, make it a service instead.', __METHOD__), E_USER_DEPRECATED); + @trigger_error(sprintf('%s() expects an instance of "%s" as first argument since version 3.4. Not passing it is deprecated and will throw a TypeError in 4.0.', __METHOD__, Connection::class), E_USER_DEPRECATED); parent::__construct($connection); diff --git a/src/Symfony/Bundle/SecurityBundle/Command/SetAclCommand.php b/src/Symfony/Bundle/SecurityBundle/Command/SetAclCommand.php index bdb293a4ec6fd..0955129f072d2 100644 --- a/src/Symfony/Bundle/SecurityBundle/Command/SetAclCommand.php +++ b/src/Symfony/Bundle/SecurityBundle/Command/SetAclCommand.php @@ -42,7 +42,7 @@ class SetAclCommand extends ContainerAwareCommand public function __construct($provider = null) { if (!$provider instanceof MutableAclProviderInterface) { - @trigger_error(sprintf('Passing a command name as the first argument of "%s" is deprecated since version 3.4 and will be removed in 4.0. If the command was registered by convention, make it a service instead.', __METHOD__), E_USER_DEPRECATED); + @trigger_error(sprintf('%s() expects an instance of "%s" as first argument since version 3.4. Not passing it is deprecated and will throw a TypeError in 4.0.', __METHOD__, MutableAclProviderInterface::class), E_USER_DEPRECATED); parent::__construct($provider); From 76ea6dfd3398ed64c2bee9e382ec1299482f027e Mon Sep 17 00:00:00 2001 From: Roland Franssen Date: Fri, 1 Sep 2017 20:06:13 +0200 Subject: [PATCH 0749/1099] [HttpKernel] Deprecate EnvParametersResource --- UPGRADE-3.4.md | 2 ++ UPGRADE-4.0.md | 2 ++ src/Symfony/Component/HttpKernel/CHANGELOG.md | 1 + .../Component/HttpKernel/Config/EnvParametersResource.php | 2 ++ .../HttpKernel/Tests/Config/EnvParametersResourceTest.php | 3 +++ 5 files changed, 10 insertions(+) diff --git a/UPGRADE-3.4.md b/UPGRADE-3.4.md index 5a677088acd9f..70cc26f976e1c 100644 --- a/UPGRADE-3.4.md +++ b/UPGRADE-3.4.md @@ -154,6 +154,8 @@ HttpKernel * The `getCacheDir()` method of your kernel should not be called while building the container. Use the `%kernel.cache_dir%` parameter instead. Not doing so may break the `cache:clear` command. + * The `Symfony\Component\HttpKernel\Config\EnvParametersResource` class has been deprecated and will be removed in 4.0. + Process ------- diff --git a/UPGRADE-4.0.md b/UPGRADE-4.0.md index 0b9a727a17368..6b061a582db77 100644 --- a/UPGRADE-4.0.md +++ b/UPGRADE-4.0.md @@ -519,6 +519,8 @@ HttpKernel * The `getCacheDir()` method of your kernel should not be called while building the container. Use the `%kernel.cache_dir%` parameter instead. Not doing so may break the `cache:clear` command. + * The `Symfony\Component\HttpKernel\Config\EnvParametersResource` class has been removed. + Ldap ---- diff --git a/src/Symfony/Component/HttpKernel/CHANGELOG.md b/src/Symfony/Component/HttpKernel/CHANGELOG.md index be467b407b00c..4a4c81dac096a 100644 --- a/src/Symfony/Component/HttpKernel/CHANGELOG.md +++ b/src/Symfony/Component/HttpKernel/CHANGELOG.md @@ -8,6 +8,7 @@ CHANGELOG * deprecated commands auto registration * added `AddCacheClearerPass` * added `AddCacheWarmerPass` + * deprecated `EnvParametersResource` 3.3.0 ----- diff --git a/src/Symfony/Component/HttpKernel/Config/EnvParametersResource.php b/src/Symfony/Component/HttpKernel/Config/EnvParametersResource.php index 0fe6aca8c1d8d..0f48869c6375c 100644 --- a/src/Symfony/Component/HttpKernel/Config/EnvParametersResource.php +++ b/src/Symfony/Component/HttpKernel/Config/EnvParametersResource.php @@ -17,6 +17,8 @@ * EnvParametersResource represents resources stored in prefixed environment variables. * * @author Chris Wilkinson + * + * @deprecated since version 3.4, to be removed in 4.0 */ class EnvParametersResource implements SelfCheckingResourceInterface, \Serializable { diff --git a/src/Symfony/Component/HttpKernel/Tests/Config/EnvParametersResourceTest.php b/src/Symfony/Component/HttpKernel/Tests/Config/EnvParametersResourceTest.php index 6fe8a6756899d..986e05d8b888a 100644 --- a/src/Symfony/Component/HttpKernel/Tests/Config/EnvParametersResourceTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/Config/EnvParametersResourceTest.php @@ -14,6 +14,9 @@ use PHPUnit\Framework\TestCase; use Symfony\Component\HttpKernel\Config\EnvParametersResource; +/** + * @group legacy + */ class EnvParametersResourceTest extends TestCase { protected $prefix = '__DUMMY_'; From 484d278f50e740c72224db7af94c7342be382331 Mon Sep 17 00:00:00 2001 From: Arnaud Date: Thu, 26 Jan 2017 11:39:46 +0100 Subject: [PATCH 0750/1099] [Console] Display file and line on Exception --- src/Symfony/Component/Console/Application.php | 27 +++++++++---------- .../Fixtures/application_renderexception1.txt | 8 +++--- .../Fixtures/application_renderexception2.txt | 8 +++--- .../Fixtures/application_renderexception3.txt | 6 ++--- .../application_renderexception3decorated.txt | 6 ++--- .../Fixtures/application_renderexception4.txt | 10 +++---- ...plication_renderexception_doublewidth1.txt | 2 +- ..._renderexception_doublewidth1decorated.txt | 2 +- ...plication_renderexception_doublewidth2.txt | 2 +- ...plication_renderexception_escapeslines.txt | 2 +- 10 files changed, 35 insertions(+), 38 deletions(-) diff --git a/src/Symfony/Component/Console/Application.php b/src/Symfony/Component/Console/Application.php index c1731843e6eb2..41c2a238e08a1 100644 --- a/src/Symfony/Component/Console/Application.php +++ b/src/Symfony/Component/Console/Application.php @@ -736,13 +736,13 @@ public function renderException(\Exception $e, OutputInterface $output) protected function doRenderException(\Exception $e, OutputInterface $output) { do { - $title = sprintf( - ' [%s%s] ', - get_class($e), - $output->isVerbose() && 0 !== ($code = $e->getCode()) ? ' ('.$code.')' : '' - ); - - $len = Helper::strlen($title); + $message = $e->getMessage(); + if ('' === $message || OutputInterface::VERBOSITY_VERBOSE <= $output->getVerbosity()) { + $title = sprintf(' [%s%s] ', get_class($e), 0 !== ($code = $e->getCode()) ? ' ('.$code.')' : ''); + $len = Helper::strlen($title); + } else { + $len = 0; + } $width = $this->terminal->getWidth() ? $this->terminal->getWidth() - 1 : PHP_INT_MAX; // HHVM only accepts 32 bits integer in str_split, even when PHP_INT_MAX is a 64 bit integer: https://github.com/facebook/hhvm/issues/1327 @@ -750,7 +750,7 @@ protected function doRenderException(\Exception $e, OutputInterface $output) $width = 1 << 31; } $lines = array(); - foreach (preg_split('/\r?\n/', $e->getMessage()) as $line) { + foreach ('' !== $message ? preg_split('/\r?\n/', $message) : array() as $line) { foreach ($this->splitStringByWidth($line, $width - 4) as $line) { // pre-format lines to get the right string length $lineLength = Helper::strlen($line) + 4; @@ -761,8 +761,11 @@ protected function doRenderException(\Exception $e, OutputInterface $output) } $messages = array(); + $messages[] = sprintf('%s', OutputFormatter::escape(sprintf('In %s line %s:', basename($e->getFile()) ?: 'n/a', $e->getLine() ?: 'n/a'))); $messages[] = $emptyLine = sprintf('%s', str_repeat(' ', $len)); - $messages[] = sprintf('%s%s', $title, str_repeat(' ', max(0, $len - Helper::strlen($title)))); + if ('' === $message || OutputInterface::VERBOSITY_VERBOSE <= $output->getVerbosity()) { + $messages[] = sprintf('%s%s', $title, str_repeat(' ', max(0, $len - Helper::strlen($title)))); + } foreach ($lines as $line) { $messages[] = sprintf(' %s %s', OutputFormatter::escape($line[0]), str_repeat(' ', $len - $line[1])); } @@ -776,12 +779,6 @@ protected function doRenderException(\Exception $e, OutputInterface $output) // exception related properties $trace = $e->getTrace(); - array_unshift($trace, array( - 'function' => '', - 'file' => $e->getFile() !== null ? $e->getFile() : 'n/a', - 'line' => $e->getLine() !== null ? $e->getLine() : 'n/a', - 'args' => array(), - )); for ($i = 0, $count = count($trace); $i < $count; ++$i) { $class = isset($trace[$i]['class']) ? $trace[$i]['class'] : ''; diff --git a/src/Symfony/Component/Console/Tests/Fixtures/application_renderexception1.txt b/src/Symfony/Component/Console/Tests/Fixtures/application_renderexception1.txt index 919cec4214a97..700ffada3d2fa 100644 --- a/src/Symfony/Component/Console/Tests/Fixtures/application_renderexception1.txt +++ b/src/Symfony/Component/Console/Tests/Fixtures/application_renderexception1.txt @@ -1,6 +1,6 @@ - - [Symfony\Component\Console\Exception\CommandNotFoundException] - Command "foo" is not defined. - +In Application.php line 615: + + Command "foo" is not defined. + diff --git a/src/Symfony/Component/Console/Tests/Fixtures/application_renderexception2.txt b/src/Symfony/Component/Console/Tests/Fixtures/application_renderexception2.txt index 64561715e04fb..9d0cacb81aedc 100644 --- a/src/Symfony/Component/Console/Tests/Fixtures/application_renderexception2.txt +++ b/src/Symfony/Component/Console/Tests/Fixtures/application_renderexception2.txt @@ -1,8 +1,8 @@ - - [Symfony\Component\Console\Exception\InvalidOptionException] - The "--foo" option does not exist. - +In ArrayInput.php line 172: + + The "--foo" option does not exist. + list [--raw] [--format FORMAT] [--] [] diff --git a/src/Symfony/Component/Console/Tests/Fixtures/application_renderexception3.txt b/src/Symfony/Component/Console/Tests/Fixtures/application_renderexception3.txt index f41925f52a6ea..5366b84f82304 100644 --- a/src/Symfony/Component/Console/Tests/Fixtures/application_renderexception3.txt +++ b/src/Symfony/Component/Console/Tests/Fixtures/application_renderexception3.txt @@ -1,16 +1,16 @@ +In Foo3Command.php line 26: - [Exception] Third exception comment +In Foo3Command.php line 23: - [Exception] Second exception comment +In Foo3Command.php line 21: - [Exception] First exception

this is html

diff --git a/src/Symfony/Component/Console/Tests/Fixtures/application_renderexception3decorated.txt b/src/Symfony/Component/Console/Tests/Fixtures/application_renderexception3decorated.txt index 5adccdd70245f..59937092e78da 100644 --- a/src/Symfony/Component/Console/Tests/Fixtures/application_renderexception3decorated.txt +++ b/src/Symfony/Component/Console/Tests/Fixtures/application_renderexception3decorated.txt @@ -1,16 +1,16 @@ +In Foo3Command.php line 26:   - [Exception]   Third exception comment    +In Foo3Command.php line 23:   - [Exception]   Second exception comment    +In Foo3Command.php line 21:   - [Exception]   First exception

this is html

   diff --git a/src/Symfony/Component/Console/Tests/Fixtures/application_renderexception4.txt b/src/Symfony/Component/Console/Tests/Fixtures/application_renderexception4.txt index cb080e9cb53b8..040564447f57b 100644 --- a/src/Symfony/Component/Console/Tests/Fixtures/application_renderexception4.txt +++ b/src/Symfony/Component/Console/Tests/Fixtures/application_renderexception4.txt @@ -1,7 +1,7 @@ - - [Symfony\Component\Console\Exception\CommandNotFoundException] - Command "foo" is not define - d. - +In Application.php line 615: + + Command "foo" is not define + d. + diff --git a/src/Symfony/Component/Console/Tests/Fixtures/application_renderexception_doublewidth1.txt b/src/Symfony/Component/Console/Tests/Fixtures/application_renderexception_doublewidth1.txt index 1ba5f8fdd914d..01986c917b545 100644 --- a/src/Symfony/Component/Console/Tests/Fixtures/application_renderexception_doublewidth1.txt +++ b/src/Symfony/Component/Console/Tests/Fixtures/application_renderexception_doublewidth1.txt @@ -1,6 +1,6 @@ +In ApplicationTest.php line 716: - [Exception] エラーメッセージ diff --git a/src/Symfony/Component/Console/Tests/Fixtures/application_renderexception_doublewidth1decorated.txt b/src/Symfony/Component/Console/Tests/Fixtures/application_renderexception_doublewidth1decorated.txt index 20644251c2f9b..ba057d8cc77ff 100644 --- a/src/Symfony/Component/Console/Tests/Fixtures/application_renderexception_doublewidth1decorated.txt +++ b/src/Symfony/Component/Console/Tests/Fixtures/application_renderexception_doublewidth1decorated.txt @@ -1,6 +1,6 @@ +In ApplicationTest.php line 716:   - [Exception]   エラーメッセージ    diff --git a/src/Symfony/Component/Console/Tests/Fixtures/application_renderexception_doublewidth2.txt b/src/Symfony/Component/Console/Tests/Fixtures/application_renderexception_doublewidth2.txt index e41fcfcf675af..66b52c879a66a 100644 --- a/src/Symfony/Component/Console/Tests/Fixtures/application_renderexception_doublewidth2.txt +++ b/src/Symfony/Component/Console/Tests/Fixtures/application_renderexception_doublewidth2.txt @@ -1,6 +1,6 @@ +In ApplicationTest.php line 730: - [Exception] コマンドの実行中にエラーが 発生しました。 diff --git a/src/Symfony/Component/Console/Tests/Fixtures/application_renderexception_escapeslines.txt b/src/Symfony/Component/Console/Tests/Fixtures/application_renderexception_escapeslines.txt index cf79b37a92d6e..326ee42f6d741 100644 --- a/src/Symfony/Component/Console/Tests/Fixtures/application_renderexception_escapeslines.txt +++ b/src/Symfony/Component/Console/Tests/Fixtures/application_renderexception_escapeslines.txt @@ -1,6 +1,6 @@ +In ApplicationTest.php line 744: - [Exception] dont break here < info>! From 263b95e1d1b071d6660d11732844313db80374e7 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Sun, 3 Sep 2017 20:01:57 +0200 Subject: [PATCH 0751/1099] [DI] Minor fix in dumped code --- .../Component/DependencyInjection/Dumper/PhpDumper.php | 8 ++------ .../DependencyInjection/Tests/Fixtures/php/services9.php | 8 ++++---- 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php index 6e2230ea6cb14..ef56da6bdcebd 100644 --- a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php +++ b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php @@ -1579,13 +1579,9 @@ private function getServiceCall($id, Reference $reference = null) $code = sprintf('$this->get(\'%s\')', $id); } - if ($this->container->hasDefinition($id) && $this->container->getDefinition($id)->isShared()) { - // The following is PHP 5.5 syntax for what could be written as "(\$this->services['$id'] ?? $code)" on PHP>=7.0 + // The following is PHP 5.5 syntax for what could be written as "(\$this->services['$id'] ?? $code)" on PHP>=7.0 - $code = "\${(\$_ = isset(\$this->services['$id']) ? \$this->services['$id'] : $code) && false ?: '_'}"; - } - - return $code; + return "\${(\$_ = isset(\$this->services['$id']) ? \$this->services['$id'] : $code) && false ?: '_'}"; } /** diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9.php index 4998b60f4c719..77cc57604c770 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9.php @@ -280,7 +280,7 @@ protected function getLazyContextIgnoreInvalidRefService() return $this->services['lazy_context_ignore_invalid_ref'] = new \LazyContext(new RewindableGenerator(function () { yield 0 => ${($_ = isset($this->services['foo.baz']) ? $this->services['foo.baz'] : $this->get('foo.baz')) && false ?: '_'}; if ($this->has('invalid')) { - yield 1 => $this->get('invalid', ContainerInterface::NULL_ON_INVALID_REFERENCE); + yield 1 => ${($_ = isset($this->services['invalid']) ? $this->services['invalid'] : $this->get('invalid', ContainerInterface::NULL_ON_INVALID_REFERENCE)) && false ?: '_'}; } }, function () { return 1 + (int) ($this->has('invalid')); @@ -301,12 +301,12 @@ protected function getMethodCall1Service() $this->services['method_call1'] = $instance = new \Bar\FooClass(); $instance->setBar(${($_ = isset($this->services['foo']) ? $this->services['foo'] : $this->get('foo')) && false ?: '_'}); - $instance->setBar($this->get('foo2', ContainerInterface::NULL_ON_INVALID_REFERENCE)); + $instance->setBar(${($_ = isset($this->services['foo2']) ? $this->services['foo2'] : $this->get('foo2', ContainerInterface::NULL_ON_INVALID_REFERENCE)) && false ?: '_'}); if ($this->has('foo3')) { - $instance->setBar($this->get('foo3', ContainerInterface::NULL_ON_INVALID_REFERENCE)); + $instance->setBar(${($_ = isset($this->services['foo3']) ? $this->services['foo3'] : $this->get('foo3', ContainerInterface::NULL_ON_INVALID_REFERENCE)) && false ?: '_'}); } if ($this->has('foobaz')) { - $instance->setBar($this->get('foobaz', ContainerInterface::NULL_ON_INVALID_REFERENCE)); + $instance->setBar(${($_ = isset($this->services['foobaz']) ? $this->services['foobaz'] : $this->get('foobaz', ContainerInterface::NULL_ON_INVALID_REFERENCE)) && false ?: '_'}); } $instance->setBar((${($_ = isset($this->services['foo']) ? $this->services['foo'] : $this->get('foo')) && false ?: '_'}->foo() . (($this->hasParameter("foo")) ? ($this->getParameter("foo")) : ("default")))); From fc918693768405d211f2244446a613d0598a58c2 Mon Sep 17 00:00:00 2001 From: Robin Chalas Date: Sun, 3 Sep 2017 21:27:51 +0200 Subject: [PATCH 0752/1099] Fix ability to deprecate a config node --- .../Definition/Builder/ArrayNodeDefinition.php | 1 + .../Component/Config/Definition/VariableNode.php | 4 ++++ .../Config/Tests/Definition/ArrayNodeTest.php | 9 +++++++++ .../Definition/Builder/ArrayNodeDefinitionTest.php | 14 ++++++++++++++ .../Builder/BooleanNodeDefinitionTest.php | 11 +++++++++++ .../Definition/Builder/EnumNodeDefinitionTest.php | 12 ++++++++++++ .../Config/Tests/Definition/ScalarNodeTest.php | 9 +++++++++ 7 files changed, 60 insertions(+) diff --git a/src/Symfony/Component/Config/Definition/Builder/ArrayNodeDefinition.php b/src/Symfony/Component/Config/Definition/Builder/ArrayNodeDefinition.php index cac53044a9a10..7e345aa89fff5 100644 --- a/src/Symfony/Component/Config/Definition/Builder/ArrayNodeDefinition.php +++ b/src/Symfony/Component/Config/Definition/Builder/ArrayNodeDefinition.php @@ -453,6 +453,7 @@ protected function createNode() $node->addEquivalentValue(false, $this->falseEquivalent); $node->setPerformDeepMerging($this->performDeepMerging); $node->setRequired($this->required); + $node->setDeprecated($this->deprecationMessage); $node->setIgnoreExtraKeys($this->ignoreExtraKeys, $this->removeExtraKeys); $node->setNormalizeKeys($this->normalizeKeys); diff --git a/src/Symfony/Component/Config/Definition/VariableNode.php b/src/Symfony/Component/Config/Definition/VariableNode.php index a9c35284cdcdb..f37ced901b553 100644 --- a/src/Symfony/Component/Config/Definition/VariableNode.php +++ b/src/Symfony/Component/Config/Definition/VariableNode.php @@ -84,6 +84,10 @@ protected function validateType($value) */ protected function finalizeValue($value) { + if ($this->deprecationMessage) { + @trigger_error($this->getDeprecationMessage($this->getName(), $this->getPath()), E_USER_DEPRECATED); + } + if (!$this->allowEmptyValue && $this->isValueEmpty($value)) { $ex = new InvalidConfigurationException(sprintf( 'The path "%s" cannot contain an empty value, but got %s.', diff --git a/src/Symfony/Component/Config/Tests/Definition/ArrayNodeTest.php b/src/Symfony/Component/Config/Tests/Definition/ArrayNodeTest.php index 0b5565e0b379b..7a5bf30373acd 100644 --- a/src/Symfony/Component/Config/Tests/Definition/ArrayNodeTest.php +++ b/src/Symfony/Component/Config/Tests/Definition/ArrayNodeTest.php @@ -216,4 +216,13 @@ public function testGetDefaultValueWithoutDefaultValue() $node = new ArrayNode('foo'); $node->getDefaultValue(); } + + public function testSetDeprecated() + { + $node = new ArrayNode('foo'); + $node->setDeprecated('"%node%" is deprecated'); + + $this->assertTrue($node->isDeprecated()); + $this->assertSame('"foo" is deprecated', $node->getDeprecationMessage($node->getName(), $node->getPath())); + } } diff --git a/src/Symfony/Component/Config/Tests/Definition/Builder/ArrayNodeDefinitionTest.php b/src/Symfony/Component/Config/Tests/Definition/Builder/ArrayNodeDefinitionTest.php index 4c2a397cff6df..e32c093eeb31b 100644 --- a/src/Symfony/Component/Config/Tests/Definition/Builder/ArrayNodeDefinitionTest.php +++ b/src/Symfony/Component/Config/Tests/Definition/Builder/ArrayNodeDefinitionTest.php @@ -298,6 +298,20 @@ public function testRequiresAtLeastOneElement() $this->addToAssertionCount(1); } + public function testSetDeprecated() + { + $node = new ArrayNodeDefinition('root'); + $node + ->children() + ->arrayNode('foo')->setDeprecated('The "%path%" node is deprecated.')->end() + ->end() + ; + $deprecatedNode = $node->getNode()->getChildren()['foo']; + + $this->assertTrue($deprecatedNode->isDeprecated()); + $this->assertSame('The "root.foo" node is deprecated.', $deprecatedNode->getDeprecationMessage($deprecatedNode->getName(), $deprecatedNode->getPath())); + } + /** * @expectedException \Symfony\Component\Config\Definition\Exception\InvalidConfigurationException * @expectedExceptionMessage The path "root" should have at least 1 element(s) defined. diff --git a/src/Symfony/Component/Config/Tests/Definition/Builder/BooleanNodeDefinitionTest.php b/src/Symfony/Component/Config/Tests/Definition/Builder/BooleanNodeDefinitionTest.php index 291dd602d9393..c0d347f3d3191 100644 --- a/src/Symfony/Component/Config/Tests/Definition/Builder/BooleanNodeDefinitionTest.php +++ b/src/Symfony/Component/Config/Tests/Definition/Builder/BooleanNodeDefinitionTest.php @@ -25,4 +25,15 @@ public function testCannotBeEmptyThrowsAnException() $def = new BooleanNodeDefinition('foo'); $def->cannotBeEmpty(); } + + public function testSetDeprecated() + { + $def = new BooleanNodeDefinition('foo'); + $def->setDeprecated('The "%path%" node is deprecated.'); + + $node = $def->getNode(); + + $this->assertTrue($node->isDeprecated()); + $this->assertSame('The "foo" node is deprecated.', $node->getDeprecationMessage($node->getName(), $node->getPath())); + } } diff --git a/src/Symfony/Component/Config/Tests/Definition/Builder/EnumNodeDefinitionTest.php b/src/Symfony/Component/Config/Tests/Definition/Builder/EnumNodeDefinitionTest.php index 0f09b78e7968b..9c0aa0e11cf97 100644 --- a/src/Symfony/Component/Config/Tests/Definition/Builder/EnumNodeDefinitionTest.php +++ b/src/Symfony/Component/Config/Tests/Definition/Builder/EnumNodeDefinitionTest.php @@ -62,4 +62,16 @@ public function testGetNode() $node = $def->getNode(); $this->assertEquals(array('foo', 'bar'), $node->getValues()); } + + public function testSetDeprecated() + { + $def = new EnumNodeDefinition('foo'); + $def->values(array('foo', 'bar')); + $def->setDeprecated('The "%path%" node is deprecated.'); + + $node = $def->getNode(); + + $this->assertTrue($node->isDeprecated()); + $this->assertSame('The "foo" node is deprecated.', $def->getNode()->getDeprecationMessage($node->getName(), $node->getPath())); + } } diff --git a/src/Symfony/Component/Config/Tests/Definition/ScalarNodeTest.php b/src/Symfony/Component/Config/Tests/Definition/ScalarNodeTest.php index a402a61ef951d..1981ac9459aac 100644 --- a/src/Symfony/Component/Config/Tests/Definition/ScalarNodeTest.php +++ b/src/Symfony/Component/Config/Tests/Definition/ScalarNodeTest.php @@ -40,6 +40,15 @@ public function getValidValues() ); } + public function testSetDeprecated() + { + $node = new ScalarNode('foo'); + $node->setDeprecated('"%node%" is deprecated'); + + $this->assertTrue($node->isDeprecated()); + $this->assertSame('"foo" is deprecated', $node->getDeprecationMessage($node->getName(), $node->getPath())); + } + /** * @dataProvider getInvalidValues * @expectedException \Symfony\Component\Config\Definition\Exception\InvalidTypeException From 012e381e16f9d23d2a0a235da2df2cef1b16de26 Mon Sep 17 00:00:00 2001 From: Sanpi Date: Tue, 29 Aug 2017 20:08:05 +0200 Subject: [PATCH 0753/1099] Use new configuration node depreciation method --- .../DependencyInjection/Configuration.php | 10 ++++++---- .../DependencyInjection/FrameworkExtension.php | 4 ---- src/Symfony/Bundle/FrameworkBundle/composer.json | 2 +- 3 files changed, 7 insertions(+), 9 deletions(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php index fcc0e714c8cb6..87685e3241992 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php @@ -66,10 +66,9 @@ public function getConfigTreeBuilder() ->defaultTrue() ->end() ->arrayNode('trusted_proxies') + ->setDeprecated('The "%path%.%node%" configuration key has been deprecated in Symfony 3.3. Use the Request::setTrustedProxies() method in your front controller instead.') ->beforeNormalization() ->ifTrue(function ($v) { - @trigger_error('The "framework.trusted_proxies" configuration key has been deprecated in Symfony 3.3. Use the Request::setTrustedProxies() method in your front controller instead.', E_USER_DEPRECATED); - return !is_array($v) && null !== $v; }) ->then(function ($v) { return is_bool($v) ? array() : preg_split('/\s*,\s*/', $v); }) @@ -663,8 +662,9 @@ private function addValidationSection(ArrayNodeDefinition $rootNode) ->{!class_exists(FullStack::class) && class_exists(Validation::class) ? 'canBeDisabled' : 'canBeEnabled'}() ->children() ->scalarNode('cache') + // Can be removed in 4.0, when validator.mapping.cache.doctrine.apc is removed + ->setDeprecated('The "%path%.%node%" option is deprecated since Symfony 3.2 and will be removed in 4.0. Configure the "cache.validator" service under "framework.cache.pools" instead.') ->beforeNormalization() - // Can be removed in 4.0, when validator.mapping.cache.doctrine.apc is removed ->ifString()->then(function ($v) { if ('validator.mapping.cache.doctrine.apc' === $v && !class_exists('Doctrine\Common\Cache\ApcCache')) { throw new LogicException('Doctrine APC cache for the validator cannot be enabled as the Doctrine Cache package is not installed.'); @@ -727,7 +727,9 @@ private function addSerializerSection(ArrayNodeDefinition $rootNode) ->{!class_exists(FullStack::class) && class_exists(Serializer::class) ? 'canBeDisabled' : 'canBeEnabled'}() ->children() ->booleanNode('enable_annotations')->{!class_exists(FullStack::class) && class_exists(Annotation::class) ? 'defaultTrue' : 'defaultFalse'}()->end() - ->scalarNode('cache')->end() + ->scalarNode('cache') + ->setDeprecated('The "%path%.%node%" option is deprecated since Symfony 3.1 and will be removed in 4.0. Configure the "cache.serializer" service under "framework.cache.pools" instead.') + ->end() ->scalarNode('name_converter')->end() ->scalarNode('circular_reference_handler')->end() ->arrayNode('mapping') diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php index f54b74abb6051..16f13ac79ad51 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php @@ -1198,8 +1198,6 @@ private function registerValidationConfiguration(array $config, ContainerBuilder } if (isset($config['cache']) && $config['cache']) { - @trigger_error('The "framework.validation.cache" option is deprecated since Symfony 3.2 and will be removed in 4.0. Configure the "cache.validator" service under "framework.cache.pools" instead.', E_USER_DEPRECATED); - $container->setParameter( 'validator.mapping.cache.prefix', 'validator_'.$this->getKernelRootHash($container) @@ -1454,8 +1452,6 @@ private function registerSerializerConfiguration(array $config, ContainerBuilder $container->getDefinition('serializer.mapping.cache_warmer')->replaceArgument(0, $serializerLoaders); if (isset($config['cache']) && $config['cache']) { - @trigger_error('The "framework.serializer.cache" option is deprecated since Symfony 3.1 and will be removed in 4.0. Configure the "cache.serializer" service under "framework.cache.pools" instead.', E_USER_DEPRECATED); - $container->setParameter( 'serializer.mapping.cache.prefix', 'serializer_'.$this->getKernelRootHash($container) diff --git a/src/Symfony/Bundle/FrameworkBundle/composer.json b/src/Symfony/Bundle/FrameworkBundle/composer.json index afe1961d95670..3e0354ec625c1 100644 --- a/src/Symfony/Bundle/FrameworkBundle/composer.json +++ b/src/Symfony/Bundle/FrameworkBundle/composer.json @@ -21,7 +21,7 @@ "symfony/cache": "~3.4|~4.0", "symfony/class-loader": "~3.2", "symfony/dependency-injection": "~3.4|~4.0", - "symfony/config": "~3.3|~4.0", + "symfony/config": "~3.4|~4.0", "symfony/event-dispatcher": "^3.3.1|~4.0", "symfony/http-foundation": "~3.3|~4.0", "symfony/http-kernel": "~3.4|~4.0", From 1be23c2a86e98e2f7f45917090c2d7f9e519358c Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Fri, 1 Sep 2017 08:00:27 +0200 Subject: [PATCH 0754/1099] [Yaml] add inline parser context initializer Calling the parser to initialize some internal context does not look like a good idea. Additionally, this change allows to not accept null values in `Inline::parse()` in 3.4 anymore. --- src/Symfony/Component/Yaml/Inline.php | 21 +++++++++++++++++---- src/Symfony/Component/Yaml/Parser.php | 4 +--- 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/src/Symfony/Component/Yaml/Inline.php b/src/Symfony/Component/Yaml/Inline.php index c78c811baa5a7..fee21eb34ecc2 100644 --- a/src/Symfony/Component/Yaml/Inline.php +++ b/src/Symfony/Component/Yaml/Inline.php @@ -33,6 +33,22 @@ class Inline private static $objectForMap = false; private static $constantSupport = false; + /** + * @param int $flags + * @param int|null $parsedLineNumber + */ + public static function initialize($flags, $parsedLineNumber = null) + { + self::$exceptionOnInvalidType = (bool) (Yaml::PARSE_EXCEPTION_ON_INVALID_TYPE & $flags); + self::$objectSupport = (bool) (Yaml::PARSE_OBJECT & $flags); + self::$objectForMap = (bool) (Yaml::PARSE_OBJECT_FOR_MAP & $flags); + self::$constantSupport = (bool) (Yaml::PARSE_CONSTANT & $flags); + + if (null !== $parsedLineNumber) { + self::$parsedLineNumber = $parsedLineNumber; + } + } + /** * Converts a YAML string to a PHP value. * @@ -78,10 +94,7 @@ public static function parse($value, $flags = 0, $references = array()) } } - self::$exceptionOnInvalidType = (bool) (Yaml::PARSE_EXCEPTION_ON_INVALID_TYPE & $flags); - self::$objectSupport = (bool) (Yaml::PARSE_OBJECT & $flags); - self::$objectForMap = (bool) (Yaml::PARSE_OBJECT_FOR_MAP & $flags); - self::$constantSupport = (bool) (Yaml::PARSE_CONSTANT & $flags); + self::initialize($flags); $value = trim($value); diff --git a/src/Symfony/Component/Yaml/Parser.php b/src/Symfony/Component/Yaml/Parser.php index b39512c869d14..042d9d186d273 100644 --- a/src/Symfony/Component/Yaml/Parser.php +++ b/src/Symfony/Component/Yaml/Parser.php @@ -222,10 +222,8 @@ private function doParse($value, $flags) } $context = 'mapping'; - // force correct settings - Inline::parse(null, $flags, $this->refs); + Inline::initialize($flags, $this->getRealCurrentLineNb()); try { - Inline::$parsedLineNumber = $this->getRealCurrentLineNb(); $i = 0; $evaluateKey = !(Yaml::PARSE_KEYS_AS_STRINGS & $flags); From eaa506f562281e4152aea2fbae79e38b1a5c7e82 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Sun, 3 Sep 2017 12:36:19 +0200 Subject: [PATCH 0755/1099] be able to enable workflow support explicitly --- .../DependencyInjection/Configuration.php | 250 ++++++++++-------- .../FrameworkExtension.php | 8 +- .../Resources/config/schema/symfony-1.0.xsd | 9 +- .../DependencyInjection/ConfigurationTest.php | 5 +- .../Fixtures/php/workflows_enabled.php | 5 + .../Fixtures/xml/workflows_enabled.xml | 11 + .../Fixtures/yml/workflows_enabled.yml | 2 + .../FrameworkExtensionTest.php | 10 + 8 files changed, 178 insertions(+), 122 deletions(-) create mode 100644 src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/workflows_enabled.php create mode 100644 src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/workflows_enabled.xml create mode 100644 src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/workflows_enabled.yml diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php index fcc0e714c8cb6..66934aba6a419 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php @@ -247,141 +247,165 @@ private function addWorkflowSection(ArrayNodeDefinition $rootNode) ->fixXmlConfig('workflow') ->children() ->arrayNode('workflows') - ->useAttributeAsKey('name') - ->prototype('array') - ->fixXmlConfig('support') - ->fixXmlConfig('place') - ->fixXmlConfig('transition') - ->children() - ->arrayNode('audit_trail') - ->canBeEnabled() - ->end() - ->enumNode('type') - ->values(array('workflow', 'state_machine')) - ->end() - ->arrayNode('marking_store') - ->fixXmlConfig('argument') + ->canBeEnabled() + ->beforeNormalization() + ->always(function ($v) { + if (true === $v['enabled']) { + $workflows = $v; + unset($workflows['enabled']); + + if (count($workflows) === 1 && isset($workflows[0]['enabled'])) { + $workflows = array(); + } + + $v = array( + 'enabled' => true, + 'workflows' => $workflows, + ); + } + + return $v; + }) + ->end() + ->children() + ->arrayNode('workflows') + ->useAttributeAsKey('name') + ->prototype('array') + ->fixXmlConfig('support') + ->fixXmlConfig('place') + ->fixXmlConfig('transition') ->children() + ->arrayNode('audit_trail') + ->canBeEnabled() + ->end() ->enumNode('type') - ->values(array('multiple_state', 'single_state')) + ->values(array('workflow', 'state_machine')) + ->end() + ->arrayNode('marking_store') + ->fixXmlConfig('argument') + ->children() + ->enumNode('type') + ->values(array('multiple_state', 'single_state')) + ->end() + ->arrayNode('arguments') + ->beforeNormalization() + ->ifString() + ->then(function ($v) { return array($v); }) + ->end() + ->requiresAtLeastOneElement() + ->prototype('scalar') + ->end() + ->end() + ->scalarNode('service') + ->cannotBeEmpty() + ->end() + ->end() + ->validate() + ->ifTrue(function ($v) { return isset($v['type']) && isset($v['service']); }) + ->thenInvalid('"type" and "service" cannot be used together.') + ->end() + ->validate() + ->ifTrue(function ($v) { return !empty($v['arguments']) && isset($v['service']); }) + ->thenInvalid('"arguments" and "service" cannot be used together.') + ->end() ->end() - ->arrayNode('arguments') + ->arrayNode('supports') ->beforeNormalization() ->ifString() ->then(function ($v) { return array($v); }) ->end() - ->requiresAtLeastOneElement() ->prototype('scalar') + ->cannotBeEmpty() + ->validate() + ->ifTrue(function ($v) { return !class_exists($v); }) + ->thenInvalid('The supported class %s does not exist.') + ->end() ->end() ->end() - ->scalarNode('service') + ->scalarNode('support_strategy') ->cannotBeEmpty() ->end() - ->end() - ->validate() - ->ifTrue(function ($v) { return isset($v['type']) && isset($v['service']); }) - ->thenInvalid('"type" and "service" cannot be used together.') - ->end() - ->validate() - ->ifTrue(function ($v) { return !empty($v['arguments']) && isset($v['service']); }) - ->thenInvalid('"arguments" and "service" cannot be used together.') - ->end() - ->end() - ->arrayNode('supports') - ->beforeNormalization() - ->ifString() - ->then(function ($v) { return array($v); }) - ->end() - ->prototype('scalar') - ->cannotBeEmpty() - ->validate() - ->ifTrue(function ($v) { return !class_exists($v); }) - ->thenInvalid('The supported class %s does not exist.') + ->scalarNode('initial_place') + ->defaultNull() ->end() - ->end() - ->end() - ->scalarNode('support_strategy') - ->cannotBeEmpty() - ->end() - ->scalarNode('initial_place') - ->defaultNull() - ->end() - ->arrayNode('places') - ->isRequired() - ->requiresAtLeastOneElement() - ->prototype('scalar') - ->cannotBeEmpty() - ->end() - ->end() - ->arrayNode('transitions') - ->beforeNormalization() - ->always() - ->then(function ($transitions) { - // It's an indexed array, we let the validation occurs - if (isset($transitions[0])) { - return $transitions; - } - - foreach ($transitions as $name => $transition) { - if (array_key_exists('name', $transition)) { - continue; - } - $transition['name'] = $name; - $transitions[$name] = $transition; - } - - return $transitions; - }) - ->end() - ->isRequired() - ->requiresAtLeastOneElement() - ->prototype('array') - ->children() - ->scalarNode('name') - ->isRequired() - ->cannotBeEmpty() - ->end() - ->scalarNode('guard') + ->arrayNode('places') + ->isRequired() + ->requiresAtLeastOneElement() + ->prototype('scalar') ->cannotBeEmpty() - ->info('An expression to block the transition') - ->example('is_fully_authenticated() and has_role(\'ROLE_JOURNALIST\') and subject.getTitle() == \'My first article\'') ->end() - ->arrayNode('from') - ->beforeNormalization() - ->ifString() - ->then(function ($v) { return array($v); }) - ->end() - ->requiresAtLeastOneElement() - ->prototype('scalar') - ->cannotBeEmpty() - ->end() + ->end() + ->arrayNode('transitions') + ->beforeNormalization() + ->always() + ->then(function ($transitions) { + // It's an indexed array, we let the validation occurs + if (isset($transitions[0])) { + return $transitions; + } + + foreach ($transitions as $name => $transition) { + if (array_key_exists('name', $transition)) { + continue; + } + $transition['name'] = $name; + $transitions[$name] = $transition; + } + + return $transitions; + }) ->end() - ->arrayNode('to') - ->beforeNormalization() - ->ifString() - ->then(function ($v) { return array($v); }) - ->end() - ->requiresAtLeastOneElement() - ->prototype('scalar') - ->cannotBeEmpty() + ->isRequired() + ->requiresAtLeastOneElement() + ->prototype('array') + ->children() + ->scalarNode('name') + ->isRequired() + ->cannotBeEmpty() + ->end() + ->scalarNode('guard') + ->cannotBeEmpty() + ->info('An expression to block the transition') + ->example('is_fully_authenticated() and has_role(\'ROLE_JOURNALIST\') and subject.getTitle() == \'My first article\'') + ->end() + ->arrayNode('from') + ->beforeNormalization() + ->ifString() + ->then(function ($v) { return array($v); }) + ->end() + ->requiresAtLeastOneElement() + ->prototype('scalar') + ->cannotBeEmpty() + ->end() + ->end() + ->arrayNode('to') + ->beforeNormalization() + ->ifString() + ->then(function ($v) { return array($v); }) + ->end() + ->requiresAtLeastOneElement() + ->prototype('scalar') + ->cannotBeEmpty() + ->end() + ->end() ->end() ->end() ->end() ->end() + ->validate() + ->ifTrue(function ($v) { + return $v['supports'] && isset($v['support_strategy']); + }) + ->thenInvalid('"supports" and "support_strategy" cannot be used together.') + ->end() + ->validate() + ->ifTrue(function ($v) { + return !$v['supports'] && !isset($v['support_strategy']); + }) + ->thenInvalid('"supports" or "support_strategy" should be configured.') + ->end() ->end() ->end() - ->validate() - ->ifTrue(function ($v) { - return $v['supports'] && isset($v['support_strategy']); - }) - ->thenInvalid('"supports" and "support_strategy" cannot be used together.') - ->end() - ->validate() - ->ifTrue(function ($v) { - return !$v['supports'] && !isset($v['support_strategy']); - }) - ->thenInvalid('"supports" or "support_strategy" should be configured.') - ->end() ->end() ->end() ->end() diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php index f54b74abb6051..2d382712911ef 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php @@ -530,13 +530,13 @@ private function registerProfilerConfiguration(array $config, ContainerBuilder $ /** * Loads the workflow configuration. * - * @param array $workflows A workflow configuration array + * @param array $config A workflow configuration array * @param ContainerBuilder $container A ContainerBuilder instance * @param XmlFileLoader $loader An XmlFileLoader instance */ - private function registerWorkflowConfiguration(array $workflows, ContainerBuilder $container, XmlFileLoader $loader) + private function registerWorkflowConfiguration(array $config, ContainerBuilder $container, XmlFileLoader $loader) { - if (!$workflows) { + if (!$config['enabled']) { if (!class_exists(Workflow\Workflow::class)) { $container->removeDefinition(WorkflowDumpCommand::class); } @@ -552,7 +552,7 @@ private function registerWorkflowConfiguration(array $workflows, ContainerBuilde $registryDefinition = $container->getDefinition('workflow.registry'); - foreach ($workflows as $name => $workflow) { + foreach ($config['workflows'] as $name => $workflow) { if (!array_key_exists('type', $workflow)) { $workflow['type'] = 'workflow'; @trigger_error(sprintf('The "type" option of the "framework.workflows.%s" configuration entry must be defined since Symfony 3.3. The default value will be "state_machine" in Symfony 4.0.', $name), E_USER_DEPRECATED); 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 d6138133cf2ea..481c469e36164 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 @@ -254,15 +254,16 @@ - + - - + + - + + diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/ConfigurationTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/ConfigurationTest.php index 0d2578db040af..1835625da8611 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/ConfigurationTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/ConfigurationTest.php @@ -331,7 +331,10 @@ protected static function getBundleDefaultConfig() 'default_redis_provider' => 'redis://localhost', 'default_memcached_provider' => 'memcached://localhost', ), - 'workflows' => array(), + 'workflows' => array( + 'enabled' => false, + 'workflows' => array(), + ), 'php_errors' => array( 'log' => true, 'throw' => true, diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/workflows_enabled.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/workflows_enabled.php new file mode 100644 index 0000000000000..9a2fe9136a4b3 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/php/workflows_enabled.php @@ -0,0 +1,5 @@ +loadFromExtension('framework', array( + 'workflows' => null, +)); diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/workflows_enabled.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/workflows_enabled.xml new file mode 100644 index 0000000000000..51da644be1f9e --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/workflows_enabled.xml @@ -0,0 +1,11 @@ + + + + + + + diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/workflows_enabled.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/workflows_enabled.yml new file mode 100644 index 0000000000000..2a716ff0a1b14 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/workflows_enabled.yml @@ -0,0 +1,2 @@ +framework: + workflows: ~ diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php index d63a74c874f02..991eda1ea6ac6 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php @@ -12,6 +12,7 @@ namespace Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection; use Doctrine\Common\Annotations\Annotation; +use Symfony\Bundle\FrameworkBundle\Command\WorkflowDumpCommand; use Symfony\Bundle\FullStack; use Symfony\Bundle\FrameworkBundle\Tests\TestCase; use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\AddAnnotationsCachedReaderPass; @@ -42,6 +43,7 @@ use Symfony\Component\Serializer\Normalizer\JsonSerializableNormalizer; use Symfony\Component\Translation\DependencyInjection\TranslatorPass; use Symfony\Component\Validator\DependencyInjection\AddConstraintValidatorsPass; +use Symfony\Component\Workflow\Registry; abstract class FrameworkExtensionTest extends TestCase { @@ -307,6 +309,14 @@ public function testWorkflowMultipleTransitionsWithSameName() $this->assertSame(array('draft'), $transitions[4]->getArgument(1)); } + public function testWorkflowServicesCanBeEnabled() + { + $container = $this->createContainerFromFile('workflows_enabled'); + + $this->assertTrue($container->has(Registry::class)); + $this->assertTrue($container->hasDefinition(WorkflowDumpCommand::class)); + } + public function testRouter() { $container = $this->createContainerFromFile('full'); From 5c030dd2404bb6bd1c245745f99d95a77a9efa93 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Mon, 4 Sep 2017 16:58:03 +0200 Subject: [PATCH 0756/1099] sync upgrade file for Symfony 4.0 between branches --- UPGRADE-4.0.md | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/UPGRADE-4.0.md b/UPGRADE-4.0.md index 0b9a727a17368..3697f0dbf87ad 100644 --- a/UPGRADE-4.0.md +++ b/UPGRADE-4.0.md @@ -146,7 +146,7 @@ DependencyInjection ``` - * Service identifiers are now case sensitive. + * Service identifiers and parameter names are now case sensitive. * The `Reference` and `Alias` classes do not make service identifiers lowercase anymore. @@ -391,6 +391,9 @@ FrameworkBundle fully-qualified class name of your Kernel or override the `KernelTestCase::createKernel()` or `KernelTestCase::getKernelClass()` method instead. + * The methods `KernelTestCase::getPhpUnitXmlDir()` and `KernelTestCase::getPhpUnitCliConfigArgument()` + have been removed. + * The `Symfony\Bundle\FrameworkBundle\Validator\ConstraintValidatorFactory` class has been removed. Use `Symfony\Component\Validator\ContainerConstraintValidatorFactory` instead. @@ -541,6 +544,8 @@ Process * Extending `Process::run()`, `Process::mustRun()` and `Process::restart()` is not supported anymore. + * The `getEnhanceWindowsCompatibility()` and `setEnhanceWindowsCompatibility()` methods of the `Process` class have been removed. + ProxyManager ------------ @@ -557,6 +562,8 @@ Security * The `AccessDecisionManager::setVoters()` method has been removed. Pass the voters to the constructor instead. + * Support for defining voters that don't implement the `VoterInterface` has been removed. + SecurityBundle -------------- @@ -683,6 +690,21 @@ Validator } ``` + * Setting the `checkDNS` option of the `Url` constraint to `true` is dropped + in favor of `Url::CHECK_DNS_TYPE_*` constants values. + + Before: + + ```php + $constraint = new Url(['checkDNS' => true]); + ``` + + After: + + ```php + $constraint = new Url(['checkDNS' => Url::CHECK_DNS_TYPE_ANY]); + ``` + VarDumper --------- @@ -716,6 +738,12 @@ VarDumper VarDumperTestTrait::assertDumpMatchesFormat($dump, $data, $filter = 0, $message = ''); ``` +WebProfilerBundle +----------------- + + * Removed the `getTemplates()` method of the `TemplateManager` class in favor + of the `getNames()` method + Workflow -------- From 479b5d639a307552b1e4eb40e7e765e9c8acf789 Mon Sep 17 00:00:00 2001 From: Dany Maillard Date: Tue, 29 Aug 2017 22:11:03 +0200 Subject: [PATCH 0757/1099] Improve microseconds support in date caster --- .../Component/VarDumper/Caster/DateCaster.php | 15 ++- .../VarDumper/Tests/Caster/DateCasterTest.php | 112 ++++++++++-------- 2 files changed, 71 insertions(+), 56 deletions(-) diff --git a/src/Symfony/Component/VarDumper/Caster/DateCaster.php b/src/Symfony/Component/VarDumper/Caster/DateCaster.php index 0b6f551e0b57b..db62b7586da3e 100644 --- a/src/Symfony/Component/VarDumper/Caster/DateCaster.php +++ b/src/Symfony/Component/VarDumper/Caster/DateCaster.php @@ -32,7 +32,7 @@ public static function castDateTime(\DateTimeInterface $d, array $a, Stub $stub, ; $a = array(); - $a[$prefix.'date'] = new ConstStub($d->format('Y-m-d H:i:'.self::formatSeconds($d->format('s'), $d->format('u')).($location ? ' e (P)' : ' P')), $title); + $a[$prefix.'date'] = new ConstStub(self::formatDateTime($d, $location ? ' e (P)' : ' P'), $title); $stub->class .= $d->format(' @U'); @@ -62,7 +62,7 @@ private static function formatInterval(\DateInterval $i) } if (\PHP_VERSION_ID >= 70100 && isset($i->f)) { - $format .= $i->h || $i->i || $i->s || $i->f ? '%H:%I:'.self::formatSeconds($i->s, $i->f) : ''; + $format .= $i->h || $i->i || $i->s || $i->f ? '%H:%I:'.self::formatSeconds($i->s, substr($i->f, 2)) : ''; } else { $format .= $i->h || $i->i || $i->s ? '%H:%I:%S' : ''; } @@ -100,16 +100,16 @@ public static function castPeriod(\DatePeriod $p, array $a, Stub $stub, $isNeste ); break; } - $dates[] = sprintf('%s) %s', $i + 1, $d->format('Y-m-d H:i:s')); + $dates[] = sprintf('%s) %s', $i + 1, self::formatDateTime($d)); } } $period = sprintf( 'every %s, from %s (%s) %s', self::formatInterval($p->getDateInterval()), - $p->getStartDate()->format('Y-m-d H:i:s'), + self::formatDateTime($p->getStartDate()), $p->include_start_date ? 'included' : 'excluded', - ($end = $p->getEndDate()) ? 'to '.$end->format('Y-m-d H:i:s') : 'recurring '.$p->recurrences.' time/s' + ($end = $p->getEndDate()) ? 'to '.self::formatDateTime($end) : 'recurring '.$p->recurrences.' time/s' ); $p = array(Caster::PREFIX_VIRTUAL.'period' => new ConstStub($period, implode("\n", $dates))); @@ -117,6 +117,11 @@ public static function castPeriod(\DatePeriod $p, array $a, Stub $stub, $isNeste return $filter & Caster::EXCLUDE_VERBOSE ? $p : $p + $a; } + private static function formatDateTime(\DateTimeInterface $d, $extra = '') + { + return $d->format('Y-m-d H:i:'.self::formatSeconds($d->format('s'), $d->format('u')).$extra); + } + private static function formatSeconds($s, $us) { return sprintf('%02d.%s', $s, 0 === ($len = strlen($t = rtrim($us, '0'))) ? '0' : ($len <= 3 ? str_pad($t, 3, '0') : $us)); diff --git a/src/Symfony/Component/VarDumper/Tests/Caster/DateCasterTest.php b/src/Symfony/Component/VarDumper/Tests/Caster/DateCasterTest.php index 2acea527f0dc4..8df1765a378cb 100644 --- a/src/Symfony/Component/VarDumper/Tests/Caster/DateCasterTest.php +++ b/src/Symfony/Component/VarDumper/Tests/Caster/DateCasterTest.php @@ -100,10 +100,9 @@ public function provideDateTimes() /** * @dataProvider provideIntervals */ - public function testDumpInterval($intervalSpec, $invert, $expected) + public function testDumpInterval($intervalSpec, $ms, $invert, $expected) { - $interval = new \DateInterval($intervalSpec); - $interval->invert = $invert; + $interval = $this->createInterval($intervalSpec, $ms, $invert); $xDump = <<invert = $invert; + $interval = $this->createInterval($intervalSpec, $ms, $invert); $xDump = <<invert = $invert; + $interval = $this->createInterval($intervalSpec, $ms, $invert); $stub = new Stub(); $cast = DateCaster::castInterval($interval, array('foo' => 'bar'), $stub, false, Caster::EXCLUDE_VERBOSE); @@ -167,40 +164,42 @@ public function testCastInterval($intervalSpec, $invert, $xInterval, $xSeconds) } EODUMP; - $this->assertDumpEquals($xDump, $cast["\0~\0interval"]); + $this->assertDumpMatchesFormat($xDump, $cast["\0~\0interval"]); } public function provideIntervals() { $i = new \DateInterval('PT0S'); - $ms = \PHP_VERSION_ID >= 70100 && isset($i->f) ? '.0' : ''; + $ms = ($withMs = \PHP_VERSION_ID >= 70100 && isset($i->f)) ? '.0' : ''; return array( - array('PT0S', 0, '0s', '0s'), - array('PT1S', 0, '+ 00:00:01'.$ms, '1s'), - array('PT2M', 0, '+ 00:02:00'.$ms, '120s'), - array('PT3H', 0, '+ 03:00:00'.$ms, '10 800s'), - array('P4D', 0, '+ 4d', '345 600s'), - array('P5M', 0, '+ 5m', null), - array('P6Y', 0, '+ 6y', null), - array('P1Y2M3DT4H5M6S', 0, '+ 1y 2m 3d 04:05:06'.$ms, null), - array('PT1M60S', 0, '+ 00:02:00'.$ms, null), - array('PT1H60M', 0, '+ 02:00:00'.$ms, null), - array('P1DT24H', 0, '+ 2d', null), - array('P1M32D', 0, '+ 1m 32d', null), - - array('PT0S', 1, '0s', '0s'), - array('PT1S', 1, '- 00:00:01'.$ms, '-1s'), - array('PT2M', 1, '- 00:02:00'.$ms, '-120s'), - array('PT3H', 1, '- 03:00:00'.$ms, '-10 800s'), - array('P4D', 1, '- 4d', '-345 600s'), - array('P5M', 1, '- 5m', null), - array('P6Y', 1, '- 6y', null), - array('P1Y2M3DT4H5M6S', 1, '- 1y 2m 3d 04:05:06'.$ms, null), - array('PT1M60S', 1, '- 00:02:00'.$ms, null), - array('PT1H60M', 1, '- 02:00:00'.$ms, null), - array('P1DT24H', 1, '- 2d', null), - array('P1M32D', 1, '- 1m 32d', null), + array('PT0S', 0, 0, '0s', '0s'), + array('PT0S', 0.1, 0, $withMs ? '+ 00:00:00.100' : '0s', '%is'), + array('PT1S', 0, 0, '+ 00:00:01'.$ms, '1s'), + array('PT2M', 0, 0, '+ 00:02:00'.$ms, '120s'), + array('PT3H', 0, 0, '+ 03:00:00'.$ms, '10 800s'), + array('P4D', 0, 0, '+ 4d', '345 600s'), + array('P5M', 0, 0, '+ 5m', null), + array('P6Y', 0, 0, '+ 6y', null), + array('P1Y2M3DT4H5M6S', 0, 0, '+ 1y 2m 3d 04:05:06'.$ms, null), + array('PT1M60S', 0, 0, '+ 00:02:00'.$ms, null), + array('PT1H60M', 0, 0, '+ 02:00:00'.$ms, null), + array('P1DT24H', 0, 0, '+ 2d', null), + array('P1M32D', 0, 0, '+ 1m 32d', null), + + array('PT0S', 0, 1, '0s', '0s'), + array('PT0S', 0.1, 1, $withMs ? '- 00:00:00.100' : '0s', '%is'), + array('PT1S', 0, 1, '- 00:00:01'.$ms, '-1s'), + array('PT2M', 0, 1, '- 00:02:00'.$ms, '-120s'), + array('PT3H', 0, 1, '- 03:00:00'.$ms, '-10 800s'), + array('P4D', 0, 1, '- 4d', '-345 600s'), + array('P5M', 0, 1, '- 5m', null), + array('P6Y', 0, 1, '- 6y', null), + array('P1Y2M3DT4H5M6S', 0, 1, '- 1y 2m 3d 04:05:06'.$ms, null), + array('PT1M60S', 0, 1, '- 00:02:00'.$ms, null), + array('PT1H60M', 0, 1, '- 02:00:00'.$ms, null), + array('P1DT24H', 0, 1, '- 2d', null), + array('P1M32D', 0, 1, '- 1m 32d', null), ); } @@ -349,7 +348,7 @@ public function testCastPeriod($start, $interval, $end, $options, $xPeriod, $xDa ] EODUMP; - $this->assertDumpMatchesFormat($xDump, $cast); + $this->assertDumpEquals($xDump, $cast); $xDump = <<= 70100 && isset($i->f) ? '.0' : ''; $periods = array( - array('2017-01-01', 'P1D', '2017-01-03', 0, 'every + 1d, from 2017-01-01 00:00:00 (included) to 2017-01-03 00:00:00', '1) 2017-01-01%a2) 2017-01-02'), - array('2017-01-01', 'P1D', 1, 0, 'every + 1d, from 2017-01-01 00:00:00 (included) recurring 2 time/s', '1) 2017-01-01%a2) 2017-01-02'), + array('2017-01-01', 'P1D', '2017-01-03', 0, 'every + 1d, from 2017-01-01 00:00:00.0 (included) to 2017-01-03 00:00:00.0', '1) 2017-01-01%a2) 2017-01-02'), + array('2017-01-01', 'P1D', 1, 0, 'every + 1d, from 2017-01-01 00:00:00.0 (included) recurring 2 time/s', '1) 2017-01-01%a2) 2017-01-02'), - array('2017-01-01', 'P1D', '2017-01-04', 0, 'every + 1d, from 2017-01-01 00:00:00 (included) to 2017-01-04 00:00:00', '1) 2017-01-01%a2) 2017-01-02%a3) 2017-01-03'), - array('2017-01-01', 'P1D', 2, 0, 'every + 1d, from 2017-01-01 00:00:00 (included) recurring 3 time/s', '1) 2017-01-01%a2) 2017-01-02%a3) 2017-01-03'), + array('2017-01-01', 'P1D', '2017-01-04', 0, 'every + 1d, from 2017-01-01 00:00:00.0 (included) to 2017-01-04 00:00:00.0', '1) 2017-01-01%a2) 2017-01-02%a3) 2017-01-03'), + array('2017-01-01', 'P1D', 2, 0, 'every + 1d, from 2017-01-01 00:00:00.0 (included) recurring 3 time/s', '1) 2017-01-01%a2) 2017-01-02%a3) 2017-01-03'), - array('2017-01-01', 'P1D', '2017-01-05', 0, 'every + 1d, from 2017-01-01 00:00:00 (included) to 2017-01-05 00:00:00', '1) 2017-01-01%a2) 2017-01-02%a1 more'), - array('2017-01-01', 'P1D', 3, 0, 'every + 1d, from 2017-01-01 00:00:00 (included) recurring 4 time/s', '1) 2017-01-01%a2) 2017-01-02%a3) 2017-01-03%a1 more'), + array('2017-01-01', 'P1D', '2017-01-05', 0, 'every + 1d, from 2017-01-01 00:00:00.0 (included) to 2017-01-05 00:00:00.0', '1) 2017-01-01%a2) 2017-01-02%a1 more'), + array('2017-01-01', 'P1D', 3, 0, 'every + 1d, from 2017-01-01 00:00:00.0 (included) recurring 4 time/s', '1) 2017-01-01%a2) 2017-01-02%a3) 2017-01-03%a1 more'), - array('2017-01-01', 'P1D', '2017-01-21', 0, 'every + 1d, from 2017-01-01 00:00:00 (included) to 2017-01-21 00:00:00', '1) 2017-01-01%a17 more'), - array('2017-01-01', 'P1D', 19, 0, 'every + 1d, from 2017-01-01 00:00:00 (included) recurring 20 time/s', '1) 2017-01-01%a17 more'), + array('2017-01-01', 'P1D', '2017-01-21', 0, 'every + 1d, from 2017-01-01 00:00:00.0 (included) to 2017-01-21 00:00:00.0', '1) 2017-01-01%a17 more'), + array('2017-01-01', 'P1D', 19, 0, 'every + 1d, from 2017-01-01 00:00:00.0 (included) recurring 20 time/s', '1) 2017-01-01%a17 more'), - array('2017-01-01 01:00:00', 'P1D', '2017-01-03 01:00:00', 0, 'every + 1d, from 2017-01-01 01:00:00 (included) to 2017-01-03 01:00:00', '1) 2017-01-01 01:00:00%a2) 2017-01-02 01:00:00'), - array('2017-01-01 01:00:00', 'P1D', 1, 0, 'every + 1d, from 2017-01-01 01:00:00 (included) recurring 2 time/s', '1) 2017-01-01 01:00:00%a2) 2017-01-02 01:00:00'), + array('2017-01-01 01:00:00', 'P1D', '2017-01-03 01:00:00', 0, 'every + 1d, from 2017-01-01 01:00:00.0 (included) to 2017-01-03 01:00:00.0', '1) 2017-01-01 01:00:00.0%a2) 2017-01-02 01:00:00.0'), + array('2017-01-01 01:00:00', 'P1D', 1, 0, 'every + 1d, from 2017-01-01 01:00:00.0 (included) recurring 2 time/s', '1) 2017-01-01 01:00:00.0%a2) 2017-01-02 01:00:00.0'), - array('2017-01-01', 'P1DT1H', '2017-01-03', 0, "every + 1d 01:00:00$ms, from 2017-01-01 00:00:00 (included) to 2017-01-03 00:00:00", '1) 2017-01-01 00:00:00%a2) 2017-01-02 01:00:00'), - array('2017-01-01', 'P1DT1H', 1, 0, "every + 1d 01:00:00$ms, from 2017-01-01 00:00:00 (included) recurring 2 time/s", '1) 2017-01-01 00:00:00%a2) 2017-01-02 01:00:00'), + array('2017-01-01', 'P1DT1H', '2017-01-03', 0, "every + 1d 01:00:00$ms, from 2017-01-01 00:00:00.0 (included) to 2017-01-03 00:00:00.0", '1) 2017-01-01 00:00:00.0%a2) 2017-01-02 01:00:00.0'), + array('2017-01-01', 'P1DT1H', 1, 0, "every + 1d 01:00:00$ms, from 2017-01-01 00:00:00.0 (included) recurring 2 time/s", '1) 2017-01-01 00:00:00.0%a2) 2017-01-02 01:00:00.0'), - array('2017-01-01', 'P1D', '2017-01-04', \DatePeriod::EXCLUDE_START_DATE, 'every + 1d, from 2017-01-01 00:00:00 (excluded) to 2017-01-04 00:00:00', '1) 2017-01-02%a2) 2017-01-03'), - array('2017-01-01', 'P1D', 2, \DatePeriod::EXCLUDE_START_DATE, 'every + 1d, from 2017-01-01 00:00:00 (excluded) recurring 2 time/s', '1) 2017-01-02%a2) 2017-01-03'), + array('2017-01-01', 'P1D', '2017-01-04', \DatePeriod::EXCLUDE_START_DATE, 'every + 1d, from 2017-01-01 00:00:00.0 (excluded) to 2017-01-04 00:00:00.0', '1) 2017-01-02%a2) 2017-01-03'), + array('2017-01-01', 'P1D', 2, \DatePeriod::EXCLUDE_START_DATE, 'every + 1d, from 2017-01-01 00:00:00.0 (excluded) recurring 2 time/s', '1) 2017-01-02%a2) 2017-01-03'), ); if (\PHP_VERSION_ID < 70107) { @@ -401,4 +400,15 @@ public function providePeriods() return $periods; } + + private function createInterval($intervalSpec, $ms, $invert) + { + $interval = new \DateInterval($intervalSpec); + if (\PHP_VERSION_ID >= 70100 && isset($interval->f)) { + $interval->f = $ms; + } + $interval->invert = $invert; + + return $interval; + } } From 4a62cc6668b7cbdeecf9064ace5b79d84fcc1379 Mon Sep 17 00:00:00 2001 From: Robin Chalas Date: Mon, 4 Sep 2017 15:08:32 +0200 Subject: [PATCH 0758/1099] Do not trigger deprecation if node has not been explicitly filled --- .../Component/Config/Definition/ArrayNode.php | 8 ++--- .../Config/Definition/VariableNode.php | 4 --- .../Config/Tests/Definition/ArrayNodeTest.php | 31 ++++++++++++++++--- .../Tests/Definition/ScalarNodeTest.php | 31 ++++++++++++++++--- 4 files changed, 58 insertions(+), 16 deletions(-) diff --git a/src/Symfony/Component/Config/Definition/ArrayNode.php b/src/Symfony/Component/Config/Definition/ArrayNode.php index 2ffa2a2137fa8..ef068c9f34f78 100644 --- a/src/Symfony/Component/Config/Definition/ArrayNode.php +++ b/src/Symfony/Component/Config/Definition/ArrayNode.php @@ -234,10 +234,6 @@ protected function finalizeValue($value) } foreach ($this->children as $name => $child) { - if ($child->isDeprecated()) { - @trigger_error($child->getDeprecationMessage($name, $this->getPath()), E_USER_DEPRECATED); - } - if (!array_key_exists($name, $value)) { if ($child->isRequired()) { $msg = sprintf('The child node "%s" at path "%s" must be configured.', $name, $this->getPath()); @@ -254,6 +250,10 @@ protected function finalizeValue($value) continue; } + if ($child->isDeprecated()) { + @trigger_error($child->getDeprecationMessage($name, $this->getPath()), E_USER_DEPRECATED); + } + try { $value[$name] = $child->finalize($value[$name]); } catch (UnsetKeyException $e) { diff --git a/src/Symfony/Component/Config/Definition/VariableNode.php b/src/Symfony/Component/Config/Definition/VariableNode.php index f37ced901b553..a9c35284cdcdb 100644 --- a/src/Symfony/Component/Config/Definition/VariableNode.php +++ b/src/Symfony/Component/Config/Definition/VariableNode.php @@ -84,10 +84,6 @@ protected function validateType($value) */ protected function finalizeValue($value) { - if ($this->deprecationMessage) { - @trigger_error($this->getDeprecationMessage($this->getName(), $this->getPath()), E_USER_DEPRECATED); - } - if (!$this->allowEmptyValue && $this->isValueEmpty($value)) { $ex = new InvalidConfigurationException(sprintf( 'The path "%s" cannot contain an empty value, but got %s.', diff --git a/src/Symfony/Component/Config/Tests/Definition/ArrayNodeTest.php b/src/Symfony/Component/Config/Tests/Definition/ArrayNodeTest.php index 7a5bf30373acd..58d2939300f71 100644 --- a/src/Symfony/Component/Config/Tests/Definition/ArrayNodeTest.php +++ b/src/Symfony/Component/Config/Tests/Definition/ArrayNodeTest.php @@ -219,10 +219,33 @@ public function testGetDefaultValueWithoutDefaultValue() public function testSetDeprecated() { - $node = new ArrayNode('foo'); - $node->setDeprecated('"%node%" is deprecated'); + $childNode = new ArrayNode('foo'); + $childNode->setDeprecated('"%node%" is deprecated'); + + $this->assertTrue($childNode->isDeprecated()); + $this->assertSame('"foo" is deprecated', $childNode->getDeprecationMessage($childNode->getName(), $childNode->getPath())); + + $node = new ArrayNode('root'); + $node->addChild($childNode); + + $deprecationTriggered = false; + $deprecationHandler = function ($level, $message, $file, $line) use (&$prevErrorHandler, &$deprecationTriggered) { + if (E_USER_DEPRECATED === $level) { + return $deprecationTriggered = true; + } + + return $prevErrorHandler ? $prevErrorHandler($level, $message, $file, $line) : false; + }; + + $prevErrorHandler = set_error_handler($deprecationHandler); + $node->finalize(array()); + restore_error_handler(); + + $this->assertFalse($deprecationTriggered, '->finalize() should not trigger if the deprecated node is not set'); - $this->assertTrue($node->isDeprecated()); - $this->assertSame('"foo" is deprecated', $node->getDeprecationMessage($node->getName(), $node->getPath())); + $prevErrorHandler = set_error_handler($deprecationHandler); + $node->finalize(array('foo' => array())); + restore_error_handler(); + $this->assertTrue($deprecationTriggered, '->finalize() should trigger if the deprecated node is set'); } } diff --git a/src/Symfony/Component/Config/Tests/Definition/ScalarNodeTest.php b/src/Symfony/Component/Config/Tests/Definition/ScalarNodeTest.php index 1981ac9459aac..481ef3f4969cf 100644 --- a/src/Symfony/Component/Config/Tests/Definition/ScalarNodeTest.php +++ b/src/Symfony/Component/Config/Tests/Definition/ScalarNodeTest.php @@ -12,6 +12,7 @@ namespace Symfony\Component\Config\Tests\Definition; use PHPUnit\Framework\TestCase; +use Symfony\Component\Config\Definition\ArrayNode; use Symfony\Component\Config\Definition\ScalarNode; class ScalarNodeTest extends TestCase @@ -42,11 +43,33 @@ public function getValidValues() public function testSetDeprecated() { - $node = new ScalarNode('foo'); - $node->setDeprecated('"%node%" is deprecated'); + $childNode = new ScalarNode('foo'); + $childNode->setDeprecated('"%node%" is deprecated'); - $this->assertTrue($node->isDeprecated()); - $this->assertSame('"foo" is deprecated', $node->getDeprecationMessage($node->getName(), $node->getPath())); + $this->assertTrue($childNode->isDeprecated()); + $this->assertSame('"foo" is deprecated', $childNode->getDeprecationMessage($childNode->getName(), $childNode->getPath())); + + $node = new ArrayNode('root'); + $node->addChild($childNode); + + $deprecationTriggered = 0; + $deprecationHandler = function ($level, $message, $file, $line) use (&$prevErrorHandler, &$deprecationTriggered) { + if (E_USER_DEPRECATED === $level) { + return ++$deprecationTriggered; + } + + return $prevErrorHandler ? $prevErrorHandler($level, $message, $file, $line) : false; + }; + + $prevErrorHandler = set_error_handler($deprecationHandler); + $node->finalize(array()); + restore_error_handler(); + $this->assertSame(0, $deprecationTriggered, '->finalize() should not trigger if the deprecated node is not set'); + + $prevErrorHandler = set_error_handler($deprecationHandler); + $node->finalize(array('foo' => '')); + restore_error_handler(); + $this->assertSame(1, $deprecationTriggered, '->finalize() should trigger if the deprecated node is set'); } /** From 2a7f86f85b62799794e8d4ada3246672fefe10c0 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Wed, 26 Jul 2017 09:41:52 +0200 Subject: [PATCH 0759/1099] [3.4][DI] Inline trivial services --- .../DependencyInjection/Dumper/PhpDumper.php | 57 +++++++++++++++++-- .../Tests/Fixtures/containers/container9.php | 1 + .../Tests/Fixtures/php/services9.php | 30 +++++----- .../Tests/Fixtures/php/services9_as_files.txt | 17 +++++- .../Tests/Fixtures/php/services9_compiled.php | 44 +++++++++----- .../Tests/Fixtures/php/services_locator.php | 16 +++--- .../Fixtures/php/services_private_frozen.php | 4 +- .../php/services_private_in_expression.php | 2 +- .../Fixtures/php/services_subscriber.php | 8 +-- .../php/services_uninitialized_ref.php | 8 +-- .../Tests/Fixtures/xml/services9.xml | 1 + .../Tests/Fixtures/yaml/services9.yml | 1 + 12 files changed, 139 insertions(+), 50 deletions(-) diff --git a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php index 5bd1c2a20ce70..add4e7c616f57 100644 --- a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php +++ b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php @@ -475,6 +475,50 @@ private function isSimpleInstance($id, Definition $definition) return true; } + /** + * Checks if the definition is a trivial instance. + * + * @param Definition $definition + * + * @return bool + */ + private function isTrivialInstance(Definition $definition) + { + if ($definition->isSynthetic() || $definition->getFile() || $definition->getMethodCalls() || $definition->getProperties() || $definition->getConfigurator()) { + return false; + } + if ($definition->isDeprecated() || $definition->isLazy() || $definition->getFactory() || 3 < count($definition->getArguments())) { + return false; + } + + foreach ($definition->getArguments() as $arg) { + if (!$arg || ($arg instanceof Reference && 'service_container' !== (string) $arg)) { + continue; + } + if (is_array($arg) && 3 >= count($arg)) { + foreach ($arg as $k => $v) { + if ($this->dumpValue($k) !== $this->dumpValue($k, false)) { + return false; + } + if (!$v || ($v instanceof Reference && 'service_container' !== (string) $v)) { + continue; + } + if (!is_scalar($v) || $this->dumpValue($v) !== $this->dumpValue($v, false)) { + return false; + } + } + } elseif (!is_scalar($arg) || $this->dumpValue($arg) !== $this->dumpValue($arg, false)) { + return false; + } + } + + if (false !== strpos($this->dumpLiteralClass($this->dumpValue($definition->getClass())), '$')) { + return false; + } + + return true; + } + /** * Adds method calls to a service definition. * @@ -1669,14 +1713,19 @@ private function getServiceCall($id, Reference $reference = null) if (null !== $reference && ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE === $reference->getInvalidBehavior()) { $code = 'null'; - } elseif ($this->asFiles && $this->container->hasDefinition($id)) { - if ($this->container->getDefinition($id)->isShared()) { + } elseif ($this->container->hasDefinition($id)) { + $definition = $this->container->getDefinition($id); + + if ($this->isTrivialInstance($definition)) { + $code = substr($this->addNewInstance($definition, '', '', $id), 8, -2); + if ($definition->isShared()) { + $code = sprintf('$this->services[\'%s\'] = %s', $id, $code); + } + } elseif ($this->asFiles && $definition->isShared()) { $code = sprintf("\$this->load(__DIR__.'/%s.php')", $this->generateMethodName($id)); } else { $code = sprintf('$this->%s()', $this->generateMethodName($id)); } - } elseif ($this->container->hasDefinition($id) && !$this->container->getDefinition($id)->isPublic()) { - $code = sprintf('$this->%s()', $this->generateMethodName($id)); } elseif (null !== $reference && ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE !== $reference->getInvalidBehavior()) { $code = sprintf('$this->get(\'%s\', ContainerInterface::NULL_ON_INVALID_REFERENCE)', $id); } else { diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container9.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container9.php index 6445e0f427e06..2906004828a59 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container9.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container9.php @@ -126,6 +126,7 @@ $container ->register('factory_simple', 'SimpleFactoryClass') ->addArgument('foo') + ->setDeprecated(true) ->setPublic(false) ; $container diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9.php index b4e3965743a2b..ec7c57a8dfb41 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9.php @@ -79,7 +79,7 @@ public function __construct() */ protected function getBarService() { - $a = ${($_ = isset($this->services['foo.baz']) ? $this->services['foo.baz'] : $this->get('foo.baz')) && false ?: '_'}; + $a = ${($_ = isset($this->services['foo.baz']) ? $this->services['foo.baz'] : $this->getFoo_BazService()) && false ?: '_'}; $this->services['bar'] = $instance = new \Bar\FooClass('foo', $a, $this->getParameter('foo_bar')); @@ -97,7 +97,7 @@ protected function getBazService() { $this->services['baz'] = $instance = new \Baz(); - $instance->setFoo(${($_ = isset($this->services['foo_with_inline']) ? $this->services['foo_with_inline'] : $this->get('foo_with_inline')) && false ?: '_'}); + $instance->setFoo(${($_ = isset($this->services['foo_with_inline']) ? $this->services['foo_with_inline'] : $this->getFooWithInlineService()) && false ?: '_'}); return $instance; } @@ -125,7 +125,7 @@ protected function getConfiguredServiceSimpleService() { $this->services['configured_service_simple'] = $instance = new \stdClass(); - ${($_ = isset($this->services['configurator_service_simple']) ? $this->services['configurator_service_simple'] : $this->getConfiguratorServiceSimpleService()) && false ?: '_'}->configureStdClass($instance); + ${($_ = isset($this->services['configurator_service_simple']) ? $this->services['configurator_service_simple'] : $this->services['configurator_service_simple'] = new \ConfClass('bar')) && false ?: '_'}->configureStdClass($instance); return $instance; } @@ -181,7 +181,7 @@ protected function getDeprecatedServiceService() */ protected function getFactoryServiceService() { - return $this->services['factory_service'] = ${($_ = isset($this->services['foo.baz']) ? $this->services['foo.baz'] : $this->get('foo.baz')) && false ?: '_'}->getInstance(); + return $this->services['factory_service'] = ${($_ = isset($this->services['foo.baz']) ? $this->services['foo.baz'] : $this->getFoo_BazService()) && false ?: '_'}->getInstance(); } /** @@ -201,14 +201,14 @@ protected function getFactoryServiceSimpleService() */ protected function getFooService() { - $a = ${($_ = isset($this->services['foo.baz']) ? $this->services['foo.baz'] : $this->get('foo.baz')) && false ?: '_'}; + $a = ${($_ = isset($this->services['foo.baz']) ? $this->services['foo.baz'] : $this->getFoo_BazService()) && false ?: '_'}; $this->services['foo'] = $instance = \Bar\FooClass::getInstance('foo', $a, array($this->getParameter('foo') => 'foo is '.$this->getParameter('foo').'', 'foobar' => $this->getParameter('foo')), true, $this); $instance->foo = 'bar'; $instance->moo = $a; $instance->qux = array($this->getParameter('foo') => 'foo is '.$this->getParameter('foo').'', 'foobar' => $this->getParameter('foo')); - $instance->setBar(${($_ = isset($this->services['bar']) ? $this->services['bar'] : $this->get('bar')) && false ?: '_'}); + $instance->setBar(${($_ = isset($this->services['bar']) ? $this->services['bar'] : $this->getBarService()) && false ?: '_'}); $instance->initialize(); sc_configure($instance); @@ -238,7 +238,7 @@ protected function getFooBarService() { $class = $this->getParameter('foo_class'); - return new $class(${($_ = isset($this->services['deprecated_service']) ? $this->services['deprecated_service'] : $this->get('deprecated_service')) && false ?: '_'}); + return new $class(${($_ = isset($this->services['deprecated_service']) ? $this->services['deprecated_service'] : $this->getDeprecatedServiceService()) && false ?: '_'}); } /** @@ -263,7 +263,7 @@ protected function getFooWithInlineService() protected function getLazyContextService() { return $this->services['lazy_context'] = new \LazyContext(new RewindableGenerator(function () { - yield 'k1' => ${($_ = isset($this->services['foo.baz']) ? $this->services['foo.baz'] : $this->get('foo.baz')) && false ?: '_'}; + yield 'k1' => ${($_ = isset($this->services['foo.baz']) ? $this->services['foo.baz'] : $this->getFoo_BazService()) && false ?: '_'}; yield 'k2' => $this; }, 2), new RewindableGenerator(function () { return new \EmptyIterator(); @@ -278,7 +278,7 @@ protected function getLazyContextService() protected function getLazyContextIgnoreInvalidRefService() { return $this->services['lazy_context_ignore_invalid_ref'] = new \LazyContext(new RewindableGenerator(function () { - yield 0 => ${($_ = isset($this->services['foo.baz']) ? $this->services['foo.baz'] : $this->get('foo.baz')) && false ?: '_'}; + yield 0 => ${($_ = isset($this->services['foo.baz']) ? $this->services['foo.baz'] : $this->getFoo_BazService()) && false ?: '_'}; if ($this->has('invalid')) { yield 1 => ${($_ = isset($this->services['invalid']) ? $this->services['invalid'] : $this->get('invalid', ContainerInterface::NULL_ON_INVALID_REFERENCE)) && false ?: '_'}; } @@ -300,7 +300,7 @@ protected function getMethodCall1Service() $this->services['method_call1'] = $instance = new \Bar\FooClass(); - $instance->setBar(${($_ = isset($this->services['foo']) ? $this->services['foo'] : $this->get('foo')) && false ?: '_'}); + $instance->setBar(${($_ = isset($this->services['foo']) ? $this->services['foo'] : $this->getFooService()) && false ?: '_'}); $instance->setBar(${($_ = isset($this->services['foo2']) ? $this->services['foo2'] : $this->get('foo2', ContainerInterface::NULL_ON_INVALID_REFERENCE)) && false ?: '_'}); if ($this->has('foo3')) { $instance->setBar(${($_ = isset($this->services['foo3']) ? $this->services['foo3'] : $this->get('foo3', ContainerInterface::NULL_ON_INVALID_REFERENCE)) && false ?: '_'}); @@ -308,7 +308,7 @@ protected function getMethodCall1Service() if ($this->has('foobaz')) { $instance->setBar(${($_ = isset($this->services['foobaz']) ? $this->services['foobaz'] : $this->get('foobaz', ContainerInterface::NULL_ON_INVALID_REFERENCE)) && false ?: '_'}); } - $instance->setBar((${($_ = isset($this->services['foo']) ? $this->services['foo'] : $this->get('foo')) && false ?: '_'}->foo() . (($this->hasParameter("foo")) ? ($this->getParameter("foo")) : ("default")))); + $instance->setBar((${($_ = isset($this->services['foo']) ? $this->services['foo'] : $this->getFooService()) && false ?: '_'}->foo() . (($this->hasParameter("foo")) ? ($this->getParameter("foo")) : ("default")))); return $instance; } @@ -346,7 +346,7 @@ protected function getConfiguratorServiceService() { $this->services['configurator_service'] = $instance = new \ConfClass(); - $instance->setFoo(${($_ = isset($this->services['baz']) ? $this->services['baz'] : $this->get('baz')) && false ?: '_'}); + $instance->setFoo(${($_ = isset($this->services['baz']) ? $this->services['baz'] : $this->getBazService()) && false ?: '_'}); return $instance; } @@ -365,9 +365,13 @@ protected function getConfiguratorServiceSimpleService() * Gets the private 'factory_simple' shared service. * * @return \SimpleFactoryClass + * + * @deprecated The "factory_simple" service is deprecated. You should stop using it, as it will soon be removed. */ protected function getFactorySimpleService() { + @trigger_error('The "factory_simple" service is deprecated. You should stop using it, as it will soon be removed.', E_USER_DEPRECATED); + return $this->services['factory_simple'] = new \SimpleFactoryClass('foo'); } @@ -381,7 +385,7 @@ protected function getInlinedService() $this->services['inlined'] = $instance = new \Bar(); $instance->pub = 'pub'; - $instance->setBaz(${($_ = isset($this->services['baz']) ? $this->services['baz'] : $this->get('baz')) && false ?: '_'}); + $instance->setBaz(${($_ = isset($this->services['baz']) ? $this->services['baz'] : $this->getBazService()) && false ?: '_'}); return $instance; } diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_as_files.txt b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_as_files.txt index 2793610bae8ca..059f0912815ca 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_as_files.txt +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_as_files.txt @@ -102,7 +102,18 @@ use Symfony\Component\DependencyInjection\Argument\RewindableGenerator; // This file has been auto-generated by the Symfony Dependency Injection Component for internal use. // Returns the public 'factory_service_simple' shared service. -return $this->services['factory_service_simple'] = (new \SimpleFactoryClass('foo'))->getInstance(); +return $this->services['factory_service_simple'] = ${($_ = isset($this->services['factory_simple']) ? $this->services['factory_simple'] : $this->load(__DIR__.'/getFactorySimpleService.php')) && false ?: '_'}->getInstance(); + + [Container%s/getFactorySimpleService.php] => services['factory_simple'] = new \SimpleFactoryClass('foo'); [Container%s/getFooService.php] => __DIR__.'/getDeprecatedServiceService.php', 'factory_service' => __DIR__.'/getFactoryServiceService.php', 'factory_service_simple' => __DIR__.'/getFactoryServiceSimpleService.php', + 'factory_simple' => __DIR__.'/getFactorySimpleService.php', 'foo' => __DIR__.'/getFooService.php', 'foo.baz' => __DIR__.'/getFoo_BazService.php', 'foo_with_inline' => __DIR__.'/getFooWithInlineService.php', @@ -281,6 +293,9 @@ class Container%s extends Container 'new_factory_service' => __DIR__.'/getNewFactoryServiceService.php', 'service_from_static_method' => __DIR__.'/getServiceFromStaticMethodService.php', ); + $this->privates = array( + 'factory_simple' => true, + ); $this->aliases = array( 'alias_for_alias' => 'foo', 'alias_for_foo' => 'foo', diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_compiled.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_compiled.php index e77bc565792a8..103bb0de34d88 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_compiled.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_compiled.php @@ -39,6 +39,7 @@ public function __construct() 'deprecated_service' => 'getDeprecatedServiceService', 'factory_service' => 'getFactoryServiceService', 'factory_service_simple' => 'getFactoryServiceSimpleService', + 'factory_simple' => 'getFactorySimpleService', 'foo' => 'getFooService', 'foo.baz' => 'getFoo_BazService', 'foo_bar' => 'getFooBarService', @@ -49,6 +50,9 @@ public function __construct() 'new_factory_service' => 'getNewFactoryServiceService', 'service_from_static_method' => 'getServiceFromStaticMethodService', ); + $this->privates = array( + 'factory_simple' => true, + ); $this->aliases = array( 'alias_for_alias' => 'foo', 'alias_for_foo' => 'foo', @@ -89,7 +93,7 @@ public function isFrozen() */ protected function getBarService() { - $a = ${($_ = isset($this->services['foo.baz']) ? $this->services['foo.baz'] : $this->get('foo.baz')) && false ?: '_'}; + $a = ${($_ = isset($this->services['foo.baz']) ? $this->services['foo.baz'] : $this->getFoo_BazService()) && false ?: '_'}; $this->services['bar'] = $instance = new \Bar\FooClass('foo', $a, $this->getParameter('foo_bar')); @@ -107,7 +111,7 @@ protected function getBazService() { $this->services['baz'] = $instance = new \Baz(); - $instance->setFoo(${($_ = isset($this->services['foo_with_inline']) ? $this->services['foo_with_inline'] : $this->get('foo_with_inline')) && false ?: '_'}); + $instance->setFoo(${($_ = isset($this->services['foo_with_inline']) ? $this->services['foo_with_inline'] : $this->getFooWithInlineService()) && false ?: '_'}); return $instance; } @@ -120,7 +124,7 @@ protected function getBazService() protected function getConfiguredServiceService() { $a = new \ConfClass(); - $a->setFoo(${($_ = isset($this->services['baz']) ? $this->services['baz'] : $this->get('baz')) && false ?: '_'}); + $a->setFoo(${($_ = isset($this->services['baz']) ? $this->services['baz'] : $this->getBazService()) && false ?: '_'}); $this->services['configured_service'] = $instance = new \stdClass(); @@ -184,7 +188,7 @@ protected function getDeprecatedServiceService() */ protected function getFactoryServiceService() { - return $this->services['factory_service'] = ${($_ = isset($this->services['foo.baz']) ? $this->services['foo.baz'] : $this->get('foo.baz')) && false ?: '_'}->getInstance(); + return $this->services['factory_service'] = ${($_ = isset($this->services['foo.baz']) ? $this->services['foo.baz'] : $this->getFoo_BazService()) && false ?: '_'}->getInstance(); } /** @@ -194,7 +198,7 @@ protected function getFactoryServiceService() */ protected function getFactoryServiceSimpleService() { - return $this->services['factory_service_simple'] = (new \SimpleFactoryClass('foo'))->getInstance(); + return $this->services['factory_service_simple'] = ${($_ = isset($this->services['factory_simple']) ? $this->services['factory_simple'] : $this->getFactorySimpleService()) && false ?: '_'}->getInstance(); } /** @@ -204,14 +208,14 @@ protected function getFactoryServiceSimpleService() */ protected function getFooService() { - $a = ${($_ = isset($this->services['foo.baz']) ? $this->services['foo.baz'] : $this->get('foo.baz')) && false ?: '_'}; + $a = ${($_ = isset($this->services['foo.baz']) ? $this->services['foo.baz'] : $this->getFoo_BazService()) && false ?: '_'}; $this->services['foo'] = $instance = \Bar\FooClass::getInstance('foo', $a, array('bar' => 'foo is bar', 'foobar' => 'bar'), true, $this); $instance->foo = 'bar'; $instance->moo = $a; $instance->qux = array('bar' => 'foo is bar', 'foobar' => 'bar'); - $instance->setBar(${($_ = isset($this->services['bar']) ? $this->services['bar'] : $this->get('bar')) && false ?: '_'}); + $instance->setBar(${($_ = isset($this->services['bar']) ? $this->services['bar'] : $this->getBarService()) && false ?: '_'}); $instance->initialize(); sc_configure($instance); @@ -239,7 +243,7 @@ protected function getFoo_BazService() */ protected function getFooBarService() { - return new \Bar\FooClass(${($_ = isset($this->services['deprecated_service']) ? $this->services['deprecated_service'] : $this->get('deprecated_service')) && false ?: '_'}); + return new \Bar\FooClass(${($_ = isset($this->services['deprecated_service']) ? $this->services['deprecated_service'] : $this->getDeprecatedServiceService()) && false ?: '_'}); } /** @@ -254,7 +258,7 @@ protected function getFooWithInlineService() $this->services['foo_with_inline'] = $instance = new \Foo(); $a->pub = 'pub'; - $a->setBaz(${($_ = isset($this->services['baz']) ? $this->services['baz'] : $this->get('baz')) && false ?: '_'}); + $a->setBaz(${($_ = isset($this->services['baz']) ? $this->services['baz'] : $this->getBazService()) && false ?: '_'}); $instance->setBar($a); @@ -269,7 +273,7 @@ protected function getFooWithInlineService() protected function getLazyContextService() { return $this->services['lazy_context'] = new \LazyContext(new RewindableGenerator(function () { - yield 'k1' => ${($_ = isset($this->services['foo.baz']) ? $this->services['foo.baz'] : $this->get('foo.baz')) && false ?: '_'}; + yield 'k1' => ${($_ = isset($this->services['foo.baz']) ? $this->services['foo.baz'] : $this->getFoo_BazService()) && false ?: '_'}; yield 'k2' => $this; }, 2), new RewindableGenerator(function () { return new \EmptyIterator(); @@ -284,7 +288,7 @@ protected function getLazyContextService() protected function getLazyContextIgnoreInvalidRefService() { return $this->services['lazy_context_ignore_invalid_ref'] = new \LazyContext(new RewindableGenerator(function () { - yield 0 => ${($_ = isset($this->services['foo.baz']) ? $this->services['foo.baz'] : $this->get('foo.baz')) && false ?: '_'}; + yield 0 => ${($_ = isset($this->services['foo.baz']) ? $this->services['foo.baz'] : $this->getFoo_BazService()) && false ?: '_'}; }, 1), new RewindableGenerator(function () { return new \EmptyIterator(); }, 0)); @@ -301,9 +305,9 @@ protected function getMethodCall1Service() $this->services['method_call1'] = $instance = new \Bar\FooClass(); - $instance->setBar(${($_ = isset($this->services['foo']) ? $this->services['foo'] : $this->get('foo')) && false ?: '_'}); + $instance->setBar(${($_ = isset($this->services['foo']) ? $this->services['foo'] : $this->getFooService()) && false ?: '_'}); $instance->setBar(NULL); - $instance->setBar((${($_ = isset($this->services['foo']) ? $this->services['foo'] : $this->get('foo')) && false ?: '_'}->foo() . (($this->hasParameter("foo")) ? ($this->getParameter("foo")) : ("default")))); + $instance->setBar((${($_ = isset($this->services['foo']) ? $this->services['foo'] : $this->getFooService()) && false ?: '_'}->foo() . (($this->hasParameter("foo")) ? ($this->getParameter("foo")) : ("default")))); return $instance; } @@ -335,6 +339,20 @@ protected function getServiceFromStaticMethodService() return $this->services['service_from_static_method'] = \Bar\FooClass::getInstance(); } + /** + * Gets the private 'factory_simple' shared service. + * + * @return \SimpleFactoryClass + * + * @deprecated The "factory_simple" service is deprecated. You should stop using it, as it will soon be removed. + */ + protected function getFactorySimpleService() + { + @trigger_error('The "factory_simple" service is deprecated. You should stop using it, as it will soon be removed.', E_USER_DEPRECATED); + + return $this->services['factory_simple'] = new \SimpleFactoryClass('foo'); + } + /** * {@inheritdoc} */ diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_locator.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_locator.php index 0bbb83ae88d4a..751ad8e4fa454 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_locator.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_locator.php @@ -78,7 +78,7 @@ public function isFrozen() */ protected function getBarServiceService() { - return $this->services['bar_service'] = new \stdClass(${($_ = isset($this->services['baz_service']) ? $this->services['baz_service'] : $this->getBazServiceService()) && false ?: '_'}); + return $this->services['bar_service'] = new \stdClass(${($_ = isset($this->services['baz_service']) ? $this->services['baz_service'] : $this->services['baz_service'] = new \stdClass()) && false ?: '_'}); } /** @@ -89,9 +89,9 @@ protected function getBarServiceService() protected function getFooServiceService() { return $this->services['foo_service'] = new \Symfony\Component\DependencyInjection\ServiceLocator(array('bar' => function () { - return ${($_ = isset($this->services['bar_service']) ? $this->services['bar_service'] : $this->get('bar_service')) && false ?: '_'}; + return ${($_ = isset($this->services['bar_service']) ? $this->services['bar_service'] : $this->services['bar_service'] = new \stdClass(${($_ = isset($this->services['baz_service']) ? $this->services['baz_service'] : $this->services['baz_service'] = new \stdClass()) && false ?: '_'})) && false ?: '_'}; }, 'baz' => function () { - $f = function (\stdClass $v) { return $v; }; return $f(${($_ = isset($this->services['baz_service']) ? $this->services['baz_service'] : $this->getBazServiceService()) && false ?: '_'}); + $f = function (\stdClass $v) { return $v; }; return $f(${($_ = isset($this->services['baz_service']) ? $this->services['baz_service'] : $this->services['baz_service'] = new \stdClass()) && false ?: '_'}); }, 'nil' => function () { return NULL; })); @@ -135,7 +135,7 @@ protected function getTranslator_Loader3Service() protected function getTranslator1Service() { return $this->services['translator_1'] = new \Symfony\Component\DependencyInjection\Tests\Fixtures\StubbedTranslator(new \Symfony\Component\DependencyInjection\ServiceLocator(array('translator.loader_1' => function () { - return ${($_ = isset($this->services['translator.loader_1']) ? $this->services['translator.loader_1'] : $this->get('translator.loader_1')) && false ?: '_'}; + return ${($_ = isset($this->services['translator.loader_1']) ? $this->services['translator.loader_1'] : $this->services['translator.loader_1'] = new \stdClass()) && false ?: '_'}; }))); } @@ -147,10 +147,10 @@ protected function getTranslator1Service() protected function getTranslator2Service() { $this->services['translator_2'] = $instance = new \Symfony\Component\DependencyInjection\Tests\Fixtures\StubbedTranslator(new \Symfony\Component\DependencyInjection\ServiceLocator(array('translator.loader_2' => function () { - return ${($_ = isset($this->services['translator.loader_2']) ? $this->services['translator.loader_2'] : $this->get('translator.loader_2')) && false ?: '_'}; + return ${($_ = isset($this->services['translator.loader_2']) ? $this->services['translator.loader_2'] : $this->services['translator.loader_2'] = new \stdClass()) && false ?: '_'}; }))); - $instance->addResource('db', ${($_ = isset($this->services['translator.loader_2']) ? $this->services['translator.loader_2'] : $this->get('translator.loader_2')) && false ?: '_'}, 'nl'); + $instance->addResource('db', ${($_ = isset($this->services['translator.loader_2']) ? $this->services['translator.loader_2'] : $this->services['translator.loader_2'] = new \stdClass()) && false ?: '_'}, 'nl'); return $instance; } @@ -162,10 +162,10 @@ protected function getTranslator2Service() */ protected function getTranslator3Service() { - $a = ${($_ = isset($this->services['translator.loader_3']) ? $this->services['translator.loader_3'] : $this->get('translator.loader_3')) && false ?: '_'}; + $a = ${($_ = isset($this->services['translator.loader_3']) ? $this->services['translator.loader_3'] : $this->services['translator.loader_3'] = new \stdClass()) && false ?: '_'}; $this->services['translator_3'] = $instance = new \Symfony\Component\DependencyInjection\Tests\Fixtures\StubbedTranslator(new \Symfony\Component\DependencyInjection\ServiceLocator(array('translator.loader_3' => function () { - return ${($_ = isset($this->services['translator.loader_3']) ? $this->services['translator.loader_3'] : $this->get('translator.loader_3')) && false ?: '_'}; + return ${($_ = isset($this->services['translator.loader_3']) ? $this->services['translator.loader_3'] : $this->services['translator.loader_3'] = new \stdClass()) && false ?: '_'}; }))); $instance->addResource('db', $a, 'nl'); diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_private_frozen.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_private_frozen.php index 782e17c2a4e84..a6717fd6abf8f 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_private_frozen.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_private_frozen.php @@ -72,7 +72,7 @@ public function isFrozen() */ protected function getBarServiceService() { - return $this->services['bar_service'] = new \stdClass(${($_ = isset($this->services['baz_service']) ? $this->services['baz_service'] : $this->getBazServiceService()) && false ?: '_'}); + return $this->services['bar_service'] = new \stdClass(${($_ = isset($this->services['baz_service']) ? $this->services['baz_service'] : $this->services['baz_service'] = new \stdClass()) && false ?: '_'}); } /** @@ -82,7 +82,7 @@ protected function getBarServiceService() */ protected function getFooServiceService() { - return $this->services['foo_service'] = new \stdClass(${($_ = isset($this->services['baz_service']) ? $this->services['baz_service'] : $this->getBazServiceService()) && false ?: '_'}); + return $this->services['foo_service'] = new \stdClass(${($_ = isset($this->services['baz_service']) ? $this->services['baz_service'] : $this->services['baz_service'] = new \stdClass()) && false ?: '_'}); } /** diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_private_in_expression.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_private_in_expression.php index bd334df048711..e5129d4f36566 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_private_in_expression.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_private_in_expression.php @@ -71,7 +71,7 @@ public function isFrozen() */ protected function getPublicFooService() { - return $this->services['public_foo'] = new \stdClass(${($_ = isset($this->services['private_foo']) ? $this->services['private_foo'] : $this->getPrivateFooService()) && false ?: '_'}); + return $this->services['public_foo'] = new \stdClass(${($_ = isset($this->services['private_foo']) ? $this->services['private_foo'] : $this->services['private_foo'] = new \stdClass()) && false ?: '_'}); } /** diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_subscriber.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_subscriber.php index 0f87da56175d8..3d7cc80336831 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_subscriber.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_subscriber.php @@ -87,13 +87,13 @@ protected function getTestServiceSubscriberService() protected function getFooServiceService() { return $this->services['foo_service'] = new \Symfony\Component\DependencyInjection\Tests\Fixtures\TestServiceSubscriber(new \Symfony\Component\DependencyInjection\ServiceLocator(array('Symfony\\Component\\DependencyInjection\\Tests\\Fixtures\\CustomDefinition' => function () { - $f = function (\Symfony\Component\DependencyInjection\Tests\Fixtures\CustomDefinition $v = null) { return $v; }; return $f(${($_ = isset($this->services['Symfony\Component\DependencyInjection\Tests\Fixtures\CustomDefinition']) ? $this->services['Symfony\Component\DependencyInjection\Tests\Fixtures\CustomDefinition'] : $this->getCustomDefinitionService()) && false ?: '_'}); + $f = function (\Symfony\Component\DependencyInjection\Tests\Fixtures\CustomDefinition $v = null) { return $v; }; return $f(${($_ = isset($this->services['Symfony\Component\DependencyInjection\Tests\Fixtures\CustomDefinition']) ? $this->services['Symfony\Component\DependencyInjection\Tests\Fixtures\CustomDefinition'] : $this->services['Symfony\Component\DependencyInjection\Tests\Fixtures\CustomDefinition'] = new \Symfony\Component\DependencyInjection\Tests\Fixtures\CustomDefinition()) && false ?: '_'}); }, 'Symfony\\Component\\DependencyInjection\\Tests\\Fixtures\\TestServiceSubscriber' => function () { - $f = function (\Symfony\Component\DependencyInjection\Tests\Fixtures\TestServiceSubscriber $v) { return $v; }; return $f(${($_ = isset($this->services['Symfony\Component\DependencyInjection\Tests\Fixtures\TestServiceSubscriber']) ? $this->services['Symfony\Component\DependencyInjection\Tests\Fixtures\TestServiceSubscriber'] : $this->get('Symfony\Component\DependencyInjection\Tests\Fixtures\TestServiceSubscriber')) && false ?: '_'}); + $f = function (\Symfony\Component\DependencyInjection\Tests\Fixtures\TestServiceSubscriber $v) { return $v; }; return $f(${($_ = isset($this->services['Symfony\Component\DependencyInjection\Tests\Fixtures\TestServiceSubscriber']) ? $this->services['Symfony\Component\DependencyInjection\Tests\Fixtures\TestServiceSubscriber'] : $this->services['Symfony\Component\DependencyInjection\Tests\Fixtures\TestServiceSubscriber'] = new \Symfony\Component\DependencyInjection\Tests\Fixtures\TestServiceSubscriber()) && false ?: '_'}); }, 'bar' => function () { - $f = function (\Symfony\Component\DependencyInjection\Tests\Fixtures\CustomDefinition $v) { return $v; }; return $f(${($_ = isset($this->services['Symfony\Component\DependencyInjection\Tests\Fixtures\TestServiceSubscriber']) ? $this->services['Symfony\Component\DependencyInjection\Tests\Fixtures\TestServiceSubscriber'] : $this->get('Symfony\Component\DependencyInjection\Tests\Fixtures\TestServiceSubscriber')) && false ?: '_'}); + $f = function (\Symfony\Component\DependencyInjection\Tests\Fixtures\CustomDefinition $v) { return $v; }; return $f(${($_ = isset($this->services['Symfony\Component\DependencyInjection\Tests\Fixtures\TestServiceSubscriber']) ? $this->services['Symfony\Component\DependencyInjection\Tests\Fixtures\TestServiceSubscriber'] : $this->services['Symfony\Component\DependencyInjection\Tests\Fixtures\TestServiceSubscriber'] = new \Symfony\Component\DependencyInjection\Tests\Fixtures\TestServiceSubscriber()) && false ?: '_'}); }, 'baz' => function () { - $f = function (\Symfony\Component\DependencyInjection\Tests\Fixtures\CustomDefinition $v = null) { return $v; }; return $f(${($_ = isset($this->services['Symfony\Component\DependencyInjection\Tests\Fixtures\CustomDefinition']) ? $this->services['Symfony\Component\DependencyInjection\Tests\Fixtures\CustomDefinition'] : $this->getCustomDefinitionService()) && false ?: '_'}); + $f = function (\Symfony\Component\DependencyInjection\Tests\Fixtures\CustomDefinition $v = null) { return $v; }; return $f(${($_ = isset($this->services['Symfony\Component\DependencyInjection\Tests\Fixtures\CustomDefinition']) ? $this->services['Symfony\Component\DependencyInjection\Tests\Fixtures\CustomDefinition'] : $this->services['Symfony\Component\DependencyInjection\Tests\Fixtures\CustomDefinition'] = new \Symfony\Component\DependencyInjection\Tests\Fixtures\CustomDefinition()) && false ?: '_'}); }))); } diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_uninitialized_ref.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_uninitialized_ref.php index df0d74c07cbeb..71b19e0303d63 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_uninitialized_ref.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_uninitialized_ref.php @@ -76,12 +76,12 @@ protected function getBarService() $this->services['bar'] = $instance = new \stdClass(); $instance->foo1 = ${($_ = isset($this->services['foo1']) ? $this->services['foo1'] : null) && false ?: '_'}; - $instance->foo2 = null; + $instance->foo2 = ${($_ = isset($this->services['foo2']) ? $this->services['foo2'] : null) && false ?: '_'}; $instance->foo3 = ${($_ = isset($this->services['foo3']) ? $this->services['foo3'] : null) && false ?: '_'}; $instance->closures = array(0 => function () { return ${($_ = isset($this->services['foo1']) ? $this->services['foo1'] : null) && false ?: '_'}; }, 1 => function () { - return null; + return ${($_ = isset($this->services['foo2']) ? $this->services['foo2'] : null) && false ?: '_'}; }, 2 => function () { return ${($_ = isset($this->services['foo3']) ? $this->services['foo3'] : null) && false ?: '_'}; }); @@ -90,7 +90,7 @@ protected function getBarService() yield 'foo1' => ${($_ = isset($this->services['foo1']) ? $this->services['foo1'] : null) && false ?: '_'}; } if (false) { - yield 'foo2' => null; + yield 'foo2' => ${($_ = isset($this->services['foo2']) ? $this->services['foo2'] : null) && false ?: '_'}; } if (isset($this->services['foo3'])) { yield 'foo3' => ${($_ = isset($this->services['foo3']) ? $this->services['foo3'] : null) && false ?: '_'}; @@ -111,7 +111,7 @@ protected function getBazService() { $this->services['baz'] = $instance = new \stdClass(); - $instance->foo3 = ${($_ = isset($this->services['foo3']) ? $this->services['foo3'] : $this->getFoo3Service()) && false ?: '_'}; + $instance->foo3 = ${($_ = isset($this->services['foo3']) ? $this->services['foo3'] : $this->services['foo3'] = new \stdClass()) && false ?: '_'}; return $instance; } diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services9.xml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services9.xml index fb2050ab6191f..c7884fb11d6ab 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services9.xml +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services9.xml @@ -114,6 +114,7 @@ foo + The "%service_id%" service is deprecated. You should stop using it, as it will soon be removed. diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services9.yml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services9.yml index 984f2136700c0..01b67d78ac553 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services9.yml +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services9.yml @@ -106,6 +106,7 @@ services: factory: [Bar\FooClass, getInstance] factory_simple: class: SimpleFactoryClass + deprecated: The "%service_id%" service is deprecated. You should stop using it, as it will soon be removed. public: false arguments: ['foo'] factory_service_simple: From 61966df131568db58c579e408b4ad9ab15903ffc Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Mon, 4 Sep 2017 19:49:50 +0200 Subject: [PATCH 0760/1099] [DI] There are no initialized-only refs to undeclared services --- .../Component/DependencyInjection/Dumper/PhpDumper.php | 10 ++++++---- .../Tests/Fixtures/php/services_uninitialized_ref.php | 6 +++--- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php index add4e7c616f57..2f70d59d819ec 100644 --- a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php +++ b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php @@ -1711,12 +1711,12 @@ private function getServiceCall($id, Reference $reference = null) return '$this'; } - if (null !== $reference && ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE === $reference->getInvalidBehavior()) { - $code = 'null'; - } elseif ($this->container->hasDefinition($id)) { + if ($this->container->hasDefinition($id)) { $definition = $this->container->getDefinition($id); - if ($this->isTrivialInstance($definition)) { + if (null !== $reference && ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE === $reference->getInvalidBehavior()) { + $code = 'null'; + } elseif ($this->isTrivialInstance($definition)) { $code = substr($this->addNewInstance($definition, '', '', $id), 8, -2); if ($definition->isShared()) { $code = sprintf('$this->services[\'%s\'] = %s', $id, $code); @@ -1726,6 +1726,8 @@ private function getServiceCall($id, Reference $reference = null) } else { $code = sprintf('$this->%s()', $this->generateMethodName($id)); } + } elseif (null !== $reference && ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE === $reference->getInvalidBehavior()) { + return 'null'; } elseif (null !== $reference && ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE !== $reference->getInvalidBehavior()) { $code = sprintf('$this->get(\'%s\', ContainerInterface::NULL_ON_INVALID_REFERENCE)', $id); } else { diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_uninitialized_ref.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_uninitialized_ref.php index 71b19e0303d63..4c26d58d70c28 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_uninitialized_ref.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_uninitialized_ref.php @@ -76,12 +76,12 @@ protected function getBarService() $this->services['bar'] = $instance = new \stdClass(); $instance->foo1 = ${($_ = isset($this->services['foo1']) ? $this->services['foo1'] : null) && false ?: '_'}; - $instance->foo2 = ${($_ = isset($this->services['foo2']) ? $this->services['foo2'] : null) && false ?: '_'}; + $instance->foo2 = null; $instance->foo3 = ${($_ = isset($this->services['foo3']) ? $this->services['foo3'] : null) && false ?: '_'}; $instance->closures = array(0 => function () { return ${($_ = isset($this->services['foo1']) ? $this->services['foo1'] : null) && false ?: '_'}; }, 1 => function () { - return ${($_ = isset($this->services['foo2']) ? $this->services['foo2'] : null) && false ?: '_'}; + return null; }, 2 => function () { return ${($_ = isset($this->services['foo3']) ? $this->services['foo3'] : null) && false ?: '_'}; }); @@ -90,7 +90,7 @@ protected function getBarService() yield 'foo1' => ${($_ = isset($this->services['foo1']) ? $this->services['foo1'] : null) && false ?: '_'}; } if (false) { - yield 'foo2' => ${($_ = isset($this->services['foo2']) ? $this->services['foo2'] : null) && false ?: '_'}; + yield 'foo2' => null; } if (isset($this->services['foo3'])) { yield 'foo3' => ${($_ = isset($this->services['foo3']) ? $this->services['foo3'] : null) && false ?: '_'}; From b635b62463b6d12682e3cbae7fbeca14f38e295d Mon Sep 17 00:00:00 2001 From: Yanick Witschi Date: Sun, 3 Sep 2017 13:14:53 +0200 Subject: [PATCH 0761/1099] Implemented PruneableInterface on TagAwareAdapter --- .../Cache/Adapter/TagAwareAdapter.php | 15 ++++- src/Symfony/Component/Cache/CHANGELOG.md | 2 +- .../Tests/Adapter/TagAwareAdapterTest.php | 57 +++++++++++++++++++ 3 files changed, 72 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/Cache/Adapter/TagAwareAdapter.php b/src/Symfony/Component/Cache/Adapter/TagAwareAdapter.php index 1e0617ebe271d..96df1128bb895 100644 --- a/src/Symfony/Component/Cache/Adapter/TagAwareAdapter.php +++ b/src/Symfony/Component/Cache/Adapter/TagAwareAdapter.php @@ -14,11 +14,12 @@ use Psr\Cache\CacheItemInterface; use Psr\Cache\InvalidArgumentException; use Symfony\Component\Cache\CacheItem; +use Symfony\Component\Cache\PruneableInterface; /** * @author Nicolas Grekas */ -class TagAwareAdapter implements TagAwareAdapterInterface +class TagAwareAdapter implements TagAwareAdapterInterface, PruneableInterface { const TAGS_PREFIX = "\0tags\0"; @@ -334,4 +335,16 @@ private function getTagVersions(array $tagsByKey) return $tagVersions; } + + /** + * {@inheritdoc} + */ + public function prune() + { + if ($this->itemsAdapter instanceof PruneableInterface) { + return $this->itemsAdapter->prune(); + } + + return false; + } } diff --git a/src/Symfony/Component/Cache/CHANGELOG.md b/src/Symfony/Component/Cache/CHANGELOG.md index bd637f10df0b0..7389a7edcc57d 100644 --- a/src/Symfony/Component/Cache/CHANGELOG.md +++ b/src/Symfony/Component/Cache/CHANGELOG.md @@ -5,7 +5,7 @@ CHANGELOG ----- * added PruneableInterface so PSR-6 or PSR-16 cache implementations can declare support for manual stale cache pruning - * added prune logic to FilesystemTrait, PhpFilesTrait, PdoTrait, and ChainTrait + * added prune logic to FilesystemTrait, PhpFilesTrait, PdoTrait, TagAwareAdapter and ChainTrait * now FilesystemAdapter, PhpFilesAdapter, FilesystemCache, PhpFilesCache, PdoAdapter, PdoCache, ChainAdapter, and ChainCache implement PruneableInterface and support manual stale cache pruning diff --git a/src/Symfony/Component/Cache/Tests/Adapter/TagAwareAdapterTest.php b/src/Symfony/Component/Cache/Tests/Adapter/TagAwareAdapterTest.php index deca227c47dd0..0e4e07a16d51b 100644 --- a/src/Symfony/Component/Cache/Tests/Adapter/TagAwareAdapterTest.php +++ b/src/Symfony/Component/Cache/Tests/Adapter/TagAwareAdapterTest.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Cache\Tests\Adapter; +use Symfony\Component\Cache\Adapter\AdapterInterface; use Symfony\Component\Cache\Adapter\FilesystemAdapter; use Symfony\Component\Cache\Adapter\TagAwareAdapter; @@ -125,4 +126,60 @@ public function testGetPreviousTags() $i = $pool->getItem('k'); $this->assertSame(array('foo' => 'foo'), $i->getPreviousTags()); } + + public function testPrune() + { + $cache = new TagAwareAdapter($this->getPruneableMock()); + $this->assertTrue($cache->prune()); + + $cache = new TagAwareAdapter($this->getNonPruneableMock()); + $this->assertFalse($cache->prune()); + + $cache = new TagAwareAdapter($this->getFailingPruneableMock()); + $this->assertFalse($cache->prune()); + } + + /** + * @return \PHPUnit_Framework_MockObject_MockObject|PruneableCacheInterface + */ + private function getPruneableMock() + { + $pruneable = $this + ->getMockBuilder(PruneableCacheInterface::class) + ->getMock(); + + $pruneable + ->expects($this->atLeastOnce()) + ->method('prune') + ->will($this->returnValue(true)); + + return $pruneable; + } + + /** + * @return \PHPUnit_Framework_MockObject_MockObject|PruneableCacheInterface + */ + private function getFailingPruneableMock() + { + $pruneable = $this + ->getMockBuilder(PruneableCacheInterface::class) + ->getMock(); + + $pruneable + ->expects($this->atLeastOnce()) + ->method('prune') + ->will($this->returnValue(false)); + + return $pruneable; + } + + /** + * @return \PHPUnit_Framework_MockObject_MockObject|AdapterInterface + */ + private function getNonPruneableMock() + { + return $this + ->getMockBuilder(AdapterInterface::class) + ->getMock(); + } } From 1cad4696daddd5124346ada2e38d17c336c323bd Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Mon, 4 Sep 2017 20:35:21 +0200 Subject: [PATCH 0762/1099] fix merge --- .../Component/VarDumper/Tests/Caster/DateCasterTest.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Symfony/Component/VarDumper/Tests/Caster/DateCasterTest.php b/src/Symfony/Component/VarDumper/Tests/Caster/DateCasterTest.php index cb6b6a6b16b71..0298c8b3cb5a9 100644 --- a/src/Symfony/Component/VarDumper/Tests/Caster/DateCasterTest.php +++ b/src/Symfony/Component/VarDumper/Tests/Caster/DateCasterTest.php @@ -360,6 +360,10 @@ public function providePeriods() array('2017-01-01', 'P1D', 2, \DatePeriod::EXCLUDE_START_DATE, 'every + 1d, from 2017-01-01 00:00:00.0 (excluded) recurring 2 time/s', '1) 2017-01-02%a2) 2017-01-03'), ); + if (\PHP_VERSION_ID < 70107) { + array_walk($periods, function (&$i) { $i[5] = ''; }); + } + return $periods; } From 2ba5005830187a01fdeb033edf6ae96d0bfcd643 Mon Sep 17 00:00:00 2001 From: Robin Chalas Date: Mon, 4 Sep 2017 22:01:21 +0200 Subject: [PATCH 0763/1099] Fix ArrayInput::toString() for VALUE_IS_ARRAY options/args --- src/Symfony/Component/Console/Input/ArrayInput.php | 10 ++++++++-- .../Component/Console/Tests/Input/ArrayInputTest.php | 3 +++ 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/Console/Input/ArrayInput.php b/src/Symfony/Component/Console/Input/ArrayInput.php index e9d4f8e842a9f..4937860b83204 100644 --- a/src/Symfony/Component/Console/Input/ArrayInput.php +++ b/src/Symfony/Component/Console/Input/ArrayInput.php @@ -101,9 +101,15 @@ public function __toString() $params = array(); foreach ($this->parameters as $param => $val) { if ($param && '-' === $param[0]) { - $params[] = $param.('' != $val ? '='.$this->escapeToken($val) : ''); + if (is_array($val)) { + foreach ($val as $v) { + $params[] = $param.('' != $v ? '='.$this->escapeToken($v) : ''); + } + } else { + $params[] = $param.('' != $val ? '='.$this->escapeToken($val) : ''); + } } else { - $params[] = $this->escapeToken($val); + $params[] = is_array($val) ? array_map(array($this, 'escapeToken'), $val) : $this->escapeToken($val); } } diff --git a/src/Symfony/Component/Console/Tests/Input/ArrayInputTest.php b/src/Symfony/Component/Console/Tests/Input/ArrayInputTest.php index 06e65f7398bdc..608020a5caa55 100644 --- a/src/Symfony/Component/Console/Tests/Input/ArrayInputTest.php +++ b/src/Symfony/Component/Console/Tests/Input/ArrayInputTest.php @@ -140,5 +140,8 @@ public function testToString() { $input = new ArrayInput(array('-f' => null, '-b' => 'bar', '--foo' => 'b a z', '--lala' => null, 'test' => 'Foo', 'test2' => "A\nB'C")); $this->assertEquals('-f -b=bar --foo='.escapeshellarg('b a z').' --lala Foo '.escapeshellarg("A\nB'C"), (string) $input); + + $input = new ArrayInput(array('-b' => array('bval_1', 'bval_2'), '--f' => array('fval_1', 'fval_2'))); + $this->assertSame('-b=bval_1 -b=bval_2 --f=fval_1 --f=fval_2', (string) $input); } } From 5798dd6beccd9587339358c63420a1e7222f6959 Mon Sep 17 00:00:00 2001 From: Denis Golubovskiy Date: Thu, 24 Aug 2017 21:57:21 +0300 Subject: [PATCH 0764/1099] [Cache] Use options from Memcached DSN --- src/Symfony/Component/Cache/CHANGELOG.md | 1 + .../Tests/Adapter/MemcachedAdapterTest.php | 30 +++++++++++++ .../Component/Cache/Traits/MemcachedTrait.php | 45 ++++++++++--------- 3 files changed, 54 insertions(+), 22 deletions(-) diff --git a/src/Symfony/Component/Cache/CHANGELOG.md b/src/Symfony/Component/Cache/CHANGELOG.md index e8172d94988d4..58b737dc950f3 100644 --- a/src/Symfony/Component/Cache/CHANGELOG.md +++ b/src/Symfony/Component/Cache/CHANGELOG.md @@ -4,6 +4,7 @@ CHANGELOG 3.4.0 ----- + * added using options from Memcached DSN * added PruneableInterface so PSR-6 or PSR-16 cache implementations can declare support for manual stale cache pruning * added FilesystemTrait::prune() and PhpFilesTrait::prune() implementations * now FilesystemAdapter, PhpFilesAdapter, FilesystemCache, and PhpFilesCache implement PruneableInterface and support diff --git a/src/Symfony/Component/Cache/Tests/Adapter/MemcachedAdapterTest.php b/src/Symfony/Component/Cache/Tests/Adapter/MemcachedAdapterTest.php index 82b41c3b4d870..a506108c7bc03 100644 --- a/src/Symfony/Component/Cache/Tests/Adapter/MemcachedAdapterTest.php +++ b/src/Symfony/Component/Cache/Tests/Adapter/MemcachedAdapterTest.php @@ -162,4 +162,34 @@ public function provideServersSetting() ); } } + + /** + * @dataProvider provideDsnWithOptions + */ + public function testDsnWithOptions($dsn, array $options, array $expectedOptions) + { + $client = MemcachedAdapter::createConnection($dsn, $options); + + foreach ($expectedOptions as $option => $expect) { + $this->assertSame($expect, $client->getOption($option)); + } + } + + public function provideDsnWithOptions() + { + if (!class_exists('\Memcached')) { + self::markTestSkipped('Extension memcached required.'); + } + + yield array( + 'memcached://localhost:11222?retry_timeout=10', + array(\Memcached::OPT_RETRY_TIMEOUT => 8), + array(\Memcached::OPT_RETRY_TIMEOUT => 10), + ); + yield array( + 'memcached://localhost:11222?socket_recv_size=1&socket_send_size=2', + array(\Memcached::OPT_RETRY_TIMEOUT => 8), + array(\Memcached::OPT_SOCKET_RECV_SIZE => 1, \Memcached::OPT_SOCKET_SEND_SIZE => 2, \Memcached::OPT_RETRY_TIMEOUT => 8), + ); + } } diff --git a/src/Symfony/Component/Cache/Traits/MemcachedTrait.php b/src/Symfony/Component/Cache/Traits/MemcachedTrait.php index c2832946f98c2..ee990163a3d65 100644 --- a/src/Symfony/Component/Cache/Traits/MemcachedTrait.php +++ b/src/Symfony/Component/Cache/Traits/MemcachedTrait.php @@ -83,28 +83,6 @@ public static function createConnection($servers, array $options = array()) $client = new \Memcached($options['persistent_id']); $username = $options['username']; $password = $options['password']; - unset($options['persistent_id'], $options['username'], $options['password']); - $options = array_change_key_case($options, CASE_UPPER); - - // set client's options - $client->setOption(\Memcached::OPT_BINARY_PROTOCOL, true); - $client->setOption(\Memcached::OPT_NO_BLOCK, true); - if (!array_key_exists('LIBKETAMA_COMPATIBLE', $options) && !array_key_exists(\Memcached::OPT_LIBKETAMA_COMPATIBLE, $options)) { - $client->setOption(\Memcached::OPT_LIBKETAMA_COMPATIBLE, true); - } - foreach ($options as $name => $value) { - if (is_int($name)) { - continue; - } - if ('HASH' === $name || 'SERIALIZER' === $name || 'DISTRIBUTION' === $name) { - $value = constant('Memcached::'.$name.'_'.strtoupper($value)); - } - $opt = constant('Memcached::OPT_'.$name); - - unset($options[$name]); - $options[$opt] = $value; - } - $client->setOptions($options); // parse any DSN in $servers foreach ($servers as $i => $dsn) { @@ -139,11 +117,34 @@ public static function createConnection($servers, array $options = array()) if (isset($params['query'])) { parse_str($params['query'], $query); $params += $query; + $options = $query + $options; } $servers[$i] = array($params['host'], $params['port'], $params['weight']); } + // set client's options + unset($options['persistent_id'], $options['username'], $options['password'], $options['weight']); + $options = array_change_key_case($options, CASE_UPPER); + $client->setOption(\Memcached::OPT_BINARY_PROTOCOL, true); + $client->setOption(\Memcached::OPT_NO_BLOCK, true); + if (!array_key_exists('LIBKETAMA_COMPATIBLE', $options) && !array_key_exists(\Memcached::OPT_LIBKETAMA_COMPATIBLE, $options)) { + $client->setOption(\Memcached::OPT_LIBKETAMA_COMPATIBLE, true); + } + foreach ($options as $name => $value) { + if (is_int($name)) { + continue; + } + if ('HASH' === $name || 'SERIALIZER' === $name || 'DISTRIBUTION' === $name) { + $value = constant('Memcached::'.$name.'_'.strtoupper($value)); + } + $opt = constant('Memcached::OPT_'.$name); + + unset($options[$name]); + $options[$opt] = $value; + } + $client->setOptions($options); + // set client's servers, taking care of persistent connections if (!$client->isPristine()) { $oldServers = array(); From 36d2a45d1d1d373292226a47c2be9828ec072149 Mon Sep 17 00:00:00 2001 From: Roland Franssen Date: Fri, 1 Sep 2017 18:34:37 +0200 Subject: [PATCH 0765/1099] [HttpKernel] Dont register env parameter resource --- .../Config/EnvParametersResource.php | 97 --------------- src/Symfony/Component/HttpKernel/Kernel.php | 2 - .../Config/EnvParametersResourceTest.php | 110 ------------------ .../Component/HttpKernel/Tests/KernelTest.php | 37 ------ 4 files changed, 246 deletions(-) delete mode 100644 src/Symfony/Component/HttpKernel/Config/EnvParametersResource.php delete mode 100644 src/Symfony/Component/HttpKernel/Tests/Config/EnvParametersResourceTest.php diff --git a/src/Symfony/Component/HttpKernel/Config/EnvParametersResource.php b/src/Symfony/Component/HttpKernel/Config/EnvParametersResource.php deleted file mode 100644 index c2b73cea94f61..0000000000000 --- a/src/Symfony/Component/HttpKernel/Config/EnvParametersResource.php +++ /dev/null @@ -1,97 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\Config; - -use Symfony\Component\Config\Resource\SelfCheckingResourceInterface; - -/** - * EnvParametersResource represents resources stored in prefixed environment variables. - * - * @author Chris Wilkinson - * - * @deprecated since version 3.4, to be removed in 4.0 - */ -class EnvParametersResource implements SelfCheckingResourceInterface, \Serializable -{ - /** - * @var string - */ - private $prefix; - - /** - * @var string - */ - private $variables; - - /** - * Constructor. - * - * @param string $prefix - */ - public function __construct($prefix) - { - $this->prefix = $prefix; - $this->variables = $this->findVariables(); - } - - /** - * {@inheritdoc} - */ - public function __toString() - { - return serialize($this->getResource()); - } - - /** - * @return array An array with two keys: 'prefix' for the prefix used and 'variables' containing all the variables watched by this resource - */ - public function getResource() - { - return array('prefix' => $this->prefix, 'variables' => $this->variables); - } - - /** - * {@inheritdoc} - */ - public function isFresh($timestamp) - { - return $this->findVariables() === $this->variables; - } - - public function serialize() - { - return serialize(array('prefix' => $this->prefix, 'variables' => $this->variables)); - } - - public function unserialize($serialized) - { - $unserialized = unserialize($serialized, array('allowed_classes' => false)); - - $this->prefix = $unserialized['prefix']; - $this->variables = $unserialized['variables']; - } - - private function findVariables() - { - $variables = array(); - - foreach ($_SERVER as $key => $value) { - if (0 === strpos($key, $this->prefix)) { - $variables[$key] = $value; - } - } - - ksort($variables); - - return $variables; - } -} diff --git a/src/Symfony/Component/HttpKernel/Kernel.php b/src/Symfony/Component/HttpKernel/Kernel.php index d97de8a722a4b..913ba1a81ea18 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -26,7 +26,6 @@ use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\Bundle\BundleInterface; -use Symfony\Component\HttpKernel\Config\EnvParametersResource; use Symfony\Component\HttpKernel\Config\FileLocator; use Symfony\Component\HttpKernel\DependencyInjection\MergeExtensionConfigurationPass; use Symfony\Component\HttpKernel\DependencyInjection\AddAnnotatedClassesToCachePass; @@ -625,7 +624,6 @@ protected function buildContainer() } $container->addCompilerPass(new AddAnnotatedClassesToCachePass($this)); - $container->addResource(new EnvParametersResource('SYMFONY__')); return $container; } diff --git a/src/Symfony/Component/HttpKernel/Tests/Config/EnvParametersResourceTest.php b/src/Symfony/Component/HttpKernel/Tests/Config/EnvParametersResourceTest.php deleted file mode 100644 index 986e05d8b888a..0000000000000 --- a/src/Symfony/Component/HttpKernel/Tests/Config/EnvParametersResourceTest.php +++ /dev/null @@ -1,110 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\Tests\Config; - -use PHPUnit\Framework\TestCase; -use Symfony\Component\HttpKernel\Config\EnvParametersResource; - -/** - * @group legacy - */ -class EnvParametersResourceTest extends TestCase -{ - protected $prefix = '__DUMMY_'; - protected $initialEnv; - protected $resource; - - protected function setUp() - { - $this->initialEnv = array( - $this->prefix.'1' => 'foo', - $this->prefix.'2' => 'bar', - ); - - foreach ($this->initialEnv as $key => $value) { - $_SERVER[$key] = $value; - } - - $this->resource = new EnvParametersResource($this->prefix); - } - - protected function tearDown() - { - foreach ($_SERVER as $key => $value) { - if (0 === strpos($key, $this->prefix)) { - unset($_SERVER[$key]); - } - } - } - - public function testGetResource() - { - $this->assertSame( - array('prefix' => $this->prefix, 'variables' => $this->initialEnv), - $this->resource->getResource(), - '->getResource() returns the resource' - ); - } - - public function testToString() - { - $this->assertSame( - serialize(array('prefix' => $this->prefix, 'variables' => $this->initialEnv)), - (string) $this->resource - ); - } - - public function testIsFreshNotChanged() - { - $this->assertTrue( - $this->resource->isFresh(time()), - '->isFresh() returns true if the variables have not changed' - ); - } - - public function testIsFreshValueChanged() - { - reset($this->initialEnv); - $_SERVER[key($this->initialEnv)] = 'baz'; - - $this->assertFalse( - $this->resource->isFresh(time()), - '->isFresh() returns false if a variable has been changed' - ); - } - - public function testIsFreshValueRemoved() - { - reset($this->initialEnv); - unset($_SERVER[key($this->initialEnv)]); - - $this->assertFalse( - $this->resource->isFresh(time()), - '->isFresh() returns false if a variable has been removed' - ); - } - - public function testIsFreshValueAdded() - { - $_SERVER[$this->prefix.'3'] = 'foo'; - - $this->assertFalse( - $this->resource->isFresh(time()), - '->isFresh() returns false if a variable has been added' - ); - } - - public function testSerializeUnserialize() - { - $this->assertEquals($this->resource, unserialize(serialize($this->resource))); - } -} diff --git a/src/Symfony/Component/HttpKernel/Tests/KernelTest.php b/src/Symfony/Component/HttpKernel/Tests/KernelTest.php index 613c6f990202d..8b49ab9c984c4 100644 --- a/src/Symfony/Component/HttpKernel/Tests/KernelTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/KernelTest.php @@ -16,7 +16,6 @@ use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\Filesystem\Filesystem; use Symfony\Component\HttpKernel\Bundle\BundleInterface; -use Symfony\Component\HttpKernel\Config\EnvParametersResource; use Symfony\Component\HttpKernel\Kernel; use Symfony\Component\HttpKernel\HttpKernelInterface; use Symfony\Component\HttpFoundation\Request; @@ -104,42 +103,6 @@ public function testClassCacheIsNotLoadedByDefault() $kernel->boot(); } - public function testEnvParametersResourceIsAdded() - { - $container = new ContainerBuilder(); - $kernel = $this->getMockBuilder('Symfony\Component\HttpKernel\Tests\Fixtures\KernelForTest') - ->disableOriginalConstructor() - ->setMethods(array('getContainerBuilder', 'prepareContainer', 'getCacheDir', 'getLogDir')) - ->getMock(); - $kernel->expects($this->any()) - ->method('getContainerBuilder') - ->will($this->returnValue($container)); - $kernel->expects($this->any()) - ->method('prepareContainer') - ->will($this->returnValue(null)); - $kernel->expects($this->any()) - ->method('getCacheDir') - ->will($this->returnValue(sys_get_temp_dir())); - $kernel->expects($this->any()) - ->method('getLogDir') - ->will($this->returnValue(sys_get_temp_dir())); - - $reflection = new \ReflectionClass(get_class($kernel)); - $method = $reflection->getMethod('buildContainer'); - $method->setAccessible(true); - $method->invoke($kernel); - - $found = false; - foreach ($container->getResources() as $resource) { - if ($resource instanceof EnvParametersResource) { - $found = true; - break; - } - } - - $this->assertTrue($found); - } - public function testBootKernelSeveralTimesOnlyInitializesBundlesOnce() { $kernel = $this->getKernel(array('initializeBundles', 'initializeContainer')); From 66621cc559b08889f11a559d47ecb4fd01183320 Mon Sep 17 00:00:00 2001 From: Oleg Voronkovich Date: Sun, 3 Sep 2017 20:54:53 +0300 Subject: [PATCH 0766/1099] [Dotenv] Add a BC break note --- src/Symfony/Component/Dotenv/CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Symfony/Component/Dotenv/CHANGELOG.md b/src/Symfony/Component/Dotenv/CHANGELOG.md index 2204282c26ca6..f04cc1bdf7bba 100644 --- a/src/Symfony/Component/Dotenv/CHANGELOG.md +++ b/src/Symfony/Component/Dotenv/CHANGELOG.md @@ -4,4 +4,5 @@ CHANGELOG 3.3.0 ----- + * [BC BREAK] Since v3.3.7, the latest Dotenv files override the previous ones. Real env vars are not affected and are not overridden. * added the component From 0caeeff48a5d09d4b1dcddb8d9ca0ee0a0c1cde5 Mon Sep 17 00:00:00 2001 From: Christophe Coevoet Date: Tue, 5 Sep 2017 13:23:06 +0200 Subject: [PATCH 0767/1099] Create directories recursively in the PHPUnit bridge --- src/Symfony/Bridge/PhpUnit/bin/simple-phpunit | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Bridge/PhpUnit/bin/simple-phpunit b/src/Symfony/Bridge/PhpUnit/bin/simple-phpunit index c19d30f4af9e6..a2747f3be2a09 100755 --- a/src/Symfony/Bridge/PhpUnit/bin/simple-phpunit +++ b/src/Symfony/Bridge/PhpUnit/bin/simple-phpunit @@ -41,7 +41,7 @@ $COMPOSER = file_exists($COMPOSER = $oldPwd.'/composer.phar') || ($COMPOSER = rt if (!file_exists("$PHPUNIT_DIR/phpunit-$PHPUNIT_VERSION/phpunit") || md5_file(__FILE__)."\n".getenv('SYMFONY_PHPUNIT_REMOVE') !== @file_get_contents("$PHPUNIT_DIR/.$PHPUNIT_VERSION.md5")) { // Build a standalone phpunit without symfony/yaml nor prophecy by default - @mkdir($PHPUNIT_DIR); + @mkdir($PHPUNIT_DIR, 0777, true); chdir($PHPUNIT_DIR); if (file_exists("phpunit-$PHPUNIT_VERSION")) { passthru(sprintf('\\' === DIRECTORY_SEPARATOR ? '(del /S /F /Q %s & rmdir %1$s) >nul': 'rm -rf %s', "phpunit-$PHPUNIT_VERSION")); From 76c42175b97f13a155282ee1f4591a59d35228b4 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Tue, 5 Sep 2017 17:39:41 +0200 Subject: [PATCH 0768/1099] [FrameworkBundle] Fix Di config to allow for more private services --- .../Compiler/CachePoolClearerPass.php | 27 ++++------------ .../Compiler/CachePoolPass.php | 32 +++++++++++++------ .../Compiler/TemplatingPass.php | 7 ++++ .../Compiler/UnusedTagsPass.php | 1 + .../FrameworkExtension.php | 6 ++-- .../FrameworkBundle/FrameworkBundle.php | 2 +- .../Resources/config/templating_debug.xml | 2 +- .../Resources/config/templating_php.xml | 7 +++- .../Templating/Helper/FormHelper.php | 2 +- .../Controller/SubRequestController.php | 4 +-- .../Tests/Functional/app/Session/config.yml | 5 +++ .../WebProfilerExtensionTest.php | 23 ++++++------- .../Component/Form/FormRendererInterface.php | 2 +- 13 files changed, 65 insertions(+), 55 deletions(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/CachePoolClearerPass.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/CachePoolClearerPass.php index 882f9b2dccf67..094712ded69d3 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/CachePoolClearerPass.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/CachePoolClearerPass.php @@ -27,29 +27,16 @@ final class CachePoolClearerPass implements CompilerPassInterface public function process(ContainerBuilder $container) { $container->getParameterBag()->remove('cache.prefix.seed'); - $poolsByClearer = array(); - $pools = array(); - foreach ($container->findTaggedServiceIds('cache.pool') as $id => $attributes) { - $pools[$id] = new Reference($id); - foreach (array_reverse($attributes) as $attr) { - if (isset($attr['clearer'])) { - $poolsByClearer[$attr['clearer']][$id] = $pools[$id]; - } - if (!empty($attr['unlazy'])) { - $container->getDefinition($id)->setLazy(false); - } - if (array_key_exists('clearer', $attr) || array_key_exists('unlazy', $attr)) { - break; + foreach ($container->findTaggedServiceIds('cache.pool.clearer') as $id => $attr) { + $clearer = $container->getDefinition($id); + $pools = array(); + foreach ($clearer->getArgument(0) as $id => $ref) { + if ($container->hasDefinition($id)) { + $pools[$id] = new Reference($id); } } - } - - $container->getDefinition('cache.global_clearer')->addArgument($pools); - - foreach ($poolsByClearer as $clearer => $pools) { - $clearer = $container->getDefinition($clearer); - $clearer->addArgument($pools); + $clearer->replaceArgument(0, $pools); } if (!$container->has('cache.annotations')) { diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/CachePoolPass.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/CachePoolPass.php index c63175e2d3ac0..6a633c7b25361 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/CachePoolPass.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/CachePoolPass.php @@ -37,6 +37,8 @@ public function process(ContainerBuilder $container) } $seed .= '.'.$container->getParameter('kernel.name').'.'.$container->getParameter('kernel.environment'); + $pools = array(); + $clearers = array(); $attributes = array( 'provider', 'namespace', @@ -47,10 +49,8 @@ public function process(ContainerBuilder $container) if ($pool->isAbstract()) { continue; } - $isLazy = $pool->isLazy(); while ($adapter instanceof ChildDefinition) { $adapter = $container->findDefinition($adapter->getParent()); - $isLazy = $isLazy || $adapter->isLazy(); if ($t = $adapter->getTag('cache.pool')) { $tags[0] += $t[0]; } @@ -82,17 +82,29 @@ public function process(ContainerBuilder $container) throw new InvalidArgumentException(sprintf('Invalid "cache.pool" tag for service "%s": accepted attributes are "clearer", "provider", "namespace" and "default_lifetime", found "%s".', $id, implode('", "', array_keys($tags[0])))); } - $attr = array(); if (null !== $clearer) { - $attr['clearer'] = $clearer; + $clearers[$clearer][$id] = new Reference($id, $container::IGNORE_ON_UNINITIALIZED_REFERENCE); } - if (!$isLazy) { - $pool->setLazy(true); - $attr['unlazy'] = true; - } - if ($attr) { - $pool->addTag('cache.pool', $attr); + + $pools[$id] = new Reference($id, $container::IGNORE_ON_UNINITIALIZED_REFERENCE); + } + + $clearer = 'cache.global_clearer'; + while ($container->hasAlias($clearer)) { + $clearer = (string) $container->getAlias($clearer); + } + if ($container->hasDefinition($clearer)) { + $clearers['cache.global_clearer'] = $pools; + } + + foreach ($clearers as $id => $pools) { + $clearer = $container->getDefinition($id); + if ($clearer instanceof ChilDefinition) { + $clearer->replaceArgument(0, $pools); + } else { + $clearer->setArgument(0, $pools); } + $clearer->addTag('cache.pool.clearer'); } } diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/TemplatingPass.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/TemplatingPass.php index 8e2e4d0dbfb34..b916a27a6d619 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/TemplatingPass.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/TemplatingPass.php @@ -15,6 +15,7 @@ use Symfony\Component\DependencyInjection\Alias; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; +use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\Templating\EngineInterface as ComponentEngineInterface; class TemplatingPass implements CompilerPassInterface @@ -31,16 +32,22 @@ public function process(ContainerBuilder $container) } if ($container->hasDefinition('templating.engine.php')) { + $refs = array(); $helpers = array(); foreach ($container->findTaggedServiceIds('templating.helper', true) as $id => $attributes) { if (isset($attributes[0]['alias'])) { $helpers[$attributes[0]['alias']] = $id; + $refs[$id] = new Reference($id); } } if (count($helpers) > 0) { $definition = $container->getDefinition('templating.engine.php'); $definition->addMethodCall('setHelpers', array($helpers)); + + if ($container->hasDefinition('templating.engine.php.helpers_locator')) { + $container->getDefinition('templating.engine.php.helpers_locator')->replaceArgument(0, $refs); + } } } } diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/UnusedTagsPass.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/UnusedTagsPass.php index ffc19c49dfeff..1ebb5562986ab 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/UnusedTagsPass.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/UnusedTagsPass.php @@ -22,6 +22,7 @@ class UnusedTagsPass implements CompilerPassInterface { private $whitelist = array( + 'cache.pool.clearer', 'console.command', 'container.service_locator', 'container.service_subscriber', diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php index 16f13ac79ad51..3b59ec9ef4583 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php @@ -597,15 +597,15 @@ private function registerWorkflowConfiguration(array $workflows, ContainerBuilde } // Create Workflow + $workflowId = sprintf('%s.%s', $type, $name); $workflowDefinition = new ChildDefinition(sprintf('%s.abstract', $type)); - $workflowDefinition->replaceArgument(0, $definitionDefinition); + $workflowDefinition->replaceArgument(0, new Reference(sprintf('%s.definition', $workflowId))); if (isset($markingStoreDefinition)) { $workflowDefinition->replaceArgument(1, $markingStoreDefinition); } $workflowDefinition->replaceArgument(3, $name); // Store to container - $workflowId = sprintf('%s.%s', $type, $name); $container->setDefinition($workflowId, $workflowDefinition); $container->setDefinition(sprintf('%s.definition', $workflowId), $definitionDefinition); @@ -680,7 +680,7 @@ private function registerDebugConfiguration(array $config, ContainerBuilder $con if (class_exists(Stopwatch::class)) { $container->register('debug.stopwatch', Stopwatch::class)->addArgument(true); - $container->setAlias(Stopwatch::class, 'debug.stopwatch'); + $container->setAlias(Stopwatch::class, new Alias('debug.stopwatch', false)); } $debug = $container->getParameter('kernel.debug'); diff --git a/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php b/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php index 47129136d7920..ba117ceeb82a2 100644 --- a/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php +++ b/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php @@ -106,7 +106,7 @@ public function build(ContainerBuilder $container) $container->addCompilerPass(new AddExpressionLanguageProvidersPass()); $this->addCompilerPassIfExists($container, TranslationExtractorPass::class); $this->addCompilerPassIfExists($container, TranslationDumperPass::class); - $container->addCompilerPass(new FragmentRendererPass(), PassConfig::TYPE_AFTER_REMOVING); + $container->addCompilerPass(new FragmentRendererPass()); $this->addCompilerPassIfExists($container, SerializerPass::class); $this->addCompilerPassIfExists($container, PropertyInfoPass::class); $container->addCompilerPass(new DataCollectorTranslatorPass()); diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/templating_debug.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/templating_debug.xml index cc478a03eb349..0bdfbe24ea3bd 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/templating_debug.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/templating_debug.xml @@ -9,7 +9,7 @@ - + diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/templating_php.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/templating_php.xml index 09a00c78e44a5..5eb7233592f65 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/templating_php.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/templating_php.xml @@ -9,12 +9,17 @@ - + %kernel.charset% + + + + + diff --git a/src/Symfony/Bundle/FrameworkBundle/Templating/Helper/FormHelper.php b/src/Symfony/Bundle/FrameworkBundle/Templating/Helper/FormHelper.php index 68d46c2c3facb..bc6c255f09d07 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Templating/Helper/FormHelper.php +++ b/src/Symfony/Bundle/FrameworkBundle/Templating/Helper/FormHelper.php @@ -226,7 +226,7 @@ public function block(FormView $view, $blockName, array $variables = array()) * Check the token in your action using the same CSRF token id. * * - * $csrfProvider = $this->get('security.csrf.token_generator'); + * // $csrfProvider being an instance of Symfony\Component\Security\Csrf\TokenGenerator\TokenGeneratorInterface * if (!$csrfProvider->isCsrfTokenValid('rm_user_'.$user->getId(), $token)) { * throw new \RuntimeException('CSRF attack detected.'); * } diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/TestBundle/Controller/SubRequestController.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/TestBundle/Controller/SubRequestController.php index 5df6e29590a5b..1df462992be30 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/TestBundle/Controller/SubRequestController.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/TestBundle/Controller/SubRequestController.php @@ -21,10 +21,8 @@ class SubRequestController implements ContainerAwareInterface { use ContainerAwareTrait; - public function indexAction() + public function indexAction($handler) { - $handler = $this->container->get('fragment.handler'); - $errorUrl = $this->generateUrl('subrequest_fragment_error', array('_locale' => 'fr', '_format' => 'json')); $altUrl = $this->generateUrl('subrequest_fragment', array('_locale' => 'fr', '_format' => 'json')); diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/Session/config.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/Session/config.yml index 65dd6c7fa91f1..ad6bdb691ca52 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/Session/config.yml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/Session/config.yml @@ -1,2 +1,7 @@ imports: - { resource: ./../config/default.yml } + +services: + Symfony\Bundle\FrameworkBundle\Tests\Functional\Bundle\TestBundle\Controller\SubRequestController: + tags: + - { name: controller.service_arguments, action: indexAction, argument: handler, id: fragment.handler } diff --git a/src/Symfony/Bundle/WebProfilerBundle/Tests/DependencyInjection/WebProfilerExtensionTest.php b/src/Symfony/Bundle/WebProfilerBundle/Tests/DependencyInjection/WebProfilerExtensionTest.php index af0573e5a362d..25e352e7124ce 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Tests/DependencyInjection/WebProfilerExtensionTest.php +++ b/src/Symfony/Bundle/WebProfilerBundle/Tests/DependencyInjection/WebProfilerExtensionTest.php @@ -17,7 +17,8 @@ use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\DependencyInjection\Reference; -use Symfony\Component\DependencyInjection\Dumper\PhpDumper; +use Symfony\Component\EventDispatcher\DependencyInjection\RegisterListenersPass; +use Symfony\Component\EventDispatcher\EventDispatcher; class WebProfilerExtensionTest extends TestCase { @@ -51,6 +52,7 @@ protected function setUp() $this->kernel = $this->getMockBuilder('Symfony\\Component\\HttpKernel\\KernelInterface')->getMock(); $this->container = new ContainerBuilder(); + $this->container->register('event_dispatcher', EventDispatcher::class); $this->container->register('router', $this->getMockClass('Symfony\\Component\\Routing\\RouterInterface')); $this->container->register('twig', 'Twig\Environment'); $this->container->register('twig_loader', 'Twig\Loader\ArrayLoader')->addArgument(array()); @@ -66,6 +68,7 @@ protected function setUp() ->addArgument(new Definition($this->getMockClass('Symfony\\Component\\HttpKernel\\Profiler\\ProfilerStorageInterface'))); $this->container->setParameter('data_collector.templates', array()); $this->container->set('kernel', $this->kernel); + $this->container->addCompilerPass(new RegisterListenersPass()); } protected function tearDown() @@ -88,7 +91,7 @@ public function testDefaultConfig($debug) $this->assertFalse($this->container->has('web_profiler.debug_toolbar')); - $this->assertSaneContainer($this->getDumpedContainer()); + $this->assertSaneContainer($this->getCompiledContainer()); } /** @@ -101,7 +104,7 @@ public function testToolbarConfig($toolbarEnabled, $interceptRedirects, $listene $this->assertSame($listenerInjected, $this->container->has('web_profiler.debug_toolbar')); - $this->assertSaneContainer($this->getDumpedContainer(), '', array('web_profiler.csp.handler')); + $this->assertSaneContainer($this->getCompiledContainer(), '', array('web_profiler.csp.handler')); if ($listenerInjected) { $this->assertSame($listenerEnabled, $this->container->get('web_profiler.debug_toolbar')->isEnabled()); @@ -118,19 +121,11 @@ public function getDebugModes() ); } - private function getDumpedContainer() + private function getCompiledContainer() { - static $i = 0; - $class = 'WebProfilerExtensionTestContainer'.$i++; - $this->container->compile(); + $this->container->set('kernel', $this->kernel); - $dumper = new PhpDumper($this->container); - eval('?>'.$dumper->dump(array('class' => $class))); - - $container = new $class(); - $container->set('kernel', $this->kernel); - - return $container; + return $this->container; } } diff --git a/src/Symfony/Component/Form/FormRendererInterface.php b/src/Symfony/Component/Form/FormRendererInterface.php index f0f51e4f59251..34c7822455c19 100644 --- a/src/Symfony/Component/Form/FormRendererInterface.php +++ b/src/Symfony/Component/Form/FormRendererInterface.php @@ -76,7 +76,7 @@ public function searchAndRenderBlock(FormView $view, $blockNameSuffix, array $va * Check the token in your action using the same token ID. * * - * $csrfProvider = $this->get('security.csrf.token_generator'); + * // $csrfProvider being an instance of Symfony\Component\Security\Csrf\TokenGenerator\TokenGeneratorInterface * if (!$csrfProvider->isCsrfTokenValid('rm_user_'.$user->getId(), $token)) { * throw new \RuntimeException('CSRF attack detected.'); * } From 3fdcb40df3bb5039022bce5581c31e6bac52c588 Mon Sep 17 00:00:00 2001 From: Yonel Ceruto Date: Fri, 1 Sep 2017 10:02:44 -0400 Subject: [PATCH 0769/1099] [TwigBridge] Show Twig's loader paths on debug:twig command --- .../Bridge/Twig/Command/DebugCommand.php | 52 ++++++++++++++++++- .../TwigBundle/Resources/config/console.xml | 1 + 2 files changed, 52 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Bridge/Twig/Command/DebugCommand.php b/src/Symfony/Bridge/Twig/Command/DebugCommand.php index da98feb7632bb..258387173a540 100644 --- a/src/Symfony/Bridge/Twig/Command/DebugCommand.php +++ b/src/Symfony/Bridge/Twig/Command/DebugCommand.php @@ -18,6 +18,7 @@ use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Style\SymfonyStyle; use Twig\Environment; +use Twig\Loader\FilesystemLoader; /** * Lists twig functions, filters, globals and tests present in the current project. @@ -29,11 +30,13 @@ class DebugCommand extends Command protected static $defaultName = 'debug:twig'; private $twig; + private $projectDir; /** * @param Environment $twig + * @param string|null $projectDir */ - public function __construct($twig = null) + public function __construct($twig = null, $projectDir = null) { if (!$twig instanceof Environment) { @trigger_error(sprintf('Passing a command name as the first argument of "%s" is deprecated since version 3.4 and will be removed in 4.0. If the command was registered by convention, make it a service instead.', __METHOD__), E_USER_DEPRECATED); @@ -46,6 +49,7 @@ public function __construct($twig = null) parent::__construct(); $this->twig = $twig; + $this->projectDir = $projectDir; } public function setTwigEnvironment(Environment $twig) @@ -120,6 +124,7 @@ protected function execute(InputInterface $input, OutputInterface $output) } } $data['tests'] = array_keys($data['tests']); + $data['loader_paths'] = $this->getLoaderPaths(); $io->writeln(json_encode($data)); return 0; @@ -145,9 +150,54 @@ protected function execute(InputInterface $input, OutputInterface $output) $io->listing($items); } + $rows = array(); + foreach ($this->getLoaderPaths() as $namespace => $paths) { + if (count($paths) > 1) { + $rows[] = array('', ''); + } + foreach ($paths as $path) { + $rows[] = array($namespace, '- '.$path); + $namespace = ''; + } + if (count($paths) > 1) { + $rows[] = array('', ''); + } + } + array_pop($rows); + $io->section('Loader Paths'); + $io->table(array('Namespace', 'Paths'), $rows); + return 0; } + private function getLoaderPaths() + { + if (!($loader = $this->twig->getLoader()) instanceof FilesystemLoader) { + return array(); + } + + $loaderPaths = array(); + foreach ($loader->getNamespaces() as $namespace) { + $paths = array_map(function ($path) use ($namespace) { + if (null !== $this->projectDir && 0 === strpos($path, $this->projectDir)) { + $path = ltrim(substr($path, strlen($this->projectDir)), DIRECTORY_SEPARATOR); + } + + return $path; + }, $loader->getPaths($namespace)); + + if (FilesystemLoader::MAIN_NAMESPACE === $namespace) { + $namespace = '(None)'; + } else { + $namespace = '@'.$namespace; + } + + $loaderPaths[$namespace] = $paths; + } + + return $loaderPaths; + } + private function getMetadata($type, $entity) { if ($type === 'globals') { diff --git a/src/Symfony/Bundle/TwigBundle/Resources/config/console.xml b/src/Symfony/Bundle/TwigBundle/Resources/config/console.xml index a8997823749fe..d716f309f451d 100644 --- a/src/Symfony/Bundle/TwigBundle/Resources/config/console.xml +++ b/src/Symfony/Bundle/TwigBundle/Resources/config/console.xml @@ -9,6 +9,7 @@ + %kernel.project_dir% From 9cadeb8af2986f00134a5107e368f32b876aef91 Mon Sep 17 00:00:00 2001 From: "Alexander M. Turek" Date: Tue, 5 Sep 2017 22:39:38 +0200 Subject: [PATCH 0770/1099] Don't use return on Assert::markTestSkipped. --- .../DependencyInjection/Tests/Loader/IniFileLoaderTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/DependencyInjection/Tests/Loader/IniFileLoaderTest.php b/src/Symfony/Component/DependencyInjection/Tests/Loader/IniFileLoaderTest.php index 003cd714b1fa9..d3c2dfc76fc5e 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Loader/IniFileLoaderTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Loader/IniFileLoaderTest.php @@ -51,7 +51,7 @@ public function testTypeConversions($key, $value, $supported) public function testTypeConversionsWithNativePhp($key, $value, $supported) { if (defined('HHVM_VERSION_ID')) { - return $this->markTestSkipped(); + $this->markTestSkipped(); } if (!$supported) { From f8afe02a49b46a28254be1a988761825c9bdd9fb Mon Sep 17 00:00:00 2001 From: Yonel Ceruto Date: Wed, 6 Sep 2017 08:10:51 -0400 Subject: [PATCH 0771/1099] Add help description to debug:form command --- src/Symfony/Component/Form/Command/DebugCommand.php | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/Symfony/Component/Form/Command/DebugCommand.php b/src/Symfony/Component/Form/Command/DebugCommand.php index 3cb4904ab3a7d..d646ffa154305 100644 --- a/src/Symfony/Component/Form/Command/DebugCommand.php +++ b/src/Symfony/Component/Form/Command/DebugCommand.php @@ -51,6 +51,16 @@ protected function configure() new InputOption('format', null, InputOption::VALUE_REQUIRED, 'The output format (txt or json)', 'txt'), )) ->setDescription('Displays form type information') + ->setHelp(<<<'EOF' +The %command.name% command displays information about a form type. + +Either the fully-qualified class name or the short class name can be used: + + php %command.full_name% Symfony\Component\Form\Extension\Core\Type\ChoiceType + php %command.full_name% ChoiceType + +EOF + ) ; } From cfc9346f660d6c8917a6e60a41935268e73a43b7 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Wed, 6 Sep 2017 10:30:21 +0200 Subject: [PATCH 0772/1099] [travis] update to trusty --- .travis.yml | 8 ++------ appveyor.yml | 6 +++--- src/Symfony/Bundle/SecurityBundle/composer.json | 16 ++++++++-------- .../Component/HttpFoundation/JsonResponse.php | 4 ++-- .../HttpFoundation/Tests/JsonResponseTest.php | 7 +++++-- 5 files changed, 20 insertions(+), 21 deletions(-) diff --git a/.travis.yml b/.travis.yml index b7ce58bd8ffbb..e01ab63ab3227 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,6 @@ language: php -dist: precise +dist: trusty sudo: false git: @@ -13,17 +13,14 @@ addons: env: global: - - MIN_PHP=5.3.9 + - MIN_PHP=5.4.9 - SYMFONY_PROCESS_PHP_TEST_BINARY=~/.phpenv/versions/5.6/bin/php matrix: include: - # Use the newer stack for HHVM as HHVM does not support Precise anymore since a long time and so Precise has an outdated version - php: hhvm-3.18 sudo: required - dist: trusty group: edge - - php: 5.3 - php: 5.4 - php: 5.5 - php: 5.6 @@ -99,7 +96,6 @@ before_install: echo opcache.enable_cli = 1 >> $INI echo hhvm.jit = 0 >> $INI echo apc.enable_cli = 1 >> $INI - echo extension = ldap.so >> $INI [[ $PHP = 5.* ]] && echo extension = memcache.so >> $INI if [[ $PHP = 5.* ]]; then echo extension = mongo.so >> $INI diff --git a/appveyor.yml b/appveyor.yml index ae43082f82fd8..6d869967263bd 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -17,8 +17,8 @@ init: install: - mkdir c:\php && cd c:\php - appveyor DownloadFile https://raw.githubusercontent.com/symfony/binary-utils/master/cacert.pem - - appveyor DownloadFile https://github.com/symfony/binary-utils/releases/download/v0.1/php-5.3.11-nts-Win32-VC9-x86.zip - - 7z x php-5.3.11-nts-Win32-VC9-x86.zip -y >nul + - appveyor DownloadFile https://github.com/symfony/binary-utils/releases/download/v0.1/php-5.3.9-nts-Win32-VC9-x86.zip + - 7z x php-5.3.9-nts-Win32-VC9-x86.zip -y >nul - appveyor DownloadFile https://raw.githubusercontent.com/symfony/binary-utils/master/ICU-51.2-dlls.zip - 7z x ICU-51.2-dlls.zip -y >nul - appveyor DownloadFile https://github.com/symfony/binary-utils/releases/download/v0.1/php-7.1.3-Win32-VC14-x86.zip @@ -61,7 +61,7 @@ test_script: - cd c:\php && 7z x php-7.1.3-Win32-VC14-x86.zip -y >nul && copy /Y php.ini-min php.ini - cd c:\projects\symfony - php phpunit src\Symfony --exclude-group benchmark,intl-data || SET X=!errorlevel! - - cd c:\php && 7z x php-5.3.11-nts-Win32-VC9-x86.zip -y >nul && copy /Y php.ini-min php.ini + - cd c:\php && 7z x php-5.3.9-nts-Win32-VC9-x86.zip -y >nul && copy /Y php.ini-min php.ini - cd c:\projects\symfony - SET SYMFONY_PHPUNIT_SKIPPED_TESTS=phpunit.skipped - php phpunit src\Symfony --exclude-group benchmark,intl-data || SET X=!errorlevel! diff --git a/src/Symfony/Bundle/SecurityBundle/composer.json b/src/Symfony/Bundle/SecurityBundle/composer.json index 6d6073f7f0bc3..69091f5269c32 100644 --- a/src/Symfony/Bundle/SecurityBundle/composer.json +++ b/src/Symfony/Bundle/SecurityBundle/composer.json @@ -23,20 +23,20 @@ "symfony/http-kernel": "~2.7" }, "require-dev": { - "symfony/browser-kit": "~2.4", + "symfony/browser-kit": "~2.7", "symfony/console": "~2.7", - "symfony/css-selector": "^2.0.5", - "symfony/dependency-injection": "^2.6.6", - "symfony/dom-crawler": "^2.0.5", + "symfony/css-selector": "^2.7", + "symfony/dependency-injection": "^2.7", + "symfony/dom-crawler": "^2.7", "symfony/form": "~2.7.15|^2.8.8", "symfony/framework-bundle": "~2.7.25|^2.8.18", "symfony/http-foundation": "~2.7", "symfony/twig-bundle": "~2.7", "symfony/twig-bridge": "^2.7.4", - "symfony/process": "^2.0.5", - "symfony/validator": "~2.5", - "symfony/yaml": "^2.0.5", - "symfony/expression-language": "~2.6", + "symfony/process": "^2.7", + "symfony/validator": "~2.7", + "symfony/yaml": "^2.7", + "symfony/expression-language": "~2.7", "doctrine/doctrine-bundle": "~1.2", "twig/twig": "~1.34|~2.4", "ircmaxell/password-compat": "~1.0" diff --git a/src/Symfony/Component/HttpFoundation/JsonResponse.php b/src/Symfony/Component/HttpFoundation/JsonResponse.php index c6e0ba6541061..621c8410c2c21 100644 --- a/src/Symfony/Component/HttpFoundation/JsonResponse.php +++ b/src/Symfony/Component/HttpFoundation/JsonResponse.php @@ -121,7 +121,7 @@ public function setData($data = array()) $data = json_encode($data, $this->encodingOptions); } else { try { - if (\PHP_VERSION_ID < 50400) { + if (!interface_exists('JsonSerializable', false)) { // PHP 5.3 triggers annoying warnings for some // types that can't be serialized as JSON (INF, resources, etc.) // but doesn't provide the JsonSerializable interface. @@ -153,7 +153,7 @@ public function setData($data = array()) if (\PHP_VERSION_ID < 50500) { restore_error_handler(); } - if (\PHP_VERSION_ID >= 50400 && 'Exception' === get_class($e) && 0 === strpos($e->getMessage(), 'Failed calling ')) { + if (interface_exists('JsonSerializable', false) && 'Exception' === get_class($e) && 0 === strpos($e->getMessage(), 'Failed calling ')) { throw $e->getPrevious() ?: $e; } throw $e; diff --git a/src/Symfony/Component/HttpFoundation/Tests/JsonResponseTest.php b/src/Symfony/Component/HttpFoundation/Tests/JsonResponseTest.php index 8156da06939e4..e15505cc6948e 100644 --- a/src/Symfony/Component/HttpFoundation/Tests/JsonResponseTest.php +++ b/src/Symfony/Component/HttpFoundation/Tests/JsonResponseTest.php @@ -206,10 +206,13 @@ public function testSetContent() /** * @expectedException \Exception * @expectedExceptionMessage This error is expected - * @requires PHP 5.4 */ public function testSetContentJsonSerializeError() { + if (!interface_exists('JsonSerializable', false)) { + $this->markTestSkipped('JsonSerializable is required.'); + } + $serializable = new JsonSerializableObject(); JsonResponse::create($serializable); @@ -224,7 +227,7 @@ public function testSetComplexCallback() } } -if (interface_exists('JsonSerializable')) { +if (interface_exists('JsonSerializable', false)) { class JsonSerializableObject implements \JsonSerializable { public function jsonSerialize() From a0f9f2c53739ef336064e9e3d5ecd0c0d2046418 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Tue, 5 Sep 2017 19:39:30 +0200 Subject: [PATCH 0773/1099] check permissions if dump target dir is missing `is_dir()` returns `false` if the parent directory misses the executable bit even when the directory itself is present. --- src/Symfony/Component/Filesystem/Filesystem.php | 10 ++++++++++ .../Filesystem/Tests/FilesystemTest.php | 16 ++++++++++++++++ .../Filesystem/Tests/FilesystemTestCase.php | 1 + 3 files changed, 27 insertions(+) diff --git a/src/Symfony/Component/Filesystem/Filesystem.php b/src/Symfony/Component/Filesystem/Filesystem.php index bc2e3dcc2d897..bbef48b466885 100644 --- a/src/Symfony/Component/Filesystem/Filesystem.php +++ b/src/Symfony/Component/Filesystem/Filesystem.php @@ -532,6 +532,16 @@ public function dumpFile($filename, $content, $mode = 0666) $dir = dirname($filename); if (!is_dir($dir)) { + $oldCwd = getcwd(); + + if (!@chdir(dirname($dir))) { + // When the parent directory misses the executable permission bit, we are unable to enter it and thus + // cannot check if the target directory exists. + throw new IOException(sprintf('Unable to detect if the target directory "%s" exists.', $dir)); + } + + chdir($oldCwd); + $this->mkdir($dir); } diff --git a/src/Symfony/Component/Filesystem/Tests/FilesystemTest.php b/src/Symfony/Component/Filesystem/Tests/FilesystemTest.php index b7bdfac4155e0..44eeceabd9f49 100644 --- a/src/Symfony/Component/Filesystem/Tests/FilesystemTest.php +++ b/src/Symfony/Component/Filesystem/Tests/FilesystemTest.php @@ -1102,6 +1102,22 @@ public function testDumpKeepsExistingPermissionsWhenOverwritingAnExistingFile() $this->assertFilePermissions(745, $filename); } + /** + * @expectedException \Symfony\Component\Filesystem\Exception\IOException + * @expectedExceptionMessageRegExp /^Unable to detect if the target directory ".*" exists\.$/ + */ + public function testDumpFailsWithExceptionIfExecutablePermissionsForTheParentDirectoryAreMissing() + { + $this->markAsSkippedIfChmodIsMissing(); + + $target = $this->workspace.DIRECTORY_SEPARATOR.'foo'; + $file = $target.DIRECTORY_SEPARATOR.'foobar'; + mkdir($target); + chmod($this->workspace, 0666); + + $this->filesystem->dumpFile($file, 'baz'); + } + public function testCopyShouldKeepExecutionPermission() { $this->markAsSkippedIfChmodIsMissing(); diff --git a/src/Symfony/Component/Filesystem/Tests/FilesystemTestCase.php b/src/Symfony/Component/Filesystem/Tests/FilesystemTestCase.php index 5586a00547a68..47598b29427da 100644 --- a/src/Symfony/Component/Filesystem/Tests/FilesystemTestCase.php +++ b/src/Symfony/Component/Filesystem/Tests/FilesystemTestCase.php @@ -61,6 +61,7 @@ protected function tearDown() $this->longPathNamesWindows = array(); } + chmod($this->workspace, 0777); $this->filesystem->remove($this->workspace); umask($this->umask); } From d1fe4153a16489d153e5660c8407789929d32ef1 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Wed, 6 Sep 2017 18:53:48 +0200 Subject: [PATCH 0774/1099] [HttpFoundation] Fix logic when JsonSerializable is missing --- .../Component/HttpFoundation/JsonResponse.php | 33 ++++++++++--------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/src/Symfony/Component/HttpFoundation/JsonResponse.php b/src/Symfony/Component/HttpFoundation/JsonResponse.php index 621c8410c2c21..8837175df8d10 100644 --- a/src/Symfony/Component/HttpFoundation/JsonResponse.php +++ b/src/Symfony/Component/HttpFoundation/JsonResponse.php @@ -127,30 +127,31 @@ public function setData($data = array()) // but doesn't provide the JsonSerializable interface. set_error_handler(function () { return false; }); $data = @json_encode($data, $this->encodingOptions); - } else { + restore_error_handler(); + } elseif (\PHP_VERSION_ID < 50500) { // PHP 5.4 and up wrap exceptions thrown by JsonSerializable // objects in a new exception that needs to be removed. // Fortunately, PHP 5.5 and up do not trigger any warning anymore. - if (\PHP_VERSION_ID < 50500) { - // Clear json_last_error() - json_encode(null); - $errorHandler = set_error_handler('var_dump'); - restore_error_handler(); - set_error_handler(function () use ($errorHandler) { - if (JSON_ERROR_NONE === json_last_error()) { - return $errorHandler && false !== call_user_func_array($errorHandler, func_get_args()); - } - }); - } - + // Clear json_last_error() + json_encode(null); + $errorHandler = set_error_handler('var_dump'); + restore_error_handler(); + set_error_handler(function () use ($errorHandler) { + if (JSON_ERROR_NONE === json_last_error()) { + return $errorHandler && false !== call_user_func_array($errorHandler, func_get_args()); + } + }); + $data = json_encode($data, $this->encodingOptions); + restore_error_handler(); + } else { $data = json_encode($data, $this->encodingOptions); } - - if (\PHP_VERSION_ID < 50500) { + } catch (\Error $e) { + if (\PHP_VERSION_ID < 50500 || !interface_exists('JsonSerializable', false)) { restore_error_handler(); } } catch (\Exception $e) { - if (\PHP_VERSION_ID < 50500) { + if (\PHP_VERSION_ID < 50500 || !interface_exists('JsonSerializable', false)) { restore_error_handler(); } if (interface_exists('JsonSerializable', false) && 'Exception' === get_class($e) && 0 === strpos($e->getMessage(), 'Failed calling ')) { From e4ce14d0737495ab76d3d580b79c9c8e5be6bf53 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Wed, 6 Sep 2017 19:03:33 +0200 Subject: [PATCH 0775/1099] [travis] add ldap.so for php70 --- .travis.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.travis.yml b/.travis.yml index e01ab63ab3227..1d31503dcbd77 100644 --- a/.travis.yml +++ b/.travis.yml @@ -120,6 +120,11 @@ before_install: - | # Install extra PHP extensions + if [[ ! $skip && $PHP = 7.0 ]]; then + wget https://github.com/symfony/binary-utils/releases/download/v0.1/ldap-php70.tar.bz2 + tar -xjf ldap-php70.tar.bz2 + echo extension = $(pwd)/ldap.so >> $INI + fi if [[ ! $skip && $PHP = 5.* ]]; then ([[ $deps ]] || tfold ext.symfony_debug 'cd src/Symfony/Component/Debug/Resources/ext && phpize && ./configure && make && echo extension = $(pwd)/modules/symfony_debug.so >> '"$INI") && tfold ext.memcached pecl install -f memcached-2.1.0 && From 07933655e868303a46db98475162aed9c872e500 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Wed, 6 Sep 2017 19:21:48 +0200 Subject: [PATCH 0776/1099] [travis] fix minor php7.0 version --- .travis.yml | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/.travis.yml b/.travis.yml index c5aa9c01c74ff..a9b4bb229554e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -25,7 +25,7 @@ matrix: group: edge - php: 5.5 - php: 5.6 - - php: 7.0 + - php: 7.0.8 env: deps=high - php: 7.1 env: deps=low @@ -128,7 +128,7 @@ before_install: - | # Install extra PHP extensions - if [[ ! $skip && $PHP = 7.0 ]]; then + if [[ ! $skip && $PHP = 7.0.* ]]; then wget https://github.com/symfony/binary-utils/releases/download/v0.1/ldap-php70.tar.bz2 tar -xjf ldap-php70.tar.bz2 echo extension = $(pwd)/ldap.so >> $INI @@ -197,10 +197,7 @@ install: elif [[ $deps = high ]]; then echo "$COMPONENTS" | parallel --gnu -j10% "tfold {} 'cd {} && $COMPOSER_UP && $PHPUNIT_X$LEGACY'" elif [[ $deps = low ]]; then - echo "$COMPONENTS" | parallel --gnu -j10% "tfold {} 'cd {} && $COMPOSER_UP --prefer-lowest --prefer-stable && $PHPUNIT_X'" && - # Test the PhpUnit bridge on PHP 5.3, using the original phpunit script - tfold src/Symfony/Bridge/PhpUnit \ - "cd src/Symfony/Bridge/PhpUnit && wget https://phar.phpunit.de/phpunit-4.8.phar && phpenv global 5.3 && composer update --no-progress --ansi && php phpunit-4.8.phar" + echo "$COMPONENTS" | parallel --gnu -j10% "tfold {} 'cd {} && $COMPOSER_UP --prefer-lowest --prefer-stable && $PHPUNIT_X'" elif [[ $PHP = hhvm* ]]; then $PHPUNIT --exclude-group benchmark,intl-data else From 73cdb68308670ea6e9caede76738aa31adbcf8b7 Mon Sep 17 00:00:00 2001 From: Yonel Ceruto Date: Wed, 6 Sep 2017 15:05:48 -0400 Subject: [PATCH 0777/1099] Get KERNEL_CLASS through $_ENV too --- src/Symfony/Bundle/FrameworkBundle/Test/KernelTestCase.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/Test/KernelTestCase.php b/src/Symfony/Bundle/FrameworkBundle/Test/KernelTestCase.php index 26781cdf2285c..af8f4300f2961 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Test/KernelTestCase.php +++ b/src/Symfony/Bundle/FrameworkBundle/Test/KernelTestCase.php @@ -106,8 +106,9 @@ private static function getPhpUnitCliConfigArgument() */ protected static function getKernelClass() { - if (isset($_SERVER['KERNEL_CLASS'])) { - if (!class_exists($class = $_SERVER['KERNEL_CLASS'])) { + if (isset($_SERVER['KERNEL_CLASS']) || isset($_ENV['KERNEL_CLASS'])) { + $class = isset($_SERVER['KERNEL_CLASS']) ? $_SERVER['KERNEL_CLASS'] : $_ENV['KERNEL_CLASS']; + if (!class_exists($class)) { throw new \RuntimeException(sprintf('Class "%s" doesn\'t exist or cannot be autoloaded. Check that the KERNEL_CLASS value in phpunit.xml matches the fully-qualified class name of your Kernel or override the %s::createKernel() method.', $class, static::class)); } From 8015ad60ccf07b8a27c251197717c53fde5ff472 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Wed, 6 Sep 2017 21:47:44 +0200 Subject: [PATCH 0778/1099] Fix merge --- .../Console/Tests/Fixtures/application_renderexception2.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/Console/Tests/Fixtures/application_renderexception2.txt b/src/Symfony/Component/Console/Tests/Fixtures/application_renderexception2.txt index 9d0cacb81aedc..457e6df46c0a9 100644 --- a/src/Symfony/Component/Console/Tests/Fixtures/application_renderexception2.txt +++ b/src/Symfony/Component/Console/Tests/Fixtures/application_renderexception2.txt @@ -1,5 +1,5 @@ -In ArrayInput.php line 172: +In ArrayInput.php line 178: The "--foo" option does not exist. From 367c4d981064170000d4799da9606ec69812c6bf Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Wed, 6 Sep 2017 22:50:21 +0200 Subject: [PATCH 0779/1099] Fix deps=low tests --- .../Tests/DependencyInjection/WebProfilerExtensionTest.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Bundle/WebProfilerBundle/Tests/DependencyInjection/WebProfilerExtensionTest.php b/src/Symfony/Bundle/WebProfilerBundle/Tests/DependencyInjection/WebProfilerExtensionTest.php index 25e352e7124ce..cc229cd37fea9 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Tests/DependencyInjection/WebProfilerExtensionTest.php +++ b/src/Symfony/Bundle/WebProfilerBundle/Tests/DependencyInjection/WebProfilerExtensionTest.php @@ -18,7 +18,7 @@ use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\EventDispatcher\DependencyInjection\RegisterListenersPass; -use Symfony\Component\EventDispatcher\EventDispatcher; +use Symfony\Component\EventDispatcher\ContainerAwareEventDispatcher; class WebProfilerExtensionTest extends TestCase { @@ -52,7 +52,7 @@ protected function setUp() $this->kernel = $this->getMockBuilder('Symfony\\Component\\HttpKernel\\KernelInterface')->getMock(); $this->container = new ContainerBuilder(); - $this->container->register('event_dispatcher', EventDispatcher::class); + $this->container->register('event_dispatcher', ContainerAwareEventDispatcher::class)->addArgument(new Reference('service_container')); $this->container->register('router', $this->getMockClass('Symfony\\Component\\Routing\\RouterInterface')); $this->container->register('twig', 'Twig\Environment'); $this->container->register('twig_loader', 'Twig\Loader\ArrayLoader')->addArgument(array()); From 2fde0942ace81ae5f4481cd9a0a7998c42e9f10e Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Wed, 6 Sep 2017 23:01:01 +0200 Subject: [PATCH 0780/1099] fix the fix --- .../Tests/DependencyInjection/WebProfilerExtensionTest.php | 4 ++-- src/Symfony/Bundle/WebProfilerBundle/composer.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Bundle/WebProfilerBundle/Tests/DependencyInjection/WebProfilerExtensionTest.php b/src/Symfony/Bundle/WebProfilerBundle/Tests/DependencyInjection/WebProfilerExtensionTest.php index cc229cd37fea9..25e352e7124ce 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Tests/DependencyInjection/WebProfilerExtensionTest.php +++ b/src/Symfony/Bundle/WebProfilerBundle/Tests/DependencyInjection/WebProfilerExtensionTest.php @@ -18,7 +18,7 @@ use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\EventDispatcher\DependencyInjection\RegisterListenersPass; -use Symfony\Component\EventDispatcher\ContainerAwareEventDispatcher; +use Symfony\Component\EventDispatcher\EventDispatcher; class WebProfilerExtensionTest extends TestCase { @@ -52,7 +52,7 @@ protected function setUp() $this->kernel = $this->getMockBuilder('Symfony\\Component\\HttpKernel\\KernelInterface')->getMock(); $this->container = new ContainerBuilder(); - $this->container->register('event_dispatcher', ContainerAwareEventDispatcher::class)->addArgument(new Reference('service_container')); + $this->container->register('event_dispatcher', EventDispatcher::class); $this->container->register('router', $this->getMockClass('Symfony\\Component\\Routing\\RouterInterface')); $this->container->register('twig', 'Twig\Environment'); $this->container->register('twig_loader', 'Twig\Loader\ArrayLoader')->addArgument(array()); diff --git a/src/Symfony/Bundle/WebProfilerBundle/composer.json b/src/Symfony/Bundle/WebProfilerBundle/composer.json index b7e2014c97348..c49d793016e04 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/composer.json +++ b/src/Symfony/Bundle/WebProfilerBundle/composer.json @@ -32,7 +32,7 @@ }, "conflict": { "symfony/dependency-injection": "<3.3", - "symfony/event-dispatcher": "<3.2", + "symfony/event-dispatcher": "<3.3", "symfony/var-dumper": "<3.3" }, "autoload": { From cf11fb9652f6c41c986d740a20429a1523cb65a5 Mon Sep 17 00:00:00 2001 From: Yonel Ceruto Date: Wed, 6 Sep 2017 18:24:46 -0400 Subject: [PATCH 0781/1099] Get KERNEL_DIR through $_ENV too for KernelTestCase --- src/Symfony/Bundle/FrameworkBundle/Test/KernelTestCase.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/Test/KernelTestCase.php b/src/Symfony/Bundle/FrameworkBundle/Test/KernelTestCase.php index 351a8cc80a15d..5dadca83f2e1b 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Test/KernelTestCase.php +++ b/src/Symfony/Bundle/FrameworkBundle/Test/KernelTestCase.php @@ -105,8 +105,8 @@ private static function getPhpUnitCliConfigArgument() */ protected static function getKernelClass() { - if (isset($_SERVER['KERNEL_DIR'])) { - $dir = $_SERVER['KERNEL_DIR']; + if (isset($_SERVER['KERNEL_DIR']) || isset($_ENV['KERNEL_DIR'])) { + $dir = isset($_SERVER['KERNEL_DIR']) ? $_SERVER['KERNEL_DIR'] : $_ENV['KERNEL_DIR']; if (!is_dir($dir)) { $phpUnitDir = static::getPhpUnitXmlDir(); From 1f92e459db0efd2576eaa63a4fa0fe39e68b32dd Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Sat, 22 Oct 2016 18:25:15 +0200 Subject: [PATCH 0782/1099] [DI] Allow processing env vars --- .../FrameworkExtension.php | 3 + .../DependencyInjection/CHANGELOG.md | 1 + .../Compiler/PassConfig.php | 1 + .../Compiler/RegisterEnvVarProcessorsPass.php | 72 +++++++ .../DependencyInjection/Container.php | 37 +++- .../DependencyInjection/ContainerBuilder.php | 14 +- .../DependencyInjection/Dumper/PhpDumper.php | 15 +- .../DependencyInjection/EnvVarProcessor.php | 160 ++++++++++++++ .../EnvVarProcessorInterface.php | 38 ++++ .../EnvPlaceholderParameterBag.php | 21 +- .../RegisterEnvVarProcessorsPassTest.php | 75 +++++++ .../Tests/ContainerBuilderTest.php | 64 ++++++ .../Tests/Dumper/PhpDumperTest.php | 110 +++++++++- .../Tests/Fixtures/array.json | 1 + .../Tests/Fixtures/php/services26.php | 21 +- .../Fixtures/php/services_base64_env.php | 167 +++++++++++++++ .../Tests/Fixtures/php/services_rot13_env.php | 196 ++++++++++++++++++ .../Tests/Fixtures/yaml/services26.yml | 6 + 18 files changed, 977 insertions(+), 25 deletions(-) create mode 100644 src/Symfony/Component/DependencyInjection/Compiler/RegisterEnvVarProcessorsPass.php create mode 100644 src/Symfony/Component/DependencyInjection/EnvVarProcessor.php create mode 100644 src/Symfony/Component/DependencyInjection/EnvVarProcessorInterface.php create mode 100644 src/Symfony/Component/DependencyInjection/Tests/Compiler/RegisterEnvVarProcessorsPassTest.php create mode 100644 src/Symfony/Component/DependencyInjection/Tests/Fixtures/array.json create mode 100644 src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_base64_env.php create mode 100644 src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_rot13_env.php diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php index d3d10fd97f4af..72d66442c62c9 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php @@ -36,6 +36,7 @@ use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\DependencyInjection\Definition; +use Symfony\Component\DependencyInjection\EnvVarProcessorInterface; use Symfony\Component\DependencyInjection\Exception\LogicException; use Symfony\Component\DependencyInjection\Loader\XmlFileLoader; use Symfony\Component\DependencyInjection\Reference; @@ -283,6 +284,8 @@ public function load(array $configs, ContainerBuilder $container) ->addTag('console.command'); $container->registerForAutoconfiguration(ResourceCheckerInterface::class) ->addTag('config_cache.resource_checker'); + $container->registerForAutoconfiguration(EnvVarProcessorInterface::class) + ->addTag('container.env_var_processor'); $container->registerForAutoconfiguration(ServiceSubscriberInterface::class) ->addTag('container.service_subscriber'); $container->registerForAutoconfiguration(ArgumentValueResolverInterface::class) diff --git a/src/Symfony/Component/DependencyInjection/CHANGELOG.md b/src/Symfony/Component/DependencyInjection/CHANGELOG.md index 4232369e2e007..09bc2ce361e36 100644 --- a/src/Symfony/Component/DependencyInjection/CHANGELOG.md +++ b/src/Symfony/Component/DependencyInjection/CHANGELOG.md @@ -4,6 +4,7 @@ CHANGELOG 3.4.0 ----- + * added `EnvVarProcessorInterface` and corresponding "container.env_var_processor" tag for processing env vars * added support for ignore-on-uninitialized references * deprecated service auto-registration while autowiring * deprecated the ability to check for the initialization of a private service with the `Container::initialized()` method diff --git a/src/Symfony/Component/DependencyInjection/Compiler/PassConfig.php b/src/Symfony/Component/DependencyInjection/Compiler/PassConfig.php index 184c7b25a0883..63659ed8927c2 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/PassConfig.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/PassConfig.php @@ -43,6 +43,7 @@ public function __construct() 100 => array( $resolveClassPass = new ResolveClassPass(), new ResolveInstanceofConditionalsPass(), + new RegisterEnvVarProcessorsPass(), ), ); diff --git a/src/Symfony/Component/DependencyInjection/Compiler/RegisterEnvVarProcessorsPass.php b/src/Symfony/Component/DependencyInjection/Compiler/RegisterEnvVarProcessorsPass.php new file mode 100644 index 0000000000000..247f5b69ad40f --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Compiler/RegisterEnvVarProcessorsPass.php @@ -0,0 +1,72 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Compiler; + +use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\EnvVarProcessorInterface; +use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; +use Symfony\Component\DependencyInjection\ParameterBag\EnvPlaceholderParameterBag; +use Symfony\Component\DependencyInjection\ServiceLocator; +use Symfony\Component\DependencyInjection\Reference; + +/** + * Creates the container.env_var_processors_locator service. + * + * @author Nicolas Grekas + */ +class RegisterEnvVarProcessorsPass implements CompilerPassInterface +{ + private static $allowedTypes = array('array', 'bool', 'float', 'int', 'string'); + + public function process(ContainerBuilder $container) + { + $bag = $container->getParameterBag(); + $types = array(); + $processors = array(); + foreach ($container->findTaggedServiceIds('container.env_var_processor') as $id => $tags) { + foreach ($tags as $attr) { + if (!$r = $container->getReflectionClass($class = $container->getDefinition($id)->getClass())) { + throw new InvalidArgumentException(sprintf('Class "%s" used for service "%s" cannot be found.', $class, $id)); + } elseif (!$r->isSubclassOf(EnvVarProcessorInterface::class)) { + throw new InvalidArgumentException(sprintf('Service "%s" must implement interface "%s".', $id, EnvVarProcessorInterface::class)); + } + foreach ($class::getProvidedTypes() as $prefix => $type) { + $processors[$prefix] = new ServiceClosureArgument(new Reference($id)); + $types[$prefix] = self::validateProvidedTypes($type, $class); + } + } + } + + if ($processors) { + if ($bag instanceof EnvPlaceholderParameterBag) { + $bag->setProvidedTypes($types); + } + $container->register('container.env_var_processors_locator', ServiceLocator::class) + ->setArguments(array($processors)) + ; + } + } + + private static function validateProvidedTypes($types, $class) + { + $types = explode('|', $types); + + foreach ($types as $type) { + if (!in_array($type, self::$allowedTypes)) { + throw new InvalidArgumentException(sprintf('Invalid type "%s" returned by "%s::getProvidedTypes()", expected one of "%s".', $type, $class, implode('", "', self::$allowedTypes))); + } + } + + return $types; + } +} diff --git a/src/Symfony/Component/DependencyInjection/Container.php b/src/Symfony/Component/DependencyInjection/Container.php index ac423bd4a4739..75ba8a2bdb630 100644 --- a/src/Symfony/Component/DependencyInjection/Container.php +++ b/src/Symfony/Component/DependencyInjection/Container.php @@ -13,6 +13,7 @@ use Symfony\Component\DependencyInjection\Exception\EnvNotFoundException; use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; +use Symfony\Component\DependencyInjection\Exception\ParameterCircularReferenceException; use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException; use Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException; use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface; @@ -48,6 +49,7 @@ class Container implements ResettableContainerInterface protected $methodMap = array(); protected $aliases = array(); protected $loading = array(); + protected $resolving = array(); /** * @internal @@ -62,6 +64,7 @@ class Container implements ResettableContainerInterface private $underscoreMap = array('_' => '', '.' => '_', '\\' => '_'); private $envCache = array(); private $compiled = false; + private $getEnv; /** * @param ParameterBagInterface $parameterBag A ParameterBagInterface instance @@ -438,23 +441,37 @@ protected function load($file) */ protected function getEnv($name) { + if (isset($this->resolving[$envName = "env($name)"])) { + throw new ParameterCircularReferenceException(array_keys($this->resolving)); + } if (isset($this->envCache[$name]) || array_key_exists($name, $this->envCache)) { return $this->envCache[$name]; } - if (isset($_SERVER[$name]) && 0 !== strpos($name, 'HTTP_')) { - return $this->envCache[$name] = $_SERVER[$name]; - } - if (isset($_ENV[$name])) { - return $this->envCache[$name] = $_ENV[$name]; + if (!$this->has($id = 'container.env_var_processors_locator')) { + $this->set($id, new ServiceLocator(array())); } - if (false !== ($env = getenv($name)) && null !== $env) { // null is a possible value because of thread safety issues - return $this->envCache[$name] = $env; + if (!$this->getEnv) { + $this->getEnv = new \ReflectionMethod($this, __FUNCTION__); + $this->getEnv->setAccessible(true); + $this->getEnv = $this->getEnv->getClosure($this); } - if (!$this->hasParameter("env($name)")) { - throw new EnvNotFoundException($name); + $processors = $this->get($id); + + if (false !== $i = strpos($name, ':')) { + $prefix = substr($name, 0, $i); + $localName = substr($name, 1 + $i); + } else { + $prefix = 'string'; + $localName = $name; } + $processor = $processors->has($prefix) ? $processors->get($prefix) : new EnvVarProcessor($this); - return $this->envCache[$name] = $this->getParameter("env($name)"); + $this->resolving[$envName] = true; + try { + return $this->envCache[$name] = $processor->getEnv($prefix, $localName, $this->getEnv); + } finally { + unset($this->resolving[$envName]); + } } /** diff --git a/src/Symfony/Component/DependencyInjection/ContainerBuilder.php b/src/Symfony/Component/DependencyInjection/ContainerBuilder.php index 2b8dfd6a3e520..63a7c2b33176b 100644 --- a/src/Symfony/Component/DependencyInjection/ContainerBuilder.php +++ b/src/Symfony/Component/DependencyInjection/ContainerBuilder.php @@ -1472,20 +1472,26 @@ public static function hash($value) protected function getEnv($name) { $value = parent::getEnv($name); + $bag = $this->getParameterBag(); - if (!is_string($value) || !$this->getParameterBag() instanceof EnvPlaceholderParameterBag) { + if (!is_string($value) || !$bag instanceof EnvPlaceholderParameterBag) { return $value; } - foreach ($this->getParameterBag()->getEnvPlaceholders() as $env => $placeholders) { + foreach ($bag->getEnvPlaceholders() as $env => $placeholders) { if (isset($placeholders[$value])) { - $bag = new ParameterBag($this->getParameterBag()->all()); + $bag = new ParameterBag($bag->all()); return $bag->unescapeValue($bag->get("env($name)")); } } - return $value; + $this->resolving["env($name)"] = true; + try { + return $bag->unescapeValue($this->resolveEnvPlaceholders($bag->escapeValue($value), true)); + } finally { + unset($this->resolving["env($name)"]); + } } /** diff --git a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php index 2f70d59d819ec..87835ee44008e 100644 --- a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php +++ b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php @@ -1112,7 +1112,7 @@ private function addDefaultParametersMethod() $export = $this->exportParameters(array($value)); $export = explode('0 => ', substr(rtrim($export, " )\n"), 7, -1), 2); - if (preg_match("/\\\$this->(?:getEnv\('\w++'\)|targetDirs\[\d++\])/", $export[1])) { + if (preg_match("/\\\$this->(?:getEnv\('(?:\w++:)*+\w++'\)|targetDirs\[\d++\])/", $export[1])) { $dynamicPhp[$key] = sprintf('%scase %s: $value = %s; break;', $export[0], $this->export($key), $export[1]); } else { $php[] = sprintf('%s%s => %s,', $export[0], $this->export($key), $export[1]); @@ -1685,7 +1685,7 @@ private function dumpParameter($name) return $dumpedValue; } - if (!preg_match("/\\\$this->(?:getEnv\('\w++'\)|targetDirs\[\d++\])/", $dumpedValue)) { + if (!preg_match("/\\\$this->(?:getEnv\('(?:\w++:)*+\w++'\)|targetDirs\[\d++\])/", $dumpedValue)) { return sprintf("\$this->parameters['%s']", $name); } } @@ -1880,13 +1880,16 @@ private function doExport($value) { $export = var_export($value, true); - if ("'" === $export[0] && $export !== $resolvedExport = $this->container->resolveEnvPlaceholders($export, "'.\$this->getEnv('%s').'")) { + if ("'" === $export[0] && $export !== $resolvedExport = $this->container->resolveEnvPlaceholders($export, "'.\$this->getEnv('string:%s').'")) { $export = $resolvedExport; - if ("'" === $export[1]) { - $export = substr($export, 3); - } if (".''" === substr($export, -3)) { $export = substr($export, 0, -3); + if ("'" === $export[1]) { + $export = substr_replace($export, '', 18, 7); + } + } + if ("'" === $export[1]) { + $export = substr($export, 3); } } diff --git a/src/Symfony/Component/DependencyInjection/EnvVarProcessor.php b/src/Symfony/Component/DependencyInjection/EnvVarProcessor.php new file mode 100644 index 0000000000000..51a19367e2179 --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/EnvVarProcessor.php @@ -0,0 +1,160 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection; + +use Symfony\Component\Config\Util\XmlUtils; +use Symfony\Component\DependencyInjection\Exception\EnvNotFoundException; +use Symfony\Component\DependencyInjection\Exception\RuntimeException; + +class EnvVarProcessor implements EnvVarProcessorInterface +{ + private $container; + + public function __construct(ContainerInterface $container) + { + $this->container = $container; + } + + /** + * {@inheritdoc} + */ + public static function getProvidedTypes() + { + return array( + 'base64' => 'string', + 'bool' => 'bool', + 'const' => 'bool|int|float|string|array', + 'file' => 'string', + 'float' => 'float', + 'int' => 'int', + 'json' => 'array', + 'resolve' => 'string', + 'string' => 'string', + ); + } + + /** + * {@inheritdoc} + */ + public function getEnv($prefix, $name, \Closure $getEnv) + { + $i = strpos($name, ':'); + + if ('file' === $prefix) { + if (!is_scalar($file = $getEnv($name))) { + throw new RuntimeException(sprintf('Invalid file name: env var "%s" is non-scalar.', $name)); + } + if (!file_exists($file)) { + throw new RuntimeException(sprintf('Env "file:%s" not found: %s does not exist.', $name, $file)); + } + + return file_get_contents($file); + } + + if (false !== $i || 'string' !== $prefix) { + if (null === $env = $getEnv($name)) { + return; + } + } elseif (isset($_SERVER[$name]) && 0 !== strpos($name, 'HTTP_')) { + $env = $_SERVER[$name]; + } elseif (isset($_ENV[$name])) { + $env = $_ENV[$name]; + } elseif (false === ($env = getenv($name)) || null === $env) { // null is a possible value because of thread safety issues + if (!$this->container->hasParameter("env($name)")) { + throw new EnvNotFoundException($name); + } + + if (null === $env = $this->container->getParameter("env($name)")) { + return; + } + } + + if (!is_scalar($env)) { + throw new RuntimeException(sprintf('Non-scalar env var "%s" cannot be cast to %s.', $name, $prefix)); + } + + if ('string' === $prefix) { + return (string) $env; + } + + if ('bool' === $prefix) { + return (bool) self::phpize($env); + } + + if ('int' === $prefix) { + if (!is_numeric($env = self::phpize($env))) { + throw new RuntimeException(sprintf('Non-numeric env var "%s" cannot be cast to int.', $name)); + } + + return (int) $env; + } + + if ('float' === $prefix) { + if (!is_numeric($env = self::phpize($env))) { + throw new RuntimeException(sprintf('Non-numeric env var "%s" cannot be cast to float.', $name)); + } + + return (float) $env; + } + + if ('const' === $prefix) { + if (!defined($env)) { + throw new RuntimeException(sprintf('Env var "%s" maps to undefined constant "%s".', $name, $env)); + } + + return constant($name); + } + + if ('base64' === $prefix) { + return base64_decode($env); + } + + if ('json' === $prefix) { + $env = json_decode($env, true, JSON_BIGINT_AS_STRING); + + if (JSON_ERROR_NONE !== json_last_error()) { + throw new RuntimeException(sprintf('Invalid JSON in env var "%s": '.json_last_error_msg(), $name)); + } + + if (!is_array($env)) { + throw new RuntimeException(sprintf('Invalid JSON env var "%s": array expected, %s given.', $name, gettype($env))); + } + + return $env; + } + + if ('resolve' === $prefix) { + return preg_replace_callback('/%%|%([^%\s]+)%/', function ($match) use ($name) { + if (!isset($match[1])) { + return '%'; + } + $value = $this->container->getParameter($match[1]); + if (!is_scalar($value)) { + throw new RuntimeException(sprintf('Parameter "%s" found when resolving env var "%s" must be scalar, "%s" given.', $match[1], $name, gettype($value))); + } + + return $value; + }, $env); + } + + throw new RuntimeException(sprintf('Unsupported env var prefix "%s".', $prefix)); + } + + private static function phpize($value) + { + if (!class_exists(XmlUtils::class)) { + throw new RuntimeException('The Symfony Config component is required to cast env vars to "bool", "int" or "float".'); + } + + return XmlUtils::phpize($value); + } +} diff --git a/src/Symfony/Component/DependencyInjection/EnvVarProcessorInterface.php b/src/Symfony/Component/DependencyInjection/EnvVarProcessorInterface.php new file mode 100644 index 0000000000000..fce9f5cd7a998 --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/EnvVarProcessorInterface.php @@ -0,0 +1,38 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection; + +/** + * The EnvVarProcessorInterface is implemented by objects that manage environment-like variables. + * + * @author Nicolas Grekas + */ +interface EnvVarProcessorInterface +{ + /** + * Returns the value of the given variable as managed by the current instance. + * + * @param string $prefix The namespace of the variable + * @param string $name The name of the variable within the namespace + * @param \Closure $getEnv A closure that allows fetching more env vars + * + * @return mixed + * + * @throws RuntimeException on error + */ + public function getEnv($prefix, $name, \Closure $getEnv); + + /** + * @return string[] The PHP-types managed by getEnv(), keyed by prefixes + */ + public static function getProvidedTypes(); +} diff --git a/src/Symfony/Component/DependencyInjection/ParameterBag/EnvPlaceholderParameterBag.php b/src/Symfony/Component/DependencyInjection/ParameterBag/EnvPlaceholderParameterBag.php index fd859068be33c..e0fe4c7cdfc57 100644 --- a/src/Symfony/Component/DependencyInjection/ParameterBag/EnvPlaceholderParameterBag.php +++ b/src/Symfony/Component/DependencyInjection/ParameterBag/EnvPlaceholderParameterBag.php @@ -20,6 +20,7 @@ class EnvPlaceholderParameterBag extends ParameterBag { private $envPlaceholders = array(); + private $providedTypes = array(); /** * {@inheritdoc} @@ -34,7 +35,7 @@ public function get($name) return $placeholder; // return first result } } - if (preg_match('/\W/', $env)) { + if (!preg_match('/^(?:\w++:)*+\w++$/', $env)) { throw new InvalidArgumentException(sprintf('Invalid %s name: only "word" characters are allowed.', $name)); } @@ -80,6 +81,24 @@ public function mergeEnvPlaceholders(self $bag) } } + /** + * Maps env prefixes to their corresponding PHP types. + */ + public function setProvidedTypes(array $providedTypes) + { + $this->providedTypes = $providedTypes; + } + + /** + * Gets the PHP types corresponding to env() parameter prefixes. + * + * @return string[][] + */ + public function getProvidedTypes() + { + return $this->providedTypes; + } + /** * {@inheritdoc} */ diff --git a/src/Symfony/Component/DependencyInjection/Tests/Compiler/RegisterEnvVarProcessorsPassTest.php b/src/Symfony/Component/DependencyInjection/Tests/Compiler/RegisterEnvVarProcessorsPassTest.php new file mode 100644 index 0000000000000..dc3a1f1834f5e --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Tests/Compiler/RegisterEnvVarProcessorsPassTest.php @@ -0,0 +1,75 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Tests\Compiler; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\DependencyInjection\Compiler\RegisterEnvVarProcessorsPass; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\EnvVarProcessorInterface; + +class RegisterEnvVarProcessorsPassTest extends TestCase +{ + public function testSimpleProcessor() + { + $container = new ContainerBuilder(); + $container->register('foo', SimpleProcessor::class)->addTag('container.env_var_processor'); + + (new RegisterEnvVarProcessorsPass())->process($container); + + $this->assertTrue($container->has('container.env_var_processors_locator')); + $this->assertInstanceof(SimpleProcessor::class, $container->get('container.env_var_processors_locator')->get('foo')); + + $this->assertSame(array('foo' => array('string')), $container->getParameterBag()->getProvidedTypes()); + } + + public function testNoProcessor() + { + $container = new ContainerBuilder(); + + (new RegisterEnvVarProcessorsPass())->process($container); + + $this->assertFalse($container->has('container.env_var_processors_locator')); + } + + /** + * @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException + * @expectedExceptionMessage Invalid type "foo" returned by "Symfony\Component\DependencyInjection\Tests\Compiler\BadProcessor::getProvidedTypes()", expected one of "array", "bool", "float", "int", "string". + */ + public function testBadProcessor() + { + $container = new ContainerBuilder(); + $container->register('foo', BadProcessor::class)->addTag('container.env_var_processor'); + + (new RegisterEnvVarProcessorsPass())->process($container); + } +} + +class SimpleProcessor implements EnvVarProcessorInterface +{ + public function getEnv($prefix, $name, \Closure $getEnv) + { + return $getEnv($name); + } + + public static function getProvidedTypes() + { + return array('foo' => 'string'); + } +} + +class BadProcessor extends SimpleProcessor +{ + public static function getProvidedTypes() + { + return array('foo' => 'string|foo'); + } +} diff --git a/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php b/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php index 54e3227d23f18..d074189cbeab7 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php @@ -665,6 +665,70 @@ public function testCompileWithResolveMissingEnv() $container->compile(true); } + public function testDynamicEnv() + { + putenv('DUMMY_FOO=some%foo%'); + putenv('DUMMY_BAR=%bar%'); + + $container = new ContainerBuilder(); + $container->setParameter('foo', 'Foo%env(resolve:DUMMY_BAR)%'); + $container->setParameter('bar', 'Bar'); + $container->setParameter('baz', '%env(resolve:DUMMY_FOO)%'); + + $container->compile(true); + putenv('DUMMY_FOO'); + putenv('DUMMY_BAR'); + + $this->assertSame('someFooBar', $container->getParameter('baz')); + } + + public function testCastEnv() + { + $container = new ContainerBuilder(); + $container->setParameter('env(FAKE)', '123'); + + $container->register('foo', 'stdClass')->setProperties(array( + 'fake' => '%env(int:FAKE)%', + )); + + $container->compile(true); + + $this->assertSame(123, $container->get('foo')->fake); + } + + public function testEnvAreNullable() + { + $container = new ContainerBuilder(); + $container->setParameter('env(FAKE)', null); + + $container->register('foo', 'stdClass')->setProperties(array( + 'fake' => '%env(int:FAKE)%', + )); + + $container->compile(true); + + $this->assertNull($container->get('foo')->fake); + } + + /** + * @expectedException \Symfony\Component\DependencyInjection\Exception\ParameterCircularReferenceException + * @expectedExceptionMessage Circular reference detected for parameter "env(resolve:DUMMY_ENV_VAR)" ("env(resolve:DUMMY_ENV_VAR)" > "env(resolve:DUMMY_ENV_VAR)"). + */ + public function testCircularDynamicEnv() + { + putenv('DUMMY_ENV_VAR=some%foo%'); + + $container = new ContainerBuilder(); + $container->setParameter('foo', '%bar%'); + $container->setParameter('bar', '%env(resolve:DUMMY_ENV_VAR)%'); + + try { + $container->compile(true); + } finally { + putenv('DUMMY_ENV_VAR'); + } + } + /** * @expectedException \LogicException */ diff --git a/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php b/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php index 62213ee2804bc..ac8aee2fc596c 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php @@ -21,6 +21,7 @@ use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\ContainerInterface as SymfonyContainerInterface; use Symfony\Component\DependencyInjection\Dumper\PhpDumper; +use Symfony\Component\DependencyInjection\EnvVarProcessorInterface; use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag; use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\DependencyInjection\Tests\Fixtures\StubbedTranslator; @@ -338,13 +339,82 @@ public function testDumpAutowireData() public function testEnvParameter() { + $rand = mt_rand(); + putenv('Baz='.$rand); $container = new ContainerBuilder(); $loader = new YamlFileLoader($container, new FileLocator(self::$fixturesPath.'/yaml')); $loader->load('services26.yml'); + $container->setParameter('env(json_file)', self::$fixturesPath.'/array.json'); $container->compile(); $dumper = new PhpDumper($container); - $this->assertStringEqualsFile(self::$fixturesPath.'/php/services26.php', $dumper->dump(), '->dump() dumps inline definitions which reference service_container'); + $this->assertStringEqualsFile(self::$fixturesPath.'/php/services26.php', $dumper->dump(array('class' => 'Symfony_DI_PhpDumper_Test_EnvParameters', 'file' => self::$fixturesPath.'/php/services26.php'))); + + require self::$fixturesPath.'/php/services26.php'; + $container = new \Symfony_DI_PhpDumper_Test_EnvParameters(); + $this->assertSame($rand, $container->getParameter('baz')); + $this->assertSame(array(123, 'abc'), $container->getParameter('json')); + $this->assertSame('sqlite:///foo/bar/var/data.db', $container->getParameter('db_dsn')); + putenv('Baz'); + } + + public function testResolvedBase64EnvParameters() + { + $container = new ContainerBuilder(); + $container->setParameter('env(foo)', base64_encode('world')); + $container->setParameter('hello', '%env(base64:foo)%'); + $container->compile(true); + + $expected = array( + 'env(foo)' => 'd29ybGQ=', + 'hello' => 'world', + ); + $this->assertSame($expected, $container->getParameterBag()->all()); + } + + public function testDumpedBase64EnvParameters() + { + $container = new ContainerBuilder(); + $container->setParameter('env(foo)', base64_encode('world')); + $container->setParameter('hello', '%env(base64:foo)%'); + $container->compile(); + + $dumper = new PhpDumper($container); + $dumper->dump(); + + $this->assertStringEqualsFile(self::$fixturesPath.'/php/services_base64_env.php', $dumper->dump(array('class' => 'Symfony_DI_PhpDumper_Test_Base64Parameters'))); + + require self::$fixturesPath.'/php/services_base64_env.php'; + $container = new \Symfony_DI_PhpDumper_Test_Base64Parameters(); + $this->assertSame('world', $container->getParameter('hello')); + } + + public function testCustomEnvParameters() + { + $container = new ContainerBuilder(); + $container->setParameter('env(foo)', str_rot13('world')); + $container->setParameter('hello', '%env(rot13:foo)%'); + $container->register(Rot13EnvVarProcessor::class)->addTag('container.env_var_processor'); + $container->compile(); + + $dumper = new PhpDumper($container); + $dumper->dump(); + + $this->assertStringEqualsFile(self::$fixturesPath.'/php/services_rot13_env.php', $dumper->dump(array('class' => 'Symfony_DI_PhpDumper_Test_Rot13Parameters'))); + + require self::$fixturesPath.'/php/services_rot13_env.php'; + $container = new \Symfony_DI_PhpDumper_Test_Rot13Parameters(); + $this->assertSame('world', $container->getParameter('hello')); + } + + public function testFileEnvProcessor() + { + $container = new ContainerBuilder(); + $container->setParameter('env(foo)', __FILE__); + $container->setParameter('random', '%env(file:foo)%'); + $container->compile(true); + + $this->assertStringEqualsFile(__FILE__, $container->getParameter('random')); } /** @@ -360,6 +430,31 @@ public function testUnusedEnvParameter() $dumper->dump(); } + /** + * @expectedException \Symfony\Component\DependencyInjection\Exception\ParameterCircularReferenceException + * @expectedExceptionMessage Circular reference detected for parameter "env(resolve:DUMMY_ENV_VAR)" ("env(resolve:DUMMY_ENV_VAR)" > "env(resolve:DUMMY_ENV_VAR)"). + */ + public function testCircularDynamicEnv() + { + $container = new ContainerBuilder(); + $container->setParameter('foo', '%bar%'); + $container->setParameter('bar', '%env(resolve:DUMMY_ENV_VAR)%'); + $container->compile(); + + $dumper = new PhpDumper($container); + $dump = $dumper->dump(array('class' => $class = __FUNCTION__)); + + eval('?>'.$dump); + $container = new $class(); + + putenv('DUMMY_ENV_VAR=%foo%'); + try { + $container->getParameter('bar'); + } finally { + putenv('DUMMY_ENV_VAR'); + } + } + public function testInlinedDefinitionReferencingServiceContainer() { $container = new ContainerBuilder(); @@ -748,3 +843,16 @@ public function testParameterWithLowerCase() $this->assertSame('bar', $container->getParameter('FOO')); } } + +class Rot13EnvVarProcessor implements EnvVarProcessorInterface +{ + public function getEnv($prefix, $name, \Closure $getEnv) + { + return str_rot13($getEnv($name)); + } + + public static function getProvidedTypes() + { + return array('rot13' => 'string'); + } +} diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/array.json b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/array.json new file mode 100644 index 0000000000000..dc27f0fa15907 --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/array.json @@ -0,0 +1 @@ +[123, "abc"] diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services26.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services26.php index 0998b23a75b9a..3a38cff1a1539 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services26.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services26.php @@ -9,14 +9,14 @@ use Symfony\Component\DependencyInjection\ParameterBag\FrozenParameterBag; /** - * ProjectServiceContainer. + * Symfony_DI_PhpDumper_Test_EnvParameters. * * This class has been auto-generated * by the Symfony Dependency Injection Component. * * @final since Symfony 3.3 */ -class ProjectServiceContainer extends Container +class Symfony_DI_PhpDumper_Test_EnvParameters extends Container { private $parameters; private $targetDirs = array(); @@ -26,6 +26,10 @@ class ProjectServiceContainer extends Container */ public function __construct() { + $dir = __DIR__; + for ($i = 1; $i <= 5; ++$i) { + $this->targetDirs[$i] = $dir = dirname($dir); + } $this->parameters = $this->getDefaultParameters(); $this->services = array(); @@ -71,7 +75,7 @@ protected function getTestService() { $class = $this->getEnv('FOO'); - return $this->services['test'] = new $class($this->getEnv('Bar'), 'foo'.$this->getEnv('FOO').'baz'); + return $this->services['test'] = new $class($this->getEnv('Bar'), 'foo'.$this->getEnv('string:FOO').'baz', $this->getEnv('int:Baz')); } /** @@ -129,6 +133,10 @@ public function getParameterBag() private $loadedDynamicParameters = array( 'bar' => false, + 'baz' => false, + 'json' => false, + 'db_dsn' => false, + 'env(json_file)' => false, ); private $dynamicParameters = array(); @@ -145,6 +153,10 @@ private function getDynamicParameter($name) { switch ($name) { case 'bar': $value = $this->getEnv('FOO'); break; + case 'baz': $value = $this->getEnv('int:Baz'); break; + case 'json': $value = $this->getEnv('json:file:json_file'); break; + case 'db_dsn': $value = $this->getEnv('resolve:DB'); break; + case 'env(json_file)': $value = ($this->targetDirs[1].'/array.json'); break; default: throw new InvalidArgumentException(sprintf('The dynamic parameter "%s" must be defined.', $name)); } $this->loadedDynamicParameters[$name] = true; @@ -154,6 +166,7 @@ private function getDynamicParameter($name) private $normalizedParameterNames = array( 'env(foo)' => 'env(FOO)', + 'env(db)' => 'env(DB)', ); private function normalizeParameterName($name) @@ -178,7 +191,9 @@ private function normalizeParameterName($name) protected function getDefaultParameters() { return array( + 'project_dir' => '/foo/bar', 'env(FOO)' => 'foo', + 'env(DB)' => 'sqlite://%project_dir%/var/data.db', ); } } diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_base64_env.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_base64_env.php new file mode 100644 index 0000000000000..4f4c7e79df38b --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_base64_env.php @@ -0,0 +1,167 @@ +parameters = $this->getDefaultParameters(); + + $this->services = array(); + + $this->aliases = array(); + } + + /** + * {@inheritdoc} + */ + public function compile() + { + throw new LogicException('You cannot compile a dumped container that was already compiled.'); + } + + /** + * {@inheritdoc} + */ + public function isCompiled() + { + return true; + } + + /** + * {@inheritdoc} + */ + public function isFrozen() + { + @trigger_error(sprintf('The %s() method is deprecated since version 3.3 and will be removed in 4.0. Use the isCompiled() method instead.', __METHOD__), E_USER_DEPRECATED); + + return true; + } + + /** + * {@inheritdoc} + */ + public function getParameter($name) + { + if (!(isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters))) { + $name = $this->normalizeParameterName($name); + + if (!(isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters))) { + throw new InvalidArgumentException(sprintf('The parameter "%s" must be defined.', $name)); + } + } + if (isset($this->loadedDynamicParameters[$name])) { + return $this->loadedDynamicParameters[$name] ? $this->dynamicParameters[$name] : $this->getDynamicParameter($name); + } + + return $this->parameters[$name]; + } + + /** + * {@inheritdoc} + */ + public function hasParameter($name) + { + $name = $this->normalizeParameterName($name); + + return isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters); + } + + /** + * {@inheritdoc} + */ + public function setParameter($name, $value) + { + throw new LogicException('Impossible to call set() on a frozen ParameterBag.'); + } + + /** + * {@inheritdoc} + */ + public function getParameterBag() + { + if (null === $this->parameterBag) { + $parameters = $this->parameters; + foreach ($this->loadedDynamicParameters as $name => $loaded) { + $parameters[$name] = $loaded ? $this->dynamicParameters[$name] : $this->getDynamicParameter($name); + } + $this->parameterBag = new FrozenParameterBag($parameters); + } + + return $this->parameterBag; + } + + private $loadedDynamicParameters = array( + 'hello' => false, + ); + private $dynamicParameters = array(); + + /** + * Computes a dynamic parameter. + * + * @param string The name of the dynamic parameter to load + * + * @return mixed The value of the dynamic parameter + * + * @throws InvalidArgumentException When the dynamic parameter does not exist + */ + private function getDynamicParameter($name) + { + switch ($name) { + case 'hello': $value = $this->getEnv('base64:foo'); break; + default: throw new InvalidArgumentException(sprintf('The dynamic parameter "%s" must be defined.', $name)); + } + $this->loadedDynamicParameters[$name] = true; + + return $this->dynamicParameters[$name] = $value; + } + + private $normalizedParameterNames = array(); + + private function normalizeParameterName($name) + { + if (isset($this->normalizedParameterNames[$normalizedName = strtolower($name)]) || isset($this->parameters[$normalizedName]) || array_key_exists($normalizedName, $this->parameters)) { + $normalizedName = isset($this->normalizedParameterNames[$normalizedName]) ? $this->normalizedParameterNames[$normalizedName] : $normalizedName; + if ((string) $name !== $normalizedName) { + @trigger_error(sprintf('Parameter names will be made case sensitive in Symfony 4.0. Using "%s" instead of "%s" is deprecated since version 3.4.', $name, $normalizedName), E_USER_DEPRECATED); + } + } else { + $normalizedName = $this->normalizedParameterNames[$normalizedName] = (string) $name; + } + + return $normalizedName; + } + + /** + * Gets the default parameters. + * + * @return array An array of the default parameters + */ + protected function getDefaultParameters() + { + return array( + 'env(foo)' => 'd29ybGQ=', + ); + } +} diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_rot13_env.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_rot13_env.php new file mode 100644 index 0000000000000..2e08cdcb42f92 --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_rot13_env.php @@ -0,0 +1,196 @@ +parameters = $this->getDefaultParameters(); + + $this->services = array(); + $this->normalizedIds = array( + 'symfony\\component\\dependencyinjection\\tests\\dumper\\rot13envvarprocessor' => 'Symfony\\Component\\DependencyInjection\\Tests\\Dumper\\Rot13EnvVarProcessor', + ); + $this->methodMap = array( + 'Symfony\\Component\\DependencyInjection\\Tests\\Dumper\\Rot13EnvVarProcessor' => 'getRot13EnvVarProcessorService', + 'container.env_var_processors_locator' => 'getContainer_EnvVarProcessorsLocatorService', + ); + + $this->aliases = array(); + } + + /** + * {@inheritdoc} + */ + public function compile() + { + throw new LogicException('You cannot compile a dumped container that was already compiled.'); + } + + /** + * {@inheritdoc} + */ + public function isCompiled() + { + return true; + } + + /** + * {@inheritdoc} + */ + public function isFrozen() + { + @trigger_error(sprintf('The %s() method is deprecated since version 3.3 and will be removed in 4.0. Use the isCompiled() method instead.', __METHOD__), E_USER_DEPRECATED); + + return true; + } + + /** + * Gets the public 'Symfony\Component\DependencyInjection\Tests\Dumper\Rot13EnvVarProcessor' shared service. + * + * @return \Symfony\Component\DependencyInjection\Tests\Dumper\Rot13EnvVarProcessor + */ + protected function getRot13EnvVarProcessorService() + { + return $this->services['Symfony\Component\DependencyInjection\Tests\Dumper\Rot13EnvVarProcessor'] = new \Symfony\Component\DependencyInjection\Tests\Dumper\Rot13EnvVarProcessor(); + } + + /** + * Gets the public 'container.env_var_processors_locator' shared service. + * + * @return \Symfony\Component\DependencyInjection\ServiceLocator + */ + protected function getContainer_EnvVarProcessorsLocatorService() + { + return $this->services['container.env_var_processors_locator'] = new \Symfony\Component\DependencyInjection\ServiceLocator(array('rot13' => function () { + return ${($_ = isset($this->services['Symfony\Component\DependencyInjection\Tests\Dumper\Rot13EnvVarProcessor']) ? $this->services['Symfony\Component\DependencyInjection\Tests\Dumper\Rot13EnvVarProcessor'] : $this->services['Symfony\Component\DependencyInjection\Tests\Dumper\Rot13EnvVarProcessor'] = new \Symfony\Component\DependencyInjection\Tests\Dumper\Rot13EnvVarProcessor()) && false ?: '_'}; + })); + } + + /** + * {@inheritdoc} + */ + public function getParameter($name) + { + if (!(isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters))) { + $name = $this->normalizeParameterName($name); + + if (!(isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters))) { + throw new InvalidArgumentException(sprintf('The parameter "%s" must be defined.', $name)); + } + } + if (isset($this->loadedDynamicParameters[$name])) { + return $this->loadedDynamicParameters[$name] ? $this->dynamicParameters[$name] : $this->getDynamicParameter($name); + } + + return $this->parameters[$name]; + } + + /** + * {@inheritdoc} + */ + public function hasParameter($name) + { + $name = $this->normalizeParameterName($name); + + return isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters); + } + + /** + * {@inheritdoc} + */ + public function setParameter($name, $value) + { + throw new LogicException('Impossible to call set() on a frozen ParameterBag.'); + } + + /** + * {@inheritdoc} + */ + public function getParameterBag() + { + if (null === $this->parameterBag) { + $parameters = $this->parameters; + foreach ($this->loadedDynamicParameters as $name => $loaded) { + $parameters[$name] = $loaded ? $this->dynamicParameters[$name] : $this->getDynamicParameter($name); + } + $this->parameterBag = new FrozenParameterBag($parameters); + } + + return $this->parameterBag; + } + + private $loadedDynamicParameters = array( + 'hello' => false, + ); + private $dynamicParameters = array(); + + /** + * Computes a dynamic parameter. + * + * @param string The name of the dynamic parameter to load + * + * @return mixed The value of the dynamic parameter + * + * @throws InvalidArgumentException When the dynamic parameter does not exist + */ + private function getDynamicParameter($name) + { + switch ($name) { + case 'hello': $value = $this->getEnv('rot13:foo'); break; + default: throw new InvalidArgumentException(sprintf('The dynamic parameter "%s" must be defined.', $name)); + } + $this->loadedDynamicParameters[$name] = true; + + return $this->dynamicParameters[$name] = $value; + } + + private $normalizedParameterNames = array(); + + private function normalizeParameterName($name) + { + if (isset($this->normalizedParameterNames[$normalizedName = strtolower($name)]) || isset($this->parameters[$normalizedName]) || array_key_exists($normalizedName, $this->parameters)) { + $normalizedName = isset($this->normalizedParameterNames[$normalizedName]) ? $this->normalizedParameterNames[$normalizedName] : $normalizedName; + if ((string) $name !== $normalizedName) { + @trigger_error(sprintf('Parameter names will be made case sensitive in Symfony 4.0. Using "%s" instead of "%s" is deprecated since version 3.4.', $name, $normalizedName), E_USER_DEPRECATED); + } + } else { + $normalizedName = $this->normalizedParameterNames[$normalizedName] = (string) $name; + } + + return $normalizedName; + } + + /** + * Gets the default parameters. + * + * @return array An array of the default parameters + */ + protected function getDefaultParameters() + { + return array( + 'env(foo)' => 'jbeyq', + ); + } +} diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services26.yml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services26.yml index 2ef23c1af545f..d573e810dbe23 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services26.yml +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services26.yml @@ -1,6 +1,11 @@ parameters: + project_dir: '/foo/bar' env(FOO): foo + env(DB): 'sqlite://%%project_dir%%/var/data.db' bar: '%env(FOO)%' + baz: '%env(int:Baz)%' + json: '%env(json:file:json_file)%' + db_dsn: '%env(resolve:DB)%' services: test: @@ -8,3 +13,4 @@ services: arguments: - '%env(Bar)%' - 'foo%bar%baz' + - '%baz%' From b884c6612d80f723e5954a53c7d5e84c2d8ae61f Mon Sep 17 00:00:00 2001 From: Robin Chalas Date: Thu, 7 Sep 2017 10:19:55 +0200 Subject: [PATCH 0783/1099] Throw a meaningful exception when an undefined user provider is used inside a firewall --- .../DependencyInjection/SecurityExtension.php | 16 ++++++++++++--- .../CompleteConfigurationTest.php | 18 +++++++++++++++++ .../php/firewall_undefined_provider.php | 17 ++++++++++++++++ .../php/listener_undefined_provider.php | 16 +++++++++++++++ .../xml/firewall_undefined_provider.xml | 20 +++++++++++++++++++ .../xml/listener_undefined_provider.xml | 20 +++++++++++++++++++ .../yml/firewall_undefined_provider.yml | 10 ++++++++++ .../yml/listener_undefined_provider.yml | 10 ++++++++++ 8 files changed, 124 insertions(+), 3 deletions(-) create mode 100644 src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/firewall_undefined_provider.php create mode 100644 src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/listener_undefined_provider.php create mode 100644 src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/firewall_undefined_provider.xml create mode 100644 src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/listener_undefined_provider.xml create mode 100644 src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/firewall_undefined_provider.yml create mode 100644 src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/listener_undefined_provider.yml diff --git a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php index dffe9d36879b2..adfe5b235752b 100644 --- a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php +++ b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php @@ -332,6 +332,9 @@ private function createFirewall(ContainerBuilder $container, $id, $firewall, &$a // Provider id (take the first registered provider if none defined) if (isset($firewall['provider'])) { $defaultProvider = $this->getUserProviderId($firewall['provider']); + if (!in_array($defaultProvider, $providerIds, true)) { + throw new InvalidConfigurationException(sprintf('Invalid firewall "%s": user provider "%s" not found.', $id, $firewall['provider'])); + } } else { $defaultProvider = reset($providerIds); } @@ -422,7 +425,7 @@ private function createFirewall(ContainerBuilder $container, $id, $firewall, &$a $configuredEntryPoint = isset($firewall['entry_point']) ? $firewall['entry_point'] : null; // Authentication listeners - list($authListeners, $defaultEntryPoint) = $this->createAuthenticationListeners($container, $id, $firewall, $authenticationProviders, $defaultProvider, $configuredEntryPoint); + list($authListeners, $defaultEntryPoint) = $this->createAuthenticationListeners($container, $id, $firewall, $authenticationProviders, $defaultProvider, $providerIds, $configuredEntryPoint); $config->replaceArgument(7, $configuredEntryPoint ?: $defaultEntryPoint); @@ -477,7 +480,7 @@ private function createContextListener($container, $contextKey) return $this->contextListeners[$contextKey] = $listenerId; } - private function createAuthenticationListeners($container, $id, $firewall, &$authenticationProviders, $defaultProvider, $defaultEntryPoint) + private function createAuthenticationListeners($container, $id, $firewall, &$authenticationProviders, $defaultProvider, array $providerIds, $defaultEntryPoint) { $listeners = array(); $hasListeners = false; @@ -487,7 +490,14 @@ private function createAuthenticationListeners($container, $id, $firewall, &$aut $key = str_replace('-', '_', $factory->getKey()); if (isset($firewall[$key])) { - $userProvider = isset($firewall[$key]['provider']) ? $this->getUserProviderId($firewall[$key]['provider']) : $defaultProvider; + if (isset($firewall[$key]['provider'])) { + if (!in_array($firewall[$key]['provider'], $providerIds, true)) { + throw new InvalidConfigurationException(sprintf('Invalid firewall "%s": user provider "%s" not found.', $id, $firewall[$key]['provider'])); + } + $userProvider = $this->getUserProviderId($firewall[$key]['provider']); + } else { + $userProvider = $defaultProvider; + } list($provider, $listenerId, $defaultEntryPoint) = $factory->create($container, $id, $firewall[$key], $userProvider, $defaultEntryPoint); diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/CompleteConfigurationTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/CompleteConfigurationTest.php index 4f000d3aee0f8..202107a57abf2 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/CompleteConfigurationTest.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/CompleteConfigurationTest.php @@ -387,6 +387,24 @@ public function testAccessDecisionManagerServiceAndStrategyCannotBeUsedAtTheSame $container = $this->getContainer('access_decision_manager_service_and_strategy'); } + /** + * @expectedException \Symfony\Component\Config\Definition\Exception\InvalidConfigurationException + * @expectedExceptionMessage Invalid firewall "main": user provider "undefined" not found. + */ + public function testFirewallUndefinedUserProvider() + { + $this->getContainer('firewall_undefined_provider'); + } + + /** + * @expectedException \Symfony\Component\Config\Definition\Exception\InvalidConfigurationException + * @expectedExceptionMessage Invalid firewall "main": user provider "undefined" not found. + */ + public function testFirewallListenerUndefinedProvider() + { + $this->getContainer('listener_undefined_provider'); + } + protected function getContainer($file) { $file = $file.'.'.$this->getFileExtension(); diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/firewall_undefined_provider.php b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/firewall_undefined_provider.php new file mode 100644 index 0000000000000..78d461efe38d1 --- /dev/null +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/firewall_undefined_provider.php @@ -0,0 +1,17 @@ +loadFromExtension('security', array( + 'providers' => array( + 'default' => array( + 'memory' => array( + 'users' => array('foo' => array('password' => 'foo', 'roles' => 'ROLE_USER')), + ), + ), + ), + 'firewalls' => array( + 'main' => array( + 'provider' => 'undefined', + 'form_login' => true, + ), + ), +)); diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/listener_undefined_provider.php b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/listener_undefined_provider.php new file mode 100644 index 0000000000000..da54f025d1a70 --- /dev/null +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/listener_undefined_provider.php @@ -0,0 +1,16 @@ +loadFromExtension('security', array( + 'providers' => array( + 'default' => array( + 'memory' => array( + 'users' => array('foo' => array('password' => 'foo', 'roles' => 'ROLE_USER')), + ), + ), + ), + 'firewalls' => array( + 'main' => array( + 'form_login' => array('provider' => 'undefined'), + ), + ), +)); diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/firewall_undefined_provider.xml b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/firewall_undefined_provider.xml new file mode 100644 index 0000000000000..f596ac5a6240b --- /dev/null +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/firewall_undefined_provider.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/listener_undefined_provider.xml b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/listener_undefined_provider.xml new file mode 100644 index 0000000000000..725e85a1d0f27 --- /dev/null +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/listener_undefined_provider.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/firewall_undefined_provider.yml b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/firewall_undefined_provider.yml new file mode 100644 index 0000000000000..ec2664054009c --- /dev/null +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/firewall_undefined_provider.yml @@ -0,0 +1,10 @@ +security: + providers: + default: + memory: + users: { foo: { password: foo, roles: ROLE_USER } } + + firewalls: + main: + provider: undefined + form_login: true diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/listener_undefined_provider.yml b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/listener_undefined_provider.yml new file mode 100644 index 0000000000000..1916df4c2e7ca --- /dev/null +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/listener_undefined_provider.yml @@ -0,0 +1,10 @@ +security: + providers: + default: + memory: + users: { foo: { password: foo, roles: ROLE_USER } } + + firewalls: + main: + form_login: + provider: undefined From a7f98c60d93bad22bc36fbf308dcb4d46cdda9e3 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Thu, 7 Sep 2017 10:34:20 +0200 Subject: [PATCH 0784/1099] [DI] rename ResolveDefinitionTemplatesPass to ResolveChildDefinitionsPass --- UPGRADE-3.4.md | 3 + UPGRADE-4.0.md | 3 + .../DependencyInjection/CHANGELOG.md | 1 + .../Compiler/PassConfig.php | 2 +- .../Compiler/ResolveChildDefinitionsPass.php | 183 ++++++++ .../ResolveDefinitionTemplatesPass.php | 166 +------ .../ResolveChildDefinitionsPassTest.php | 413 ++++++++++++++++++ .../ResolveDefinitionTemplatesPassTest.php | 3 + .../ResolveInstanceofConditionalsPassTest.php | 12 +- 9 files changed, 620 insertions(+), 166 deletions(-) create mode 100644 src/Symfony/Component/DependencyInjection/Compiler/ResolveChildDefinitionsPass.php create mode 100644 src/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveChildDefinitionsPassTest.php diff --git a/UPGRADE-3.4.md b/UPGRADE-3.4.md index 5b55f2ece170c..20114937efc26 100644 --- a/UPGRADE-3.4.md +++ b/UPGRADE-3.4.md @@ -52,6 +52,9 @@ DependencyInjection * Case insensitivity of parameter names is deprecated and will be removed in 4.0. + * The `ResolveDefinitionTemplatesPass` class is deprecated and will be removed in 4.0. + Use the `ResolveChildDefinitionsPass` class instead. + Debug ----- diff --git a/UPGRADE-4.0.md b/UPGRADE-4.0.md index 219bc8f807dd7..5d404598f7ec0 100644 --- a/UPGRADE-4.0.md +++ b/UPGRADE-4.0.md @@ -159,6 +159,9 @@ DependencyInjection * The `DefinitionDecorator` class has been removed. Use the `ChildDefinition` class instead. + * The `ResolveDefinitionTemplatesPass` class has been removed. + Use the `ResolveChildDefinitionsPass` class instead. + * Using unsupported configuration keys in YAML configuration files raises an exception. diff --git a/src/Symfony/Component/DependencyInjection/CHANGELOG.md b/src/Symfony/Component/DependencyInjection/CHANGELOG.md index 4232369e2e007..c6258405b1a34 100644 --- a/src/Symfony/Component/DependencyInjection/CHANGELOG.md +++ b/src/Symfony/Component/DependencyInjection/CHANGELOG.md @@ -9,6 +9,7 @@ CHANGELOG * deprecated the ability to check for the initialization of a private service with the `Container::initialized()` method * deprecated support for top-level anonymous services in XML * deprecated case insensitivity of parameter names + * deprecated the `ResolveDefinitionTemplatesPass` class in favor of `ResolveChildDefinitionsPass` 3.3.0 ----- diff --git a/src/Symfony/Component/DependencyInjection/Compiler/PassConfig.php b/src/Symfony/Component/DependencyInjection/Compiler/PassConfig.php index 184c7b25a0883..f016ac64df205 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/PassConfig.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/PassConfig.php @@ -48,7 +48,7 @@ public function __construct() $this->optimizationPasses = array(array( new ExtensionCompilerPass(), - new ResolveDefinitionTemplatesPass(), + new ResolveChildDefinitionsPass(), new ServiceLocatorTagPass(), new DecoratorServicePass(), new ResolveParameterPlaceHoldersPass(false), diff --git a/src/Symfony/Component/DependencyInjection/Compiler/ResolveChildDefinitionsPass.php b/src/Symfony/Component/DependencyInjection/Compiler/ResolveChildDefinitionsPass.php new file mode 100644 index 0000000000000..4e09ae630f52c --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Compiler/ResolveChildDefinitionsPass.php @@ -0,0 +1,183 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Compiler; + +use Symfony\Component\DependencyInjection\ChildDefinition; +use Symfony\Component\DependencyInjection\Definition; +use Symfony\Component\DependencyInjection\Exception\ExceptionInterface; +use Symfony\Component\DependencyInjection\Exception\RuntimeException; + +/** + * This replaces all ChildDefinition instances with their equivalent fully + * merged Definition instance. + * + * @author Johannes M. Schmitt + * @author Nicolas Grekas + */ +class ResolveChildDefinitionsPass extends AbstractRecursivePass +{ + protected function processValue($value, $isRoot = false) + { + if (!$value instanceof Definition) { + return parent::processValue($value, $isRoot); + } + if ($isRoot) { + // yes, we are specifically fetching the definition from the + // container to ensure we are not operating on stale data + $value = $this->container->getDefinition($this->currentId); + } + if ($value instanceof ChildDefinition) { + $value = $this->resolveDefinition($value); + if ($isRoot) { + $this->container->setDefinition($this->currentId, $value); + } + } + + return parent::processValue($value, $isRoot); + } + + /** + * Resolves the definition. + * + * @return Definition + * + * @throws RuntimeException When the definition is invalid + */ + private function resolveDefinition(ChildDefinition $definition) + { + try { + return $this->doResolveDefinition($definition); + } catch (ExceptionInterface $e) { + $r = new \ReflectionProperty($e, 'message'); + $r->setAccessible(true); + $r->setValue($e, sprintf('Service "%s": %s', $this->currentId, $e->getMessage())); + + throw $e; + } + } + + private function doResolveDefinition(ChildDefinition $definition) + { + if (!$this->container->has($parent = $definition->getParent())) { + throw new RuntimeException(sprintf('Parent definition "%s" does not exist.', $parent)); + } + + $parentDef = $this->container->findDefinition($parent); + if ($parentDef instanceof ChildDefinition) { + $id = $this->currentId; + $this->currentId = $parent; + $parentDef = $this->resolveDefinition($parentDef); + $this->container->setDefinition($parent, $parentDef); + $this->currentId = $id; + } + + $this->container->log($this, sprintf('Resolving inheritance for "%s" (parent: %s).', $this->currentId, $parent)); + $def = new Definition(); + + // merge in parent definition + // purposely ignored attributes: abstract, shared, tags, autoconfigured + $def->setClass($parentDef->getClass()); + $def->setArguments($parentDef->getArguments()); + $def->setMethodCalls($parentDef->getMethodCalls()); + $def->setProperties($parentDef->getProperties()); + if ($parentDef->getAutowiringTypes(false)) { + $def->setAutowiringTypes($parentDef->getAutowiringTypes(false)); + } + if ($parentDef->isDeprecated()) { + $def->setDeprecated(true, $parentDef->getDeprecationMessage('%service_id%')); + } + $def->setFactory($parentDef->getFactory()); + $def->setConfigurator($parentDef->getConfigurator()); + $def->setFile($parentDef->getFile()); + $def->setPublic($parentDef->isPublic()); + $def->setLazy($parentDef->isLazy()); + $def->setAutowired($parentDef->isAutowired()); + $def->setChanges($parentDef->getChanges()); + + $def->setBindings($parentDef->getBindings()); + + // overwrite with values specified in the decorator + $changes = $definition->getChanges(); + if (isset($changes['class'])) { + $def->setClass($definition->getClass()); + } + if (isset($changes['factory'])) { + $def->setFactory($definition->getFactory()); + } + if (isset($changes['configurator'])) { + $def->setConfigurator($definition->getConfigurator()); + } + if (isset($changes['file'])) { + $def->setFile($definition->getFile()); + } + if (isset($changes['public'])) { + $def->setPublic($definition->isPublic()); + } + if (isset($changes['lazy'])) { + $def->setLazy($definition->isLazy()); + } + if (isset($changes['deprecated'])) { + $def->setDeprecated($definition->isDeprecated(), $definition->getDeprecationMessage('%service_id%')); + } + if (isset($changes['autowired'])) { + $def->setAutowired($definition->isAutowired()); + } + if (isset($changes['shared'])) { + $def->setShared($definition->isShared()); + } + if (isset($changes['decorated_service'])) { + $decoratedService = $definition->getDecoratedService(); + if (null === $decoratedService) { + $def->setDecoratedService($decoratedService); + } else { + $def->setDecoratedService($decoratedService[0], $decoratedService[1], $decoratedService[2]); + } + } + + // merge arguments + foreach ($definition->getArguments() as $k => $v) { + if (is_numeric($k)) { + $def->addArgument($v); + } elseif (0 === strpos($k, 'index_')) { + $def->replaceArgument((int) substr($k, strlen('index_')), $v); + } else { + $def->setArgument($k, $v); + } + } + + // merge properties + foreach ($definition->getProperties() as $k => $v) { + $def->setProperty($k, $v); + } + + // append method calls + if ($calls = $definition->getMethodCalls()) { + $def->setMethodCalls(array_merge($def->getMethodCalls(), $calls)); + } + + // merge autowiring types + foreach ($definition->getAutowiringTypes(false) as $autowiringType) { + $def->addAutowiringType($autowiringType); + } + + // these attributes are always taken from the child + $def->setAbstract($definition->isAbstract()); + $def->setTags($definition->getTags()); + // autoconfigure is never taken from parent (on purpose) + // and it's not legal on an instanceof + $def->setAutoconfigured($definition->isAutoconfigured()); + + return $def; + } +} + +class_alias(ResolveChildDefinitionsPass::class, ResolveDefinitionTemplatesPass::class); diff --git a/src/Symfony/Component/DependencyInjection/Compiler/ResolveDefinitionTemplatesPass.php b/src/Symfony/Component/DependencyInjection/Compiler/ResolveDefinitionTemplatesPass.php index 89ca74c459b48..30678fa704c03 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/ResolveDefinitionTemplatesPass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/ResolveDefinitionTemplatesPass.php @@ -11,171 +11,19 @@ namespace Symfony\Component\DependencyInjection\Compiler; -use Symfony\Component\DependencyInjection\ChildDefinition; -use Symfony\Component\DependencyInjection\Definition; -use Symfony\Component\DependencyInjection\Exception\ExceptionInterface; -use Symfony\Component\DependencyInjection\Exception\RuntimeException; +@trigger_error('The '.__NAMESPACE__.'\ResolveDefinitionTemplatesPass class is deprecated since version 3.4 and will be removed in 4.0. Use the ResolveChildDefinitionsPass class instead.', E_USER_DEPRECATED); -/** - * This replaces all ChildDefinition instances with their equivalent fully - * merged Definition instance. - * - * @author Johannes M. Schmitt - * @author Nicolas Grekas - */ -class ResolveDefinitionTemplatesPass extends AbstractRecursivePass -{ - protected function processValue($value, $isRoot = false) - { - if (!$value instanceof Definition) { - return parent::processValue($value, $isRoot); - } - if ($isRoot) { - // yes, we are specifically fetching the definition from the - // container to ensure we are not operating on stale data - $value = $this->container->getDefinition($this->currentId); - } - if ($value instanceof ChildDefinition) { - $value = $this->resolveDefinition($value); - if ($isRoot) { - $this->container->setDefinition($this->currentId, $value); - } - } - - return parent::processValue($value, $isRoot); - } +class_exists(ResolveChildDefinitionsPass::class); +if (false) { /** - * Resolves the definition. + * This definition decorates another definition. * - * @return Definition + * @author Johannes M. Schmitt * - * @throws RuntimeException When the definition is invalid + * @deprecated The ResolveDefinitionTemplatesPass class is deprecated since version 3.4 and will be removed in 4.0. Use the ResolveChildDefinitionsPass class instead. */ - private function resolveDefinition(ChildDefinition $definition) + class ResolveDefinitionTemplatesPass extends AbstractRecursivePass { - try { - return $this->doResolveDefinition($definition); - } catch (ExceptionInterface $e) { - $r = new \ReflectionProperty($e, 'message'); - $r->setAccessible(true); - $r->setValue($e, sprintf('Service "%s": %s', $this->currentId, $e->getMessage())); - - throw $e; - } - } - - private function doResolveDefinition(ChildDefinition $definition) - { - if (!$this->container->has($parent = $definition->getParent())) { - throw new RuntimeException(sprintf('Parent definition "%s" does not exist.', $parent)); - } - - $parentDef = $this->container->findDefinition($parent); - if ($parentDef instanceof ChildDefinition) { - $id = $this->currentId; - $this->currentId = $parent; - $parentDef = $this->resolveDefinition($parentDef); - $this->container->setDefinition($parent, $parentDef); - $this->currentId = $id; - } - - $this->container->log($this, sprintf('Resolving inheritance for "%s" (parent: %s).', $this->currentId, $parent)); - $def = new Definition(); - - // merge in parent definition - // purposely ignored attributes: abstract, shared, tags, autoconfigured - $def->setClass($parentDef->getClass()); - $def->setArguments($parentDef->getArguments()); - $def->setMethodCalls($parentDef->getMethodCalls()); - $def->setProperties($parentDef->getProperties()); - if ($parentDef->getAutowiringTypes(false)) { - $def->setAutowiringTypes($parentDef->getAutowiringTypes(false)); - } - if ($parentDef->isDeprecated()) { - $def->setDeprecated(true, $parentDef->getDeprecationMessage('%service_id%')); - } - $def->setFactory($parentDef->getFactory()); - $def->setConfigurator($parentDef->getConfigurator()); - $def->setFile($parentDef->getFile()); - $def->setPublic($parentDef->isPublic()); - $def->setLazy($parentDef->isLazy()); - $def->setAutowired($parentDef->isAutowired()); - $def->setChanges($parentDef->getChanges()); - - $def->setBindings($parentDef->getBindings()); - - // overwrite with values specified in the decorator - $changes = $definition->getChanges(); - if (isset($changes['class'])) { - $def->setClass($definition->getClass()); - } - if (isset($changes['factory'])) { - $def->setFactory($definition->getFactory()); - } - if (isset($changes['configurator'])) { - $def->setConfigurator($definition->getConfigurator()); - } - if (isset($changes['file'])) { - $def->setFile($definition->getFile()); - } - if (isset($changes['public'])) { - $def->setPublic($definition->isPublic()); - } - if (isset($changes['lazy'])) { - $def->setLazy($definition->isLazy()); - } - if (isset($changes['deprecated'])) { - $def->setDeprecated($definition->isDeprecated(), $definition->getDeprecationMessage('%service_id%')); - } - if (isset($changes['autowired'])) { - $def->setAutowired($definition->isAutowired()); - } - if (isset($changes['shared'])) { - $def->setShared($definition->isShared()); - } - if (isset($changes['decorated_service'])) { - $decoratedService = $definition->getDecoratedService(); - if (null === $decoratedService) { - $def->setDecoratedService($decoratedService); - } else { - $def->setDecoratedService($decoratedService[0], $decoratedService[1], $decoratedService[2]); - } - } - - // merge arguments - foreach ($definition->getArguments() as $k => $v) { - if (is_numeric($k)) { - $def->addArgument($v); - } elseif (0 === strpos($k, 'index_')) { - $def->replaceArgument((int) substr($k, strlen('index_')), $v); - } else { - $def->setArgument($k, $v); - } - } - - // merge properties - foreach ($definition->getProperties() as $k => $v) { - $def->setProperty($k, $v); - } - - // append method calls - if ($calls = $definition->getMethodCalls()) { - $def->setMethodCalls(array_merge($def->getMethodCalls(), $calls)); - } - - // merge autowiring types - foreach ($definition->getAutowiringTypes(false) as $autowiringType) { - $def->addAutowiringType($autowiringType); - } - - // these attributes are always taken from the child - $def->setAbstract($definition->isAbstract()); - $def->setTags($definition->getTags()); - // autoconfigure is never taken from parent (on purpose) - // and it's not legal on an instanceof - $def->setAutoconfigured($definition->isAutoconfigured()); - - return $def; } } diff --git a/src/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveChildDefinitionsPassTest.php b/src/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveChildDefinitionsPassTest.php new file mode 100644 index 0000000000000..23a1915fd777c --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveChildDefinitionsPassTest.php @@ -0,0 +1,413 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Tests\Compiler; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\DependencyInjection\ChildDefinition; +use Symfony\Component\DependencyInjection\Compiler\ResolveChildDefinitionsPass; +use Symfony\Component\DependencyInjection\Compiler\ResolveDefinitionTemplatesPass; +use Symfony\Component\DependencyInjection\ContainerBuilder; + +class ResolveChildDefinitionsPassTest extends TestCase +{ + public function testProcess() + { + $container = new ContainerBuilder(); + $container->register('parent', 'foo')->setArguments(array('moo', 'b'))->setProperty('foo', 'moo'); + $container->setDefinition('child', new ChildDefinition('parent')) + ->replaceArgument(0, 'a') + ->setProperty('foo', 'bar') + ->setClass('bar') + ; + + $this->process($container); + + $def = $container->getDefinition('child'); + $this->assertNotInstanceOf(ChildDefinition::class, $def); + $this->assertEquals('bar', $def->getClass()); + $this->assertEquals(array('a', 'b'), $def->getArguments()); + $this->assertEquals(array('foo' => 'bar'), $def->getProperties()); + } + + public function testProcessAppendsMethodCallsAlways() + { + $container = new ContainerBuilder(); + + $container + ->register('parent') + ->addMethodCall('foo', array('bar')) + ; + + $container + ->setDefinition('child', new ChildDefinition('parent')) + ->addMethodCall('bar', array('foo')) + ; + + $this->process($container); + + $def = $container->getDefinition('child'); + $this->assertEquals(array( + array('foo', array('bar')), + array('bar', array('foo')), + ), $def->getMethodCalls()); + } + + public function testProcessDoesNotCopyAbstract() + { + $container = new ContainerBuilder(); + + $container + ->register('parent') + ->setAbstract(true) + ; + + $container + ->setDefinition('child', new ChildDefinition('parent')) + ; + + $this->process($container); + + $def = $container->getDefinition('child'); + $this->assertFalse($def->isAbstract()); + } + + public function testProcessDoesNotCopyShared() + { + $container = new ContainerBuilder(); + + $container + ->register('parent') + ->setShared(false) + ; + + $container + ->setDefinition('child', new ChildDefinition('parent')) + ; + + $this->process($container); + + $def = $container->getDefinition('child'); + $this->assertTrue($def->isShared()); + } + + public function testProcessDoesNotCopyTags() + { + $container = new ContainerBuilder(); + + $container + ->register('parent') + ->addTag('foo') + ; + + $container + ->setDefinition('child', new ChildDefinition('parent')) + ; + + $this->process($container); + + $def = $container->getDefinition('child'); + $this->assertEquals(array(), $def->getTags()); + } + + public function testProcessDoesNotCopyDecoratedService() + { + $container = new ContainerBuilder(); + + $container + ->register('parent') + ->setDecoratedService('foo') + ; + + $container + ->setDefinition('child', new ChildDefinition('parent')) + ; + + $this->process($container); + + $def = $container->getDefinition('child'); + $this->assertNull($def->getDecoratedService()); + } + + public function testProcessDoesNotDropShared() + { + $container = new ContainerBuilder(); + + $container + ->register('parent') + ; + + $container + ->setDefinition('child', new ChildDefinition('parent')) + ->setShared(false) + ; + + $this->process($container); + + $def = $container->getDefinition('child'); + $this->assertFalse($def->isShared()); + } + + public function testProcessHandlesMultipleInheritance() + { + $container = new ContainerBuilder(); + + $container + ->register('parent', 'foo') + ->setArguments(array('foo', 'bar', 'c')) + ; + + $container + ->setDefinition('child2', new ChildDefinition('child1')) + ->replaceArgument(1, 'b') + ; + + $container + ->setDefinition('child1', new ChildDefinition('parent')) + ->replaceArgument(0, 'a') + ; + + $this->process($container); + + $def = $container->getDefinition('child2'); + $this->assertEquals(array('a', 'b', 'c'), $def->getArguments()); + $this->assertEquals('foo', $def->getClass()); + } + + public function testSetLazyOnServiceHasParent() + { + $container = new ContainerBuilder(); + + $container->register('parent', 'stdClass'); + + $container->setDefinition('child1', new ChildDefinition('parent')) + ->setLazy(true) + ; + + $this->process($container); + + $this->assertTrue($container->getDefinition('child1')->isLazy()); + } + + public function testSetLazyOnServiceIsParent() + { + $container = new ContainerBuilder(); + + $container->register('parent', 'stdClass') + ->setLazy(true) + ; + + $container->setDefinition('child1', new ChildDefinition('parent')); + + $this->process($container); + + $this->assertTrue($container->getDefinition('child1')->isLazy()); + } + + public function testSetAutowiredOnServiceHasParent() + { + $container = new ContainerBuilder(); + + $container->register('parent', 'stdClass') + ->setAutowired(true) + ; + + $container->setDefinition('child1', new ChildDefinition('parent')) + ->setAutowired(false) + ; + + $this->process($container); + + $this->assertFalse($container->getDefinition('child1')->isAutowired()); + } + + public function testSetAutowiredOnServiceIsParent() + { + $container = new ContainerBuilder(); + + $container->register('parent', 'stdClass') + ->setAutowired(true) + ; + + $container->setDefinition('child1', new ChildDefinition('parent')); + + $this->process($container); + + $this->assertTrue($container->getDefinition('child1')->isAutowired()); + } + + public function testDeepDefinitionsResolving() + { + $container = new ContainerBuilder(); + + $container->register('parent', 'parentClass'); + $container->register('sibling', 'siblingClass') + ->setConfigurator(new ChildDefinition('parent'), 'foo') + ->setFactory(array(new ChildDefinition('parent'), 'foo')) + ->addArgument(new ChildDefinition('parent')) + ->setProperty('prop', new ChildDefinition('parent')) + ->addMethodCall('meth', array(new ChildDefinition('parent'))) + ; + + $this->process($container); + + $configurator = $container->getDefinition('sibling')->getConfigurator(); + $this->assertSame('Symfony\Component\DependencyInjection\Definition', get_class($configurator)); + $this->assertSame('parentClass', $configurator->getClass()); + + $factory = $container->getDefinition('sibling')->getFactory(); + $this->assertSame('Symfony\Component\DependencyInjection\Definition', get_class($factory[0])); + $this->assertSame('parentClass', $factory[0]->getClass()); + + $argument = $container->getDefinition('sibling')->getArgument(0); + $this->assertSame('Symfony\Component\DependencyInjection\Definition', get_class($argument)); + $this->assertSame('parentClass', $argument->getClass()); + + $properties = $container->getDefinition('sibling')->getProperties(); + $this->assertSame('Symfony\Component\DependencyInjection\Definition', get_class($properties['prop'])); + $this->assertSame('parentClass', $properties['prop']->getClass()); + + $methodCalls = $container->getDefinition('sibling')->getMethodCalls(); + $this->assertSame('Symfony\Component\DependencyInjection\Definition', get_class($methodCalls[0][1][0])); + $this->assertSame('parentClass', $methodCalls[0][1][0]->getClass()); + } + + public function testSetDecoratedServiceOnServiceHasParent() + { + $container = new ContainerBuilder(); + + $container->register('parent', 'stdClass'); + + $container->setDefinition('child1', new ChildDefinition('parent')) + ->setDecoratedService('foo', 'foo_inner', 5) + ; + + $this->process($container); + + $this->assertEquals(array('foo', 'foo_inner', 5), $container->getDefinition('child1')->getDecoratedService()); + } + + public function testDecoratedServiceCopiesDeprecatedStatusFromParent() + { + $container = new ContainerBuilder(); + $container->register('deprecated_parent') + ->setDeprecated(true) + ; + + $container->setDefinition('decorated_deprecated_parent', new ChildDefinition('deprecated_parent')); + + $this->process($container); + + $this->assertTrue($container->getDefinition('decorated_deprecated_parent')->isDeprecated()); + } + + public function testDecoratedServiceCanOverwriteDeprecatedParentStatus() + { + $container = new ContainerBuilder(); + $container->register('deprecated_parent') + ->setDeprecated(true) + ; + + $container->setDefinition('decorated_deprecated_parent', new ChildDefinition('deprecated_parent')) + ->setDeprecated(false) + ; + + $this->process($container); + + $this->assertFalse($container->getDefinition('decorated_deprecated_parent')->isDeprecated()); + } + + /** + * @group legacy + */ + public function testProcessMergeAutowiringTypes() + { + $container = new ContainerBuilder(); + + $container + ->register('parent') + ->addAutowiringType('Foo') + ; + + $container + ->setDefinition('child', new ChildDefinition('parent')) + ->addAutowiringType('Bar') + ; + + $this->process($container); + + $childDef = $container->getDefinition('child'); + $this->assertEquals(array('Foo', 'Bar'), $childDef->getAutowiringTypes()); + + $parentDef = $container->getDefinition('parent'); + $this->assertSame(array('Foo'), $parentDef->getAutowiringTypes()); + } + + public function testProcessResolvesAliases() + { + $container = new ContainerBuilder(); + + $container->register('parent', 'ParentClass'); + $container->setAlias('parent_alias', 'parent'); + $container->setDefinition('child', new ChildDefinition('parent_alias')); + + $this->process($container); + + $def = $container->getDefinition('child'); + $this->assertSame('ParentClass', $def->getClass()); + } + + public function testProcessSetsArguments() + { + $container = new ContainerBuilder(); + + $container->register('parent', 'ParentClass')->setArguments(array(0)); + $container->setDefinition('child', (new ChildDefinition('parent'))->setArguments(array( + 1, + 'index_0' => 2, + 'foo' => 3, + ))); + + $this->process($container); + + $def = $container->getDefinition('child'); + $this->assertSame(array(2, 1, 'foo' => 3), $def->getArguments()); + } + + public function testSetAutoconfiguredOnServiceIsParent() + { + $container = new ContainerBuilder(); + + $container->register('parent', 'stdClass') + ->setAutoconfigured(true) + ; + + $container->setDefinition('child1', new ChildDefinition('parent')); + + $this->process($container); + + $this->assertFalse($container->getDefinition('child1')->isAutoconfigured()); + } + + /** + * @group legacy + */ + public function testAliasExistsForBackwardsCompatibility() + { + $this->assertInstanceOf(ResolveChildDefinitionsPass::class, new ResolveDefinitionTemplatesPass()); + } + + protected function process(ContainerBuilder $container) + { + $pass = new ResolveChildDefinitionsPass(); + $pass->process($container); + } +} diff --git a/src/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveDefinitionTemplatesPassTest.php b/src/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveDefinitionTemplatesPassTest.php index 9c64c502f659a..3d83694840e4a 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveDefinitionTemplatesPassTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveDefinitionTemplatesPassTest.php @@ -16,6 +16,9 @@ use Symfony\Component\DependencyInjection\Compiler\ResolveDefinitionTemplatesPass; use Symfony\Component\DependencyInjection\ContainerBuilder; +/** + * @group legacy + */ class ResolveDefinitionTemplatesPassTest extends TestCase { public function testProcess() diff --git a/src/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveInstanceofConditionalsPassTest.php b/src/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveInstanceofConditionalsPassTest.php index 164ab25941d64..c97fe1dabac9b 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveInstanceofConditionalsPassTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveInstanceofConditionalsPassTest.php @@ -14,7 +14,7 @@ use PHPUnit\Framework\TestCase; use Symfony\Component\DependencyInjection\ChildDefinition; use Symfony\Component\DependencyInjection\Compiler\ResolveInstanceofConditionalsPass; -use Symfony\Component\DependencyInjection\Compiler\ResolveDefinitionTemplatesPass; +use Symfony\Component\DependencyInjection\Compiler\ResolveChildDefinitionsPass; use Symfony\Component\DependencyInjection\ContainerBuilder; class ResolveInstanceofConditionalsPassTest extends TestCase @@ -57,7 +57,7 @@ public function testProcessInheritance() $container->setDefinition('child', $def); (new ResolveInstanceofConditionalsPass())->process($container); - (new ResolveDefinitionTemplatesPass())->process($container); + (new ResolveChildDefinitionsPass())->process($container); $expected = array( array('foo', array('bar')), @@ -95,7 +95,7 @@ public function testProcessHandlesMultipleInheritance() )); (new ResolveInstanceofConditionalsPass())->process($container); - (new ResolveDefinitionTemplatesPass())->process($container); + (new ResolveChildDefinitionsPass())->process($container); $def = $container->getDefinition('foo'); $this->assertTrue($def->isAutowired()); @@ -119,7 +119,7 @@ public function testProcessUsesAutoconfiguredInstanceof() ->setFactory('autoconfigured_factory'); (new ResolveInstanceofConditionalsPass())->process($container); - (new ResolveDefinitionTemplatesPass())->process($container); + (new ResolveChildDefinitionsPass())->process($container); $def = $container->getDefinition('normal_service'); // autowired thanks to the autoconfigured instanceof @@ -147,7 +147,7 @@ public function testAutoconfigureInstanceofDoesNotDuplicateTags() ; (new ResolveInstanceofConditionalsPass())->process($container); - (new ResolveDefinitionTemplatesPass())->process($container); + (new ResolveChildDefinitionsPass())->process($container); $def = $container->getDefinition('normal_service'); $this->assertSame(array('duplicated_tag' => array(array(), array('and_attributes' => 1))), $def->getTags()); @@ -165,7 +165,7 @@ public function testProcessDoesNotUseAutoconfiguredInstanceofIfNotEnabled() ->setAutowired(true); (new ResolveInstanceofConditionalsPass())->process($container); - (new ResolveDefinitionTemplatesPass())->process($container); + (new ResolveChildDefinitionsPass())->process($container); $def = $container->getDefinition('normal_service'); $this->assertFalse($def->isAutowired()); From b9c6928d7e3070d6ae07c55505ac7f333f82d98c Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Thu, 7 Sep 2017 14:05:56 +0200 Subject: [PATCH 0785/1099] [HttpKernel] "controller.service_arguments" services should be public --- .../RegisterControllerArgumentLocatorsPass.php | 1 + ...RegisterControllerArgumentLocatorsPassTest.php | 15 +++++++++++++++ 2 files changed, 16 insertions(+) diff --git a/src/Symfony/Component/HttpKernel/DependencyInjection/RegisterControllerArgumentLocatorsPass.php b/src/Symfony/Component/HttpKernel/DependencyInjection/RegisterControllerArgumentLocatorsPass.php index 222185f52766f..9c00f99b7b003 100644 --- a/src/Symfony/Component/HttpKernel/DependencyInjection/RegisterControllerArgumentLocatorsPass.php +++ b/src/Symfony/Component/HttpKernel/DependencyInjection/RegisterControllerArgumentLocatorsPass.php @@ -50,6 +50,7 @@ public function process(ContainerBuilder $container) foreach ($container->findTaggedServiceIds($this->controllerTag, true) as $id => $tags) { $def = $container->getDefinition($id); + $def->setPublic(true); $class = $def->getClass(); $autowire = $def->isAutowired(); diff --git a/src/Symfony/Component/HttpKernel/Tests/DependencyInjection/RegisterControllerArgumentLocatorsPassTest.php b/src/Symfony/Component/HttpKernel/Tests/DependencyInjection/RegisterControllerArgumentLocatorsPassTest.php index 0542698d694ef..83a07cb4663d2 100644 --- a/src/Symfony/Component/HttpKernel/Tests/DependencyInjection/RegisterControllerArgumentLocatorsPassTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/DependencyInjection/RegisterControllerArgumentLocatorsPassTest.php @@ -266,6 +266,21 @@ public function testArgumentWithNoTypeHintIsOk() $locator = $container->getDefinition((string) $resolver->getArgument(0))->getArgument(0); $this->assertEmpty(array_keys($locator)); } + + public function testControllersAreMadePublic() + { + $container = new ContainerBuilder(); + $resolver = $container->register('argument_resolver.service')->addArgument(array()); + + $container->register('foo', ArgumentWithoutTypeController::class) + ->setPublic(false) + ->addTag('controller.service_arguments'); + + $pass = new RegisterControllerArgumentLocatorsPass(); + $pass->process($container); + + $this->assertTrue($container->getDefinition('foo')->isPublic()); + } } class RegisterTestController From a29e0694de139965a1e8e1f69dd84b46cca8ce89 Mon Sep 17 00:00:00 2001 From: Sergey Linnik Date: Tue, 5 Sep 2017 10:54:44 +0300 Subject: [PATCH 0786/1099] [Security] Fix exception when use_referer option is true and referer is not set or empty --- .../DefaultAuthenticationSuccessHandler.php | 5 ++--- .../DefaultAuthenticationSuccessHandlerTest.php | 10 ++++++++++ 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Component/Security/Http/Authentication/DefaultAuthenticationSuccessHandler.php b/src/Symfony/Component/Security/Http/Authentication/DefaultAuthenticationSuccessHandler.php index 7da6e35572b47..b7411e2c11d6c 100644 --- a/src/Symfony/Component/Security/Http/Authentication/DefaultAuthenticationSuccessHandler.php +++ b/src/Symfony/Component/Security/Http/Authentication/DefaultAuthenticationSuccessHandler.php @@ -118,12 +118,11 @@ protected function determineTargetUrl(Request $request) return $targetUrl; } - if ($this->options['use_referer']) { - $targetUrl = $request->headers->get('Referer'); + if ($this->options['use_referer'] && $targetUrl = $request->headers->get('Referer')) { if (false !== $pos = strpos($targetUrl, '?')) { $targetUrl = substr($targetUrl, 0, $pos); } - if ($targetUrl !== $this->httpUtils->generateUri($request, $this->options['login_path'])) { + if ($targetUrl && $targetUrl !== $this->httpUtils->generateUri($request, $this->options['login_path'])) { return $targetUrl; } } diff --git a/src/Symfony/Component/Security/Http/Tests/Authentication/DefaultAuthenticationSuccessHandlerTest.php b/src/Symfony/Component/Security/Http/Tests/Authentication/DefaultAuthenticationSuccessHandlerTest.php index b42f840358e03..a7b8547b6b53d 100644 --- a/src/Symfony/Component/Security/Http/Tests/Authentication/DefaultAuthenticationSuccessHandlerTest.php +++ b/src/Symfony/Component/Security/Http/Tests/Authentication/DefaultAuthenticationSuccessHandlerTest.php @@ -83,6 +83,16 @@ public function getRequestRedirections() array(), '/', ), + 'target path as referer when referer not set' => array( + Request::create('/'), + array('use_referer' => true), + '/', + ), + 'target path as referer when referer is ?' => array( + Request::create('/', 'GET', array(), array(), array(), array('HTTP_REFERER' => '?')), + array('use_referer' => true), + '/', + ), 'target path should be different than login URL' => array( Request::create('/', 'GET', array(), array(), array(), array('HTTP_REFERER' => 'http://localhost/login')), array('use_referer' => true, 'login_path' => '/login'), From 53387b4335f0c80604f09c3a8b588a0aca351138 Mon Sep 17 00:00:00 2001 From: Javier Eguiluz Date: Sun, 3 Sep 2017 19:39:07 +0200 Subject: [PATCH 0787/1099] Deprecated the web_profiler.position option --- src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md | 2 ++ .../WebProfilerBundle/DependencyInjection/Configuration.php | 1 + 2 files changed, 3 insertions(+) diff --git a/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md b/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md index dafd4c46bb0fc..c081103a8071e 100644 --- a/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md +++ b/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md @@ -53,6 +53,8 @@ CHANGELOG `EventDispatcherDebugCommand`, `RouterDebugCommand`, `RouterMatchCommand`, `TranslationDebugCommand`, `TranslationUpdateCommand`, `XliffLintCommand` and `YamlLintCommand` classes have been marked as final + * Deprecated the `web_profiler.position` config option (in Symfony 4.0 the toolbar + will always be displayed at the bottom). 3.3.0 ----- diff --git a/src/Symfony/Bundle/WebProfilerBundle/DependencyInjection/Configuration.php b/src/Symfony/Bundle/WebProfilerBundle/DependencyInjection/Configuration.php index 957a683ca3563..e07b28925de41 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/DependencyInjection/Configuration.php +++ b/src/Symfony/Bundle/WebProfilerBundle/DependencyInjection/Configuration.php @@ -39,6 +39,7 @@ public function getConfigTreeBuilder() ->booleanNode('toolbar')->defaultFalse()->end() ->scalarNode('position') ->defaultValue('bottom') + ->setDeprecated('The "web_profiler.position" configuration key has been deprecated in Symfony 3.4 and it will be removed in 4.0.') ->validate() ->ifNotInArray(array('bottom', 'top')) ->thenInvalid('The CSS position %s is not supported') From f19cf8a9164183614c69fa3180d51281ff765ac5 Mon Sep 17 00:00:00 2001 From: Florent Mata Date: Mon, 28 Aug 2017 15:28:19 +0200 Subject: [PATCH 0788/1099] [ExpressionLanguage] make a proposal in SyntaxError message --- .../Component/ExpressionLanguage/Parser.php | 4 ++-- .../ExpressionLanguage/SyntaxError.php | 17 ++++++++++++++++- .../ExpressionLanguage/Tests/ParserTest.php | 12 ++++++++++++ 3 files changed, 30 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Component/ExpressionLanguage/Parser.php b/src/Symfony/Component/ExpressionLanguage/Parser.php index c75972447dedf..3b367030155d2 100644 --- a/src/Symfony/Component/ExpressionLanguage/Parser.php +++ b/src/Symfony/Component/ExpressionLanguage/Parser.php @@ -195,13 +195,13 @@ public function parsePrimaryExpression() default: if ('(' === $this->stream->current->value) { if (false === isset($this->functions[$token->value])) { - throw new SyntaxError(sprintf('The function "%s" does not exist', $token->value), $token->cursor, $this->stream->getExpression()); + throw new SyntaxError(sprintf('The function "%s" does not exist', $token->value), $token->cursor, $this->stream->getExpression(), $token->value, array_keys($this->functions)); } $node = new Node\FunctionNode($token->value, $this->parseArguments()); } else { if (!in_array($token->value, $this->names, true)) { - throw new SyntaxError(sprintf('Variable "%s" is not valid', $token->value), $token->cursor, $this->stream->getExpression()); + throw new SyntaxError(sprintf('Variable "%s" is not valid', $token->value), $token->cursor, $this->stream->getExpression(), $token->value, $this->names); } // is the name used in the compiled code different diff --git a/src/Symfony/Component/ExpressionLanguage/SyntaxError.php b/src/Symfony/Component/ExpressionLanguage/SyntaxError.php index 9373e9980b8f5..12348e6830836 100644 --- a/src/Symfony/Component/ExpressionLanguage/SyntaxError.php +++ b/src/Symfony/Component/ExpressionLanguage/SyntaxError.php @@ -13,7 +13,7 @@ class SyntaxError extends \LogicException { - public function __construct($message, $cursor = 0, $expression = '') + public function __construct($message, $cursor = 0, $expression = '', $subject = null, array $proposals = null) { $message = sprintf('%s around position %d', $message, $cursor); if ($expression) { @@ -21,6 +21,21 @@ public function __construct($message, $cursor = 0, $expression = '') } $message .= '.'; + if (null !== $subject && null !== $proposals) { + $minScore = INF; + foreach ($proposals as $proposal) { + $distance = levenshtein($subject, $proposal); + if ($distance < $minScore) { + $guess = $proposal; + $minScore = $distance; + } + } + + if (isset($guess) && $minScore < 3) { + $message .= sprintf(' Did you mean "%s"?', $guess); + } + } + parent::__construct($message); } } diff --git a/src/Symfony/Component/ExpressionLanguage/Tests/ParserTest.php b/src/Symfony/Component/ExpressionLanguage/Tests/ParserTest.php index 13b80cd64fbed..11464abd23e13 100644 --- a/src/Symfony/Component/ExpressionLanguage/Tests/ParserTest.php +++ b/src/Symfony/Component/ExpressionLanguage/Tests/ParserTest.php @@ -195,4 +195,16 @@ public function getInvalidPostfixData() ), ); } + + /** + * @expectedException \Symfony\Component\ExpressionLanguage\SyntaxError + * @expectedExceptionMessage Did you mean "baz"? + */ + public function testNameProposal() + { + $lexer = new Lexer(); + $parser = new Parser(array()); + + $parser->parse($lexer->tokenize('foo > bar'), array('foo', 'baz')); + } } From 47b11068683f9750729d87f6b7c24524ae46607a Mon Sep 17 00:00:00 2001 From: Yonel Ceruto Date: Thu, 7 Sep 2017 11:35:49 -0400 Subject: [PATCH 0789/1099] Do not display short exception trace for built-in console exceptions --- src/Symfony/Component/Console/Application.php | 4 +++- .../Console/Tests/Fixtures/application_renderexception1.txt | 1 - .../Console/Tests/Fixtures/application_renderexception2.txt | 1 - .../Console/Tests/Fixtures/application_renderexception4.txt | 1 - 4 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/Symfony/Component/Console/Application.php b/src/Symfony/Component/Console/Application.php index 41c2a238e08a1..9cebe5768b26e 100644 --- a/src/Symfony/Component/Console/Application.php +++ b/src/Symfony/Component/Console/Application.php @@ -761,7 +761,9 @@ protected function doRenderException(\Exception $e, OutputInterface $output) } $messages = array(); - $messages[] = sprintf('%s', OutputFormatter::escape(sprintf('In %s line %s:', basename($e->getFile()) ?: 'n/a', $e->getLine() ?: 'n/a'))); + if (!$e instanceof ExceptionInterface || OutputInterface::VERBOSITY_VERBOSE <= $output->getVerbosity()) { + $messages[] = sprintf('%s', OutputFormatter::escape(sprintf('In %s line %s:', basename($e->getFile()) ?: 'n/a', $e->getLine() ?: 'n/a'))); + } $messages[] = $emptyLine = sprintf('%s', str_repeat(' ', $len)); if ('' === $message || OutputInterface::VERBOSITY_VERBOSE <= $output->getVerbosity()) { $messages[] = sprintf('%s%s', $title, str_repeat(' ', max(0, $len - Helper::strlen($title)))); diff --git a/src/Symfony/Component/Console/Tests/Fixtures/application_renderexception1.txt b/src/Symfony/Component/Console/Tests/Fixtures/application_renderexception1.txt index 700ffada3d2fa..1df5bd6494bbf 100644 --- a/src/Symfony/Component/Console/Tests/Fixtures/application_renderexception1.txt +++ b/src/Symfony/Component/Console/Tests/Fixtures/application_renderexception1.txt @@ -1,5 +1,4 @@ -In Application.php line 615: Command "foo" is not defined. diff --git a/src/Symfony/Component/Console/Tests/Fixtures/application_renderexception2.txt b/src/Symfony/Component/Console/Tests/Fixtures/application_renderexception2.txt index 457e6df46c0a9..932063d730d67 100644 --- a/src/Symfony/Component/Console/Tests/Fixtures/application_renderexception2.txt +++ b/src/Symfony/Component/Console/Tests/Fixtures/application_renderexception2.txt @@ -1,5 +1,4 @@ -In ArrayInput.php line 178: The "--foo" option does not exist. diff --git a/src/Symfony/Component/Console/Tests/Fixtures/application_renderexception4.txt b/src/Symfony/Component/Console/Tests/Fixtures/application_renderexception4.txt index 040564447f57b..548a13e56f22e 100644 --- a/src/Symfony/Component/Console/Tests/Fixtures/application_renderexception4.txt +++ b/src/Symfony/Component/Console/Tests/Fixtures/application_renderexception4.txt @@ -1,5 +1,4 @@ -In Application.php line 615: Command "foo" is not define d. From 3eb79e5197c8b4184bf4a250fc04bf4175bf65c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9goire=20Pineau?= Date: Fri, 8 Sep 2017 15:50:13 +0200 Subject: [PATCH 0790/1099] [Fabbot] Do not run php-cs-fixer if there are no change in src/ --- .php_cs.dist | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.php_cs.dist b/.php_cs.dist index 140fd3265011c..6282431a419d4 100644 --- a/.php_cs.dist +++ b/.php_cs.dist @@ -1,5 +1,9 @@ setRules(array( '@Symfony' => true, From 1605ce1f074d96c3e62eeb297b00a66ce9a28c53 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Fri, 8 Sep 2017 16:43:09 +0200 Subject: [PATCH 0791/1099] [Filesystem] skip tests if not applicable --- src/Symfony/Component/Filesystem/Tests/FilesystemTest.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Symfony/Component/Filesystem/Tests/FilesystemTest.php b/src/Symfony/Component/Filesystem/Tests/FilesystemTest.php index 44eeceabd9f49..67ccdd1eb06d2 100644 --- a/src/Symfony/Component/Filesystem/Tests/FilesystemTest.php +++ b/src/Symfony/Component/Filesystem/Tests/FilesystemTest.php @@ -1115,6 +1115,10 @@ public function testDumpFailsWithExceptionIfExecutablePermissionsForTheParentDir mkdir($target); chmod($this->workspace, 0666); + if (false !== @chdir($this->workspace)) { + $this->markTestSkipped('Test skipped as the used PHP version does not prevent entering directories without the required permissions.'); + } + $this->filesystem->dumpFile($file, 'baz'); } From 7793b797afbbe07d34b3ade2a4a368ddc5654af4 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Fri, 8 Sep 2017 18:12:06 -0700 Subject: [PATCH 0792/1099] Revert "bug #24105 [Filesystem] check permissions if dump target dir is missing (xabbuh)" This reverts commit d74144fc0b588bb8d7e0f73e6063e4022946f8e5, reversing changes made to 2b79f484058bd3265a39709e97a8787044b2ae7d. --- .../Component/Filesystem/Filesystem.php | 10 ---------- .../Filesystem/Tests/FilesystemTest.php | 20 ------------------- .../Filesystem/Tests/FilesystemTestCase.php | 1 - 3 files changed, 31 deletions(-) diff --git a/src/Symfony/Component/Filesystem/Filesystem.php b/src/Symfony/Component/Filesystem/Filesystem.php index bbef48b466885..bc2e3dcc2d897 100644 --- a/src/Symfony/Component/Filesystem/Filesystem.php +++ b/src/Symfony/Component/Filesystem/Filesystem.php @@ -532,16 +532,6 @@ public function dumpFile($filename, $content, $mode = 0666) $dir = dirname($filename); if (!is_dir($dir)) { - $oldCwd = getcwd(); - - if (!@chdir(dirname($dir))) { - // When the parent directory misses the executable permission bit, we are unable to enter it and thus - // cannot check if the target directory exists. - throw new IOException(sprintf('Unable to detect if the target directory "%s" exists.', $dir)); - } - - chdir($oldCwd); - $this->mkdir($dir); } diff --git a/src/Symfony/Component/Filesystem/Tests/FilesystemTest.php b/src/Symfony/Component/Filesystem/Tests/FilesystemTest.php index 67ccdd1eb06d2..b7bdfac4155e0 100644 --- a/src/Symfony/Component/Filesystem/Tests/FilesystemTest.php +++ b/src/Symfony/Component/Filesystem/Tests/FilesystemTest.php @@ -1102,26 +1102,6 @@ public function testDumpKeepsExistingPermissionsWhenOverwritingAnExistingFile() $this->assertFilePermissions(745, $filename); } - /** - * @expectedException \Symfony\Component\Filesystem\Exception\IOException - * @expectedExceptionMessageRegExp /^Unable to detect if the target directory ".*" exists\.$/ - */ - public function testDumpFailsWithExceptionIfExecutablePermissionsForTheParentDirectoryAreMissing() - { - $this->markAsSkippedIfChmodIsMissing(); - - $target = $this->workspace.DIRECTORY_SEPARATOR.'foo'; - $file = $target.DIRECTORY_SEPARATOR.'foobar'; - mkdir($target); - chmod($this->workspace, 0666); - - if (false !== @chdir($this->workspace)) { - $this->markTestSkipped('Test skipped as the used PHP version does not prevent entering directories without the required permissions.'); - } - - $this->filesystem->dumpFile($file, 'baz'); - } - public function testCopyShouldKeepExecutionPermission() { $this->markAsSkippedIfChmodIsMissing(); diff --git a/src/Symfony/Component/Filesystem/Tests/FilesystemTestCase.php b/src/Symfony/Component/Filesystem/Tests/FilesystemTestCase.php index 47598b29427da..5586a00547a68 100644 --- a/src/Symfony/Component/Filesystem/Tests/FilesystemTestCase.php +++ b/src/Symfony/Component/Filesystem/Tests/FilesystemTestCase.php @@ -61,7 +61,6 @@ protected function tearDown() $this->longPathNamesWindows = array(); } - chmod($this->workspace, 0777); $this->filesystem->remove($this->workspace); umask($this->umask); } From cafdf2b8e52418622ee3073d82e4c414e3479fd7 Mon Sep 17 00:00:00 2001 From: Javier Eguiluz Date: Mon, 31 Jul 2017 15:10:19 +0200 Subject: [PATCH 0793/1099] [WebProfilerBundle] Deprecated the web_profiler.position option --- .../Bundle/WebProfilerBundle/CHANGELOG.md | 2 ++ .../Controller/ProfilerController.php | 23 +++++---------- .../DependencyInjection/Configuration.php | 8 ------ .../WebProfilerExtension.php | 5 ++-- .../EventListener/WebDebugToolbarListener.php | 5 +--- .../Resources/config/profiler.xml | 1 - .../config/schema/webprofiler-1.0.xsd | 8 ------ .../Resources/config/toolbar.xml | 1 - .../Resources/views/Profiler/toolbar.css.twig | 28 ------------------- .../views/Profiler/toolbar_js.html.twig | 10 +------ .../Controller/ProfilerControllerTest.php | 2 +- .../DependencyInjection/ConfigurationTest.php | 12 ++++---- .../WebDebugToolbarListenerTest.php | 6 ++-- 13 files changed, 23 insertions(+), 88 deletions(-) diff --git a/src/Symfony/Bundle/WebProfilerBundle/CHANGELOG.md b/src/Symfony/Bundle/WebProfilerBundle/CHANGELOG.md index 260dbdae05c67..a7b7d840f89db 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/CHANGELOG.md +++ b/src/Symfony/Bundle/WebProfilerBundle/CHANGELOG.md @@ -6,6 +6,8 @@ CHANGELOG * removed the `WebProfilerExtension::dumpValue()` method * removed the `getTemplates()` method of the `TemplateManager` class in favor of the ``getNames()`` method + * removed the `web_profiler.position` config option and the + `web_profiler.debug_toolbar.position` container parameter 3.1.0 ----- diff --git a/src/Symfony/Bundle/WebProfilerBundle/Controller/ProfilerController.php b/src/Symfony/Bundle/WebProfilerBundle/Controller/ProfilerController.php index 7ebd04b574c22..4761eda00f938 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Controller/ProfilerController.php +++ b/src/Symfony/Bundle/WebProfilerBundle/Controller/ProfilerController.php @@ -34,28 +34,25 @@ class ProfilerController private $profiler; private $twig; private $templates; - private $toolbarPosition; private $cspHandler; private $baseDir; /** * Constructor. * - * @param UrlGeneratorInterface $generator The URL Generator - * @param Profiler $profiler The profiler - * @param Environment $twig The twig environment - * @param array $templates The templates - * @param string $toolbarPosition The toolbar position (top, bottom, normal, or null -- use the configuration) - * @param ContentSecurityPolicyHandler $cspHandler The Content-Security-Policy handler - * @param string $baseDir The project root directory + * @param UrlGeneratorInterface $generator The URL Generator + * @param Profiler $profiler The profiler + * @param Environment $twig The twig environment + * @param array $templates The templates + * @param ContentSecurityPolicyHandler $cspHandler The Content-Security-Policy handler + * @param string $baseDir The project root directory */ - public function __construct(UrlGeneratorInterface $generator, Profiler $profiler = null, Environment $twig, array $templates, $toolbarPosition = 'bottom', ContentSecurityPolicyHandler $cspHandler = null, $baseDir = null) + public function __construct(UrlGeneratorInterface $generator, Profiler $profiler = null, Environment $twig, array $templates, ContentSecurityPolicyHandler $cspHandler = null, $baseDir = null) { $this->generator = $generator; $this->profiler = $profiler; $this->twig = $twig; $this->templates = $templates; - $this->toolbarPosition = $toolbarPosition; $this->cspHandler = $cspHandler; $this->baseDir = $baseDir; } @@ -161,11 +158,6 @@ public function toolbarAction(Request $request, $token) return new Response('', 404, array('Content-Type' => 'text/html')); } - // the toolbar position (top, bottom, normal, or null -- use the configuration) - if (null === $position = $request->query->get('position')) { - $position = $this->toolbarPosition; - } - $url = null; try { $url = $this->generator->generate('_profiler', array('token' => $token)); @@ -175,7 +167,6 @@ public function toolbarAction(Request $request, $token) return $this->renderWithCspNonces($request, '@WebProfiler/Profiler/toolbar.html.twig', array( 'request' => $request, - 'position' => $position, 'profile' => $profile, 'templates' => $this->getTemplateManager()->getNames($profile), 'profiler_url' => $url, diff --git a/src/Symfony/Bundle/WebProfilerBundle/DependencyInjection/Configuration.php b/src/Symfony/Bundle/WebProfilerBundle/DependencyInjection/Configuration.php index e07b28925de41..812e311195993 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/DependencyInjection/Configuration.php +++ b/src/Symfony/Bundle/WebProfilerBundle/DependencyInjection/Configuration.php @@ -37,14 +37,6 @@ public function getConfigTreeBuilder() $rootNode ->children() ->booleanNode('toolbar')->defaultFalse()->end() - ->scalarNode('position') - ->defaultValue('bottom') - ->setDeprecated('The "web_profiler.position" configuration key has been deprecated in Symfony 3.4 and it will be removed in 4.0.') - ->validate() - ->ifNotInArray(array('bottom', 'top')) - ->thenInvalid('The CSS position %s is not supported') - ->end() - ->end() ->booleanNode('intercept_redirects')->defaultFalse()->end() ->scalarNode('excluded_ajax_paths')->defaultValue('^/(app(_[\\w]+)?\\.php/)?_wdt')->end() ->end() diff --git a/src/Symfony/Bundle/WebProfilerBundle/DependencyInjection/WebProfilerExtension.php b/src/Symfony/Bundle/WebProfilerBundle/DependencyInjection/WebProfilerExtension.php index e507bf2d22b70..e8e3ee87e9c1c 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/DependencyInjection/WebProfilerExtension.php +++ b/src/Symfony/Bundle/WebProfilerBundle/DependencyInjection/WebProfilerExtension.php @@ -44,11 +44,10 @@ public function load(array $configs, ContainerBuilder $container) $loader = new XmlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config')); $loader->load('profiler.xml'); - $container->setParameter('web_profiler.debug_toolbar.position', $config['position']); if ($config['toolbar'] || $config['intercept_redirects']) { $loader->load('toolbar.xml'); - $container->getDefinition('web_profiler.debug_toolbar')->replaceArgument(5, $config['excluded_ajax_paths']); + $container->getDefinition('web_profiler.debug_toolbar')->replaceArgument(4, $config['excluded_ajax_paths']); $container->setParameter('web_profiler.debug_toolbar.intercept_redirects', $config['intercept_redirects']); $container->setParameter('web_profiler.debug_toolbar.mode', $config['toolbar'] ? WebDebugToolbarListener::ENABLED : WebDebugToolbarListener::DISABLED); } @@ -66,7 +65,7 @@ public function load(array $configs, ContainerBuilder $container) $baseDir = implode(DIRECTORY_SEPARATOR, $baseDir); $profilerController = $container->getDefinition('web_profiler.controller.profiler'); - $profilerController->replaceArgument(6, $baseDir); + $profilerController->replaceArgument(5, $baseDir); $fileLinkFormatter = $container->getDefinition('debug.file_link_formatter'); $fileLinkFormatter->replaceArgument(2, $baseDir); diff --git a/src/Symfony/Bundle/WebProfilerBundle/EventListener/WebDebugToolbarListener.php b/src/Symfony/Bundle/WebProfilerBundle/EventListener/WebDebugToolbarListener.php index 6ffdbc7ad0764..d99f9d5b32d9c 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/EventListener/WebDebugToolbarListener.php +++ b/src/Symfony/Bundle/WebProfilerBundle/EventListener/WebDebugToolbarListener.php @@ -40,17 +40,15 @@ class WebDebugToolbarListener implements EventSubscriberInterface protected $urlGenerator; protected $interceptRedirects; protected $mode; - protected $position; protected $excludedAjaxPaths; private $cspHandler; - public function __construct(Environment $twig, $interceptRedirects = false, $mode = self::ENABLED, $position = 'bottom', UrlGeneratorInterface $urlGenerator = null, $excludedAjaxPaths = '^/bundles|^/_wdt', ContentSecurityPolicyHandler $cspHandler = null) + public function __construct(Environment $twig, $interceptRedirects = false, $mode = self::ENABLED, UrlGeneratorInterface $urlGenerator = null, $excludedAjaxPaths = '^/bundles|^/_wdt', ContentSecurityPolicyHandler $cspHandler = null) { $this->twig = $twig; $this->urlGenerator = $urlGenerator; $this->interceptRedirects = (bool) $interceptRedirects; $this->mode = (int) $mode; - $this->position = $position; $this->excludedAjaxPaths = $excludedAjaxPaths; $this->cspHandler = $cspHandler; } @@ -124,7 +122,6 @@ protected function injectToolbar(Response $response, Request $request, array $no $toolbar = "\n".str_replace("\n", '', $this->twig->render( '@WebProfiler/Profiler/toolbar_js.html.twig', array( - 'position' => $this->position, 'excluded_ajax_paths' => $this->excludedAjaxPaths, 'token' => $response->headers->get('X-Debug-Token'), 'request' => $request, diff --git a/src/Symfony/Bundle/WebProfilerBundle/Resources/config/profiler.xml b/src/Symfony/Bundle/WebProfilerBundle/Resources/config/profiler.xml index 4c659b628144d..538bea8ef3087 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Resources/config/profiler.xml +++ b/src/Symfony/Bundle/WebProfilerBundle/Resources/config/profiler.xml @@ -12,7 +12,6 @@ %data_collector.templates% - %web_profiler.debug_toolbar.position% null diff --git a/src/Symfony/Bundle/WebProfilerBundle/Resources/config/schema/webprofiler-1.0.xsd b/src/Symfony/Bundle/WebProfilerBundle/Resources/config/schema/webprofiler-1.0.xsd index 84cc8ae9a97f3..e22105a178fa7 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Resources/config/schema/webprofiler-1.0.xsd +++ b/src/Symfony/Bundle/WebProfilerBundle/Resources/config/schema/webprofiler-1.0.xsd @@ -10,13 +10,5 @@ - - - - - - - - diff --git a/src/Symfony/Bundle/WebProfilerBundle/Resources/config/toolbar.xml b/src/Symfony/Bundle/WebProfilerBundle/Resources/config/toolbar.xml index 25f49fc2cd069..da06324ac6ede 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Resources/config/toolbar.xml +++ b/src/Symfony/Bundle/WebProfilerBundle/Resources/config/toolbar.xml @@ -12,7 +12,6 @@ %web_profiler.debug_toolbar.intercept_redirects% %web_profiler.debug_toolbar.mode% - %web_profiler.debug_toolbar.position% diff --git a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/toolbar.css.twig b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/toolbar.css.twig index ac2e38eea1842..74d3c8b5b3e56 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/toolbar.css.twig +++ b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/toolbar.css.twig @@ -416,34 +416,6 @@ display: none; } -/* Override the setting when the toolbar is on the top */ -{% if position == 'top' %} - .sf-minitoolbar { - border-bottom-left-radius: 4px; - border-top-left-radius: 0; - bottom: auto; - right: 0; - top: 0; - } - - .sf-toolbarreset { - bottom: auto; - box-shadow: 0 1px 0 rgba(0, 0, 0, 0.2); - top: 0; - } - - .sf-toolbar-block .sf-toolbar-info { - bottom: auto; - top: 36px; - } -{% endif %} - -{% if not floatable %} - .sf-toolbarreset { - position: static; - } -{% endif %} - /* Responsive Design */ .sf-toolbar-icon .sf-toolbar-label, .sf-toolbar-icon .sf-toolbar-value { diff --git a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/toolbar_js.html.twig b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/toolbar_js.html.twig index 33a59d4322925..c2b91f5261057 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/toolbar_js.html.twig +++ b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/toolbar_js.html.twig @@ -1,18 +1,10 @@
{{ include('@WebProfiler/Profiler/base_js.html.twig') }} - {{ include('@WebProfiler/Profiler/toolbar.css.twig', { 'position': position, 'floatable': true }) }} + {{ include('@WebProfiler/Profiler/toolbar.css.twig') }} /*getMockBuilder('Symfony\Bundle\WebProfilerBundle\Csp\NonceGenerator')->getMock(); - return new ProfilerController($urlGenerator, $profiler, $twig, array(), 'bottom', new ContentSecurityPolicyHandler($nonceGenerator)); + return new ProfilerController($urlGenerator, $profiler, $twig, array(), new ContentSecurityPolicyHandler($nonceGenerator)); } return new ProfilerController($urlGenerator, $profiler, $twig, array()); diff --git a/src/Symfony/Bundle/WebProfilerBundle/Tests/DependencyInjection/ConfigurationTest.php b/src/Symfony/Bundle/WebProfilerBundle/Tests/DependencyInjection/ConfigurationTest.php index b11f6928b4e92..d10c56a167ae3 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Tests/DependencyInjection/ConfigurationTest.php +++ b/src/Symfony/Bundle/WebProfilerBundle/Tests/DependencyInjection/ConfigurationTest.php @@ -32,12 +32,12 @@ public function testConfigTree($options, $results) public function getDebugModes() { return array( - array(array(), array('intercept_redirects' => false, 'toolbar' => false, 'position' => 'bottom', 'excluded_ajax_paths' => '^/(app(_[\\w]+)?\\.php/)?_wdt')), - array(array('intercept_redirects' => true), array('intercept_redirects' => true, 'toolbar' => false, 'position' => 'bottom', 'excluded_ajax_paths' => '^/(app(_[\\w]+)?\\.php/)?_wdt')), - array(array('intercept_redirects' => false), array('intercept_redirects' => false, 'toolbar' => false, 'position' => 'bottom', 'excluded_ajax_paths' => '^/(app(_[\\w]+)?\\.php/)?_wdt')), - array(array('toolbar' => true), array('intercept_redirects' => false, 'toolbar' => true, 'position' => 'bottom', 'excluded_ajax_paths' => '^/(app(_[\\w]+)?\\.php/)?_wdt')), - array(array('position' => 'top'), array('intercept_redirects' => false, 'toolbar' => false, 'position' => 'top', 'excluded_ajax_paths' => '^/(app(_[\\w]+)?\\.php/)?_wdt')), - array(array('excluded_ajax_paths' => 'test'), array('intercept_redirects' => false, 'toolbar' => false, 'position' => 'bottom', 'excluded_ajax_paths' => 'test')), + array(array(), array('intercept_redirects' => false, 'toolbar' => false, 'excluded_ajax_paths' => '^/(app(_[\\w]+)?\\.php/)?_wdt')), + array(array('intercept_redirects' => true), array('intercept_redirects' => true, 'toolbar' => false, 'excluded_ajax_paths' => '^/(app(_[\\w]+)?\\.php/)?_wdt')), + array(array('intercept_redirects' => false), array('intercept_redirects' => false, 'toolbar' => false, 'excluded_ajax_paths' => '^/(app(_[\\w]+)?\\.php/)?_wdt')), + array(array('toolbar' => true), array('intercept_redirects' => false, 'toolbar' => true, 'excluded_ajax_paths' => '^/(app(_[\\w]+)?\\.php/)?_wdt')), + array(array(), array('intercept_redirects' => false, 'toolbar' => false, 'excluded_ajax_paths' => '^/(app(_[\\w]+)?\\.php/)?_wdt')), + array(array('excluded_ajax_paths' => 'test'), array('intercept_redirects' => false, 'toolbar' => false, 'excluded_ajax_paths' => 'test')), ); } } diff --git a/src/Symfony/Bundle/WebProfilerBundle/Tests/EventListener/WebDebugToolbarListenerTest.php b/src/Symfony/Bundle/WebProfilerBundle/Tests/EventListener/WebDebugToolbarListenerTest.php index 5e5e7a21fe76b..6b2f11e36b542 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Tests/EventListener/WebDebugToolbarListenerTest.php +++ b/src/Symfony/Bundle/WebProfilerBundle/Tests/EventListener/WebDebugToolbarListenerTest.php @@ -219,7 +219,7 @@ public function testXDebugUrlHeader() $event = new FilterResponseEvent($this->getKernelMock(), $this->getRequestMock(), HttpKernelInterface::MASTER_REQUEST, $response); - $listener = new WebDebugToolbarListener($this->getTwigMock(), false, WebDebugToolbarListener::ENABLED, 'bottom', $urlGenerator); + $listener = new WebDebugToolbarListener($this->getTwigMock(), false, WebDebugToolbarListener::ENABLED, $urlGenerator); $listener->onKernelResponse($event); $this->assertEquals('http://mydomain.com/_profiler/xxxxxxxx', $response->headers->get('X-Debug-Token-Link')); @@ -240,7 +240,7 @@ public function testThrowingUrlGenerator() $event = new FilterResponseEvent($this->getKernelMock(), $this->getRequestMock(), HttpKernelInterface::MASTER_REQUEST, $response); - $listener = new WebDebugToolbarListener($this->getTwigMock(), false, WebDebugToolbarListener::ENABLED, 'bottom', $urlGenerator); + $listener = new WebDebugToolbarListener($this->getTwigMock(), false, WebDebugToolbarListener::ENABLED, $urlGenerator); $listener->onKernelResponse($event); $this->assertEquals('Exception: foo', $response->headers->get('X-Debug-Error')); @@ -261,7 +261,7 @@ public function testThrowingErrorCleanup() $event = new FilterResponseEvent($this->getKernelMock(), $this->getRequestMock(), HttpKernelInterface::MASTER_REQUEST, $response); - $listener = new WebDebugToolbarListener($this->getTwigMock(), false, WebDebugToolbarListener::ENABLED, 'bottom', $urlGenerator); + $listener = new WebDebugToolbarListener($this->getTwigMock(), false, WebDebugToolbarListener::ENABLED, $urlGenerator); $listener->onKernelResponse($event); $this->assertEquals('Exception: This multiline tabbed text should come out on a single plain line', $response->headers->get('X-Debug-Error')); From 2a696d3a1e1e5b23f916384b3a5ff1145b1284d6 Mon Sep 17 00:00:00 2001 From: Javier Eguiluz Date: Thu, 7 Sep 2017 17:53:58 +0200 Subject: [PATCH 0794/1099] Fixed deprecations in WebProfiler tests --- .../Bundle/FrameworkBundle/CHANGELOG.md | 2 -- .../Bundle/WebProfilerBundle/CHANGELOG.md | 7 ++++++ .../DependencyInjection/ConfigurationTest.php | 23 ++++++++++++++++++- .../Bundle/WebProfilerBundle/composer.json | 3 ++- 4 files changed, 31 insertions(+), 4 deletions(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md b/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md index c081103a8071e..dafd4c46bb0fc 100644 --- a/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md +++ b/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md @@ -53,8 +53,6 @@ CHANGELOG `EventDispatcherDebugCommand`, `RouterDebugCommand`, `RouterMatchCommand`, `TranslationDebugCommand`, `TranslationUpdateCommand`, `XliffLintCommand` and `YamlLintCommand` classes have been marked as final - * Deprecated the `web_profiler.position` config option (in Symfony 4.0 the toolbar - will always be displayed at the bottom). 3.3.0 ----- diff --git a/src/Symfony/Bundle/WebProfilerBundle/CHANGELOG.md b/src/Symfony/Bundle/WebProfilerBundle/CHANGELOG.md index 64102cc761c34..c1259b0a20e1d 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/CHANGELOG.md +++ b/src/Symfony/Bundle/WebProfilerBundle/CHANGELOG.md @@ -1,6 +1,13 @@ CHANGELOG ========= +3.4.0 +----- + + * Deprecated the `web_profiler.position` config option (in 4.0 version the toolbar + will always be displayed at the bottom) and the `web_profiler.debug_toolbar.position` + container parameter. + 3.1.0 ----- diff --git a/src/Symfony/Bundle/WebProfilerBundle/Tests/DependencyInjection/ConfigurationTest.php b/src/Symfony/Bundle/WebProfilerBundle/Tests/DependencyInjection/ConfigurationTest.php index b11f6928b4e92..afbecf9b381e9 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Tests/DependencyInjection/ConfigurationTest.php +++ b/src/Symfony/Bundle/WebProfilerBundle/Tests/DependencyInjection/ConfigurationTest.php @@ -29,6 +29,20 @@ public function testConfigTree($options, $results) $this->assertEquals($results, $config); } + /** + * @dataProvider getPositionConfig + * @group legacy + * @expectedDeprecation The "web_profiler.position" configuration key has been deprecated in Symfony 3.4 and it will be removed in 4.0. + */ + public function testPositionConfig($options, $results) + { + $processor = new Processor(); + $configuration = new Configuration(); + $config = $processor->processConfiguration($configuration, array($options)); + + $this->assertEquals($results, $config); + } + public function getDebugModes() { return array( @@ -36,8 +50,15 @@ public function getDebugModes() array(array('intercept_redirects' => true), array('intercept_redirects' => true, 'toolbar' => false, 'position' => 'bottom', 'excluded_ajax_paths' => '^/(app(_[\\w]+)?\\.php/)?_wdt')), array(array('intercept_redirects' => false), array('intercept_redirects' => false, 'toolbar' => false, 'position' => 'bottom', 'excluded_ajax_paths' => '^/(app(_[\\w]+)?\\.php/)?_wdt')), array(array('toolbar' => true), array('intercept_redirects' => false, 'toolbar' => true, 'position' => 'bottom', 'excluded_ajax_paths' => '^/(app(_[\\w]+)?\\.php/)?_wdt')), - array(array('position' => 'top'), array('intercept_redirects' => false, 'toolbar' => false, 'position' => 'top', 'excluded_ajax_paths' => '^/(app(_[\\w]+)?\\.php/)?_wdt')), array(array('excluded_ajax_paths' => 'test'), array('intercept_redirects' => false, 'toolbar' => false, 'position' => 'bottom', 'excluded_ajax_paths' => 'test')), ); } + + public function getPositionConfig() + { + return array( + array(array('position' => 'top'), array('intercept_redirects' => false, 'toolbar' => false, 'excluded_ajax_paths' => '^/(app(_[\\w]+)?\\.php/)?_wdt', 'position' => 'top')), + array(array('position' => 'bottom'), array('intercept_redirects' => false, 'toolbar' => false, 'excluded_ajax_paths' => '^/(app(_[\\w]+)?\\.php/)?_wdt', 'position' => 'bottom')), + ); + } } diff --git a/src/Symfony/Bundle/WebProfilerBundle/composer.json b/src/Symfony/Bundle/WebProfilerBundle/composer.json index c49d793016e04..40ead3bff2564 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/composer.json +++ b/src/Symfony/Bundle/WebProfilerBundle/composer.json @@ -25,12 +25,13 @@ "twig/twig": "~1.34|~2.4" }, "require-dev": { - "symfony/config": "~2.8|~3.0|~4.0", + "symfony/config": "~3.4|~4.0", "symfony/console": "~2.8|~3.0|~4.0", "symfony/dependency-injection": "~3.3|~4.0", "symfony/stopwatch": "~2.8|~3.0|~4.0" }, "conflict": { + "symfony/config": "<3.4", "symfony/dependency-injection": "<3.3", "symfony/event-dispatcher": "<3.3", "symfony/var-dumper": "<3.3" From efa4cb9a66eca0f3bc533b6253a441b57e510e8a Mon Sep 17 00:00:00 2001 From: Robin Chalas Date: Sat, 9 Sep 2017 08:49:11 +0200 Subject: [PATCH 0795/1099] [SecurityBundle] Fix valid provider considered undefined --- .../DependencyInjection/SecurityExtension.php | 10 ++++---- .../CompleteConfigurationTest.php | 12 ++++++++++ .../Fixtures/php/firewall_provider.php | 24 +++++++++++++++++++ .../Fixtures/php/listener_provider.php | 16 +++++++++++++ .../Fixtures/xml/firewall_provider.xml | 20 ++++++++++++++++ .../Fixtures/xml/listener_provider.xml | 20 ++++++++++++++++ .../Fixtures/yml/firewall_provider.yml | 16 +++++++++++++ .../Fixtures/yml/listener_provider.yml | 10 ++++++++ 8 files changed, 123 insertions(+), 5 deletions(-) create mode 100644 src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/firewall_provider.php create mode 100644 src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/listener_provider.php create mode 100644 src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/firewall_provider.xml create mode 100644 src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/listener_provider.xml create mode 100644 src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/firewall_provider.yml create mode 100644 src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/listener_provider.yml diff --git a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php index adfe5b235752b..73a1cef128dd8 100644 --- a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php +++ b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php @@ -331,10 +331,10 @@ private function createFirewall(ContainerBuilder $container, $id, $firewall, &$a // Provider id (take the first registered provider if none defined) if (isset($firewall['provider'])) { - $defaultProvider = $this->getUserProviderId($firewall['provider']); - if (!in_array($defaultProvider, $providerIds, true)) { + if (!isset($providerIds[$normalizedName = str_replace('-', '_', $firewall['provider'])])) { throw new InvalidConfigurationException(sprintf('Invalid firewall "%s": user provider "%s" not found.', $id, $firewall['provider'])); } + $defaultProvider = $providerIds[$normalizedName]; } else { $defaultProvider = reset($providerIds); } @@ -491,10 +491,10 @@ private function createAuthenticationListeners($container, $id, $firewall, &$aut if (isset($firewall[$key])) { if (isset($firewall[$key]['provider'])) { - if (!in_array($firewall[$key]['provider'], $providerIds, true)) { + if (!isset($providerIds[$normalizedName = str_replace('-', '_', $firewall[$key]['provider'])])) { throw new InvalidConfigurationException(sprintf('Invalid firewall "%s": user provider "%s" not found.', $id, $firewall[$key]['provider'])); } - $userProvider = $this->getUserProviderId($firewall[$key]['provider']); + $userProvider = $providerIds[$normalizedName]; } else { $userProvider = $defaultProvider; } @@ -596,7 +596,7 @@ private function createUserProviders($config, ContainerBuilder $container) $providerIds = array(); foreach ($config['providers'] as $name => $provider) { $id = $this->createUserDaoProvider($name, $provider, $container); - $providerIds[] = $id; + $providerIds[str_replace('-', '_', $name)] = $id; } return $providerIds; diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/CompleteConfigurationTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/CompleteConfigurationTest.php index 202107a57abf2..1cb5a6acda066 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/CompleteConfigurationTest.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/CompleteConfigurationTest.php @@ -405,6 +405,18 @@ public function testFirewallListenerUndefinedProvider() $this->getContainer('listener_undefined_provider'); } + public function testFirewallWithUserProvider() + { + $this->getContainer('firewall_provider'); + $this->addToAssertionCount(1); + } + + public function testFirewallListenerWithProvider() + { + $this->getContainer('listener_provider'); + $this->addToAssertionCount(1); + } + protected function getContainer($file) { $file = $file.'.'.$this->getFileExtension(); diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/firewall_provider.php b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/firewall_provider.php new file mode 100644 index 0000000000000..ff9d9f6b89df6 --- /dev/null +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/firewall_provider.php @@ -0,0 +1,24 @@ +loadFromExtension('security', array( + 'providers' => array( + 'default' => array( + 'memory' => $memory = array( + 'users' => array('foo' => array('password' => 'foo', 'roles' => 'ROLE_USER')), + ), + ), + 'with-dash' => array( + 'memory' => $memory, + ), + ), + 'firewalls' => array( + 'main' => array( + 'provider' => 'default', + 'form_login' => true, + ), + 'other' => array( + 'provider' => 'with-dash', + 'form_login' => true, + ), + ), +)); diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/listener_provider.php b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/listener_provider.php new file mode 100644 index 0000000000000..d7f1cd6973f36 --- /dev/null +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/listener_provider.php @@ -0,0 +1,16 @@ +loadFromExtension('security', array( + 'providers' => array( + 'default' => array( + 'memory' => array( + 'users' => array('foo' => array('password' => 'foo', 'roles' => 'ROLE_USER')), + ), + ), + ), + 'firewalls' => array( + 'main' => array( + 'form_login' => array('provider' => 'default'), + ), + ), +)); diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/firewall_provider.xml b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/firewall_provider.xml new file mode 100644 index 0000000000000..bd87fee4abae9 --- /dev/null +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/firewall_provider.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/listener_provider.xml b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/listener_provider.xml new file mode 100644 index 0000000000000..b1bcd8eae8155 --- /dev/null +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/listener_provider.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/firewall_provider.yml b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/firewall_provider.yml new file mode 100644 index 0000000000000..11c329aa8e2fe --- /dev/null +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/firewall_provider.yml @@ -0,0 +1,16 @@ +security: + providers: + default: + memory: + users: { foo: { password: foo, roles: ROLE_USER } } + with-dash: + memory: + users: { foo: { password: foo, roles: ROLE_USER } } + + firewalls: + main: + provider: default + form_login: true + other: + provider: with-dash + form_login: true diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/listener_provider.yml b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/listener_provider.yml new file mode 100644 index 0000000000000..652f23b5f0425 --- /dev/null +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/listener_provider.yml @@ -0,0 +1,10 @@ +security: + providers: + default: + memory: + users: { foo: { password: foo, roles: ROLE_USER } } + + firewalls: + main: + form_login: + provider: default From bfae4549680358a6fd4d9fb82f047048efdc57d6 Mon Sep 17 00:00:00 2001 From: SpacePossum Date: Mon, 11 Sep 2017 07:17:31 +0200 Subject: [PATCH 0796/1099] Remove `protected_to_private` rule. --- .php_cs.dist | 1 + 1 file changed, 1 insertion(+) diff --git a/.php_cs.dist b/.php_cs.dist index 2e432b791eed0..04d9ec5bdc5a8 100644 --- a/.php_cs.dist +++ b/.php_cs.dist @@ -13,6 +13,7 @@ return PhpCsFixer\Config::create() 'braces' => array('allow_single_line_closure' => true), 'heredoc_to_nowdoc' => false, 'phpdoc_annotation_without_dot' => false, + 'protected_to_private' => false, )) ->setRiskyAllowed(true) ->setFinder( From 122da5add5fd298983503e82fb8a47a10f258d79 Mon Sep 17 00:00:00 2001 From: Mara Blaga Date: Mon, 11 Sep 2017 15:10:51 +0100 Subject: [PATCH 0797/1099] [DomCrawler] Fix conversion to int on GetPhpFiles --- src/Symfony/Component/DomCrawler/Form.php | 12 ++++++++++++ src/Symfony/Component/DomCrawler/Tests/FormTest.php | 9 +++++++++ 2 files changed, 21 insertions(+) diff --git a/src/Symfony/Component/DomCrawler/Form.php b/src/Symfony/Component/DomCrawler/Form.php index bad1b34935d04..db4d60dd3d141 100644 --- a/src/Symfony/Component/DomCrawler/Form.php +++ b/src/Symfony/Component/DomCrawler/Form.php @@ -172,6 +172,18 @@ public function getPhpFiles() if (!empty($qs)) { parse_str($qs, $expandedValue); $varName = substr($name, 0, strlen(key($expandedValue))); + + array_walk_recursive( + $expandedValue, + function (&$value, $key) { + if (ctype_digit($value) && ('size' === $key || 'error' === $key)) { + $value = (int) $value; + } + } + ); + + reset($expandedValue); + $values = array_replace_recursive($values, array($varName => current($expandedValue))); } } diff --git a/src/Symfony/Component/DomCrawler/Tests/FormTest.php b/src/Symfony/Component/DomCrawler/Tests/FormTest.php index 0a4cd7201e1bb..437a5ddaf0cbf 100644 --- a/src/Symfony/Component/DomCrawler/Tests/FormTest.php +++ b/src/Symfony/Component/DomCrawler/Tests/FormTest.php @@ -456,6 +456,15 @@ public function testGetPhpFiles() $form = $this->createForm(''); $this->assertEquals(array('f.o o' => array('bar' => array('ba.z' => array('name' => '', 'type' => '', 'tmp_name' => '', 'error' => 4, 'size' => 0), array('name' => '', 'type' => '', 'tmp_name' => '', 'error' => 4, 'size' => 0)))), $form->getPhpFiles(), '->getPhpFiles() preserves periods and spaces in names recursively'); + + $form = $this->createForm('
'); + $files = $form->getPhpFiles(); + + $this->assertSame(0, $files['foo']['bar']['size'], '->getPhpFiles() converts size to int'); + $this->assertSame(4, $files['foo']['bar']['error'], '->getPhpFiles() converts error to int'); + + $form = $this->createForm('
'); + $this->assertEquals(array('size' => array('error' => array('name' => '', 'type' => '', 'tmp_name' => '', 'error' => 4, 'size' => 0))), $form->getPhpFiles(), '->getPhpFiles() int conversion does not collide with file names'); } /** From 4fa6fcfb93e0adda06a8136dc3870f84fc48dceb Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Mon, 11 Sep 2017 09:13:13 -0700 Subject: [PATCH 0798/1099] updated CHANGELOG for 3.3.9 --- CHANGELOG-3.3.md | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/CHANGELOG-3.3.md b/CHANGELOG-3.3.md index 3331ea2a1d1fa..320bf84f1dc7d 100644 --- a/CHANGELOG-3.3.md +++ b/CHANGELOG-3.3.md @@ -7,6 +7,23 @@ in 3.3 minor versions. To get the diff for a specific change, go to https://github.com/symfony/symfony/commit/XXX where XXX is the change hash To get the diff between two versions, go to https://github.com/symfony/symfony/compare/v3.3.0...v3.3.1 +* 3.3.9 (2017-09-11) + + * bug #24141 [DomCrawler] Fix conversion to int on GetPhpFiles (MaraBlaga) + * bug #23853 Filtering empty uuids in ORMQueryBuilderLoader. (mlazovla) + * bug #24101 [Security] Fix exception when use_referer option is true and referer is not set or empty (linniksa) + * bug #24105 [Filesystem] check permissions if dump target dir is missing (xabbuh) + * bug #24126 [HttpKernel] "controller.service_arguments" services should be public (nicolas-grekas) + * bug #24113 [FrameworkBundle] Get KERNEL_CLASS through $_ENV too for KernelTestCase (yceruto) + * bug #24115 [FrameworkBundle] Get KERNEL_DIR through $_ENV too for KernelTestCase (yceruto) + * bug #24041 [ExpressionLanguage] throws an exception on calling uncallable method (fmata) + * bug #24096 Fix ArrayInput::toString() for VALUE_IS_ARRAY options/args (chalasr) + * bug #24082 [DI] Minor fix in dumped code (nicolas-grekas) + * bug #23969 [Cache] Use namespace versioning for backends that dont support clearing by keys (nicolas-grekas) + * bug #24021 [DI] Don't track merged configs when the extension doesn't expose it (nicolas-grekas) + * bug #24011 [Cache] Always require symfony/polyfill-apcu to provide APCuIterator everywhere (guillaumelecerf) + * bug #23730 Fixed the escaping of back slashes and << in console output (javiereguiluz) + * 3.3.8 (2017-08-28) * bug #24016 [DI] Fix tracking env var placeholders nested in object graphs (nicolas-grekas) From b9c93f1faa5e0555e2f768fc974fc05d4080a07d Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Mon, 11 Sep 2017 09:13:23 -0700 Subject: [PATCH 0799/1099] updated VERSION for 3.3.9 --- 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 f8ed2b08b4b63..5f986cf4f9f09 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -61,12 +61,12 @@ abstract class Kernel implements KernelInterface, TerminableInterface private $projectDir; - const VERSION = '3.3.9-DEV'; + const VERSION = '3.3.9'; const VERSION_ID = 30309; const MAJOR_VERSION = 3; const MINOR_VERSION = 3; const RELEASE_VERSION = 9; - const EXTRA_VERSION = 'DEV'; + const EXTRA_VERSION = ''; const END_OF_MAINTENANCE = '01/2018'; const END_OF_LIFE = '07/2018'; From 9570a454ef805419cc1f3f7cedc11afd5a176ce1 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Mon, 11 Sep 2017 09:45:56 -0700 Subject: [PATCH 0800/1099] bumped Symfony version to 3.3.10 --- 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 5f986cf4f9f09..89352961adc4e 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -61,12 +61,12 @@ abstract class Kernel implements KernelInterface, TerminableInterface private $projectDir; - const VERSION = '3.3.9'; - const VERSION_ID = 30309; + const VERSION = '3.3.10-DEV'; + const VERSION_ID = 30310; const MAJOR_VERSION = 3; const MINOR_VERSION = 3; - const RELEASE_VERSION = 9; - const EXTRA_VERSION = ''; + const RELEASE_VERSION = 10; + const EXTRA_VERSION = 'DEV'; const END_OF_MAINTENANCE = '01/2018'; const END_OF_LIFE = '07/2018'; From 98a8a6c735c7ff65d739df1478d565a32e037585 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20LEFEBVRE?= Date: Sat, 22 Jul 2017 14:19:22 +0200 Subject: [PATCH 0801/1099] Feature #23583 Add current and fallback locales in WDT / Profiler --- .../views/Collector/translation.html.twig | 20 +++++++++++++++++++ .../TranslationDataCollector.php | 13 ++++++++++++ 2 files changed, 33 insertions(+) diff --git a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/translation.html.twig b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/translation.html.twig index f2ecb1113a04b..bed53f349f40f 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/translation.html.twig +++ b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/translation.html.twig @@ -12,6 +12,12 @@ {% endset %} {% set text %} +
+ Locale + + {{ collector.locale|default('-') }} + +
Missing messages @@ -61,6 +67,20 @@ {% endblock %} {% block panelContent %} + +

Translation Locales

+ +
+
+ {{ collector.locale|default('-') }} + Locale +
+
+ {{ collector.fallbackLocales|join(', ')|default('-') }} + Fallback locales +
+
+

Translation Metrics

diff --git a/src/Symfony/Component/Translation/DataCollector/TranslationDataCollector.php b/src/Symfony/Component/Translation/DataCollector/TranslationDataCollector.php index b99a49f7ff124..1696fc71ffeea 100644 --- a/src/Symfony/Component/Translation/DataCollector/TranslationDataCollector.php +++ b/src/Symfony/Component/Translation/DataCollector/TranslationDataCollector.php @@ -45,6 +45,9 @@ public function lateCollect() $this->data = $this->computeCount($messages); $this->data['messages'] = $messages; + $this->data['locale'] = $this->translator->getLocale(); + $this->data['fallback_locales'] = $this->translator->getFallbackLocales(); + $this->data = $this->cloneVar($this->data); } @@ -87,6 +90,16 @@ public function getCountDefines() return isset($this->data[DataCollectorTranslator::MESSAGE_DEFINED]) ? $this->data[DataCollectorTranslator::MESSAGE_DEFINED] : 0; } + public function getLocale() + { + return !empty($this->data['locale']) ? $this->data['locale'] : null; + } + + public function getFallbackLocales() + { + return (isset($this->data['fallback_locales']) && count($this->data['fallback_locales']) > 0) ? $this->data['fallback_locales'] : array(); + } + /** * {@inheritdoc} */ From 2c62ba815076cd1b8ae7164efe206da50ed6280c Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Mon, 11 Sep 2017 10:58:01 -0700 Subject: [PATCH 0802/1099] fixed CS --- .../FrameworkBundle/DependencyInjection/Configuration.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php index a9c5ec462dcd2..cf24be14d9ff0 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php @@ -253,7 +253,7 @@ private function addWorkflowSection(ArrayNodeDefinition $rootNode) $workflows = $v; unset($workflows['enabled']); - if (count($workflows) === 1 && isset($workflows[0]['enabled'])) { + if (1 === count($workflows) && isset($workflows[0]['enabled'])) { $workflows = array(); } From 6eff3e5b559feb151720fe76d695750227945fd4 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Mon, 11 Sep 2017 10:47:15 -0700 Subject: [PATCH 0803/1099] deprecated profiler.matcher configuration --- UPGRADE-3.4.md | 5 +++++ UPGRADE-4.0.md | 5 +++++ src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md | 1 + .../FrameworkBundle/DependencyInjection/Configuration.php | 1 + 4 files changed, 12 insertions(+) diff --git a/UPGRADE-3.4.md b/UPGRADE-3.4.md index 20114937efc26..f5ae0f7b23a35 100644 --- a/UPGRADE-3.4.md +++ b/UPGRADE-3.4.md @@ -210,6 +210,11 @@ Process * The `Symfony\Component\Process\ProcessBuilder` class has been deprecated, use the `Symfony\Component\Process\Process` class directly instead. +Profiler +-------- + + * The `profiler.matcher` option has been deprecated. + SecurityBundle -------------- diff --git a/UPGRADE-4.0.md b/UPGRADE-4.0.md index 5d404598f7ec0..c6e11a198f8b9 100644 --- a/UPGRADE-4.0.md +++ b/UPGRADE-4.0.md @@ -583,6 +583,11 @@ Process * The `getEnhanceWindowsCompatibility()` and `setEnhanceWindowsCompatibility()` methods of the `Process` class have been removed. +Profiler +-------- + + * The `profiler.matcher` option has been removed. + ProxyManager ------------ diff --git a/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md b/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md index dafd4c46bb0fc..0c7581e7c0b7d 100644 --- a/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md +++ b/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md @@ -4,6 +4,7 @@ CHANGELOG 3.4.0 ----- + * Deprecated `profiler.matcher` option * Added support for `EventSubscriberInterface` on `MicroKernelTrait` * Removed `doctrine/cache` from the list of required dependencies in `composer.json` * Deprecated `validator.mapping.cache.doctrine.apc` service diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php index cf24be14d9ff0..6b98ef7cd444f 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php @@ -219,6 +219,7 @@ private function addProfilerSection(ArrayNodeDefinition $rootNode) ->booleanNode('only_master_requests')->defaultFalse()->end() ->scalarNode('dsn')->defaultValue('file:%kernel.cache_dir%/profiler')->end() ->arrayNode('matcher') + ->setDeprecated('The "profiler.matcher" configuration key has been deprecated in Symfony 3.4 and it will be removed in 4.0.') ->canBeEnabled() ->performNoDeepMerging() ->fixXmlConfig('ip') From 7a97b49436b20c9664f3e286f8c174bc1aae0364 Mon Sep 17 00:00:00 2001 From: Dariusz Date: Mon, 11 Sep 2017 11:28:55 +0200 Subject: [PATCH 0804/1099] [CS] Apply phpdoc_annotation_without_dot --- .php_cs.dist | 1 - .../AbstractDoctrineExtension.php | 2 +- .../CompilerPass/RegisterMappingsPass.php | 16 +++--- .../Form/ChoiceList/DoctrineChoiceLoader.php | 4 +- .../Form/ChoiceList/EntityChoiceList.php | 4 +- .../Doctrine/Form/ChoiceList/IdReader.php | 10 ++-- .../Templating/Helper/FormHelper.php | 2 +- .../Component/Config/Definition/BaseNode.php | 2 +- .../Builder/ArrayNodeDefinition.php | 4 +- .../Component/Console/Question/Question.php | 2 +- .../Debug/Tests/DebugClassLoaderTest.php | 2 +- .../Debug/Tests/Fixtures/DeprecatedClass.php | 2 +- .../Tests/Fixtures/DeprecatedInterface.php | 2 +- .../Compiler/CheckCircularReferencesPass.php | 2 +- .../Compiler/CheckReferenceValidityPass.php | 2 +- .../DependencyInjection/Definition.php | 2 +- .../ParameterBag/ParameterBag.php | 4 +- src/Symfony/Component/DomCrawler/Crawler.php | 2 +- .../EventDispatcherInterface.php | 4 +- .../EventDispatcher/GenericEvent.php | 4 +- .../Component/Filesystem/Filesystem.php | 2 +- src/Symfony/Component/Finder/Finder.php | 2 +- .../Component/Form/AbstractRendererEngine.php | 16 +++--- src/Symfony/Component/Form/Button.php | 2 +- src/Symfony/Component/Form/ButtonBuilder.php | 2 +- .../Form/ChoiceList/ArrayChoiceList.php | 4 +- .../Factory/CachingFactoryDecorator.php | 2 +- .../Form/ChoiceList/View/ChoiceGroupView.php | 4 +- .../Form/ChoiceList/View/ChoiceListView.php | 4 +- .../Component/Form/DataMapperInterface.php | 4 +- .../Form/DataTransformerInterface.php | 4 +- .../Extension/Core/ChoiceList/ChoiceList.php | 42 ++++++++-------- .../Core/ChoiceList/ObjectChoiceList.php | 8 +-- .../Core/ChoiceList/SimpleChoiceList.php | 12 ++--- .../BooleanToStringTransformer.php | 4 +- .../ChoiceToBooleanArrayTransformer.php | 12 ++--- .../ChoicesToBooleanArrayTransformer.php | 8 +-- .../ChoicesToValuesTransformer.php | 6 +-- .../DateTimeToLocalizedStringTransformer.php | 8 +-- .../MoneyToLocalizedStringTransformer.php | 8 +-- .../NumberToLocalizedStringTransformer.php | 8 +-- .../PercentToLocalizedStringTransformer.php | 8 +-- .../ValueToDuplicatesTransformer.php | 4 +- .../EventListener/MergeCollectionListener.php | 8 +-- .../Validator/ValidatorTypeGuesser.php | 4 +- .../ViolationMapperInterface.php | 8 +-- .../ViolationMapper/ViolationPath.php | 6 +-- src/Symfony/Component/Form/Form.php | 8 +-- .../Component/Form/FormConfigBuilder.php | 8 +-- .../Form/FormConfigBuilderInterface.php | 9 ++-- .../Component/Form/FormConfigInterface.php | 4 +- .../Component/Form/FormErrorIterator.php | 4 +- src/Symfony/Component/Form/FormInterface.php | 26 +++++----- .../Form/FormRendererEngineInterface.php | 18 +++---- src/Symfony/Component/Form/SubmitButton.php | 2 +- .../Form/Util/OrderedHashMapIterator.php | 8 +-- .../Component/HttpFoundation/Response.php | 6 +-- .../Session/SessionInterface.php | 2 +- .../Storage/SessionStorageInterface.php | 6 +-- .../EventListener/FragmentListener.php | 2 +- .../Data/Bundle/Compiler/GenrbCompiler.php | 2 +- .../Bundle/Reader/BufferedBundleReader.php | 4 +- .../Reader/BundleEntryReaderInterface.php | 4 +- .../Bundle/Reader/BundleReaderInterface.php | 4 +- .../Data/Bundle/Writer/TextBundleWriter.php | 20 ++++---- .../Intl/DateFormatter/IntlDateFormatter.php | 6 +-- .../Intl/NumberFormatter/NumberFormatter.php | 18 +++---- .../Intl/Resources/stubs/functions.php | 8 +-- .../Component/Intl/Util/IcuVersion.php | 4 +- src/Symfony/Component/Intl/Util/SvnCommit.php | 4 +- .../Component/Intl/Util/SvnRepository.php | 4 +- src/Symfony/Component/Intl/Util/Version.php | 4 +- .../OptionsResolverInterface.php | 50 +++++++++---------- src/Symfony/Component/Process/Process.php | 4 +- .../PropertyAccess/PropertyAccessor.php | 6 +-- .../PropertyAccess/PropertyPathBuilder.php | 16 +++--- .../Routing/Loader/XmlFileLoader.php | 4 +- .../Component/Routing/RouteCompiler.php | 4 +- .../Authorization/AuthorizationChecker.php | 2 +- .../Core/User/InMemoryUserProvider.php | 2 +- .../Http/Logout/LogoutUrlGenerator.php | 2 +- .../Serializer/Encoder/ChainDecoder.php | 2 +- .../Normalizer/NormalizableInterface.php | 10 ++-- .../Translation/Loader/MoFileLoader.php | 2 +- .../Component/Validator/Constraint.php | 2 +- .../ConstraintViolationInterface.php | 8 +-- .../ConstraintViolationListInterface.php | 2 +- .../Component/Validator/DefaultTranslator.php | 4 +- .../Validator/ExecutionContextInterface.php | 12 ++--- .../Component/Validator/Validation.php | 2 +- .../Validator/ValidationVisitorInterface.php | 4 +- src/Symfony/Component/Validator/Validator.php | 4 +- .../Validator/ValidatorInterface.php | 4 +- 93 files changed, 301 insertions(+), 303 deletions(-) diff --git a/.php_cs.dist b/.php_cs.dist index 6282431a419d4..25f1f4c931bdc 100644 --- a/.php_cs.dist +++ b/.php_cs.dist @@ -12,7 +12,6 @@ return PhpCsFixer\Config::create() 'no_unreachable_default_argument_value' => false, 'braces' => array('allow_single_line_closure' => true), 'heredoc_to_nowdoc' => false, - 'phpdoc_annotation_without_dot' => false, )) ->setRiskyAllowed(true) ->setFinder( diff --git a/src/Symfony/Bridge/Doctrine/DependencyInjection/AbstractDoctrineExtension.php b/src/Symfony/Bridge/Doctrine/DependencyInjection/AbstractDoctrineExtension.php index 940ca6fdf9fbd..b3fecad9df233 100644 --- a/src/Symfony/Bridge/Doctrine/DependencyInjection/AbstractDoctrineExtension.php +++ b/src/Symfony/Bridge/Doctrine/DependencyInjection/AbstractDoctrineExtension.php @@ -301,7 +301,7 @@ protected function detectMetadataDriver($dir, ContainerBuilder $container) * @param ContainerBuilder $container A ContainerBuilder instance * @param string $cacheName * - * @throws \InvalidArgumentException In case of unknown driver type. + * @throws \InvalidArgumentException in case of unknown driver type */ protected function loadObjectManagerCacheDriver(array $objectManager, ContainerBuilder $container, $cacheName) { diff --git a/src/Symfony/Bridge/Doctrine/DependencyInjection/CompilerPass/RegisterMappingsPass.php b/src/Symfony/Bridge/Doctrine/DependencyInjection/CompilerPass/RegisterMappingsPass.php index e37e4f66c29aa..7f169fe1ae696 100644 --- a/src/Symfony/Bridge/Doctrine/DependencyInjection/CompilerPass/RegisterMappingsPass.php +++ b/src/Symfony/Bridge/Doctrine/DependencyInjection/CompilerPass/RegisterMappingsPass.php @@ -108,15 +108,15 @@ abstract class RegisterMappingsPass implements CompilerPassInterface * * @param Definition|Reference $driver Driver DI definition or reference * @param string[] $namespaces List of namespaces handled by $driver - * @param string[] $managerParameters List of container parameters that could - * hold the manager name. + * @param string[] $managerParameters list of container parameters that could + * hold the manager name * @param string $driverPattern Pattern for the metadata driver service name * @param string|false $enabledParameter Service container parameter that must be * present to enable the mapping. Set to false * to not do any check, optional. * @param string $configurationPattern Pattern for the Configuration service name - * @param string $registerAliasMethodName Name of Configuration class method to - * register alias. + * @param string $registerAliasMethodName name of Configuration class method to + * register alias * @param string[] $aliasMap Map of alias to namespace */ public function __construct($driver, array $namespaces, array $managerParameters, $driverPattern, $enabledParameter = false, $configurationPattern = '', $registerAliasMethodName = '', array $aliasMap = array()) @@ -174,7 +174,7 @@ public function process(ContainerBuilder $container) * @return string The name of the chain driver service * * @throws ParameterNotFoundException if non of the managerParameters has a - * non-empty value. + * non-empty value */ protected function getChainDriverServiceName(ContainerBuilder $container) { @@ -185,7 +185,7 @@ protected function getChainDriverServiceName(ContainerBuilder $container) * Create the service definition for the metadata driver. * * @param ContainerBuilder $container passed on in case an extending class - * needs access to the container. + * needs access to the container * * @return Definition|Reference the metadata driver to add to all chain drivers */ @@ -202,7 +202,7 @@ protected function getDriver(ContainerBuilder $container) * @return string a service definition name * * @throws ParameterNotFoundException if none of the managerParameters has a - * non-empty value. + * non-empty value */ private function getConfigurationServiceName(ContainerBuilder $container) { @@ -219,7 +219,7 @@ private function getConfigurationServiceName(ContainerBuilder $container) * * @return string The name of the active manager * - * @throws ParameterNotFoundException If none of the managerParameters is found in the container. + * @throws ParameterNotFoundException if none of the managerParameters is found in the container */ private function getManagerName(ContainerBuilder $container) { diff --git a/src/Symfony/Bridge/Doctrine/Form/ChoiceList/DoctrineChoiceLoader.php b/src/Symfony/Bridge/Doctrine/Form/ChoiceList/DoctrineChoiceLoader.php index 9343876ef35b5..02280c4fe8785 100644 --- a/src/Symfony/Bridge/Doctrine/Form/ChoiceList/DoctrineChoiceLoader.php +++ b/src/Symfony/Bridge/Doctrine/Form/ChoiceList/DoctrineChoiceLoader.php @@ -65,8 +65,8 @@ class DoctrineChoiceLoader implements ChoiceLoaderInterface * @param ObjectManager $manager The object manager * @param string $class The class name of the * loaded objects - * @param IdReader $idReader The reader for the object - * IDs. + * @param IdReader $idReader the reader for the object + * IDs * @param null|EntityLoaderInterface $objectLoader The objects loader */ public function __construct(ChoiceListFactoryInterface $factory, ObjectManager $manager, $class, IdReader $idReader = null, EntityLoaderInterface $objectLoader = null) diff --git a/src/Symfony/Bridge/Doctrine/Form/ChoiceList/EntityChoiceList.php b/src/Symfony/Bridge/Doctrine/Form/ChoiceList/EntityChoiceList.php index d22a85466f972..72d7a6f10bd4f 100644 --- a/src/Symfony/Bridge/Doctrine/Form/ChoiceList/EntityChoiceList.php +++ b/src/Symfony/Bridge/Doctrine/Form/ChoiceList/EntityChoiceList.php @@ -389,8 +389,8 @@ public function getIndicesForValues(array $values) * * @param mixed $entity The choice to create an index for * - * @return int|string A unique index containing only ASCII letters, - * digits and underscores. + * @return int|string a unique index containing only ASCII letters, + * digits and underscores */ protected function createIndex($entity) { diff --git a/src/Symfony/Bridge/Doctrine/Form/ChoiceList/IdReader.php b/src/Symfony/Bridge/Doctrine/Form/ChoiceList/IdReader.php index cd966ea986f79..0161adf3b4c0a 100644 --- a/src/Symfony/Bridge/Doctrine/Form/ChoiceList/IdReader.php +++ b/src/Symfony/Bridge/Doctrine/Form/ChoiceList/IdReader.php @@ -20,7 +20,7 @@ * * @author Bernhard Schussek * - * @internal This class is meant for internal use only. + * @internal this class is meant for internal use only */ class IdReader { @@ -79,8 +79,8 @@ public function __construct(ObjectManager $om, ClassMetadata $classMetadata) /** * Returns whether the class has a single-column ID. * - * @return bool Returns `true` if the class has a single-column ID and - * `false` otherwise. + * @return bool returns `true` if the class has a single-column ID and + * `false` otherwise */ public function isSingleId() { @@ -90,8 +90,8 @@ public function isSingleId() /** * Returns whether the class has a single-column integer ID. * - * @return bool Returns `true` if the class has a single-column integer ID - * and `false` otherwise. + * @return bool returns `true` if the class has a single-column integer ID + * and `false` otherwise */ public function isIntId() { diff --git a/src/Symfony/Bundle/FrameworkBundle/Templating/Helper/FormHelper.php b/src/Symfony/Bundle/FrameworkBundle/Templating/Helper/FormHelper.php index 47c434aa476da..8375fb0235a0c 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Templating/Helper/FormHelper.php +++ b/src/Symfony/Bundle/FrameworkBundle/Templating/Helper/FormHelper.php @@ -257,7 +257,7 @@ public function block(FormView $view, $blockName, array $variables = array()) * * @return string A CSRF token * - * @throws \BadMethodCallException When no CSRF provider was injected in the constructor. + * @throws \BadMethodCallException when no CSRF provider was injected in the constructor */ public function csrfToken($intention) { diff --git a/src/Symfony/Component/Config/Definition/BaseNode.php b/src/Symfony/Component/Config/Definition/BaseNode.php index dbf36335b69e3..09d047994ae08 100644 --- a/src/Symfony/Component/Config/Definition/BaseNode.php +++ b/src/Symfony/Component/Config/Definition/BaseNode.php @@ -38,7 +38,7 @@ abstract class BaseNode implements NodeInterface * @param string $name The name of the node * @param NodeInterface $parent The parent of this node * - * @throws \InvalidArgumentException if the name contains a period. + * @throws \InvalidArgumentException if the name contains a period */ public function __construct($name, NodeInterface $parent = null) { diff --git a/src/Symfony/Component/Config/Definition/Builder/ArrayNodeDefinition.php b/src/Symfony/Component/Config/Definition/Builder/ArrayNodeDefinition.php index 03bb0cfdeeb3c..f2d22fd1f5c54 100644 --- a/src/Symfony/Component/Config/Definition/Builder/ArrayNodeDefinition.php +++ b/src/Symfony/Component/Config/Definition/Builder/ArrayNodeDefinition.php @@ -97,10 +97,10 @@ public function addDefaultsIfNotSet() /** * Adds children with a default value when none are defined. * - * @param int|string|array|null $children The number of children|The child name|The children names to be added - * * This method is applicable to prototype nodes only. * + * @param int|string|array|null $children the number of children|The child name|The children names to be added + * * @return $this */ public function addDefaultChildrenIfNoneSet($children = null) diff --git a/src/Symfony/Component/Console/Question/Question.php b/src/Symfony/Component/Console/Question/Question.php index 373501d691f8c..f466254324583 100644 --- a/src/Symfony/Component/Console/Question/Question.php +++ b/src/Symfony/Component/Console/Question/Question.php @@ -187,7 +187,7 @@ public function getValidator() * * @return $this * - * @throws \InvalidArgumentException In case the number of attempts is invalid. + * @throws \InvalidArgumentException in case the number of attempts is invalid */ public function setMaxAttempts($attempts) { diff --git a/src/Symfony/Component/Debug/Tests/DebugClassLoaderTest.php b/src/Symfony/Component/Debug/Tests/DebugClassLoaderTest.php index 1843418e919c9..437f1e2ecfa72 100644 --- a/src/Symfony/Component/Debug/Tests/DebugClassLoaderTest.php +++ b/src/Symfony/Component/Debug/Tests/DebugClassLoaderTest.php @@ -208,7 +208,7 @@ class_exists('Test\\'.__NAMESPACE__.'\\'.$class, true); $xError = array( 'type' => E_USER_DEPRECATED, - 'message' => 'The Test\Symfony\Component\Debug\Tests\\'.$class.' class '.$type.' Symfony\Component\Debug\Tests\Fixtures\\'.$super.' that is deprecated but this is a test deprecation notice.', + 'message' => 'The Test\Symfony\Component\Debug\Tests\\'.$class.' class '.$type.' Symfony\Component\Debug\Tests\Fixtures\\'.$super.' that is deprecated but this is a test deprecation notice', ); $this->assertSame($xError, $lastError); diff --git a/src/Symfony/Component/Debug/Tests/Fixtures/DeprecatedClass.php b/src/Symfony/Component/Debug/Tests/Fixtures/DeprecatedClass.php index b4c78cd140f13..51fde5af8a1d0 100644 --- a/src/Symfony/Component/Debug/Tests/Fixtures/DeprecatedClass.php +++ b/src/Symfony/Component/Debug/Tests/Fixtures/DeprecatedClass.php @@ -4,7 +4,7 @@ /** * @deprecated but this is a test - * deprecation notice. + * deprecation notice * @foobar */ class DeprecatedClass diff --git a/src/Symfony/Component/Debug/Tests/Fixtures/DeprecatedInterface.php b/src/Symfony/Component/Debug/Tests/Fixtures/DeprecatedInterface.php index 505eccae751b9..6bab62f9563b8 100644 --- a/src/Symfony/Component/Debug/Tests/Fixtures/DeprecatedInterface.php +++ b/src/Symfony/Component/Debug/Tests/Fixtures/DeprecatedInterface.php @@ -4,7 +4,7 @@ /** * @deprecated but this is a test - * deprecation notice. + * deprecation notice * @foobar */ interface DeprecatedInterface diff --git a/src/Symfony/Component/DependencyInjection/Compiler/CheckCircularReferencesPass.php b/src/Symfony/Component/DependencyInjection/Compiler/CheckCircularReferencesPass.php index f39a89af2be71..0b9c573acfbdb 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/CheckCircularReferencesPass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/CheckCircularReferencesPass.php @@ -51,7 +51,7 @@ public function process(ContainerBuilder $container) * * @param ServiceReferenceGraphEdge[] $edges An array of Edges * - * @throws ServiceCircularReferenceException When a circular reference is found. + * @throws ServiceCircularReferenceException when a circular reference is found */ private function checkOutEdges(array $edges) { diff --git a/src/Symfony/Component/DependencyInjection/Compiler/CheckReferenceValidityPass.php b/src/Symfony/Component/DependencyInjection/Compiler/CheckReferenceValidityPass.php index 82202a9fb6007..f8c09d42f0c61 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/CheckReferenceValidityPass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/CheckReferenceValidityPass.php @@ -85,7 +85,7 @@ public function process(ContainerBuilder $container) * * @param array $arguments An array of Reference objects * - * @throws RuntimeException when there is a reference to an abstract definition. + * @throws RuntimeException when there is a reference to an abstract definition */ private function validateReferences(array $arguments) { diff --git a/src/Symfony/Component/DependencyInjection/Definition.php b/src/Symfony/Component/DependencyInjection/Definition.php index cad6398f7fb8e..780ad187cdba5 100644 --- a/src/Symfony/Component/DependencyInjection/Definition.php +++ b/src/Symfony/Component/DependencyInjection/Definition.php @@ -140,7 +140,7 @@ public function setFactoryMethod($factoryMethod) * * @return $this * - * @throws InvalidArgumentException In case the decorated service id and the new decorated service id are equals. + * @throws InvalidArgumentException in case the decorated service id and the new decorated service id are equals */ public function setDecoratedService($id, $renamedId = null) { diff --git a/src/Symfony/Component/DependencyInjection/ParameterBag/ParameterBag.php b/src/Symfony/Component/DependencyInjection/ParameterBag/ParameterBag.php index 0611b1f69e322..dbfa5b6ae594c 100644 --- a/src/Symfony/Component/DependencyInjection/ParameterBag/ParameterBag.php +++ b/src/Symfony/Component/DependencyInjection/ParameterBag/ParameterBag.php @@ -151,7 +151,7 @@ public function resolve() * * @throws ParameterNotFoundException if a placeholder references a parameter that does not exist * @throws ParameterCircularReferenceException if a circular reference if detected - * @throws RuntimeException when a given parameter has a type problem. + * @throws RuntimeException when a given parameter has a type problem */ public function resolveValue($value, array $resolving = array()) { @@ -181,7 +181,7 @@ public function resolveValue($value, array $resolving = array()) * * @throws ParameterNotFoundException if a placeholder references a parameter that does not exist * @throws ParameterCircularReferenceException if a circular reference if detected - * @throws RuntimeException when a given parameter has a type problem. + * @throws RuntimeException when a given parameter has a type problem */ public function resolveString($value, array $resolving = array()) { diff --git a/src/Symfony/Component/DomCrawler/Crawler.php b/src/Symfony/Component/DomCrawler/Crawler.php index ed9b0b02398f5..f711c02bfff83 100644 --- a/src/Symfony/Component/DomCrawler/Crawler.php +++ b/src/Symfony/Component/DomCrawler/Crawler.php @@ -71,7 +71,7 @@ public function clear() * * @param \DOMNodeList|\DOMNode|array|string|null $node A node * - * @throws \InvalidArgumentException When node is not the expected type. + * @throws \InvalidArgumentException when node is not the expected type */ public function add($node) { diff --git a/src/Symfony/Component/EventDispatcher/EventDispatcherInterface.php b/src/Symfony/Component/EventDispatcher/EventDispatcherInterface.php index abe8d2895ebc3..b1f976cdf20ab 100644 --- a/src/Symfony/Component/EventDispatcher/EventDispatcherInterface.php +++ b/src/Symfony/Component/EventDispatcher/EventDispatcherInterface.php @@ -26,8 +26,8 @@ interface EventDispatcherInterface * @param string $eventName The name of the event to dispatch. The name of * the event is the name of the method that is * invoked on listeners. - * @param Event $event The event to pass to the event handlers/listeners - * If not supplied, an empty Event instance is created. + * @param Event $event the event to pass to the event handlers/listeners + * If not supplied, an empty Event instance is created * * @return Event */ diff --git a/src/Symfony/Component/EventDispatcher/GenericEvent.php b/src/Symfony/Component/EventDispatcher/GenericEvent.php index e8e4cc050266e..a7520a0f34567 100644 --- a/src/Symfony/Component/EventDispatcher/GenericEvent.php +++ b/src/Symfony/Component/EventDispatcher/GenericEvent.php @@ -63,7 +63,7 @@ public function getSubject() * * @return mixed Contents of array key * - * @throws \InvalidArgumentException If key is not found. + * @throws \InvalidArgumentException if key is not found */ public function getArgument($key) { @@ -132,7 +132,7 @@ public function hasArgument($key) * * @return mixed * - * @throws \InvalidArgumentException If key does not exist in $this->args. + * @throws \InvalidArgumentException if key does not exist in $this->args */ public function offsetGet($key) { diff --git a/src/Symfony/Component/Filesystem/Filesystem.php b/src/Symfony/Component/Filesystem/Filesystem.php index bc2e3dcc2d897..3a8316573160c 100644 --- a/src/Symfony/Component/Filesystem/Filesystem.php +++ b/src/Symfony/Component/Filesystem/Filesystem.php @@ -525,7 +525,7 @@ public function isAbsolutePath($file) * @param null|int $mode The file mode (octal). If null, file permissions are not modified * Deprecated since version 2.3.12, to be removed in 3.0. * - * @throws IOException If the file cannot be written to. + * @throws IOException if the file cannot be written to */ public function dumpFile($filename, $content, $mode = 0666) { diff --git a/src/Symfony/Component/Finder/Finder.php b/src/Symfony/Component/Finder/Finder.php index edbdcd6402074..d8408d1f3c90d 100644 --- a/src/Symfony/Component/Finder/Finder.php +++ b/src/Symfony/Component/Finder/Finder.php @@ -681,7 +681,7 @@ public function getIterator() * * @return $this * - * @throws \InvalidArgumentException When the given argument is not iterable. + * @throws \InvalidArgumentException when the given argument is not iterable */ public function append($iterator) { diff --git a/src/Symfony/Component/Form/AbstractRendererEngine.php b/src/Symfony/Component/Form/AbstractRendererEngine.php index ae9938a0f004c..7519011225282 100644 --- a/src/Symfony/Component/Form/AbstractRendererEngine.php +++ b/src/Symfony/Component/Form/AbstractRendererEngine.php @@ -139,14 +139,14 @@ abstract protected function loadResourceForBlockName($cacheKey, FormView $view, * * @see getResourceForBlockHierarchy() * - * @param string $cacheKey The cache key used for storing the - * resource. - * @param FormView $view The form view for finding the applying - * themes. - * @param array $blockNameHierarchy The block hierarchy, with the most - * specific block name at the end. - * @param int $hierarchyLevel The level in the block hierarchy that - * should be loaded. + * @param string $cacheKey the cache key used for storing the + * resource + * @param FormView $view the form view for finding the applying + * themes + * @param array $blockNameHierarchy the block hierarchy, with the most + * specific block name at the end + * @param int $hierarchyLevel the level in the block hierarchy that + * should be loaded * * @return bool True if the resource could be loaded, false otherwise */ diff --git a/src/Symfony/Component/Form/Button.php b/src/Symfony/Component/Form/Button.php index efc14c063932b..9a5f8a60bd433 100644 --- a/src/Symfony/Component/Form/Button.php +++ b/src/Symfony/Component/Form/Button.php @@ -371,7 +371,7 @@ public function handleRequest($request = null) * * @return $this * - * @throws Exception\AlreadySubmittedException If the button has already been submitted. + * @throws Exception\AlreadySubmittedException if the button has already been submitted */ public function submit($submittedData, $clearMissing = true) { diff --git a/src/Symfony/Component/Form/ButtonBuilder.php b/src/Symfony/Component/Form/ButtonBuilder.php index eaecb382fd327..ad311db29095c 100644 --- a/src/Symfony/Component/Form/ButtonBuilder.php +++ b/src/Symfony/Component/Form/ButtonBuilder.php @@ -58,7 +58,7 @@ class ButtonBuilder implements \IteratorAggregate, FormBuilderInterface * @param string $name The name of the button * @param array $options The button's options * - * @throws InvalidArgumentException If the name is empty. + * @throws InvalidArgumentException if the name is empty */ public function __construct($name, array $options = array()) { diff --git a/src/Symfony/Component/Form/ChoiceList/ArrayChoiceList.php b/src/Symfony/Component/Form/ChoiceList/ArrayChoiceList.php index 4a2588ef1d475..676987e641216 100644 --- a/src/Symfony/Component/Form/ChoiceList/ArrayChoiceList.php +++ b/src/Symfony/Component/Form/ChoiceList/ArrayChoiceList.php @@ -222,8 +222,8 @@ protected function flatten(array $choices, $value, &$choicesByValues, &$keysByVa * @param array $choices The choices * @param array|null $cache The cache for previously checked entries. Internal * - * @return bool Returns true if the choices can be cast to strings and - * false otherwise. + * @return bool returns true if the choices can be cast to strings and + * false otherwise */ private function castableToString(array $choices, array &$cache = array()) { diff --git a/src/Symfony/Component/Form/ChoiceList/Factory/CachingFactoryDecorator.php b/src/Symfony/Component/Form/ChoiceList/Factory/CachingFactoryDecorator.php index ae7f2375bb896..5ce851096cfc8 100644 --- a/src/Symfony/Component/Form/ChoiceList/Factory/CachingFactoryDecorator.php +++ b/src/Symfony/Component/Form/ChoiceList/Factory/CachingFactoryDecorator.php @@ -48,7 +48,7 @@ class CachingFactoryDecorator implements ChoiceListFactoryInterface * * @return string The SHA-256 hash * - * @internal Should not be used by user-land code. + * @internal should not be used by user-land code */ public static function generateHash($value, $namespace = '') { diff --git a/src/Symfony/Component/Form/ChoiceList/View/ChoiceGroupView.php b/src/Symfony/Component/Form/ChoiceList/View/ChoiceGroupView.php index 9e648cc360000..455fa68ac4ba1 100644 --- a/src/Symfony/Component/Form/ChoiceList/View/ChoiceGroupView.php +++ b/src/Symfony/Component/Form/ChoiceList/View/ChoiceGroupView.php @@ -36,8 +36,8 @@ class ChoiceGroupView implements \IteratorAggregate * Creates a new choice group view. * * @param string $label The label of the group - * @param ChoiceGroupView[]|ChoiceView[] $choices The choice views in the - * group. + * @param ChoiceGroupView[]|ChoiceView[] $choices the choice views in the + * group */ public function __construct($label, array $choices = array()) { diff --git a/src/Symfony/Component/Form/ChoiceList/View/ChoiceListView.php b/src/Symfony/Component/Form/ChoiceList/View/ChoiceListView.php index cea30dd655559..05c40a48831cd 100644 --- a/src/Symfony/Component/Form/ChoiceList/View/ChoiceListView.php +++ b/src/Symfony/Component/Form/ChoiceList/View/ChoiceListView.php @@ -40,8 +40,8 @@ class ChoiceListView * Creates a new choice list view. * * @param ChoiceGroupView[]|ChoiceView[] $choices The choice views - * @param ChoiceGroupView[]|ChoiceView[] $preferredChoices The preferred - * choice views. + * @param ChoiceGroupView[]|ChoiceView[] $preferredChoices the preferred + * choice views */ public function __construct(array $choices = array(), array $preferredChoices = array()) { diff --git a/src/Symfony/Component/Form/DataMapperInterface.php b/src/Symfony/Component/Form/DataMapperInterface.php index f1867a9f901f4..bb262e7b8e6b8 100644 --- a/src/Symfony/Component/Form/DataMapperInterface.php +++ b/src/Symfony/Component/Form/DataMapperInterface.php @@ -22,7 +22,7 @@ interface DataMapperInterface * @param mixed $data Structured data * @param FormInterface[]|\Traversable $forms A list of {@link FormInterface} instances * - * @throws Exception\UnexpectedTypeException if the type of the data parameter is not supported. + * @throws Exception\UnexpectedTypeException if the type of the data parameter is not supported */ public function mapDataToForms($data, $forms); @@ -32,7 +32,7 @@ public function mapDataToForms($data, $forms); * @param FormInterface[]|\Traversable $forms A list of {@link FormInterface} instances * @param mixed $data Structured data * - * @throws Exception\UnexpectedTypeException if the type of the data parameter is not supported. + * @throws Exception\UnexpectedTypeException if the type of the data parameter is not supported */ public function mapFormsToData($forms, &$data); } diff --git a/src/Symfony/Component/Form/DataTransformerInterface.php b/src/Symfony/Component/Form/DataTransformerInterface.php index ee0afda8a91b1..deb073c8128fe 100644 --- a/src/Symfony/Component/Form/DataTransformerInterface.php +++ b/src/Symfony/Component/Form/DataTransformerInterface.php @@ -45,7 +45,7 @@ interface DataTransformerInterface * * @return mixed The value in the transformed representation * - * @throws TransformationFailedException When the transformation fails. + * @throws TransformationFailedException when the transformation fails */ public function transform($value); @@ -71,7 +71,7 @@ public function transform($value); * * @return mixed The value in the original representation * - * @throws TransformationFailedException When the transformation fails. + * @throws TransformationFailedException when the transformation fails */ public function reverseTransform($value); } diff --git a/src/Symfony/Component/Form/Extension/Core/ChoiceList/ChoiceList.php b/src/Symfony/Component/Form/Extension/Core/ChoiceList/ChoiceList.php index 90e5d774e72e5..6e0cea5539405 100644 --- a/src/Symfony/Component/Form/Extension/Core/ChoiceList/ChoiceList.php +++ b/src/Symfony/Component/Form/Extension/Core/ChoiceList/ChoiceList.php @@ -82,10 +82,10 @@ class ChoiceList implements ChoiceListInterface * level of the hierarchy may also be a \Traversable. * @param array $labels The array of labels. The structure of this array * should match the structure of $choices. - * @param array $preferredChoices A flat array of choices that should be - * presented to the user with priority. + * @param array $preferredChoices a flat array of choices that should be + * presented to the user with priority * - * @throws UnexpectedTypeException If the choices are not an array or \Traversable. + * @throws UnexpectedTypeException if the choices are not an array or \Traversable */ public function __construct($choices, array $labels, array $preferredChoices = array()) { @@ -260,16 +260,16 @@ public function getIndicesForValues(array $values) /** * Recursively adds the given choices to the list. * - * @param array $bucketForPreferred The bucket where to store the preferred - * view objects. - * @param array $bucketForRemaining The bucket where to store the - * non-preferred view objects. + * @param array $bucketForPreferred the bucket where to store the preferred + * view objects + * @param array $bucketForRemaining the bucket where to store the + * non-preferred view objects * @param array|\Traversable $choices The list of choices * @param array $labels The labels corresponding to the choices * @param array $preferredChoices The preferred choices * - * @throws InvalidArgumentException If the structures of the choices and labels array do not match. - * @throws InvalidConfigurationException If no valid value or index could be created for a choice. + * @throws InvalidArgumentException if the structures of the choices and labels array do not match + * @throws InvalidConfigurationException if no valid value or index could be created for a choice */ protected function addChoices(array &$bucketForPreferred, array &$bucketForRemaining, $choices, array $labels, array $preferredChoices) { @@ -307,15 +307,15 @@ protected function addChoices(array &$bucketForPreferred, array &$bucketForRemai * Recursively adds a choice group. * * @param string $group The name of the group - * @param array $bucketForPreferred The bucket where to store the preferred - * view objects. - * @param array $bucketForRemaining The bucket where to store the - * non-preferred view objects. + * @param array $bucketForPreferred the bucket where to store the preferred + * view objects + * @param array $bucketForRemaining the bucket where to store the + * non-preferred view objects * @param array $choices The list of choices in the group * @param array $labels The labels corresponding to the choices in the group * @param array $preferredChoices The preferred choices * - * @throws InvalidConfigurationException If no valid value or index could be created for a choice. + * @throws InvalidConfigurationException if no valid value or index could be created for a choice */ protected function addChoiceGroup($group, array &$bucketForPreferred, array &$bucketForRemaining, array $choices, array $labels, array $preferredChoices) { @@ -344,15 +344,15 @@ protected function addChoiceGroup($group, array &$bucketForPreferred, array &$bu /** * Adds a new choice. * - * @param array $bucketForPreferred The bucket where to store the preferred - * view objects. - * @param array $bucketForRemaining The bucket where to store the - * non-preferred view objects. + * @param array $bucketForPreferred the bucket where to store the preferred + * view objects + * @param array $bucketForRemaining the bucket where to store the + * non-preferred view objects * @param mixed $choice The choice to add * @param string $label The label for the choice * @param array $preferredChoices The preferred choices * - * @throws InvalidConfigurationException If no valid value or index could be created. + * @throws InvalidConfigurationException if no valid value or index could be created */ protected function addChoice(array &$bucketForPreferred, array &$bucketForRemaining, $choice, $label, array $preferredChoices) { @@ -404,8 +404,8 @@ protected function isPreferred($choice, array $preferredChoices) * * @param mixed $choice The choice to create an index for * - * @return int|string A unique index containing only ASCII letters, - * digits and underscores. + * @return int|string a unique index containing only ASCII letters, + * digits and underscores */ protected function createIndex($choice) { diff --git a/src/Symfony/Component/Form/Extension/Core/ChoiceList/ObjectChoiceList.php b/src/Symfony/Component/Form/Extension/Core/ChoiceList/ObjectChoiceList.php index 6460ba81efafa..5e2b9a75a2909 100644 --- a/src/Symfony/Component/Form/Extension/Core/ChoiceList/ObjectChoiceList.php +++ b/src/Symfony/Component/Form/Extension/Core/ChoiceList/ObjectChoiceList.php @@ -80,8 +80,8 @@ class ObjectChoiceList extends ChoiceList * by calling the getter on the object. If the * path is NULL, the object's __toString() method * is used instead. - * @param array $preferredChoices A flat array of choices that should be - * presented to the user with priority. + * @param array $preferredChoices a flat array of choices that should be + * presented to the user with priority * @param string $groupPath A property path pointing to the property used * to group the choices. Only allowed if * the choices are given as flat array. @@ -109,8 +109,8 @@ public function __construct($choices, $labelPath = null, array $preferredChoices * @param array $labels Ignored * @param array $preferredChoices The choices to display with priority * - * @throws InvalidArgumentException When passing a hierarchy of choices and using - * the "groupPath" option at the same time. + * @throws InvalidArgumentException when passing a hierarchy of choices and using + * the "groupPath" option at the same time */ protected function initialize($choices, array $labels, array $preferredChoices) { diff --git a/src/Symfony/Component/Form/Extension/Core/ChoiceList/SimpleChoiceList.php b/src/Symfony/Component/Form/Extension/Core/ChoiceList/SimpleChoiceList.php index 537e318f80dbf..e5fd865d0dee1 100644 --- a/src/Symfony/Component/Form/Extension/Core/ChoiceList/SimpleChoiceList.php +++ b/src/Symfony/Component/Form/Extension/Core/ChoiceList/SimpleChoiceList.php @@ -44,8 +44,8 @@ class SimpleChoiceList extends ChoiceList * as hierarchy of unlimited depth by creating nested * arrays. The title of the sub-hierarchy is stored * in the array key pointing to the nested array. - * @param array $preferredChoices A flat array of choices that should be - * presented to the user with priority. + * @param array $preferredChoices a flat array of choices that should be + * presented to the user with priority */ public function __construct(array $choices, array $preferredChoices = array()) { @@ -83,10 +83,10 @@ public function getValuesForChoices(array $choices) * Takes care of splitting the single $choices array passed in the * constructor into choices and labels. * - * @param array $bucketForPreferred The bucket where to store the preferred - * view objects. - * @param array $bucketForRemaining The bucket where to store the - * non-preferred view objects. + * @param array $bucketForPreferred the bucket where to store the preferred + * view objects + * @param array $bucketForRemaining the bucket where to store the + * non-preferred view objects * @param array|\Traversable $choices The list of choices * @param array $labels Ignored * @param array $preferredChoices The preferred choices diff --git a/src/Symfony/Component/Form/Extension/Core/DataTransformer/BooleanToStringTransformer.php b/src/Symfony/Component/Form/Extension/Core/DataTransformer/BooleanToStringTransformer.php index 5d3e5eaf051c2..f98b787cacde8 100644 --- a/src/Symfony/Component/Form/Extension/Core/DataTransformer/BooleanToStringTransformer.php +++ b/src/Symfony/Component/Form/Extension/Core/DataTransformer/BooleanToStringTransformer.php @@ -46,7 +46,7 @@ public function __construct($trueValue) * * @return string String value * - * @throws TransformationFailedException If the given value is not a Boolean. + * @throws TransformationFailedException if the given value is not a Boolean */ public function transform($value) { @@ -68,7 +68,7 @@ public function transform($value) * * @return bool Boolean value * - * @throws TransformationFailedException If the given value is not a string. + * @throws TransformationFailedException if the given value is not a string */ public function reverseTransform($value) { diff --git a/src/Symfony/Component/Form/Extension/Core/DataTransformer/ChoiceToBooleanArrayTransformer.php b/src/Symfony/Component/Form/Extension/Core/DataTransformer/ChoiceToBooleanArrayTransformer.php index 50ee4b693e485..89f13b6cb26e4 100644 --- a/src/Symfony/Component/Form/Extension/Core/DataTransformer/ChoiceToBooleanArrayTransformer.php +++ b/src/Symfony/Component/Form/Extension/Core/DataTransformer/ChoiceToBooleanArrayTransformer.php @@ -49,13 +49,13 @@ public function __construct(ChoiceListInterface $choiceList, $placeholderPresent * depending on whether a given option is selected. If this field is rendered * as select tag, the value is not modified. * - * @param mixed $choice An array if "multiple" is set to true, a scalar - * value otherwise. + * @param mixed $choice an array if "multiple" is set to true, a scalar + * value otherwise * * @return mixed An array * - * @throws TransformationFailedException If the given value is not scalar or - * if the choices can not be retrieved. + * @throws TransformationFailedException if the given value is not scalar or + * if the choices can not be retrieved */ public function transform($choice) { @@ -89,10 +89,10 @@ public function transform($choice) * * @return mixed A scalar value * - * @throws TransformationFailedException If the given value is not an array, + * @throws TransformationFailedException if the given value is not an array, * if the recuperation of the choices * fails or if some choice can't be - * found. + * found */ public function reverseTransform($values) { diff --git a/src/Symfony/Component/Form/Extension/Core/DataTransformer/ChoicesToBooleanArrayTransformer.php b/src/Symfony/Component/Form/Extension/Core/DataTransformer/ChoicesToBooleanArrayTransformer.php index 26c6781403227..6cbc5dd464cc0 100644 --- a/src/Symfony/Component/Form/Extension/Core/DataTransformer/ChoicesToBooleanArrayTransformer.php +++ b/src/Symfony/Component/Form/Extension/Core/DataTransformer/ChoicesToBooleanArrayTransformer.php @@ -44,8 +44,8 @@ public function __construct(ChoiceListInterface $choiceList) * * @return mixed An array * - * @throws TransformationFailedException If the given value is not an array - * or if the choices can not be retrieved. + * @throws TransformationFailedException if the given value is not an array + * or if the choices can not be retrieved */ public function transform($array) { @@ -83,10 +83,10 @@ public function transform($array) * * @return mixed An array * - * @throws TransformationFailedException If the given value is not an array, + * @throws TransformationFailedException if the given value is not an array, * if the recuperation of the choices * fails or if some choice can't be - * found. + * found */ public function reverseTransform($values) { diff --git a/src/Symfony/Component/Form/Extension/Core/DataTransformer/ChoicesToValuesTransformer.php b/src/Symfony/Component/Form/Extension/Core/DataTransformer/ChoicesToValuesTransformer.php index 0a1f2f028863a..65bcf6d4ae3ea 100644 --- a/src/Symfony/Component/Form/Extension/Core/DataTransformer/ChoicesToValuesTransformer.php +++ b/src/Symfony/Component/Form/Extension/Core/DataTransformer/ChoicesToValuesTransformer.php @@ -37,7 +37,7 @@ public function __construct(ChoiceListInterface $choiceList) * * @return array * - * @throws TransformationFailedException If the given value is not an array. + * @throws TransformationFailedException if the given value is not an array */ public function transform($array) { @@ -57,9 +57,9 @@ public function transform($array) * * @return array * - * @throws TransformationFailedException If the given value is not an array + * @throws TransformationFailedException if the given value is not an array * or if no matching choice could be - * found for some given value. + * found for some given value */ public function reverseTransform($array) { diff --git a/src/Symfony/Component/Form/Extension/Core/DataTransformer/DateTimeToLocalizedStringTransformer.php b/src/Symfony/Component/Form/Extension/Core/DataTransformer/DateTimeToLocalizedStringTransformer.php index e1db36bda663d..bc8f64dffa6c5 100644 --- a/src/Symfony/Component/Form/Extension/Core/DataTransformer/DateTimeToLocalizedStringTransformer.php +++ b/src/Symfony/Component/Form/Extension/Core/DataTransformer/DateTimeToLocalizedStringTransformer.php @@ -74,9 +74,9 @@ public function __construct($inputTimezone = null, $outputTimezone = null, $date * * @return string|array Localized date string/array * - * @throws TransformationFailedException If the given value is not an instance + * @throws TransformationFailedException if the given value is not an instance * of \DateTime or \DateTimeInterface or - * if the date could not be transformed. + * if the date could not be transformed */ public function transform($dateTime) { @@ -152,11 +152,11 @@ public function reverseTransform($value) /** * Returns a preconfigured IntlDateFormatter instance. * - * @param bool $ignoreTimezone Use UTC regardless of the configured timezone. + * @param bool $ignoreTimezone use UTC regardless of the configured timezone * * @return \IntlDateFormatter * - * @throws TransformationFailedException in case the date formatter can not be constructed. + * @throws TransformationFailedException in case the date formatter can not be constructed */ protected function getIntlDateFormatter($ignoreTimezone = false) { diff --git a/src/Symfony/Component/Form/Extension/Core/DataTransformer/MoneyToLocalizedStringTransformer.php b/src/Symfony/Component/Form/Extension/Core/DataTransformer/MoneyToLocalizedStringTransformer.php index 6eeee1280bd75..5993c01cb0da9 100644 --- a/src/Symfony/Component/Form/Extension/Core/DataTransformer/MoneyToLocalizedStringTransformer.php +++ b/src/Symfony/Component/Form/Extension/Core/DataTransformer/MoneyToLocalizedStringTransformer.php @@ -49,8 +49,8 @@ public function __construct($scale = 2, $grouping = true, $roundingMode = self:: * * @return string Localized money string * - * @throws TransformationFailedException If the given value is not numeric or - * if the value can not be transformed. + * @throws TransformationFailedException if the given value is not numeric or + * if the value can not be transformed */ public function transform($value) { @@ -72,8 +72,8 @@ public function transform($value) * * @return int|float Normalized number * - * @throws TransformationFailedException If the given value is not a string - * or if the value can not be transformed. + * @throws TransformationFailedException if the given value is not a string + * or if the value can not be transformed */ public function reverseTransform($value) { diff --git a/src/Symfony/Component/Form/Extension/Core/DataTransformer/NumberToLocalizedStringTransformer.php b/src/Symfony/Component/Form/Extension/Core/DataTransformer/NumberToLocalizedStringTransformer.php index 1e86ffb92e8a9..a719847142366 100644 --- a/src/Symfony/Component/Form/Extension/Core/DataTransformer/NumberToLocalizedStringTransformer.php +++ b/src/Symfony/Component/Form/Extension/Core/DataTransformer/NumberToLocalizedStringTransformer.php @@ -124,8 +124,8 @@ public function __construct($scale = null, $grouping = false, $roundingMode = se * * @return string Localized value * - * @throws TransformationFailedException If the given value is not numeric - * or if the value can not be transformed. + * @throws TransformationFailedException if the given value is not numeric + * or if the value can not be transformed */ public function transform($value) { @@ -157,8 +157,8 @@ public function transform($value) * * @return int|float The numeric value * - * @throws TransformationFailedException If the given value is not a string - * or if the value can not be transformed. + * @throws TransformationFailedException if the given value is not a string + * or if the value can not be transformed */ public function reverseTransform($value) { diff --git a/src/Symfony/Component/Form/Extension/Core/DataTransformer/PercentToLocalizedStringTransformer.php b/src/Symfony/Component/Form/Extension/Core/DataTransformer/PercentToLocalizedStringTransformer.php index 7fc191a054ff4..0eb3e2be26dcd 100644 --- a/src/Symfony/Component/Form/Extension/Core/DataTransformer/PercentToLocalizedStringTransformer.php +++ b/src/Symfony/Component/Form/Extension/Core/DataTransformer/PercentToLocalizedStringTransformer.php @@ -70,8 +70,8 @@ public function __construct($scale = null, $type = null) * * @return string Percentage value * - * @throws TransformationFailedException If the given value is not numeric or - * if the value could not be transformed. + * @throws TransformationFailedException if the given value is not numeric or + * if the value could not be transformed */ public function transform($value) { @@ -105,8 +105,8 @@ public function transform($value) * * @return int|float Normalized value * - * @throws TransformationFailedException If the given value is not a string or - * if the value could not be transformed. + * @throws TransformationFailedException if the given value is not a string or + * if the value could not be transformed */ public function reverseTransform($value) { diff --git a/src/Symfony/Component/Form/Extension/Core/DataTransformer/ValueToDuplicatesTransformer.php b/src/Symfony/Component/Form/Extension/Core/DataTransformer/ValueToDuplicatesTransformer.php index ffc9915fa409f..2c1d6d0f62b88 100644 --- a/src/Symfony/Component/Form/Extension/Core/DataTransformer/ValueToDuplicatesTransformer.php +++ b/src/Symfony/Component/Form/Extension/Core/DataTransformer/ValueToDuplicatesTransformer.php @@ -51,8 +51,8 @@ public function transform($value) * * @return mixed The value * - * @throws TransformationFailedException If the given value is not an array or - * if the given array can not be transformed. + * @throws TransformationFailedException if the given value is not an array or + * if the given array can not be transformed */ public function reverseTransform($array) { diff --git a/src/Symfony/Component/Form/Extension/Core/EventListener/MergeCollectionListener.php b/src/Symfony/Component/Form/Extension/Core/EventListener/MergeCollectionListener.php index a65116fd5c8ce..6cd5e69d0e48e 100644 --- a/src/Symfony/Component/Form/Extension/Core/EventListener/MergeCollectionListener.php +++ b/src/Symfony/Component/Form/Extension/Core/EventListener/MergeCollectionListener.php @@ -38,10 +38,10 @@ class MergeCollectionListener implements EventSubscriberInterface /** * Creates a new listener. * - * @param bool $allowAdd Whether values might be added to the - * collection. - * @param bool $allowDelete Whether values might be removed from the - * collection. + * @param bool $allowAdd whether values might be added to the + * collection + * @param bool $allowDelete whether values might be removed from the + * collection */ public function __construct($allowAdd = false, $allowDelete = false) { diff --git a/src/Symfony/Component/Form/Extension/Validator/ValidatorTypeGuesser.php b/src/Symfony/Component/Form/Extension/Validator/ValidatorTypeGuesser.php index 880e71d39a24b..b04a9447fc724 100644 --- a/src/Symfony/Component/Form/Extension/Validator/ValidatorTypeGuesser.php +++ b/src/Symfony/Component/Form/Extension/Validator/ValidatorTypeGuesser.php @@ -258,8 +258,8 @@ public function guessPatternForConstraint(Constraint $constraint) * @param string $property The property for which to find constraints * @param \Closure $closure The closure that returns a guess * for a given constraint - * @param mixed $defaultValue The default value assumed if no other value - * can be guessed. + * @param mixed $defaultValue the default value assumed if no other value + * can be guessed * * @return Guess|null The guessed value with the highest confidence */ diff --git a/src/Symfony/Component/Form/Extension/Validator/ViolationMapper/ViolationMapperInterface.php b/src/Symfony/Component/Form/Extension/Validator/ViolationMapper/ViolationMapperInterface.php index bb7c6b7670aef..7f3a4297c3fcb 100644 --- a/src/Symfony/Component/Form/Extension/Validator/ViolationMapper/ViolationMapperInterface.php +++ b/src/Symfony/Component/Form/Extension/Validator/ViolationMapper/ViolationMapperInterface.php @@ -24,10 +24,10 @@ interface ViolationMapperInterface * the given form. * * @param ConstraintViolation $violation The violation to map - * @param FormInterface $form The root form of the tree - * to map it to. - * @param bool $allowNonSynchronized Whether to allow - * mapping to non-synchronized forms. + * @param FormInterface $form the root form of the tree + * to map it to + * @param bool $allowNonSynchronized whether to allow + * mapping to non-synchronized forms */ public function mapViolation(ConstraintViolation $violation, FormInterface $form, $allowNonSynchronized = false); } diff --git a/src/Symfony/Component/Form/Extension/Validator/ViolationMapper/ViolationPath.php b/src/Symfony/Component/Form/Extension/Validator/ViolationMapper/ViolationPath.php index 1e984e2f4da83..fcc2b7c103d85 100644 --- a/src/Symfony/Component/Form/Extension/Validator/ViolationMapper/ViolationPath.php +++ b/src/Symfony/Component/Form/Extension/Validator/ViolationMapper/ViolationPath.php @@ -48,8 +48,8 @@ class ViolationPath implements \IteratorAggregate, PropertyPathInterface /** * Creates a new violation path from a string. * - * @param string $violationPath The property path of a {@link \Symfony\Component\Validator\ConstraintViolation} - * object. + * @param string $violationPath the property path of a {@link \Symfony\Component\Validator\ConstraintViolation} + * object */ public function __construct($violationPath) { @@ -210,7 +210,7 @@ public function isIndex($index) * * @return bool Whether the element maps to a form * - * @throws OutOfBoundsException If the offset is invalid. + * @throws OutOfBoundsException if the offset is invalid */ public function mapsForm($index) { diff --git a/src/Symfony/Component/Form/Form.php b/src/Symfony/Component/Form/Form.php index 87cd15bf47d87..7e662f8f1e5c0 100644 --- a/src/Symfony/Component/Form/Form.php +++ b/src/Symfony/Component/Form/Form.php @@ -996,7 +996,7 @@ public function offsetExists($name) * * @return FormInterface The child form * - * @throws \OutOfBoundsException If the named child does not exist. + * @throws \OutOfBoundsException if the named child does not exist */ public function offsetGet($name) { @@ -1009,8 +1009,8 @@ public function offsetGet($name) * @param string $name Ignored. The name of the child is used * @param FormInterface $child The child to be added * - * @throws AlreadySubmittedException If the form has already been submitted. - * @throws LogicException When trying to add a child to a non-compound form. + * @throws AlreadySubmittedException if the form has already been submitted + * @throws LogicException when trying to add a child to a non-compound form * * @see self::add() */ @@ -1024,7 +1024,7 @@ public function offsetSet($name, $child) * * @param string $name The name of the child to remove * - * @throws AlreadySubmittedException If the form has already been submitted. + * @throws AlreadySubmittedException if the form has already been submitted */ public function offsetUnset($name) { diff --git a/src/Symfony/Component/Form/FormConfigBuilder.php b/src/Symfony/Component/Form/FormConfigBuilder.php index 61c0da55c0bef..f51881a092c97 100644 --- a/src/Symfony/Component/Form/FormConfigBuilder.php +++ b/src/Symfony/Component/Form/FormConfigBuilder.php @@ -185,8 +185,8 @@ class FormConfigBuilder implements FormConfigBuilderInterface * @param EventDispatcherInterface $dispatcher The event dispatcher * @param array $options The form options * - * @throws InvalidArgumentException If the data class is not a valid class or if - * the name contains invalid characters. + * @throws InvalidArgumentException if the data class is not a valid class or if + * the name contains invalid characters */ public function __construct($name, $dataClass, EventDispatcherInterface $dispatcher, array $options = array()) { @@ -882,8 +882,8 @@ public function getFormConfig() * * @param string|int $name The tested form name * - * @throws UnexpectedTypeException If the name is not a string or an integer. - * @throws InvalidArgumentException If the name contains invalid characters. + * @throws UnexpectedTypeException if the name is not a string or an integer + * @throws InvalidArgumentException if the name contains invalid characters */ public static function validateName($name) { diff --git a/src/Symfony/Component/Form/FormConfigBuilderInterface.php b/src/Symfony/Component/Form/FormConfigBuilderInterface.php index 13ac4682b6bca..3cb4e384824de 100644 --- a/src/Symfony/Component/Form/FormConfigBuilderInterface.php +++ b/src/Symfony/Component/Form/FormConfigBuilderInterface.php @@ -152,9 +152,8 @@ public function setRequired($required); /** * Sets the property path that the form should be mapped to. * - * @param null|string|PropertyPathInterface $propertyPath - * The property path or null if the path should be set - * automatically based on the form's name. + * @param null|string|PropertyPathInterface $propertyPath the property path or null if the path should be set + * automatically based on the form's name * * @return $this The configuration object */ @@ -173,8 +172,8 @@ public function setMapped($mapped); /** * Sets whether the form's data should be modified by reference. * - * @param bool $byReference Whether the data should be - * modified by reference. + * @param bool $byReference whether the data should be + * modified by reference * * @return $this The configuration object */ diff --git a/src/Symfony/Component/Form/FormConfigInterface.php b/src/Symfony/Component/Form/FormConfigInterface.php index c2f97901d25c3..47a2ac35a89a5 100644 --- a/src/Symfony/Component/Form/FormConfigInterface.php +++ b/src/Symfony/Component/Form/FormConfigInterface.php @@ -213,8 +213,8 @@ public function getRequestHandler(); /** * Returns whether the form should be initialized upon creation. * - * @return bool Returns true if the form should be initialized - * when created, false otherwise. + * @return bool returns true if the form should be initialized + * when created, false otherwise */ public function getAutoInitialize(); diff --git a/src/Symfony/Component/Form/FormErrorIterator.php b/src/Symfony/Component/Form/FormErrorIterator.php index 41a1297d30f57..f3958e77aeccf 100644 --- a/src/Symfony/Component/Form/FormErrorIterator.php +++ b/src/Symfony/Component/Form/FormErrorIterator.php @@ -107,8 +107,8 @@ public function getForm() /** * Returns the current element of the iterator. * - * @return FormError|FormErrorIterator An error or an iterator containing - * nested errors. + * @return FormError|FormErrorIterator an error or an iterator containing + * nested errors */ public function current() { diff --git a/src/Symfony/Component/Form/FormInterface.php b/src/Symfony/Component/Form/FormInterface.php index a61f7f99d0d74..780c00f40af48 100644 --- a/src/Symfony/Component/Form/FormInterface.php +++ b/src/Symfony/Component/Form/FormInterface.php @@ -27,9 +27,9 @@ interface FormInterface extends \ArrayAccess, \Traversable, \Countable * * @return self * - * @throws Exception\AlreadySubmittedException If the form has already been submitted. - * @throws Exception\LogicException When trying to set a parent for a form with - * an empty name. + * @throws Exception\AlreadySubmittedException if the form has already been submitted + * @throws Exception\LogicException when trying to set a parent for a form with + * an empty name */ public function setParent(FormInterface $parent = null); @@ -49,9 +49,9 @@ public function getParent(); * * @return self * - * @throws Exception\AlreadySubmittedException If the form has already been submitted. - * @throws Exception\LogicException When trying to add a child to a non-compound form. - * @throws Exception\UnexpectedTypeException If $child or $type has an unexpected type. + * @throws Exception\AlreadySubmittedException if the form has already been submitted + * @throws Exception\LogicException when trying to add a child to a non-compound form + * @throws Exception\UnexpectedTypeException if $child or $type has an unexpected type */ public function add($child, $type = null, array $options = array()); @@ -62,7 +62,7 @@ public function add($child, $type = null, array $options = array()); * * @return self * - * @throws \OutOfBoundsException If the named child does not exist. + * @throws \OutOfBoundsException if the named child does not exist */ public function get($name); @@ -82,7 +82,7 @@ public function has($name); * * @return $this * - * @throws Exception\AlreadySubmittedException If the form has already been submitted. + * @throws Exception\AlreadySubmittedException if the form has already been submitted */ public function remove($name); @@ -112,7 +112,7 @@ public function getErrors($deep = false, $flatten = true); * * @return $this * - * @throws Exception\AlreadySubmittedException If the form has already been submitted. + * @throws Exception\AlreadySubmittedException if the form has already been submitted * @throws Exception\LogicException If listeners try to call setData in a cycle. Or if * the view data does not match the expected type * according to {@link FormConfigInterface::getDataClass}. @@ -129,7 +129,7 @@ public function getData(); /** * Returns the normalized data of the field. * - * @return mixed When the field is not submitted, the default data is returned + * @return mixed When the field is not submitted, the default data is returned. * When the field is submitted, the normalized submitted data is * returned if the field is valid, null otherwise. */ @@ -270,13 +270,13 @@ public function handleRequest($request = null); * Submits data to the form, transforms and validates it. * * @param null|string|array $submittedData The submitted data - * @param bool $clearMissing Whether to set fields to NULL + * @param bool $clearMissing whether to set fields to NULL * when they are missing in the - * submitted data. + * submitted data * * @return $this * - * @throws Exception\AlreadySubmittedException If the form has already been submitted. + * @throws Exception\AlreadySubmittedException if the form has already been submitted */ public function submit($submittedData, $clearMissing = true); diff --git a/src/Symfony/Component/Form/FormRendererEngineInterface.php b/src/Symfony/Component/Form/FormRendererEngineInterface.php index c3667b1dbb5fb..9d116b8608846 100644 --- a/src/Symfony/Component/Form/FormRendererEngineInterface.php +++ b/src/Symfony/Component/Form/FormRendererEngineInterface.php @@ -36,13 +36,13 @@ public function setTheme(FormView $view, $themes); * The type of the resource is decided by the implementation. The resource * is later passed to {@link renderBlock()} by the rendering algorithm. * - * @param FormView $view The view for determining the used themes + * @param FormView $view The view for determining the used themes. * First the themes attached directly to the * view with {@link setTheme()} are considered, * then the ones of its parent etc. - * @param string $blockName The name of the block to render + * @param string $blockName the name of the block to render * - * @return mixed The renderer resource or false, if none was found + * @return mixed the renderer resource or false, if none was found */ public function getResourceForBlockName(FormView $view, $blockName); @@ -70,12 +70,12 @@ public function getResourceForBlockName(FormView $view, $blockName); * The type of the resource is decided by the implementation. The resource * is later passed to {@link renderBlock()} by the rendering algorithm. * - * @param FormView $view The view for determining the used themes + * @param FormView $view The view for determining the used themes. * First the themes attached directly to * the view with {@link setTheme()} are * considered, then the ones of its parent etc. - * @param array $blockNameHierarchy The block name hierarchy, with the root block - * at the beginning. + * @param array $blockNameHierarchy the block name hierarchy, with the root block + * at the beginning * @param int $hierarchyLevel The level in the hierarchy at which to start * looking. Level 0 indicates the root block, i.e. * the first element of $blockNameHierarchy. @@ -110,12 +110,12 @@ public function getResourceForBlockNameHierarchy(FormView $view, array $blockNam * The type of the resource is decided by the implementation. The resource * is later passed to {@link renderBlock()} by the rendering algorithm. * - * @param FormView $view The view for determining the used themes + * @param FormView $view The view for determining the used themes. * First the themes attached directly to * the view with {@link setTheme()} are * considered, then the ones of its parent etc. - * @param array $blockNameHierarchy The block name hierarchy, with the root block - * at the beginning. + * @param array $blockNameHierarchy the block name hierarchy, with the root block + * at the beginning * @param int $hierarchyLevel The level in the hierarchy at which to start * looking. Level 0 indicates the root block, i.e. * the first element of $blockNameHierarchy. diff --git a/src/Symfony/Component/Form/SubmitButton.php b/src/Symfony/Component/Form/SubmitButton.php index 4bfc1b6465819..ae69e0426d6b1 100644 --- a/src/Symfony/Component/Form/SubmitButton.php +++ b/src/Symfony/Component/Form/SubmitButton.php @@ -39,7 +39,7 @@ public function isClicked() * * @return $this * - * @throws Exception\AlreadySubmittedException If the form has already been submitted. + * @throws Exception\AlreadySubmittedException if the form has already been submitted */ public function submit($submittedData, $clearMissing = true) { diff --git a/src/Symfony/Component/Form/Util/OrderedHashMapIterator.php b/src/Symfony/Component/Form/Util/OrderedHashMapIterator.php index 534d74ea6f0e4..7305f51640c38 100644 --- a/src/Symfony/Component/Form/Util/OrderedHashMapIterator.php +++ b/src/Symfony/Component/Form/Util/OrderedHashMapIterator.php @@ -58,10 +58,10 @@ class OrderedHashMapIterator implements \Iterator /** * Creates a new iterator. * - * @param array $elements The elements of the map, indexed by their - * keys. - * @param array $orderedKeys The keys of the map in the order in which - * they should be iterated. + * @param array $elements the elements of the map, indexed by their + * keys + * @param array $orderedKeys the keys of the map in the order in which + * they should be iterated * @param array $managedCursors An array from which to reference the * iterator's cursor as long as it is alive. * This array is managed by the corresponding diff --git a/src/Symfony/Component/HttpFoundation/Response.php b/src/Symfony/Component/HttpFoundation/Response.php index f9512d6706ef9..074c896ff7b3d 100644 --- a/src/Symfony/Component/HttpFoundation/Response.php +++ b/src/Symfony/Component/HttpFoundation/Response.php @@ -441,12 +441,12 @@ public function getProtocolVersion() /** * Sets the response status code. * - * @param int $code HTTP status code - * @param mixed $text HTTP status text - * * If the status text is null it will be automatically populated for the known * status codes and left empty otherwise. * + * @param int $code HTTP status code + * @param mixed $text HTTP status text + * * @return $this * * @throws \InvalidArgumentException When the HTTP status code is not valid diff --git a/src/Symfony/Component/HttpFoundation/Session/SessionInterface.php b/src/Symfony/Component/HttpFoundation/Session/SessionInterface.php index d3fcd2eec4e73..172c9b457fb15 100644 --- a/src/Symfony/Component/HttpFoundation/Session/SessionInterface.php +++ b/src/Symfony/Component/HttpFoundation/Session/SessionInterface.php @@ -25,7 +25,7 @@ interface SessionInterface * * @return bool True if session started * - * @throws \RuntimeException If session fails to start. + * @throws \RuntimeException if session fails to start */ public function start(); diff --git a/src/Symfony/Component/HttpFoundation/Session/Storage/SessionStorageInterface.php b/src/Symfony/Component/HttpFoundation/Session/Storage/SessionStorageInterface.php index 34f6c4633f477..097583d5a51eb 100644 --- a/src/Symfony/Component/HttpFoundation/Session/Storage/SessionStorageInterface.php +++ b/src/Symfony/Component/HttpFoundation/Session/Storage/SessionStorageInterface.php @@ -26,7 +26,7 @@ interface SessionStorageInterface * * @return bool True if started * - * @throws \RuntimeException If something goes wrong starting the session. + * @throws \RuntimeException if something goes wrong starting the session */ public function start(); @@ -104,8 +104,8 @@ public function regenerate($destroy = false, $lifetime = null); * a real PHP session would interfere with testing, in which case * it should actually persist the session data if required. * - * @throws \RuntimeException If the session is saved without being started, or if the session - * is already closed. + * @throws \RuntimeException if the session is saved without being started, or if the session + * is already closed */ public function save(); diff --git a/src/Symfony/Component/HttpKernel/EventListener/FragmentListener.php b/src/Symfony/Component/HttpKernel/EventListener/FragmentListener.php index ad6349286dde7..a00ea18304691 100644 --- a/src/Symfony/Component/HttpKernel/EventListener/FragmentListener.php +++ b/src/Symfony/Component/HttpKernel/EventListener/FragmentListener.php @@ -51,7 +51,7 @@ public function __construct(UriSigner $signer, $fragmentPath = '/_fragment') * * @param GetResponseEvent $event A GetResponseEvent instance * - * @throws AccessDeniedHttpException if the request does not come from a trusted IP. + * @throws AccessDeniedHttpException if the request does not come from a trusted IP */ public function onKernelRequest(GetResponseEvent $event) { diff --git a/src/Symfony/Component/Intl/Data/Bundle/Compiler/GenrbCompiler.php b/src/Symfony/Component/Intl/Data/Bundle/Compiler/GenrbCompiler.php index 9a91888cf57cf..8db6890c7c680 100644 --- a/src/Symfony/Component/Intl/Data/Bundle/Compiler/GenrbCompiler.php +++ b/src/Symfony/Component/Intl/Data/Bundle/Compiler/GenrbCompiler.php @@ -34,7 +34,7 @@ class GenrbCompiler implements BundleCompilerInterface * @param string $envVars Optional. Environment variables to be loaded when * running "genrb". * - * @throws RuntimeException If the "genrb" cannot be found. + * @throws RuntimeException if the "genrb" cannot be found */ public function __construct($genrb = 'genrb', $envVars = '') { diff --git a/src/Symfony/Component/Intl/Data/Bundle/Reader/BufferedBundleReader.php b/src/Symfony/Component/Intl/Data/Bundle/Reader/BufferedBundleReader.php index ff04294683e32..1826fcd0fa798 100644 --- a/src/Symfony/Component/Intl/Data/Bundle/Reader/BufferedBundleReader.php +++ b/src/Symfony/Component/Intl/Data/Bundle/Reader/BufferedBundleReader.php @@ -31,8 +31,8 @@ class BufferedBundleReader implements BundleReaderInterface * Buffers a given reader. * * @param BundleReaderInterface $reader The reader to buffer - * @param int $bufferSize The number of entries to store - * in the buffer. + * @param int $bufferSize the number of entries to store + * in the buffer */ public function __construct(BundleReaderInterface $reader, $bufferSize) { diff --git a/src/Symfony/Component/Intl/Data/Bundle/Reader/BundleEntryReaderInterface.php b/src/Symfony/Component/Intl/Data/Bundle/Reader/BundleEntryReaderInterface.php index e999440190aca..13cf85bb48810 100644 --- a/src/Symfony/Component/Intl/Data/Bundle/Reader/BundleEntryReaderInterface.php +++ b/src/Symfony/Component/Intl/Data/Bundle/Reader/BundleEntryReaderInterface.php @@ -46,8 +46,8 @@ interface BundleEntryReaderInterface extends BundleReaderInterface * (i.e. array or \ArrayAccess) or cannot be found * in the requested locale. * - * @return mixed Returns an array or {@link \ArrayAccess} instance for - * complex data and a scalar value for simple data. + * @return mixed returns an array or {@link \ArrayAccess} instance for + * complex data and a scalar value for simple data * * @throws MissingResourceException If the indices cannot be accessed */ diff --git a/src/Symfony/Component/Intl/Data/Bundle/Reader/BundleReaderInterface.php b/src/Symfony/Component/Intl/Data/Bundle/Reader/BundleReaderInterface.php index 8d3da825f77eb..04d5900e34228 100644 --- a/src/Symfony/Component/Intl/Data/Bundle/Reader/BundleReaderInterface.php +++ b/src/Symfony/Component/Intl/Data/Bundle/Reader/BundleReaderInterface.php @@ -26,8 +26,8 @@ interface BundleReaderInterface * @param string $path The path to the resource bundle * @param string $locale The locale to read * - * @return mixed Returns an array or {@link \ArrayAccess} instance for - * complex data, a scalar value otherwise. + * @return mixed returns an array or {@link \ArrayAccess} instance for + * complex data, a scalar value otherwise */ public function read($path, $locale); } diff --git a/src/Symfony/Component/Intl/Data/Bundle/Writer/TextBundleWriter.php b/src/Symfony/Component/Intl/Data/Bundle/Writer/TextBundleWriter.php index 3b7d94f10a247..a0fb4334f907d 100644 --- a/src/Symfony/Component/Intl/Data/Bundle/Writer/TextBundleWriter.php +++ b/src/Symfony/Component/Intl/Data/Bundle/Writer/TextBundleWriter.php @@ -46,8 +46,8 @@ public function write($path, $locale, $data, $fallback = true) * @param resource $file The file handle to write to * @param string $bundleName The name of the bundle * @param mixed $value The value of the node - * @param bool $fallback Whether the resource bundle should be merged - * with the fallback locale. + * @param bool $fallback whether the resource bundle should be merged + * with the fallback locale * * @see http://source.icu-project.org/repos/icu/icuhtml/trunk/design/bnf_rb.txt */ @@ -66,8 +66,8 @@ private function writeResourceBundle($file, $bundleName, $value, $fallback) * @param resource $file The file handle to write to * @param mixed $value The value of the node * @param int $indentation The number of levels to indent - * @param bool $requireBraces Whether to require braces to be printed - * around the value. + * @param bool $requireBraces whether to require braces to be printed + * around the value * * @see http://source.icu-project.org/repos/icu/icuhtml/trunk/design/bnf_rb.txt */ @@ -153,8 +153,8 @@ private function writeIntVector($file, array $value, $indentation) * * @param resource $file The file handle to write to * @param string $value The value of the node - * @param bool $requireBraces Whether to require braces to be printed - * around the value. + * @param bool $requireBraces whether to require braces to be printed + * around the value * * @see http://source.icu-project.org/repos/icu/icuhtml/trunk/design/bnf_rb.txt */ @@ -199,11 +199,11 @@ private function writeArray($file, array $value, $indentation) * @param resource $file The file handle to write to * @param array|\Traversable $value The value of the node * @param int $indentation The number of levels to indent - * @param bool $fallback Whether the table should be merged - * with the fallback locale. + * @param bool $fallback whether the table should be merged + * with the fallback locale * - * @throws UnexpectedTypeException When $value is not an array and not a - * \Traversable instance. + * @throws UnexpectedTypeException when $value is not an array and not a + * \Traversable instance */ private function writeTable($file, $value, $indentation, $fallback = true) { diff --git a/src/Symfony/Component/Intl/DateFormatter/IntlDateFormatter.php b/src/Symfony/Component/Intl/DateFormatter/IntlDateFormatter.php index 438b4d73e943b..e3279d0b352d5 100644 --- a/src/Symfony/Component/Intl/DateFormatter/IntlDateFormatter.php +++ b/src/Symfony/Component/Intl/DateFormatter/IntlDateFormatter.php @@ -167,8 +167,8 @@ public function __construct($locale, $datetype, $timetype, $timezone = null, $ca * @param int $datetype Type of date formatting, one of the format type constants * @param int $timetype Type of time formatting, one of the format type constants * @param string $timezone Timezone identifier - * @param int $calendar Calendar to use for formatting or parsing; default is Gregorian - * One of the calendar constants. + * @param int $calendar calendar to use for formatting or parsing; default is Gregorian + * One of the calendar constants * @param string $pattern Optional pattern to use when formatting * * @return self @@ -524,7 +524,7 @@ public function setPattern($pattern) /** * Set the formatter's timezone identifier. * - * @param string $timeZoneId The time zone ID string of the time zone to use + * @param string $timeZoneId The time zone ID string of the time zone to use. * If NULL or the empty string, the default time zone for the * runtime is used. * diff --git a/src/Symfony/Component/Intl/NumberFormatter/NumberFormatter.php b/src/Symfony/Component/Intl/NumberFormatter/NumberFormatter.php index ce03e9f5d6642..b5aa050a4ea13 100644 --- a/src/Symfony/Component/Intl/NumberFormatter/NumberFormatter.php +++ b/src/Symfony/Component/Intl/NumberFormatter/NumberFormatter.php @@ -258,7 +258,7 @@ class NumberFormatter * Constructor. * * @param string $locale The locale code. The only currently supported locale is "en" (or null using the default locale, i.e. "en") - * @param int $style Style of the formatting, one of the format style constants + * @param int $style Style of the formatting, one of the format style constants. * The only supported styles are NumberFormatter::DECIMAL * and NumberFormatter::CURRENCY. * @param string $pattern Not supported. A pattern string in case $style is NumberFormat::PATTERN_DECIMAL or @@ -295,7 +295,7 @@ public function __construct($locale = 'en', $style = null, $pattern = null) * Static constructor. * * @param string $locale The locale code. The only supported locale is "en" (or null using the default locale, i.e. "en") - * @param int $style Style of the formatting, one of the format style constants + * @param int $style Style of the formatting, one of the format style constants. * The only currently supported styles are NumberFormatter::DECIMAL * and NumberFormatter::CURRENCY. * @param string $pattern Not supported. A pattern string in case $style is NumberFormat::PATTERN_DECIMAL or @@ -355,8 +355,8 @@ public function formatCurrency($value, $currency) /** * Format a number. * - * @param int|float $value The value to format - * @param int $type Type of the formatting, one of the format type constants + * @param int|float $value the value to format + * @param int $type Type of the formatting, one of the format type constants. * Only type NumberFormatter::TYPE_DEFAULT is currently supported. * * @return bool|string The formatted value or false on error @@ -516,9 +516,9 @@ public function parseCurrency($value, &$currency, &$position = null) /** * Parse a number. * - * @param string $value The value to parse - * @param int $type Type of the formatting, one of the format type constants. NumberFormatter::TYPE_DOUBLE by default - * @param int $position Offset to begin the parsing on return this value will hold the offset at which the parsing ended + * @param string $value the value to parse + * @param int $type Type of the formatting, one of the format type constants. NumberFormatter::TYPE_DOUBLE by default. + * @param int $position offset to begin the parsing on return this value will hold the offset at which the parsing ended * * @return int|float|false The parsed value of false on error * @@ -566,10 +566,10 @@ public function parse($value, $type = self::TYPE_DOUBLE, &$position = 0) /** * Set an attribute. * - * @param int $attr An attribute specifier, one of the numeric attribute constants + * @param int $attr An attribute specifier, one of the numeric attribute constants. * The only currently supported attributes are NumberFormatter::FRACTION_DIGITS, * NumberFormatter::GROUPING_USED and NumberFormatter::ROUNDING_MODE. - * @param int $value The attribute value + * @param int $value the attribute value * * @return bool true on success or false on failure * diff --git a/src/Symfony/Component/Intl/Resources/stubs/functions.php b/src/Symfony/Component/Intl/Resources/stubs/functions.php index 64e111e8abcb7..c7250d1fd15d5 100644 --- a/src/Symfony/Component/Intl/Resources/stubs/functions.php +++ b/src/Symfony/Component/Intl/Resources/stubs/functions.php @@ -35,8 +35,8 @@ function intl_is_failure($errorCode) * * @author Bernhard Schussek * - * @return bool The error code of the last intl function call or - * IntlGlobals::U_ZERO_ERROR if no error occurred. + * @return bool the error code of the last intl function call or + * IntlGlobals::U_ZERO_ERROR if no error occurred * * @see IntlGlobals::getErrorCode() */ @@ -51,8 +51,8 @@ function intl_get_error_code() * * @author Bernhard Schussek * - * @return bool The error message of the last intl function call or - * "U_ZERO_ERROR" if no error occurred. + * @return bool the error message of the last intl function call or + * "U_ZERO_ERROR" if no error occurred * * @see IntlGlobals::getErrorMessage() */ diff --git a/src/Symfony/Component/Intl/Util/IcuVersion.php b/src/Symfony/Component/Intl/Util/IcuVersion.php index e7324e7fd381a..1f141224a59e8 100644 --- a/src/Symfony/Component/Intl/Util/IcuVersion.php +++ b/src/Symfony/Component/Intl/Util/IcuVersion.php @@ -84,8 +84,8 @@ public static function compare($version1, $version2, $operator, $precision = nul * @param int|null $precision The number of components to include. Pass * NULL to return the version unchanged. * - * @return string|null The normalized ICU version or NULL if it couldn't be - * normalized. + * @return string|null the normalized ICU version or NULL if it couldn't be + * normalized */ public static function normalize($version, $precision) { diff --git a/src/Symfony/Component/Intl/Util/SvnCommit.php b/src/Symfony/Component/Intl/Util/SvnCommit.php index c5ae1f1d79fa7..ef90b6f884e87 100644 --- a/src/Symfony/Component/Intl/Util/SvnCommit.php +++ b/src/Symfony/Component/Intl/Util/SvnCommit.php @@ -26,8 +26,8 @@ class SvnCommit /** * Creates a commit from the given "svn info" data. * - * @param \SimpleXMLElement $svnInfo The XML result from the "svn info" - * command. + * @param \SimpleXMLElement $svnInfo the XML result from the "svn info" + * command */ public function __construct(\SimpleXMLElement $svnInfo) { diff --git a/src/Symfony/Component/Intl/Util/SvnRepository.php b/src/Symfony/Component/Intl/Util/SvnRepository.php index 8b5e8f31f859e..3732cbb3920d7 100644 --- a/src/Symfony/Component/Intl/Util/SvnRepository.php +++ b/src/Symfony/Component/Intl/Util/SvnRepository.php @@ -44,7 +44,7 @@ class SvnRepository * * @return static * - * @throws RuntimeException If an error occurs during the download. + * @throws RuntimeException if an error occurs during the download */ public static function download($url, $targetDir) { @@ -119,7 +119,7 @@ public function getLastCommit() * * @return \SimpleXMLElement The XML result from the "svn info" command * - * @throws RuntimeException If the "svn info" command failed. + * @throws RuntimeException if the "svn info" command failed */ private function getSvnInfo() { diff --git a/src/Symfony/Component/Intl/Util/Version.php b/src/Symfony/Component/Intl/Util/Version.php index 11e97fe8bdd94..d24c3bae1bf9b 100644 --- a/src/Symfony/Component/Intl/Util/Version.php +++ b/src/Symfony/Component/Intl/Util/Version.php @@ -67,8 +67,8 @@ public static function compare($version1, $version2, $operator, $precision = nul * @param int|null $precision The number of components to include. Pass * NULL to return the version unchanged. * - * @return string|null The normalized version or NULL if it couldn't be - * normalized. + * @return string|null the normalized version or NULL if it couldn't be + * normalized */ public static function normalize($version, $precision) { diff --git a/src/Symfony/Component/OptionsResolver/OptionsResolverInterface.php b/src/Symfony/Component/OptionsResolver/OptionsResolverInterface.php index f8b6885742d8a..58e499e0ac8f4 100644 --- a/src/Symfony/Component/OptionsResolver/OptionsResolverInterface.php +++ b/src/Symfony/Component/OptionsResolver/OptionsResolverInterface.php @@ -40,8 +40,8 @@ interface OptionsResolverInterface * * The closures should return the lazily created option value. * - * @param array $defaultValues A list of option names as keys and default - * values or closures as values. + * @param array $defaultValues a list of option names as keys and default + * values or closures as values * * @return $this */ @@ -55,8 +55,8 @@ public function setDefaults(array $defaultValues); * performance if the previous default value is calculated by an expensive * closure. * - * @param array $defaultValues A list of option names as keys and default - * values or closures as values. + * @param array $defaultValues a list of option names as keys and default + * values or closures as values * * @return $this */ @@ -92,15 +92,15 @@ public function setRequired($optionNames); /** * Sets allowed values for a list of options. * - * @param array $allowedValues A list of option names as keys and arrays + * @param array $allowedValues a list of option names as keys and arrays * with values acceptable for that option as - * values. + * values * * @return $this * - * @throws InvalidOptionsException If an option has not been defined + * @throws InvalidOptionsException if an option has not been defined * (see {@link isKnown()}) for which - * an allowed value is set. + * an allowed value is set */ public function setAllowedValues($allowedValues); @@ -109,28 +109,28 @@ public function setAllowedValues($allowedValues); * * The values are merged with the allowed values defined previously. * - * @param array $allowedValues A list of option names as keys and arrays + * @param array $allowedValues a list of option names as keys and arrays * with values acceptable for that option as - * values. + * values * * @return $this * - * @throws InvalidOptionsException If an option has not been defined + * @throws InvalidOptionsException if an option has not been defined * (see {@link isKnown()}) for which - * an allowed value is set. + * an allowed value is set */ public function addAllowedValues($allowedValues); /** * Sets allowed types for a list of options. * - * @param array $allowedTypes A list of option names as keys and type - * names passed as string or array as values. + * @param array $allowedTypes a list of option names as keys and type + * names passed as string or array as values * * @return $this * - * @throws InvalidOptionsException If an option has not been defined for - * which an allowed type is set. + * @throws InvalidOptionsException if an option has not been defined for + * which an allowed type is set */ public function setAllowedTypes($allowedTypes); @@ -139,13 +139,13 @@ public function setAllowedTypes($allowedTypes); * * The types are merged with the allowed types defined previously. * - * @param array $allowedTypes A list of option names as keys and type - * names passed as string or array as values. + * @param array $allowedTypes a list of option names as keys and type + * names passed as string or array as values * * @return $this * - * @throws InvalidOptionsException If an option has not been defined for - * which an allowed type is set. + * @throws InvalidOptionsException if an option has not been defined for + * which an allowed type is set */ public function addAllowedTypes($allowedTypes); @@ -201,12 +201,12 @@ public function isRequired($option); * * @return array A list of options and their values * - * @throws InvalidOptionsException If any of the passed options has not + * @throws InvalidOptionsException if any of the passed options has not * been defined or does not contain an - * allowed value. - * @throws MissingOptionsException If a required option is missing. - * @throws OptionDefinitionException If a cyclic dependency is detected - * between two lazy options. + * allowed value + * @throws MissingOptionsException if a required option is missing + * @throws OptionDefinitionException if a cyclic dependency is detected + * between two lazy options */ public function resolve(array $options = array()); } diff --git a/src/Symfony/Component/Process/Process.php b/src/Symfony/Component/Process/Process.php index 96a93343f1d5d..b31230d2939e6 100644 --- a/src/Symfony/Component/Process/Process.php +++ b/src/Symfony/Component/Process/Process.php @@ -1487,7 +1487,7 @@ private function doSignal($signal, $throwException) * * @param string $functionName The function name that was called * - * @throws LogicException If the process has not run. + * @throws LogicException if the process has not run */ private function requireProcessIsStarted($functionName) { @@ -1501,7 +1501,7 @@ private function requireProcessIsStarted($functionName) * * @param string $functionName The function name that was called * - * @throws LogicException If the process is not yet terminated. + * @throws LogicException if the process is not yet terminated */ private function requireProcessIsTerminated($functionName) { diff --git a/src/Symfony/Component/PropertyAccess/PropertyAccessor.php b/src/Symfony/Component/PropertyAccess/PropertyAccessor.php index a6615f11e7a5e..03dc617782f2d 100644 --- a/src/Symfony/Component/PropertyAccess/PropertyAccessor.php +++ b/src/Symfony/Component/PropertyAccess/PropertyAccessor.php @@ -330,7 +330,7 @@ public function isWritable($objectOrArray, $propertyPath) * * @return array The values read in the path * - * @throws UnexpectedTypeException If a value within the path is neither object nor array. + * @throws UnexpectedTypeException if a value within the path is neither object nor array * @throws NoSuchIndexException If a non-existing index is accessed */ private function readPropertiesUntil($zval, PropertyPathInterface $propertyPath, $lastIndex, $ignoreInvalidIndices = true) @@ -448,7 +448,7 @@ private function readIndex($zval, $index) * * @return array The array containing the value of the property * - * @throws NoSuchPropertyException If the property does not exist or is not public. + * @throws NoSuchPropertyException if the property does not exist or is not public */ private function readProperty($zval, $property) { @@ -590,7 +590,7 @@ private function writeIndex($zval, $index, $value) * @param string $property The property to write * @param mixed $value The value to write * - * @throws NoSuchPropertyException If the property does not exist or is not public. + * @throws NoSuchPropertyException if the property does not exist or is not public */ private function writeProperty($zval, $property, $value) { diff --git a/src/Symfony/Component/PropertyAccess/PropertyPathBuilder.php b/src/Symfony/Component/PropertyAccess/PropertyPathBuilder.php index 57751bf13e741..9d1e0870715a5 100644 --- a/src/Symfony/Component/PropertyAccess/PropertyPathBuilder.php +++ b/src/Symfony/Component/PropertyAccess/PropertyPathBuilder.php @@ -45,10 +45,10 @@ public function __construct($path = null) * Appends a (sub-) path to the current path. * * @param PropertyPathInterface|string $path The path to append - * @param int $offset The offset where the appended - * piece starts in $path. - * @param int $length The length of the appended piece - * If 0, the full path is appended. + * @param int $offset the offset where the appended + * piece starts in $path + * @param int $length the length of the appended piece + * If 0, the full path is appended */ public function append($path, $offset = 0, $length = 0) { @@ -113,10 +113,10 @@ public function remove($offset, $length = 1) * @param int $offset The offset at which to replace * @param int $length The length of the piece to replace * @param PropertyPathInterface|string $path The path to insert - * @param int $pathOffset The offset where the inserted piece - * starts in $path. - * @param int $pathLength The length of the inserted piece - * If 0, the full path is inserted. + * @param int $pathOffset the offset where the inserted piece + * starts in $path + * @param int $pathLength the length of the inserted piece + * If 0, the full path is inserted * * @throws OutOfBoundsException If the offset is invalid */ diff --git a/src/Symfony/Component/Routing/Loader/XmlFileLoader.php b/src/Symfony/Component/Routing/Loader/XmlFileLoader.php index cdf1973df4158..e8713ccab8b2d 100644 --- a/src/Symfony/Component/Routing/Loader/XmlFileLoader.php +++ b/src/Symfony/Component/Routing/Loader/XmlFileLoader.php @@ -36,8 +36,8 @@ class XmlFileLoader extends FileLoader * * @return RouteCollection A RouteCollection instance * - * @throws \InvalidArgumentException When the file cannot be loaded or when the XML cannot be - * parsed because it does not validate against the scheme. + * @throws \InvalidArgumentException when the file cannot be loaded or when the XML cannot be + * parsed because it does not validate against the scheme */ public function load($file, $type = null) { diff --git a/src/Symfony/Component/Routing/RouteCompiler.php b/src/Symfony/Component/Routing/RouteCompiler.php index ba608e7dd2e70..ecbc96422989a 100644 --- a/src/Symfony/Component/Routing/RouteCompiler.php +++ b/src/Symfony/Component/Routing/RouteCompiler.php @@ -40,8 +40,8 @@ class RouteCompiler implements RouteCompilerInterface * {@inheritdoc} * * @throws \LogicException If a variable is referenced more than once - * @throws \DomainException If a variable name starts with a digit or if it is too long to be successfully used as - * a PCRE subpattern. + * @throws \DomainException if a variable name starts with a digit or if it is too long to be successfully used as + * a PCRE subpattern */ public static function compile(Route $route) { diff --git a/src/Symfony/Component/Security/Core/Authorization/AuthorizationChecker.php b/src/Symfony/Component/Security/Core/Authorization/AuthorizationChecker.php index 23c190cb563d0..483ee6e5ac296 100644 --- a/src/Symfony/Component/Security/Core/Authorization/AuthorizationChecker.php +++ b/src/Symfony/Component/Security/Core/Authorization/AuthorizationChecker.php @@ -49,7 +49,7 @@ public function __construct(TokenStorageInterface $tokenStorage, AuthenticationM /** * {@inheritdoc} * - * @throws AuthenticationCredentialsNotFoundException when the token storage has no authentication token. + * @throws AuthenticationCredentialsNotFoundException when the token storage has no authentication token */ final public function isGranted($attributes, $object = null) { diff --git a/src/Symfony/Component/Security/Core/User/InMemoryUserProvider.php b/src/Symfony/Component/Security/Core/User/InMemoryUserProvider.php index e09d72e564f12..cde4454e9be3e 100644 --- a/src/Symfony/Component/Security/Core/User/InMemoryUserProvider.php +++ b/src/Symfony/Component/Security/Core/User/InMemoryUserProvider.php @@ -101,7 +101,7 @@ public function supportsClass($class) * * @return User * - * @throws UsernameNotFoundException If user whose given username does not exist. + * @throws UsernameNotFoundException if user whose given username does not exist */ private function getUser($username) { diff --git a/src/Symfony/Component/Security/Http/Logout/LogoutUrlGenerator.php b/src/Symfony/Component/Security/Http/Logout/LogoutUrlGenerator.php index 1472a99b244a2..1499d7e5ea33f 100644 --- a/src/Symfony/Component/Security/Http/Logout/LogoutUrlGenerator.php +++ b/src/Symfony/Component/Security/Http/Logout/LogoutUrlGenerator.php @@ -90,7 +90,7 @@ public function getLogoutUrl($key = null) * * @return string The logout URL * - * @throws \InvalidArgumentException if no LogoutListener is registered for the key or the key could not be found automatically. + * @throws \InvalidArgumentException if no LogoutListener is registered for the key or the key could not be found automatically */ private function generateLogoutUrl($key, $referenceType) { diff --git a/src/Symfony/Component/Serializer/Encoder/ChainDecoder.php b/src/Symfony/Component/Serializer/Encoder/ChainDecoder.php index 352ba584a7638..f8f17b4f723e6 100644 --- a/src/Symfony/Component/Serializer/Encoder/ChainDecoder.php +++ b/src/Symfony/Component/Serializer/Encoder/ChainDecoder.php @@ -59,7 +59,7 @@ public function supportsDecoding($format) * * @return DecoderInterface * - * @throws RuntimeException If no decoder is found. + * @throws RuntimeException if no decoder is found */ private function getDecoder($format) { diff --git a/src/Symfony/Component/Serializer/Normalizer/NormalizableInterface.php b/src/Symfony/Component/Serializer/Normalizer/NormalizableInterface.php index e19fe5ce58576..48fb8b482ee44 100644 --- a/src/Symfony/Component/Serializer/Normalizer/NormalizableInterface.php +++ b/src/Symfony/Component/Serializer/Normalizer/NormalizableInterface.php @@ -27,11 +27,11 @@ interface NormalizableInterface * It is important to understand that the normalize() call should normalize * recursively all child objects of the implementor. * - * @param NormalizerInterface $normalizer The normalizer is given so that you - * can use it to normalize objects contained within this object. - * @param string|null $format The format is optionally given to be able to normalize differently - * based on different output formats. - * @param array $context Options for normalizing this object + * @param NormalizerInterface $normalizer the normalizer is given so that you + * can use it to normalize objects contained within this object + * @param string|null $format the format is optionally given to be able to normalize differently + * based on different output formats + * @param array $context options for normalizing this object * * @return array|scalar */ diff --git a/src/Symfony/Component/Translation/Loader/MoFileLoader.php b/src/Symfony/Component/Translation/Loader/MoFileLoader.php index ed8c9f1dc9023..3a0c80f1c91cf 100644 --- a/src/Symfony/Component/Translation/Loader/MoFileLoader.php +++ b/src/Symfony/Component/Translation/Loader/MoFileLoader.php @@ -82,7 +82,7 @@ public function load($resource, $locale, $domain = 'messages') * * @return array * - * @throws InvalidResourceException If stream content has an invalid format. + * @throws InvalidResourceException if stream content has an invalid format */ private function parse($resource) { diff --git a/src/Symfony/Component/Validator/Constraint.php b/src/Symfony/Component/Validator/Constraint.php index 08041d4c7eed1..fc9d8ae563448 100644 --- a/src/Symfony/Component/Validator/Constraint.php +++ b/src/Symfony/Component/Validator/Constraint.php @@ -209,7 +209,7 @@ public function __set($option, $value) * * @throws InvalidOptionsException If an invalid option name is given * - * @internal This method should not be used or overwritten in userland code. + * @internal this method should not be used or overwritten in userland code */ public function __get($option) { diff --git a/src/Symfony/Component/Validator/ConstraintViolationInterface.php b/src/Symfony/Component/Validator/ConstraintViolationInterface.php index 363ef27ef0c51..de8ed69729dac 100644 --- a/src/Symfony/Component/Validator/ConstraintViolationInterface.php +++ b/src/Symfony/Component/Validator/ConstraintViolationInterface.php @@ -56,8 +56,8 @@ public function getMessageTemplate(); /** * Returns the parameters to be inserted into the raw violation message. * - * @return array A possibly empty list of parameters indexed by the names - * that appear in the message template. + * @return array a possibly empty list of parameters indexed by the names + * that appear in the message template * * @see getMessageTemplate() * @deprecated since version 2.7, to be replaced by getParameters() in 3.0. @@ -111,8 +111,8 @@ public function getPropertyPath(); /** * Returns the value that caused the violation. * - * @return mixed The invalid value that caused the validated constraint to - * fail. + * @return mixed the invalid value that caused the validated constraint to + * fail */ public function getInvalidValue(); diff --git a/src/Symfony/Component/Validator/ConstraintViolationListInterface.php b/src/Symfony/Component/Validator/ConstraintViolationListInterface.php index d96755c9a277e..bc7dc9ee46247 100644 --- a/src/Symfony/Component/Validator/ConstraintViolationListInterface.php +++ b/src/Symfony/Component/Validator/ConstraintViolationListInterface.php @@ -39,7 +39,7 @@ public function addAll(ConstraintViolationListInterface $otherList); * * @return ConstraintViolationInterface The violation * - * @throws \OutOfBoundsException If the offset does not exist. + * @throws \OutOfBoundsException if the offset does not exist */ public function get($offset); diff --git a/src/Symfony/Component/Validator/DefaultTranslator.php b/src/Symfony/Component/Validator/DefaultTranslator.php index 85853d8d858ce..15712d0d68e12 100644 --- a/src/Symfony/Component/Validator/DefaultTranslator.php +++ b/src/Symfony/Component/Validator/DefaultTranslator.php @@ -129,8 +129,8 @@ public function trans($id, array $parameters = array(), $domain = null, $locale * * @return string The translated string * - * @throws InvalidArgumentException If the message id does not have the format - * "singular|plural". + * @throws InvalidArgumentException if the message id does not have the format + * "singular|plural" */ public function transChoice($id, $number, array $parameters = array(), $domain = null, $locale = null) { diff --git a/src/Symfony/Component/Validator/ExecutionContextInterface.php b/src/Symfony/Component/Validator/ExecutionContextInterface.php index 075fecb0c520a..d887124e33c0f 100644 --- a/src/Symfony/Component/Validator/ExecutionContextInterface.php +++ b/src/Symfony/Component/Validator/ExecutionContextInterface.php @@ -150,10 +150,10 @@ public function addViolationAt($subPath, $message, array $parameters = array(), * @param null|string|string[] $groups The groups to validate in. If you don't pass any * groups here, the current group of the context * will be used. - * @param bool $traverse Whether to traverse the value if it is an array - * or an instance of \Traversable. - * @param bool $deep Whether to traverse the value recursively if - * it is a collection of collections. + * @param bool $traverse whether to traverse the value if it is an array + * or an instance of \Traversable + * @param bool $deep whether to traverse the value recursively if + * it is a collection of collections * * @deprecated since version 2.5, to be removed in 3.0. * Use {@link Context\ExecutionContextInterface::getValidator()} @@ -237,8 +237,8 @@ public function getValue(); * has been called with a plain value and constraint, this method returns * null. * - * @return MetadataInterface|null The metadata of the currently validated - * value. + * @return MetadataInterface|null the metadata of the currently validated + * value */ public function getMetadata(); diff --git a/src/Symfony/Component/Validator/Validation.php b/src/Symfony/Component/Validator/Validation.php index 94ed62c52559b..a469b47e25ea2 100644 --- a/src/Symfony/Component/Validator/Validation.php +++ b/src/Symfony/Component/Validator/Validation.php @@ -21,7 +21,7 @@ final class Validation /** * The Validator API provided by Symfony 2.4 and older. * - * @deprecated use API_VERSION_2_5_BC instead. + * @deprecated use API_VERSION_2_5_BC instead */ const API_VERSION_2_4 = 1; diff --git a/src/Symfony/Component/Validator/ValidationVisitorInterface.php b/src/Symfony/Component/Validator/ValidationVisitorInterface.php index b6c6e9f1cb9d3..28d492132b8a1 100644 --- a/src/Symfony/Component/Validator/ValidationVisitorInterface.php +++ b/src/Symfony/Component/Validator/ValidationVisitorInterface.php @@ -62,8 +62,8 @@ interface ValidationVisitorInterface * @param bool $traverse Whether to traverse the value if it is traversable * @param bool $deep Whether to traverse nested traversable values recursively * - * @throws Exception\NoSuchMetadataException If no metadata can be found for - * the given value. + * @throws Exception\NoSuchMetadataException if no metadata can be found for + * the given value */ public function validate($value, $group, $propertyPath, $traverse = false, $deep = false); diff --git a/src/Symfony/Component/Validator/Validator.php b/src/Symfony/Component/Validator/Validator.php index feaec0d400382..c69c7a86b7927 100644 --- a/src/Symfony/Component/Validator/Validator.php +++ b/src/Symfony/Component/Validator/Validator.php @@ -108,7 +108,7 @@ public function validate($value, $groups = null, $traverse = false, $deep = fals /** * {@inheritdoc} * - * @throws ValidatorException If the metadata for the value does not support properties. + * @throws ValidatorException if the metadata for the value does not support properties */ public function validateProperty($containingValue, $property, $groups = null) { @@ -139,7 +139,7 @@ public function validateProperty($containingValue, $property, $groups = null) /** * {@inheritdoc} * - * @throws ValidatorException If the metadata for the value does not support properties. + * @throws ValidatorException if the metadata for the value does not support properties */ public function validatePropertyValue($containingValue, $property, $value, $groups = null) { diff --git a/src/Symfony/Component/Validator/ValidatorInterface.php b/src/Symfony/Component/Validator/ValidatorInterface.php index 58b8cd6e4cbb7..fd7785b6ea24d 100644 --- a/src/Symfony/Component/Validator/ValidatorInterface.php +++ b/src/Symfony/Component/Validator/ValidatorInterface.php @@ -64,8 +64,8 @@ public function validateProperty($containingValue, $property, $groups = null); * * @param mixed $containingValue The value containing the property * @param string $property The name of the property to validate - * @param string $value The value to validate against the - * constraints of the property. + * @param string $value the value to validate against the + * constraints of the property * @param array|null $groups The validation groups to validate * * @return ConstraintViolationListInterface A list of constraint violations. If the From 10204ffe9950e1f809ca49f8e5a5967b07806aee Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Mon, 11 Sep 2017 13:58:17 -0700 Subject: [PATCH 0805/1099] [WebProfilerBundle] fixed TemplateManager when using Twig 2 without compat interfaces --- .../Bundle/WebProfilerBundle/Profiler/TemplateManager.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Bundle/WebProfilerBundle/Profiler/TemplateManager.php b/src/Symfony/Bundle/WebProfilerBundle/Profiler/TemplateManager.php index 5b6b9f100461a..91cd1fb837f28 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Profiler/TemplateManager.php +++ b/src/Symfony/Bundle/WebProfilerBundle/Profiler/TemplateManager.php @@ -126,7 +126,7 @@ protected function templateExists($template) } try { - if ($loader instanceof SourceContextLoaderInterface) { + if ($loader instanceof SourceContextLoaderInterface || method_exists($loader, 'getSourceContext')) { $loader->getSourceContext($template); } else { $loader->getSource($template); From df07e7336361642c1bba3bee94e69e6b4c45c325 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Mon, 11 Sep 2017 14:10:59 -0700 Subject: [PATCH 0806/1099] fixed CS --- .../Bundle/FrameworkBundle/Command/AssetsInstallCommand.php | 2 +- src/Symfony/Component/DependencyInjection/Definition.php | 2 +- src/Symfony/Component/Ldap/LdapClientInterface.php | 2 +- src/Symfony/Component/Translation/Loader/FileLoader.php | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/AssetsInstallCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/AssetsInstallCommand.php index c068713df6b2a..66f7f9ca8b468 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/AssetsInstallCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/AssetsInstallCommand.php @@ -222,7 +222,7 @@ private function absoluteSymlinkWithFallback($originDir, $targetDir) * @param string $targetDir * @param bool $relative * - * @throws IOException If link can not be created. + * @throws IOException if link can not be created */ private function symlink($originDir, $targetDir, $relative = false) { diff --git a/src/Symfony/Component/DependencyInjection/Definition.php b/src/Symfony/Component/DependencyInjection/Definition.php index 05d3c59cff5a5..d2d61d54828ac 100644 --- a/src/Symfony/Component/DependencyInjection/Definition.php +++ b/src/Symfony/Component/DependencyInjection/Definition.php @@ -777,7 +777,7 @@ public function isAbstract() * * @return $this * - * @throws InvalidArgumentException When the message template is invalid. + * @throws InvalidArgumentException when the message template is invalid */ public function setDeprecated($status = true, $template = null) { diff --git a/src/Symfony/Component/Ldap/LdapClientInterface.php b/src/Symfony/Component/Ldap/LdapClientInterface.php index dcdc0818da10b..aed445f3484bc 100644 --- a/src/Symfony/Component/Ldap/LdapClientInterface.php +++ b/src/Symfony/Component/Ldap/LdapClientInterface.php @@ -29,7 +29,7 @@ interface LdapClientInterface * @param string $dn A LDAP dn * @param string $password A password * - * @throws ConnectionException If dn / password could not be bound. + * @throws ConnectionException if dn / password could not be bound */ public function bind($dn = null, $password = null); diff --git a/src/Symfony/Component/Translation/Loader/FileLoader.php b/src/Symfony/Component/Translation/Loader/FileLoader.php index 1885963a99550..322679d24cdb8 100644 --- a/src/Symfony/Component/Translation/Loader/FileLoader.php +++ b/src/Symfony/Component/Translation/Loader/FileLoader.php @@ -59,7 +59,7 @@ public function load($resource, $locale, $domain = 'messages') * * @return array * - * @throws InvalidResourceException If stream content has an invalid format. + * @throws InvalidResourceException if stream content has an invalid format */ abstract protected function loadResource($resource); } From ceae3bf16c5243fc5d86d8d8c149d461cca70a0b Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Mon, 11 Sep 2017 14:23:01 -0700 Subject: [PATCH 0807/1099] fixed CS --- .../Bridge/Twig/Tests/Extension/WorkflowExtensionTest.php | 1 - src/Symfony/Bundle/SecurityBundle/Security/FirewallMap.php | 1 - src/Symfony/Component/Cache/Traits/RedisTrait.php | 2 +- src/Symfony/Component/Console/Command/Command.php | 2 +- src/Symfony/Component/Console/Tester/CommandTester.php | 4 ++-- .../DependencyInjection/Loader/DirectoryLoader.php | 2 -- .../Component/DependencyInjection/Loader/IniFileLoader.php | 1 - .../Component/DependencyInjection/Loader/PhpFileLoader.php | 2 -- .../Core/DataTransformer/DateIntervalToArrayTransformer.php | 6 +++--- .../DataTransformer/DateIntervalToStringTransformer.php | 6 +++--- src/Symfony/Component/Form/FormErrorIterator.php | 2 +- src/Symfony/Component/HttpFoundation/JsonResponse.php | 2 +- src/Symfony/Component/HttpKernel/HttpCache/HttpCache.php | 4 ++-- src/Symfony/Component/Ldap/LdapInterface.php | 2 +- src/Symfony/Component/Process/Tests/PhpProcessTest.php | 2 +- .../Component/Routing/Matcher/Dumper/PhpMatcherDumper.php | 2 +- .../Routing/Matcher/Dumper/StaticPrefixCollection.php | 2 +- .../Component/Security/Http/Logout/LogoutUrlGenerator.php | 2 +- src/Symfony/Component/Validator/ConstraintViolationList.php | 2 +- .../Validator/Context/ExecutionContextInterface.php | 4 ++-- src/Symfony/Component/VarDumper/Cloner/Data.php | 6 +++--- .../Component/WebLink/Tests/HttpHeaderSerializerTest.php | 1 - 22 files changed, 25 insertions(+), 33 deletions(-) diff --git a/src/Symfony/Bridge/Twig/Tests/Extension/WorkflowExtensionTest.php b/src/Symfony/Bridge/Twig/Tests/Extension/WorkflowExtensionTest.php index e134434c9b4e7..60934c1c2df84 100644 --- a/src/Symfony/Bridge/Twig/Tests/Extension/WorkflowExtensionTest.php +++ b/src/Symfony/Bridge/Twig/Tests/Extension/WorkflowExtensionTest.php @@ -14,7 +14,6 @@ use PHPUnit\Framework\TestCase; use Symfony\Bridge\Twig\Extension\WorkflowExtension; use Symfony\Component\Workflow\Definition; -use Symfony\Component\Workflow\Marking; use Symfony\Component\Workflow\Registry; use Symfony\Component\Workflow\SupportStrategy\ClassInstanceSupportStrategy; use Symfony\Component\Workflow\Transition; diff --git a/src/Symfony/Bundle/SecurityBundle/Security/FirewallMap.php b/src/Symfony/Bundle/SecurityBundle/Security/FirewallMap.php index af31a0fb60026..3af674d652c9a 100644 --- a/src/Symfony/Bundle/SecurityBundle/Security/FirewallMap.php +++ b/src/Symfony/Bundle/SecurityBundle/Security/FirewallMap.php @@ -12,7 +12,6 @@ namespace Symfony\Bundle\SecurityBundle\Security; use Psr\Container\ContainerInterface; -use Symfony\Bundle\SecurityBundle\Security\FirewallContext; use Symfony\Component\Security\Http\FirewallMapInterface; use Symfony\Component\HttpFoundation\Request; diff --git a/src/Symfony/Component/Cache/Traits/RedisTrait.php b/src/Symfony/Component/Cache/Traits/RedisTrait.php index 6202051a8de5d..467e602070c7a 100644 --- a/src/Symfony/Component/Cache/Traits/RedisTrait.php +++ b/src/Symfony/Component/Cache/Traits/RedisTrait.php @@ -67,7 +67,7 @@ public function init($redisClient, $namespace = '', $defaultLifetime = 0) * @param string $dsn * @param array $options See self::$defaultConnectionOptions * - * @throws InvalidArgumentException When the DSN is invalid. + * @throws InvalidArgumentException when the DSN is invalid * * @return \Redis|\Predis\Client According to the "class" option */ diff --git a/src/Symfony/Component/Console/Command/Command.php b/src/Symfony/Component/Console/Command/Command.php index 08a74c3b69a9a..915102175ea21 100644 --- a/src/Symfony/Component/Console/Command/Command.php +++ b/src/Symfony/Component/Console/Command/Command.php @@ -475,7 +475,7 @@ public function setHidden($hidden) } /** - * @return bool Whether the command should be publicly shown or not. + * @return bool whether the command should be publicly shown or not */ public function isHidden() { diff --git a/src/Symfony/Component/Console/Tester/CommandTester.php b/src/Symfony/Component/Console/Tester/CommandTester.php index 0bb1603c33c6f..143c269b17034 100644 --- a/src/Symfony/Component/Console/Tester/CommandTester.php +++ b/src/Symfony/Component/Console/Tester/CommandTester.php @@ -137,8 +137,8 @@ public function getStatusCode() /** * Sets the user inputs. * - * @param array An array of strings representing each input - * passed to the command input stream. + * @param array an array of strings representing each input + * passed to the command input stream * * @return CommandTester */ diff --git a/src/Symfony/Component/DependencyInjection/Loader/DirectoryLoader.php b/src/Symfony/Component/DependencyInjection/Loader/DirectoryLoader.php index 3ab4c5dc82e7e..769f1026e8d98 100644 --- a/src/Symfony/Component/DependencyInjection/Loader/DirectoryLoader.php +++ b/src/Symfony/Component/DependencyInjection/Loader/DirectoryLoader.php @@ -11,8 +11,6 @@ namespace Symfony\Component\DependencyInjection\Loader; -use Symfony\Component\Config\Resource\DirectoryResource; - /** * DirectoryLoader is a recursive loader to go through directories. * diff --git a/src/Symfony/Component/DependencyInjection/Loader/IniFileLoader.php b/src/Symfony/Component/DependencyInjection/Loader/IniFileLoader.php index 170e726396a5e..6cc9a1acaf256 100644 --- a/src/Symfony/Component/DependencyInjection/Loader/IniFileLoader.php +++ b/src/Symfony/Component/DependencyInjection/Loader/IniFileLoader.php @@ -11,7 +11,6 @@ namespace Symfony\Component\DependencyInjection\Loader; -use Symfony\Component\Config\Resource\FileResource; use Symfony\Component\Config\Util\XmlUtils; use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; diff --git a/src/Symfony/Component/DependencyInjection/Loader/PhpFileLoader.php b/src/Symfony/Component/DependencyInjection/Loader/PhpFileLoader.php index 36ef0d4752bc9..9d887e4af03f6 100644 --- a/src/Symfony/Component/DependencyInjection/Loader/PhpFileLoader.php +++ b/src/Symfony/Component/DependencyInjection/Loader/PhpFileLoader.php @@ -11,8 +11,6 @@ namespace Symfony\Component\DependencyInjection\Loader; -use Symfony\Component\Config\Resource\FileResource; - /** * PhpFileLoader loads service definitions from a PHP file. * diff --git a/src/Symfony/Component/Form/Extension/Core/DataTransformer/DateIntervalToArrayTransformer.php b/src/Symfony/Component/Form/Extension/Core/DataTransformer/DateIntervalToArrayTransformer.php index a766760a12213..3e299ba994acf 100644 --- a/src/Symfony/Component/Form/Extension/Core/DataTransformer/DateIntervalToArrayTransformer.php +++ b/src/Symfony/Component/Form/Extension/Core/DataTransformer/DateIntervalToArrayTransformer.php @@ -62,7 +62,7 @@ public function __construct(array $fields = null, $pad = false) * * @return array Interval array * - * @throws UnexpectedTypeException If the given value is not a \DateInterval instance. + * @throws UnexpectedTypeException if the given value is not a \DateInterval instance */ public function transform($dateInterval) { @@ -108,8 +108,8 @@ public function transform($dateInterval) * * @return \DateInterval Normalized date interval * - * @throws UnexpectedTypeException If the given value is not an array. - * @throws TransformationFailedException If the value could not be transformed. + * @throws UnexpectedTypeException if the given value is not an array + * @throws TransformationFailedException if the value could not be transformed */ public function reverseTransform($value) { diff --git a/src/Symfony/Component/Form/Extension/Core/DataTransformer/DateIntervalToStringTransformer.php b/src/Symfony/Component/Form/Extension/Core/DataTransformer/DateIntervalToStringTransformer.php index 7b9cca0fbd151..dffe146623772 100644 --- a/src/Symfony/Component/Form/Extension/Core/DataTransformer/DateIntervalToStringTransformer.php +++ b/src/Symfony/Component/Form/Extension/Core/DataTransformer/DateIntervalToStringTransformer.php @@ -46,7 +46,7 @@ public function __construct($format = 'P%yY%mM%dDT%hH%iM%sS', $parseSigned = fal * * @return string An ISO 8601 or relative date string like date interval presentation * - * @throws UnexpectedTypeException If the given value is not a \DateInterval instance. + * @throws UnexpectedTypeException if the given value is not a \DateInterval instance */ public function transform($value) { @@ -67,8 +67,8 @@ public function transform($value) * * @return \DateInterval An instance of \DateInterval * - * @throws UnexpectedTypeException If the given value is not a string. - * @throws TransformationFailedException If the date interval could not be parsed. + * @throws UnexpectedTypeException if the given value is not a string + * @throws TransformationFailedException if the date interval could not be parsed */ public function reverseTransform($value) { diff --git a/src/Symfony/Component/Form/FormErrorIterator.php b/src/Symfony/Component/Form/FormErrorIterator.php index 1aca7fb84a3f0..13dac154fa73a 100644 --- a/src/Symfony/Component/Form/FormErrorIterator.php +++ b/src/Symfony/Component/Form/FormErrorIterator.php @@ -271,7 +271,7 @@ public function seek($position) * * @param string|string[] $codes The codes to find * - * @return static New instance which contains only specific errors. + * @return static new instance which contains only specific errors */ public function findByCodes($codes) { diff --git a/src/Symfony/Component/HttpFoundation/JsonResponse.php b/src/Symfony/Component/HttpFoundation/JsonResponse.php index 547a8e4876806..137ac33c46ed0 100644 --- a/src/Symfony/Component/HttpFoundation/JsonResponse.php +++ b/src/Symfony/Component/HttpFoundation/JsonResponse.php @@ -150,7 +150,7 @@ public function setData($data = array()) try { $data = @json_encode($data, $this->encodingOptions); } finally { - restore_error_handler(); + restore_error_handler(); } } else { try { diff --git a/src/Symfony/Component/HttpKernel/HttpCache/HttpCache.php b/src/Symfony/Component/HttpKernel/HttpCache/HttpCache.php index be2bc63dda6de..c9c06597f99d1 100644 --- a/src/Symfony/Component/HttpKernel/HttpCache/HttpCache.php +++ b/src/Symfony/Component/HttpKernel/HttpCache/HttpCache.php @@ -704,7 +704,7 @@ private function getTraceKey(Request $request) * * @param Response $entry * - * @return bool True when the stale response may be served, false otherwise. + * @return bool true when the stale response may be served, false otherwise */ private function mayServeStaleWhileRevalidate(Response $entry) { @@ -722,7 +722,7 @@ private function mayServeStaleWhileRevalidate(Response $entry) * * @param Request $request The request to wait for * - * @return bool True if the lock was released before the internal timeout was hit; false if the wait timeout was exceeded. + * @return bool true if the lock was released before the internal timeout was hit; false if the wait timeout was exceeded */ private function waitForLock(Request $request) { diff --git a/src/Symfony/Component/Ldap/LdapInterface.php b/src/Symfony/Component/Ldap/LdapInterface.php index f71f7e04f81a3..9f24276d61a20 100644 --- a/src/Symfony/Component/Ldap/LdapInterface.php +++ b/src/Symfony/Component/Ldap/LdapInterface.php @@ -31,7 +31,7 @@ interface LdapInterface * @param string $dn A LDAP dn * @param string $password A password * - * @throws ConnectionException If dn / password could not be bound. + * @throws ConnectionException if dn / password could not be bound */ public function bind($dn = null, $password = null); diff --git a/src/Symfony/Component/Process/Tests/PhpProcessTest.php b/src/Symfony/Component/Process/Tests/PhpProcessTest.php index 988cd091598ce..f67368c7b358a 100644 --- a/src/Symfony/Component/Process/Tests/PhpProcessTest.php +++ b/src/Symfony/Component/Process/Tests/PhpProcessTest.php @@ -43,6 +43,6 @@ public function testCommandLine() $process->wait(); $this->assertContains($commandLine, $process->getCommandLine(), '::getCommandLine() returns the command line of PHP after wait'); - $this->assertSame(phpversion().PHP_SAPI, $process->getOutput()); + $this->assertSame(PHP_VERSION.PHP_SAPI, $process->getOutput()); } } diff --git a/src/Symfony/Component/Routing/Matcher/Dumper/PhpMatcherDumper.php b/src/Symfony/Component/Routing/Matcher/Dumper/PhpMatcherDumper.php index 1397bac448d4d..5e1d30fb571e2 100644 --- a/src/Symfony/Component/Routing/Matcher/Dumper/PhpMatcherDumper.php +++ b/src/Symfony/Component/Routing/Matcher/Dumper/PhpMatcherDumper.php @@ -182,7 +182,7 @@ private function buildStaticPrefixCollection(DumperCollection $collection) * * @param StaticPrefixCollection $collection A StaticPrefixCollection instance * @param bool $supportsRedirections Whether redirections are supported by the base class - * @param string $ifOrElseIf Either "if" or "elseif" to influence chaining. + * @param string $ifOrElseIf either "if" or "elseif" to influence chaining * * @return string PHP code */ diff --git a/src/Symfony/Component/Routing/Matcher/Dumper/StaticPrefixCollection.php b/src/Symfony/Component/Routing/Matcher/Dumper/StaticPrefixCollection.php index b2bfa343764cc..b4518fdc8f897 100644 --- a/src/Symfony/Component/Routing/Matcher/Dumper/StaticPrefixCollection.php +++ b/src/Symfony/Component/Routing/Matcher/Dumper/StaticPrefixCollection.php @@ -225,7 +225,7 @@ private function shouldBeInlined() * * @param string $prefix * - * @throws \LogicException When a prefix does not belong in a group. + * @throws \LogicException when a prefix does not belong in a group */ private function guardAgainstAddingNotAcceptedRoutes($prefix) { diff --git a/src/Symfony/Component/Security/Http/Logout/LogoutUrlGenerator.php b/src/Symfony/Component/Security/Http/Logout/LogoutUrlGenerator.php index 3f2def8d735cc..11f492b59b081 100644 --- a/src/Symfony/Component/Security/Http/Logout/LogoutUrlGenerator.php +++ b/src/Symfony/Component/Security/Http/Logout/LogoutUrlGenerator.php @@ -145,7 +145,7 @@ private function generateLogoutUrl($key, $referenceType) * * @return array The logout listener found * - * @throws \InvalidArgumentException if no LogoutListener is registered for the key or could not be found automatically. + * @throws \InvalidArgumentException if no LogoutListener is registered for the key or could not be found automatically */ private function getListener($key) { diff --git a/src/Symfony/Component/Validator/ConstraintViolationList.php b/src/Symfony/Component/Validator/ConstraintViolationList.php index f2da581e4efb0..a80d602b26fd9 100644 --- a/src/Symfony/Component/Validator/ConstraintViolationList.php +++ b/src/Symfony/Component/Validator/ConstraintViolationList.php @@ -164,7 +164,7 @@ public function offsetUnset($offset) * * @param string|string[] $codes The codes to find * - * @return static New instance which contains only specific errors. + * @return static new instance which contains only specific errors */ public function findByCodes($codes) { diff --git a/src/Symfony/Component/Validator/Context/ExecutionContextInterface.php b/src/Symfony/Component/Validator/Context/ExecutionContextInterface.php index 1b1452582dff4..fa0053bb420dd 100644 --- a/src/Symfony/Component/Validator/Context/ExecutionContextInterface.php +++ b/src/Symfony/Component/Validator/Context/ExecutionContextInterface.php @@ -275,8 +275,8 @@ public function getValue(); * has been called with a plain value and constraint, this method returns * null. * - * @return MetadataInterface|null The metadata of the currently validated - * value. + * @return MetadataInterface|null the metadata of the currently validated + * value */ public function getMetadata(); diff --git a/src/Symfony/Component/VarDumper/Cloner/Data.php b/src/Symfony/Component/VarDumper/Cloner/Data.php index 3de76cdc7da42..a6630558c58cd 100644 --- a/src/Symfony/Component/VarDumper/Cloner/Data.php +++ b/src/Symfony/Component/VarDumper/Cloner/Data.php @@ -34,7 +34,7 @@ public function __construct(array $data) } /** - * @return string The type of the value. + * @return string the type of the value */ public function getType() { @@ -61,9 +61,9 @@ public function getType() } /** - * @param bool $recursive Whether values should be resolved recursively or not. + * @param bool $recursive whether values should be resolved recursively or not * - * @return scalar|array|null|Data[] A native representation of the original value. + * @return scalar|array|null|Data[] a native representation of the original value */ public function getValue($recursive = false) { diff --git a/src/Symfony/Component/WebLink/Tests/HttpHeaderSerializerTest.php b/src/Symfony/Component/WebLink/Tests/HttpHeaderSerializerTest.php index c5d0716ef96f5..553371fbb414e 100644 --- a/src/Symfony/Component/WebLink/Tests/HttpHeaderSerializerTest.php +++ b/src/Symfony/Component/WebLink/Tests/HttpHeaderSerializerTest.php @@ -11,7 +11,6 @@ namespace Symfony\Component\WebLink\Tests; -use Fig\Link\GenericLinkProvider; use Fig\Link\Link; use PHPUnit\Framework\TestCase; use Symfony\Component\WebLink\HttpHeaderSerializer; From 7ab8efb74ecd422ed627753971637bd7d8dc92ca Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Mon, 11 Sep 2017 14:34:45 -0700 Subject: [PATCH 0808/1099] fixed CS --- src/Symfony/Component/Debug/Tests/Fixtures/InternalTrait2.php | 2 +- src/Symfony/Component/HttpFoundation/Response.php | 4 ++-- src/Symfony/Component/Lock/Key.php | 2 +- src/Symfony/Component/Lock/LockInterface.php | 2 +- src/Symfony/Component/Lock/Store/SemaphoreStore.php | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Symfony/Component/Debug/Tests/Fixtures/InternalTrait2.php b/src/Symfony/Component/Debug/Tests/Fixtures/InternalTrait2.php index 73df6d5acf250..05f18e83e4a9e 100644 --- a/src/Symfony/Component/Debug/Tests/Fixtures/InternalTrait2.php +++ b/src/Symfony/Component/Debug/Tests/Fixtures/InternalTrait2.php @@ -15,7 +15,7 @@ public function internalMethod() } /** - * @internal but should not trigger a deprecation. + * @internal but should not trigger a deprecation */ public function usedInInternalClass() { diff --git a/src/Symfony/Component/HttpFoundation/Response.php b/src/Symfony/Component/HttpFoundation/Response.php index 15fa56a6b8f1f..359143f33d77a 100644 --- a/src/Symfony/Component/HttpFoundation/Response.php +++ b/src/Symfony/Component/HttpFoundation/Response.php @@ -613,7 +613,7 @@ public function setPublic() /** * Marks the response as "immutable". * - * @param bool $immutable Enables or disables the immutable directive. + * @param bool $immutable enables or disables the immutable directive * * @return $this */ @@ -631,7 +631,7 @@ public function setImmutable($immutable = true) /** * Returns true if the response is marked as "immutable". * - * @return bool Returns true if the response is marked as "immutable"; otherwise false. + * @return bool returns true if the response is marked as "immutable"; otherwise false */ public function isImmutable() { diff --git a/src/Symfony/Component/Lock/Key.php b/src/Symfony/Component/Lock/Key.php index 1f5a7de740ef9..8be4f3a255975 100644 --- a/src/Symfony/Component/Lock/Key.php +++ b/src/Symfony/Component/Lock/Key.php @@ -78,7 +78,7 @@ public function resetLifetime() } /** - * @param float $ttl The expiration delay of locks in seconds. + * @param float $ttl the expiration delay of locks in seconds */ public function reduceLifetime($ttl) { diff --git a/src/Symfony/Component/Lock/LockInterface.php b/src/Symfony/Component/Lock/LockInterface.php index ab05d7a8f4ab1..437a4cc2770c8 100644 --- a/src/Symfony/Component/Lock/LockInterface.php +++ b/src/Symfony/Component/Lock/LockInterface.php @@ -28,7 +28,7 @@ interface LockInterface * * @param bool $blocking Whether or not the Lock should wait for the release of someone else * - * @return bool Whether or not the lock had been acquired. + * @return bool whether or not the lock had been acquired * * @throws LockConflictedException If the lock is acquired by someone else in blocking mode * @throws LockAcquiringException If the lock can not be acquired diff --git a/src/Symfony/Component/Lock/Store/SemaphoreStore.php b/src/Symfony/Component/Lock/Store/SemaphoreStore.php index 64123e8a51e2b..73a1776827a81 100644 --- a/src/Symfony/Component/Lock/Store/SemaphoreStore.php +++ b/src/Symfony/Component/Lock/Store/SemaphoreStore.php @@ -27,7 +27,7 @@ class SemaphoreStore implements StoreInterface /** * Returns whether or not the store is supported. * - * @param bool|null $blocking When not null, checked again the blocking mode. + * @param bool|null $blocking when not null, checked again the blocking mode * * @return bool * From 97ac19c666e0c22bd5bb7a71f23bf3f07b080f07 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Mon, 11 Sep 2017 14:45:47 -0700 Subject: [PATCH 0809/1099] fixed CS --- .../Component/Console/Helper/SymfonyQuestionHelper.php | 2 -- src/Symfony/Component/Form/FormInterface.php | 2 +- .../Component/VarDumper/Tests/Caster/DateCasterTest.php | 4 ++-- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/src/Symfony/Component/Console/Helper/SymfonyQuestionHelper.php b/src/Symfony/Component/Console/Helper/SymfonyQuestionHelper.php index a63225149297d..79016b9f2d90b 100644 --- a/src/Symfony/Component/Console/Helper/SymfonyQuestionHelper.php +++ b/src/Symfony/Component/Console/Helper/SymfonyQuestionHelper.php @@ -11,8 +11,6 @@ namespace Symfony\Component\Console\Helper; -use Symfony\Component\Console\Exception\LogicException; -use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Question\ChoiceQuestion; use Symfony\Component\Console\Question\ConfirmationQuestion; diff --git a/src/Symfony/Component/Form/FormInterface.php b/src/Symfony/Component/Form/FormInterface.php index f4033f60658b4..9897dbe35f998 100644 --- a/src/Symfony/Component/Form/FormInterface.php +++ b/src/Symfony/Component/Form/FormInterface.php @@ -189,7 +189,7 @@ public function addError(FormError $error); /** * Returns whether the form and all children are valid. * - * @throws Exception\LogicException If the form is not submitted. + * @throws Exception\LogicException if the form is not submitted * * @return bool */ diff --git a/src/Symfony/Component/VarDumper/Tests/Caster/DateCasterTest.php b/src/Symfony/Component/VarDumper/Tests/Caster/DateCasterTest.php index 0298c8b3cb5a9..e6a98f993602d 100644 --- a/src/Symfony/Component/VarDumper/Tests/Caster/DateCasterTest.php +++ b/src/Symfony/Component/VarDumper/Tests/Caster/DateCasterTest.php @@ -353,8 +353,8 @@ public function providePeriods() array('2017-01-01 01:00:00', 'P1D', '2017-01-03 01:00:00', 0, 'every + 1d, from 2017-01-01 01:00:00.0 (included) to 2017-01-03 01:00:00.0', '1) 2017-01-01 01:00:00.0%a2) 2017-01-02 01:00:00.0'), array('2017-01-01 01:00:00', 'P1D', 1, 0, 'every + 1d, from 2017-01-01 01:00:00.0 (included) recurring 2 time/s', '1) 2017-01-01 01:00:00.0%a2) 2017-01-02 01:00:00.0'), - array('2017-01-01', 'P1DT1H', '2017-01-03', 0, "every + 1d 01:00:00.0, from 2017-01-01 00:00:00.0 (included) to 2017-01-03 00:00:00.0", '1) 2017-01-01 00:00:00.0%a2) 2017-01-02 01:00:00.0'), - array('2017-01-01', 'P1DT1H', 1, 0, "every + 1d 01:00:00.0, from 2017-01-01 00:00:00.0 (included) recurring 2 time/s", '1) 2017-01-01 00:00:00.0%a2) 2017-01-02 01:00:00.0'), + array('2017-01-01', 'P1DT1H', '2017-01-03', 0, 'every + 1d 01:00:00.0, from 2017-01-01 00:00:00.0 (included) to 2017-01-03 00:00:00.0', '1) 2017-01-01 00:00:00.0%a2) 2017-01-02 01:00:00.0'), + array('2017-01-01', 'P1DT1H', 1, 0, 'every + 1d 01:00:00.0, from 2017-01-01 00:00:00.0 (included) recurring 2 time/s', '1) 2017-01-01 00:00:00.0%a2) 2017-01-02 01:00:00.0'), array('2017-01-01', 'P1D', '2017-01-04', \DatePeriod::EXCLUDE_START_DATE, 'every + 1d, from 2017-01-01 00:00:00.0 (excluded) to 2017-01-04 00:00:00.0', '1) 2017-01-02%a2) 2017-01-03'), array('2017-01-01', 'P1D', 2, \DatePeriod::EXCLUDE_START_DATE, 'every + 1d, from 2017-01-01 00:00:00.0 (excluded) recurring 2 time/s', '1) 2017-01-02%a2) 2017-01-03'), From 4ea681e7d1d1ce7f15fcfdb14a004ad40d271acf Mon Sep 17 00:00:00 2001 From: Dariusz Date: Tue, 12 Sep 2017 00:23:36 +0200 Subject: [PATCH 0810/1099] .php_cs.dist - simplify config --- .php_cs.dist | 3 --- 1 file changed, 3 deletions(-) diff --git a/.php_cs.dist b/.php_cs.dist index 25f1f4c931bdc..d84a0624bd3c5 100644 --- a/.php_cs.dist +++ b/.php_cs.dist @@ -9,9 +9,6 @@ return PhpCsFixer\Config::create() '@Symfony' => true, '@Symfony:risky' => true, 'array_syntax' => array('syntax' => 'long'), - 'no_unreachable_default_argument_value' => false, - 'braces' => array('allow_single_line_closure' => true), - 'heredoc_to_nowdoc' => false, )) ->setRiskyAllowed(true) ->setFinder( From 75a26bb80151d22f8922a502cc283473cee01519 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Tue, 12 Sep 2017 10:02:51 +0200 Subject: [PATCH 0811/1099] [Debug] fix test assertion --- src/Symfony/Component/Debug/Tests/DebugClassLoaderTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/Debug/Tests/DebugClassLoaderTest.php b/src/Symfony/Component/Debug/Tests/DebugClassLoaderTest.php index 71dcfd9b835e3..babf36d2bd053 100644 --- a/src/Symfony/Component/Debug/Tests/DebugClassLoaderTest.php +++ b/src/Symfony/Component/Debug/Tests/DebugClassLoaderTest.php @@ -204,7 +204,7 @@ class_exists('Test\\'.__NAMESPACE__.'\\'.$class, true); $xError = array( 'type' => E_USER_DEPRECATED, - 'message' => 'The "Test\Symfony\Component\Debug\Tests\\'.$class.'" class '.$type.' "Symfony\Component\Debug\Tests\Fixtures\\'.$super.'" that is deprecated but this is a test deprecation notice', + 'message' => 'The "Test\Symfony\Component\Debug\Tests\\'.$class.'" class '.$type.' "Symfony\Component\Debug\Tests\Fixtures\\'.$super.'" that is deprecated but this is a test deprecation notice.', ); $this->assertSame($xError, $lastError); From 42183b02133003047724b0a9d93fa2112235272c Mon Sep 17 00:00:00 2001 From: Abdellatif Ait boudad Date: Sun, 18 Sep 2016 09:17:44 +0100 Subject: [PATCH 0812/1099] [Translation] Support adding custom message formatter --- UPGRADE-3.4.md | 21 +++++ UPGRADE-4.0.md | 3 + .../Extension/TranslationExtensionTest.php | 9 +- .../DependencyInjection/Configuration.php | 1 + .../FrameworkExtension.php | 1 + .../Resources/config/schema/symfony-1.0.xsd | 1 + .../Resources/config/translation.xml | 6 +- .../DependencyInjection/ConfigurationTest.php | 1 + .../Tests/Translation/TranslatorTest.php | 14 ++-- .../Translation/Translator.php | 16 ++-- .../Component/Translation/CHANGELOG.md | 1 + .../ChoiceMessageFormatterInterface.php | 30 +++++++ .../Formatter/MessageFormatter.php | 48 +++++++++++ .../Formatter/MessageFormatterInterface.php | 30 +++++++ .../Tests/Formatter/MessageFormatterTest.php | 82 +++++++++++++++++++ .../Translation/Tests/TranslatorTest.php | 29 ++++--- .../Component/Translation/Translator.php | 38 ++++++--- 17 files changed, 282 insertions(+), 49 deletions(-) create mode 100644 src/Symfony/Component/Translation/Formatter/ChoiceMessageFormatterInterface.php create mode 100644 src/Symfony/Component/Translation/Formatter/MessageFormatter.php create mode 100644 src/Symfony/Component/Translation/Formatter/MessageFormatterInterface.php create mode 100644 src/Symfony/Component/Translation/Tests/Formatter/MessageFormatterTest.php diff --git a/UPGRADE-3.4.md b/UPGRADE-3.4.md index 20114937efc26..9a3a74dd61655 100644 --- a/UPGRADE-3.4.md +++ b/UPGRADE-3.4.md @@ -234,6 +234,27 @@ Translation and will be removed in 4.0, use `Symfony\Component\Translation\Writer\TranslationWriter::write` instead. + * Passing a `Symfony\Component\Translation\MessageSelector` to `Translator` has been + deprecated. You should pass a message formatter instead + + Before: + + ```php + use Symfony\Component\Translation\Translator; + use Symfony\Component\Translation\MessageSelector; + + $translator = new Translator('fr_FR', new MessageSelector()); + ``` + + After: + + ```php + use Symfony\Component\Translation\Translator; + use Symfony\Component\Translation\Formatter\MessageFormatter; + + $translator = new Translator('fr_FR', new MessageFormatter()); + ``` + TwigBridge ---------- diff --git a/UPGRADE-4.0.md b/UPGRADE-4.0.md index 5d404598f7ec0..9dffe96789b90 100644 --- a/UPGRADE-4.0.md +++ b/UPGRADE-4.0.md @@ -643,6 +643,9 @@ Translation * Removed `Symfony\Component\Translation\Writer\TranslationWriter::writeTranslations`, use `Symfony\Component\Translation\Writer\TranslationWriter::write` instead. + * Removed support for passing `Symfony\Component\Translation\MessageSelector` as a second argument to the + `Translator::__construct()`. You should pass an instance of `Symfony\Component\Translation\Formatter\MessageFormatterInterface` instead. + TwigBundle ---------- diff --git a/src/Symfony/Bridge/Twig/Tests/Extension/TranslationExtensionTest.php b/src/Symfony/Bridge/Twig/Tests/Extension/TranslationExtensionTest.php index 36016d7f49bca..b20e0c3905a3a 100644 --- a/src/Symfony/Bridge/Twig/Tests/Extension/TranslationExtensionTest.php +++ b/src/Symfony/Bridge/Twig/Tests/Extension/TranslationExtensionTest.php @@ -14,7 +14,6 @@ use PHPUnit\Framework\TestCase; use Symfony\Bridge\Twig\Extension\TranslationExtension; use Symfony\Component\Translation\Translator; -use Symfony\Component\Translation\MessageSelector; use Symfony\Component\Translation\Loader\ArrayLoader; use Twig\Environment; use Twig\Loader\ArrayLoader as TwigArrayLoader; @@ -37,7 +36,7 @@ public function testTrans($template, $expected, array $variables = array()) echo $template."\n"; $loader = new TwigArrayLoader(array('index' => $template)); $twig = new Environment($loader, array('debug' => true, 'cache' => false)); - $twig->addExtension(new TranslationExtension(new Translator('en', new MessageSelector()))); + $twig->addExtension(new TranslationExtension(new Translator('en'))); echo $twig->compile($twig->parse($twig->tokenize($twig->getLoader()->getSourceContext('index'))))."\n\n"; $this->assertEquals($expected, $this->getTemplate($template)->render($variables)); @@ -139,7 +138,7 @@ public function testDefaultTranslationDomain() ', ); - $translator = new Translator('en', new MessageSelector()); + $translator = new Translator('en'); $translator->addLoader('array', new ArrayLoader()); $translator->addResource('array', array('foo' => 'foo (messages)'), 'en'); $translator->addResource('array', array('foo' => 'foo (custom)'), 'en', 'custom'); @@ -172,7 +171,7 @@ public function testDefaultTranslationDomainWithNamedArguments() ', ); - $translator = new Translator('en', new MessageSelector()); + $translator = new Translator('en'); $translator->addLoader('array', new ArrayLoader()); $translator->addResource('array', array('foo' => 'foo (messages)'), 'en'); $translator->addResource('array', array('foo' => 'foo (custom)'), 'en', 'custom'); @@ -187,7 +186,7 @@ public function testDefaultTranslationDomainWithNamedArguments() protected function getTemplate($template, $translator = null) { if (null === $translator) { - $translator = new Translator('en', new MessageSelector()); + $translator = new Translator('en'); } if (is_array($template)) { diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php index a9c5ec462dcd2..2fce9b2ad4aed 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php @@ -668,6 +668,7 @@ private function addTranslatorSection(ArrayNodeDefinition $rootNode) ->defaultValue(array('en')) ->end() ->booleanNode('logging')->defaultValue($this->debug)->end() + ->scalarNode('formatter')->defaultValue('translator.formatter.default')->end() ->arrayNode('paths') ->prototype('scalar')->end() ->end() diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php index 72d66442c62c9..9b3a071168a51 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php @@ -1075,6 +1075,7 @@ private function registerTranslatorConfiguration(array $config, ContainerBuilder // Use the "real" translator instead of the identity default $container->setAlias('translator', 'translator.default'); + $container->setAlias('translator.formatter', new Alias($config['formatter'], false)); $translator = $container->findDefinition('translator.default'); $translator->addMethodCall('setFallbackLocales', array($config['fallbacks'])); 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 481c469e36164..f63f93723029d 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 @@ -184,6 +184,7 @@ + diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/translation.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/translation.xml index cfe05f5148fdd..d8c8f1e030111 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/translation.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/translation.xml @@ -9,7 +9,7 @@ - + %kernel.default_locale% @@ -28,6 +28,10 @@ + + + + diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/ConfigurationTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/ConfigurationTest.php index 1835625da8611..e4e6f0f2a7bea 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/ConfigurationTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/ConfigurationTest.php @@ -255,6 +255,7 @@ protected static function getBundleDefaultConfig() 'enabled' => !class_exists(FullStack::class), 'fallbacks' => array('en'), 'logging' => true, + 'formatter' => 'translator.formatter.default', 'paths' => array(), ), 'validation' => array( diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Translation/TranslatorTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Translation/TranslatorTest.php index 6d710a76e8819..d2d0f878f642f 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Translation/TranslatorTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Translation/TranslatorTest.php @@ -14,9 +14,9 @@ use PHPUnit\Framework\TestCase; use Psr\Container\ContainerInterface; use Symfony\Bundle\FrameworkBundle\Translation\Translator; +use Symfony\Component\Translation\Formatter\MessageFormatter; use Symfony\Component\Translation\MessageCatalogue; use Symfony\Component\Filesystem\Filesystem; -use Symfony\Component\Translation\MessageSelector; class TranslatorTest extends TestCase { @@ -149,7 +149,7 @@ public function testGetDefaultLocaleOmittingLocale() ->with('kernel.default_locale') ->will($this->returnValue('en')) ; - $translator = new Translator($container, new MessageSelector()); + $translator = new Translator($container, new MessageFormatter()); $this->assertSame('en', $translator->getLocale()); } @@ -162,7 +162,7 @@ public function testGetDefaultLocaleOmittingLocale() public function testGetDefaultLocaleOmittingLocaleWithPsrContainer() { $container = $this->getMockBuilder(ContainerInterface::class)->getMock(); - $translator = new Translator($container, new MessageSelector()); + $translator = new Translator($container, new MessageFormatter()); } /** @@ -277,7 +277,7 @@ public function testLoadResourcesWithoutCaching() public function testGetDefaultLocale() { $container = $this->getMockBuilder(ContainerInterface::class)->getMock(); - $translator = new Translator($container, new MessageSelector(), 'en'); + $translator = new Translator($container, new MessageFormatter(), 'en'); $this->assertSame('en', $translator->getLocale()); } @@ -290,7 +290,7 @@ public function testInvalidOptions() { $container = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerInterface')->getMock(); - (new Translator($container, new MessageSelector(), 'en', array(), array('foo' => 'bar'))); + (new Translator($container, new MessageFormatter(), 'en', array(), array('foo' => 'bar'))); } /** @dataProvider getDebugModeAndCacheDirCombinations */ @@ -468,7 +468,7 @@ private function createTranslator($loader, $options, $translatorClass = '\Symfon if (null === $defaultLocale) { return new $translatorClass( $this->getContainer($loader), - new MessageSelector(), + new MessageFormatter(), array($loaderFomat => array($loaderFomat)), $options ); @@ -476,7 +476,7 @@ private function createTranslator($loader, $options, $translatorClass = '\Symfon return new $translatorClass( $this->getContainer($loader), - new MessageSelector(), + new MessageFormatter(), $defaultLocale, array($loaderFomat => array($loaderFomat)), $options diff --git a/src/Symfony/Bundle/FrameworkBundle/Translation/Translator.php b/src/Symfony/Bundle/FrameworkBundle/Translation/Translator.php index d18a3b81f04ef..2b41d5af61dbd 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Translation/Translator.php +++ b/src/Symfony/Bundle/FrameworkBundle/Translation/Translator.php @@ -15,8 +15,8 @@ use Symfony\Component\DependencyInjection\ContainerInterface as SymfonyContainerInterface; use Symfony\Component\HttpKernel\CacheWarmer\WarmableInterface; use Symfony\Component\Translation\Translator as BaseTranslator; -use Symfony\Component\Translation\MessageSelector; use Symfony\Component\Translation\Exception\InvalidArgumentException; +use Symfony\Component\Translation\Formatter\MessageFormatterInterface; /** * Translator. @@ -56,15 +56,15 @@ class Translator extends BaseTranslator implements WarmableInterface * * debug: Whether to enable debugging or not (false by default) * * resource_files: List of translation resources available grouped by locale. * - * @param ContainerInterface $container A ContainerInterface instance - * @param MessageSelector $selector The message selector for pluralization - * @param string $defaultLocale - * @param array $loaderIds An array of loader Ids - * @param array $options An array of options + * @param ContainerInterface $container A ContainerInterface instance + * @param MessageFormatterInterface $formatter The message formatter + * @param string $defaultLocale + * @param array $loaderIds An array of loader Ids + * @param array $options An array of options * * @throws InvalidArgumentException */ - public function __construct(ContainerInterface $container, MessageSelector $selector, $defaultLocale = null, array $loaderIds = array(), array $options = array()) + public function __construct(ContainerInterface $container, $formatter, $defaultLocale = null, array $loaderIds = array(), array $options = array()) { // BC 3.x, to be removed in 4.0 along with the $defaultLocale default value if (is_array($defaultLocale) || 3 > func_num_args()) { @@ -90,7 +90,7 @@ public function __construct(ContainerInterface $container, MessageSelector $sele $this->resourceLocales = array_keys($this->options['resource_files']); $this->addResourceFiles($this->options['resource_files']); - parent::__construct($defaultLocale, $selector, $this->options['cache_dir'], $this->options['debug']); + parent::__construct($defaultLocale, $formatter, $this->options['cache_dir'], $this->options['debug']); } /** diff --git a/src/Symfony/Component/Translation/CHANGELOG.md b/src/Symfony/Component/Translation/CHANGELOG.md index cdd11cb91be6c..24753841cadb4 100644 --- a/src/Symfony/Component/Translation/CHANGELOG.md +++ b/src/Symfony/Component/Translation/CHANGELOG.md @@ -12,6 +12,7 @@ CHANGELOG * Improved Xliff 2.0 loader to load `` section. * Added `TranslationWriterInterface` * Deprecated `TranslationWriter::writeTranslations` in favor of `TranslationWriter::write` + * added support for adding custom message formatter and decoupling the default one. 3.2.0 ----- diff --git a/src/Symfony/Component/Translation/Formatter/ChoiceMessageFormatterInterface.php b/src/Symfony/Component/Translation/Formatter/ChoiceMessageFormatterInterface.php new file mode 100644 index 0000000000000..92acbcafe2032 --- /dev/null +++ b/src/Symfony/Component/Translation/Formatter/ChoiceMessageFormatterInterface.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\Component\Translation\Formatter; + +/** + * @author Abdellatif Ait boudad + */ +interface ChoiceMessageFormatterInterface +{ + /** + * Formats a localized message pattern with given arguments. + * + * @param string $message The message (may also be an object that can be cast to string) + * @param int $number The number to use to find the indice of the message + * @param string $locale The message locale + * @param array $parameters An array of parameters for the message + * + * @return string + */ + public function choiceFormat($message, $number, $locale, array $parameters = array()); +} diff --git a/src/Symfony/Component/Translation/Formatter/MessageFormatter.php b/src/Symfony/Component/Translation/Formatter/MessageFormatter.php new file mode 100644 index 0000000000000..e174be36c3a46 --- /dev/null +++ b/src/Symfony/Component/Translation/Formatter/MessageFormatter.php @@ -0,0 +1,48 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Formatter; + +use Symfony\Component\Translation\MessageSelector; + +/** + * @author Abdellatif Ait boudad + */ +class MessageFormatter implements MessageFormatterInterface, ChoiceMessageFormatterInterface +{ + private $selector; + + /** + * @param MessageSelector|null $selector The message selector for pluralization + */ + public function __construct(MessageSelector $selector = null) + { + $this->selector = $selector ?: new MessageSelector(); + } + + /** + * {@inheritdoc} + */ + public function format($message, $locale, array $parameters = array()) + { + return strtr($message, $parameters); + } + + /** + * {@inheritdoc} + */ + public function choiceFormat($message, $number, $locale, array $parameters = array()) + { + $parameters = array_merge(array('%count%' => $number), $parameters); + + return $this->format($this->selector->choose($message, (int) $number, $locale), $locale, $parameters); + } +} diff --git a/src/Symfony/Component/Translation/Formatter/MessageFormatterInterface.php b/src/Symfony/Component/Translation/Formatter/MessageFormatterInterface.php new file mode 100644 index 0000000000000..86937fb2f0853 --- /dev/null +++ b/src/Symfony/Component/Translation/Formatter/MessageFormatterInterface.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\Component\Translation\Formatter; + +/** + * @author Guilherme Blanco + * @author Abdellatif Ait boudad + */ +interface MessageFormatterInterface +{ + /** + * Formats a localized message pattern with given arguments. + * + * @param string $message The message (may also be an object that can be cast to string) + * @param string $locale The message locale + * @param array $parameters An array of parameters for the message + * + * @return string + */ + public function format($message, $locale, array $parameters = array()); +} diff --git a/src/Symfony/Component/Translation/Tests/Formatter/MessageFormatterTest.php b/src/Symfony/Component/Translation/Tests/Formatter/MessageFormatterTest.php new file mode 100644 index 0000000000000..1fa736e7e3df4 --- /dev/null +++ b/src/Symfony/Component/Translation/Tests/Formatter/MessageFormatterTest.php @@ -0,0 +1,82 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Tests\Formatter; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\Translation\Formatter\MessageFormatter; + +class MessageFormatterTest extends TestCase +{ + /** + * @dataProvider getTransMessages + */ + public function testFormat($expected, $message, $parameters = array()) + { + $this->assertEquals($expected, $this->getMessageFormatter()->format($message, 'en', $parameters)); + } + + /** + * @dataProvider getTransChoiceMessages + */ + public function testFormatPlural($expected, $message, $number, $parameters) + { + $this->assertEquals($expected, $this->getMessageFormatter()->choiceFormat($message, $number, 'fr', $parameters)); + } + + public function getTransMessages() + { + return array( + array( + 'There is one apple', + 'There is one apple', + ), + array( + 'There are 5 apples', + 'There are %count% apples', + array('%count%' => 5), + ), + array( + 'There are 5 apples', + 'There are {{count}} apples', + array('{{count}}' => 5), + ), + ); + } + + public function getTransChoiceMessages() + { + return array( + array('Il y a 0 pomme', '[0,1] Il y a %count% pomme|]1,Inf] Il y a %count% pommes', 0, array('%count%' => 0)), + array('Il y a 1 pomme', '[0,1] Il y a %count% pomme|]1,Inf] Il y a %count% pommes', 1, array('%count%' => 1)), + array('Il y a 10 pommes', '[0,1] Il y a %count% pomme|]1,Inf] Il y a %count% pommes', 10, array('%count%' => 10)), + + array('Il y a 0 pomme', 'Il y a %count% pomme|Il y a %count% pommes', 0, array('%count%' => 0)), + array('Il y a 1 pomme', 'Il y a %count% pomme|Il y a %count% pommes', 1, array('%count%' => 1)), + array('Il y a 10 pommes', 'Il y a %count% pomme|Il y a %count% pommes', 10, array('%count%' => 10)), + + array('Il y a 0 pomme', 'one: Il y a %count% pomme|more: Il y a %count% pommes', 0, array('%count%' => 0)), + array('Il y a 1 pomme', 'one: Il y a %count% pomme|more: Il y a %count% pommes', 1, array('%count%' => 1)), + array('Il y a 10 pommes', 'one: Il y a %count% pomme|more: Il y a %count% pommes', 10, array('%count%' => 10)), + + array('Il n\'y a aucune pomme', '{0} Il n\'y a aucune pomme|one: Il y a %count% pomme|more: Il y a %count% pommes', 0, array('%count%' => 0)), + array('Il y a 1 pomme', '{0} Il n\'y a aucune pomme|one: Il y a %count% pomme|more: Il y a %count% pommes', 1, array('%count%' => 1)), + array('Il y a 10 pommes', '{0} Il n\'y a aucune pomme|one: Il y a %count% pomme|more: Il y a %count% pommes', 10, array('%count%' => 10)), + + array('Il y a 0 pomme', '[0,1] Il y a %count% pomme|]1,Inf] Il y a %count% pommes', 0, array('%count%' => 0)), + ); + } + + private function getMessageFormatter() + { + return new MessageFormatter(); + } +} diff --git a/src/Symfony/Component/Translation/Tests/TranslatorTest.php b/src/Symfony/Component/Translation/Tests/TranslatorTest.php index 2394fdb4320b1..d2c6fd51f453c 100644 --- a/src/Symfony/Component/Translation/Tests/TranslatorTest.php +++ b/src/Symfony/Component/Translation/Tests/TranslatorTest.php @@ -13,7 +13,6 @@ use PHPUnit\Framework\TestCase; use Symfony\Component\Translation\Translator; -use Symfony\Component\Translation\MessageSelector; use Symfony\Component\Translation\Loader\ArrayLoader; use Symfony\Component\Translation\MessageCatalogue; @@ -25,7 +24,7 @@ class TranslatorTest extends TestCase */ public function testConstructorInvalidLocale($locale) { - $translator = new Translator($locale, new MessageSelector()); + $translator = new Translator($locale); } /** @@ -33,14 +32,14 @@ public function testConstructorInvalidLocale($locale) */ public function testConstructorValidLocale($locale) { - $translator = new Translator($locale, new MessageSelector()); + $translator = new Translator($locale); $this->assertEquals($locale, $translator->getLocale()); } public function testConstructorWithoutLocale() { - $translator = new Translator(null, new MessageSelector()); + $translator = new Translator(null); $this->assertNull($translator->getLocale()); } @@ -61,7 +60,7 @@ public function testSetGetLocale() */ public function testSetInvalidLocale($locale) { - $translator = new Translator('fr', new MessageSelector()); + $translator = new Translator('fr'); $translator->setLocale($locale); } @@ -70,7 +69,7 @@ public function testSetInvalidLocale($locale) */ public function testSetValidLocale($locale) { - $translator = new Translator($locale, new MessageSelector()); + $translator = new Translator($locale); $translator->setLocale($locale); $this->assertEquals($locale, $translator->getLocale()); @@ -144,7 +143,7 @@ public function testSetFallbackLocalesMultiple() */ public function testSetFallbackInvalidLocales($locale) { - $translator = new Translator('fr', new MessageSelector()); + $translator = new Translator('fr'); $translator->setFallbackLocales(array('fr', $locale)); } @@ -153,7 +152,7 @@ public function testSetFallbackInvalidLocales($locale) */ public function testSetFallbackValidLocales($locale) { - $translator = new Translator($locale, new MessageSelector()); + $translator = new Translator($locale); $translator->setFallbackLocales(array('fr', $locale)); // no assertion. this method just asserts that no exception is thrown $this->addToAssertionCount(1); @@ -176,7 +175,7 @@ public function testTransWithFallbackLocale() */ public function testAddResourceInvalidLocales($locale) { - $translator = new Translator('fr', new MessageSelector()); + $translator = new Translator('fr'); $translator->addResource('array', array('foo' => 'foofoo'), $locale); } @@ -185,7 +184,7 @@ public function testAddResourceInvalidLocales($locale) */ public function testAddResourceValidLocales($locale) { - $translator = new Translator('fr', new MessageSelector()); + $translator = new Translator('fr'); $translator->addResource('array', array('foo' => 'foofoo'), $locale); // no assertion. this method just asserts that no exception is thrown $this->addToAssertionCount(1); @@ -288,7 +287,7 @@ public function testNestedFallbackCatalogueWhenUsingMultipleLocales() public function testFallbackCatalogueResources() { - $translator = new Translator('en_GB', new MessageSelector()); + $translator = new Translator('en_GB'); $translator->addLoader('yml', new \Symfony\Component\Translation\Loader\YamlFileLoader()); $translator->addResource('yml', __DIR__.'/fixtures/empty.yml', 'en_GB'); $translator->addResource('yml', __DIR__.'/fixtures/resources.yml', 'en'); @@ -324,7 +323,7 @@ public function testTrans($expected, $id, $translation, $parameters, $locale, $d */ public function testTransInvalidLocale($locale) { - $translator = new Translator('en', new MessageSelector()); + $translator = new Translator('en'); $translator->addLoader('array', new ArrayLoader()); $translator->addResource('array', array('foo' => 'foofoo'), 'en'); @@ -336,7 +335,7 @@ public function testTransInvalidLocale($locale) */ public function testTransValidLocale($locale) { - $translator = new Translator($locale, new MessageSelector()); + $translator = new Translator($locale); $translator->addLoader('array', new ArrayLoader()); $translator->addResource('array', array('test' => 'OK'), $locale); @@ -374,7 +373,7 @@ public function testTransChoice($expected, $id, $translation, $number, $paramete */ public function testTransChoiceInvalidLocale($locale) { - $translator = new Translator('en', new MessageSelector()); + $translator = new Translator('en'); $translator->addLoader('array', new ArrayLoader()); $translator->addResource('array', array('foo' => 'foofoo'), 'en'); @@ -386,7 +385,7 @@ public function testTransChoiceInvalidLocale($locale) */ public function testTransChoiceValidLocale($locale) { - $translator = new Translator('en', new MessageSelector()); + $translator = new Translator('en'); $translator->addLoader('array', new ArrayLoader()); $translator->addResource('array', array('foo' => 'foofoo'), 'en'); diff --git a/src/Symfony/Component/Translation/Translator.php b/src/Symfony/Component/Translation/Translator.php index 897aced2717b5..96553ec989986 100644 --- a/src/Symfony/Component/Translation/Translator.php +++ b/src/Symfony/Component/Translation/Translator.php @@ -14,10 +14,14 @@ use Symfony\Component\Translation\Loader\LoaderInterface; use Symfony\Component\Translation\Exception\NotFoundResourceException; use Symfony\Component\Translation\Exception\InvalidArgumentException; +use Symfony\Component\Translation\Exception\LogicException; use Symfony\Component\Translation\Exception\RuntimeException; use Symfony\Component\Config\ConfigCacheInterface; use Symfony\Component\Config\ConfigCacheFactoryInterface; use Symfony\Component\Config\ConfigCacheFactory; +use Symfony\Component\Translation\Formatter\MessageFormatterInterface; +use Symfony\Component\Translation\Formatter\ChoiceMessageFormatterInterface; +use Symfony\Component\Translation\Formatter\MessageFormatter; /** * Translator. @@ -52,9 +56,9 @@ class Translator implements TranslatorInterface, TranslatorBagInterface private $resources = array(); /** - * @var MessageSelector + * @var MessageFormatterInterface */ - private $selector; + private $formatter; /** * @var string @@ -74,17 +78,25 @@ class Translator implements TranslatorInterface, TranslatorBagInterface /** * Constructor. * - * @param string $locale The locale - * @param MessageSelector|null $selector The message selector for pluralization - * @param string|null $cacheDir The directory to use for the cache - * @param bool $debug Use cache in debug mode ? + * @param string $locale The locale + * @param MessageFormatterInterface|null $formatter The message formatter + * @param string|null $cacheDir The directory to use for the cache + * @param bool $debug Use cache in debug mode ? * * @throws InvalidArgumentException If a locale contains invalid characters */ - public function __construct($locale, MessageSelector $selector = null, $cacheDir = null, $debug = false) + public function __construct($locale, $formatter = null, $cacheDir = null, $debug = false) { $this->setLocale($locale); - $this->selector = $selector ?: new MessageSelector(); + + if ($formatter instanceof MessageSelector) { + $formatter = new MessageFormatter($formatter); + @trigger_error(sprintf('Passing a "%s" instance into the "%s" as a second argument is deprecated since version 3.4 and will be removed in 4.0. Inject a "%s" implementation instead.', MessageSelector::class, __METHOD__, MessageFormatterInterface::class), E_USER_DEPRECATED); + } elseif (null === $formatter) { + $formatter = new MessageFormatter(); + } + + $this->formatter = $formatter; $this->cacheDir = $cacheDir; $this->debug = $debug; } @@ -192,7 +204,7 @@ public function trans($id, array $parameters = array(), $domain = null, $locale $domain = 'messages'; } - return strtr($this->getCatalogue($locale)->get((string) $id, $domain), $parameters); + return $this->formatter->format($this->getCatalogue($locale)->get((string) $id, $domain), $locale, $parameters); } /** @@ -200,9 +212,9 @@ public function trans($id, array $parameters = array(), $domain = null, $locale */ public function transChoice($id, $number, array $parameters = array(), $domain = null, $locale = null) { - $parameters = array_merge(array( - '%count%' => $number, - ), $parameters); + if (!$this->formatter instanceof ChoiceMessageFormatterInterface) { + throw new LogicException(sprintf('The formatter "%s" does not support plural translations.', get_class($this->formatter))); + } if (null === $domain) { $domain = 'messages'; @@ -220,7 +232,7 @@ public function transChoice($id, $number, array $parameters = array(), $domain = } } - return strtr($this->selector->choose($catalogue->get($id, $domain), (int) $number, $locale), $parameters); + return $this->formatter->choiceFormat($catalogue->get($id, $domain), $number, $locale, $parameters); } /** From 5bc0b0527e961fef3b943a995677a37bde0f9307 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Haso=C5=88?= Date: Tue, 12 Sep 2017 16:32:04 +0200 Subject: [PATCH 0813/1099] [FrameworkBundle] Enable assets with templates only if the Asset component is installed --- .../FrameworkBundle/DependencyInjection/Configuration.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php index fab5ac344600e..3a95ee5fedb63 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php @@ -52,7 +52,7 @@ public function getConfigTreeBuilder() $rootNode ->beforeNormalization() - ->ifTrue(function ($v) { return !isset($v['assets']) && isset($v['templating']); }) + ->ifTrue(function ($v) { return !isset($v['assets']) && isset($v['templating']) && class_exists(Package::class); }) ->then(function ($v) { $v['assets'] = array(); From f1ab3b28ac95f7ea5ce16be4a2c91639d08cfb35 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Tue, 12 Sep 2017 18:00:24 +0200 Subject: [PATCH 0814/1099] [Routing] Cleanup apache fixtures --- .../Tests/Fixtures/dumper/url_matcher1.apache | 163 ------------------ .../Tests/Fixtures/dumper/url_matcher2.apache | 7 - 2 files changed, 170 deletions(-) delete mode 100644 src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher1.apache delete mode 100644 src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher2.apache diff --git a/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher1.apache b/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher1.apache deleted file mode 100644 index 26a561cc91180..0000000000000 --- a/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher1.apache +++ /dev/null @@ -1,163 +0,0 @@ -# skip "real" requests -RewriteCond %{REQUEST_FILENAME} -f -RewriteRule .* - [QSA,L] - -# foo -RewriteCond %{REQUEST_URI} ^/foo/(baz|symfony)$ -RewriteRule .* app.php [QSA,L,E=_ROUTING_route:foo,E=_ROUTING_param_bar:%1,E=_ROUTING_default_def:test] - -# foobar -RewriteCond %{REQUEST_URI} ^/foo(?:/([^/]++))?$ -RewriteRule .* app.php [QSA,L,E=_ROUTING_route:foobar,E=_ROUTING_param_bar:%1,E=_ROUTING_default_bar:toto] - -# bar -RewriteCond %{REQUEST_URI} ^/bar/([^/]++)$ -RewriteCond %{REQUEST_METHOD} !^(GET|HEAD)$ [NC] -RewriteRule .* - [S=1,E=_ROUTING_allow_GET:1,E=_ROUTING_allow_HEAD:1] -RewriteCond %{REQUEST_URI} ^/bar/([^/]++)$ -RewriteRule .* app.php [QSA,L,E=_ROUTING_route:bar,E=_ROUTING_param_foo:%1] - -# baragain -RewriteCond %{REQUEST_URI} ^/baragain/([^/]++)$ -RewriteCond %{REQUEST_METHOD} !^(GET|POST|HEAD)$ [NC] -RewriteRule .* - [S=1,E=_ROUTING_allow_GET:1,E=_ROUTING_allow_POST:1,E=_ROUTING_allow_HEAD:1] -RewriteCond %{REQUEST_URI} ^/baragain/([^/]++)$ -RewriteRule .* app.php [QSA,L,E=_ROUTING_route:baragain,E=_ROUTING_param_foo:%1] - -# baz -RewriteCond %{REQUEST_URI} ^/test/baz$ -RewriteRule .* app.php [QSA,L,E=_ROUTING_route:baz] - -# baz2 -RewriteCond %{REQUEST_URI} ^/test/baz\.html$ -RewriteRule .* app.php [QSA,L,E=_ROUTING_route:baz2] - -# baz3 -RewriteCond %{REQUEST_URI} ^/test/baz3$ -RewriteRule .* $0/ [QSA,L,R=301] -RewriteCond %{REQUEST_URI} ^/test/baz3/$ -RewriteRule .* app.php [QSA,L,E=_ROUTING_route:baz3] - -# baz4 -RewriteCond %{REQUEST_URI} ^/test/([^/]++)$ -RewriteRule .* $0/ [QSA,L,R=301] -RewriteCond %{REQUEST_URI} ^/test/([^/]++)/$ -RewriteRule .* app.php [QSA,L,E=_ROUTING_route:baz4,E=_ROUTING_param_foo:%1] - -# baz5 -RewriteCond %{REQUEST_URI} ^/test/([^/]++)/$ -RewriteCond %{REQUEST_METHOD} !^(GET|HEAD)$ [NC] -RewriteRule .* - [S=2,E=_ROUTING_allow_GET:1,E=_ROUTING_allow_HEAD:1] -RewriteCond %{REQUEST_URI} ^/test/([^/]++)$ -RewriteRule .* $0/ [QSA,L,R=301] -RewriteCond %{REQUEST_URI} ^/test/([^/]++)/$ -RewriteRule .* app.php [QSA,L,E=_ROUTING_route:baz5,E=_ROUTING_param_foo:%1] - -# baz5unsafe -RewriteCond %{REQUEST_URI} ^/testunsafe/([^/]++)/$ -RewriteCond %{REQUEST_METHOD} !^(POST)$ [NC] -RewriteRule .* - [S=1,E=_ROUTING_allow_POST:1] -RewriteCond %{REQUEST_URI} ^/testunsafe/([^/]++)/$ -RewriteRule .* app.php [QSA,L,E=_ROUTING_route:baz5unsafe,E=_ROUTING_param_foo:%1] - -# baz6 -RewriteCond %{REQUEST_URI} ^/test/baz$ -RewriteRule .* app.php [QSA,L,E=_ROUTING_route:baz6,E=_ROUTING_default_foo:bar\ baz] - -# baz7 -RewriteCond %{REQUEST_URI} ^/te\ st/baz$ -RewriteRule .* app.php [QSA,L,E=_ROUTING_route:baz7] - -# baz8 -RewriteCond %{REQUEST_URI} ^/te\\\ st/baz$ -RewriteRule .* app.php [QSA,L,E=_ROUTING_route:baz8] - -# baz9 -RewriteCond %{REQUEST_URI} ^/test/(te\\\ st)$ -RewriteRule .* app.php [QSA,L,E=_ROUTING_route:baz9,E=_ROUTING_param_baz:%1] - -RewriteCond %{HTTP:Host} ^a\.example\.com$ -RewriteRule .? - [E=__ROUTING_host_1:1] - -# route1 -RewriteCond %{ENV:__ROUTING_host_1} =1 -RewriteCond %{REQUEST_URI} ^/route1$ -RewriteRule .* app.php [QSA,L,E=_ROUTING_route:route1] - -# route2 -RewriteCond %{ENV:__ROUTING_host_1} =1 -RewriteCond %{REQUEST_URI} ^/c2/route2$ -RewriteRule .* app.php [QSA,L,E=_ROUTING_route:route2] - -RewriteCond %{HTTP:Host} ^b\.example\.com$ -RewriteRule .? - [E=__ROUTING_host_2:1] - -# route3 -RewriteCond %{ENV:__ROUTING_host_2} =1 -RewriteCond %{REQUEST_URI} ^/c2/route3$ -RewriteRule .* app.php [QSA,L,E=_ROUTING_route:route3] - -RewriteCond %{HTTP:Host} ^a\.example\.com$ -RewriteRule .? - [E=__ROUTING_host_3:1] - -# route4 -RewriteCond %{ENV:__ROUTING_host_3} =1 -RewriteCond %{REQUEST_URI} ^/route4$ -RewriteRule .* app.php [QSA,L,E=_ROUTING_route:route4] - -RewriteCond %{HTTP:Host} ^c\.example\.com$ -RewriteRule .? - [E=__ROUTING_host_4:1] - -# route5 -RewriteCond %{ENV:__ROUTING_host_4} =1 -RewriteCond %{REQUEST_URI} ^/route5$ -RewriteRule .* app.php [QSA,L,E=_ROUTING_route:route5] - -# route6 -RewriteCond %{REQUEST_URI} ^/route6$ -RewriteRule .* app.php [QSA,L,E=_ROUTING_route:route6] - -RewriteCond %{HTTP:Host} ^([^\.]++)\.example\.com$ -RewriteRule .? - [E=__ROUTING_host_5:1,E=__ROUTING_host_5_var1:%1] - -# route11 -RewriteCond %{ENV:__ROUTING_host_5} =1 -RewriteCond %{REQUEST_URI} ^/route11$ -RewriteRule .* app.php [QSA,L,E=_ROUTING_route:route11,E=_ROUTING_param_var1:%{ENV:__ROUTING_host_5_var1}] - -# route12 -RewriteCond %{ENV:__ROUTING_host_5} =1 -RewriteCond %{REQUEST_URI} ^/route12$ -RewriteRule .* app.php [QSA,L,E=_ROUTING_route:route12,E=_ROUTING_param_var1:%{ENV:__ROUTING_host_5_var1},E=_ROUTING_default_var1:val] - -# route13 -RewriteCond %{ENV:__ROUTING_host_5} =1 -RewriteCond %{REQUEST_URI} ^/route13/([^/]++)$ -RewriteRule .* app.php [QSA,L,E=_ROUTING_route:route13,E=_ROUTING_param_var1:%{ENV:__ROUTING_host_5_var1},E=_ROUTING_param_name:%1] - -# route14 -RewriteCond %{ENV:__ROUTING_host_5} =1 -RewriteCond %{REQUEST_URI} ^/route14/([^/]++)$ -RewriteRule .* app.php [QSA,L,E=_ROUTING_route:route14,E=_ROUTING_param_var1:%{ENV:__ROUTING_host_5_var1},E=_ROUTING_param_name:%1,E=_ROUTING_default_var1:val] - -RewriteCond %{HTTP:Host} ^c\.example\.com$ -RewriteRule .? - [E=__ROUTING_host_6:1] - -# route15 -RewriteCond %{ENV:__ROUTING_host_6} =1 -RewriteCond %{REQUEST_URI} ^/route15/([^/]++)$ -RewriteRule .* app.php [QSA,L,E=_ROUTING_route:route15,E=_ROUTING_param_name:%1] - -# route16 -RewriteCond %{REQUEST_URI} ^/route16/([^/]++)$ -RewriteRule .* app.php [QSA,L,E=_ROUTING_route:route16,E=_ROUTING_param_name:%1,E=_ROUTING_default_var1:val] - -# route17 -RewriteCond %{REQUEST_URI} ^/route17$ -RewriteRule .* app.php [QSA,L,E=_ROUTING_route:route17] - -# 405 Method Not Allowed -RewriteCond %{ENV:_ROUTING__allow_GET} =1 [OR] -RewriteCond %{ENV:_ROUTING__allow_HEAD} =1 [OR] -RewriteCond %{ENV:_ROUTING__allow_POST} =1 -RewriteRule .* app.php [QSA,L] diff --git a/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher2.apache b/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher2.apache deleted file mode 100644 index 309f2ff0e5394..0000000000000 --- a/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher2.apache +++ /dev/null @@ -1,7 +0,0 @@ -# skip "real" requests -RewriteCond %{REQUEST_FILENAME} -f -RewriteRule .* - [QSA,L] - -# foo -RewriteCond %{REQUEST_URI} ^/foo$ -RewriteRule .* ap\ p_d\ ev.php [QSA,L,E=_ROUTING_route:foo] From 8d5674480f8b7dfbd908fbc5492ac3393074f2ee Mon Sep 17 00:00:00 2001 From: Yonel Ceruto Date: Tue, 12 Sep 2017 14:46:33 -0400 Subject: [PATCH 0815/1099] Add support to environment variables APP_ENV/DEBUG in KernelTestCase --- .../FrameworkBundle/Test/KernelTestCase.php | 25 ++++++++++++++++--- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/Test/KernelTestCase.php b/src/Symfony/Bundle/FrameworkBundle/Test/KernelTestCase.php index 4617aea71c4b3..1927146c4cffa 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Test/KernelTestCase.php +++ b/src/Symfony/Bundle/FrameworkBundle/Test/KernelTestCase.php @@ -178,10 +178,27 @@ protected static function createKernel(array $options = array()) static::$class = static::getKernelClass(); } - return new static::$class( - isset($options['environment']) ? $options['environment'] : 'test', - isset($options['debug']) ? $options['debug'] : true - ); + if (isset($options['environment'])) { + $env = $options['environment']; + } elseif (isset($_SERVER['APP_ENV'])) { + $env = $_SERVER['APP_ENV']; + } elseif (isset($_ENV['APP_ENV'])) { + $env = $_ENV['APP_ENV']; + } else { + $env = 'test'; + } + + if (isset($options['debug'])) { + $debug = $options['debug']; + } elseif (isset($_SERVER['APP_DEBUG'])) { + $debug = $_SERVER['APP_DEBUG']; + } elseif (isset($_ENV['APP_DEBUG'])) { + $debug = $_ENV['APP_DEBUG']; + } else { + $debug = true; + } + + return new static::$class($env, $debug); } /** From 2028a83689fe7d413670fc47d5ef5b9c749bfabc Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Tue, 12 Sep 2017 18:35:33 +0200 Subject: [PATCH 0816/1099] drop MessageSelector support in the Translator --- .../Bundle/FrameworkBundle/Translation/Translator.php | 2 +- src/Symfony/Component/Translation/CHANGELOG.md | 1 + src/Symfony/Component/Translation/Translator.php | 7 ++----- 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/Translation/Translator.php b/src/Symfony/Bundle/FrameworkBundle/Translation/Translator.php index 190bd5d0da817..14cb2adecfe55 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Translation/Translator.php +++ b/src/Symfony/Bundle/FrameworkBundle/Translation/Translator.php @@ -63,7 +63,7 @@ class Translator extends BaseTranslator implements WarmableInterface * * @throws InvalidArgumentException */ - public function __construct(ContainerInterface $container, $formatter, string $defaultLocale, array $loaderIds = array(), array $options = array()) + public function __construct(ContainerInterface $container, MessageFormatterInterface $formatter, string $defaultLocale, array $loaderIds = array(), array $options = array()) { $this->container = $container; $this->loaderIds = $loaderIds; diff --git a/src/Symfony/Component/Translation/CHANGELOG.md b/src/Symfony/Component/Translation/CHANGELOG.md index 289fed1ce4344..ed821fa03d715 100644 --- a/src/Symfony/Component/Translation/CHANGELOG.md +++ b/src/Symfony/Component/Translation/CHANGELOG.md @@ -6,6 +6,7 @@ CHANGELOG * removed the backup feature of the `FileDumper` class * removed `TranslationWriter::writeTranslations()` method + * removed support for passing `MessageSelector` instances to the constructor of the `Translator` class 3.4.0 ----- diff --git a/src/Symfony/Component/Translation/Translator.php b/src/Symfony/Component/Translation/Translator.php index 5ed01af58b914..f691e65ba6525 100644 --- a/src/Symfony/Component/Translation/Translator.php +++ b/src/Symfony/Component/Translation/Translator.php @@ -85,14 +85,11 @@ class Translator implements TranslatorInterface, TranslatorBagInterface * * @throws InvalidArgumentException If a locale contains invalid characters */ - public function __construct($locale, $formatter = null, $cacheDir = null, $debug = false) + public function __construct($locale, MessageFormatterInterface $formatter = null, $cacheDir = null, $debug = false) { $this->setLocale($locale); - if ($formatter instanceof MessageSelector) { - $formatter = new MessageFormatter($formatter); - @trigger_error(sprintf('Passing a "%s" instance into the "%s" as a second argument is deprecated since version 3.4 and will be removed in 4.0. Inject a "%s" implementation instead.', MessageSelector::class, __METHOD__, MessageFormatterInterface::class), E_USER_DEPRECATED); - } elseif (null === $formatter) { + if (null === $formatter) { $formatter = new MessageFormatter(); } From 1936491f9b12891326aa875aa32050475d2a0404 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Tue, 5 Sep 2017 13:45:10 +0200 Subject: [PATCH 0817/1099] Make as many services private as possible --- .../AbstractDoctrineExtension.php | 3 + .../DependencyInjection/DebugExtension.php | 3 + .../DebugBundle/Resources/config/services.xml | 4 +- src/Symfony/Bundle/DebugBundle/composer.json | 5 +- .../FrameworkExtension.php | 161 +++++++++++++- .../Resources/config/annotations.xml | 2 +- .../Resources/config/assets.xml | 10 +- .../Resources/config/cache.xml | 16 +- .../Resources/config/collectors.xml | 4 +- .../Resources/config/debug.xml | 6 +- .../Resources/config/debug_prod.xml | 2 +- .../FrameworkBundle/Resources/config/esi.xml | 4 +- .../FrameworkBundle/Resources/config/form.xml | 17 +- .../Resources/config/form_csrf.xml | 6 +- .../Resources/config/form_debug.xml | 6 +- .../Resources/config/fragment_listener.xml | 2 +- .../Resources/config/fragment_renderer.xml | 10 +- .../Resources/config/profiling.xml | 2 +- .../Resources/config/property_access.xml | 2 +- .../Resources/config/property_info.xml | 2 +- .../Resources/config/request.xml | 2 +- .../Resources/config/routing.xml | 2 +- .../Resources/config/serializer.xml | 2 +- .../Resources/config/services.xml | 8 +- .../Resources/config/session.xml | 10 +- .../FrameworkBundle/Resources/config/ssi.xml | 4 +- .../Resources/config/templating.xml | 4 +- .../Resources/config/templating_php.xml | 22 +- .../FrameworkBundle/Resources/config/test.xml | 6 +- .../Resources/config/translation.xml | 56 ++--- .../Resources/config/translation_debug.xml | 2 +- .../Resources/config/validator.xml | 6 +- .../FrameworkBundle/Resources/config/web.xml | 8 +- .../Resources/config/workflow.xml | 6 +- .../Functional/CachePoolClearCommandTest.php | 4 +- .../Tests/Functional/PropertyInfoTest.php | 2 +- .../Functional/app/Serializer/config.yml | 3 + .../DependencyInjection/SecurityExtension.php | 21 +- .../SecurityBundle/Resources/config/guard.xml | 1 - .../Resources/config/security.xml | 8 +- .../Resources/config/security_acl_dbal.xml | 6 +- .../Resources/config/security_debug.xml | 2 +- .../Resources/config/security_rememberme.xml | 2 +- .../Resources/config/templating_php.xml | 4 +- .../Tests/Functional/SetAclCommandTest.php | 10 +- .../Tests/Functional/app/Acl/config.yml | 3 + .../Bundle/SecurityBundle/composer.json | 3 +- .../Compiler/TwigLoaderPass.php | 5 +- .../DependencyInjection/TwigExtension.php | 7 + .../TwigBundle/Resources/config/form.xml | 2 +- .../TwigBundle/Resources/config/twig.xml | 10 +- .../Compiler/TwigLoaderPassTest.php | 10 +- src/Symfony/Bundle/TwigBundle/composer.json | 7 +- .../WebProfilerExtension.php | 1 + .../Resources/config/toolbar.xml | 2 +- .../Bundle/WebProfilerBundle/composer.json | 6 +- .../Component/DependencyInjection/Alias.php | 34 +++ .../Compiler/CheckDefinitionValidityPass.php | 2 +- .../Compiler/DecoratorServicePass.php | 4 +- .../Compiler/InlineServiceDefinitionsPass.php | 2 +- .../Compiler/RemovePrivateAliasesPass.php | 2 +- .../Compiler/RemoveUnusedDefinitionsPass.php | 5 +- .../ReplaceAliasByActualDefinitionPass.php | 5 +- .../Compiler/ResolveChildDefinitionsPass.php | 23 ++ .../ResolveReferencesToAliasesPass.php | 2 +- .../DependencyInjection/ContainerBuilder.php | 4 +- .../DependencyInjection/Definition.php | 30 +++ .../DependencyInjection/Dumper/PhpDumper.php | 12 +- .../ResolveChildDefinitionsPassTest.php | 20 ++ .../Tests/Dumper/PhpDumperTest.php | 46 ++++ .../Fixtures/php/services_legacy_privates.php | 200 ++++++++++++++++++ .../yaml/services_legacy_privates.yml | 28 +++ 72 files changed, 758 insertions(+), 185 deletions(-) create mode 100644 src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_legacy_privates.php create mode 100644 src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services_legacy_privates.yml diff --git a/src/Symfony/Bridge/Doctrine/DependencyInjection/AbstractDoctrineExtension.php b/src/Symfony/Bridge/Doctrine/DependencyInjection/AbstractDoctrineExtension.php index 3d4fc46e1fff4..229cacf8255a9 100644 --- a/src/Symfony/Bridge/Doctrine/DependencyInjection/AbstractDoctrineExtension.php +++ b/src/Symfony/Bridge/Doctrine/DependencyInjection/AbstractDoctrineExtension.php @@ -333,6 +333,7 @@ protected function loadCacheDriver($cacheName, $objectManagerName, array $cacheD $memcachePort = !empty($cacheDriver['port']) || (isset($cacheDriver['port']) && $cacheDriver['port'] === 0) ? $cacheDriver['port'] : '%'.$this->getObjectManagerElementName('cache.memcache_port').'%'; $cacheDef = new Definition($memcacheClass); $memcacheInstance = new Definition($memcacheInstanceClass); + $memcacheInstance->setPrivate(true); $memcacheInstance->addMethodCall('connect', array( $memcacheHost, $memcachePort, )); @@ -346,6 +347,7 @@ protected function loadCacheDriver($cacheName, $objectManagerName, array $cacheD $memcachedPort = !empty($cacheDriver['port']) ? $cacheDriver['port'] : '%'.$this->getObjectManagerElementName('cache.memcached_port').'%'; $cacheDef = new Definition($memcachedClass); $memcachedInstance = new Definition($memcachedInstanceClass); + $memcachedInstance->setPrivate(true); $memcachedInstance->addMethodCall('addServer', array( $memcachedHost, $memcachedPort, )); @@ -359,6 +361,7 @@ protected function loadCacheDriver($cacheName, $objectManagerName, array $cacheD $redisPort = !empty($cacheDriver['port']) ? $cacheDriver['port'] : '%'.$this->getObjectManagerElementName('cache.redis_port').'%'; $cacheDef = new Definition($redisClass); $redisInstance = new Definition($redisInstanceClass); + $redisInstance->setPrivate(true); $redisInstance->addMethodCall('connect', array( $redisHost, $redisPort, )); diff --git a/src/Symfony/Bundle/DebugBundle/DependencyInjection/DebugExtension.php b/src/Symfony/Bundle/DebugBundle/DependencyInjection/DebugExtension.php index 835d823664021..d7c0ee7287468 100644 --- a/src/Symfony/Bundle/DebugBundle/DependencyInjection/DebugExtension.php +++ b/src/Symfony/Bundle/DebugBundle/DependencyInjection/DebugExtension.php @@ -35,6 +35,9 @@ public function load(array $configs, ContainerBuilder $container) $loader = new XmlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config')); $loader->load('services.xml'); + $container->getDefinition('debug.dump_listener')->setPrivate(true); + $container->getDefinition('var_dumper.cli_dumper')->setPrivate(true); + $container->getDefinition('var_dumper.cloner') ->addMethodCall('setMaxItems', array($config['max_items'])) ->addMethodCall('setMinDepth', array($config['min_depth'])) diff --git a/src/Symfony/Bundle/DebugBundle/Resources/config/services.xml b/src/Symfony/Bundle/DebugBundle/Resources/config/services.xml index 79460a160259a..7e276dafab5d2 100644 --- a/src/Symfony/Bundle/DebugBundle/Resources/config/services.xml +++ b/src/Symfony/Bundle/DebugBundle/Resources/config/services.xml @@ -22,14 +22,14 @@ null - + - + null %kernel.charset% 0 diff --git a/src/Symfony/Bundle/DebugBundle/composer.json b/src/Symfony/Bundle/DebugBundle/composer.json index 5ad163e3031a3..7b59b82c765f6 100644 --- a/src/Symfony/Bundle/DebugBundle/composer.json +++ b/src/Symfony/Bundle/DebugBundle/composer.json @@ -24,9 +24,12 @@ }, "require-dev": { "symfony/config": "~3.3|~4.0", - "symfony/dependency-injection": "~3.3|~4.0", + "symfony/dependency-injection": "~3.4|~4.0", "symfony/web-profiler-bundle": "~2.8|~3.0|~4.0" }, + "conflict": { + "symfony/dependency-injection": "<3.4" + }, "suggest": { "symfony/config": "For service container configuration", "symfony/dependency-injection": "For using as a service from the container" diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php index 9b3a071168a51..0ead938a1bf10 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php @@ -115,6 +115,15 @@ public function load(array $configs, ContainerBuilder $container) $loader->load('web.xml'); $loader->load('services.xml'); + $container->getDefinition('kernel.class_cache.cache_warmer')->setPrivate(true); + $container->getDefinition('uri_signer')->setPrivate(true); + $container->getDefinition('config_cache_factory')->setPrivate(true); + $container->getDefinition('response_listener')->setPrivate(true); + $container->getDefinition('file_locator')->setPrivate(true); + $container->getDefinition('streamed_response_listener')->setPrivate(true); + $container->getDefinition('locale_listener')->setPrivate(true); + $container->getDefinition('validate_request_listener')->setPrivate(true); + // forward compatibility with Symfony 4.0 where the ContainerAwareEventDispatcher class is removed if (!class_exists(ContainerAwareEventDispatcher::class)) { $definition = $container->getDefinition('event_dispatcher'); @@ -131,6 +140,12 @@ public function load(array $configs, ContainerBuilder $container) $loader->load('fragment_renderer.xml'); + $container->getDefinition('fragment.handler')->setPrivate(true); + $container->getDefinition('fragment.renderer.inline')->setPrivate(true); + $container->getDefinition('fragment.renderer.hinclude')->setPrivate(true); + $container->getDefinition('fragment.renderer.esi')->setPrivate(true); + $container->getDefinition('fragment.renderer.ssi')->setPrivate(true); + if (class_exists(Application::class)) { $loader->load('console.xml'); @@ -145,9 +160,20 @@ public function load(array $configs, ContainerBuilder $container) // Property access is used by both the Form and the Validator component $loader->load('property_access.xml'); + $container->getDefinition('property_accessor')->setPrivate(true); + // Load Cache configuration first as it is used by other components $loader->load('cache.xml'); + $container->getDefinition('cache.adapter.system')->setPrivate(true); + $container->getDefinition('cache.adapter.apcu')->setPrivate(true); + $container->getDefinition('cache.adapter.doctrine')->setPrivate(true); + $container->getDefinition('cache.adapter.filesystem')->setPrivate(true); + $container->getDefinition('cache.adapter.psr6')->setPrivate(true); + $container->getDefinition('cache.adapter.redis')->setPrivate(true); + $container->getDefinition('cache.adapter.memcached')->setPrivate(true); + $container->getDefinition('cache.default_clearer')->setPrivate(true); + $configuration = $this->getConfiguration($configs, $container); $config = $this->processConfiguration($configuration, $configs); @@ -202,6 +228,10 @@ public function load(array $configs, ContainerBuilder $container) if (!empty($config['test'])) { $loader->load('test.xml'); + + $container->getDefinition('test.client.history')->setPrivate(true); + $container->getDefinition('test.client.cookiejar')->setPrivate(true); + $container->getDefinition('test.session.listener')->setPrivate(true); } if ($this->isConfigEnabled($container, $config['session'])) { @@ -389,6 +419,19 @@ public function getConfiguration(array $config, ContainerBuilder $container) private function registerFormConfiguration($config, ContainerBuilder $container, XmlFileLoader $loader) { $loader->load('form.xml'); + + $container->getDefinition('form.resolved_type_factory')->setPrivate(true); + $container->getDefinition('form.registry')->setPrivate(true); + $container->getDefinition('form.type_guesser.validator')->setPrivate(true); + $container->getDefinition('form.type.form')->setPrivate(true); + $container->getDefinition('form.type.choice')->setPrivate(true); + $container->getDefinition('form.type_extension.form.http_foundation')->setPrivate(true); + $container->getDefinition('form.type_extension.form.validator')->setPrivate(true); + $container->getDefinition('form.type_extension.repeated.validator')->setPrivate(true); + $container->getDefinition('form.type_extension.submit.validator')->setPrivate(true); + $container->getDefinition('form.type_extension.upload.validator')->setPrivate(true); + $container->getDefinition('deprecated.form.registry')->setPrivate(true); + if (null === $config['form']['csrf_protection']['enabled']) { $config['form']['csrf_protection']['enabled'] = $config['csrf_protection']['enabled']; } @@ -396,6 +439,9 @@ private function registerFormConfiguration($config, ContainerBuilder $container, if ($this->isConfigEnabled($container, $config['form']['csrf_protection'])) { $loader->load('form_csrf.xml'); + $container->getDefinition('form.type_extension.csrf')->setPrivate(true); + $container->getDefinition('deprecated.form.registry.csrf')->setPrivate(true); + $container->setParameter('form.type_extension.csrf.enabled', true); $container->setParameter('form.type_extension.csrf.field_name', $config['form']['csrf_protection']['field_name']); } else { @@ -419,6 +465,9 @@ private function registerEsiConfiguration(array $config, ContainerBuilder $conta } $loader->load('esi.xml'); + + $container->getDefinition('esi')->setPrivate(true); + $container->getDefinition('esi_listener')->setPrivate(true); } /** @@ -437,6 +486,9 @@ private function registerSsiConfiguration(array $config, ContainerBuilder $conta } $loader->load('ssi.xml'); + + $container->getDefinition('ssi')->setPrivate(true); + $container->getDefinition('ssi_listener')->setPrivate(true); } /** @@ -480,8 +532,16 @@ private function registerProfilerConfiguration(array $config, ContainerBuilder $ $loader->load('collectors.xml'); $loader->load('cache_debug.xml'); + $container->getDefinition('data_collector.request')->setPrivate(true); + $container->getDefinition('data_collector.router')->setPrivate(true); + $container->getDefinition('profiler_listener')->setPrivate(true); + if ($this->formConfigEnabled) { $loader->load('form_debug.xml'); + + $container->getDefinition('form.resolved_type_factory')->setPrivate(true); + $container->getDefinition('data_collector.form.extractor')->setPrivate(true); + $container->getDefinition('data_collector.form')->setPrivate(true); } if ($this->validatorConfigEnabled) { @@ -490,6 +550,9 @@ private function registerProfilerConfiguration(array $config, ContainerBuilder $ if ($this->translationConfigEnabled) { $loader->load('translation_debug.xml'); + + $container->getDefinition('data_collector.translation')->setPrivate(true); + $container->getDefinition('translator.data_collector')->setDecoratedService('translator'); } @@ -506,7 +569,7 @@ private function registerProfilerConfiguration(array $config, ContainerBuilder $ if ($this->isConfigEnabled($container, $config['matcher'])) { if (isset($config['matcher']['service'])) { - $container->setAlias('profiler.request_matcher', $config['matcher']['service']); + $container->setAlias('profiler.request_matcher', $config['matcher']['service'])->setPrivate(true); } elseif (isset($config['matcher']['ip']) || isset($config['matcher']['path']) || isset($config['matcher']['ips'])) { $definition = $container->register('profiler.request_matcher', 'Symfony\\Component\\HttpFoundation\\RequestMatcher'); $definition->setPublic(false); @@ -553,6 +616,10 @@ private function registerWorkflowConfiguration(array $config, ContainerBuilder $ $loader->load('workflow.xml'); + $container->getDefinition('workflow.marking_store.multiple_state')->setPrivate(true); + $container->getDefinition('workflow.marking_store.single_state')->setPrivate(true); + $container->getDefinition('workflow.registry')->setPrivate(true); + $registryDefinition = $container->getDefinition('workflow.registry'); foreach ($config['workflows'] as $name => $workflow) { @@ -626,6 +693,7 @@ private function registerWorkflowConfiguration(array $config, ContainerBuilder $ // Enable the AuditTrail if ($workflow['audit_trail']['enabled']) { $listener = new Definition(Workflow\EventListener\AuditTrailListener::class); + $listener->setPrivate(true); $listener->addTag('monolog.logger', array('channel' => 'workflow')); $listener->addTag('kernel.event_listener', array('event' => sprintf('workflow.%s.leave', $name), 'method' => 'onLeave')); $listener->addTag('kernel.event_listener', array('event' => sprintf('workflow.%s.transition', $name), 'method' => 'onTransition')); @@ -636,6 +704,7 @@ private function registerWorkflowConfiguration(array $config, ContainerBuilder $ // Add Guard Listener $guard = new Definition(Workflow\EventListener\GuardListener::class); + $guard->setPrivate(true); $configuration = array(); foreach ($workflow['transitions'] as $transitionName => $config) { if (!isset($config['guard'])) { @@ -681,8 +750,10 @@ private function registerDebugConfiguration(array $config, ContainerBuilder $con { $loader->load('debug_prod.xml'); + $container->getDefinition('debug.debug_handlers_listener')->setPrivate(true); + if (class_exists(Stopwatch::class)) { - $container->register('debug.stopwatch', Stopwatch::class)->addArgument(true); + $container->register('debug.stopwatch', Stopwatch::class)->addArgument(true)->setPrivate(true); $container->setAlias(Stopwatch::class, new Alias('debug.stopwatch', false)); } @@ -694,6 +765,9 @@ private function registerDebugConfiguration(array $config, ContainerBuilder $con if ($debug && class_exists(Stopwatch::class)) { $loader->load('debug.xml'); + $container->getDefinition('debug.event_dispatcher')->setPrivate(true); + $container->getDefinition('debug.controller_resolver')->setPrivate(true); + $container->getDefinition('debug.argument_resolver')->setPrivate(true); } $definition = $container->findDefinition('debug.debug_handlers_listener'); @@ -734,6 +808,8 @@ private function registerRouterConfiguration(array $config, ContainerBuilder $co $loader->load('routing.xml'); + $container->getDefinition('router_listener')->setPrivate(true); + $container->setParameter('router.resource', $config['resource']); $container->setParameter('router.cache_class_prefix', $container->getParameter('kernel.container_class')); $router = $container->findDefinition('router.default'); @@ -792,8 +868,14 @@ private function registerSessionConfiguration(array $config, ContainerBuilder $c { $loader->load('session.xml'); + $container->getDefinition('session.storage.native')->setPrivate(true); + $container->getDefinition('session.storage.php_bridge')->setPrivate(true); + $container->getDefinition('session_listener')->setPrivate(true); + $container->getDefinition('session.save_listener')->setPrivate(true); + $container->getAlias('session.storage.filesystem')->setPrivate(true); + // session storage - $container->setAlias('session.storage', $config['storage_id']); + $container->setAlias('session.storage', $config['storage_id'])->setPrivate(true); $options = array(); foreach (array('name', 'cookie_lifetime', 'cookie_path', 'cookie_domain', 'cookie_secure', 'cookie_httponly', 'use_cookies', 'gc_maxlifetime', 'gc_probability', 'gc_divisor', 'use_strict_mode') as $key) { if (isset($config[$key])) { @@ -816,7 +898,7 @@ private function registerSessionConfiguration(array $config, ContainerBuilder $c $handlerId = 'session.handler.write_check'; } - $container->setAlias('session.handler', $handlerId); + $container->setAlias('session.handler', $handlerId)->setPrivate(true); } $container->setParameter('session.save_path', $config['save_path']); @@ -853,6 +935,9 @@ private function registerRequestConfiguration(array $config, ContainerBuilder $c { if ($config['formats']) { $loader->load('request.xml'); + + $container->getDefinition('request.add_request_formats_listener')->setPrivate(true); + $container ->getDefinition('request.add_request_formats_listener') ->replaceArgument(0, $config['formats']) @@ -871,6 +956,9 @@ private function registerTemplatingConfiguration(array $config, ContainerBuilder { $loader->load('templating.xml'); + $container->getDefinition('templating.name_parser')->setPrivate(true); + $container->getDefinition('templating.filename_parser')->setPrivate(true); + $container->setParameter('fragment.renderer.hinclude.global_template', $config['hinclude_default_template']); if ($container->getParameter('kernel.debug')) { @@ -889,10 +977,10 @@ private function registerTemplatingConfiguration(array $config, ContainerBuilder // Use a delegation unless only a single loader was registered if (1 === count($loaders)) { - $container->setAlias('templating.loader', (string) reset($loaders)); + $container->setAlias('templating.loader', (string) reset($loaders))->setPrivate(true); } else { $container->getDefinition('templating.loader.chain')->addArgument($loaders); - $container->setAlias('templating.loader', 'templating.loader.chain'); + $container->setAlias('templating.loader', 'templating.loader.chain')->setPrivate(true); } } @@ -937,13 +1025,25 @@ private function registerTemplatingConfiguration(array $config, ContainerBuilder if (in_array('php', $config['engines'], true)) { $loader->load('templating_php.xml'); + $container->getDefinition('templating.helper.slots')->setPrivate(true); + $container->getDefinition('templating.helper.request')->setPrivate(true); + $container->getDefinition('templating.helper.session')->setPrivate(true); + $container->getDefinition('templating.helper.router')->setPrivate(true); + $container->getDefinition('templating.helper.assets')->setPrivate(true); + $container->getDefinition('templating.helper.actions')->setPrivate(true); + $container->getDefinition('templating.helper.code')->setPrivate(true); + $container->getDefinition('templating.helper.translator')->setPrivate(true); + $container->getDefinition('templating.helper.form')->setPrivate(true); + $container->getDefinition('templating.helper.stopwatch')->setPrivate(true); + $container->getDefinition('templating.globals')->setPrivate(true); + $container->setParameter('templating.helper.form.resources', $config['form']['resources']); if ($container->getParameter('kernel.debug') && class_exists(Stopwatch::class)) { $loader->load('templating_debug.xml'); $container->setDefinition('templating.engine.php', $container->findDefinition('debug.templating.engine.php')); - $container->setAlias('debug.templating.engine.php', 'templating.engine.php'); + $container->setAlias('debug.templating.engine.php', 'templating.engine.php')->setPrivate(true); } if (\PHP_VERSION_ID < 70000) { @@ -977,6 +1077,12 @@ private function registerAssetsConfiguration(array $config, ContainerBuilder $co { $loader->load('assets.xml'); + $container->getDefinition('assets.packages')->setPrivate(true); + $container->getDefinition('assets.context')->setPrivate(true); + $container->getDefinition('assets.path_package')->setPrivate(true); + $container->getDefinition('assets.url_package')->setPrivate(true); + $container->getDefinition('assets.static_version_strategy')->setPrivate(true); + $defaultVersion = null; if ($config['version_strategy']) { @@ -1073,6 +1179,35 @@ private function registerTranslatorConfiguration(array $config, ContainerBuilder $loader->load('translation.xml'); + $container->getDefinition('translator.default')->setPrivate(true); + $container->getDefinition('translation.loader.php')->setPrivate(true); + $container->getDefinition('translation.loader.yml')->setPrivate(true); + $container->getDefinition('translation.loader.xliff')->setPrivate(true); + $container->getDefinition('translation.loader.po')->setPrivate(true); + $container->getDefinition('translation.loader.mo')->setPrivate(true); + $container->getDefinition('translation.loader.qt')->setPrivate(true); + $container->getDefinition('translation.loader.csv')->setPrivate(true); + $container->getDefinition('translation.loader.res')->setPrivate(true); + $container->getDefinition('translation.loader.dat')->setPrivate(true); + $container->getDefinition('translation.loader.ini')->setPrivate(true); + $container->getDefinition('translation.loader.json')->setPrivate(true); + $container->getDefinition('translation.dumper.php')->setPrivate(true); + $container->getDefinition('translation.dumper.xliff')->setPrivate(true); + $container->getDefinition('translation.dumper.po')->setPrivate(true); + $container->getDefinition('translation.dumper.mo')->setPrivate(true); + $container->getDefinition('translation.dumper.yml')->setPrivate(true); + $container->getDefinition('translation.dumper.qt')->setPrivate(true); + $container->getDefinition('translation.dumper.csv')->setPrivate(true); + $container->getDefinition('translation.dumper.ini')->setPrivate(true); + $container->getDefinition('translation.dumper.json')->setPrivate(true); + $container->getDefinition('translation.dumper.res')->setPrivate(true); + $container->getDefinition('translation.extractor.php')->setPrivate(true); + $container->getDefinition('translator_listener')->setPrivate(true); + $container->getDefinition('translation.loader')->setPrivate(true); + $container->getDefinition('translation.reader')->setPrivate(true); + $container->getDefinition('translation.extractor')->setPrivate(true); + $container->getDefinition('translation.writer')->setPrivate(true); + // Use the "real" translator instead of the identity default $container->setAlias('translator', 'translator.default'); $container->setAlias('translator.formatter', new Alias($config['formatter'], false)); @@ -1169,6 +1304,10 @@ private function registerValidationConfiguration(array $config, ContainerBuilder $loader->load('validator.xml'); + $container->getDefinition('validator.builder')->setPrivate(true); + $container->getDefinition('validator.expression')->setPrivate(true); + $container->getDefinition('validator.email')->setPrivate(true); + $validatorBuilder = $container->getDefinition('validator.builder'); $container->setParameter('validator.translation_domain', $config['translation_domain']); @@ -1282,6 +1421,8 @@ private function registerAnnotationsConfiguration(array $config, ContainerBuilde $loader->load('annotations.xml'); + $container->getAlias('annotation_reader')->setPrivate(true); + if ('none' !== $config['cache']) { if (!class_exists('Doctrine\Common\Cache\CacheProvider')) { throw new LogicException('Annotations cannot be enabled as the Doctrine Cache library is not installed.'); @@ -1408,6 +1549,9 @@ private function registerSerializerConfiguration(array $config, ContainerBuilder } $loader->load('serializer.xml'); + + $container->getDefinition('serializer.mapping.cache.symfony')->setPrivate(true); + $chainLoader = $container->getDefinition('serializer.mapping.chain_loader'); $serializerLoaders = array(); @@ -1498,8 +1642,11 @@ private function registerPropertyInfoConfiguration(array $config, ContainerBuild { $loader->load('property_info.xml'); + $container->getDefinition('property_info')->setPrivate(true); + if (interface_exists('phpDocumentor\Reflection\DocBlockFactoryInterface')) { $definition = $container->register('property_info.php_doc_extractor', 'Symfony\Component\PropertyInfo\Extractor\PhpDocExtractor'); + $definition->setPrivate(true); $definition->addTag('property_info.description_extractor', array('priority' => -1000)); $definition->addTag('property_info.type_extractor', array('priority' => -1001)); } diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/annotations.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/annotations.xml index 15bf002954199..6b290d7763867 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/annotations.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/annotations.xml @@ -49,7 +49,7 @@ - + diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/assets.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/assets.xml index e714e2834c5fc..9584afdb134ed 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/assets.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/assets.xml @@ -7,7 +7,7 @@ - + @@ -17,23 +17,23 @@ - + - + - + - + diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/cache.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/cache.xml index e0d5788bc4879..cbed70e4e11a1 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/cache.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/cache.xml @@ -27,7 +27,7 @@ - + @@ -38,7 +38,7 @@ - + @@ -49,7 +49,7 @@ - + @@ -60,7 +60,7 @@ - + @@ -71,14 +71,14 @@ - + 0 - + @@ -89,7 +89,7 @@ - + @@ -100,7 +100,7 @@ - + diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/collectors.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/collectors.xml index 8cd0c3ced0d8b..a1b73097e0bd7 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/collectors.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/collectors.xml @@ -12,7 +12,7 @@ - + @@ -47,7 +47,7 @@ - + diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/debug.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/debug.xml index aa988dc5b93cf..9aa1367f585e1 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/debug.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/debug.xml @@ -7,20 +7,20 @@ - + - + - + diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/debug_prod.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/debug_prod.xml index fc4efe4e02253..28a8a8a2c04b1 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/debug_prod.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/debug_prod.xml @@ -11,7 +11,7 @@ - + null diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/esi.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/esi.xml index 8925acb1ac8f0..cd9fa061dd240 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/esi.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/esi.xml @@ -7,9 +7,9 @@ - + - + diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/form.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/form.xml index 642d8d4ee7bfc..211bccb688b49 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/form.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/form.xml @@ -8,11 +8,11 @@ - + - + - + - + diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/fragment_listener.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/fragment_listener.xml index a9628ad5609e5..49fbbbaf388cb 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/fragment_listener.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/fragment_listener.xml @@ -7,7 +7,7 @@ - + %fragment.path% diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/fragment_renderer.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/fragment_renderer.xml index a24d2880ea823..3f518522e153c 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/fragment_renderer.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/fragment_renderer.xml @@ -12,27 +12,27 @@ - + %kernel.debug% - + %fragment.path% - + %fragment.renderer.hinclude.global_template% %fragment.path% - + @@ -40,7 +40,7 @@ %fragment.path% - + diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/profiling.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/profiling.xml index c409e981de7bb..635dc8d2b3ed0 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/profiling.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/profiling.xml @@ -17,7 +17,7 @@ %profiler.storage.dsn% - + diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/property_access.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/property_access.xml index 15e684b62ae2d..91924e5972d8e 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/property_access.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/property_access.xml @@ -7,7 +7,7 @@ - + diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/property_info.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/property_info.xml index 8e0498e4f68b3..a893127276564 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/property_info.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/property_info.xml @@ -7,7 +7,7 @@ - + diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/request.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/request.xml index b9e9e9c7e058b..9cb049c01735f 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/request.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/request.xml @@ -7,7 +7,7 @@ - + diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/routing.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/routing.xml index 22bd38f8b80d6..6856512e20349 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/routing.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/routing.xml @@ -102,7 +102,7 @@ - + diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/serializer.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/serializer.xml index d350091a01820..924ebf18d8b0f 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/serializer.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/serializer.xml @@ -60,7 +60,7 @@ - + %serializer.mapping.cache.file% diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/services.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/services.xml index cecbdf8d85f2a..9ff2c259ee43b 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/services.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/services.xml @@ -27,7 +27,7 @@ - + Symfony\Component\HttpFoundation\ParameterBag Symfony\Component\HttpFoundation\HeaderBag @@ -49,7 +49,7 @@ - + %kernel.root_dir%/Resources @@ -58,11 +58,11 @@ - + %kernel.secret% - + diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/session.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/session.xml index 2a930075bbf54..0cb86362a231e 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/session.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/session.xml @@ -26,13 +26,13 @@ %session.metadata.update_threshold% - + %session.storage.options% - + @@ -53,7 +53,7 @@ - + @@ -65,11 +65,11 @@ - + - + diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/ssi.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/ssi.xml index 4df799fcf5fe3..8a3c0cb593bff 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/ssi.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/ssi.xml @@ -7,9 +7,9 @@ - + - + diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/templating.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/templating.xml index 1de55085c84f5..68b0eeefd7ccf 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/templating.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/templating.xml @@ -12,11 +12,11 @@ - + - + diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/templating_php.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/templating_php.xml index 5eb7233592f65..5d4aa8625eefd 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/templating_php.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/templating_php.xml @@ -20,53 +20,53 @@ - + - + - + - + - + - + - + %kernel.root_dir% %kernel.charset% - + - + - + @@ -81,7 +81,7 @@ - + diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/test.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/test.xml index 2b75d4c5b7016..ff109c4cd2420 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/test.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/test.xml @@ -18,11 +18,11 @@ - + - + - + diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/translation.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/translation.xml index d8c8f1e030111..b1f478ac90bac 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/translation.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/translation.xml @@ -7,7 +7,7 @@ - + %kernel.default_locale% @@ -32,67 +32,67 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -101,38 +101,38 @@ - + - + - + - + - + - + - + The "%service_id%" service is deprecated since Symfony 3.4 and will be removed in 4.0. Use "translation.reader" instead. - + - + - + @@ -140,7 +140,7 @@ - + diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/translation_debug.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/translation_debug.xml index ba30db65dcb80..945f8653a524a 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/translation_debug.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/translation_debug.xml @@ -13,7 +13,7 @@ - + diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/validator.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/validator.xml index aa472d380cb33..66e7c7c23517e 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/validator.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/validator.xml @@ -17,7 +17,7 @@ - + @@ -64,11 +64,11 @@ - + - + diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/web.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/web.xml index 1eed0e92f6c21..0622c4196c104 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/web.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/web.xml @@ -51,23 +51,23 @@ - + %kernel.charset% - + - + %kernel.default_locale% - + diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/workflow.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/workflow.xml index 0a033d692afdc..d881f699f75ec 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/workflow.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/workflow.xml @@ -20,10 +20,10 @@ - - + + - + diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/CachePoolClearCommandTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/CachePoolClearCommandTest.php index a9a5959848e67..9aa0c019d58af 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/CachePoolClearCommandTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/CachePoolClearCommandTest.php @@ -58,10 +58,10 @@ public function testClearPoolWithCustomClearer() public function testCallClearer() { $tester = $this->createCommandTester(); - $tester->execute(array('pools' => array('cache.default_clearer')), array('decorated' => false)); + $tester->execute(array('pools' => array('cache.app_clearer')), array('decorated' => false)); $this->assertSame(0, $tester->getStatusCode(), 'cache:pool:clear exits with 0 in case of success'); - $this->assertContains('Calling cache clearer: cache.default_clearer', $tester->getDisplay()); + $this->assertContains('Calling cache clearer: cache.app_clearer', $tester->getDisplay()); $this->assertContains('[OK] Cache was successfully cleared.', $tester->getDisplay()); } diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/PropertyInfoTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/PropertyInfoTest.php index c02a6b84e519c..f98072ce7b39c 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/PropertyInfoTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/PropertyInfoTest.php @@ -20,7 +20,7 @@ public function testPhpDocPriority() static::bootKernel(array('test_case' => 'Serializer')); $container = static::$kernel->getContainer(); - $this->assertEquals(array(new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, new Type(Type::BUILTIN_TYPE_INT), new Type(Type::BUILTIN_TYPE_INT))), $container->get('property_info')->getTypes('Symfony\Bundle\FrameworkBundle\Tests\Functional\Dummy', 'codes')); + $this->assertEquals(array(new Type(Type::BUILTIN_TYPE_ARRAY, false, null, true, new Type(Type::BUILTIN_TYPE_INT), new Type(Type::BUILTIN_TYPE_INT))), $container->get('test.property_info')->getTypes('Symfony\Bundle\FrameworkBundle\Tests\Functional\Dummy', 'codes')); } } diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/Serializer/config.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/Serializer/config.yml index cac135c315d00..fe3de69299946 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/Serializer/config.yml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/Serializer/config.yml @@ -1,6 +1,9 @@ imports: - { resource: ../config/default.yml } +services: + test.property_info: '@property_info' + framework: serializer: { enabled: true } property_info: { enabled: true } diff --git a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php index 73a1cef128dd8..95e382b7b4226 100644 --- a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php +++ b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php @@ -73,8 +73,19 @@ public function load(array $configs, ContainerBuilder $container) $loader->load('collectors.xml'); $loader->load('guard.xml'); + $container->getDefinition('security.authentication.guard_handler')->setPrivate(true); + $container->getDefinition('security.firewall')->setPrivate(true); + $container->getDefinition('security.firewall.context')->setPrivate(true); + $container->getDefinition('security.validator.user_password')->setPrivate(true); + $container->getDefinition('security.rememberme.response_listener')->setPrivate(true); + $container->getDefinition('templating.helper.logout_url')->setPrivate(true); + $container->getDefinition('templating.helper.security')->setPrivate(true); + $container->getAlias('security.encoder_factory')->setPrivate(true); + if ($container->hasParameter('kernel.debug') && $container->getParameter('kernel.debug')) { $loader->load('security_debug.xml'); + + $container->getAlias('security.firewall')->setPrivate(true); } if (!class_exists('Symfony\Component\ExpressionLanguage\ExpressionLanguage')) { @@ -88,7 +99,7 @@ public function load(array $configs, ContainerBuilder $container) $container->setParameter('security.authentication.session_strategy.strategy', $config['session_fixation_strategy']); if (isset($config['access_decision_manager']['service'])) { - $container->setAlias('security.access.decision_manager', $config['access_decision_manager']['service']); + $container->setAlias('security.access.decision_manager', $config['access_decision_manager']['service'])->setPrivate(true); } else { $container ->getDefinition('security.access.decision_manager') @@ -151,13 +162,13 @@ private function aclLoad($config, ContainerBuilder $container) $loader->load('security_acl.xml'); if (isset($config['cache']['id'])) { - $container->setAlias('security.acl.cache', $config['cache']['id']); + $container->setAlias('security.acl.cache', $config['cache']['id'])->setPrivate(true); } $container->getDefinition('security.acl.voter.basic_permissions')->addArgument($config['voter']['allow_if_object_identity_unavailable']); // custom ACL provider if (isset($config['provider'])) { - $container->setAlias('security.acl.provider', $config['provider']); + $container->setAlias('security.acl.provider', $config['provider'])->setPrivate(true); return; } @@ -169,6 +180,10 @@ private function configureDbalAclProvider(array $config, ContainerBuilder $conta { $loader->load('security_acl_dbal.xml'); + $container->getDefinition('security.acl.dbal.schema')->setPrivate(true); + $container->getAlias('security.acl.dbal.connection')->setPrivate(true); + $container->getAlias('security.acl.provider')->setPrivate(true); + if (null !== $config['connection']) { $container->setAlias('security.acl.dbal.connection', sprintf('doctrine.dbal.%s_connection', $config['connection'])); } diff --git a/src/Symfony/Bundle/SecurityBundle/Resources/config/guard.xml b/src/Symfony/Bundle/SecurityBundle/Resources/config/guard.xml index 77a09f24f8a95..ce6021823ba74 100644 --- a/src/Symfony/Bundle/SecurityBundle/Resources/config/guard.xml +++ b/src/Symfony/Bundle/SecurityBundle/Resources/config/guard.xml @@ -9,7 +9,6 @@ diff --git a/src/Symfony/Bundle/SecurityBundle/Resources/config/security.xml b/src/Symfony/Bundle/SecurityBundle/Resources/config/security.xml index 9b31ae84439d7..79a4866d8cbe4 100644 --- a/src/Symfony/Bundle/SecurityBundle/Resources/config/security.xml +++ b/src/Symfony/Bundle/SecurityBundle/Resources/config/security.xml @@ -51,7 +51,7 @@ - + @@ -105,7 +105,7 @@ - + @@ -118,7 +118,7 @@ - + @@ -169,7 +169,7 @@ - + diff --git a/src/Symfony/Bundle/SecurityBundle/Resources/config/security_acl_dbal.xml b/src/Symfony/Bundle/SecurityBundle/Resources/config/security_acl_dbal.xml index 1399be3c12bde..c1ed332654fe0 100644 --- a/src/Symfony/Bundle/SecurityBundle/Resources/config/security_acl_dbal.xml +++ b/src/Symfony/Bundle/SecurityBundle/Resources/config/security_acl_dbal.xml @@ -7,7 +7,7 @@ - + @@ -22,7 +22,7 @@ - + %security.acl.dbal.class_table_name% %security.acl.dbal.entry_table_name% @@ -36,7 +36,7 @@ - + diff --git a/src/Symfony/Bundle/SecurityBundle/Resources/config/security_debug.xml b/src/Symfony/Bundle/SecurityBundle/Resources/config/security_debug.xml index 6087f9ee5b19e..d3b7b936ea69a 100644 --- a/src/Symfony/Bundle/SecurityBundle/Resources/config/security_debug.xml +++ b/src/Symfony/Bundle/SecurityBundle/Resources/config/security_debug.xml @@ -18,6 +18,6 @@ - + diff --git a/src/Symfony/Bundle/SecurityBundle/Resources/config/security_rememberme.xml b/src/Symfony/Bundle/SecurityBundle/Resources/config/security_rememberme.xml index 1f0e288687606..c05cdcaa2d290 100644 --- a/src/Symfony/Bundle/SecurityBundle/Resources/config/security_rememberme.xml +++ b/src/Symfony/Bundle/SecurityBundle/Resources/config/security_rememberme.xml @@ -45,7 +45,7 @@ public="false" abstract="true" /> - + diff --git a/src/Symfony/Bundle/SecurityBundle/Resources/config/templating_php.xml b/src/Symfony/Bundle/SecurityBundle/Resources/config/templating_php.xml index b0676e2fc15b1..6f2ec1cbf977e 100644 --- a/src/Symfony/Bundle/SecurityBundle/Resources/config/templating_php.xml +++ b/src/Symfony/Bundle/SecurityBundle/Resources/config/templating_php.xml @@ -7,12 +7,12 @@ - + - + diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/SetAclCommandTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/SetAclCommandTest.php index 5ecbf47078afe..803109ec2097c 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/SetAclCommandTest.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/SetAclCommandTest.php @@ -67,7 +67,7 @@ public function testSetAclUser() $permissionMap = new BasicPermissionMap(); /** @var \Symfony\Component\Security\Acl\Model\AclProviderInterface $aclProvider */ - $aclProvider = $application->getKernel()->getContainer()->get('security.acl.provider'); + $aclProvider = $application->getKernel()->getContainer()->get('test.security.acl.provider'); $acl = $aclProvider->findAcl($objectIdentity, array($securityIdentity1)); $this->assertTrue($acl->isGranted($permissionMap->getMasks($grantedPermission1, null), array($securityIdentity1))); @@ -95,7 +95,7 @@ public function testSetAclRole() $role = 'ROLE_ADMIN'; $application = $this->getApplication(); - $application->add(new SetAclCommand($application->getKernel()->getContainer()->get('security.acl.provider'))); + $application->add(new SetAclCommand($application->getKernel()->getContainer()->get('test.security.acl.provider'))); $setAclCommand = $application->find('acl:set'); $setAclCommandTester = new CommandTester($setAclCommand); @@ -111,7 +111,7 @@ public function testSetAclRole() $permissionMap = new BasicPermissionMap(); /** @var \Symfony\Component\Security\Acl\Model\AclProviderInterface $aclProvider */ - $aclProvider = $application->getKernel()->getContainer()->get('security.acl.provider'); + $aclProvider = $application->getKernel()->getContainer()->get('test.security.acl.provider'); $acl = $aclProvider->findAcl($objectIdentity, array($roleSecurityIdentity, $userSecurityIdentity)); $this->assertTrue($acl->isGranted($permissionMap->getMasks($grantedPermission, null), array($roleSecurityIdentity))); @@ -137,7 +137,7 @@ public function testSetAclClassScope() $role = 'ROLE_USER'; $application = $this->getApplication(); - $application->add(new SetAclCommand($application->getKernel()->getContainer()->get('security.acl.provider'))); + $application->add(new SetAclCommand($application->getKernel()->getContainer()->get('test.security.acl.provider'))); $setAclCommand = $application->find('acl:set'); $setAclCommandTester = new CommandTester($setAclCommand); @@ -154,7 +154,7 @@ public function testSetAclClassScope() $permissionMap = new BasicPermissionMap(); /** @var \Symfony\Component\Security\Acl\Model\AclProviderInterface $aclProvider */ - $aclProvider = $application->getKernel()->getContainer()->get('security.acl.provider'); + $aclProvider = $application->getKernel()->getContainer()->get('test.security.acl.provider'); $acl1 = $aclProvider->findAcl($objectIdentity1, array($roleSecurityIdentity)); $this->assertTrue($acl1->isGranted($permissionMap->getMasks($grantedPermission, null), array($roleSecurityIdentity))); diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/Acl/config.yml b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/Acl/config.yml index 33eadbc7cdf03..49191e01d85c2 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/Acl/config.yml +++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/Acl/config.yml @@ -1,6 +1,9 @@ imports: - { resource: ./../config/framework.yml } +services: + test.security.acl.provider: '@security.acl.provider' + doctrine: dbal: driver: pdo_sqlite diff --git a/src/Symfony/Bundle/SecurityBundle/composer.json b/src/Symfony/Bundle/SecurityBundle/composer.json index 38bf0220536d5..9690cf325aa14 100644 --- a/src/Symfony/Bundle/SecurityBundle/composer.json +++ b/src/Symfony/Bundle/SecurityBundle/composer.json @@ -31,7 +31,7 @@ "symfony/dom-crawler": "~2.8|~3.0|~4.0", "symfony/event-dispatcher": "^3.3.1|~4.0", "symfony/form": "^2.8.18|^3.2.5|~4.0", - "symfony/framework-bundle": "^3.2.8|~4.0", + "symfony/framework-bundle": "^3.4|~4.0", "symfony/http-foundation": "~2.8|~3.0|~4.0", "symfony/security-acl": "~2.8|~3.0", "symfony/translation": "~2.8|~3.0|~4.0", @@ -48,6 +48,7 @@ "conflict": { "symfony/var-dumper": "<3.3", "symfony/event-dispatcher": "<3.3.1", + "symfony/framework-bundle": "<3.4", "symfony/console": "<3.4" }, "suggest": { diff --git a/src/Symfony/Bundle/TwigBundle/DependencyInjection/Compiler/TwigLoaderPass.php b/src/Symfony/Bundle/TwigBundle/DependencyInjection/Compiler/TwigLoaderPass.php index f2c1d32eec974..0f61aecc2c5b7 100644 --- a/src/Symfony/Bundle/TwigBundle/DependencyInjection/Compiler/TwigLoaderPass.php +++ b/src/Symfony/Bundle/TwigBundle/DependencyInjection/Compiler/TwigLoaderPass.php @@ -11,6 +11,7 @@ namespace Symfony\Bundle\TwigBundle\DependencyInjection\Compiler; +use Symfony\Component\DependencyInjection\Alias; use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; @@ -43,7 +44,7 @@ public function process(ContainerBuilder $container) } if (1 === $found) { - $container->setAlias('twig.loader', $id); + $container->setAlias('twig.loader', $id)->setPrivate(true); } else { $chainLoader = $container->getDefinition('twig.loader.chain'); krsort($prioritizedLoaders); @@ -54,7 +55,7 @@ public function process(ContainerBuilder $container) } } - $container->setAlias('twig.loader', 'twig.loader.chain'); + $container->setAlias('twig.loader', 'twig.loader.chain')->setPrivate(true); } } } diff --git a/src/Symfony/Bundle/TwigBundle/DependencyInjection/TwigExtension.php b/src/Symfony/Bundle/TwigBundle/DependencyInjection/TwigExtension.php index ca0c68d49b02a..f3dd1811c7f16 100644 --- a/src/Symfony/Bundle/TwigBundle/DependencyInjection/TwigExtension.php +++ b/src/Symfony/Bundle/TwigBundle/DependencyInjection/TwigExtension.php @@ -43,8 +43,15 @@ public function load(array $configs, ContainerBuilder $container) $loader = new XmlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config')); $loader->load('twig.xml'); + $container->getDefinition('twig.profile')->setPrivate(true); + $container->getDefinition('twig.runtime.httpkernel')->setPrivate(true); + $container->getDefinition('twig.translation.extractor')->setPrivate(true); + $container->getDefinition('workflow.twig_extension')->setPrivate(true); + $container->getDefinition('twig.exception_listener')->setPrivate(true); + if (class_exists('Symfony\Component\Form\Form')) { $loader->load('form.xml'); + $container->getDefinition('twig.form.renderer')->setPrivate(true); } if (interface_exists('Symfony\Component\Templating\EngineInterface')) { diff --git a/src/Symfony/Bundle/TwigBundle/Resources/config/form.xml b/src/Symfony/Bundle/TwigBundle/Resources/config/form.xml index b1cee0ae381f7..caa799bc346c0 100644 --- a/src/Symfony/Bundle/TwigBundle/Resources/config/form.xml +++ b/src/Symfony/Bundle/TwigBundle/Resources/config/form.xml @@ -18,7 +18,7 @@ - + diff --git a/src/Symfony/Bundle/TwigBundle/Resources/config/twig.xml b/src/Symfony/Bundle/TwigBundle/Resources/config/twig.xml index bf53c2b2b28f6..8c6a944603333 100644 --- a/src/Symfony/Bundle/TwigBundle/Resources/config/twig.xml +++ b/src/Symfony/Bundle/TwigBundle/Resources/config/twig.xml @@ -63,7 +63,7 @@ - + @@ -100,7 +100,7 @@ - + @@ -112,16 +112,16 @@ - + - + - + %twig.exception_listener.controller% diff --git a/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/Compiler/TwigLoaderPassTest.php b/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/Compiler/TwigLoaderPassTest.php index 10bcf3e8f66a8..6575f28c9736d 100644 --- a/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/Compiler/TwigLoaderPassTest.php +++ b/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/Compiler/TwigLoaderPassTest.php @@ -12,6 +12,7 @@ namespace Symfony\Bundle\TwigBundle\Tests\DependencyInjection\Compiler; use PHPUnit\Framework\TestCase; +use Symfony\Component\DependencyInjection\Alias; use Symfony\Component\DependencyInjection\Definition; use Symfony\Bundle\TwigBundle\DependencyInjection\Compiler\TwigLoaderPass; @@ -55,7 +56,8 @@ public function testMapperPassWithOneTaggedLoaders() ->will($this->returnValue($serviceIds)); $this->builder->expects($this->once()) ->method('setAlias') - ->with('twig.loader', 'test_loader_1'); + ->with('twig.loader', 'test_loader_1') + ->will($this->returnValue(new Alias('test_loader_1'))); $this->pass->process($this->builder); } @@ -85,7 +87,8 @@ public function testMapperPassWithTwoTaggedLoaders() ->will($this->returnValue($this->chainLoader)); $this->builder->expects($this->once()) ->method('setAlias') - ->with('twig.loader', 'twig.loader.chain'); + ->with('twig.loader', 'twig.loader.chain') + ->will($this->returnValue(new Alias('twig.loader.chain'))); $this->pass->process($this->builder); $calls = $this->chainLoader->getMethodCalls(); @@ -121,7 +124,8 @@ public function testMapperPassWithTwoTaggedLoadersWithPriority() ->will($this->returnValue($this->chainLoader)); $this->builder->expects($this->once()) ->method('setAlias') - ->with('twig.loader', 'twig.loader.chain'); + ->with('twig.loader', 'twig.loader.chain') + ->will($this->returnValue(new Alias('twig.loader.chain'))); $this->pass->process($this->builder); $calls = $this->chainLoader->getMethodCalls(); diff --git a/src/Symfony/Bundle/TwigBundle/composer.json b/src/Symfony/Bundle/TwigBundle/composer.json index 3b8ca5b99469b..3d5fff2779a10 100644 --- a/src/Symfony/Bundle/TwigBundle/composer.json +++ b/src/Symfony/Bundle/TwigBundle/composer.json @@ -26,20 +26,21 @@ "require-dev": { "symfony/asset": "~2.8|~3.0|~4.0", "symfony/stopwatch": "~2.8|~3.0|~4.0", - "symfony/dependency-injection": "~3.3|~4.0", + "symfony/dependency-injection": "~3.4|~4.0", "symfony/expression-language": "~2.8|~3.0|~4.0", "symfony/finder": "~2.8|~3.0|~4.0", "symfony/form": "~2.8|~3.0|~4.0", "symfony/routing": "~2.8|~3.0|~4.0", "symfony/templating": "~2.8|~3.0|~4.0", "symfony/yaml": "~2.8|~3.0|~4.0", - "symfony/framework-bundle": "^3.2.8|~4.0", + "symfony/framework-bundle": "^3.3|~4.0", "symfony/web-link": "~3.3|~4.0", "doctrine/annotations": "~1.0", "doctrine/cache": "~1.0" }, "conflict": { - "symfony/dependency-injection": "<3.3" + "symfony/dependency-injection": "<3.4", + "symfony/event-dispatcher": "<3.3.1" }, "autoload": { "psr-4": { "Symfony\\Bundle\\TwigBundle\\": "" }, diff --git a/src/Symfony/Bundle/WebProfilerBundle/DependencyInjection/WebProfilerExtension.php b/src/Symfony/Bundle/WebProfilerBundle/DependencyInjection/WebProfilerExtension.php index e507bf2d22b70..b0db2e3bc8f22 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/DependencyInjection/WebProfilerExtension.php +++ b/src/Symfony/Bundle/WebProfilerBundle/DependencyInjection/WebProfilerExtension.php @@ -48,6 +48,7 @@ public function load(array $configs, ContainerBuilder $container) if ($config['toolbar'] || $config['intercept_redirects']) { $loader->load('toolbar.xml'); + $container->getDefinition('web_profiler.debug_toolbar')->setPrivate(true); $container->getDefinition('web_profiler.debug_toolbar')->replaceArgument(5, $config['excluded_ajax_paths']); $container->setParameter('web_profiler.debug_toolbar.intercept_redirects', $config['intercept_redirects']); $container->setParameter('web_profiler.debug_toolbar.mode', $config['toolbar'] ? WebDebugToolbarListener::ENABLED : WebDebugToolbarListener::DISABLED); diff --git a/src/Symfony/Bundle/WebProfilerBundle/Resources/config/toolbar.xml b/src/Symfony/Bundle/WebProfilerBundle/Resources/config/toolbar.xml index 25f49fc2cd069..16a7022c6d960 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Resources/config/toolbar.xml +++ b/src/Symfony/Bundle/WebProfilerBundle/Resources/config/toolbar.xml @@ -7,7 +7,7 @@ - + %web_profiler.debug_toolbar.intercept_redirects% diff --git a/src/Symfony/Bundle/WebProfilerBundle/composer.json b/src/Symfony/Bundle/WebProfilerBundle/composer.json index 40ead3bff2564..dd2a4d728f53c 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/composer.json +++ b/src/Symfony/Bundle/WebProfilerBundle/composer.json @@ -27,13 +27,13 @@ "require-dev": { "symfony/config": "~3.4|~4.0", "symfony/console": "~2.8|~3.0|~4.0", - "symfony/dependency-injection": "~3.3|~4.0", + "symfony/dependency-injection": "~3.4|~4.0", "symfony/stopwatch": "~2.8|~3.0|~4.0" }, "conflict": { "symfony/config": "<3.4", - "symfony/dependency-injection": "<3.3", - "symfony/event-dispatcher": "<3.3", + "symfony/dependency-injection": "<3.4", + "symfony/event-dispatcher": "<3.3.1", "symfony/var-dumper": "<3.3" }, "autoload": { diff --git a/src/Symfony/Component/DependencyInjection/Alias.php b/src/Symfony/Component/DependencyInjection/Alias.php index a113f8f7f2c38..ee43bd399f92b 100644 --- a/src/Symfony/Component/DependencyInjection/Alias.php +++ b/src/Symfony/Component/DependencyInjection/Alias.php @@ -15,6 +15,7 @@ class Alias { private $id; private $public; + private $private = false; /** * @param string $id Alias identifier @@ -40,10 +41,43 @@ public function isPublic() * Sets if this Alias is public. * * @param bool $boolean If this Alias should be public + * + * @return $this */ public function setPublic($boolean) { $this->public = (bool) $boolean; + + return $this; + } + + /** + * Sets if this Alias is private. + * + * When set, the "private" state has a higher precedence than "public". + * In version 3.4, a "private" alias always remains publicly accessible, + * but triggers a deprecation notice when accessed from the container, + * so that the alias can be made really private in 4.0. + * + * @param bool $boolean + * + * @return $this + */ + public function setPrivate($boolean) + { + $this->private = (bool) $boolean; + + return $this; + } + + /** + * Whether this alias is private. + * + * @return bool + */ + public function isPrivate() + { + return $this->private; } /** diff --git a/src/Symfony/Component/DependencyInjection/Compiler/CheckDefinitionValidityPass.php b/src/Symfony/Component/DependencyInjection/Compiler/CheckDefinitionValidityPass.php index a43e0cd78f404..815dbcae4915d 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/CheckDefinitionValidityPass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/CheckDefinitionValidityPass.php @@ -39,7 +39,7 @@ public function process(ContainerBuilder $container) { foreach ($container->getDefinitions() as $id => $definition) { // synthetic service is public - if ($definition->isSynthetic() && !$definition->isPublic()) { + if ($definition->isSynthetic() && (!$definition->isPublic() || $definition->isPrivate())) { throw new RuntimeException(sprintf('A synthetic service ("%s") must be public.', $id)); } diff --git a/src/Symfony/Component/DependencyInjection/Compiler/DecoratorServicePass.php b/src/Symfony/Component/DependencyInjection/Compiler/DecoratorServicePass.php index d1fe95a0bc7a5..0e9a68e7f0026 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/DecoratorServicePass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/DecoratorServicePass.php @@ -49,6 +49,7 @@ public function process(ContainerBuilder $container) if ($container->hasAlias($inner)) { $alias = $container->getAlias($inner); $public = $alias->isPublic(); + $private = $alias->isPrivate(); $container->setAlias($renamedId, new Alias((string) $alias, false)); } else { $decoratedDefinition = $container->getDefinition($inner); @@ -57,6 +58,7 @@ public function process(ContainerBuilder $container) $definition->setAutowiringTypes($types); } $public = $decoratedDefinition->isPublic(); + $private = $decoratedDefinition->isPrivate(); $decoratedDefinition->setPublic(false); $decoratedDefinition->setTags(array()); if ($decoratedDefinition->getAutowiringTypes(false)) { @@ -65,7 +67,7 @@ public function process(ContainerBuilder $container) $container->setDefinition($renamedId, $decoratedDefinition); } - $container->setAlias($inner, new Alias($id, $public)); + $container->setAlias($inner, $id)->setPublic($public && !$private)->setPrivate($private); } } } diff --git a/src/Symfony/Component/DependencyInjection/Compiler/InlineServiceDefinitionsPass.php b/src/Symfony/Component/DependencyInjection/Compiler/InlineServiceDefinitionsPass.php index 240e1ab65527f..73f75b30a982c 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/InlineServiceDefinitionsPass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/InlineServiceDefinitionsPass.php @@ -82,7 +82,7 @@ private function isInlineableDefinition($id, Definition $definition, ServiceRefe return true; } - if ($definition->isDeprecated() || $definition->isPublic() || $definition->isLazy()) { + if ($definition->isDeprecated() || $definition->isPublic() || $definition->isPrivate() || $definition->isLazy()) { return false; } diff --git a/src/Symfony/Component/DependencyInjection/Compiler/RemovePrivateAliasesPass.php b/src/Symfony/Component/DependencyInjection/Compiler/RemovePrivateAliasesPass.php index 5d6d51d6916f3..529dc9e5b37a3 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/RemovePrivateAliasesPass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/RemovePrivateAliasesPass.php @@ -30,7 +30,7 @@ class RemovePrivateAliasesPass implements CompilerPassInterface public function process(ContainerBuilder $container) { foreach ($container->getAliases() as $id => $alias) { - if ($alias->isPublic()) { + if ($alias->isPublic() || $alias->isPrivate()) { continue; } diff --git a/src/Symfony/Component/DependencyInjection/Compiler/RemoveUnusedDefinitionsPass.php b/src/Symfony/Component/DependencyInjection/Compiler/RemoveUnusedDefinitionsPass.php index a8a01be6d5291..7fcf6cc634283 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/RemoveUnusedDefinitionsPass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/RemoveUnusedDefinitionsPass.php @@ -41,7 +41,7 @@ public function process(ContainerBuilder $container) $hasChanged = false; foreach ($container->getDefinitions() as $id => $definition) { - if ($definition->isPublic()) { + if ($definition->isPublic() || $definition->isPrivate()) { continue; } @@ -68,7 +68,8 @@ public function process(ContainerBuilder $container) if (1 === count($referencingAliases) && false === $isReferenced) { $container->setDefinition((string) reset($referencingAliases), $definition); - $definition->setPublic(true); + $definition->setPrivate(reset($referencingAliases)->isPrivate()); + $definition->setPublic(!$definition->isPrivate()); $container->removeDefinition($id); $container->log($this, sprintf('Removed service "%s"; reason: replaces alias %s.', $id, reset($referencingAliases))); } elseif (0 === count($referencingAliases) && false === $isReferenced) { diff --git a/src/Symfony/Component/DependencyInjection/Compiler/ReplaceAliasByActualDefinitionPass.php b/src/Symfony/Component/DependencyInjection/Compiler/ReplaceAliasByActualDefinitionPass.php index 30a8f5d048f9a..124bd08b6f92c 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/ReplaceAliasByActualDefinitionPass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/ReplaceAliasByActualDefinitionPass.php @@ -58,11 +58,12 @@ public function process(ContainerBuilder $container) } catch (InvalidArgumentException $e) { throw new InvalidArgumentException(sprintf('Unable to replace alias "%s" with actual definition "%s".', $definitionId, $targetId), null, $e); } - if ($definition->isPublic()) { + if ($definition->isPublic() || $definition->isPrivate()) { continue; } // Remove private definition and schedule for replacement - $definition->setPublic(true); + $definition->setPublic(!$target->isPrivate()); + $definition->setPrivate($target->isPrivate()); $container->setDefinition($definitionId, $definition); $container->removeDefinition($targetId); $replacements[$targetId] = $definitionId; diff --git a/src/Symfony/Component/DependencyInjection/Compiler/ResolveChildDefinitionsPass.php b/src/Symfony/Component/DependencyInjection/Compiler/ResolveChildDefinitionsPass.php index 4e09ae630f52c..7625377793769 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/ResolveChildDefinitionsPass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/ResolveChildDefinitionsPass.php @@ -12,6 +12,7 @@ namespace Symfony\Component\DependencyInjection\Compiler; use Symfony\Component\DependencyInjection\ChildDefinition; +use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\DependencyInjection\Exception\ExceptionInterface; use Symfony\Component\DependencyInjection\Exception\RuntimeException; @@ -25,6 +26,26 @@ */ class ResolveChildDefinitionsPass extends AbstractRecursivePass { + /** + * {@inheritdoc} + */ + public function process(ContainerBuilder $container) + { + parent::process($container); + + foreach ($container->getDefinitions() as $definition) { + if ($definition->isPrivate()) { + $definition->setPublic(false); + } + } + + foreach ($container->getAliases() as $alias) { + if ($alias->isPrivate()) { + $alias->setPublic(false); + } + } + } + protected function processValue($value, $isRoot = false) { if (!$value instanceof Definition) { @@ -121,6 +142,8 @@ private function doResolveDefinition(ChildDefinition $definition) } if (isset($changes['public'])) { $def->setPublic($definition->isPublic()); + } else { + $def->setPrivate($definition->isPrivate() || $parentDef->isPrivate()); } if (isset($changes['lazy'])) { $def->setLazy($definition->isLazy()); diff --git a/src/Symfony/Component/DependencyInjection/Compiler/ResolveReferencesToAliasesPass.php b/src/Symfony/Component/DependencyInjection/Compiler/ResolveReferencesToAliasesPass.php index 6e79faba43f04..6946969a2c06f 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/ResolveReferencesToAliasesPass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/ResolveReferencesToAliasesPass.php @@ -51,7 +51,7 @@ public function process(ContainerBuilder $container) foreach ($container->getAliases() as $id => $alias) { $aliasId = (string) $alias; if ($aliasId !== $defId = $this->getDefinitionId($aliasId)) { - $container->setAlias($id, new Alias($defId, $alias->isPublic())); + $container->setAlias($id, $defId)->setPublic($alias->isPublic() && !$alias->isPrivate())->setPrivate($alias->isPrivate()); } } } diff --git a/src/Symfony/Component/DependencyInjection/ContainerBuilder.php b/src/Symfony/Component/DependencyInjection/ContainerBuilder.php index 63a7c2b33176b..f053694e9715d 100644 --- a/src/Symfony/Component/DependencyInjection/ContainerBuilder.php +++ b/src/Symfony/Component/DependencyInjection/ContainerBuilder.php @@ -806,6 +806,8 @@ public function setAliases(array $aliases) * @param string $alias The alias to create * @param string|Alias $id The service to alias * + * @return Alias + * * @throws InvalidArgumentException if the id is not a string or an Alias * @throws InvalidArgumentException if the alias is for itself */ @@ -825,7 +827,7 @@ public function setAlias($alias, $id) unset($this->definitions[$alias]); - $this->aliasDefinitions[$alias] = $id; + return $this->aliasDefinitions[$alias] = $id; } /** diff --git a/src/Symfony/Component/DependencyInjection/Definition.php b/src/Symfony/Component/DependencyInjection/Definition.php index e3ff8e5411ddc..2cfa3f9f481c6 100644 --- a/src/Symfony/Component/DependencyInjection/Definition.php +++ b/src/Symfony/Component/DependencyInjection/Definition.php @@ -35,6 +35,7 @@ class Definition private $configurator; private $tags = array(); private $public = true; + private $private = false; private $synthetic = false; private $abstract = false; private $lazy = false; @@ -616,6 +617,35 @@ public function isPublic() return $this->public; } + /** + * Sets if this service is private. + * + * When set, the "private" state has a higher precedence than "public". + * In version 3.4, a "private" service always remains publicly accessible, + * but triggers a deprecation notice when accessed from the container, + * so that the service can be made really private in 4.0. + * + * @param bool $boolean + * + * @return $this + */ + public function setPrivate($boolean) + { + $this->private = (bool) $boolean; + + return $this; + } + + /** + * Whether this service is private. + * + * @return bool + */ + public function isPrivate() + { + return $this->private; + } + /** * Sets the lazy flag of this service. * diff --git a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php index 87835ee44008e..f32187b1c1bb4 100644 --- a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php +++ b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php @@ -1040,11 +1040,17 @@ private function addFileMap() */ private function addPrivateServices() { - if (!$definitions = $this->container->getDefinitions()) { - return ''; + $code = ''; + + $aliases = $this->container->getAliases(); + ksort($aliases); + foreach ($aliases as $id => $alias) { + if ($alias->isPrivate()) { + $code .= ' '.$this->export($id)." => true,\n"; + } } - $code = ''; + $definitions = $this->container->getDefinitions(); ksort($definitions); foreach ($definitions as $id => $definition) { if (!$definition->isPublic()) { diff --git a/src/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveChildDefinitionsPassTest.php b/src/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveChildDefinitionsPassTest.php index 23a1915fd777c..cb9a879a05d48 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveChildDefinitionsPassTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveChildDefinitionsPassTest.php @@ -397,6 +397,26 @@ public function testSetAutoconfiguredOnServiceIsParent() $this->assertFalse($container->getDefinition('child1')->isAutoconfigured()); } + public function testPrivateHasHigherPrecedenceThanPublic() + { + $container = new ContainerBuilder(); + + $container->register('foo', 'stdClass') + ->setPrivate(true) + ->setPublic(true) + ; + + $container->setAlias('bar', 'foo') + ->setPrivate(false) + ->setPublic(false) + ; + + $this->process($container); + + $this->assertFalse($container->getDefinition('foo')->isPublic()); + $this->assertFalse($container->getAlias('bar')->isPublic()); + } + /** * @group legacy */ diff --git a/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php b/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php index ac8aee2fc596c..4ea8290cfc725 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php @@ -778,6 +778,52 @@ public function testDumpHandlesLiteralClassWithRootNamespace() $this->assertInstanceOf('stdClass', $container->get('foo')); } + /** + * @group legacy + * @expectedDeprecation Requesting the "private" private service is deprecated since Symfony 3.2 and won't be supported anymore in Symfony 4.0. + * @expectedDeprecation Requesting the "private_alias" private service is deprecated since Symfony 3.2 and won't be supported anymore in Symfony 4.0. + * @expectedDeprecation Requesting the "decorated_private" private service is deprecated since Symfony 3.2 and won't be supported anymore in Symfony 4.0. + * @expectedDeprecation Requesting the "decorated_private_alias" private service is deprecated since Symfony 3.2 and won't be supported anymore in Symfony 4.0. + * @expectedDeprecation Requesting the "private_not_inlined" private service is deprecated since Symfony 3.2 and won't be supported anymore in Symfony 4.0. + * @expectedDeprecation Requesting the "private_not_removed" private service is deprecated since Symfony 3.2 and won't be supported anymore in Symfony 4.0. + * @expectedDeprecation Requesting the "private_child" private service is deprecated since Symfony 3.2 and won't be supported anymore in Symfony 4.0. + * @expectedDeprecation Requesting the "private_parent" private service is deprecated since Symfony 3.2 and won't be supported anymore in Symfony 4.0. + */ + public function testLegacyPrivateServices() + { + $container = new ContainerBuilder(); + $loader = new YamlFileLoader($container, new FileLocator(self::$fixturesPath.'/yaml')); + $loader->load('services_legacy_privates.yml'); + + $container->getDefinition('private')->setPrivate(true); + $container->getDefinition('private_not_inlined')->setPrivate(true); + $container->getDefinition('private_not_removed')->setPrivate(true); + $container->getDefinition('decorated_private')->setPrivate(true); + $container->getDefinition('private_child')->setPrivate(true); + $container->getAlias('decorated_private_alias')->setPrivate(true); + $container->getAlias('private_alias')->setPrivate(true); + + $container->compile(); + $dumper = new PhpDumper($container); + + $this->assertStringEqualsFile(self::$fixturesPath.'/php/services_legacy_privates.php', $dumper->dump(array('class' => 'Symfony_DI_PhpDumper_Test_Legacy_Privates', 'file' => self::$fixturesPath.'/php/services_legacy_privates.php'))); + + require self::$fixturesPath.'/php/services_legacy_privates.php'; + + $container = new \Symfony_DI_PhpDumper_Test_Legacy_Privates(); + + $container->get('private'); + $container->get('private_alias'); + $container->get('alias_to_private'); + $container->get('decorated_private'); + $container->get('decorated_private_alias'); + $container->get('private_not_inlined'); + $container->get('private_not_removed'); + $container->get('private_child'); + $container->get('private_parent'); + $container->get('public_child'); + } + /** * This test checks the trigger of a deprecation note and should not be removed in major releases. * diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_legacy_privates.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_legacy_privates.php new file mode 100644 index 0000000000000..70e781bdfd9e9 --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_legacy_privates.php @@ -0,0 +1,200 @@ +targetDirs[$i] = $dir = dirname($dir); + } + $this->services = array(); + $this->methodMap = array( + 'bar' => 'getBarService', + 'private' => 'getPrivateService', + 'private_alias' => 'getPrivateAliasService', + 'private_alias_decorator' => 'getPrivateAliasDecoratorService', + 'private_child' => 'getPrivateChildService', + 'private_decorator' => 'getPrivateDecoratorService', + 'private_decorator.inner' => 'getPrivateDecorator_InnerService', + 'private_not_inlined' => 'getPrivateNotInlinedService', + 'private_not_removed' => 'getPrivateNotRemovedService', + 'private_parent' => 'getPrivateParentService', + 'public_child' => 'getPublicChildService', + ); + $this->privates = array( + 'decorated_private' => true, + 'decorated_private_alias' => true, + 'private' => true, + 'private_alias' => true, + 'private_child' => true, + 'private_decorator.inner' => true, + 'private_not_inlined' => true, + 'private_not_removed' => true, + 'private_parent' => true, + ); + $this->aliases = array( + 'alias_to_private' => 'private', + 'decorated_private' => 'private_decorator', + 'decorated_private_alias' => 'private_alias_decorator', + ); + } + + /** + * {@inheritdoc} + */ + public function compile() + { + throw new LogicException('You cannot compile a dumped container that was already compiled.'); + } + + /** + * {@inheritdoc} + */ + public function isCompiled() + { + return true; + } + + /** + * {@inheritdoc} + */ + public function isFrozen() + { + @trigger_error(sprintf('The %s() method is deprecated since version 3.3 and will be removed in 4.0. Use the isCompiled() method instead.', __METHOD__), E_USER_DEPRECATED); + + return true; + } + + /** + * Gets the public 'bar' shared service. + * + * @return \stdClass + */ + protected function getBarService() + { + return $this->services['bar'] = new \stdClass(${($_ = isset($this->services['private_not_inlined']) ? $this->services['private_not_inlined'] : $this->services['private_not_inlined'] = new \stdClass()) && false ?: '_'}); + } + + /** + * Gets the public 'private_alias_decorator' shared service. + * + * @return \stdClass + */ + protected function getPrivateAliasDecoratorService() + { + return $this->services['private_alias_decorator'] = new \stdClass(); + } + + /** + * Gets the public 'private_decorator' shared service. + * + * @return \stdClass + */ + protected function getPrivateDecoratorService() + { + return $this->services['private_decorator'] = new \stdClass(); + } + + /** + * Gets the public 'public_child' shared service. + * + * @return \stdClass + */ + protected function getPublicChildService() + { + return $this->services['public_child'] = new \stdClass(); + } + + /** + * Gets the private 'private' shared service. + * + * @return \stdClass + */ + protected function getPrivateService() + { + return $this->services['private'] = new \stdClass(); + } + + /** + * Gets the private 'private_alias' shared service. + * + * @return \stdClass + */ + protected function getPrivateAliasService() + { + return $this->services['private_alias'] = new \stdClass(); + } + + /** + * Gets the private 'private_child' shared service. + * + * @return \stdClass + */ + protected function getPrivateChildService() + { + return $this->services['private_child'] = new \stdClass(); + } + + /** + * Gets the private 'private_decorator.inner' shared service. + * + * @return \stdClass + */ + protected function getPrivateDecorator_InnerService() + { + return $this->services['private_decorator.inner'] = new \stdClass(); + } + + /** + * Gets the private 'private_not_inlined' shared service. + * + * @return \stdClass + */ + protected function getPrivateNotInlinedService() + { + return $this->services['private_not_inlined'] = new \stdClass(); + } + + /** + * Gets the private 'private_not_removed' shared service. + * + * @return \stdClass + */ + protected function getPrivateNotRemovedService() + { + return $this->services['private_not_removed'] = new \stdClass(); + } + + /** + * Gets the private 'private_parent' shared service. + * + * @return \stdClass + */ + protected function getPrivateParentService() + { + return $this->services['private_parent'] = new \stdClass(); + } +} diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services_legacy_privates.yml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services_legacy_privates.yml new file mode 100644 index 0000000000000..ac54a57dff013 --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services_legacy_privates.yml @@ -0,0 +1,28 @@ +services: + + foo: {class: stdClass, public: false} + + bar: + class: stdClass + arguments: [ '@private_not_inlined' ] + + private: {class: stdClass, public: false} + decorated_private: {class: stdClass} + decorated_private_alias: '@foo' + alias_to_private: '@private' + private_alias: {alias: foo, public: false} + + private_decorator: + class: stdClass + decorates: 'decorated_private' + + private_alias_decorator: + class: stdClass + decorates: 'decorated_private_alias' + + private_not_inlined: {class: stdClass, public: false} + private_not_removed: {class: stdClass, public: false} + + private_child: {parent: foo} + private_parent: {parent: private} + public_child: {parent: private, public: true} From 256055218e924e71668f0770008efbf2ceac9e2d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9goire=20Pineau?= Date: Mon, 11 Sep 2017 19:24:55 +0200 Subject: [PATCH 0818/1099] [Intl] Fixed support of Locale::getFallback --- src/Symfony/Component/Intl/Locale.php | 43 ++++++++++++---- .../Component/Intl/Tests/LocaleTest.php | 49 +++++++++++++++++++ 2 files changed, 82 insertions(+), 10 deletions(-) create mode 100644 src/Symfony/Component/Intl/Tests/LocaleTest.php diff --git a/src/Symfony/Component/Intl/Locale.php b/src/Symfony/Component/Intl/Locale.php index ee09bd263cd42..6dbd71a4ba221 100644 --- a/src/Symfony/Component/Intl/Locale.php +++ b/src/Symfony/Component/Intl/Locale.php @@ -67,21 +67,44 @@ public static function getDefaultFallback() */ public static function getFallback($locale) { - if (false === $pos = strrpos($locale, '_')) { - if (self::$defaultFallback === $locale) { - return 'root'; - } + if (function_exists('locale_parse')) { + $localeSubTags = locale_parse($locale); + if (1 === count($localeSubTags)) { + if (self::$defaultFallback === $localeSubTags['language']) { + return 'root'; + } + + // Don't return default fallback for "root", "meta" or others + // Normal locales have two or three letters + if (strlen($locale) < 4) { + return self::$defaultFallback; + } - // Don't return default fallback for "root", "meta" or others - // Normal locales have two or three letters - if (strlen($locale) < 4) { - return self::$defaultFallback; + return null; } - return; + array_pop($localeSubTags); + + return locale_compose($localeSubTags); + } + + if (false !== $pos = strrpos($locale, '_')) { + return substr($locale, 0, $pos); } - return substr($locale, 0, $pos); + if (false !== $pos = strrpos($locale, '-')) { + return substr($locale, 0, $pos); + } + + if (self::$defaultFallback === $locale) { + return 'root'; + } + + // Don't return default fallback for "root", "meta" or others + // Normal locales have two or three letters + if (strlen($locale) < 4) { + return self::$defaultFallback; + } } /** diff --git a/src/Symfony/Component/Intl/Tests/LocaleTest.php b/src/Symfony/Component/Intl/Tests/LocaleTest.php new file mode 100644 index 0000000000000..e10df5575ab6c --- /dev/null +++ b/src/Symfony/Component/Intl/Tests/LocaleTest.php @@ -0,0 +1,49 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Intl\Tests; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\Intl\Locale; + +class LocaleTest extends TestCase +{ + public function provideGetFallbackTests() + { + $tests = array( + array('sl_Latn_IT', 'sl_Latn_IT_nedis'), + array('sl_Latn', 'sl_Latn_IT'), + array('fr', 'fr_FR'), + array('fr', 'fr-FR'), + array('en', 'fr'), + array('root', 'en'), + array(null, 'root'), + ); + + if (function_exists('locale_parse')) { + $tests[] = array('sl_Latn_IT', 'sl-Latn-IT-nedis'); + $tests[] = array('sl_Latn', 'sl-Latn_IT'); + } else { + $tests[] = array('sl-Latn-IT', 'sl-Latn-IT-nedis'); + $tests[] = array('sl-Latn', 'sl-Latn-IT'); + } + + return $tests; + } + + /** + * @dataProvider provideGetFallbackTests + */ + public function testGetFallback($expected, $locale) + { + $this->assertSame($expected, Locale::getFallback($locale)); + } +} From 8729f9fd6a95130948fc33f796a6672a49eaf9b9 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Wed, 13 Sep 2017 13:10:11 +0200 Subject: [PATCH 0819/1099] [DI] Resolve nested refs to aliases --- .../FrameworkExtension.php | 2 +- .../Bundle/SecurityBundle/composer.json | 4 +- .../ResolveReferencesToAliasesPass.php | 75 ++++--------------- 3 files changed, 19 insertions(+), 62 deletions(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php index 0ead938a1bf10..ea6dec7fd6bd1 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php @@ -1463,7 +1463,7 @@ private function registerAnnotationsConfiguration(array $config, ContainerBuilde ->replaceArgument(2, $config['debug']) ->addTag('annotations.cached_reader', array('provider' => $cacheService)) ; - $container->setAlias('annotation_reader', 'annotations.cached_reader'); + $container->setAlias('annotation_reader', 'annotations.cached_reader')->setPrivate(true); $container->setAlias(Reader::class, new Alias('annotations.cached_reader', false)); } else { $container->removeDefinition('annotations.cached_reader'); diff --git a/src/Symfony/Bundle/SecurityBundle/composer.json b/src/Symfony/Bundle/SecurityBundle/composer.json index 9690cf325aa14..3e7caac2ec5f9 100644 --- a/src/Symfony/Bundle/SecurityBundle/composer.json +++ b/src/Symfony/Bundle/SecurityBundle/composer.json @@ -35,8 +35,8 @@ "symfony/http-foundation": "~2.8|~3.0|~4.0", "symfony/security-acl": "~2.8|~3.0", "symfony/translation": "~2.8|~3.0|~4.0", - "symfony/twig-bundle": "~2.8|~3.0|~4.0", - "symfony/twig-bridge": "~2.8|~3.0|~4.0", + "symfony/twig-bundle": "~3.4|~4.0", + "symfony/twig-bridge": "~3.4|~4.0", "symfony/process": "~2.8|~3.0|~4.0", "symfony/validator": "^3.2.5|~4.0", "symfony/var-dumper": "~3.3|~4.0", diff --git a/src/Symfony/Component/DependencyInjection/Compiler/ResolveReferencesToAliasesPass.php b/src/Symfony/Component/DependencyInjection/Compiler/ResolveReferencesToAliasesPass.php index 6946969a2c06f..6d42f7b4632e1 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/ResolveReferencesToAliasesPass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/ResolveReferencesToAliasesPass.php @@ -11,8 +11,6 @@ namespace Symfony\Component\DependencyInjection\Compiler; -use Symfony\Component\DependencyInjection\Alias; -use Symfony\Component\DependencyInjection\Argument\ArgumentInterface; use Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException; use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\DependencyInjection\ContainerBuilder; @@ -22,97 +20,56 @@ * * @author Johannes M. Schmitt */ -class ResolveReferencesToAliasesPass implements CompilerPassInterface +class ResolveReferencesToAliasesPass extends AbstractRecursivePass { - private $container; - /** - * Processes the ContainerBuilder to replace references to aliases with actual service references. - * - * @param ContainerBuilder $container + * {@inheritdoc} */ public function process(ContainerBuilder $container) { - $this->container = $container; - - foreach ($container->getDefinitions() as $definition) { - if ($definition->isSynthetic() || $definition->isAbstract()) { - continue; - } - - $definition->setArguments($this->processArguments($definition->getArguments())); - $definition->setMethodCalls($this->processArguments($definition->getMethodCalls())); - $definition->setProperties($this->processArguments($definition->getProperties())); - if (isset($definition->getChanges()['factory'])) { - $definition->setFactory($this->processFactory($definition->getFactory())); - } - } + parent::process($container); foreach ($container->getAliases() as $id => $alias) { $aliasId = (string) $alias; - if ($aliasId !== $defId = $this->getDefinitionId($aliasId)) { + if ($aliasId !== $defId = $this->getDefinitionId($aliasId, $container)) { $container->setAlias($id, $defId)->setPublic($alias->isPublic() && !$alias->isPrivate())->setPrivate($alias->isPrivate()); } } } /** - * Processes the arguments to replace aliases. - * - * @param array $arguments An array of References - * - * @return array An array of References + * {@inheritdoc} */ - private function processArguments(array $arguments) + protected function processValue($value, $isRoot = false) { - foreach ($arguments as $k => $argument) { - if (is_array($argument)) { - $arguments[$k] = $this->processArguments($argument); - } elseif ($argument instanceof ArgumentInterface) { - $argument->setValues($this->processArguments($argument->getValues())); - } elseif ($argument instanceof Reference) { - $defId = $this->getDefinitionId($id = (string) $argument); + if ($value instanceof Reference) { + $defId = $this->getDefinitionId($id = (string) $value, $this->container); - if ($defId !== $id) { - $arguments[$k] = new Reference($defId, $argument->getInvalidBehavior()); - } + if ($defId !== $id) { + return new Reference($defId, $value->getInvalidBehavior()); } } - return $arguments; - } - - private function processFactory($factory) - { - if (null === $factory || !is_array($factory) || !$factory[0] instanceof Reference) { - return $factory; - } - - $defId = $this->getDefinitionId($id = (string) $factory[0]); - - if ($defId !== $id) { - $factory[0] = new Reference($defId, $factory[0]->getInvalidBehavior()); - } - - return $factory; + return parent::processValue($value); } /** * Resolves an alias into a definition id. * - * @param string $id The definition or alias id to resolve + * @param string $id The definition or alias id to resolve + * @param ContainerBuilder $container * * @return string The definition id with aliases resolved */ - private function getDefinitionId($id) + private function getDefinitionId($id, $container) { $seen = array(); - while ($this->container->hasAlias($id)) { + while ($container->hasAlias($id)) { if (isset($seen[$id])) { throw new ServiceCircularReferenceException($id, array_keys($seen)); } $seen[$id] = true; - $id = (string) $this->container->getAlias($id); + $id = (string) $container->getAlias($id); } return $id; From 30a13baef3d3351b047c3fb37251b87b8190d1d2 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Wed, 13 Sep 2017 13:33:28 +0200 Subject: [PATCH 0820/1099] fix oups --- .../Compiler/ResolveReferencesToAliasesPass.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/DependencyInjection/Compiler/ResolveReferencesToAliasesPass.php b/src/Symfony/Component/DependencyInjection/Compiler/ResolveReferencesToAliasesPass.php index 6d42f7b4632e1..7ab97044bfe7b 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/ResolveReferencesToAliasesPass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/ResolveReferencesToAliasesPass.php @@ -61,7 +61,7 @@ protected function processValue($value, $isRoot = false) * * @return string The definition id with aliases resolved */ - private function getDefinitionId($id, $container) + private function getDefinitionId($id, ContainerBuilder $container) { $seen = array(); while ($container->hasAlias($id)) { From 86eb10c4131ce06fbfaf1af131315645fd5ec51d Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Wed, 13 Sep 2017 13:41:56 +0200 Subject: [PATCH 0821/1099] Fix travis php7.0 --- .travis.yml | 5 ----- 1 file changed, 5 deletions(-) diff --git a/.travis.yml b/.travis.yml index 1d31503dcbd77..e01ab63ab3227 100644 --- a/.travis.yml +++ b/.travis.yml @@ -120,11 +120,6 @@ before_install: - | # Install extra PHP extensions - if [[ ! $skip && $PHP = 7.0 ]]; then - wget https://github.com/symfony/binary-utils/releases/download/v0.1/ldap-php70.tar.bz2 - tar -xjf ldap-php70.tar.bz2 - echo extension = $(pwd)/ldap.so >> $INI - fi if [[ ! $skip && $PHP = 5.* ]]; then ([[ $deps ]] || tfold ext.symfony_debug 'cd src/Symfony/Component/Debug/Resources/ext && phpize && ./configure && make && echo extension = $(pwd)/modules/symfony_debug.so >> '"$INI") && tfold ext.memcached pecl install -f memcached-2.1.0 && From a1b391fb0025cb8f76a917f690a39035dc446db0 Mon Sep 17 00:00:00 2001 From: Yonel Ceruto Date: Fri, 1 Sep 2017 17:54:17 -0400 Subject: [PATCH 0822/1099] Add default templates directory and option to configure it --- src/Symfony/Bundle/TwigBundle/CHANGELOG.md | 1 + .../DependencyInjection/Configuration.php | 4 ++++ .../DependencyInjection/TwigExtension.php | 14 ++++++++++++-- .../Resources/config/schema/twig-1.0.xsd | 1 + .../DependencyInjection/Fixtures/php/full.php | 1 + .../templates/bundles/TwigBundle/layout.html.twig | 1 + .../Fixtures/templates/layout.html.twig | 1 + .../DependencyInjection/Fixtures/xml/full.xml | 2 +- .../DependencyInjection/Fixtures/yml/full.yml | 1 + .../DependencyInjection/TwigExtensionTest.php | 2 ++ 10 files changed, 25 insertions(+), 3 deletions(-) create mode 100644 src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/Fixtures/templates/bundles/TwigBundle/layout.html.twig create mode 100644 src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/Fixtures/templates/layout.html.twig diff --git a/src/Symfony/Bundle/TwigBundle/CHANGELOG.md b/src/Symfony/Bundle/TwigBundle/CHANGELOG.md index 58a6a7229653d..8ba6647306e04 100644 --- a/src/Symfony/Bundle/TwigBundle/CHANGELOG.md +++ b/src/Symfony/Bundle/TwigBundle/CHANGELOG.md @@ -6,6 +6,7 @@ CHANGELOG * deprecated `Symfony\Bundle\TwigBundle\Command\DebugCommand`, use `Symfony\Bridge\Twig\Command\DebugCommand` instead * deprecated relying on the `ContainerAwareInterface` implementation for `Symfony\Bundle\TwigBundle\Command\LintCommand` + * added option to configure default path templates (via `default_path`) 3.3.0 ----- diff --git a/src/Symfony/Bundle/TwigBundle/DependencyInjection/Configuration.php b/src/Symfony/Bundle/TwigBundle/DependencyInjection/Configuration.php index 4880d2534d8f5..f4488c0d5ccd4 100644 --- a/src/Symfony/Bundle/TwigBundle/DependencyInjection/Configuration.php +++ b/src/Symfony/Bundle/TwigBundle/DependencyInjection/Configuration.php @@ -130,6 +130,10 @@ private function addTwigOptions(ArrayNodeDefinition $rootNode) ->booleanNode('strict_variables')->end() ->scalarNode('auto_reload')->end() ->integerNode('optimizations')->min(-1)->end() + ->scalarNode('default_path') + ->info('The default path used to load templates') + ->defaultValue('%kernel.project_dir%/templates') + ->end() ->arrayNode('paths') ->normalizeKeys(false) ->useAttributeAsKey('paths') diff --git a/src/Symfony/Bundle/TwigBundle/DependencyInjection/TwigExtension.php b/src/Symfony/Bundle/TwigBundle/DependencyInjection/TwigExtension.php index ca0c68d49b02a..718767324a2e0 100644 --- a/src/Symfony/Bundle/TwigBundle/DependencyInjection/TwigExtension.php +++ b/src/Symfony/Bundle/TwigBundle/DependencyInjection/TwigExtension.php @@ -109,7 +109,7 @@ public function load(array $configs, ContainerBuilder $container) $container->getDefinition('twig.cache_warmer')->replaceArgument(2, $config['paths']); $container->getDefinition('twig.template_iterator')->replaceArgument(2, $config['paths']); - $bundleHierarchy = $this->getBundleHierarchy($container); + $bundleHierarchy = $this->getBundleHierarchy($container, $config); foreach ($bundleHierarchy as $name => $bundle) { $namespace = $this->normalizeBundleName($name); @@ -130,6 +130,11 @@ public function load(array $configs, ContainerBuilder $container) } $container->addResource(new FileExistenceResource($dir)); + if (file_exists($dir = $container->getParameterBag()->resolveValue($config['default_path']))) { + $twigFilesystemLoaderDefinition->addMethodCall('addPath', array($dir)); + } + $container->addResource(new FileExistenceResource($dir)); + if (!empty($config['globals'])) { $def = $container->getDefinition('twig'); foreach ($config['globals'] as $key => $global) { @@ -174,7 +179,7 @@ public function load(array $configs, ContainerBuilder $container) } } - private function getBundleHierarchy(ContainerBuilder $container) + private function getBundleHierarchy(ContainerBuilder $container, array $config) { $bundleHierarchy = array(); @@ -192,6 +197,11 @@ private function getBundleHierarchy(ContainerBuilder $container) } $container->addResource(new FileExistenceResource($dir)); + if (file_exists($dir = $container->getParameterBag()->resolveValue($config['default_path']).'/bundles/'.$name)) { + $bundleHierarchy[$name]['paths'][] = $dir; + } + $container->addResource(new FileExistenceResource($dir)); + if (file_exists($dir = $bundle['path'].'/Resources/views')) { $bundleHierarchy[$name]['paths'][] = $dir; } diff --git a/src/Symfony/Bundle/TwigBundle/Resources/config/schema/twig-1.0.xsd b/src/Symfony/Bundle/TwigBundle/Resources/config/schema/twig-1.0.xsd index 61b57798b27cf..3e491f7029833 100644 --- a/src/Symfony/Bundle/TwigBundle/Resources/config/schema/twig-1.0.xsd +++ b/src/Symfony/Bundle/TwigBundle/Resources/config/schema/twig-1.0.xsd @@ -26,6 +26,7 @@ + diff --git a/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/Fixtures/php/full.php b/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/Fixtures/php/full.php index 9385131730d86..839d037fdcd00 100644 --- a/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/Fixtures/php/full.php +++ b/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/Fixtures/php/full.php @@ -17,6 +17,7 @@ 'charset' => 'ISO-8859-1', 'debug' => true, 'strict_variables' => true, + 'default_path' => '%kernel.root_dir%/templates', 'paths' => array( 'path1', 'path2', diff --git a/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/Fixtures/templates/bundles/TwigBundle/layout.html.twig b/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/Fixtures/templates/bundles/TwigBundle/layout.html.twig new file mode 100644 index 0000000000000..bb07ecfe55a36 --- /dev/null +++ b/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/Fixtures/templates/bundles/TwigBundle/layout.html.twig @@ -0,0 +1 @@ +This is a layout diff --git a/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/Fixtures/templates/layout.html.twig b/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/Fixtures/templates/layout.html.twig new file mode 100644 index 0000000000000..bb07ecfe55a36 --- /dev/null +++ b/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/Fixtures/templates/layout.html.twig @@ -0,0 +1 @@ +This is a layout diff --git a/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/Fixtures/xml/full.xml b/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/Fixtures/xml/full.xml index 14c95af97e8f4..702e34617d6b9 100644 --- a/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/Fixtures/xml/full.xml +++ b/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/Fixtures/xml/full.xml @@ -6,7 +6,7 @@ xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd http://symfony.com/schema/dic/twig http://symfony.com/schema/dic/twig/twig-1.0.xsd"> - + MyBundle::form.html.twig @@qux diff --git a/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/Fixtures/yml/full.yml b/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/Fixtures/yml/full.yml index 68ecf463f09f6..07d4abe767a41 100644 --- a/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/Fixtures/yml/full.yml +++ b/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/Fixtures/yml/full.yml @@ -13,6 +13,7 @@ twig: charset: ISO-8859-1 debug: true strict_variables: true + default_path: '%kernel.root_dir%/templates' paths: path1: '' path2: '' diff --git a/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/TwigExtensionTest.php b/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/TwigExtensionTest.php index cdd686029423a..9d47948d67b77 100644 --- a/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/TwigExtensionTest.php +++ b/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/TwigExtensionTest.php @@ -196,6 +196,7 @@ public function testTwigLoaderPaths($format) array(__DIR__.'/Fixtures/Bundle/ChildChildTwigBundle/Resources/views', 'Twig'), array(__DIR__.'/Fixtures/Bundle/ChildTwigBundle/Resources/views', 'Twig'), array(__DIR__.'/Fixtures/Resources/TwigBundle/views', 'Twig'), + array(__DIR__.'/Fixtures/templates/bundles/TwigBundle', 'Twig'), array(realpath(__DIR__.'/../..').'/Resources/views', 'Twig'), array(__DIR__.'/Fixtures/Bundle/ChildChildChildChildTwigBundle/Resources/views', 'ChildTwig'), array(__DIR__.'/Fixtures/Bundle/ChildChildChildTwigBundle/Resources/views', 'ChildTwig'), @@ -205,6 +206,7 @@ public function testTwigLoaderPaths($format) array(__DIR__.'/Fixtures/Bundle/ChildChildChildTwigBundle/Resources/views', 'ChildChildTwig'), array(__DIR__.'/Fixtures/Bundle/ChildChildTwigBundle/Resources/views', 'ChildChildTwig'), array(__DIR__.'/Fixtures/Resources/views'), + array(__DIR__.'/Fixtures/templates'), ), $paths); } From d1f7024e1488697d8a9e1c49c99a81c07175e6b2 Mon Sep 17 00:00:00 2001 From: "Alexander M. Turek" Date: Wed, 13 Sep 2017 15:44:19 +0200 Subject: [PATCH 0823/1099] Removed unnecessary getDefinition() call. --- .../DependencyInjection/RegisterListenersPass.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/Symfony/Component/EventDispatcher/DependencyInjection/RegisterListenersPass.php b/src/Symfony/Component/EventDispatcher/DependencyInjection/RegisterListenersPass.php index 50e466a3983c6..a08f54c3b0098 100644 --- a/src/Symfony/Component/EventDispatcher/DependencyInjection/RegisterListenersPass.php +++ b/src/Symfony/Component/EventDispatcher/DependencyInjection/RegisterListenersPass.php @@ -62,8 +62,6 @@ public function process(ContainerBuilder $container) $definition = $container->findDefinition($this->dispatcherService); foreach ($container->findTaggedServiceIds($this->listenerTag, true) as $id => $events) { - $def = $container->getDefinition($id); - foreach ($events as $event) { $priority = isset($event['priority']) ? $event['priority'] : 0; From b524c84ce104b285a0c490c712582b3f28fe12eb Mon Sep 17 00:00:00 2001 From: gitlost Date: Tue, 11 Jul 2017 04:43:03 +0100 Subject: [PATCH 0824/1099] [Filesystem] mirror - fix copying content with same name as source/target. --- .../Component/Filesystem/Filesystem.php | 6 ++- .../Filesystem/Tests/FilesystemTest.php | 47 +++++++++++++++++++ 2 files changed, 51 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/Filesystem/Filesystem.php b/src/Symfony/Component/Filesystem/Filesystem.php index bc2e3dcc2d897..b563dcc3751f2 100644 --- a/src/Symfony/Component/Filesystem/Filesystem.php +++ b/src/Symfony/Component/Filesystem/Filesystem.php @@ -444,6 +444,7 @@ public function mirror($originDir, $targetDir, \Traversable $iterator = null, $o { $targetDir = rtrim($targetDir, '/\\'); $originDir = rtrim($originDir, '/\\'); + $originDirLen = strlen($originDir); // Iterate in destination folder to remove obsolete entries if ($this->exists($targetDir) && isset($options['delete']) && $options['delete']) { @@ -452,8 +453,9 @@ public function mirror($originDir, $targetDir, \Traversable $iterator = null, $o $flags = \FilesystemIterator::SKIP_DOTS; $deleteIterator = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($targetDir, $flags), \RecursiveIteratorIterator::CHILD_FIRST); } + $targetDirLen = strlen($targetDir); foreach ($deleteIterator as $file) { - $origin = str_replace($targetDir, $originDir, $file->getPathname()); + $origin = $originDir.substr($file->getPathname(), $targetDirLen); if (!$this->exists($origin)) { $this->remove($file); } @@ -475,7 +477,7 @@ public function mirror($originDir, $targetDir, \Traversable $iterator = null, $o } foreach ($iterator as $file) { - $target = str_replace($originDir, $targetDir, $file->getPathname()); + $target = $targetDir.substr($file->getPathname(), $originDirLen); if ($copyOnWindows) { if (is_file($file)) { diff --git a/src/Symfony/Component/Filesystem/Tests/FilesystemTest.php b/src/Symfony/Component/Filesystem/Tests/FilesystemTest.php index b7bdfac4155e0..a4d111c218c6a 100644 --- a/src/Symfony/Component/Filesystem/Tests/FilesystemTest.php +++ b/src/Symfony/Component/Filesystem/Tests/FilesystemTest.php @@ -1009,6 +1009,53 @@ public function testMirrorCopiesRelativeLinkedContents() $this->assertEquals('\\' === DIRECTORY_SEPARATOR ? realpath($sourcePath.'\nested') : 'nested', readlink($targetPath.DIRECTORY_SEPARATOR.'link1')); } + public function testMirrorContentsWithSameNameAsSourceOrTargetWithoutDeleteOption() + { + $sourcePath = $this->workspace.DIRECTORY_SEPARATOR.'source'.DIRECTORY_SEPARATOR; + + mkdir($sourcePath); + touch($sourcePath.'source'); + touch($sourcePath.'target'); + + $targetPath = $this->workspace.DIRECTORY_SEPARATOR.'target'.DIRECTORY_SEPARATOR; + + $oldPath = getcwd(); + chdir($this->workspace); + + $this->filesystem->mirror('source', $targetPath); + + chdir($oldPath); + + $this->assertTrue(is_dir($targetPath)); + $this->assertFileExists($targetPath.'source'); + $this->assertFileExists($targetPath.'target'); + } + + public function testMirrorContentsWithSameNameAsSourceOrTargetWithDeleteOption() + { + $sourcePath = $this->workspace.DIRECTORY_SEPARATOR.'source'.DIRECTORY_SEPARATOR; + + mkdir($sourcePath); + touch($sourcePath.'source'); + + $targetPath = $this->workspace.DIRECTORY_SEPARATOR.'target'.DIRECTORY_SEPARATOR; + + mkdir($targetPath); + touch($targetPath.'source'); + touch($targetPath.'target'); + + $oldPath = getcwd(); + chdir($this->workspace); + + $this->filesystem->mirror('source', 'target', null, array('delete' => true)); + + chdir($oldPath); + + $this->assertTrue(is_dir($targetPath)); + $this->assertFileExists($targetPath.'source'); + $this->assertFileNotExists($targetPath.'target'); + } + /** * @dataProvider providePathsForIsAbsolutePath */ From 10ce932504829ec89a2565cc0b0f6e4d17c6f76e Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Wed, 13 Sep 2017 20:51:11 +0200 Subject: [PATCH 0825/1099] [PhpUnitBridge] do not require an error context The error context argument of an error handler is deprecated as of PHP 7.2. Requiring it in the error handler of the SymfonyTestsListenerTrait will make error handlers fail that are executed when running PHPUnit tests and forward the error handling to the previously registered error handler. --- src/Symfony/Bridge/PhpUnit/Legacy/SymfonyTestsListenerTrait.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Bridge/PhpUnit/Legacy/SymfonyTestsListenerTrait.php b/src/Symfony/Bridge/PhpUnit/Legacy/SymfonyTestsListenerTrait.php index 173a0fa82fd93..b561c8f2f53a5 100644 --- a/src/Symfony/Bridge/PhpUnit/Legacy/SymfonyTestsListenerTrait.php +++ b/src/Symfony/Bridge/PhpUnit/Legacy/SymfonyTestsListenerTrait.php @@ -303,7 +303,7 @@ public function endTest($test, $time) } } - public function handleError($type, $msg, $file, $line, $context) + public function handleError($type, $msg, $file, $line, $context = array()) { if (E_USER_DEPRECATED !== $type && E_DEPRECATED !== $type) { $h = $this->previousErrorHandler; From 8b7c7c179b2fdee778ec0e77a49cdf5f01960e73 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Thu, 14 Sep 2017 10:50:29 +0200 Subject: [PATCH 0826/1099] [DI] Fix non-instantiables auto-discovery --- src/Symfony/Component/DependencyInjection/Loader/FileLoader.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/DependencyInjection/Loader/FileLoader.php b/src/Symfony/Component/DependencyInjection/Loader/FileLoader.php index 40cf8f9ee4cae..8ad8a1ebd4216 100644 --- a/src/Symfony/Component/DependencyInjection/Loader/FileLoader.php +++ b/src/Symfony/Component/DependencyInjection/Loader/FileLoader.php @@ -133,7 +133,7 @@ private function findClasses($namespace, $pattern, $excludePattern) throw new InvalidArgumentException(sprintf('Expected to find class "%s" in file "%s" while importing services from resource "%s", but it was not found! Check the namespace prefix used with the resource.', $class, $path, $pattern)); } - if (!$r->isInterface() && !$r->isTrait() && !$r->isAbstract()) { + if ($r->isInstantiable()) { $classes[] = $class; } } From 7c3bdd913997236f06dae2a351d14c333ce36a14 Mon Sep 17 00:00:00 2001 From: "Alexander M. Turek" Date: Wed, 13 Sep 2017 22:59:37 +0200 Subject: [PATCH 0827/1099] Reset stopwatch. --- .../DependencyInjection/FrameworkExtension.php | 5 ++++- src/Symfony/Bundle/FrameworkBundle/composer.json | 3 ++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php index ea6dec7fd6bd1..cef14f756cc40 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php @@ -753,7 +753,10 @@ private function registerDebugConfiguration(array $config, ContainerBuilder $con $container->getDefinition('debug.debug_handlers_listener')->setPrivate(true); if (class_exists(Stopwatch::class)) { - $container->register('debug.stopwatch', Stopwatch::class)->addArgument(true)->setPrivate(true); + $container->register('debug.stopwatch', Stopwatch::class) + ->addArgument(true) + ->setPrivate(true) + ->addTag('kernel.reset', array('method' => 'reset')); $container->setAlias(Stopwatch::class, new Alias('debug.stopwatch', false)); } diff --git a/src/Symfony/Bundle/FrameworkBundle/composer.json b/src/Symfony/Bundle/FrameworkBundle/composer.json index 3e0354ec625c1..9b16b9417950c 100644 --- a/src/Symfony/Bundle/FrameworkBundle/composer.json +++ b/src/Symfony/Bundle/FrameworkBundle/composer.json @@ -46,7 +46,7 @@ "symfony/security-core": "~3.2|~4.0", "symfony/security-csrf": "~2.8|~3.0|~4.0", "symfony/serializer": "~3.3|~4.0", - "symfony/stopwatch": "~2.8|~3.0|~4.0", + "symfony/stopwatch": "~3.4|~4.0", "symfony/translation": "~3.4|~4.0", "symfony/templating": "~2.8|~3.0|~4.0", "symfony/validator": "~3.4|~4.0", @@ -68,6 +68,7 @@ "symfony/form": "<3.4", "symfony/property-info": "<3.3", "symfony/serializer": "<3.3", + "symfony/stopwatch": "<3.4", "symfony/translation": "<3.4", "symfony/validator": "<3.4", "symfony/workflow": "<3.3" From d4f6039dcd49c08b1d0f3b2be043074665f11523 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A1chym=20Tou=C5=A1ek?= Date: Thu, 14 Sep 2017 10:24:46 +0200 Subject: [PATCH 0828/1099] [HttpFoundation] Fix file upload multiple with no files --- src/Symfony/Component/HttpFoundation/FileBag.php | 4 ++-- .../Component/HttpFoundation/Tests/FileBagTest.php | 13 +++++++++++++ 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/HttpFoundation/FileBag.php b/src/Symfony/Component/HttpFoundation/FileBag.php index e17a9057b7157..1f3a502fb75c4 100644 --- a/src/Symfony/Component/HttpFoundation/FileBag.php +++ b/src/Symfony/Component/HttpFoundation/FileBag.php @@ -69,7 +69,7 @@ public function add(array $files = array()) * * @param array|UploadedFile $file A (multi-dimensional) array of uploaded file information * - * @return UploadedFile|UploadedFile[] A (multi-dimensional) array of UploadedFile instances + * @return UploadedFile[]|UploadedFile|null A (multi-dimensional) array of UploadedFile instances */ protected function convertFileInformation($file) { @@ -89,7 +89,7 @@ protected function convertFileInformation($file) $file = new UploadedFile($file['tmp_name'], $file['name'], $file['type'], $file['size'], $file['error']); } } else { - $file = array_map(array($this, 'convertFileInformation'), $file); + $file = array_filter(array_map(array($this, 'convertFileInformation'), $file)); } } diff --git a/src/Symfony/Component/HttpFoundation/Tests/FileBagTest.php b/src/Symfony/Component/HttpFoundation/Tests/FileBagTest.php index e7defa677713b..7d2902d325d46 100644 --- a/src/Symfony/Component/HttpFoundation/Tests/FileBagTest.php +++ b/src/Symfony/Component/HttpFoundation/Tests/FileBagTest.php @@ -60,6 +60,19 @@ public function testShouldSetEmptyUploadedFilesToNull() $this->assertNull($bag->get('file')); } + public function testShouldRemoveEmptyUploadedFilesForMultiUpload() + { + $bag = new FileBag(array('file' => array( + 'name' => array(''), + 'type' => array(''), + 'tmp_name' => array(''), + 'error' => array(UPLOAD_ERR_NO_FILE), + 'size' => array(0), + ))); + + $this->assertSame(array(), $bag->get('file')); + } + public function testShouldConvertUploadedFilesWithPhpBug() { $tmpFile = $this->createTempFile(); From d9a6b76dbdff123d0c99261b785cdb15c2fbe97e Mon Sep 17 00:00:00 2001 From: "Alexander M. Turek" Date: Mon, 11 Sep 2017 16:29:04 +0200 Subject: [PATCH 0829/1099] A DI tag for resettable services. --- .../FrameworkBundle/FrameworkBundle.php | 2 + .../Resources/config/services.xml | 6 ++ .../ResettableServicePass.php | 69 +++++++++++++++ .../EventListener/ServiceResetListener.php | 50 +++++++++++ .../ResettableServicePassTest.php | 85 +++++++++++++++++++ .../ServiceResetListenerTest.php | 76 +++++++++++++++++ .../Tests/Fixtures/ClearableService.php | 13 +++ .../Tests/Fixtures/ResettableService.php | 13 +++ 8 files changed, 314 insertions(+) create mode 100644 src/Symfony/Component/HttpKernel/DependencyInjection/ResettableServicePass.php create mode 100644 src/Symfony/Component/HttpKernel/EventListener/ServiceResetListener.php create mode 100644 src/Symfony/Component/HttpKernel/Tests/DependencyInjection/ResettableServicePassTest.php create mode 100644 src/Symfony/Component/HttpKernel/Tests/EventListener/ServiceResetListenerTest.php create mode 100644 src/Symfony/Component/HttpKernel/Tests/Fixtures/ClearableService.php create mode 100644 src/Symfony/Component/HttpKernel/Tests/Fixtures/ResettableService.php diff --git a/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php b/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php index ba117ceeb82a2..c6936d35be83d 100644 --- a/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php +++ b/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php @@ -33,6 +33,7 @@ use Symfony\Component\HttpKernel\DependencyInjection\ControllerArgumentValueResolverPass; use Symfony\Component\HttpKernel\DependencyInjection\RegisterControllerArgumentLocatorsPass; use Symfony\Component\HttpKernel\DependencyInjection\RemoveEmptyControllerArgumentLocatorsPass; +use Symfony\Component\HttpKernel\DependencyInjection\ResettableServicePass; use Symfony\Component\PropertyInfo\DependencyInjection\PropertyInfoPass; use Symfony\Component\Routing\DependencyInjection\RoutingResolverPass; use Symfony\Component\Serializer\DependencyInjection\SerializerPass; @@ -117,6 +118,7 @@ public function build(ContainerBuilder $container) $container->addCompilerPass(new CachePoolPrunerPass(), PassConfig::TYPE_AFTER_REMOVING); $this->addCompilerPassIfExists($container, FormPass::class); $container->addCompilerPass(new WorkflowGuardListenerPass()); + $container->addCompilerPass(new ResettableServicePass()); if ($container->getParameter('kernel.debug')) { $container->addCompilerPass(new AddDebugLogProcessorPass(), PassConfig::TYPE_BEFORE_OPTIMIZATION, -32); diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/services.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/services.xml index 9ff2c259ee43b..0bae93663bf5c 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/services.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/services.xml @@ -74,5 +74,11 @@ + + + + + + diff --git a/src/Symfony/Component/HttpKernel/DependencyInjection/ResettableServicePass.php b/src/Symfony/Component/HttpKernel/DependencyInjection/ResettableServicePass.php new file mode 100644 index 0000000000000..56cd059284afe --- /dev/null +++ b/src/Symfony/Component/HttpKernel/DependencyInjection/ResettableServicePass.php @@ -0,0 +1,69 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\DependencyInjection; + +use Symfony\Component\DependencyInjection\Argument\IteratorArgument; +use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\ContainerInterface; +use Symfony\Component\DependencyInjection\Exception\RuntimeException; +use Symfony\Component\DependencyInjection\Reference; +use Symfony\Component\HttpKernel\EventListener\ServiceResetListener; + +/** + * @author Alexander M. Turek + */ +class ResettableServicePass implements CompilerPassInterface +{ + private $tagName; + + /** + * @param string $tagName + */ + public function __construct($tagName = 'kernel.reset') + { + $this->tagName = $tagName; + } + + /** + * {@inheritdoc} + */ + public function process(ContainerBuilder $container) + { + if (!$container->has(ServiceResetListener::class)) { + return; + } + + $services = $methods = array(); + + foreach ($container->findTaggedServiceIds($this->tagName, true) as $id => $tags) { + $services[$id] = new Reference($id, ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE); + $attributes = $tags[0]; + + if (!isset($attributes['method'])) { + throw new RuntimeException(sprintf('Tag %s requires the "method" attribute to be set.', $this->tagName)); + } + + $methods[$id] = $attributes['method']; + } + + if (empty($services)) { + $container->removeDefinition(ServiceResetListener::class); + + return; + } + + $container->findDefinition(ServiceResetListener::class) + ->replaceArgument(0, new IteratorArgument($services)) + ->replaceArgument(1, $methods); + } +} diff --git a/src/Symfony/Component/HttpKernel/EventListener/ServiceResetListener.php b/src/Symfony/Component/HttpKernel/EventListener/ServiceResetListener.php new file mode 100644 index 0000000000000..cf6d15930315f --- /dev/null +++ b/src/Symfony/Component/HttpKernel/EventListener/ServiceResetListener.php @@ -0,0 +1,50 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\EventListener; + +use Symfony\Component\EventDispatcher\EventSubscriberInterface; +use Symfony\Component\HttpKernel\KernelEvents; + +/** + * Clean up services between requests. + * + * @author Alexander M. Turek + */ +class ServiceResetListener implements EventSubscriberInterface +{ + private $services; + private $resetMethods; + + public function __construct(\Traversable $services, array $resetMethods) + { + $this->services = $services; + $this->resetMethods = $resetMethods; + } + + public function onKernelTerminate() + { + foreach ($this->services as $id => $service) { + $method = $this->resetMethods[$id]; + $service->$method(); + } + } + + /** + * {@inheritdoc} + */ + public static function getSubscribedEvents() + { + return array( + KernelEvents::TERMINATE => array('onKernelTerminate', -2048), + ); + } +} diff --git a/src/Symfony/Component/HttpKernel/Tests/DependencyInjection/ResettableServicePassTest.php b/src/Symfony/Component/HttpKernel/Tests/DependencyInjection/ResettableServicePassTest.php new file mode 100644 index 0000000000000..7363586f99588 --- /dev/null +++ b/src/Symfony/Component/HttpKernel/Tests/DependencyInjection/ResettableServicePassTest.php @@ -0,0 +1,85 @@ +register('one', ResettableService::class) + ->addTag('kernel.reset', array('method' => 'reset')); + $container->register('two', ClearableService::class) + ->addTag('kernel.reset', array('method' => 'clear')); + + $container->register(ServiceResetListener::class) + ->setArguments(array(null, array())); + $container->addCompilerPass(new ResettableServicePass('kernel.reset')); + + $container->compile(); + + $definition = $container->getDefinition(ServiceResetListener::class); + + $this->assertEquals( + array( + new IteratorArgument(array( + 'one' => new Reference('one', ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE), + 'two' => new Reference('two', ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE), + )), + array( + 'one' => 'reset', + 'two' => 'clear', + ), + ), + $definition->getArguments() + ); + } + + /** + * @expectedException \Symfony\Component\DependencyInjection\Exception\RuntimeException + * @expectedExceptionMessage Tag kernel.reset requires the "method" attribute to be set. + */ + public function testMissingMethod() + { + $container = new ContainerBuilder(); + $container->register(ResettableService::class) + ->addTag('kernel.reset'); + $container->register(ServiceResetListener::class) + ->setArguments(array(null, array())); + $container->addCompilerPass(new ResettableServicePass('kernel.reset')); + + $container->compile(); + } + + public function testCompilerPassWithoutResetters() + { + $container = new ContainerBuilder(); + $container->register(ServiceResetListener::class) + ->setArguments(array(null, array())); + $container->addCompilerPass(new ResettableServicePass()); + + $container->compile(); + + $this->assertFalse($container->has(ServiceResetListener::class)); + } + + public function testCompilerPassWithoutListener() + { + $container = new ContainerBuilder(); + $container->addCompilerPass(new ResettableServicePass()); + + $container->compile(); + + $this->assertFalse($container->has(ServiceResetListener::class)); + } +} diff --git a/src/Symfony/Component/HttpKernel/Tests/EventListener/ServiceResetListenerTest.php b/src/Symfony/Component/HttpKernel/Tests/EventListener/ServiceResetListenerTest.php new file mode 100644 index 0000000000000..4675fbe71e5a2 --- /dev/null +++ b/src/Symfony/Component/HttpKernel/Tests/EventListener/ServiceResetListenerTest.php @@ -0,0 +1,76 @@ +buildContainer(); + $container->get('reset_subscriber')->onKernelTerminate(); + + $this->assertEquals(0, ResettableService::$counter); + $this->assertEquals(0, ClearableService::$counter); + } + + public function testResetServicesPartially() + { + $container = $this->buildContainer(); + $container->get('one'); + $container->get('reset_subscriber')->onKernelTerminate(); + + $this->assertEquals(1, ResettableService::$counter); + $this->assertEquals(0, ClearableService::$counter); + } + + public function testResetServicesTwice() + { + $container = $this->buildContainer(); + $container->get('one'); + $container->get('reset_subscriber')->onKernelTerminate(); + $container->get('two'); + $container->get('reset_subscriber')->onKernelTerminate(); + + $this->assertEquals(2, ResettableService::$counter); + $this->assertEquals(1, ClearableService::$counter); + } + + /** + * @return ContainerBuilder + */ + private function buildContainer() + { + $container = new ContainerBuilder(); + $container->register('one', ResettableService::class); + $container->register('two', ClearableService::class); + + $container->register('reset_subscriber', ServiceResetListener::class) + ->addArgument(new IteratorArgument(array( + 'one' => new Reference('one', ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE), + 'two' => new Reference('two', ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE), + ))) + ->addArgument(array( + 'one' => 'reset', + 'two' => 'clear', + )); + + $container->compile(); + + return $container; + } +} diff --git a/src/Symfony/Component/HttpKernel/Tests/Fixtures/ClearableService.php b/src/Symfony/Component/HttpKernel/Tests/Fixtures/ClearableService.php new file mode 100644 index 0000000000000..35acb419ce3e5 --- /dev/null +++ b/src/Symfony/Component/HttpKernel/Tests/Fixtures/ClearableService.php @@ -0,0 +1,13 @@ + Date: Mon, 11 Sep 2017 11:38:49 -0700 Subject: [PATCH 0830/1099] fixed CS --- src/Symfony/Component/HttpKernel/Kernel.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/HttpKernel/Kernel.php b/src/Symfony/Component/HttpKernel/Kernel.php index d20258d4ac389..56628544ab15d 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -852,7 +852,7 @@ public static function stripComments($source) do { $token = $tokens[++$i]; $output .= isset($token[1]) && 'b"' !== $token ? $token[1] : $token; - } while ($token[0] !== T_END_HEREDOC); + } while (T_END_HEREDOC !== $token[0]); $rawChunk = ''; } elseif (T_WHITESPACE === $token[0]) { if ($ignoreSpace) { From 8092dc6838fca79773d9489185f704a15e15a348 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Mon, 11 Sep 2017 11:14:25 -0700 Subject: [PATCH 0831/1099] removed the profiler.matcher configuration --- .../DependencyInjection/Configuration.php | 17 --------------- .../FrameworkExtension.php | 21 ------------------- .../Resources/config/profiling.xml | 2 +- .../DependencyInjection/ConfigurationTest.php | 4 ---- 4 files changed, 1 insertion(+), 43 deletions(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php index 55583eba06c32..e31802ac84c04 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php @@ -185,23 +185,6 @@ private function addProfilerSection(ArrayNodeDefinition $rootNode) ->booleanNode('only_exceptions')->defaultFalse()->end() ->booleanNode('only_master_requests')->defaultFalse()->end() ->scalarNode('dsn')->defaultValue('file:%kernel.cache_dir%/profiler')->end() - ->arrayNode('matcher') - ->setDeprecated('The "profiler.matcher" configuration key has been deprecated in Symfony 3.4 and it will be removed in 4.0.') - ->canBeEnabled() - ->performNoDeepMerging() - ->fixXmlConfig('ip') - ->children() - ->scalarNode('path') - ->info('use the urldecoded format') - ->example('^/path to resource/') - ->end() - ->scalarNode('service')->end() - ->arrayNode('ips') - ->beforeNormalization()->ifString()->then(function ($v) { return array($v); })->end() - ->prototype('scalar')->end() - ->end() - ->end() - ->end() ->end() ->end() ->end() diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php index 9593564b6c7c2..5d047cc02ce98 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php @@ -445,27 +445,6 @@ private function registerProfilerConfiguration(array $config, ContainerBuilder $ $container->setParameter('profiler.storage.dsn', $config['dsn']); - if ($this->isConfigEnabled($container, $config['matcher'])) { - if (isset($config['matcher']['service'])) { - $container->setAlias('profiler.request_matcher', $config['matcher']['service'])->setPrivate(true); - } elseif (isset($config['matcher']['ip']) || isset($config['matcher']['path']) || isset($config['matcher']['ips'])) { - $definition = $container->register('profiler.request_matcher', 'Symfony\\Component\\HttpFoundation\\RequestMatcher'); - $definition->setPublic(false); - - if (isset($config['matcher']['ip'])) { - $definition->addMethodCall('matchIp', array($config['matcher']['ip'])); - } - - if (isset($config['matcher']['ips'])) { - $definition->addMethodCall('matchIps', array($config['matcher']['ips'])); - } - - if (isset($config['matcher']['path'])) { - $definition->addMethodCall('matchPath', array($config['matcher']['path'])); - } - } - } - if (!$config['collect']) { $container->getDefinition('profiler')->addMethodCall('disable', array()); } diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/profiling.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/profiling.xml index 635dc8d2b3ed0..8816284fa78ed 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/profiling.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/profiling.xml @@ -21,7 +21,7 @@ - + null %profiler_listener.only_exceptions% %profiler_listener.only_master_requests% diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/ConfigurationTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/ConfigurationTest.php index c53f6544ed8ab..eb28c69527160 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/ConfigurationTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/ConfigurationTest.php @@ -148,10 +148,6 @@ protected static function getBundleDefaultConfig() 'only_master_requests' => false, 'dsn' => 'file:%kernel.cache_dir%/profiler', 'collect' => true, - 'matcher' => array( - 'enabled' => false, - 'ips' => array(), - ), ), 'translator' => array( 'enabled' => !class_exists(FullStack::class), From 5b77d991e98e0d4d8ad3567529ffc68fc2393207 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Thu, 14 Sep 2017 20:37:43 -0700 Subject: [PATCH 0832/1099] fixed CS --- .../DependencyInjection/FrameworkExtension.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php index 5d047cc02ce98..8120561255cd5 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php @@ -480,9 +480,9 @@ private function registerWorkflowConfiguration(array $config, ContainerBuilder $ $transitions = array(); foreach ($workflow['transitions'] as $transition) { - if ($type === 'workflow') { + if ('workflow' === $type) { $transitions[] = new Definition(Workflow\Transition::class, array($transition['name'], $transition['from'], $transition['to'])); - } elseif ($type === 'state_machine') { + } elseif ('state_machine' === $type) { foreach ($transition['from'] as $from) { foreach ($transition['to'] as $to) { $transitions[] = new Definition(Workflow\Transition::class, array($transition['name'], $from, $to)); From 89893c120425a2c8fa915106f4c539f822957d27 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Mon, 11 Sep 2017 10:56:43 -0700 Subject: [PATCH 0833/1099] [HttpKernel] deprecated bundle inheritance --- UPGRADE-3.4.md | 2 ++ UPGRADE-4.0.md | 2 ++ .../Controller/ControllerNameParser.php | 4 +-- .../HttpKernel/Bundle/BundleInterface.php | 2 ++ src/Symfony/Component/HttpKernel/CHANGELOG.md | 1 + src/Symfony/Component/HttpKernel/Kernel.php | 15 ++++++++-- .../Component/HttpKernel/KernelInterface.php | 3 ++ .../Component/HttpKernel/Tests/KernelTest.php | 28 +++++++++++++++++++ 8 files changed, 53 insertions(+), 4 deletions(-) diff --git a/UPGRADE-3.4.md b/UPGRADE-3.4.md index 2c80252b5b8ab..c5def31a9603e 100644 --- a/UPGRADE-3.4.md +++ b/UPGRADE-3.4.md @@ -173,6 +173,8 @@ FrameworkBundle HttpKernel ---------- + * Bundle inheritance has been deprecated. + * Relying on convention-based commands discovery has been deprecated and won't be supported in 4.0. Use PSR-4 based service discovery instead. diff --git a/UPGRADE-4.0.md b/UPGRADE-4.0.md index 9f8017c47e8a4..e5a69675a2fa0 100644 --- a/UPGRADE-4.0.md +++ b/UPGRADE-4.0.md @@ -493,6 +493,8 @@ HttpFoundation HttpKernel ---------- + * Bundle inheritance has been removed. + * Relying on convention-based commands discovery is not supported anymore. Use PSR-4 based service discovery instead. diff --git a/src/Symfony/Bundle/FrameworkBundle/Controller/ControllerNameParser.php b/src/Symfony/Bundle/FrameworkBundle/Controller/ControllerNameParser.php index 989dc8cd23d7c..323c5122a531f 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Controller/ControllerNameParser.php +++ b/src/Symfony/Bundle/FrameworkBundle/Controller/ControllerNameParser.php @@ -58,7 +58,7 @@ public function parse($controller) try { // this throws an exception if there is no such bundle - $allBundles = $this->kernel->getBundle($bundle, false); + $allBundles = $this->kernel->getBundle($bundle, false, true); } catch (\InvalidArgumentException $e) { $message = sprintf( 'The "%s" (from the _controller value "%s") does not exist or is not enabled in your kernel!', @@ -141,7 +141,7 @@ private function findAlternative($nonExistentBundleName) } $lev = levenshtein($nonExistentBundleName, $bundleName); - if ($lev <= strlen($nonExistentBundleName) / 3 && ($alternative === null || $lev < $shortest)) { + if ($lev <= strlen($nonExistentBundleName) / 3 && (null === $alternative || $lev < $shortest)) { $alternative = $bundleName; $shortest = $lev; } diff --git a/src/Symfony/Component/HttpKernel/Bundle/BundleInterface.php b/src/Symfony/Component/HttpKernel/Bundle/BundleInterface.php index 25eea1d76dec3..f4a160c2fd587 100644 --- a/src/Symfony/Component/HttpKernel/Bundle/BundleInterface.php +++ b/src/Symfony/Component/HttpKernel/Bundle/BundleInterface.php @@ -56,6 +56,8 @@ public function getContainerExtension(); * bundle. * * @return string The Bundle name it overrides or null if no parent + * + * @deprecated This method is deprecated as of 3.4 and will be removed in 4.0. */ public function getParent(); diff --git a/src/Symfony/Component/HttpKernel/CHANGELOG.md b/src/Symfony/Component/HttpKernel/CHANGELOG.md index 4a4c81dac096a..702394ade5bd4 100644 --- a/src/Symfony/Component/HttpKernel/CHANGELOG.md +++ b/src/Symfony/Component/HttpKernel/CHANGELOG.md @@ -4,6 +4,7 @@ CHANGELOG 3.4.0 ----- + * deprecated bundle inheritance * added `RebootableInterface` and implemented it in `Kernel` * deprecated commands auto registration * added `AddCacheClearerPass` diff --git a/src/Symfony/Component/HttpKernel/Kernel.php b/src/Symfony/Component/HttpKernel/Kernel.php index 56628544ab15d..4f7ec2c289bac 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -204,8 +204,17 @@ public function getBundles() /** * {@inheritdoc} */ - public function getBundle($name, $first = true) + public function getBundle($name, $first = true/*, $noDeprecation = false */) { + $noDeprecation = false; + if (func_num_args() >= 3) { + $noDeprecation = func_get_arg(2); + } + + if (!$first && !$noDeprecation) { + @trigger_error(sprintf('Passing "false" as the second argument to %s() is deprecated as of 3.4 and will be removed in 4.0.', __METHOD__), E_USER_DEPRECATED); + } + 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))); } @@ -241,7 +250,7 @@ public function locateResource($name, $dir = null, $first = true) $isResource = 0 === strpos($path, 'Resources') && null !== $dir; $overridePath = substr($path, 9); $resourceBundle = null; - $bundles = $this->getBundle($bundleName, false); + $bundles = $this->getBundle($bundleName, false, true); $files = array(); foreach ($bundles as $bundle) { @@ -468,6 +477,8 @@ protected function initializeBundles() $this->bundles[$name] = $bundle; if ($parentName = $bundle->getParent()) { + @trigger_error('Bundle inheritance is deprecated as of 3.4 and will be removed in 4.0.', E_USER_DEPRECATED); + if (isset($directChildren[$parentName])) { throw new \LogicException(sprintf('Bundle "%s" is directly extended by two bundles "%s" and "%s".', $parentName, $name, $directChildren[$parentName])); } diff --git a/src/Symfony/Component/HttpKernel/KernelInterface.php b/src/Symfony/Component/HttpKernel/KernelInterface.php index b8609b9ededb9..9fd3777889289 100644 --- a/src/Symfony/Component/HttpKernel/KernelInterface.php +++ b/src/Symfony/Component/HttpKernel/KernelInterface.php @@ -60,6 +60,9 @@ public function getBundles(); /** * Returns a bundle and optionally its descendants by its name. * + * The second argument is deprecated as of 3.4 and will be removed in 4.0. This method + * will always return an instance of BundleInterface in 4.0. + * * @param string $name Bundle name * @param bool $first Whether to return the first bundle only or together with its descendants * diff --git a/src/Symfony/Component/HttpKernel/Tests/KernelTest.php b/src/Symfony/Component/HttpKernel/Tests/KernelTest.php index 4392e30e652f3..4a093472b9df1 100644 --- a/src/Symfony/Component/HttpKernel/Tests/KernelTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/KernelTest.php @@ -410,6 +410,9 @@ public function testLocateResourceReturnsTheFirstThatMatches() $this->assertEquals(__DIR__.'/Fixtures/Bundle1Bundle/foo.txt', $kernel->locateResource('@Bundle1Bundle/foo.txt')); } + /** + * @group legacy + */ public function testLocateResourceReturnsTheFirstThatMatchesWithParent() { $parent = $this->getBundle(__DIR__.'/Fixtures/Bundle1Bundle'); @@ -426,6 +429,9 @@ public function testLocateResourceReturnsTheFirstThatMatchesWithParent() $this->assertEquals(__DIR__.'/Fixtures/Bundle1Bundle/bar.txt', $kernel->locateResource('@ParentAABundle/bar.txt')); } + /** + * @group legacy + */ public function testLocateResourceReturnsAllMatches() { $parent = $this->getBundle(__DIR__.'/Fixtures/Bundle1Bundle'); @@ -444,6 +450,9 @@ public function testLocateResourceReturnsAllMatches() $kernel->locateResource('@Bundle1Bundle/foo.txt', null, false)); } + /** + * @group legacy + */ public function testLocateResourceReturnsAllMatchesBis() { $kernel = $this->getKernel(array('getBundle')); @@ -492,6 +501,9 @@ public function testLocateResourceReturnsTheDirOneForResources() ); } + /** + * @group legacy + */ public function testLocateResourceReturnsTheDirOneForResourcesAndBundleOnes() { $kernel = $this->getKernel(array('getBundle')); @@ -508,6 +520,9 @@ public function testLocateResourceReturnsTheDirOneForResourcesAndBundleOnes() ); } + /** + * @group legacy + */ public function testLocateResourceOverrideBundleAndResourcesFolders() { $parent = $this->getBundle(__DIR__.'/Fixtures/BaseBundle', null, 'BaseBundle', 'BaseBundle'); @@ -581,6 +596,9 @@ public function testLocateResourceOnDirectories() ); } + /** + * @group legacy + */ public function testInitializeBundles() { $parent = $this->getBundle(null, null, 'ParentABundle'); @@ -599,6 +617,9 @@ public function testInitializeBundles() $this->assertEquals(array($child, $parent), $map['ParentABundle']); } + /** + * @group legacy + */ public function testInitializeBundlesSupportInheritanceCascade() { $grandparent = $this->getBundle(null, null, 'GrandParentBBundle'); @@ -621,6 +642,7 @@ public function testInitializeBundlesSupportInheritanceCascade() } /** + * @group legacy * @expectedException \LogicException * @expectedExceptionMessage Bundle "ChildCBundle" extends bundle "FooBar", which is not registered. */ @@ -631,6 +653,9 @@ public function testInitializeBundlesThrowsExceptionWhenAParentDoesNotExists() $kernel->boot(); } + /** + * @group legacy + */ public function testInitializeBundlesSupportsArbitraryBundleRegistrationOrder() { $grandparent = $this->getBundle(null, null, 'GrandParentCBundle'); @@ -653,6 +678,7 @@ public function testInitializeBundlesSupportsArbitraryBundleRegistrationOrder() } /** + * @group legacy * @expectedException \LogicException * @expectedExceptionMessage Bundle "ParentCBundle" is directly extended by two bundles "ChildC2Bundle" and "ChildC1Bundle". */ @@ -667,6 +693,7 @@ public function testInitializeBundlesThrowsExceptionWhenABundleIsDirectlyExtende } /** + * @group legacy * @expectedException \LogicException * @expectedExceptionMessage Trying to register two bundles with the same name "DuplicateName" */ @@ -680,6 +707,7 @@ public function testInitializeBundleThrowsExceptionWhenRegisteringTwoBundlesWith } /** + * @group legacy * @expectedException \LogicException * @expectedExceptionMessage Bundle "CircularRefBundle" can not extend itself. */ From 3e90138214c54f8cbf7914706562771b40017cc0 Mon Sep 17 00:00:00 2001 From: SpacePossum Date: Thu, 7 Sep 2017 11:04:22 +0200 Subject: [PATCH 0834/1099] [CS][2.7] yoda_style, no_unneeded_curly_braces, no_unneeded_final_method, semicolon_after_instruction --- .php_cs.dist | 3 ++ .../AbstractDoctrineExtension.php | 6 +-- .../Form/ChoiceList/ORMQueryBuilderLoader.php | 2 +- .../MergeDoctrineCollectionListener.php | 2 +- .../Doctrine/Form/Type/DoctrineType.php | 2 +- .../Bridge/Twig/Command/DebugCommand.php | 20 +++++----- .../Twig/Extension/StopwatchExtension.php | 2 +- ...xtensionBootstrap3HorizontalLayoutTest.php | 2 +- .../FormExtensionBootstrap3LayoutTest.php | 2 +- .../Extension/FormExtensionDivLayoutTest.php | 2 +- .../FormExtensionTableLayoutTest.php | 2 +- .../Command/TranslationUpdateCommand.php | 10 ++--- .../Controller/ControllerNameParser.php | 2 +- .../Controller/RedirectController.php | 2 +- .../Controller/TemplateController.php | 2 +- .../views/FormTable/button_row.html.php | 2 +- .../views/FormTable/form_row.html.php | 6 +-- .../FormTable/form_widget_compound.html.php | 10 ++--- .../views/FormTable/hidden_row.html.php | 2 +- .../FrameworkBundle/Test/KernelTestCase.php | 2 +- .../Fixtures/StubTemplateNameParser.php | 4 +- .../Resources/Child/form_label.html.php | 2 +- .../Parent/form_widget_simple.html.php | 4 +- .../Templating/TemplateFilenameParserTest.php | 2 +- .../SecurityBundle/Command/SetAclCommand.php | 2 +- .../DependencyInjection/MainConfiguration.php | 2 +- .../Security/Factory/RememberMeFactory.php | 2 +- .../CompleteConfigurationTest.php | 2 +- src/Symfony/Component/BrowserKit/History.php | 2 +- .../ClassLoader/ClassCollectionLoader.php | 2 +- .../ClassLoader/ClassMapGenerator.php | 2 +- .../Definition/Dumper/YamlReferenceDumper.php | 2 +- src/Symfony/Component/Config/FileLocator.php | 6 +-- .../Component/Config/Util/XmlUtils.php | 2 +- src/Symfony/Component/Console/Application.php | 8 ++-- .../Console/Descriptor/XmlDescriptor.php | 4 +- .../Component/Console/Helper/DialogHelper.php | 6 +-- .../Console/Helper/ProgressHelper.php | 2 +- .../Console/Helper/QuestionHelper.php | 6 +-- .../Component/Console/Input/ArgvInput.php | 2 +- .../Console/Logger/ConsoleLogger.php | 2 +- .../Tests/Helper/LegacyDialogHelperTest.php | 2 +- .../Tests/Helper/LegacyProgressHelperTest.php | 2 +- .../Tests/Helper/QuestionHelperTest.php | 2 +- .../Parser/Shortcut/EmptyStringParser.php | 2 +- .../DependencyInjection/Container.php | 2 +- .../DependencyInjection/ContainerBuilder.php | 2 +- .../DependencyInjection/Definition.php | 2 +- .../DependencyInjection/Dumper/PhpDumper.php | 6 +-- .../DependencyInjection/Dumper/XmlDumper.php | 4 +- .../Extension/Extension.php | 2 +- .../Loader/XmlFileLoader.php | 4 +- .../Loader/YamlFileLoader.php | 2 +- src/Symfony/Component/DomCrawler/Crawler.php | 2 +- .../DomCrawler/Tests/CrawlerTest.php | 2 +- .../ContainerAwareEventDispatcher.php | 2 +- .../Component/ExpressionLanguage/Parser.php | 6 +-- .../ExpressionLanguage/TokenStream.php | 2 +- .../Component/Filesystem/Filesystem.php | 4 +- .../Finder/Adapter/GnuFindAdapter.php | 2 +- .../Component/Finder/Expression/Regex.php | 4 +- .../Tests/Iterator/SortableIteratorTest.php | 6 +-- .../ChoiceToBooleanArrayTransformer.php | 2 +- .../DateTimeToLocalizedStringTransformer.php | 4 +- .../EventListener/CsrfValidationListener.php | 2 +- .../Component/Form/ResolvedFormType.php | 8 ++-- .../Form/Test/FormPerformanceTestCase.php | 2 +- .../Form/Tests/AbstractLayoutTest.php | 4 +- .../ViolationMapper/ViolationMapperTest.php | 4 +- .../Tests/Fixtures/AlternatingRowType.php | 2 +- .../Tests/Fixtures/FixedDataTransformer.php | 2 +- .../HttpFoundation/AcceptHeaderItem.php | 4 +- .../HttpFoundation/BinaryFileResponse.php | 6 +-- .../HttpFoundation/File/UploadedFile.php | 4 +- .../Component/HttpFoundation/IpUtils.php | 2 +- .../Component/HttpFoundation/Request.php | 28 ++++++------- .../HttpFoundation/RequestMatcher.php | 2 +- .../Component/HttpFoundation/Response.php | 4 +- .../Component/HttpFoundation/ServerBag.php | 2 +- .../Attribute/NamespacedAttributeBag.php | 2 +- .../Handler/MemcachedSessionHandler.php | 2 +- .../Tests/File/MimeType/MimeTypeTest.php | 2 +- .../HttpFoundation/Tests/RequestTest.php | 2 +- .../Component/HttpKernel/HttpCache/Store.php | 2 +- src/Symfony/Component/HttpKernel/Kernel.php | 2 +- .../Profiler/BaseMemcacheProfilerStorage.php | 6 +-- .../Profiler/RedisProfilerStorage.php | 8 ++-- .../Data/Bundle/Compiler/GenrbCompiler.php | 2 +- .../DateFormat/TimeZoneTransformer.php | 4 +- ...odArgumentValueNotImplementedException.php | 2 +- .../Intl/NumberFormatter/NumberFormatter.php | 18 ++++----- .../AbstractCurrencyDataProviderTest.php | 4 +- .../AbstractNumberFormatterTest.php | 6 +-- .../Component/Intl/Util/SvnRepository.php | 6 +-- .../Exception/ProcessTimedOutException.php | 4 +- src/Symfony/Component/Process/Process.php | 8 ++-- .../Component/Process/Tests/ProcessTest.php | 6 +-- .../Exception/UnexpectedTypeException.php | 2 +- .../Matcher/Dumper/PhpMatcherDumper.php | 6 +-- .../Tests/Fixtures/dumper/url_matcher1.php | 36 ++++++++--------- .../Tests/Fixtures/dumper/url_matcher2.php | 40 +++++++++---------- .../Tests/Fixtures/dumper/url_matcher3.php | 4 +- .../Security/Acl/Dbal/MutableAclProvider.php | 8 ++-- .../Tests/Dbal/AclProviderBenchmarkTest.php | 8 ++-- .../Authorization/AccessDecisionManager.php | 2 +- .../Core/User/InMemoryUserProvider.php | 2 +- .../Authentication/AuthenticationUtils.php | 2 +- .../Component/Security/Http/HttpUtils.php | 2 +- .../RememberMe/AbstractRememberMeServices.php | 2 +- ...PersistentTokenBasedRememberMeServices.php | 4 +- .../TokenBasedRememberMeServices.php | 2 +- .../Tests/Firewall/ContextListenerTest.php | 2 +- .../Tests/RememberMe/ResponseListenerTest.php | 2 +- .../Serializer/Encoder/XmlEncoder.php | 8 ++-- .../Normalizer/AbstractNormalizer.php | 2 +- .../Normalizer/GetSetMethodNormalizer.php | 2 +- .../Normalizer/ObjectNormalizer.php | 6 +-- .../Normalizer/PropertyNormalizer.php | 2 +- .../Serializer/Tests/Fixtures/ScalarDummy.php | 4 +- .../Templating/Loader/FilesystemLoader.php | 6 +-- .../Translation/Loader/MoFileLoader.php | 8 ++-- .../Translation/Loader/PoFileLoader.php | 14 +++---- .../Translation/Loader/QtFileLoader.php | 2 +- .../Translation/PluralizationRules.php | 28 ++++++------- .../Component/Translation/Translator.php | 2 +- .../Component/Validator/Constraint.php | 2 +- .../Validator/Constraints/ChoiceValidator.php | 4 +- .../Validator/Constraints/Collection.php | 2 +- .../Validator/Constraints/ImageValidator.php | 2 +- .../Validator/Constraints/TypeValidator.php | 2 +- .../Validator/Constraints/UuidValidator.php | 2 +- .../Mapping/Loader/AbstractLoader.php | 4 +- .../Component/VarDumper/Caster/SplCaster.php | 2 +- .../VarDumper/Tests/VarClonerTest.php | 2 +- src/Symfony/Component/Yaml/Inline.php | 2 +- src/Symfony/Component/Yaml/Parser.php | 10 ++--- src/Symfony/Component/Yaml/Yaml.php | 2 +- 137 files changed, 313 insertions(+), 310 deletions(-) diff --git a/.php_cs.dist b/.php_cs.dist index d84a0624bd3c5..624618ab80a43 100644 --- a/.php_cs.dist +++ b/.php_cs.dist @@ -9,11 +9,14 @@ return PhpCsFixer\Config::create() '@Symfony' => true, '@Symfony:risky' => true, 'array_syntax' => array('syntax' => 'long'), + 'no_break_comment' => false, + 'protected_to_private' => false, )) ->setRiskyAllowed(true) ->setFinder( PhpCsFixer\Finder::create() ->in(__DIR__.'/src') + ->append(array(__FILE__)) ->exclude(array( // directories containing files with content that is autogenerated by `var_export`, which breaks CS in output code 'Symfony/Component/DependencyInjection/Tests/Fixtures', diff --git a/src/Symfony/Bridge/Doctrine/DependencyInjection/AbstractDoctrineExtension.php b/src/Symfony/Bridge/Doctrine/DependencyInjection/AbstractDoctrineExtension.php index b3fecad9df233..c0623572ec606 100644 --- a/src/Symfony/Bridge/Doctrine/DependencyInjection/AbstractDoctrineExtension.php +++ b/src/Symfony/Bridge/Doctrine/DependencyInjection/AbstractDoctrineExtension.php @@ -199,13 +199,13 @@ protected function registerMappingDrivers($objectManager, ContainerBuilder $cont if ($container->hasDefinition($mappingService)) { $mappingDriverDef = $container->getDefinition($mappingService); $args = $mappingDriverDef->getArguments(); - if ($driverType == 'annotation') { + if ('annotation' == $driverType) { $args[1] = array_merge(array_values($driverPaths), $args[1]); } else { $args[0] = array_merge(array_values($driverPaths), $args[0]); } $mappingDriverDef->setArguments($args); - } elseif ($driverType == 'annotation') { + } elseif ('annotation' == $driverType) { $mappingDriverDef = new Definition('%'.$this->getObjectManagerElementName('metadata.'.$driverType.'.class%'), array( new Reference($this->getObjectManagerElementName('metadata.annotation_reader')), array_values($driverPaths), @@ -333,7 +333,7 @@ protected function loadCacheDriver($cacheName, $objectManagerName, array $cacheD $memcacheClass = !empty($cacheDriver['class']) ? $cacheDriver['class'] : '%'.$this->getObjectManagerElementName('cache.memcache.class').'%'; $memcacheInstanceClass = !empty($cacheDriver['instance_class']) ? $cacheDriver['instance_class'] : '%'.$this->getObjectManagerElementName('cache.memcache_instance.class').'%'; $memcacheHost = !empty($cacheDriver['host']) ? $cacheDriver['host'] : '%'.$this->getObjectManagerElementName('cache.memcache_host').'%'; - $memcachePort = !empty($cacheDriver['port']) || (isset($cacheDriver['port']) && $cacheDriver['port'] === 0) ? $cacheDriver['port'] : '%'.$this->getObjectManagerElementName('cache.memcache_port').'%'; + $memcachePort = !empty($cacheDriver['port']) || (isset($cacheDriver['port']) && 0 === $cacheDriver['port']) ? $cacheDriver['port'] : '%'.$this->getObjectManagerElementName('cache.memcache_port').'%'; $cacheDef = new Definition($memcacheClass); $memcacheInstance = new Definition($memcacheInstanceClass); $memcacheInstance->addMethodCall('connect', array( diff --git a/src/Symfony/Bridge/Doctrine/Form/ChoiceList/ORMQueryBuilderLoader.php b/src/Symfony/Bridge/Doctrine/Form/ChoiceList/ORMQueryBuilderLoader.php index 297e2ddfe7a43..8d73c32d9e04b 100644 --- a/src/Symfony/Bridge/Doctrine/Form/ChoiceList/ORMQueryBuilderLoader.php +++ b/src/Symfony/Bridge/Doctrine/Form/ChoiceList/ORMQueryBuilderLoader.php @@ -111,7 +111,7 @@ public function getEntitiesByIds($identifier, array $values) // Like above, but we just filter out empty strings. $values = array_values(array_filter($values, function ($v) { - return (string) $v !== ''; + return '' !== (string) $v; })); } else { $parameterType = Connection::PARAM_STR_ARRAY; diff --git a/src/Symfony/Bridge/Doctrine/Form/EventListener/MergeDoctrineCollectionListener.php b/src/Symfony/Bridge/Doctrine/Form/EventListener/MergeDoctrineCollectionListener.php index 4edf1043c59fc..bb4cfa5087c49 100644 --- a/src/Symfony/Bridge/Doctrine/Form/EventListener/MergeDoctrineCollectionListener.php +++ b/src/Symfony/Bridge/Doctrine/Form/EventListener/MergeDoctrineCollectionListener.php @@ -41,7 +41,7 @@ public function onBind(FormEvent $event) // If all items were removed, call clear which has a higher // performance on persistent collections - if ($collection instanceof Collection && count($data) === 0) { + if ($collection instanceof Collection && 0 === count($data)) { $collection->clear(); } } diff --git a/src/Symfony/Bridge/Doctrine/Form/Type/DoctrineType.php b/src/Symfony/Bridge/Doctrine/Form/Type/DoctrineType.php index 2dd139750c7bd..17036a591322a 100644 --- a/src/Symfony/Bridge/Doctrine/Form/Type/DoctrineType.php +++ b/src/Symfony/Bridge/Doctrine/Form/Type/DoctrineType.php @@ -176,7 +176,7 @@ public function configureOptions(OptionsResolver $resolver) $entityLoader ); - if ($hash !== null) { + if (null !== $hash) { $choiceLoaders[$hash] = $doctrineChoiceLoader; } diff --git a/src/Symfony/Bridge/Twig/Command/DebugCommand.php b/src/Symfony/Bridge/Twig/Command/DebugCommand.php index d62aef0f2c32a..f86013b0e2476 100644 --- a/src/Symfony/Bridge/Twig/Command/DebugCommand.php +++ b/src/Symfony/Bridge/Twig/Command/DebugCommand.php @@ -88,7 +88,7 @@ protected function execute(InputInterface $input, OutputInterface $output) $types = array('functions', 'filters', 'tests', 'globals'); - if ($input->getOption('format') === 'json') { + if ('json' === $input->getOption('format')) { $data = array(); foreach ($types as $type) { foreach ($twig->{'get'.ucfirst($type)}() as $name => $entity) { @@ -129,13 +129,13 @@ protected function execute(InputInterface $input, OutputInterface $output) private function getMetadata($type, $entity) { - if ($type === 'globals') { + if ('globals' === $type) { return $entity; } - if ($type === 'tests') { + if ('tests' === $type) { return; } - if ($type === 'functions' || $type === 'filters') { + if ('functions' === $type || 'filters' === $type) { $cb = $entity->getCallable(); if (null === $cb) { return; @@ -165,7 +165,7 @@ private function getMetadata($type, $entity) array_shift($args); } - if ($type === 'filters') { + if ('filters' === $type) { // remove the value the filter is applied on array_shift($args); } @@ -185,20 +185,20 @@ private function getMetadata($type, $entity) private function getPrettyMetadata($type, $entity) { - if ($type === 'tests') { + if ('tests' === $type) { return ''; } try { $meta = $this->getMetadata($type, $entity); - if ($meta === null) { + if (null === $meta) { return '(unknown?)'; } } catch (\UnexpectedValueException $e) { return ' '.$e->getMessage().''; } - if ($type === 'globals') { + if ('globals' === $type) { if (is_object($meta)) { return ' = object('.get_class($meta).')'; } @@ -206,11 +206,11 @@ private function getPrettyMetadata($type, $entity) return ' = '.substr(@json_encode($meta), 0, 50); } - if ($type === 'functions') { + if ('functions' === $type) { return '('.implode(', ', $meta).')'; } - if ($type === 'filters') { + if ('filters' === $type) { return $meta ? '('.implode(', ', $meta).')' : ''; } } diff --git a/src/Symfony/Bridge/Twig/Extension/StopwatchExtension.php b/src/Symfony/Bridge/Twig/Extension/StopwatchExtension.php index 635188b7389e4..cb91ff428b0a2 100644 --- a/src/Symfony/Bridge/Twig/Extension/StopwatchExtension.php +++ b/src/Symfony/Bridge/Twig/Extension/StopwatchExtension.php @@ -48,7 +48,7 @@ public function getTokenParsers() * Some stuff which will be recorded on the timeline * {% endstopwatch %} */ - new StopwatchTokenParser($this->stopwatch !== null && $this->enabled), + new StopwatchTokenParser(null !== $this->stopwatch && $this->enabled), ); } diff --git a/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionBootstrap3HorizontalLayoutTest.php b/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionBootstrap3HorizontalLayoutTest.php index 9d84946177af2..3fb3a19c277ef 100644 --- a/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionBootstrap3HorizontalLayoutTest.php +++ b/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionBootstrap3HorizontalLayoutTest.php @@ -75,7 +75,7 @@ protected function renderEnctype(FormView $view) protected function renderLabel(FormView $view, $label = null, array $vars = array()) { - if ($label !== null) { + if (null !== $label) { $vars += array('label' => $label); } diff --git a/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionBootstrap3LayoutTest.php b/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionBootstrap3LayoutTest.php index 10161cbd4e1a7..85ef2ceed53af 100644 --- a/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionBootstrap3LayoutTest.php +++ b/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionBootstrap3LayoutTest.php @@ -75,7 +75,7 @@ protected function renderEnctype(FormView $view) protected function renderLabel(FormView $view, $label = null, array $vars = array()) { - if ($label !== null) { + if (null !== $label) { $vars += array('label' => $label); } diff --git a/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionDivLayoutTest.php b/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionDivLayoutTest.php index 2d7339b369d30..e2fbb48ce0339 100644 --- a/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionDivLayoutTest.php +++ b/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionDivLayoutTest.php @@ -158,7 +158,7 @@ protected function renderEnctype(FormView $view) protected function renderLabel(FormView $view, $label = null, array $vars = array()) { - if ($label !== null) { + if (null !== $label) { $vars += array('label' => $label); } diff --git a/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionTableLayoutTest.php b/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionTableLayoutTest.php index 1d526d5138fa5..1b5f4022daeb3 100644 --- a/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionTableLayoutTest.php +++ b/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionTableLayoutTest.php @@ -76,7 +76,7 @@ protected function renderEnctype(FormView $view) protected function renderLabel(FormView $view, $label = null, array $vars = array()) { - if ($label !== null) { + if (null !== $label) { $vars += array('label' => $label); } diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/TranslationUpdateCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/TranslationUpdateCommand.php index f310613d10315..3f1605da582b9 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/TranslationUpdateCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/TranslationUpdateCommand.php @@ -72,7 +72,7 @@ protected function execute(InputInterface $input, OutputInterface $output) $output = new SymfonyStyle($input, $output); // check presence of force or dump-message - if ($input->getOption('force') !== true && $input->getOption('dump-messages') !== true) { + if (true !== $input->getOption('force') && true !== $input->getOption('dump-messages')) { $output->error('You must choose one of --force or --dump-messages'); return 1; @@ -151,7 +151,7 @@ protected function execute(InputInterface $input, OutputInterface $output) } // show compiled list of messages - if ($input->getOption('dump-messages') === true) { + if (true === $input->getOption('dump-messages')) { $output->newLine(); foreach ($operation->getDomains() as $domain) { $output->section(sprintf('Displaying messages for domain %s:', $domain)); @@ -168,17 +168,17 @@ protected function execute(InputInterface $input, OutputInterface $output) )); } - if ($input->getOption('output-format') == 'xlf') { + if ('xlf' == $input->getOption('output-format')) { $output->writeln('Xliff output version is 1.2'); } } - if ($input->getOption('no-backup') === true) { + if (true === $input->getOption('no-backup')) { $writer->disableBackup(); } // save the files - if ($input->getOption('force') === true) { + if (true === $input->getOption('force')) { $output->text('Writing files'); $bundleTransPath = false; diff --git a/src/Symfony/Bundle/FrameworkBundle/Controller/ControllerNameParser.php b/src/Symfony/Bundle/FrameworkBundle/Controller/ControllerNameParser.php index 989dc8cd23d7c..5cfb30f3713ce 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Controller/ControllerNameParser.php +++ b/src/Symfony/Bundle/FrameworkBundle/Controller/ControllerNameParser.php @@ -141,7 +141,7 @@ private function findAlternative($nonExistentBundleName) } $lev = levenshtein($nonExistentBundleName, $bundleName); - if ($lev <= strlen($nonExistentBundleName) / 3 && ($alternative === null || $lev < $shortest)) { + if ($lev <= strlen($nonExistentBundleName) / 3 && (null === $alternative || $lev < $shortest)) { $alternative = $bundleName; $shortest = $lev; } diff --git a/src/Symfony/Bundle/FrameworkBundle/Controller/RedirectController.php b/src/Symfony/Bundle/FrameworkBundle/Controller/RedirectController.php index b8f4e6415a540..9d060ed43ad3d 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Controller/RedirectController.php +++ b/src/Symfony/Bundle/FrameworkBundle/Controller/RedirectController.php @@ -100,7 +100,7 @@ public function urlRedirectAction(Request $request, $path, $permanent = false, $ $qs = $request->getQueryString(); if ($qs) { - if (strpos($path, '?') === false) { + if (false === strpos($path, '?')) { $qs = '?'.$qs; } else { $qs = '&'.$qs; diff --git a/src/Symfony/Bundle/FrameworkBundle/Controller/TemplateController.php b/src/Symfony/Bundle/FrameworkBundle/Controller/TemplateController.php index 16d15f902340c..f75ab2d79514f 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Controller/TemplateController.php +++ b/src/Symfony/Bundle/FrameworkBundle/Controller/TemplateController.php @@ -46,7 +46,7 @@ public function templateAction($template, $maxAge = null, $sharedAge = null, $pr if ($private) { $response->setPrivate(); - } elseif ($private === false || (null === $private && ($maxAge || $sharedAge))) { + } elseif (false === $private || (null === $private && ($maxAge || $sharedAge))) { $response->setPublic(); } diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/views/FormTable/button_row.html.php b/src/Symfony/Bundle/FrameworkBundle/Resources/views/FormTable/button_row.html.php index ef4d22b975081..67d0137e20b97 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/views/FormTable/button_row.html.php +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/views/FormTable/button_row.html.php @@ -1,6 +1,6 @@ - widget($form) ?> + widget($form); ?> diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/views/FormTable/form_row.html.php b/src/Symfony/Bundle/FrameworkBundle/Resources/views/FormTable/form_row.html.php index 7e1f2f5d28db8..e2f03ff2b7064 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/views/FormTable/form_row.html.php +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/views/FormTable/form_row.html.php @@ -1,9 +1,9 @@ - label($form) ?> + label($form); ?> - errors($form) ?> - widget($form) ?> + errors($form); ?> + widget($form); ?> diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/views/FormTable/form_widget_compound.html.php b/src/Symfony/Bundle/FrameworkBundle/Resources/views/FormTable/form_widget_compound.html.php index 20b9668aa49c9..adc897338861b 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/views/FormTable/form_widget_compound.html.php +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/views/FormTable/form_widget_compound.html.php @@ -1,11 +1,11 @@ -block($form, 'widget_container_attributes') ?>> +
block($form, 'widget_container_attributes'); ?>> parent && $errors): ?> - - block($form, 'form_rows') ?> - rest($form) ?> + + block($form, 'form_rows'); ?> + rest($form); ?>
- errors($form) ?> + errors($form); ?>
diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/views/FormTable/hidden_row.html.php b/src/Symfony/Bundle/FrameworkBundle/Resources/views/FormTable/hidden_row.html.php index 491ece3602327..116b300bd5619 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/views/FormTable/hidden_row.html.php +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/views/FormTable/hidden_row.html.php @@ -1,5 +1,5 @@ - widget($form) ?> + widget($form); ?> diff --git a/src/Symfony/Bundle/FrameworkBundle/Test/KernelTestCase.php b/src/Symfony/Bundle/FrameworkBundle/Test/KernelTestCase.php index 5dadca83f2e1b..6b979c4f36118 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Test/KernelTestCase.php +++ b/src/Symfony/Bundle/FrameworkBundle/Test/KernelTestCase.php @@ -77,7 +77,7 @@ private static function getPhpUnitCliConfigArgument() $dir = null; $reversedArgs = array_reverse($_SERVER['argv']); foreach ($reversedArgs as $argIndex => $testArg) { - if (preg_match('/^-[^ \-]*c$/', $testArg) || $testArg === '--configuration') { + if (preg_match('/^-[^ \-]*c$/', $testArg) || '--configuration' === $testArg) { $dir = realpath($reversedArgs[$argIndex - 1]); break; } elseif (0 === strpos($testArg, '--configuration=')) { diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Templating/Helper/Fixtures/StubTemplateNameParser.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Templating/Helper/Fixtures/StubTemplateNameParser.php index 3a66454947977..9835bc2a228ea 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Templating/Helper/Fixtures/StubTemplateNameParser.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Templating/Helper/Fixtures/StubTemplateNameParser.php @@ -30,9 +30,9 @@ public function parse($name) { list($bundle, $controller, $template) = explode(':', $name, 3); - if ($template[0] == '_') { + if ('_' == $template[0]) { $path = $this->rootTheme.'/Custom/'.$template; - } elseif ($bundle === 'TestBundle') { + } elseif ('TestBundle' === $bundle) { $path = $this->rootTheme.'/'.$controller.'/'.$template; } else { $path = $this->root.'/'.$controller.'/'.$template; diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Templating/Helper/Resources/Child/form_label.html.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Templating/Helper/Resources/Child/form_label.html.php index 0c1af407cb9fc..aebb53d3e7221 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Templating/Helper/Resources/Child/form_label.html.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Templating/Helper/Resources/Child/form_label.html.php @@ -1 +1 @@ - + diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Templating/Helper/Resources/Parent/form_widget_simple.html.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Templating/Helper/Resources/Parent/form_widget_simple.html.php index 3c6c158a53d8c..1b53a7213f025 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Templating/Helper/Resources/Parent/form_widget_simple.html.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Templating/Helper/Resources/Parent/form_widget_simple.html.php @@ -1,2 +1,2 @@ - -block($form, 'widget_attributes') ?> value="" rel="theme" /> + +block($form, 'widget_attributes'); ?> value="" rel="theme" /> diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Templating/TemplateFilenameParserTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Templating/TemplateFilenameParserTest.php index 77dd2699ab9ea..8cdc26ecfe292 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Templating/TemplateFilenameParserTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Templating/TemplateFilenameParserTest.php @@ -36,7 +36,7 @@ public function testParseFromFilename($file, $ref) { $template = $this->parser->parse($file); - if ($ref === false) { + if (false === $ref) { $this->assertFalse($template); } else { $this->assertEquals($template->getLogicalName(), $ref->getLogicalName()); diff --git a/src/Symfony/Bundle/SecurityBundle/Command/SetAclCommand.php b/src/Symfony/Bundle/SecurityBundle/Command/SetAclCommand.php index ba34782346275..7d0f3a261b123 100644 --- a/src/Symfony/Bundle/SecurityBundle/Command/SetAclCommand.php +++ b/src/Symfony/Bundle/SecurityBundle/Command/SetAclCommand.php @@ -120,7 +120,7 @@ protected function execute(InputInterface $input, OutputInterface $output) foreach ($userOption as $user) { $data = explode(':', $user, 2); - if (count($data) === 1) { + if (1 === count($data)) { throw new \InvalidArgumentException('The user must follow the format "Acme/MyUser:username".'); } diff --git a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/MainConfiguration.php b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/MainConfiguration.php index df6380224cd20..382c4ade6af8b 100644 --- a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/MainConfiguration.php +++ b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/MainConfiguration.php @@ -394,7 +394,7 @@ private function addProvidersSection(ArrayNodeDefinition $rootNode) ->thenInvalid('You cannot set multiple provider types for the same provider') ->end() ->validate() - ->ifTrue(function ($v) { return count($v) === 0; }) + ->ifTrue(function ($v) { return 0 === count($v); }) ->thenInvalid('You must set a provider definition for the provider.') ->end() ; diff --git a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/RememberMeFactory.php b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/RememberMeFactory.php index c6688affb40ae..a77d872e26c40 100644 --- a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/RememberMeFactory.php +++ b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/RememberMeFactory.php @@ -93,7 +93,7 @@ public function create(ContainerBuilder $container, $id, $config, $userProvider, $userProviders[] = new Reference('security.user.provider.concrete.'.$providerName); } } - if (count($userProviders) === 0) { + if (0 === count($userProviders)) { throw new \RuntimeException('You must configure at least one remember-me aware listener (such as form-login) for each firewall that has remember-me enabled.'); } diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/CompleteConfigurationTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/CompleteConfigurationTest.php index d273fb05942b3..6da50316a4721 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/CompleteConfigurationTest.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/CompleteConfigurationTest.php @@ -133,7 +133,7 @@ public function testAccess() $rules = array(); foreach ($container->getDefinition('security.access_map')->getMethodCalls() as $call) { - if ($call[0] == 'add') { + if ('add' == $call[0]) { $rules[] = array((string) $call[1][0], $call[1][1], $call[1][2]); } } diff --git a/src/Symfony/Component/BrowserKit/History.php b/src/Symfony/Component/BrowserKit/History.php index 8e38fe5ca8711..13af2b4f37927 100644 --- a/src/Symfony/Component/BrowserKit/History.php +++ b/src/Symfony/Component/BrowserKit/History.php @@ -49,7 +49,7 @@ public function add(Request $request) */ public function isEmpty() { - return count($this->stack) == 0; + return 0 == count($this->stack); } /** diff --git a/src/Symfony/Component/ClassLoader/ClassCollectionLoader.php b/src/Symfony/Component/ClassLoader/ClassCollectionLoader.php index cd3c433ed200a..3f2a8ab1c99fc 100644 --- a/src/Symfony/Component/ClassLoader/ClassCollectionLoader.php +++ b/src/Symfony/Component/ClassLoader/ClassCollectionLoader.php @@ -215,7 +215,7 @@ public static function fixNamespaceDeclarations($source) do { $token = $tokens[++$i]; $output .= isset($token[1]) && 'b"' !== $token ? $token[1] : $token; - } while ($token[0] !== T_END_HEREDOC); + } while (T_END_HEREDOC !== $token[0]); $output .= "\n"; $rawChunk = ''; } elseif (T_CONSTANT_ENCAPSED_STRING === $token[0]) { diff --git a/src/Symfony/Component/ClassLoader/ClassMapGenerator.php b/src/Symfony/Component/ClassLoader/ClassMapGenerator.php index a35c90ca10d8b..ab9762cd04e5d 100644 --- a/src/Symfony/Component/ClassLoader/ClassMapGenerator.php +++ b/src/Symfony/Component/ClassLoader/ClassMapGenerator.php @@ -66,7 +66,7 @@ public static function createMap($dir) $path = $file->getRealPath() ?: $file->getPathname(); - if (pathinfo($path, PATHINFO_EXTENSION) !== 'php') { + if ('php' !== pathinfo($path, PATHINFO_EXTENSION)) { continue; } diff --git a/src/Symfony/Component/Config/Definition/Dumper/YamlReferenceDumper.php b/src/Symfony/Component/Config/Definition/Dumper/YamlReferenceDumper.php index 12ababe39435b..2b103d9533b09 100644 --- a/src/Symfony/Component/Config/Definition/Dumper/YamlReferenceDumper.php +++ b/src/Symfony/Component/Config/Definition/Dumper/YamlReferenceDumper.php @@ -117,7 +117,7 @@ private function writeNode(NodeInterface $node, $depth = 0) $comments[] = 'Example: '.$example; } - $default = (string) $default != '' ? ' '.$default : ''; + $default = '' != (string) $default ? ' '.$default : ''; $comments = count($comments) ? '# '.implode(', ', $comments) : ''; $text = rtrim(sprintf('%-21s%s %s', $node->getName().':', $default, $comments), ' '); diff --git a/src/Symfony/Component/Config/FileLocator.php b/src/Symfony/Component/Config/FileLocator.php index 4816724c8190e..94e7e23b43729 100644 --- a/src/Symfony/Component/Config/FileLocator.php +++ b/src/Symfony/Component/Config/FileLocator.php @@ -81,10 +81,10 @@ public function locate($name, $currentPath = null, $first = true) */ private function isAbsolutePath($file) { - if ($file[0] === '/' || $file[0] === '\\' + if ('/' === $file[0] || '\\' === $file[0] || (strlen($file) > 3 && ctype_alpha($file[0]) - && $file[1] === ':' - && ($file[2] === '\\' || $file[2] === '/') + && ':' === $file[1] + && ('\\' === $file[2] || '/' === $file[2]) ) || null !== parse_url($file, PHP_URL_SCHEME) ) { diff --git a/src/Symfony/Component/Config/Util/XmlUtils.php b/src/Symfony/Component/Config/Util/XmlUtils.php index 0f16fc080bf05..9c7ac126ef1ca 100644 --- a/src/Symfony/Component/Config/Util/XmlUtils.php +++ b/src/Symfony/Component/Config/Util/XmlUtils.php @@ -68,7 +68,7 @@ public static function loadFile($file, $schemaOrCallable = null) libxml_disable_entity_loader($disableEntities); foreach ($dom->childNodes as $child) { - if ($child->nodeType === XML_DOCUMENT_TYPE_NODE) { + if (XML_DOCUMENT_TYPE_NODE === $child->nodeType) { throw new \InvalidArgumentException('Document types are not allowed.'); } } diff --git a/src/Symfony/Component/Console/Application.php b/src/Symfony/Component/Console/Application.php index 873b09e808729..21b2e8ea5c40a 100644 --- a/src/Symfony/Component/Console/Application.php +++ b/src/Symfony/Component/Console/Application.php @@ -709,8 +709,8 @@ public function renderException($e, $output) $trace = $e->getTrace(); array_unshift($trace, array( 'function' => '', - 'file' => $e->getFile() !== null ? $e->getFile() : 'n/a', - 'line' => $e->getLine() !== null ? $e->getLine() : 'n/a', + 'file' => null !== $e->getFile() ? $e->getFile() : 'n/a', + 'line' => null !== $e->getLine() ? $e->getLine() : 'n/a', 'args' => array(), )); @@ -838,9 +838,9 @@ protected function configureIO(InputInterface $input, OutputInterface $output) $output->setVerbosity(OutputInterface::VERBOSITY_QUIET); $input->setInteractive(false); } else { - if ($input->hasParameterOption('-vvv') || $input->hasParameterOption('--verbose=3') || $input->getParameterOption('--verbose') === 3) { + if ($input->hasParameterOption('-vvv') || $input->hasParameterOption('--verbose=3') || 3 === $input->getParameterOption('--verbose')) { $output->setVerbosity(OutputInterface::VERBOSITY_DEBUG); - } elseif ($input->hasParameterOption('-vv') || $input->hasParameterOption('--verbose=2') || $input->getParameterOption('--verbose') === 2) { + } elseif ($input->hasParameterOption('-vv') || $input->hasParameterOption('--verbose=2') || 2 === $input->getParameterOption('--verbose')) { $output->setVerbosity(OutputInterface::VERBOSITY_VERY_VERBOSE); } elseif ($input->hasParameterOption('-v') || $input->hasParameterOption('--verbose=1') || $input->hasParameterOption('--verbose') || $input->getParameterOption('--verbose')) { $output->setVerbosity(OutputInterface::VERBOSITY_VERBOSE); diff --git a/src/Symfony/Component/Console/Descriptor/XmlDescriptor.php b/src/Symfony/Component/Console/Descriptor/XmlDescriptor.php index b5676beb3766f..0f1fb472c25c8 100644 --- a/src/Symfony/Component/Console/Descriptor/XmlDescriptor.php +++ b/src/Symfony/Component/Console/Descriptor/XmlDescriptor.php @@ -94,9 +94,9 @@ public function getApplicationDocument(Application $application, $namespace = nu $dom = new \DOMDocument('1.0', 'UTF-8'); $dom->appendChild($rootXml = $dom->createElement('symfony')); - if ($application->getName() !== 'UNKNOWN') { + if ('UNKNOWN' !== $application->getName()) { $rootXml->setAttribute('name', $application->getName()); - if ($application->getVersion() !== 'UNKNOWN') { + if ('UNKNOWN' !== $application->getVersion()) { $rootXml->setAttribute('version', $application->getVersion()); } } diff --git a/src/Symfony/Component/Console/Helper/DialogHelper.php b/src/Symfony/Component/Console/Helper/DialogHelper.php index 7f5a5df2cea81..342fe02638604 100644 --- a/src/Symfony/Component/Console/Helper/DialogHelper.php +++ b/src/Symfony/Component/Console/Helper/DialogHelper.php @@ -159,7 +159,7 @@ public function ask(OutputInterface $output, $question, $default = null, array $ $output->write("\033[1D"); } - if ($i === 0) { + if (0 === $i) { $ofs = -1; $matches = $autocomplete; $numMatches = count($matches); @@ -324,7 +324,7 @@ public function askHiddenResponse(OutputInterface $output, $question, $fallback if (false !== $shell = $this->getShell()) { $output->write($question); - $readCmd = $shell === 'csh' ? 'set mypassword = $<' : 'read -r mypassword'; + $readCmd = 'csh' === $shell ? 'set mypassword = $<' : 'read -r mypassword'; $command = sprintf("/usr/bin/env %s -c 'stty -echo; %s; stty echo; echo \$mypassword'", $shell, $readCmd); $value = rtrim(shell_exec($command)); $output->writeln(''); @@ -462,7 +462,7 @@ private function hasSttyAvailable() exec('stty 2>&1', $output, $exitcode); - return self::$stty = $exitcode === 0; + return self::$stty = 0 === $exitcode; } /** diff --git a/src/Symfony/Component/Console/Helper/ProgressHelper.php b/src/Symfony/Component/Console/Helper/ProgressHelper.php index 625fb8120824a..b95befe00f870 100644 --- a/src/Symfony/Component/Console/Helper/ProgressHelper.php +++ b/src/Symfony/Component/Console/Helper/ProgressHelper.php @@ -423,7 +423,7 @@ private function humaneTime($secs) $text = ''; foreach ($this->timeFormats as $format) { if ($secs < $format[0]) { - if (count($format) == 2) { + if (2 == count($format)) { $text = $format[1]; break; } else { diff --git a/src/Symfony/Component/Console/Helper/QuestionHelper.php b/src/Symfony/Component/Console/Helper/QuestionHelper.php index 676c3c045114f..4cdecfd41a49a 100644 --- a/src/Symfony/Component/Console/Helper/QuestionHelper.php +++ b/src/Symfony/Component/Console/Helper/QuestionHelper.php @@ -235,7 +235,7 @@ private function autocomplete(OutputInterface $output, Question $question, $inpu $output->write("\033[1D"); } - if ($i === 0) { + if (0 === $i) { $ofs = -1; $matches = $autocomplete; $numMatches = count($matches); @@ -365,7 +365,7 @@ private function getHiddenResponse(OutputInterface $output, $inputStream) } if (false !== $shell = $this->getShell()) { - $readCmd = $shell === 'csh' ? 'set mypassword = $<' : 'read -r mypassword'; + $readCmd = 'csh' === $shell ? 'set mypassword = $<' : 'read -r mypassword'; $command = sprintf("/usr/bin/env %s -c 'stty -echo; %s; stty echo; echo \$mypassword'", $shell, $readCmd); $value = rtrim(shell_exec($command)); $output->writeln(''); @@ -447,6 +447,6 @@ private function hasSttyAvailable() exec('stty 2>&1', $output, $exitcode); - return self::$stty = $exitcode === 0; + return self::$stty = 0 === $exitcode; } } diff --git a/src/Symfony/Component/Console/Input/ArgvInput.php b/src/Symfony/Component/Console/Input/ArgvInput.php index 119be49170853..55df649ed7efb 100644 --- a/src/Symfony/Component/Console/Input/ArgvInput.php +++ b/src/Symfony/Component/Console/Input/ArgvInput.php @@ -328,7 +328,7 @@ public function __toString() return $match[1].$self->escapeToken($match[2]); } - if ($token && $token[0] !== '-') { + if ($token && '-' !== $token[0]) { return $self->escapeToken($token); } diff --git a/src/Symfony/Component/Console/Logger/ConsoleLogger.php b/src/Symfony/Component/Console/Logger/ConsoleLogger.php index 987e96a6587e5..4b237c17c6904 100644 --- a/src/Symfony/Component/Console/Logger/ConsoleLogger.php +++ b/src/Symfony/Component/Console/Logger/ConsoleLogger.php @@ -82,7 +82,7 @@ public function log($level, $message, array $context = array()) } // Write to the error output if necessary and available - if ($this->formatLevelMap[$level] === self::ERROR && $this->output instanceof ConsoleOutputInterface) { + if (self::ERROR === $this->formatLevelMap[$level] && $this->output instanceof ConsoleOutputInterface) { $output = $this->output->getErrorOutput(); } else { $output = $this->output; diff --git a/src/Symfony/Component/Console/Tests/Helper/LegacyDialogHelperTest.php b/src/Symfony/Component/Console/Tests/Helper/LegacyDialogHelperTest.php index d50366d1bf063..b7d1b5cf19e66 100644 --- a/src/Symfony/Component/Console/Tests/Helper/LegacyDialogHelperTest.php +++ b/src/Symfony/Component/Console/Tests/Helper/LegacyDialogHelperTest.php @@ -253,6 +253,6 @@ private function hasSttyAvailable() { exec('stty 2>&1', $output, $exitcode); - return $exitcode === 0; + return 0 === $exitcode; } } diff --git a/src/Symfony/Component/Console/Tests/Helper/LegacyProgressHelperTest.php b/src/Symfony/Component/Console/Tests/Helper/LegacyProgressHelperTest.php index 2e473c2eef170..76d003e78d18a 100644 --- a/src/Symfony/Component/Console/Tests/Helper/LegacyProgressHelperTest.php +++ b/src/Symfony/Component/Console/Tests/Helper/LegacyProgressHelperTest.php @@ -217,7 +217,7 @@ protected function generateOutput($expected) { $expectedout = $expected; - if ($this->lastMessagesLength !== null) { + if (null !== $this->lastMessagesLength) { $expectedout = str_pad($expected, $this->lastMessagesLength, "\x20", STR_PAD_RIGHT); } diff --git a/src/Symfony/Component/Console/Tests/Helper/QuestionHelperTest.php b/src/Symfony/Component/Console/Tests/Helper/QuestionHelperTest.php index 7d450252301be..4fb462cc1048d 100644 --- a/src/Symfony/Component/Console/Tests/Helper/QuestionHelperTest.php +++ b/src/Symfony/Component/Console/Tests/Helper/QuestionHelperTest.php @@ -502,6 +502,6 @@ private function hasSttyAvailable() { exec('stty 2>&1', $output, $exitcode); - return $exitcode === 0; + return 0 === $exitcode; } } diff --git a/src/Symfony/Component/CssSelector/Parser/Shortcut/EmptyStringParser.php b/src/Symfony/Component/CssSelector/Parser/Shortcut/EmptyStringParser.php index 98a08fde069ea..a35450dcd0338 100644 --- a/src/Symfony/Component/CssSelector/Parser/Shortcut/EmptyStringParser.php +++ b/src/Symfony/Component/CssSelector/Parser/Shortcut/EmptyStringParser.php @@ -35,7 +35,7 @@ class EmptyStringParser implements ParserInterface public function parse($source) { // Matches an empty string - if ($source == '') { + if ('' == $source) { return array(new SelectorNode(new ElementNode(null, '*'))); } diff --git a/src/Symfony/Component/DependencyInjection/Container.php b/src/Symfony/Component/DependencyInjection/Container.php index 4019504a5a199..0ba5d646c89cf 100644 --- a/src/Symfony/Component/DependencyInjection/Container.php +++ b/src/Symfony/Component/DependencyInjection/Container.php @@ -477,7 +477,7 @@ public function addScope(ScopeInterface $scope) $this->scopeChildren[$name] = array(); // normalize the child relations - while ($parentScope !== self::SCOPE_CONTAINER) { + while (self::SCOPE_CONTAINER !== $parentScope) { $this->scopeChildren[$parentScope][] = $name; $parentScope = $this->scopes[$parentScope]; } diff --git a/src/Symfony/Component/DependencyInjection/ContainerBuilder.php b/src/Symfony/Component/DependencyInjection/ContainerBuilder.php index c1a2ee85c42c5..f9658fcf68e04 100644 --- a/src/Symfony/Component/DependencyInjection/ContainerBuilder.php +++ b/src/Symfony/Component/DependencyInjection/ContainerBuilder.php @@ -1038,7 +1038,7 @@ public static function getServiceConditionals($value) foreach ($value as $v) { $services = array_unique(array_merge($services, self::getServiceConditionals($v))); } - } elseif ($value instanceof Reference && $value->getInvalidBehavior() === ContainerInterface::IGNORE_ON_INVALID_REFERENCE) { + } elseif ($value instanceof Reference && ContainerInterface::IGNORE_ON_INVALID_REFERENCE === $value->getInvalidBehavior()) { $services[] = (string) $value; } diff --git a/src/Symfony/Component/DependencyInjection/Definition.php b/src/Symfony/Component/DependencyInjection/Definition.php index 780ad187cdba5..97b491328677f 100644 --- a/src/Symfony/Component/DependencyInjection/Definition.php +++ b/src/Symfony/Component/DependencyInjection/Definition.php @@ -60,7 +60,7 @@ public function __construct($class = null, array $arguments = array()) */ public function setFactory($factory) { - if (is_string($factory) && strpos($factory, '::') !== false) { + if (is_string($factory) && false !== strpos($factory, '::')) { $factory = explode('::', $factory, 2); } diff --git a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php index 4d576df1bd6c8..e67c0869f4071 100644 --- a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php +++ b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php @@ -533,7 +533,7 @@ private function addServiceConfigurator(Definition $definition, $variableName = $class = $this->dumpValue($callable[0]); // If the class is a string we can optimize call_user_func away - if (strpos($class, "'") === 0) { + if (0 === strpos($class, "'")) { return sprintf(" %s::%s(\$%s);\n", $this->dumpLiteralClass($class), $callable[1], $variableName); } @@ -753,7 +753,7 @@ private function addNewInstance($id, Definition $definition, $return, $instantia $class = $this->dumpValue($callable[0]); // If the class is a string we can optimize call_user_func away - if (strpos($class, "'") === 0) { + if (0 === strpos($class, "'")) { return sprintf(" $return{$instantiation}%s::%s(%s);\n", $this->dumpLiteralClass($class), $callable[1], $arguments ? implode(', ', $arguments) : ''); } @@ -766,7 +766,7 @@ private function addNewInstance($id, Definition $definition, $return, $instantia $class = $this->dumpValue($definition->getFactoryClass(false)); // If the class is a string we can optimize call_user_func away - if (strpos($class, "'") === 0) { + if (0 === strpos($class, "'")) { return sprintf(" $return{$instantiation}%s::%s(%s);\n", $this->dumpLiteralClass($class), $definition->getFactoryMethod(false), $arguments ? implode(', ', $arguments) : ''); } diff --git a/src/Symfony/Component/DependencyInjection/Dumper/XmlDumper.php b/src/Symfony/Component/DependencyInjection/Dumper/XmlDumper.php index c793e9aed0f3d..4a4ac00d08310 100644 --- a/src/Symfony/Component/DependencyInjection/Dumper/XmlDumper.php +++ b/src/Symfony/Component/DependencyInjection/Dumper/XmlDumper.php @@ -282,9 +282,9 @@ private function convertParameters(array $parameters, $type, \DOMElement $parent $element->setAttribute('type', 'service'); $element->setAttribute('id', (string) $value); $behaviour = $value->getInvalidBehavior(); - if ($behaviour == ContainerInterface::NULL_ON_INVALID_REFERENCE) { + if (ContainerInterface::NULL_ON_INVALID_REFERENCE == $behaviour) { $element->setAttribute('on-invalid', 'null'); - } elseif ($behaviour == ContainerInterface::IGNORE_ON_INVALID_REFERENCE) { + } elseif (ContainerInterface::IGNORE_ON_INVALID_REFERENCE == $behaviour) { $element->setAttribute('on-invalid', 'ignore'); } if (!$value->isStrict()) { diff --git a/src/Symfony/Component/DependencyInjection/Extension/Extension.php b/src/Symfony/Component/DependencyInjection/Extension/Extension.php index ced39f7281b6c..5a6573b70e0da 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); - if (substr($className, -9) != 'Extension') { + if ('Extension' != substr($className, -9)) { throw new BadMethodCallException('This extension does not follow the naming convention; you must overwrite the getAlias() method.'); } $classBaseName = substr(strrchr($className, '\\'), 1, -9); diff --git a/src/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php b/src/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php index b3e4ef4d3e7c1..bc57828f35187 100644 --- a/src/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php +++ b/src/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php @@ -414,7 +414,7 @@ private function getChildren(\DOMNode $node, $name) { $children = array(); foreach ($node->childNodes as $child) { - if ($child instanceof \DOMElement && $child->localName === $name && $child->namespaceURI === self::NS) { + if ($child instanceof \DOMElement && $child->localName === $name && self::NS === $child->namespaceURI) { $children[] = $child; } } @@ -533,7 +533,7 @@ private function validateExtensions(\DOMDocument $dom, $file) private function loadFromExtensions(\DOMDocument $xml) { foreach ($xml->documentElement->childNodes as $node) { - if (!$node instanceof \DOMElement || $node->namespaceURI === self::NS) { + if (!$node instanceof \DOMElement || self::NS === $node->namespaceURI) { continue; } diff --git a/src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php b/src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php index d93891e9c8c52..ba12fdc821bc2 100644 --- a/src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php +++ b/src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php @@ -192,7 +192,7 @@ private function parseDefinition($id, $service, $file) if (isset($service['factory'])) { if (is_string($service['factory'])) { - if (strpos($service['factory'], ':') !== false && strpos($service['factory'], '::') === false) { + if (false !== strpos($service['factory'], ':') && false === strpos($service['factory'], '::')) { $parts = explode(':', $service['factory']); $definition->setFactory(array($this->resolveServices('@'.$parts[0]), $parts[1])); } else { diff --git a/src/Symfony/Component/DomCrawler/Crawler.php b/src/Symfony/Component/DomCrawler/Crawler.php index f711c02bfff83..e54dd9b9f1f91 100644 --- a/src/Symfony/Component/DomCrawler/Crawler.php +++ b/src/Symfony/Component/DomCrawler/Crawler.php @@ -969,7 +969,7 @@ protected function sibling($node, $siblingDir = 'nextSibling') $nodes = array(); do { - if ($node !== $this->getNode(0) && $node->nodeType === 1) { + if ($node !== $this->getNode(0) && 1 === $node->nodeType) { $nodes[] = $node; } } while ($node = $node->$siblingDir); diff --git a/src/Symfony/Component/DomCrawler/Tests/CrawlerTest.php b/src/Symfony/Component/DomCrawler/Tests/CrawlerTest.php index 495a4a9d14a34..335406ab2460d 100644 --- a/src/Symfony/Component/DomCrawler/Tests/CrawlerTest.php +++ b/src/Symfony/Component/DomCrawler/Tests/CrawlerTest.php @@ -295,7 +295,7 @@ public function testReduce() { $crawler = $this->createTestCrawler()->filterXPath('//ul[1]/li'); $nodes = $crawler->reduce(function ($node, $i) { - return $i !== 1; + return 1 !== $i; }); $this->assertNotSame($nodes, $crawler, '->reduce() returns a new instance of a crawler'); $this->assertInstanceOf('Symfony\\Component\\DomCrawler\\Crawler', $nodes, '->reduce() returns a new instance of a crawler'); diff --git a/src/Symfony/Component/EventDispatcher/ContainerAwareEventDispatcher.php b/src/Symfony/Component/EventDispatcher/ContainerAwareEventDispatcher.php index dc2816f16906b..1c5e5b1d554a7 100644 --- a/src/Symfony/Component/EventDispatcher/ContainerAwareEventDispatcher.php +++ b/src/Symfony/Component/EventDispatcher/ContainerAwareEventDispatcher.php @@ -175,7 +175,7 @@ protected function lazyLoad($eventName) $key = $serviceId.'.'.$method; if (!isset($this->listeners[$eventName][$key])) { $this->addListener($eventName, array($listener, $method), $priority); - } elseif ($listener !== $this->listeners[$eventName][$key]) { + } elseif ($this->listeners[$eventName][$key] !== $listener) { parent::removeListener($eventName, array($this->listeners[$eventName][$key], $method)); $this->addListener($eventName, array($listener, $method), $priority); } diff --git a/src/Symfony/Component/ExpressionLanguage/Parser.php b/src/Symfony/Component/ExpressionLanguage/Parser.php index d847dfa4b03bc..68d48a9af8f84 100644 --- a/src/Symfony/Component/ExpressionLanguage/Parser.php +++ b/src/Symfony/Component/ExpressionLanguage/Parser.php @@ -305,14 +305,14 @@ public function parseHashExpression() public function parsePostfixExpression($node) { $token = $this->stream->current; - while ($token->type == Token::PUNCTUATION_TYPE) { + while (Token::PUNCTUATION_TYPE == $token->type) { if ('.' === $token->value) { $this->stream->next(); $token = $this->stream->current; $this->stream->next(); if ( - $token->type !== Token::NAME_TYPE + Token::NAME_TYPE !== $token->type && // Operators like "not" and "matches" are valid method or property names, // @@ -325,7 +325,7 @@ public function parsePostfixExpression($node) // Other types, such as STRING_TYPE and NUMBER_TYPE, can't be parsed as property nor method names. // // As a result, if $token is NOT an operator OR $token->value is NOT a valid property or method name, an exception shall be thrown. - ($token->type !== Token::OPERATOR_TYPE || !preg_match('/[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*/A', $token->value)) + (Token::OPERATOR_TYPE !== $token->type || !preg_match('/[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*/A', $token->value)) ) { throw new SyntaxError('Expected name', $token->cursor, $this->stream->getExpression()); } diff --git a/src/Symfony/Component/ExpressionLanguage/TokenStream.php b/src/Symfony/Component/ExpressionLanguage/TokenStream.php index 3c22fc1d46ed3..471d67a83a372 100644 --- a/src/Symfony/Component/ExpressionLanguage/TokenStream.php +++ b/src/Symfony/Component/ExpressionLanguage/TokenStream.php @@ -84,7 +84,7 @@ public function expect($type, $value = null, $message = null) */ public function isEOF() { - return $this->current->type === Token::EOF_TYPE; + return Token::EOF_TYPE === $this->current->type; } /** diff --git a/src/Symfony/Component/Filesystem/Filesystem.php b/src/Symfony/Component/Filesystem/Filesystem.php index b4f238f02bda1..02a90c996901a 100644 --- a/src/Symfony/Component/Filesystem/Filesystem.php +++ b/src/Symfony/Component/Filesystem/Filesystem.php @@ -404,7 +404,7 @@ public function makePathRelative($endPath, $startPath) } // Determine how deep the start path is relative to the common path (ie, "web/bundles" = 2 levels) - if (count($startPathArr) === 1 && $startPathArr[0] === '') { + if (1 === count($startPathArr) && '' === $startPathArr[0]) { $depth = 0; } else { $depth = count($startPathArr) - $index; @@ -512,7 +512,7 @@ public function isAbsolutePath($file) { return strspn($file, '/\\', 0, 1) || (strlen($file) > 3 && ctype_alpha($file[0]) - && substr($file, 1, 1) === ':' + && ':' === substr($file, 1, 1) && strspn($file, '/\\', 2, 1) ) || null !== parse_url($file, PHP_URL_SCHEME) diff --git a/src/Symfony/Component/Finder/Adapter/GnuFindAdapter.php b/src/Symfony/Component/Finder/Adapter/GnuFindAdapter.php index 0fbf48ffa40f4..9f03953e5ee05 100644 --- a/src/Symfony/Component/Finder/Adapter/GnuFindAdapter.php +++ b/src/Symfony/Component/Finder/Adapter/GnuFindAdapter.php @@ -72,7 +72,7 @@ protected function buildFormatSorting(Command $command, $sort) */ protected function canBeUsed() { - return $this->shell->getType() === Shell::TYPE_UNIX && parent::canBeUsed(); + return Shell::TYPE_UNIX === $this->shell->getType() && parent::canBeUsed(); } /** diff --git a/src/Symfony/Component/Finder/Expression/Regex.php b/src/Symfony/Component/Finder/Expression/Regex.php index e3c404b6d73f5..531a3e2e785db 100644 --- a/src/Symfony/Component/Finder/Expression/Regex.php +++ b/src/Symfony/Component/Finder/Expression/Regex.php @@ -67,8 +67,8 @@ public static function create($expr) if ( ($start === $end && !preg_match('/[*?[:alnum:] \\\\]/', $start)) - || ($start === '{' && $end === '}') - || ($start === '(' && $end === ')') + || ('{' === $start && '}' === $end) + || ('(' === $start && ')' === $end) ) { return new self(substr($m[1], 1, -1), $m[2], $end); } diff --git a/src/Symfony/Component/Finder/Tests/Iterator/SortableIteratorTest.php b/src/Symfony/Component/Finder/Tests/Iterator/SortableIteratorTest.php index 4750f250d736c..444654a28fb61 100644 --- a/src/Symfony/Component/Finder/Tests/Iterator/SortableIteratorTest.php +++ b/src/Symfony/Component/Finder/Tests/Iterator/SortableIteratorTest.php @@ -58,9 +58,9 @@ public function testAccept($mode, $expected) $iterator = new SortableIterator($inner, $mode); - if ($mode === SortableIterator::SORT_BY_ACCESSED_TIME - || $mode === SortableIterator::SORT_BY_CHANGED_TIME - || $mode === SortableIterator::SORT_BY_MODIFIED_TIME + if (SortableIterator::SORT_BY_ACCESSED_TIME === $mode + || SortableIterator::SORT_BY_CHANGED_TIME === $mode + || SortableIterator::SORT_BY_MODIFIED_TIME === $mode ) { if ('\\' === DIRECTORY_SEPARATOR && SortableIterator::SORT_BY_MODIFIED_TIME !== $mode) { $this->markTestSkipped('Sorting by atime or ctime is not supported on Windows'); diff --git a/src/Symfony/Component/Form/Extension/Core/DataTransformer/ChoiceToBooleanArrayTransformer.php b/src/Symfony/Component/Form/Extension/Core/DataTransformer/ChoiceToBooleanArrayTransformer.php index 89f13b6cb26e4..640af6e1ff25e 100644 --- a/src/Symfony/Component/Form/Extension/Core/DataTransformer/ChoiceToBooleanArrayTransformer.php +++ b/src/Symfony/Component/Form/Extension/Core/DataTransformer/ChoiceToBooleanArrayTransformer.php @@ -109,7 +109,7 @@ public function reverseTransform($values) foreach ($values as $i => $selected) { if ($selected) { if (isset($choices[$i])) { - return $choices[$i] === '' ? null : $choices[$i]; + return '' === $choices[$i] ? null : $choices[$i]; } elseif ($this->placeholderPresent && 'placeholder' === $i) { return; } else { diff --git a/src/Symfony/Component/Form/Extension/Core/DataTransformer/DateTimeToLocalizedStringTransformer.php b/src/Symfony/Component/Form/Extension/Core/DataTransformer/DateTimeToLocalizedStringTransformer.php index bc8f64dffa6c5..ff2fa7594991e 100644 --- a/src/Symfony/Component/Form/Extension/Core/DataTransformer/DateTimeToLocalizedStringTransformer.php +++ b/src/Symfony/Component/Form/Extension/Core/DataTransformer/DateTimeToLocalizedStringTransformer.php @@ -90,7 +90,7 @@ public function transform($dateTime) $value = $this->getIntlDateFormatter()->format($dateTime->getTimestamp()); - if (intl_get_error_code() != 0) { + if (0 != intl_get_error_code()) { throw new TransformationFailedException(intl_get_error_message()); } @@ -123,7 +123,7 @@ public function reverseTransform($value) $timestamp = $this->getIntlDateFormatter($dateOnly)->parse($value); - if (intl_get_error_code() != 0) { + if (0 != intl_get_error_code()) { throw new TransformationFailedException(intl_get_error_message()); } diff --git a/src/Symfony/Component/Form/Extension/Csrf/EventListener/CsrfValidationListener.php b/src/Symfony/Component/Form/Extension/Csrf/EventListener/CsrfValidationListener.php index 034f30612df83..b232e4f3b7de8 100644 --- a/src/Symfony/Component/Form/Extension/Csrf/EventListener/CsrfValidationListener.php +++ b/src/Symfony/Component/Form/Extension/Csrf/EventListener/CsrfValidationListener.php @@ -101,7 +101,7 @@ public function __construct($fieldName, $tokenManager, $tokenId, $errorMessage, public function preSubmit(FormEvent $event) { $form = $event->getForm(); - $postRequestSizeExceeded = $form->getConfig()->getMethod() === 'POST' && $this->serverParams->hasPostMaxSizeBeenExceeded(); + $postRequestSizeExceeded = 'POST' === $form->getConfig()->getMethod() && $this->serverParams->hasPostMaxSizeBeenExceeded(); if ($form->isRoot() && $form->getConfig()->getOption('compound') && !$postRequestSizeExceeded) { $data = $event->getData(); diff --git a/src/Symfony/Component/Form/ResolvedFormType.php b/src/Symfony/Component/Form/ResolvedFormType.php index 54c96959c4881..09d578ea35d2d 100644 --- a/src/Symfony/Component/Form/ResolvedFormType.php +++ b/src/Symfony/Component/Form/ResolvedFormType.php @@ -202,10 +202,10 @@ public function getOptionsResolver() if (method_exists($this->innerType, 'configureOptions')) { $reflector = new \ReflectionMethod($this->innerType, 'setDefaultOptions'); - $isOldOverwritten = $reflector->getDeclaringClass()->getName() !== 'Symfony\Component\Form\AbstractType'; + $isOldOverwritten = 'Symfony\Component\Form\AbstractType' !== $reflector->getDeclaringClass()->getName(); $reflector = new \ReflectionMethod($this->innerType, 'configureOptions'); - $isNewOverwritten = $reflector->getDeclaringClass()->getName() !== 'Symfony\Component\Form\AbstractType'; + $isNewOverwritten = 'Symfony\Component\Form\AbstractType' !== $reflector->getDeclaringClass()->getName(); if ($isOldOverwritten && !$isNewOverwritten) { @trigger_error(get_class($this->innerType).': The FormTypeInterface::setDefaultOptions() method is deprecated since version 2.7 and will be removed in 3.0. Use configureOptions() instead. This method will be added to the FormTypeInterface with Symfony 3.0.', E_USER_DEPRECATED); @@ -219,10 +219,10 @@ public function getOptionsResolver() if (method_exists($extension, 'configureOptions')) { $reflector = new \ReflectionMethod($extension, 'setDefaultOptions'); - $isOldOverwritten = $reflector->getDeclaringClass()->getName() !== 'Symfony\Component\Form\AbstractTypeExtension'; + $isOldOverwritten = 'Symfony\Component\Form\AbstractTypeExtension' !== $reflector->getDeclaringClass()->getName(); $reflector = new \ReflectionMethod($extension, 'configureOptions'); - $isNewOverwritten = $reflector->getDeclaringClass()->getName() !== 'Symfony\Component\Form\AbstractTypeExtension'; + $isNewOverwritten = 'Symfony\Component\Form\AbstractTypeExtension' !== $reflector->getDeclaringClass()->getName(); if ($isOldOverwritten && !$isNewOverwritten) { @trigger_error(get_class($extension).': The FormTypeExtensionInterface::setDefaultOptions() method is deprecated since version 2.7 and will be removed in 3.0. Use configureOptions() instead. This method will be added to the FormTypeExtensionInterface with Symfony 3.0.', E_USER_DEPRECATED); diff --git a/src/Symfony/Component/Form/Test/FormPerformanceTestCase.php b/src/Symfony/Component/Form/Test/FormPerformanceTestCase.php index 75ddba621278f..dfb4ffaa0115b 100644 --- a/src/Symfony/Component/Form/Test/FormPerformanceTestCase.php +++ b/src/Symfony/Component/Form/Test/FormPerformanceTestCase.php @@ -35,7 +35,7 @@ protected function runTest() parent::runTest(); $time = microtime(true) - $s; - if ($this->maxRunningTime != 0 && $time > $this->maxRunningTime) { + if (0 != $this->maxRunningTime && $time > $this->maxRunningTime) { $this->fail( sprintf( 'expected running time: <= %s but was: %s', diff --git a/src/Symfony/Component/Form/Tests/AbstractLayoutTest.php b/src/Symfony/Component/Form/Tests/AbstractLayoutTest.php index 411a8196cc73d..52aaacd15ac12 100644 --- a/src/Symfony/Component/Form/Tests/AbstractLayoutTest.php +++ b/src/Symfony/Component/Form/Tests/AbstractLayoutTest.php @@ -78,8 +78,8 @@ protected function assertMatchesXpath($html, $expression, $count = 1) $this->fail(sprintf( "Failed asserting that \n\n%s\n\nmatches exactly %s. Matches %s in \n\n%s", $expression, - $count == 1 ? 'once' : $count.' times', - $nodeList->length == 1 ? 'once' : $nodeList->length.' times', + 1 == $count ? 'once' : $count.' times', + 1 == $nodeList->length ? 'once' : $nodeList->length.' times', // strip away and substr($dom->saveHTML(), 6, -8) )); diff --git a/src/Symfony/Component/Form/Tests/Extension/Validator/ViolationMapper/ViolationMapperTest.php b/src/Symfony/Component/Form/Tests/Extension/Validator/ViolationMapper/ViolationMapperTest.php index dd70b23bda0da..f874e5a4390ef 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Validator/ViolationMapper/ViolationMapperTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Validator/ViolationMapper/ViolationMapperTest.php @@ -1260,7 +1260,7 @@ public function testCustomDataErrorMapping($target, $mapFrom, $mapTo, $childName // Only add it if we expect the error to come up on a different // level than LEVEL_0, because in this case the error would // (correctly) be mapped to the distraction field - if ($target !== self::LEVEL_0) { + if (self::LEVEL_0 !== $target) { $mapFromPath = new PropertyPath($mapFrom); $mapFromPrefix = $mapFromPath->isIndex(0) ? '['.$mapFromPath->getElement(0).']' @@ -1274,7 +1274,7 @@ public function testCustomDataErrorMapping($target, $mapFrom, $mapTo, $childName $this->mapper->mapViolation($violation, $parent); - if ($target !== self::LEVEL_0) { + if (self::LEVEL_0 !== $target) { $this->assertCount(0, $distraction->getErrors(), 'distraction should not have an error, but has one'); } diff --git a/src/Symfony/Component/Form/Tests/Fixtures/AlternatingRowType.php b/src/Symfony/Component/Form/Tests/Fixtures/AlternatingRowType.php index ee7d135339dcf..738d51dc48d3f 100644 --- a/src/Symfony/Component/Form/Tests/Fixtures/AlternatingRowType.php +++ b/src/Symfony/Component/Form/Tests/Fixtures/AlternatingRowType.php @@ -15,7 +15,7 @@ public function buildForm(FormBuilderInterface $builder, array $options) $builder->addEventListener(FormEvents::PRE_SET_DATA, function (FormEvent $event) use ($formFactory) { $form = $event->getForm(); - $type = $form->getName() % 2 === 0 ? 'text' : 'textarea'; + $type = 0 === $form->getName() % 2 ? 'text' : 'textarea'; $form->add('title', $type); }); } diff --git a/src/Symfony/Component/Form/Tests/Fixtures/FixedDataTransformer.php b/src/Symfony/Component/Form/Tests/Fixtures/FixedDataTransformer.php index f7fba56c4211f..e768b1d7cfac9 100644 --- a/src/Symfony/Component/Form/Tests/Fixtures/FixedDataTransformer.php +++ b/src/Symfony/Component/Form/Tests/Fixtures/FixedDataTransformer.php @@ -36,7 +36,7 @@ public function reverseTransform($value) { $result = array_search($value, $this->mapping, true); - if ($result === false) { + if (false === $result) { throw new TransformationFailedException(sprintf('No reverse mapping for value "%s"', $value)); } diff --git a/src/Symfony/Component/HttpFoundation/AcceptHeaderItem.php b/src/Symfony/Component/HttpFoundation/AcceptHeaderItem.php index fb54b4935a9f3..06582b677ea28 100644 --- a/src/Symfony/Component/HttpFoundation/AcceptHeaderItem.php +++ b/src/Symfony/Component/HttpFoundation/AcceptHeaderItem.php @@ -67,7 +67,7 @@ public static function fromString($itemValue) $lastNullAttribute = null; foreach ($bits as $bit) { - if (($start = substr($bit, 0, 1)) === ($end = substr($bit, -1)) && ($start === '"' || $start === '\'')) { + if (($start = substr($bit, 0, 1)) === ($end = substr($bit, -1)) && ('"' === $start || '\'' === $start)) { $attributes[$lastNullAttribute] = substr($bit, 1, -1); } elseif ('=' === $end) { $lastNullAttribute = $bit = substr($bit, 0, -1); @@ -78,7 +78,7 @@ public static function fromString($itemValue) } } - return new self(($start = substr($value, 0, 1)) === ($end = substr($value, -1)) && ($start === '"' || $start === '\'') ? substr($value, 1, -1) : $value, $attributes); + return new self(($start = substr($value, 0, 1)) === ($end = substr($value, -1)) && ('"' === $start || '\'' === $start) ? substr($value, 1, -1) : $value, $attributes); } /** diff --git a/src/Symfony/Component/HttpFoundation/BinaryFileResponse.php b/src/Symfony/Component/HttpFoundation/BinaryFileResponse.php index 177b708e8f054..0cac313ddc924 100644 --- a/src/Symfony/Component/HttpFoundation/BinaryFileResponse.php +++ b/src/Symfony/Component/HttpFoundation/BinaryFileResponse.php @@ -157,7 +157,7 @@ public function setAutoEtag() */ public function setContentDisposition($disposition, $filename = '', $filenameFallback = '') { - if ($filename === '') { + if ('' === $filename) { $filename = $this->file->getFilename(); } @@ -214,7 +214,7 @@ public function prepare(Request $request) if (false === $path) { $path = $this->file->getPathname(); } - if (strtolower($type) === 'x-accel-redirect') { + if ('x-accel-redirect' === strtolower($type)) { // Do X-Accel-Mapping substitutions. // @link http://wiki.nginx.org/X-accel#X-Accel-Redirect foreach (explode(',', $request->headers->get('X-Accel-Mapping', '')) as $mapping) { @@ -254,7 +254,7 @@ public function prepare(Request $request) if ($start < 0 || $end > $fileSize - 1) { $this->setStatusCode(416); $this->headers->set('Content-Range', sprintf('bytes */%s', $fileSize)); - } elseif ($start !== 0 || $end !== $fileSize - 1) { + } elseif (0 !== $start || $end !== $fileSize - 1) { $this->maxlen = $end < $fileSize ? $end - $start + 1 : -1; $this->offset = $start; diff --git a/src/Symfony/Component/HttpFoundation/File/UploadedFile.php b/src/Symfony/Component/HttpFoundation/File/UploadedFile.php index 10837726cde5c..d32ec176cc116 100644 --- a/src/Symfony/Component/HttpFoundation/File/UploadedFile.php +++ b/src/Symfony/Component/HttpFoundation/File/UploadedFile.php @@ -198,7 +198,7 @@ public function getError() */ public function isValid() { - $isOk = $this->error === UPLOAD_ERR_OK; + $isOk = UPLOAD_ERR_OK === $this->error; return $this->test ? $isOk : $isOk && is_uploaded_file($this->getPathname()); } @@ -285,7 +285,7 @@ public function getErrorMessage() ); $errorCode = $this->error; - $maxFilesize = $errorCode === UPLOAD_ERR_INI_SIZE ? self::getMaxFilesize() / 1024 : 0; + $maxFilesize = UPLOAD_ERR_INI_SIZE === $errorCode ? self::getMaxFilesize() / 1024 : 0; $message = isset($errors[$errorCode]) ? $errors[$errorCode] : 'The file "%s" was not uploaded due to an unknown error.'; return sprintf($message, $this->getClientOriginalName(), $maxFilesize); diff --git a/src/Symfony/Component/HttpFoundation/IpUtils.php b/src/Symfony/Component/HttpFoundation/IpUtils.php index eba603b15df01..dc6d3ec818a32 100644 --- a/src/Symfony/Component/HttpFoundation/IpUtils.php +++ b/src/Symfony/Component/HttpFoundation/IpUtils.php @@ -75,7 +75,7 @@ public static function checkIp4($requestIp, $ip) if (false !== strpos($ip, '/')) { list($address, $netmask) = explode('/', $ip, 2); - if ($netmask === '0') { + if ('0' === $netmask) { return self::$checkedIps[$cacheKey] = filter_var($address, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4); } diff --git a/src/Symfony/Component/HttpFoundation/Request.php b/src/Symfony/Component/HttpFoundation/Request.php index 0c11adab6a92e..f1aff0f87edf7 100644 --- a/src/Symfony/Component/HttpFoundation/Request.php +++ b/src/Symfony/Component/HttpFoundation/Request.php @@ -427,22 +427,22 @@ public static function setFactory($callable) public function duplicate(array $query = null, array $request = null, array $attributes = null, array $cookies = null, array $files = null, array $server = null) { $dup = clone $this; - if ($query !== null) { + if (null !== $query) { $dup->query = new ParameterBag($query); } - if ($request !== null) { + if (null !== $request) { $dup->request = new ParameterBag($request); } - if ($attributes !== null) { + if (null !== $attributes) { $dup->attributes = new ParameterBag($attributes); } - if ($cookies !== null) { + if (null !== $cookies) { $dup->cookies = new ParameterBag($cookies); } - if ($files !== null) { + if (null !== $files) { $dup->files = new FileBag($files); } - if ($server !== null) { + if (null !== $server) { $dup->server = new ServerBag($server); $dup->headers = new HeaderBag($dup->server->getHeaders()); } @@ -971,7 +971,7 @@ public function getPort() } if ($host = $this->headers->get('HOST')) { - if ($host[0] === '[') { + if ('[' === $host[0]) { $pos = strpos($host, ':', strrpos($host, ']')); } else { $pos = strrpos($host, ':'); @@ -1036,7 +1036,7 @@ public function getHttpHost() $scheme = $this->getScheme(); $port = $this->getPort(); - if (('http' == $scheme && $port == 80) || ('https' == $scheme && $port == 443)) { + if (('http' == $scheme && 80 == $port) || ('https' == $scheme && 443 == $port)) { return $this->getHost(); } @@ -1618,7 +1618,7 @@ public function getLanguages() } } else { for ($i = 0, $max = count($codes); $i < $max; ++$i) { - if ($i === 0) { + if (0 === $i) { $lang = strtolower($codes[0]); } else { $lang .= '_'.strtoupper($codes[$i]); @@ -1713,7 +1713,7 @@ protected function prepareRequestUri() // IIS with ISAPI_Rewrite $requestUri = $this->headers->get('X_REWRITE_URL'); $this->headers->remove('X_REWRITE_URL'); - } elseif ($this->server->get('IIS_WasUrlRewritten') == '1' && $this->server->get('UNENCODED_URL') != '') { + } elseif ('1' == $this->server->get('IIS_WasUrlRewritten') && '' != $this->server->get('UNENCODED_URL')) { // IIS7 with URL Rewrite: make sure we get the unencoded URL (double slash problem) $requestUri = $this->server->get('UNENCODED_URL'); $this->server->remove('UNENCODED_URL'); @@ -1722,7 +1722,7 @@ protected function prepareRequestUri() $requestUri = $this->server->get('REQUEST_URI'); // HTTP proxy reqs setup request URI with scheme and host [and port] + the URL path, only use URL path $schemeAndHttpHost = $this->getSchemeAndHttpHost(); - if (strpos($requestUri, $schemeAndHttpHost) === 0) { + if (0 === strpos($requestUri, $schemeAndHttpHost)) { $requestUri = substr($requestUri, strlen($schemeAndHttpHost)); } } elseif ($this->server->has('ORIG_PATH_INFO')) { @@ -1774,7 +1774,7 @@ protected function prepareBaseUrl() // Does the baseUrl have anything in common with the request_uri? $requestUri = $this->getRequestUri(); - if ($requestUri !== '' && $requestUri[0] !== '/') { + if ('' !== $requestUri && '/' !== $requestUri[0]) { $requestUri = '/'.$requestUri; } @@ -1802,7 +1802,7 @@ protected function prepareBaseUrl() // If using mod_rewrite or ISAPI_Rewrite strip the script filename // out of baseUrl. $pos !== 0 makes sure it is not matching a value // from PATH_INFO or QUERY_STRING - if (strlen($requestUri) >= strlen($baseUrl) && (false !== $pos = strpos($requestUri, $baseUrl)) && $pos !== 0) { + if (strlen($requestUri) >= strlen($baseUrl) && (false !== $pos = strpos($requestUri, $baseUrl)) && 0 !== $pos) { $baseUrl = substr($requestUri, 0, $pos + strlen($baseUrl)); } @@ -1852,7 +1852,7 @@ protected function preparePathInfo() if (false !== $pos = strpos($requestUri, '?')) { $requestUri = substr($requestUri, 0, $pos); } - if ($requestUri !== '' && $requestUri[0] !== '/') { + if ('' !== $requestUri && '/' !== $requestUri[0]) { $requestUri = '/'.$requestUri; } diff --git a/src/Symfony/Component/HttpFoundation/RequestMatcher.php b/src/Symfony/Component/HttpFoundation/RequestMatcher.php index aa4f67b58bb43..076d077c7d072 100644 --- a/src/Symfony/Component/HttpFoundation/RequestMatcher.php +++ b/src/Symfony/Component/HttpFoundation/RequestMatcher.php @@ -173,6 +173,6 @@ public function matches(Request $request) // Note to future implementors: add additional checks above the // foreach above or else your check might not be run! - return count($this->ips) === 0; + return 0 === count($this->ips); } } diff --git a/src/Symfony/Component/HttpFoundation/Response.php b/src/Symfony/Component/HttpFoundation/Response.php index 074c896ff7b3d..860906c3d88c3 100644 --- a/src/Symfony/Component/HttpFoundation/Response.php +++ b/src/Symfony/Component/HttpFoundation/Response.php @@ -1151,7 +1151,7 @@ public static function closeOutputBuffers($targetLevel, $flush) $level = count($status); $flags = defined('PHP_OUTPUT_HANDLER_REMOVABLE') ? PHP_OUTPUT_HANDLER_REMOVABLE | ($flush ? PHP_OUTPUT_HANDLER_FLUSHABLE : PHP_OUTPUT_HANDLER_CLEANABLE) : -1; - while ($level-- > $targetLevel && ($s = $status[$level]) && (!isset($s['del']) ? !isset($s['flags']) || $flags === ($s['flags'] & $flags) : $s['del'])) { + while ($level-- > $targetLevel && ($s = $status[$level]) && (!isset($s['del']) ? !isset($s['flags']) || ($s['flags'] & $flags) === $flags : $s['del'])) { if ($flush) { ob_end_flush(); } else { @@ -1167,7 +1167,7 @@ public static function closeOutputBuffers($targetLevel, $flush) */ protected function ensureIEOverSSLCompatibility(Request $request) { - if (false !== stripos($this->headers->get('Content-Disposition'), 'attachment') && preg_match('/MSIE (.*?);/i', $request->server->get('HTTP_USER_AGENT'), $match) == 1 && true === $request->isSecure()) { + if (false !== stripos($this->headers->get('Content-Disposition'), 'attachment') && 1 == preg_match('/MSIE (.*?);/i', $request->server->get('HTTP_USER_AGENT'), $match) && true === $request->isSecure()) { if ((int) preg_replace('/(MSIE )(.*?);/', '$2', $match[0]) < 9) { $this->headers->remove('Cache-Control'); } diff --git a/src/Symfony/Component/HttpFoundation/ServerBag.php b/src/Symfony/Component/HttpFoundation/ServerBag.php index 0d38c08ac0544..19d2022ef7ddb 100644 --- a/src/Symfony/Component/HttpFoundation/ServerBag.php +++ b/src/Symfony/Component/HttpFoundation/ServerBag.php @@ -68,7 +68,7 @@ public function getHeaders() if (0 === stripos($authorizationHeader, 'basic ')) { // Decode AUTHORIZATION header into PHP_AUTH_USER and PHP_AUTH_PW when authorization header is basic $exploded = explode(':', base64_decode(substr($authorizationHeader, 6)), 2); - if (count($exploded) == 2) { + if (2 == count($exploded)) { list($headers['PHP_AUTH_USER'], $headers['PHP_AUTH_PW']) = $exploded; } } elseif (empty($this->parameters['PHP_AUTH_DIGEST']) && (0 === stripos($authorizationHeader, 'digest '))) { diff --git a/src/Symfony/Component/HttpFoundation/Session/Attribute/NamespacedAttributeBag.php b/src/Symfony/Component/HttpFoundation/Session/Attribute/NamespacedAttributeBag.php index d797a6f23886e..7301f9528a876 100644 --- a/src/Symfony/Component/HttpFoundation/Session/Attribute/NamespacedAttributeBag.php +++ b/src/Symfony/Component/HttpFoundation/Session/Attribute/NamespacedAttributeBag.php @@ -109,7 +109,7 @@ public function remove($name) protected function &resolveAttributePath($name, $writeContext = false) { $array = &$this->attributes; - $name = (strpos($name, $this->namespaceCharacter) === 0) ? substr($name, 1) : $name; + $name = (0 === strpos($name, $this->namespaceCharacter)) ? substr($name, 1) : $name; // Check if there is anything to do, else return if (!$name) { diff --git a/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/MemcachedSessionHandler.php b/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/MemcachedSessionHandler.php index 67a49ad6f5e2a..dfe2fee0d44be 100644 --- a/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/MemcachedSessionHandler.php +++ b/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/MemcachedSessionHandler.php @@ -103,7 +103,7 @@ public function destroy($sessionId) { $result = $this->memcached->delete($this->prefix.$sessionId); - return $result || $this->memcached->getResultCode() == \Memcached::RES_NOTFOUND; + return $result || \Memcached::RES_NOTFOUND == $this->memcached->getResultCode(); } /** diff --git a/src/Symfony/Component/HttpFoundation/Tests/File/MimeType/MimeTypeTest.php b/src/Symfony/Component/HttpFoundation/Tests/File/MimeType/MimeTypeTest.php index 5a2b7a21c325e..b3f1f026a558f 100644 --- a/src/Symfony/Component/HttpFoundation/Tests/File/MimeType/MimeTypeTest.php +++ b/src/Symfony/Component/HttpFoundation/Tests/File/MimeType/MimeTypeTest.php @@ -71,7 +71,7 @@ public function testGuessWithNonReadablePath() touch($path); @chmod($path, 0333); - if (substr(sprintf('%o', fileperms($path)), -4) == '0333') { + if ('0333' == substr(sprintf('%o', fileperms($path)), -4)) { $this->{method_exists($this, $_ = 'expectException') ? $_ : 'setExpectedException'}('Symfony\Component\HttpFoundation\File\Exception\AccessDeniedException'); MimeTypeGuesser::getInstance()->guess($path); } else { diff --git a/src/Symfony/Component/HttpFoundation/Tests/RequestTest.php b/src/Symfony/Component/HttpFoundation/Tests/RequestTest.php index bb7a3f4800cd6..ed4224c4fd38f 100644 --- a/src/Symfony/Component/HttpFoundation/Tests/RequestTest.php +++ b/src/Symfony/Component/HttpFoundation/Tests/RequestTest.php @@ -1008,7 +1008,7 @@ public function testGetContentReturnsResourceWhenContentSetInConstructor() $req = new Request(array(), array(), array(), array(), array(), array(), 'MyContent'); $resource = $req->getContent(true); - $this->assertTrue(is_resource($resource)); + $this->assertInternalType('resource', $resource); $this->assertEquals('MyContent', stream_get_contents($resource)); } diff --git a/src/Symfony/Component/HttpKernel/HttpCache/Store.php b/src/Symfony/Component/HttpKernel/HttpCache/Store.php index c4d961e68f043..bea7e1d84463e 100644 --- a/src/Symfony/Component/HttpKernel/HttpCache/Store.php +++ b/src/Symfony/Component/HttpKernel/HttpCache/Store.php @@ -210,7 +210,7 @@ public function write(Request $request, Response $response) $entry[1]['vary'] = array(''); } - if ($vary != $entry[1]['vary'][0] || !$this->requestsMatch($vary, $entry[0], $storedEnv)) { + if ($entry[1]['vary'][0] != $vary || !$this->requestsMatch($vary, $entry[0], $storedEnv)) { $entries[] = $entry; } } diff --git a/src/Symfony/Component/HttpKernel/Kernel.php b/src/Symfony/Component/HttpKernel/Kernel.php index 0fcbbe47fddea..4636e29908e51 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -728,7 +728,7 @@ public static function stripComments($source) do { $token = $tokens[++$i]; $output .= isset($token[1]) && 'b"' !== $token ? $token[1] : $token; - } while ($token[0] !== T_END_HEREDOC); + } while (T_END_HEREDOC !== $token[0]); $rawChunk = ''; } elseif (T_WHITESPACE === $token[0]) { if ($ignoreSpace) { diff --git a/src/Symfony/Component/HttpKernel/Profiler/BaseMemcacheProfilerStorage.php b/src/Symfony/Component/HttpKernel/Profiler/BaseMemcacheProfilerStorage.php index c6395bd67a2d0..dc48009ce3ba5 100644 --- a/src/Symfony/Component/HttpKernel/Profiler/BaseMemcacheProfilerStorage.php +++ b/src/Symfony/Component/HttpKernel/Profiler/BaseMemcacheProfilerStorage.php @@ -53,11 +53,11 @@ public function find($ip, $url, $limit, $method, $start = null, $end = null) $result = array(); foreach ($profileList as $item) { - if ($limit === 0) { + if (0 === $limit) { break; } - if ($item == '') { + if ('' == $item) { continue; } @@ -119,7 +119,7 @@ public function purge() $profileList = explode("\n", $indexContent); foreach ($profileList as $item) { - if ($item == '') { + if ('' == $item) { continue; } diff --git a/src/Symfony/Component/HttpKernel/Profiler/RedisProfilerStorage.php b/src/Symfony/Component/HttpKernel/Profiler/RedisProfilerStorage.php index b0e14ea456291..257ca4c68466e 100644 --- a/src/Symfony/Component/HttpKernel/Profiler/RedisProfilerStorage.php +++ b/src/Symfony/Component/HttpKernel/Profiler/RedisProfilerStorage.php @@ -63,11 +63,11 @@ public function find($ip, $url, $limit, $method, $start = null, $end = null) $result = array(); foreach ($profileList as $item) { - if ($limit === 0) { + if (0 === $limit) { break; } - if ($item == '') { + if ('' == $item) { continue; } @@ -123,7 +123,7 @@ public function purge() $result = array(); foreach ($profileList as $item) { - if ($item == '') { + if ('' == $item) { continue; } @@ -209,7 +209,7 @@ protected function getRedis() if (null === $this->redis) { $data = parse_url($this->dsn); - if (false === $data || !isset($data['scheme']) || $data['scheme'] !== 'redis' || !isset($data['host']) || !isset($data['port'])) { + if (false === $data || !isset($data['scheme']) || 'redis' !== $data['scheme'] || !isset($data['host']) || !isset($data['port'])) { throw new \RuntimeException(sprintf('Please check your configuration. You are trying to use Redis with an invalid dsn "%s". The minimal expected format is "redis://[host]:port".', $this->dsn)); } diff --git a/src/Symfony/Component/Intl/Data/Bundle/Compiler/GenrbCompiler.php b/src/Symfony/Component/Intl/Data/Bundle/Compiler/GenrbCompiler.php index 8db6890c7c680..b3df7387c23ad 100644 --- a/src/Symfony/Component/Intl/Data/Bundle/Compiler/GenrbCompiler.php +++ b/src/Symfony/Component/Intl/Data/Bundle/Compiler/GenrbCompiler.php @@ -61,7 +61,7 @@ public function compile($sourcePath, $targetDir) exec($this->genrb.' --quiet -e UTF-8 -d '.$targetDir.' '.$sourcePath, $output, $status); - if ($status !== 0) { + if (0 !== $status) { throw new RuntimeException(sprintf( 'genrb failed with status %d while compiling %s to %s.', $status, diff --git a/src/Symfony/Component/Intl/DateFormatter/DateFormat/TimeZoneTransformer.php b/src/Symfony/Component/Intl/DateFormatter/DateFormat/TimeZoneTransformer.php index 5170bb788eb88..79b4b3ad7c40d 100644 --- a/src/Symfony/Component/Intl/DateFormatter/DateFormat/TimeZoneTransformer.php +++ b/src/Symfony/Component/Intl/DateFormatter/DateFormat/TimeZoneTransformer.php @@ -101,7 +101,7 @@ public static function getEtcTimeZoneId($formattedTimeZone) if (preg_match('/GMT(?P[+-])(?P\d{2}):?(?P\d{2})/', $formattedTimeZone, $matches)) { $hours = (int) $matches['hours']; $minutes = (int) $matches['minutes']; - $signal = $matches['signal'] == '-' ? '+' : '-'; + $signal = '-' == $matches['signal'] ? '+' : '-'; if (0 < $minutes) { throw new NotImplementedException(sprintf( @@ -110,7 +110,7 @@ public static function getEtcTimeZoneId($formattedTimeZone) )); } - return 'Etc/GMT'.($hours !== 0 ? $signal.$hours : ''); + return 'Etc/GMT'.(0 !== $hours ? $signal.$hours : ''); } throw new \InvalidArgumentException(sprintf('The GMT time zone "%s" does not match with the supported formats GMT[+-]HH:MM or GMT[+-]HHMM.', $formattedTimeZone)); diff --git a/src/Symfony/Component/Intl/Exception/MethodArgumentValueNotImplementedException.php b/src/Symfony/Component/Intl/Exception/MethodArgumentValueNotImplementedException.php index 3193483dfe88a..59b068f0f9e61 100644 --- a/src/Symfony/Component/Intl/Exception/MethodArgumentValueNotImplementedException.php +++ b/src/Symfony/Component/Intl/Exception/MethodArgumentValueNotImplementedException.php @@ -31,7 +31,7 @@ public function __construct($methodName, $argName, $argValue, $additionalMessage $methodName, $argName, var_export($argValue, true), - $additionalMessage !== '' ? ' '.$additionalMessage.'. ' : '' + '' !== $additionalMessage ? ' '.$additionalMessage.'. ' : '' ); parent::__construct($message); diff --git a/src/Symfony/Component/Intl/NumberFormatter/NumberFormatter.php b/src/Symfony/Component/Intl/NumberFormatter/NumberFormatter.php index b5aa050a4ea13..42298e48c3a49 100644 --- a/src/Symfony/Component/Intl/NumberFormatter/NumberFormatter.php +++ b/src/Symfony/Component/Intl/NumberFormatter/NumberFormatter.php @@ -330,7 +330,7 @@ public static function create($locale = 'en', $style = null, $pattern = null) */ public function formatCurrency($value, $currency) { - if ($this->style == self::DECIMAL) { + if (self::DECIMAL == $this->style) { return $this->format($value); } @@ -369,13 +369,13 @@ public function formatCurrency($value, $currency) public function format($value, $type = self::TYPE_DEFAULT) { // The original NumberFormatter does not support this format type - if ($type == self::TYPE_CURRENCY) { + if (self::TYPE_CURRENCY == $type) { trigger_error(__METHOD__.'(): Unsupported format type '.$type, \E_USER_WARNING); return false; } - if ($this->style == self::CURRENCY) { + if (self::CURRENCY == $this->style) { throw new NotImplementedException(sprintf( '%s() method does not support the formatting of currencies (instance with CURRENCY style). %s', __METHOD__, NotImplementedException::INTL_INSTALL_MESSAGE @@ -383,7 +383,7 @@ public function format($value, $type = self::TYPE_DEFAULT) } // Only the default type is supported. - if ($type != self::TYPE_DEFAULT) { + if (self::TYPE_DEFAULT != $type) { throw new MethodArgumentValueNotImplementedException(__METHOD__, 'type', $type, 'Only TYPE_DEFAULT is supported'); } @@ -526,7 +526,7 @@ public function parseCurrency($value, &$currency, &$position = null) */ public function parse($value, $type = self::TYPE_DOUBLE, &$position = 0) { - if ($type == self::TYPE_DEFAULT || $type == self::TYPE_CURRENCY) { + if (self::TYPE_DEFAULT == $type || self::TYPE_CURRENCY == $type) { trigger_error(__METHOD__.'(): Unsupported format type '.$type, \E_USER_WARNING); return false; @@ -773,7 +773,7 @@ private function formatNumber($value, $precision) */ private function getUninitializedPrecision($value, $precision) { - if ($this->style == self::CURRENCY) { + if (self::CURRENCY == $this->style) { return $precision; } @@ -809,11 +809,11 @@ private function isInitializedAttribute($attr) */ private function convertValueDataType($value, $type) { - if ($type == self::TYPE_DOUBLE) { + if (self::TYPE_DOUBLE == $type) { $value = (float) $value; - } elseif ($type == self::TYPE_INT32) { + } elseif (self::TYPE_INT32 == $type) { $value = $this->getInt32Value($value); - } elseif ($type == self::TYPE_INT64) { + } elseif (self::TYPE_INT64 == $type) { $value = $this->getInt64Value($value); } diff --git a/src/Symfony/Component/Intl/Tests/Data/Provider/AbstractCurrencyDataProviderTest.php b/src/Symfony/Component/Intl/Tests/Data/Provider/AbstractCurrencyDataProviderTest.php index 3e71ed78a4234..7387e0e47d737 100644 --- a/src/Symfony/Component/Intl/Tests/Data/Provider/AbstractCurrencyDataProviderTest.php +++ b/src/Symfony/Component/Intl/Tests/Data/Provider/AbstractCurrencyDataProviderTest.php @@ -676,7 +676,7 @@ function ($currency) { return array($currency); }, */ public function testGetFractionDigits($currency) { - $this->assertTrue(is_numeric($this->dataProvider->getFractionDigits($currency))); + $this->assertInternalType('numeric', $this->dataProvider->getFractionDigits($currency)); } /** @@ -684,7 +684,7 @@ public function testGetFractionDigits($currency) */ public function testGetRoundingIncrement($currency) { - $this->assertTrue(is_numeric($this->dataProvider->getRoundingIncrement($currency))); + $this->assertInternalType('numeric', $this->dataProvider->getRoundingIncrement($currency)); } public function provideCurrenciesWithNumericEquivalent() diff --git a/src/Symfony/Component/Intl/Tests/NumberFormatter/AbstractNumberFormatterTest.php b/src/Symfony/Component/Intl/Tests/NumberFormatter/AbstractNumberFormatterTest.php index a3f86e2b5144a..0822fb1275fcd 100644 --- a/src/Symfony/Component/Intl/Tests/NumberFormatter/AbstractNumberFormatterTest.php +++ b/src/Symfony/Component/Intl/Tests/NumberFormatter/AbstractNumberFormatterTest.php @@ -621,7 +621,7 @@ public function testParse($value, $expected, $message, $expectedPosition, $group $this->assertSame($expected, $parsedValue, $message); $this->assertSame($expectedPosition, $position, $message); - if ($expected === false) { + if (false === $expected) { $errorCode = IntlGlobals::U_PARSE_ERROR; $errorMessage = 'Number parsing failed: U_PARSE_ERROR'; } else { @@ -631,10 +631,10 @@ public function testParse($value, $expected, $message, $expectedPosition, $group $this->assertSame($errorMessage, $this->getIntlErrorMessage()); $this->assertSame($errorCode, $this->getIntlErrorCode()); - $this->assertSame($errorCode !== 0, $this->isIntlFailure($this->getIntlErrorCode())); + $this->assertSame(0 !== $errorCode, $this->isIntlFailure($this->getIntlErrorCode())); $this->assertSame($errorMessage, $formatter->getErrorMessage()); $this->assertSame($errorCode, $formatter->getErrorCode()); - $this->assertSame($errorCode !== 0, $this->isIntlFailure($formatter->getErrorCode())); + $this->assertSame(0 !== $errorCode, $this->isIntlFailure($formatter->getErrorCode())); } public function parseProvider() diff --git a/src/Symfony/Component/Intl/Util/SvnRepository.php b/src/Symfony/Component/Intl/Util/SvnRepository.php index 3732cbb3920d7..9716a5425ead7 100644 --- a/src/Symfony/Component/Intl/Util/SvnRepository.php +++ b/src/Symfony/Component/Intl/Util/SvnRepository.php @@ -50,7 +50,7 @@ public static function download($url, $targetDir) { exec('which svn', $output, $result); - if ($result !== 0) { + if (0 !== $result) { throw new RuntimeException('The command "svn" is not installed.'); } @@ -62,7 +62,7 @@ public static function download($url, $targetDir) exec('svn checkout '.$url.' '.$targetDir, $output, $result); - if ($result !== 0) { + if (0 !== $result) { throw new RuntimeException('The SVN checkout of '.$url.'failed.'); } } @@ -128,7 +128,7 @@ private function getSvnInfo() $svnInfo = simplexml_load_string(implode("\n", $output)); - if ($result !== 0) { + if (0 !== $result) { throw new RuntimeException('svn info failed'); } diff --git a/src/Symfony/Component/Process/Exception/ProcessTimedOutException.php b/src/Symfony/Component/Process/Exception/ProcessTimedOutException.php index d45114696f640..fef4a8ae867b8 100644 --- a/src/Symfony/Component/Process/Exception/ProcessTimedOutException.php +++ b/src/Symfony/Component/Process/Exception/ProcessTimedOutException.php @@ -45,12 +45,12 @@ public function getProcess() public function isGeneralTimeout() { - return $this->timeoutType === self::TYPE_GENERAL; + return self::TYPE_GENERAL === $this->timeoutType; } public function isIdleTimeout() { - return $this->timeoutType === self::TYPE_IDLE; + return self::TYPE_IDLE === $this->timeoutType; } public function getExceededTimeout() diff --git a/src/Symfony/Component/Process/Process.php b/src/Symfony/Component/Process/Process.php index b31230d2939e6..c3447c4eb237f 100644 --- a/src/Symfony/Component/Process/Process.php +++ b/src/Symfony/Component/Process/Process.php @@ -713,7 +713,7 @@ public function isRunning() */ public function isStarted() { - return $this->status != self::STATUS_READY; + return self::STATUS_READY != $this->status; } /** @@ -725,7 +725,7 @@ public function isTerminated() { $this->updateStatus(false); - return $this->status == self::STATUS_TERMINATED; + return self::STATUS_TERMINATED == $this->status; } /** @@ -1187,7 +1187,7 @@ public function setEnhanceSigchildCompatibility($enhance) */ public function checkTimeout() { - if ($this->status !== self::STATUS_STARTED) { + if (self::STATUS_STARTED !== $this->status) { return; } @@ -1368,7 +1368,7 @@ private function readPipes($blocking, $close) $callback = $this->callback; foreach ($result as $type => $data) { if (3 !== $type) { - $callback($type === self::STDOUT ? self::OUT : self::ERR, $data); + $callback(self::STDOUT === $type ? self::OUT : self::ERR, $data); } elseif (!isset($this->fallbackStatus['signaled'])) { $this->fallbackStatus['exitcode'] = (int) $data; } diff --git a/src/Symfony/Component/Process/Tests/ProcessTest.php b/src/Symfony/Component/Process/Tests/ProcessTest.php index 90689c88cb8e6..3240aa7954d30 100644 --- a/src/Symfony/Component/Process/Tests/ProcessTest.php +++ b/src/Symfony/Component/Process/Tests/ProcessTest.php @@ -336,7 +336,7 @@ public function testCallbackIsExecutedForOutput() $called = false; $p->run(function ($type, $buffer) use (&$called) { - $called = $buffer === 'foo'; + $called = 'foo' === $buffer; }); $this->assertTrue($called, 'The callback should be executed with the output'); @@ -731,8 +731,8 @@ public function testRestart() // Ensure that both processed finished and the output is numeric $this->assertFalse($process1->isRunning()); $this->assertFalse($process2->isRunning()); - $this->assertTrue(is_numeric($process1->getOutput())); - $this->assertTrue(is_numeric($process2->getOutput())); + $this->assertInternalType('numeric', $process1->getOutput()); + $this->assertInternalType('numeric', $process2->getOutput()); // Ensure that restart returned a new process by check that the output is different $this->assertNotEquals($process1->getOutput(), $process2->getOutput()); diff --git a/src/Symfony/Component/PropertyAccess/Exception/UnexpectedTypeException.php b/src/Symfony/Component/PropertyAccess/Exception/UnexpectedTypeException.php index 3bf8fa4b5e97c..20e5962d5b556 100644 --- a/src/Symfony/Component/PropertyAccess/Exception/UnexpectedTypeException.php +++ b/src/Symfony/Component/PropertyAccess/Exception/UnexpectedTypeException.php @@ -27,7 +27,7 @@ class UnexpectedTypeException extends RuntimeException */ public function __construct($value, $path, $pathIndex = null) { - if (func_num_args() === 3 && $path instanceof PropertyPathInterface) { + if (3 === func_num_args() && $path instanceof PropertyPathInterface) { $message = sprintf( 'PropertyAccessor requires a graph of objects or arrays to operate on, '. 'but it found type "%s" while trying to traverse path "%s" at property "%s".', diff --git a/src/Symfony/Component/Routing/Matcher/Dumper/PhpMatcherDumper.php b/src/Symfony/Component/Routing/Matcher/Dumper/PhpMatcherDumper.php index aa7df8a78b5ba..881dcd0331bf9 100644 --- a/src/Symfony/Component/Routing/Matcher/Dumper/PhpMatcherDumper.php +++ b/src/Symfony/Component/Routing/Matcher/Dumper/PhpMatcherDumper.php @@ -225,11 +225,11 @@ private function compileRoute(Route $route, $name, $supportsRedirections, $paren $supportsTrailingSlash = $supportsRedirections && (!$methods || in_array('HEAD', $methods)); if (!count($compiledRoute->getPathVariables()) && false !== preg_match('#^(.)\^(?P.*?)\$\1#', $compiledRoute->getRegex(), $m)) { - if ($supportsTrailingSlash && substr($m['url'], -1) === '/') { - $conditions[] = sprintf("rtrim(\$pathinfo, '/') === %s", var_export(rtrim(str_replace('\\', '', $m['url']), '/'), true)); + if ($supportsTrailingSlash && '/' === substr($m['url'], -1)) { + $conditions[] = sprintf("%s === rtrim(\$pathinfo, '/')", var_export(rtrim(str_replace('\\', '', $m['url']), '/'), true)); $hasTrailingSlash = true; } else { - $conditions[] = sprintf('$pathinfo === %s', var_export(str_replace('\\', '', $m['url']), true)); + $conditions[] = sprintf('%s === $pathinfo', var_export(str_replace('\\', '', $m['url']), true)); } } else { if ($compiledRoute->getStaticPrefix() && $compiledRoute->getStaticPrefix() !== $parentPrefix) { diff --git a/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher1.php b/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher1.php index 4ea0b8a1a3e7c..be36a1b3933ee 100644 --- a/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher1.php +++ b/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher1.php @@ -60,17 +60,17 @@ public function match($pathinfo) if (0 === strpos($pathinfo, '/test')) { if (0 === strpos($pathinfo, '/test/baz')) { // baz - if ($pathinfo === '/test/baz') { + if ('/test/baz' === $pathinfo) { return array('_route' => 'baz'); } // baz2 - if ($pathinfo === '/test/baz.html') { + if ('/test/baz.html' === $pathinfo) { return array('_route' => 'baz2'); } // baz3 - if ($pathinfo === '/test/baz3/') { + if ('/test/baz3/' === $pathinfo) { return array('_route' => 'baz3'); } @@ -106,7 +106,7 @@ public function match($pathinfo) } // foofoo - if ($pathinfo === '/foofoo') { + if ('/foofoo' === $pathinfo) { return array ( 'def' => 'test', '_route' => 'foofoo',); } @@ -116,7 +116,7 @@ public function match($pathinfo) } // space - if ($pathinfo === '/spa ce') { + if ('/spa ce' === $pathinfo) { return array('_route' => 'space'); } @@ -161,12 +161,12 @@ public function match($pathinfo) } // overridden2 - if ($pathinfo === '/multi/new') { + if ('/multi/new' === $pathinfo) { return array('_route' => 'overridden2'); } // hey - if ($pathinfo === '/multi/hey/') { + if ('/multi/hey/' === $pathinfo) { return array('_route' => 'hey'); } @@ -184,7 +184,7 @@ public function match($pathinfo) if (0 === strpos($pathinfo, '/aba')) { // ababa - if ($pathinfo === '/ababa') { + if ('/ababa' === $pathinfo) { return array('_route' => 'ababa'); } @@ -199,12 +199,12 @@ public function match($pathinfo) if (preg_match('#^a\\.example\\.com$#si', $host, $hostMatches)) { // route1 - if ($pathinfo === '/route1') { + if ('/route1' === $pathinfo) { return array('_route' => 'route1'); } // route2 - if ($pathinfo === '/c2/route2') { + if ('/c2/route2' === $pathinfo) { return array('_route' => 'route2'); } @@ -212,7 +212,7 @@ public function match($pathinfo) if (preg_match('#^b\\.example\\.com$#si', $host, $hostMatches)) { // route3 - if ($pathinfo === '/c2/route3') { + if ('/c2/route3' === $pathinfo) { return array('_route' => 'route3'); } @@ -220,7 +220,7 @@ public function match($pathinfo) if (preg_match('#^a\\.example\\.com$#si', $host, $hostMatches)) { // route4 - if ($pathinfo === '/route4') { + if ('/route4' === $pathinfo) { return array('_route' => 'route4'); } @@ -228,26 +228,26 @@ public function match($pathinfo) if (preg_match('#^c\\.example\\.com$#si', $host, $hostMatches)) { // route5 - if ($pathinfo === '/route5') { + if ('/route5' === $pathinfo) { return array('_route' => 'route5'); } } // route6 - if ($pathinfo === '/route6') { + if ('/route6' === $pathinfo) { return array('_route' => 'route6'); } if (preg_match('#^(?P[^\\.]++)\\.example\\.com$#si', $host, $hostMatches)) { if (0 === strpos($pathinfo, '/route1')) { // route11 - if ($pathinfo === '/route11') { + if ('/route11' === $pathinfo) { return $this->mergeDefaults(array_replace($hostMatches, array('_route' => 'route11')), array ()); } // route12 - if ($pathinfo === '/route12') { + if ('/route12' === $pathinfo) { return $this->mergeDefaults(array_replace($hostMatches, array('_route' => 'route12')), array ( 'var1' => 'val',)); } @@ -280,7 +280,7 @@ public function match($pathinfo) } // route17 - if ($pathinfo === '/route17') { + if ('/route17' === $pathinfo) { return array('_route' => 'route17'); } @@ -288,7 +288,7 @@ public function match($pathinfo) if (0 === strpos($pathinfo, '/a')) { // a - if ($pathinfo === '/a/a...') { + if ('/a/a...' === $pathinfo) { return array('_route' => 'a'); } diff --git a/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher2.php b/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher2.php index f9d3fa2d8257b..afdba317b3def 100644 --- a/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher2.php +++ b/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher2.php @@ -60,17 +60,17 @@ public function match($pathinfo) if (0 === strpos($pathinfo, '/test')) { if (0 === strpos($pathinfo, '/test/baz')) { // baz - if ($pathinfo === '/test/baz') { + if ('/test/baz' === $pathinfo) { return array('_route' => 'baz'); } // baz2 - if ($pathinfo === '/test/baz.html') { + if ('/test/baz.html' === $pathinfo) { return array('_route' => 'baz2'); } // baz3 - if (rtrim($pathinfo, '/') === '/test/baz3') { + if ('/test/baz3' === rtrim($pathinfo, '/')) { if (substr($pathinfo, -1) !== '/') { return $this->redirect($pathinfo.'/', 'baz3'); } @@ -114,7 +114,7 @@ public function match($pathinfo) } // foofoo - if ($pathinfo === '/foofoo') { + if ('/foofoo' === $pathinfo) { return array ( 'def' => 'test', '_route' => 'foofoo',); } @@ -124,7 +124,7 @@ public function match($pathinfo) } // space - if ($pathinfo === '/spa ce') { + if ('/spa ce' === $pathinfo) { return array('_route' => 'space'); } @@ -169,12 +169,12 @@ public function match($pathinfo) } // overridden2 - if ($pathinfo === '/multi/new') { + if ('/multi/new' === $pathinfo) { return array('_route' => 'overridden2'); } // hey - if (rtrim($pathinfo, '/') === '/multi/hey') { + if ('/multi/hey' === rtrim($pathinfo, '/')) { if (substr($pathinfo, -1) !== '/') { return $this->redirect($pathinfo.'/', 'hey'); } @@ -196,7 +196,7 @@ public function match($pathinfo) if (0 === strpos($pathinfo, '/aba')) { // ababa - if ($pathinfo === '/ababa') { + if ('/ababa' === $pathinfo) { return array('_route' => 'ababa'); } @@ -211,12 +211,12 @@ public function match($pathinfo) if (preg_match('#^a\\.example\\.com$#si', $host, $hostMatches)) { // route1 - if ($pathinfo === '/route1') { + if ('/route1' === $pathinfo) { return array('_route' => 'route1'); } // route2 - if ($pathinfo === '/c2/route2') { + if ('/c2/route2' === $pathinfo) { return array('_route' => 'route2'); } @@ -224,7 +224,7 @@ public function match($pathinfo) if (preg_match('#^b\\.example\\.com$#si', $host, $hostMatches)) { // route3 - if ($pathinfo === '/c2/route3') { + if ('/c2/route3' === $pathinfo) { return array('_route' => 'route3'); } @@ -232,7 +232,7 @@ public function match($pathinfo) if (preg_match('#^a\\.example\\.com$#si', $host, $hostMatches)) { // route4 - if ($pathinfo === '/route4') { + if ('/route4' === $pathinfo) { return array('_route' => 'route4'); } @@ -240,26 +240,26 @@ public function match($pathinfo) if (preg_match('#^c\\.example\\.com$#si', $host, $hostMatches)) { // route5 - if ($pathinfo === '/route5') { + if ('/route5' === $pathinfo) { return array('_route' => 'route5'); } } // route6 - if ($pathinfo === '/route6') { + if ('/route6' === $pathinfo) { return array('_route' => 'route6'); } if (preg_match('#^(?P[^\\.]++)\\.example\\.com$#si', $host, $hostMatches)) { if (0 === strpos($pathinfo, '/route1')) { // route11 - if ($pathinfo === '/route11') { + if ('/route11' === $pathinfo) { return $this->mergeDefaults(array_replace($hostMatches, array('_route' => 'route11')), array ()); } // route12 - if ($pathinfo === '/route12') { + if ('/route12' === $pathinfo) { return $this->mergeDefaults(array_replace($hostMatches, array('_route' => 'route12')), array ( 'var1' => 'val',)); } @@ -292,7 +292,7 @@ public function match($pathinfo) } // route17 - if ($pathinfo === '/route17') { + if ('/route17' === $pathinfo) { return array('_route' => 'route17'); } @@ -300,7 +300,7 @@ public function match($pathinfo) if (0 === strpos($pathinfo, '/a')) { // a - if ($pathinfo === '/a/a...') { + if ('/a/a...' === $pathinfo) { return array('_route' => 'a'); } @@ -320,7 +320,7 @@ public function match($pathinfo) } // secure - if ($pathinfo === '/secure') { + if ('/secure' === $pathinfo) { $requiredSchemes = array ( 'https' => 0,); if (!isset($requiredSchemes[$this->context->getScheme()])) { return $this->redirect($pathinfo, 'secure', key($requiredSchemes)); @@ -330,7 +330,7 @@ public function match($pathinfo) } // nonsecure - if ($pathinfo === '/nonsecure') { + if ('/nonsecure' === $pathinfo) { $requiredSchemes = array ( 'http' => 0,); if (!isset($requiredSchemes[$this->context->getScheme()])) { return $this->redirect($pathinfo, 'nonsecure', key($requiredSchemes)); diff --git a/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher3.php b/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher3.php index d9da7b02d4b43..bc8bf513c4884 100644 --- a/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher3.php +++ b/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher3.php @@ -29,7 +29,7 @@ public function match($pathinfo) if (0 === strpos($pathinfo, '/rootprefix')) { // static - if ($pathinfo === '/rootprefix/test') { + if ('/rootprefix/test' === $pathinfo) { return array('_route' => 'static'); } @@ -41,7 +41,7 @@ public function match($pathinfo) } // with-condition - if ($pathinfo === '/with-condition' && ($context->getMethod() == "GET")) { + if ('/with-condition' === $pathinfo && ($context->getMethod() == "GET")) { return array('_route' => 'with-condition'); } diff --git a/src/Symfony/Component/Security/Acl/Dbal/MutableAclProvider.php b/src/Symfony/Component/Security/Acl/Dbal/MutableAclProvider.php index ba50d48fa275e..2555c15044474 100644 --- a/src/Symfony/Component/Security/Acl/Dbal/MutableAclProvider.php +++ b/src/Symfony/Component/Security/Acl/Dbal/MutableAclProvider.php @@ -315,7 +315,7 @@ public function updateAcl(MutableAclInterface $acl) foreach ($this->loadedAcls[$acl->getObjectIdentity()->getType()] as $sameTypeAcl) { if (isset($sharedPropertyChanges['classAces'])) { - if ($acl !== $sameTypeAcl && $classAcesProperty->getValue($sameTypeAcl) !== $sharedPropertyChanges['classAces'][0]) { + if ($acl !== $sameTypeAcl && $sharedPropertyChanges['classAces'][0] !== $classAcesProperty->getValue($sameTypeAcl)) { throw new ConcurrentModificationException('The "classAces" property has been modified concurrently.'); } @@ -323,7 +323,7 @@ public function updateAcl(MutableAclInterface $acl) } if (isset($sharedPropertyChanges['classFieldAces'])) { - if ($acl !== $sameTypeAcl && $classFieldAcesProperty->getValue($sameTypeAcl) !== $sharedPropertyChanges['classFieldAces'][0]) { + if ($acl !== $sameTypeAcl && $sharedPropertyChanges['classFieldAces'][0] !== $classFieldAcesProperty->getValue($sameTypeAcl)) { throw new ConcurrentModificationException('The "classFieldAces" property has been modified concurrently.'); } @@ -870,7 +870,7 @@ private function updateNewFieldAceProperty($name, array $changes) $classId = $this->createOrRetrieveClassId($oid->getType()); } - $objectIdentityId = $name === 'classFieldAces' ? null : $ace->getAcl()->getId(); + $objectIdentityId = 'classFieldAces' === $name ? null : $ace->getAcl()->getId(); $this->connection->executeQuery($this->getInsertAccessControlEntrySql($classId, $objectIdentityId, $field, $i, $sid, $ace->getStrategy(), $ace->getMask(), $ace->isGranting(), $ace->isAuditSuccess(), $ace->isAuditFailure())); $aceId = $this->connection->executeQuery($this->getSelectAccessControlEntryIdSql($classId, $objectIdentityId, $field, $i))->fetchColumn(); @@ -944,7 +944,7 @@ private function updateNewAceProperty($name, array $changes) $classId = $this->createOrRetrieveClassId($oid->getType()); } - $objectIdentityId = $name === 'classAces' ? null : $ace->getAcl()->getId(); + $objectIdentityId = 'classAces' === $name ? null : $ace->getAcl()->getId(); $this->connection->executeQuery($this->getInsertAccessControlEntrySql($classId, $objectIdentityId, null, $i, $sid, $ace->getStrategy(), $ace->getMask(), $ace->isGranting(), $ace->isAuditSuccess(), $ace->isAuditFailure())); $aceId = $this->connection->executeQuery($this->getSelectAccessControlEntryIdSql($classId, $objectIdentityId, null, $i))->fetchColumn(); diff --git a/src/Symfony/Component/Security/Acl/Tests/Dbal/AclProviderBenchmarkTest.php b/src/Symfony/Component/Security/Acl/Tests/Dbal/AclProviderBenchmarkTest.php index b5b4dab95f544..6341401c24c2a 100644 --- a/src/Symfony/Component/Security/Acl/Tests/Dbal/AclProviderBenchmarkTest.php +++ b/src/Symfony/Component/Security/Acl/Tests/Dbal/AclProviderBenchmarkTest.php @@ -121,7 +121,7 @@ protected function chooseClassId() { static $id = 1000; - if ($id === 1000 || ($id < 1500 && rand(0, 1))) { + if (1000 === $id || ($id < 1500 && rand(0, 1))) { $this->insertClassStmt->execute(array($id, $this->getRandomString(rand(20, 100), 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789\\_'))); ++$id; @@ -158,7 +158,7 @@ protected function chooseSid() { static $id = 1000; - if ($id === 1000 || ($id < 11000 && rand(0, 1))) { + if (1000 === $id || ($id < 11000 && rand(0, 1))) { $this->insertSidStmt->execute(array( $id, $this->getRandomString(rand(5, 30)), @@ -193,9 +193,9 @@ protected function generateAces($classId, $objectId) $sids[$sid][] = $fieldName; $strategy = rand(0, 2); - if ($strategy === 0) { + if (0 === $strategy) { $strategy = PermissionGrantingStrategy::ALL; - } elseif ($strategy === 1) { + } elseif (1 === $strategy) { $strategy = PermissionGrantingStrategy::ANY; } else { $strategy = PermissionGrantingStrategy::EQUAL; diff --git a/src/Symfony/Component/Security/Core/Authorization/AccessDecisionManager.php b/src/Symfony/Component/Security/Core/Authorization/AccessDecisionManager.php index c18c2cbf09f0f..55c65dd7a53a7 100644 --- a/src/Symfony/Component/Security/Core/Authorization/AccessDecisionManager.php +++ b/src/Symfony/Component/Security/Core/Authorization/AccessDecisionManager.php @@ -172,7 +172,7 @@ private function decideConsensus(TokenInterface $token, array $attributes, $obje return false; } - if ($grant == $deny && $grant != 0) { + if ($grant == $deny && 0 != $grant) { return $this->allowIfEqualGrantedDeniedDecisions; } diff --git a/src/Symfony/Component/Security/Core/User/InMemoryUserProvider.php b/src/Symfony/Component/Security/Core/User/InMemoryUserProvider.php index cde4454e9be3e..6fde611aefd0e 100644 --- a/src/Symfony/Component/Security/Core/User/InMemoryUserProvider.php +++ b/src/Symfony/Component/Security/Core/User/InMemoryUserProvider.php @@ -91,7 +91,7 @@ public function refreshUser(UserInterface $user) */ public function supportsClass($class) { - return $class === 'Symfony\Component\Security\Core\User\User'; + return 'Symfony\Component\Security\Core\User\User' === $class; } /** diff --git a/src/Symfony/Component/Security/Http/Authentication/AuthenticationUtils.php b/src/Symfony/Component/Security/Http/Authentication/AuthenticationUtils.php index c6397e8ca1e3b..0012d36a1fa00 100644 --- a/src/Symfony/Component/Security/Http/Authentication/AuthenticationUtils.php +++ b/src/Symfony/Component/Security/Http/Authentication/AuthenticationUtils.php @@ -49,7 +49,7 @@ public function getLastAuthenticationError($clearSession = true) if ($request->attributes->has(Security::AUTHENTICATION_ERROR)) { $authenticationException = $request->attributes->get(Security::AUTHENTICATION_ERROR); - } elseif ($session !== null && $session->has(Security::AUTHENTICATION_ERROR)) { + } elseif (null !== $session && $session->has(Security::AUTHENTICATION_ERROR)) { $authenticationException = $session->get(Security::AUTHENTICATION_ERROR); if ($clearSession) { diff --git a/src/Symfony/Component/Security/Http/HttpUtils.php b/src/Symfony/Component/Security/Http/HttpUtils.php index 56add79926d3e..1a8b4f3ced155 100644 --- a/src/Symfony/Component/Security/Http/HttpUtils.php +++ b/src/Symfony/Component/Security/Http/HttpUtils.php @@ -41,7 +41,7 @@ class HttpUtils public function __construct(UrlGeneratorInterface $urlGenerator = null, $urlMatcher = null) { $this->urlGenerator = $urlGenerator; - if ($urlMatcher !== null && !$urlMatcher instanceof UrlMatcherInterface && !$urlMatcher instanceof RequestMatcherInterface) { + if (null !== $urlMatcher && !$urlMatcher instanceof UrlMatcherInterface && !$urlMatcher instanceof RequestMatcherInterface) { throw new \InvalidArgumentException('Matcher must either implement UrlMatcherInterface or RequestMatcherInterface.'); } $this->urlMatcher = $urlMatcher; diff --git a/src/Symfony/Component/Security/Http/RememberMe/AbstractRememberMeServices.php b/src/Symfony/Component/Security/Http/RememberMe/AbstractRememberMeServices.php index 4ab3465c66263..675afe7eed799 100644 --- a/src/Symfony/Component/Security/Http/RememberMe/AbstractRememberMeServices.php +++ b/src/Symfony/Component/Security/Http/RememberMe/AbstractRememberMeServices.php @@ -318,6 +318,6 @@ protected function isRememberMeRequested(Request $request) $this->logger->debug('Did not send remember-me cookie.', array('parameter' => $this->options['remember_me_parameter'])); } - return $parameter === 'true' || $parameter === 'on' || $parameter === '1' || $parameter === 'yes' || $parameter === true; + return 'true' === $parameter || 'on' === $parameter || '1' === $parameter || 'yes' === $parameter || true === $parameter; } } diff --git a/src/Symfony/Component/Security/Http/RememberMe/PersistentTokenBasedRememberMeServices.php b/src/Symfony/Component/Security/Http/RememberMe/PersistentTokenBasedRememberMeServices.php index cbbbb235192d9..c294067377c27 100644 --- a/src/Symfony/Component/Security/Http/RememberMe/PersistentTokenBasedRememberMeServices.php +++ b/src/Symfony/Component/Security/Http/RememberMe/PersistentTokenBasedRememberMeServices.php @@ -72,7 +72,7 @@ protected function cancelCookie(Request $request) // Delete cookie from the tokenProvider if (null !== ($cookie = $request->cookies->get($this->options['name'])) - && count($parts = $this->decodeCookie($cookie)) === 2 + && 2 === count($parts = $this->decodeCookie($cookie)) ) { list($series) = $parts; $this->tokenProvider->deleteTokenBySeries($series); @@ -84,7 +84,7 @@ protected function cancelCookie(Request $request) */ protected function processAutoLoginCookie(array $cookieParts, Request $request) { - if (count($cookieParts) !== 2) { + if (2 !== count($cookieParts)) { throw new AuthenticationException('The cookie is invalid.'); } diff --git a/src/Symfony/Component/Security/Http/RememberMe/TokenBasedRememberMeServices.php b/src/Symfony/Component/Security/Http/RememberMe/TokenBasedRememberMeServices.php index d68ada5211a92..25d2bd5a4b9a8 100644 --- a/src/Symfony/Component/Security/Http/RememberMe/TokenBasedRememberMeServices.php +++ b/src/Symfony/Component/Security/Http/RememberMe/TokenBasedRememberMeServices.php @@ -32,7 +32,7 @@ class TokenBasedRememberMeServices extends AbstractRememberMeServices */ protected function processAutoLoginCookie(array $cookieParts, Request $request) { - if (count($cookieParts) !== 4) { + if (4 !== count($cookieParts)) { throw new AuthenticationException('The cookie is invalid.'); } diff --git a/src/Symfony/Component/Security/Http/Tests/Firewall/ContextListenerTest.php b/src/Symfony/Component/Security/Http/Tests/Firewall/ContextListenerTest.php index ba8edc3b17401..e3bb11caa9c87 100644 --- a/src/Symfony/Component/Security/Http/Tests/Firewall/ContextListenerTest.php +++ b/src/Symfony/Component/Security/Http/Tests/Firewall/ContextListenerTest.php @@ -283,7 +283,7 @@ protected function runSessionOnKernelResponse($newToken, $original = null) { $session = new Session(new MockArraySessionStorage()); - if ($original !== null) { + if (null !== $original) { $session->set('_security_session', $original); } diff --git a/src/Symfony/Component/Security/Http/Tests/RememberMe/ResponseListenerTest.php b/src/Symfony/Component/Security/Http/Tests/RememberMe/ResponseListenerTest.php index 42649ef5f6577..bc10698f0fb4f 100644 --- a/src/Symfony/Component/Security/Http/Tests/RememberMe/ResponseListenerTest.php +++ b/src/Symfony/Component/Security/Http/Tests/RememberMe/ResponseListenerTest.php @@ -96,7 +96,7 @@ private function getEvent($request, $response, $type = HttpKernelInterface::MAST ->getMock(); $event->expects($this->any())->method('getRequest')->will($this->returnValue($request)); - $event->expects($this->any())->method('isMasterRequest')->will($this->returnValue($type === HttpKernelInterface::MASTER_REQUEST)); + $event->expects($this->any())->method('isMasterRequest')->will($this->returnValue(HttpKernelInterface::MASTER_REQUEST === $type)); $event->expects($this->any())->method('getResponse')->will($this->returnValue($response)); return $event; diff --git a/src/Symfony/Component/Serializer/Encoder/XmlEncoder.php b/src/Symfony/Component/Serializer/Encoder/XmlEncoder.php index e8a24a39d69d0..b363401f235df 100644 --- a/src/Symfony/Component/Serializer/Encoder/XmlEncoder.php +++ b/src/Symfony/Component/Serializer/Encoder/XmlEncoder.php @@ -94,10 +94,10 @@ public function decode($data, $format, array $context = array()) $rootNode = null; foreach ($dom->childNodes as $child) { - if ($child->nodeType === XML_DOCUMENT_TYPE_NODE) { + if (XML_DOCUMENT_TYPE_NODE === $child->nodeType) { throw new UnexpectedValueException('Document types are not allowed.'); } - if (!$rootNode && $child->nodeType !== XML_PI_NODE) { + if (!$rootNode && XML_PI_NODE !== $child->nodeType) { $rootNode = $child; } } @@ -339,7 +339,7 @@ private function parseXmlValue(\DOMNode $node) $value = array(); foreach ($node->childNodes as $subnode) { - if ($subnode->nodeType === XML_PI_NODE) { + if (XML_PI_NODE === $subnode->nodeType) { continue; } @@ -388,7 +388,7 @@ private function buildXml(\DOMNode $parentNode, $data, $xmlRootNodeName = null) $data = $this->serializer->normalize($data, $this->format, $this->context); } $parentNode->setAttribute($attributeName, $data); - } elseif ($key === '#') { + } elseif ('#' === $key) { $append = $this->selectNodeType($parentNode, $data); } elseif (is_array($data) && false === is_numeric($key)) { // Is this array fully numeric keys? diff --git a/src/Symfony/Component/Serializer/Normalizer/AbstractNormalizer.php b/src/Symfony/Component/Serializer/Normalizer/AbstractNormalizer.php index 5149d0dbc7d97..85b9c83d5247c 100644 --- a/src/Symfony/Component/Serializer/Normalizer/AbstractNormalizer.php +++ b/src/Symfony/Component/Serializer/Normalizer/AbstractNormalizer.php @@ -325,7 +325,7 @@ protected function instantiateObject(array &$data, $class, array &$context, \Ref $paramName = $constructorParameter->name; $key = $this->nameConverter ? $this->nameConverter->normalize($paramName) : $paramName; - $allowed = $allowedAttributes === false || in_array($paramName, $allowedAttributes); + $allowed = false === $allowedAttributes || in_array($paramName, $allowedAttributes); $ignored = in_array($paramName, $this->ignoredAttributes); if (method_exists($constructorParameter, 'isVariadic') && $constructorParameter->isVariadic()) { if ($allowed && !$ignored && (isset($data[$key]) || array_key_exists($key, $data))) { diff --git a/src/Symfony/Component/Serializer/Normalizer/GetSetMethodNormalizer.php b/src/Symfony/Component/Serializer/Normalizer/GetSetMethodNormalizer.php index a5e5dbf8484c9..2b054dfc9d9cb 100644 --- a/src/Symfony/Component/Serializer/Normalizer/GetSetMethodNormalizer.php +++ b/src/Symfony/Component/Serializer/Normalizer/GetSetMethodNormalizer.php @@ -108,7 +108,7 @@ public function denormalize($data, $class, $format = null, array $context = arra $attribute = $this->nameConverter->denormalize($attribute); } - $allowed = $allowedAttributes === false || in_array($attribute, $allowedAttributes); + $allowed = false === $allowedAttributes || in_array($attribute, $allowedAttributes); $ignored = in_array($attribute, $this->ignoredAttributes); if ($allowed && !$ignored) { diff --git a/src/Symfony/Component/Serializer/Normalizer/ObjectNormalizer.php b/src/Symfony/Component/Serializer/Normalizer/ObjectNormalizer.php index fe1676fbf36fb..fbd771dbd76ab 100644 --- a/src/Symfony/Component/Serializer/Normalizer/ObjectNormalizer.php +++ b/src/Symfony/Component/Serializer/Normalizer/ObjectNormalizer.php @@ -75,10 +75,10 @@ public function normalize($object, $format = null, array $context = array()) ) { $name = $reflMethod->getName(); - if (strpos($name, 'get') === 0 || strpos($name, 'has') === 0) { + if (0 === strpos($name, 'get') || 0 === strpos($name, 'has')) { // getters and hassers $attributes[lcfirst(substr($name, 3))] = true; - } elseif (strpos($name, 'is') === 0) { + } elseif (0 === strpos($name, 'is')) { // issers $attributes[lcfirst(substr($name, 2))] = true; } @@ -148,7 +148,7 @@ public function denormalize($data, $class, $format = null, array $context = arra $attribute = $this->nameConverter->denormalize($attribute); } - $allowed = $allowedAttributes === false || in_array($attribute, $allowedAttributes); + $allowed = false === $allowedAttributes || in_array($attribute, $allowedAttributes); $ignored = in_array($attribute, $this->ignoredAttributes); if ($allowed && !$ignored) { diff --git a/src/Symfony/Component/Serializer/Normalizer/PropertyNormalizer.php b/src/Symfony/Component/Serializer/Normalizer/PropertyNormalizer.php index abbc74f27c5bc..a5764244fe4cc 100644 --- a/src/Symfony/Component/Serializer/Normalizer/PropertyNormalizer.php +++ b/src/Symfony/Component/Serializer/Normalizer/PropertyNormalizer.php @@ -105,7 +105,7 @@ public function denormalize($data, $class, $format = null, array $context = arra $propertyName = $this->nameConverter->denormalize($propertyName); } - $allowed = $allowedAttributes === false || in_array($propertyName, $allowedAttributes); + $allowed = false === $allowedAttributes || in_array($propertyName, $allowedAttributes); $ignored = in_array($propertyName, $this->ignoredAttributes); if ($allowed && !$ignored && $reflectionClass->hasProperty($propertyName)) { $property = $reflectionClass->getProperty($propertyName); diff --git a/src/Symfony/Component/Serializer/Tests/Fixtures/ScalarDummy.php b/src/Symfony/Component/Serializer/Tests/Fixtures/ScalarDummy.php index e9db23882b58f..598e76fda8bf7 100644 --- a/src/Symfony/Component/Serializer/Tests/Fixtures/ScalarDummy.php +++ b/src/Symfony/Component/Serializer/Tests/Fixtures/ScalarDummy.php @@ -23,12 +23,12 @@ class ScalarDummy implements NormalizableInterface, DenormalizableInterface public function normalize(NormalizerInterface $normalizer, $format = null, array $context = array()) { - return $format === 'xml' ? $this->xmlFoo : $this->foo; + return 'xml' === $format ? $this->xmlFoo : $this->foo; } public function denormalize(DenormalizerInterface $denormalizer, $data, $format = null, array $context = array()) { - if ($format === 'xml') { + if ('xml' === $format) { $this->xmlFoo = $data; } else { $this->foo = $data; diff --git a/src/Symfony/Component/Templating/Loader/FilesystemLoader.php b/src/Symfony/Component/Templating/Loader/FilesystemLoader.php index 0d102a6326e6c..a190f887aa053 100644 --- a/src/Symfony/Component/Templating/Loader/FilesystemLoader.php +++ b/src/Symfony/Component/Templating/Loader/FilesystemLoader.php @@ -111,10 +111,10 @@ public function isFresh(TemplateReferenceInterface $template, $time) */ protected static function isAbsolutePath($file) { - if ($file[0] == '/' || $file[0] == '\\' + if ('/' == $file[0] || '\\' == $file[0] || (strlen($file) > 3 && ctype_alpha($file[0]) - && $file[1] == ':' - && ($file[2] == '\\' || $file[2] == '/') + && ':' == $file[1] + && ('\\' == $file[2] || '/' == $file[2]) ) || null !== parse_url($file, PHP_URL_SCHEME) ) { diff --git a/src/Symfony/Component/Translation/Loader/MoFileLoader.php b/src/Symfony/Component/Translation/Loader/MoFileLoader.php index 3a0c80f1c91cf..50811d01aaf9f 100644 --- a/src/Symfony/Component/Translation/Loader/MoFileLoader.php +++ b/src/Symfony/Component/Translation/Loader/MoFileLoader.php @@ -96,9 +96,9 @@ private function parse($resource) $magic = unpack('V1', fread($stream, 4)); $magic = hexdec(substr(dechex(current($magic)), -8)); - if ($magic == self::MO_LITTLE_ENDIAN_MAGIC) { + if (self::MO_LITTLE_ENDIAN_MAGIC == $magic) { $isBigEndian = false; - } elseif ($magic == self::MO_BIG_ENDIAN_MAGIC) { + } elseif (self::MO_BIG_ENDIAN_MAGIC == $magic) { $isBigEndian = true; } else { throw new InvalidResourceException('MO stream content has an invalid format.'); @@ -132,7 +132,7 @@ private function parse($resource) fseek($stream, $offset); $singularId = fread($stream, $length); - if (strpos($singularId, "\000") !== false) { + if (false !== strpos($singularId, "\000")) { list($singularId, $pluralId) = explode("\000", $singularId); } @@ -147,7 +147,7 @@ private function parse($resource) fseek($stream, $offset); $translated = fread($stream, $length); - if (strpos($translated, "\000") !== false) { + if (false !== strpos($translated, "\000")) { $translated = explode("\000", $translated); } diff --git a/src/Symfony/Component/Translation/Loader/PoFileLoader.php b/src/Symfony/Component/Translation/Loader/PoFileLoader.php index 29e898cc47ceb..c2d0ce2b99a34 100644 --- a/src/Symfony/Component/Translation/Loader/PoFileLoader.php +++ b/src/Symfony/Component/Translation/Loader/PoFileLoader.php @@ -113,24 +113,24 @@ private function parse($resource) while ($line = fgets($stream)) { $line = trim($line); - if ($line === '') { + if ('' === $line) { // Whitespace indicated current item is done if (!in_array('fuzzy', $flags)) { $this->addMessage($messages, $item); } $item = $defaults; $flags = array(); - } elseif (substr($line, 0, 2) === '#,') { + } elseif ('#,' === substr($line, 0, 2)) { $flags = array_map('trim', explode(',', substr($line, 2))); - } elseif (substr($line, 0, 7) === 'msgid "') { + } elseif ('msgid "' === substr($line, 0, 7)) { // We start a new msg so save previous // TODO: this fails when comments or contexts are added $this->addMessage($messages, $item); $item = $defaults; $item['ids']['singular'] = substr($line, 7, -1); - } elseif (substr($line, 0, 8) === 'msgstr "') { + } elseif ('msgstr "' === substr($line, 0, 8)) { $item['translated'] = substr($line, 8, -1); - } elseif ($line[0] === '"') { + } elseif ('"' === $line[0]) { $continues = isset($item['translated']) ? 'translated' : 'ids'; if (is_array($item[$continues])) { @@ -139,9 +139,9 @@ private function parse($resource) } else { $item[$continues] .= substr($line, 1, -1); } - } elseif (substr($line, 0, 14) === 'msgid_plural "') { + } elseif ('msgid_plural "' === substr($line, 0, 14)) { $item['ids']['plural'] = substr($line, 14, -1); - } elseif (substr($line, 0, 7) === 'msgstr[') { + } elseif ('msgstr[' === substr($line, 0, 7)) { $size = strpos($line, ']'); $item['translated'][(int) substr($line, 7, 1)] = substr($line, $size + 3, -1); } diff --git a/src/Symfony/Component/Translation/Loader/QtFileLoader.php b/src/Symfony/Component/Translation/Loader/QtFileLoader.php index 657bd6eb53ce5..22536aa866c62 100644 --- a/src/Symfony/Component/Translation/Loader/QtFileLoader.php +++ b/src/Symfony/Component/Translation/Loader/QtFileLoader.php @@ -50,7 +50,7 @@ public function load($resource, $locale, $domain = 'messages') $nodes = $xpath->evaluate('//TS/context/name[text()="'.$domain.'"]'); $catalogue = new MessageCatalogue($locale); - if ($nodes->length == 1) { + if (1 == $nodes->length) { $translations = $nodes->item(0)->nextSibling->parentNode->parentNode->getElementsByTagName('message'); foreach ($translations as $translation) { $translationValue = (string) $translation->getElementsByTagName('translation')->item(0)->nodeValue; diff --git a/src/Symfony/Component/Translation/PluralizationRules.php b/src/Symfony/Component/Translation/PluralizationRules.php index 09748211b13b3..847ffe3c44f76 100644 --- a/src/Symfony/Component/Translation/PluralizationRules.php +++ b/src/Symfony/Component/Translation/PluralizationRules.php @@ -123,7 +123,7 @@ public static function get($number, $locale) case 'tk': case 'ur': case 'zu': - return ($number == 1) ? 0 : 1; + return (1 == $number) ? 0 : 1; case 'am': case 'bh': @@ -138,7 +138,7 @@ public static function get($number, $locale) case 'xbr': case 'ti': case 'wa': - return (($number == 0) || ($number == 1)) ? 0 : 1; + return ((0 == $number) || (1 == $number)) ? 0 : 1; case 'be': case 'bs': @@ -146,41 +146,41 @@ public static function get($number, $locale) case 'ru': case 'sr': case 'uk': - return (($number % 10 == 1) && ($number % 100 != 11)) ? 0 : ((($number % 10 >= 2) && ($number % 10 <= 4) && (($number % 100 < 10) || ($number % 100 >= 20))) ? 1 : 2); + return ((1 == $number % 10) && (11 != $number % 100)) ? 0 : ((($number % 10 >= 2) && ($number % 10 <= 4) && (($number % 100 < 10) || ($number % 100 >= 20))) ? 1 : 2); case 'cs': case 'sk': - return ($number == 1) ? 0 : ((($number >= 2) && ($number <= 4)) ? 1 : 2); + return (1 == $number) ? 0 : ((($number >= 2) && ($number <= 4)) ? 1 : 2); case 'ga': - return ($number == 1) ? 0 : (($number == 2) ? 1 : 2); + return (1 == $number) ? 0 : ((2 == $number) ? 1 : 2); case 'lt': - return (($number % 10 == 1) && ($number % 100 != 11)) ? 0 : ((($number % 10 >= 2) && (($number % 100 < 10) || ($number % 100 >= 20))) ? 1 : 2); + return ((1 == $number % 10) && (11 != $number % 100)) ? 0 : ((($number % 10 >= 2) && (($number % 100 < 10) || ($number % 100 >= 20))) ? 1 : 2); case 'sl': - return ($number % 100 == 1) ? 0 : (($number % 100 == 2) ? 1 : ((($number % 100 == 3) || ($number % 100 == 4)) ? 2 : 3)); + return (1 == $number % 100) ? 0 : ((2 == $number % 100) ? 1 : (((3 == $number % 100) || (4 == $number % 100)) ? 2 : 3)); case 'mk': - return ($number % 10 == 1) ? 0 : 1; + return (1 == $number % 10) ? 0 : 1; case 'mt': - return ($number == 1) ? 0 : ((($number == 0) || (($number % 100 > 1) && ($number % 100 < 11))) ? 1 : ((($number % 100 > 10) && ($number % 100 < 20)) ? 2 : 3)); + return (1 == $number) ? 0 : (((0 == $number) || (($number % 100 > 1) && ($number % 100 < 11))) ? 1 : ((($number % 100 > 10) && ($number % 100 < 20)) ? 2 : 3)); case 'lv': - return ($number == 0) ? 0 : ((($number % 10 == 1) && ($number % 100 != 11)) ? 1 : 2); + return (0 == $number) ? 0 : (((1 == $number % 10) && (11 != $number % 100)) ? 1 : 2); case 'pl': - return ($number == 1) ? 0 : ((($number % 10 >= 2) && ($number % 10 <= 4) && (($number % 100 < 12) || ($number % 100 > 14))) ? 1 : 2); + return (1 == $number) ? 0 : ((($number % 10 >= 2) && ($number % 10 <= 4) && (($number % 100 < 12) || ($number % 100 > 14))) ? 1 : 2); case 'cy': - return ($number == 1) ? 0 : (($number == 2) ? 1 : ((($number == 8) || ($number == 11)) ? 2 : 3)); + return (1 == $number) ? 0 : ((2 == $number) ? 1 : (((8 == $number) || (11 == $number)) ? 2 : 3)); case 'ro': - return ($number == 1) ? 0 : ((($number == 0) || (($number % 100 > 0) && ($number % 100 < 20))) ? 1 : 2); + return (1 == $number) ? 0 : (((0 == $number) || (($number % 100 > 0) && ($number % 100 < 20))) ? 1 : 2); case 'ar': - return ($number == 0) ? 0 : (($number == 1) ? 1 : (($number == 2) ? 2 : ((($number % 100 >= 3) && ($number % 100 <= 10)) ? 3 : ((($number % 100 >= 11) && ($number % 100 <= 99)) ? 4 : 5)))); + return (0 == $number) ? 0 : ((1 == $number) ? 1 : ((2 == $number) ? 2 : ((($number % 100 >= 3) && ($number % 100 <= 10)) ? 3 : ((($number % 100 >= 11) && ($number % 100 <= 99)) ? 4 : 5)))); default: return 0; diff --git a/src/Symfony/Component/Translation/Translator.php b/src/Symfony/Component/Translation/Translator.php index 816cfd28f9f2a..a8371f01026a4 100644 --- a/src/Symfony/Component/Translation/Translator.php +++ b/src/Symfony/Component/Translation/Translator.php @@ -443,7 +443,7 @@ protected function computeFallbackLocales($locale) $locales[] = $fallback; } - if (strrchr($locale, '_') !== false) { + if (false !== strrchr($locale, '_')) { array_unshift($locales, substr($locale, 0, -strlen(strrchr($locale, '_')))); } diff --git a/src/Symfony/Component/Validator/Constraint.php b/src/Symfony/Component/Validator/Constraint.php index fc9d8ae563448..bac99dcfcf11f 100644 --- a/src/Symfony/Component/Validator/Constraint.php +++ b/src/Symfony/Component/Validator/Constraint.php @@ -141,7 +141,7 @@ public function __construct($options = null) $invalidOptions[] = $option; } } - } elseif (null !== $options && !(is_array($options) && count($options) === 0)) { + } elseif (null !== $options && !(is_array($options) && 0 === count($options))) { $option = $this->getDefaultOption(); if (null === $option) { diff --git a/src/Symfony/Component/Validator/Constraints/ChoiceValidator.php b/src/Symfony/Component/Validator/Constraints/ChoiceValidator.php index 83cfc6e77887a..c1b11599d024d 100644 --- a/src/Symfony/Component/Validator/Constraints/ChoiceValidator.php +++ b/src/Symfony/Component/Validator/Constraints/ChoiceValidator.php @@ -81,7 +81,7 @@ public function validate($value, Constraint $constraint) $count = count($value); - if ($constraint->min !== null && $count < $constraint->min) { + if (null !== $constraint->min && $count < $constraint->min) { if ($this->context instanceof ExecutionContextInterface) { $this->context->buildViolation($constraint->minMessage) ->setParameter('{{ limit }}', $constraint->min) @@ -99,7 +99,7 @@ public function validate($value, Constraint $constraint) return; } - if ($constraint->max !== null && $count > $constraint->max) { + if (null !== $constraint->max && $count > $constraint->max) { if ($this->context instanceof ExecutionContextInterface) { $this->context->buildViolation($constraint->maxMessage) ->setParameter('{{ limit }}', $constraint->max) diff --git a/src/Symfony/Component/Validator/Constraints/Collection.php b/src/Symfony/Component/Validator/Constraints/Collection.php index ae55366cc9f23..afb0f03e35703 100644 --- a/src/Symfony/Component/Validator/Constraints/Collection.php +++ b/src/Symfony/Component/Validator/Constraints/Collection.php @@ -63,7 +63,7 @@ protected function initializeNestedConstraints() foreach ($this->fields as $fieldName => $field) { // the XmlFileLoader and YamlFileLoader pass the field Optional // and Required constraint as an array with exactly one element - if (is_array($field) && count($field) == 1) { + if (is_array($field) && 1 == count($field)) { $this->fields[$fieldName] = $field = $field[0]; } diff --git a/src/Symfony/Component/Validator/Constraints/ImageValidator.php b/src/Symfony/Component/Validator/Constraints/ImageValidator.php index a5165e25532cd..4ff9e00c2f9be 100644 --- a/src/Symfony/Component/Validator/Constraints/ImageValidator.php +++ b/src/Symfony/Component/Validator/Constraints/ImageValidator.php @@ -53,7 +53,7 @@ public function validate($value, Constraint $constraint) $size = @getimagesize($value); - if (empty($size) || ($size[0] === 0) || ($size[1] === 0)) { + if (empty($size) || (0 === $size[0]) || (0 === $size[1])) { if ($this->context instanceof ExecutionContextInterface) { $this->context->buildViolation($constraint->sizeNotDetectedMessage) ->setCode(Image::SIZE_NOT_DETECTED_ERROR) diff --git a/src/Symfony/Component/Validator/Constraints/TypeValidator.php b/src/Symfony/Component/Validator/Constraints/TypeValidator.php index 592f122502773..e5ae85e542d56 100644 --- a/src/Symfony/Component/Validator/Constraints/TypeValidator.php +++ b/src/Symfony/Component/Validator/Constraints/TypeValidator.php @@ -35,7 +35,7 @@ public function validate($value, Constraint $constraint) } $type = strtolower($constraint->type); - $type = $type == 'boolean' ? 'bool' : $constraint->type; + $type = 'boolean' == $type ? 'bool' : $constraint->type; $isFunction = 'is_'.$type; $ctypeFunction = 'ctype_'.$type; diff --git a/src/Symfony/Component/Validator/Constraints/UuidValidator.php b/src/Symfony/Component/Validator/Constraints/UuidValidator.php index d025a560d28aa..6dcda078a418e 100644 --- a/src/Symfony/Component/Validator/Constraints/UuidValidator.php +++ b/src/Symfony/Component/Validator/Constraints/UuidValidator.php @@ -327,7 +327,7 @@ private function validateStrict($value, Uuid $constraint) // 0b10xx // & 0b1100 (12) // = 0b1000 (8) - if ((hexdec($value[self::STRICT_VARIANT_POSITION]) & 12) !== 8) { + if (8 !== (hexdec($value[self::STRICT_VARIANT_POSITION]) & 12)) { if ($this->context instanceof ExecutionContextInterface) { $this->context->buildViolation($constraint->message) ->setParameter('{{ value }}', $this->formatValue($value)) diff --git a/src/Symfony/Component/Validator/Mapping/Loader/AbstractLoader.php b/src/Symfony/Component/Validator/Mapping/Loader/AbstractLoader.php index 2ae89886c8d09..0d61e9aa4394a 100644 --- a/src/Symfony/Component/Validator/Mapping/Loader/AbstractLoader.php +++ b/src/Symfony/Component/Validator/Mapping/Loader/AbstractLoader.php @@ -72,9 +72,9 @@ protected function addNamespaceAlias($alias, $namespace) */ protected function newConstraint($name, $options = null) { - if (strpos($name, '\\') !== false && class_exists($name)) { + if (false !== strpos($name, '\\') && class_exists($name)) { $className = (string) $name; - } elseif (strpos($name, ':') !== false) { + } elseif (false !== strpos($name, ':')) { list($prefix, $className) = explode(':', $name, 2); if (!isset($this->namespaces[$prefix])) { diff --git a/src/Symfony/Component/VarDumper/Caster/SplCaster.php b/src/Symfony/Component/VarDumper/Caster/SplCaster.php index d50419f624394..835837266128e 100644 --- a/src/Symfony/Component/VarDumper/Caster/SplCaster.php +++ b/src/Symfony/Component/VarDumper/Caster/SplCaster.php @@ -33,7 +33,7 @@ public static function castArrayObject(\ArrayObject $c, array $a, Stub $stub, $i $prefix.'storage' => $c->getArrayCopy(), ); - if ($class === 'ArrayObject') { + if ('ArrayObject' === $class) { $a = $b; } else { if (!($flags & \ArrayObject::STD_PROP_LIST)) { diff --git a/src/Symfony/Component/VarDumper/Tests/VarClonerTest.php b/src/Symfony/Component/VarDumper/Tests/VarClonerTest.php index 6e98d6ecbcd78..a1c69224b9bf5 100644 --- a/src/Symfony/Component/VarDumper/Tests/VarClonerTest.php +++ b/src/Symfony/Component/VarDumper/Tests/VarClonerTest.php @@ -138,7 +138,7 @@ public function testClone() public function testJsonCast() { - if (ini_get('xdebug.overload_var_dump') == 2) { + if (2 == ini_get('xdebug.overload_var_dump')) { $this->markTestSkipped('xdebug is active'); } diff --git a/src/Symfony/Component/Yaml/Inline.php b/src/Symfony/Component/Yaml/Inline.php index 06268a2bc6979..6d5ac1cd807f2 100644 --- a/src/Symfony/Component/Yaml/Inline.php +++ b/src/Symfony/Component/Yaml/Inline.php @@ -481,7 +481,7 @@ private static function evaluateScalar($scalar, $references = array()) case 'false' === $scalarLower: return false; // Optimise for returning strings. - case $scalar[0] === '+' || $scalar[0] === '-' || $scalar[0] === '.' || $scalar[0] === '!' || is_numeric($scalar[0]): + case '+' === $scalar[0] || '-' === $scalar[0] || '.' === $scalar[0] || '!' === $scalar[0] || is_numeric($scalar[0]): switch (true) { case 0 === strpos($scalar, '!str'): return (string) substr($scalar, 5); diff --git a/src/Symfony/Component/Yaml/Parser.php b/src/Symfony/Component/Yaml/Parser.php index 90a2f34e02123..fb3e205d29a52 100644 --- a/src/Symfony/Component/Yaml/Parser.php +++ b/src/Symfony/Component/Yaml/Parser.php @@ -200,7 +200,7 @@ private function doParse($value, $exceptionOnInvalidType = false, $objectSupport $data += $refValue; // array union } else { - if (isset($values['value']) && $values['value'] !== '') { + if (isset($values['value']) && '' !== $values['value']) { $value = $values['value']; } else { $value = $this->getNextEmbedBlock(); @@ -406,7 +406,7 @@ private function getNextEmbedBlock($indentation = null, $inSequence = false) $indent = $this->getCurrentLineIndentation(); // terminate all block scalars that are more indented than the current line - if (!empty($blockScalarIndentations) && $indent < $previousLineIndentation && trim($this->currentLine) !== '') { + if (!empty($blockScalarIndentations) && $indent < $previousLineIndentation && '' !== trim($this->currentLine)) { foreach ($blockScalarIndentations as $key => $blockScalarIndentation) { if ($blockScalarIndentation >= $this->getCurrentLineIndentation()) { unset($blockScalarIndentations[$key]); @@ -699,7 +699,7 @@ private function isCurrentLineComment() //checking explicitly the first char of the trim is faster than loops or strpos $ltrimmedLine = ltrim($this->currentLine, ' '); - return '' !== $ltrimmedLine && $ltrimmedLine[0] === '#'; + return '' !== $ltrimmedLine && '#' === $ltrimmedLine[0]; } private function isCurrentLineLastLineInDocument() @@ -725,7 +725,7 @@ private function cleanup($value) // remove leading comments $trimmedValue = preg_replace('#^(\#.*?\n)+#s', '', $value, -1, $count); - if ($count == 1) { + if (1 == $count) { // items have been removed, update the offset $this->offset += substr_count($value, "\n") - substr_count($trimmedValue, "\n"); $value = $trimmedValue; @@ -733,7 +733,7 @@ private function cleanup($value) // remove start of the document marker (---) $trimmedValue = preg_replace('#^\-\-\-.*?\n#s', '', $value, -1, $count); - if ($count == 1) { + if (1 == $count) { // items have been removed, update the offset $this->offset += substr_count($value, "\n") - substr_count($trimmedValue, "\n"); $value = $trimmedValue; diff --git a/src/Symfony/Component/Yaml/Yaml.php b/src/Symfony/Component/Yaml/Yaml.php index 6fc4e9273d50b..62901ec075d32 100644 --- a/src/Symfony/Component/Yaml/Yaml.php +++ b/src/Symfony/Component/Yaml/Yaml.php @@ -48,7 +48,7 @@ public static function parse($input, $exceptionOnInvalidType = false, $objectSup { // if input is a file, process it $file = ''; - if (strpos($input, "\n") === false && is_file($input)) { + if (false === strpos($input, "\n") && is_file($input)) { @trigger_error('The ability to pass file names to the '.__METHOD__.' method is deprecated since version 2.2 and will be removed in 3.0. Pass the YAML contents of the file instead.', E_USER_DEPRECATED); if (false === is_readable($input)) { From 4e9d1600eec7ee368df9b61cab69b672b1d27751 Mon Sep 17 00:00:00 2001 From: Dariusz Date: Fri, 15 Sep 2017 12:36:22 +0200 Subject: [PATCH 0835/1099] CS: recover no_break_comment --- .php_cs.dist | 1 - src/Symfony/Component/Form/Util/ServerParams.php | 3 +++ src/Symfony/Component/HttpFoundation/File/UploadedFile.php | 3 +++ .../Component/HttpKernel/DataCollector/MemoryDataCollector.php | 3 +++ src/Symfony/Component/VarDumper/Cloner/Data.php | 2 +- src/Symfony/Component/VarDumper/Dumper/CliDumper.php | 3 ++- src/Symfony/Component/Yaml/Inline.php | 1 + 7 files changed, 13 insertions(+), 3 deletions(-) diff --git a/.php_cs.dist b/.php_cs.dist index 624618ab80a43..f1a3691142b6d 100644 --- a/.php_cs.dist +++ b/.php_cs.dist @@ -9,7 +9,6 @@ return PhpCsFixer\Config::create() '@Symfony' => true, '@Symfony:risky' => true, 'array_syntax' => array('syntax' => 'long'), - 'no_break_comment' => false, 'protected_to_private' => false, )) ->setRiskyAllowed(true) diff --git a/src/Symfony/Component/Form/Util/ServerParams.php b/src/Symfony/Component/Form/Util/ServerParams.php index b9f5aaff557d6..fc5e9dd27ad34 100644 --- a/src/Symfony/Component/Form/Util/ServerParams.php +++ b/src/Symfony/Component/Form/Util/ServerParams.php @@ -62,8 +62,11 @@ public function getPostMaxSize() switch (substr($iniMax, -1)) { case 't': $max *= 1024; + // no break case 'g': $max *= 1024; + // no break case 'm': $max *= 1024; + // no break case 'k': $max *= 1024; } diff --git a/src/Symfony/Component/HttpFoundation/File/UploadedFile.php b/src/Symfony/Component/HttpFoundation/File/UploadedFile.php index d32ec176cc116..9a2d28491a1fd 100644 --- a/src/Symfony/Component/HttpFoundation/File/UploadedFile.php +++ b/src/Symfony/Component/HttpFoundation/File/UploadedFile.php @@ -259,8 +259,11 @@ public static function getMaxFilesize() switch (substr($iniMax, -1)) { case 't': $max *= 1024; + // no break case 'g': $max *= 1024; + // no break case 'm': $max *= 1024; + // no break case 'k': $max *= 1024; } diff --git a/src/Symfony/Component/HttpKernel/DataCollector/MemoryDataCollector.php b/src/Symfony/Component/HttpKernel/DataCollector/MemoryDataCollector.php index 93850108444a0..b7f61f46fd19b 100644 --- a/src/Symfony/Component/HttpKernel/DataCollector/MemoryDataCollector.php +++ b/src/Symfony/Component/HttpKernel/DataCollector/MemoryDataCollector.php @@ -99,8 +99,11 @@ private function convertToBytes($memoryLimit) switch (substr($memoryLimit, -1)) { case 't': $max *= 1024; + // no break case 'g': $max *= 1024; + // no break case 'm': $max *= 1024; + // no break case 'k': $max *= 1024; } diff --git a/src/Symfony/Component/VarDumper/Cloner/Data.php b/src/Symfony/Component/VarDumper/Cloner/Data.php index cf21f0e4bcc43..9244a567e3178 100644 --- a/src/Symfony/Component/VarDumper/Cloner/Data.php +++ b/src/Symfony/Component/VarDumper/Cloner/Data.php @@ -179,7 +179,7 @@ private function dumpItem($dumper, $cursor, &$refs, $item) $item = clone $item; $item->type = $item->class; $item->class = $item->value; - // No break; + // no break case Stub::TYPE_OBJECT: case Stub::TYPE_RESOURCE: $withChildren = $children && $cursor->depth !== $this->maxDepth && $this->maxItemsPerDepth; diff --git a/src/Symfony/Component/VarDumper/Dumper/CliDumper.php b/src/Symfony/Component/VarDumper/Dumper/CliDumper.php index 822736abd5561..107a2a438d35e 100644 --- a/src/Symfony/Component/VarDumper/Dumper/CliDumper.php +++ b/src/Symfony/Component/VarDumper/Dumper/CliDumper.php @@ -317,6 +317,7 @@ protected function dumpKey(Cursor $cursor) default: case Cursor::HASH_INDEXED: $style = 'index'; + // no break case Cursor::HASH_ASSOC: if (is_int($key)) { $this->line .= $this->style($style, $key).' => '; @@ -327,7 +328,7 @@ protected function dumpKey(Cursor $cursor) case Cursor::HASH_RESOURCE: $key = "\0~\0".$key; - // No break; + // no break case Cursor::HASH_OBJECT: if (!isset($key[0]) || "\0" !== $key[0]) { $this->line .= '+'.$bin.$this->style('public', $key).': '; diff --git a/src/Symfony/Component/Yaml/Inline.php b/src/Symfony/Component/Yaml/Inline.php index 6d5ac1cd807f2..1dd9761e970e6 100644 --- a/src/Symfony/Component/Yaml/Inline.php +++ b/src/Symfony/Component/Yaml/Inline.php @@ -537,6 +537,7 @@ private static function evaluateScalar($scalar, $references = array()) return $time; } + // no break default: return (string) $scalar; } From cdb53266b3b6349c807146c2dcd00cb57cb1588c Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Fri, 15 Sep 2017 12:58:39 +0200 Subject: [PATCH 0836/1099] fix merge --- .../Component/Debug/Tests/Exception/FlattenExceptionTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/Debug/Tests/Exception/FlattenExceptionTest.php b/src/Symfony/Component/Debug/Tests/Exception/FlattenExceptionTest.php index fadefd49d565e..e7762bdec8edd 100644 --- a/src/Symfony/Component/Debug/Tests/Exception/FlattenExceptionTest.php +++ b/src/Symfony/Component/Debug/Tests/Exception/FlattenExceptionTest.php @@ -256,7 +256,7 @@ function () {}, // assertEquals() does not like NAN values. $this->assertEquals($array[$i][0], 'float'); - $this->assertNan($array[$i++][1]); + $this->assertTrue(is_nan($array[$i++][1])); } public function testRecursionInArguments() From 4dd2e3e83762c5a4f055251f36069070924e4d6c Mon Sep 17 00:00:00 2001 From: Robin Chalas Date: Thu, 14 Sep 2017 14:40:52 +0200 Subject: [PATCH 0837/1099] Preserve URI fragment in HttpUtils::generateUri() --- src/Symfony/Component/Security/Http/HttpUtils.php | 7 ++++++- .../Component/Security/Http/Tests/HttpUtilsTest.php | 9 +++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/Security/Http/HttpUtils.php b/src/Symfony/Component/Security/Http/HttpUtils.php index 56add79926d3e..01f56b356adaf 100644 --- a/src/Symfony/Component/Security/Http/HttpUtils.php +++ b/src/Symfony/Component/Security/Http/HttpUtils.php @@ -41,7 +41,7 @@ class HttpUtils public function __construct(UrlGeneratorInterface $urlGenerator = null, $urlMatcher = null) { $this->urlGenerator = $urlGenerator; - if ($urlMatcher !== null && !$urlMatcher instanceof UrlMatcherInterface && !$urlMatcher instanceof RequestMatcherInterface) { + if (null !== $urlMatcher && !$urlMatcher instanceof UrlMatcherInterface && !$urlMatcher instanceof RequestMatcherInterface) { throw new \InvalidArgumentException('Matcher must either implement UrlMatcherInterface or RequestMatcherInterface.'); } $this->urlMatcher = $urlMatcher; @@ -150,7 +150,12 @@ public function generateUri($request, $path) // fortunately, they all are, so we have to remove entire query string $position = strpos($url, '?'); if (false !== $position) { + $fragment = parse_url($url, PHP_URL_FRAGMENT); $url = substr($url, 0, $position); + // fragment must be preserved + if ($fragment) { + $url .= "#$fragment"; + } } return $url; diff --git a/src/Symfony/Component/Security/Http/Tests/HttpUtilsTest.php b/src/Symfony/Component/Security/Http/Tests/HttpUtilsTest.php index b508012665e87..457588c180529 100644 --- a/src/Symfony/Component/Security/Http/Tests/HttpUtilsTest.php +++ b/src/Symfony/Component/Security/Http/Tests/HttpUtilsTest.php @@ -252,6 +252,15 @@ public function testGenerateUriRemovesQueryString() $this->assertEquals('/foo/bar', $utils->generateUri(new Request(), 'route_name')); } + public function testGenerateUriPreservesFragment() + { + $utils = new HttpUtils($this->getUrlGenerator('/foo/bar?param=value#fragment')); + $this->assertEquals('/foo/bar#fragment', $utils->generateUri(new Request(), 'route_name')); + + $utils = new HttpUtils($this->getUrlGenerator('/foo/bar#fragment')); + $this->assertEquals('/foo/bar#fragment', $utils->generateUri(new Request(), 'route_name')); + } + /** * @expectedException \LogicException * @expectedExceptionMessage You must provide a UrlGeneratorInterface instance to be able to use routes. From 6185cb19913984c336f7aee389842bed958af73f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Parmentier?= Date: Tue, 1 Aug 2017 17:22:43 +0200 Subject: [PATCH 0838/1099] [Serializer][FrameworkBundle] Add a DateInterval normalizer --- .../FrameworkExtension.php | 8 + .../FrameworkExtensionTest.php | 16 ++ src/Symfony/Component/Serializer/CHANGELOG.md | 1 + .../Normalizer/DateIntervalNormalizer.php | 106 ++++++++++++++ .../Normalizer/DateIntervalNormalizerTest.php | 137 ++++++++++++++++++ 5 files changed, 268 insertions(+) create mode 100644 src/Symfony/Component/Serializer/Normalizer/DateIntervalNormalizer.php create mode 100644 src/Symfony/Component/Serializer/Tests/Normalizer/DateIntervalNormalizerTest.php diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php index ea6dec7fd6bd1..937fdc5dcb43c 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php @@ -67,6 +67,7 @@ use Symfony\Component\Serializer\Encoder\YamlEncoder; use Symfony\Component\Serializer\Mapping\Factory\CacheClassMetadataFactory; use Symfony\Component\Serializer\Normalizer\DataUriNormalizer; +use Symfony\Component\Serializer\Normalizer\DateIntervalNormalizer; use Symfony\Component\Serializer\Normalizer\DateTimeNormalizer; use Symfony\Component\Serializer\Normalizer\DenormalizerInterface; use Symfony\Component\Serializer\Normalizer\JsonSerializableNormalizer; @@ -1522,6 +1523,13 @@ private function registerSerializerConfiguration(array $config, ContainerBuilder $definition->addTag('serializer.normalizer', array('priority' => -920)); } + if (class_exists(DateIntervalNormalizer::class)) { + // Run before serializer.normalizer.object + $definition = $container->register('serializer.normalizer.dateinterval', DateIntervalNormalizer::class); + $definition->setPublic(false); + $definition->addTag('serializer.normalizer', array('priority' => -915)); + } + if (class_exists('Symfony\Component\Serializer\Normalizer\DateTimeNormalizer')) { // Run before serializer.normalizer.object $definition = $container->register('serializer.normalizer.datetime', DateTimeNormalizer::class); diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php index 991eda1ea6ac6..67be87baa8a3b 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php @@ -34,6 +34,7 @@ use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Symfony\Component\PropertyAccess\PropertyAccessor; use Symfony\Component\Serializer\Mapping\Loader\AnnotationLoader; +use Symfony\Component\Serializer\Normalizer\DateIntervalNormalizer; use Symfony\Component\Serializer\Serializer; use Symfony\Component\Serializer\Mapping\Factory\CacheClassMetadataFactory; use Symfony\Component\Serializer\Mapping\Loader\XmlFileLoader; @@ -776,6 +777,21 @@ public function testDataUriNormalizerRegistered() $this->assertEquals(-920, $tag[0]['priority']); } + public function testDateIntervalNormalizerRegistered() + { + if (!class_exists(DateIntervalNormalizer::class)) { + $this->markTestSkipped('The DateIntervalNormalizer has been introduced in the Serializer Component version 3.4.'); + } + + $container = $this->createContainerFromFile('full'); + + $definition = $container->getDefinition('serializer.normalizer.dateinterval'); + $tag = $definition->getTag('serializer.normalizer'); + + $this->assertEquals(DateIntervalNormalizer::class, $definition->getClass()); + $this->assertEquals(-915, $tag[0]['priority']); + } + public function testDateTimeNormalizerRegistered() { if (!class_exists('Symfony\Component\Serializer\Normalizer\DateTimeNormalizer')) { diff --git a/src/Symfony/Component/Serializer/CHANGELOG.md b/src/Symfony/Component/Serializer/CHANGELOG.md index 2e10bd469bab4..ef59f22499264 100644 --- a/src/Symfony/Component/Serializer/CHANGELOG.md +++ b/src/Symfony/Component/Serializer/CHANGELOG.md @@ -6,6 +6,7 @@ CHANGELOG * added `AbstractObjectNormalizer::DISABLE_TYPE_ENFORCEMENT` context option to disable throwing an `UnexpectedValueException` on a type mismatch + * added support for serializing `DateInterval` objects 3.3.0 ----- diff --git a/src/Symfony/Component/Serializer/Normalizer/DateIntervalNormalizer.php b/src/Symfony/Component/Serializer/Normalizer/DateIntervalNormalizer.php new file mode 100644 index 0000000000000..3628cd670b499 --- /dev/null +++ b/src/Symfony/Component/Serializer/Normalizer/DateIntervalNormalizer.php @@ -0,0 +1,106 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Serializer\Normalizer; + +use Symfony\Component\Serializer\Exception\InvalidArgumentException; +use Symfony\Component\Serializer\Exception\UnexpectedValueException; + +/** + * Normalizes an instance of {@see \DateInterval} to an interval string. + * Denormalizes an interval string to an instance of {@see \DateInterval}. + * + * @author Jérôme Parmentier + */ +class DateIntervalNormalizer implements NormalizerInterface, DenormalizerInterface +{ + const FORMAT_KEY = 'dateinterval_format'; + + /** + * @var string + */ + private $format; + + /** + * @param string $format + */ + public function __construct($format = 'P%yY%mM%dDT%hH%iM%sS') + { + $this->format = $format; + } + + /** + * {@inheritdoc} + * + * @throws InvalidArgumentException + */ + public function normalize($object, $format = null, array $context = array()) + { + if (!$object instanceof \DateInterval) { + throw new InvalidArgumentException('The object must be an instance of "\DateInterval".'); + } + + $dateIntervalFormat = isset($context[self::FORMAT_KEY]) ? $context[self::FORMAT_KEY] : $this->format; + + return $object->format($dateIntervalFormat); + } + + /** + * {@inheritdoc} + */ + public function supportsNormalization($data, $format = null) + { + return $data instanceof \DateInterval; + } + + /** + * {@inheritdoc} + * + * @throws InvalidArgumentException + * @throws UnexpectedValueException + */ + public function denormalize($data, $class, $format = null, array $context = array()) + { + if (!is_string($data)) { + throw new InvalidArgumentException(sprintf('Data expected to be a string, %s given.', gettype($data))); + } + + if (!$this->isISO8601($data)) { + throw new UnexpectedValueException('Expected a valid ISO 8601 interval string.'); + } + + $dateIntervalFormat = isset($context[self::FORMAT_KEY]) ? $context[self::FORMAT_KEY] : $this->format; + + $valuePattern = '/^'.preg_replace('/%([yYmMdDhHiIsSwW])(\w)/', '(?P<$1>\d+)$2', $dateIntervalFormat).'$/'; + if (!preg_match($valuePattern, $data)) { + throw new UnexpectedValueException(sprintf('Value "%s" contains intervals not accepted by format "%s".', $data, $dateIntervalFormat)); + } + + try { + return new \DateInterval($data); + } catch (\Exception $e) { + throw new UnexpectedValueException($e->getMessage(), $e->getCode(), $e); + } + } + + /** + * {@inheritdoc} + */ + public function supportsDenormalization($data, $type, $format = null) + { + return \DateInterval::class === $type; + } + + private function isISO8601($string) + { + return preg_match('/^P(?=\w*(?:\d|%\w))(?:\d+Y|%[yY]Y)?(?:\d+M|%[mM]M)?(?:(?:\d+D|%[dD]D)|(?:\d+W|%[wW]W))?(?:T(?:\d+H|[hH]H)?(?:\d+M|[iI]M)?(?:\d+S|[sS]S)?)?$/', $string); + } +} diff --git a/src/Symfony/Component/Serializer/Tests/Normalizer/DateIntervalNormalizerTest.php b/src/Symfony/Component/Serializer/Tests/Normalizer/DateIntervalNormalizerTest.php new file mode 100644 index 0000000000000..f6dc6c2475e53 --- /dev/null +++ b/src/Symfony/Component/Serializer/Tests/Normalizer/DateIntervalNormalizerTest.php @@ -0,0 +1,137 @@ + + */ +class DateIntervalNormalizerTest extends TestCase +{ + /** + * @var DateIntervalNormalizer + */ + private $normalizer; + + protected function setUp() + { + $this->normalizer = new DateIntervalNormalizer(); + } + + public function dataProviderISO() + { + $data = array( + array('P%YY%MM%DDT%HH%IM%SS', 'P00Y00M00DT00H00M00S', 'PT0S'), + array('P%yY%mM%dDT%hH%iM%sS', 'P0Y0M0DT0H0M0S', 'PT0S'), + array('P%yY%mM%dDT%hH%iM%sS', 'P10Y2M3DT16H5M6S', 'P10Y2M3DT16H5M6S'), + array('P%yY%mM%dDT%hH%iM', 'P10Y2M3DT16H5M', 'P10Y2M3DT16H5M'), + array('P%yY%mM%dDT%hH', 'P10Y2M3DT16H', 'P10Y2M3DT16H'), + array('P%yY%mM%dD', 'P10Y2M3D', 'P10Y2M3DT0H'), + ); + + return $data; + } + + public function testSupportsNormalization() + { + $this->assertTrue($this->normalizer->supportsNormalization(new \DateInterval('P00Y00M00DT00H00M00S'))); + $this->assertFalse($this->normalizer->supportsNormalization(new \stdClass())); + } + + public function testNormalize() + { + $this->assertEquals('P0Y0M0DT0H0M0S', $this->normalizer->normalize(new \DateInterval('PT0S'))); + } + + /** + * @dataProvider dataProviderISO + */ + public function testNormalizeUsingFormatPassedInContext($format, $output, $input) + { + $this->assertEquals($output, $this->normalizer->normalize(new \DateInterval($input), null, array(DateIntervalNormalizer::FORMAT_KEY => $format))); + } + + /** + * @dataProvider dataProviderISO + */ + public function testNormalizeUsingFormatPassedInConstructor($format, $output, $input) + { + $this->assertEquals($output, (new DateIntervalNormalizer($format))->normalize(new \DateInterval($input))); + } + + /** + * @expectedException \Symfony\Component\Serializer\Exception\InvalidArgumentException + * @expectedExceptionMessage The object must be an instance of "\DateInterval". + */ + public function testNormalizeInvalidObjectThrowsException() + { + $this->normalizer->normalize(new \stdClass()); + } + + public function testSupportsDenormalization() + { + $this->assertTrue($this->normalizer->supportsDenormalization('P00Y00M00DT00H00M00S', \DateInterval::class)); + $this->assertFalse($this->normalizer->supportsDenormalization('foo', 'Bar')); + } + + public function testDenormalize() + { + $this->assertDateIntervalEquals(new \DateInterval('P00Y00M00DT00H00M00S'), $this->normalizer->denormalize('P00Y00M00DT00H00M00S', \DateInterval::class)); + } + + /** + * @dataProvider dataProviderISO + */ + public function testDenormalizeUsingFormatPassedInContext($format, $input, $output) + { + $this->assertDateIntervalEquals(new \DateInterval($output), $this->normalizer->denormalize($input, \DateInterval::class, null, array(DateIntervalNormalizer::FORMAT_KEY => $format))); + } + + /** + * @dataProvider dataProviderISO + */ + public function testDenormalizeUsingFormatPassedInConstructor($format, $input, $output) + { + $this->assertDateIntervalEquals(new \DateInterval($output), (new DateIntervalNormalizer($format))->denormalize($input, \DateInterval::class)); + } + + /** + * @expectedException \Symfony\Component\Serializer\Exception\InvalidArgumentException + */ + public function testDenormalizeExpectsString() + { + $this->normalizer->denormalize(1234, \DateInterval::class); + } + + /** + * @expectedException \Symfony\Component\Serializer\Exception\UnexpectedValueException + * @expectedExceptionMessage Expected a valid ISO 8601 interval string. + */ + public function testDenormalizeNonISO8601IntervalStringThrowsException() + { + $this->normalizer->denormalize('10 years 2 months 3 days', \DateInterval::class, null); + } + + /** + * @expectedException \Symfony\Component\Serializer\Exception\UnexpectedValueException + */ + public function testDenormalizeInvalidDataThrowsException() + { + $this->normalizer->denormalize('invalid interval', \DateInterval::class); + } + + /** + * @expectedException \Symfony\Component\Serializer\Exception\UnexpectedValueException + */ + public function testDenormalizeFormatMismatchThrowsException() + { + $this->normalizer->denormalize('P00Y00M00DT00H00M00S', \DateInterval::class, null, array(DateIntervalNormalizer::FORMAT_KEY => 'P%yY%mM%dD')); + } + + private function assertDateIntervalEquals(\DateInterval $expected, \DateInterval $actual) + { + $this->assertEquals($expected->format('%RP%yY%mM%dDT%hH%iM%sS'), $actual->format('%RP%yY%mM%dDT%hH%iM%sS')); + } +} From 12d1a7f81064c3669368e3b2453be28769c2085f Mon Sep 17 00:00:00 2001 From: Yonel Ceruto Date: Wed, 13 Sep 2017 08:23:26 -0400 Subject: [PATCH 0839/1099] Display form defaults on debug:form --- .../Resources/config/console.xml | 3 ++ src/Symfony/Component/Form/CHANGELOG.md | 5 +++ .../Component/Form/Command/DebugCommand.php | 40 ++++++++++++----- .../Form/Console/Descriptor/Descriptor.php | 29 ++++++++++-- .../Console/Descriptor/JsonDescriptor.php | 10 +++++ .../Console/Descriptor/TextDescriptor.php | 20 +++++++++ .../Form/DependencyInjection/FormPass.php | 17 +++++++ .../Form/Tests/Command/DebugCommandTest.php | 9 ++++ .../Descriptor/AbstractDescriptorTest.php | 22 +++++++++ .../Tests/Fixtures/Descriptor/defaults_1.json | 45 +++++++++++++++++++ .../Tests/Fixtures/Descriptor/defaults_1.txt | 27 +++++++++++ 11 files changed, 213 insertions(+), 14 deletions(-) create mode 100644 src/Symfony/Component/Form/Tests/Fixtures/Descriptor/defaults_1.json create mode 100644 src/Symfony/Component/Form/Tests/Fixtures/Descriptor/defaults_1.txt diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/console.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/console.xml index 80bc32d3ff221..7dc4ea6d2fbae 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/console.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/console.xml @@ -100,6 +100,9 @@ + + + diff --git a/src/Symfony/Component/Form/CHANGELOG.md b/src/Symfony/Component/Form/CHANGELOG.md index 1c8936995c226..8af1a324dca95 100644 --- a/src/Symfony/Component/Form/CHANGELOG.md +++ b/src/Symfony/Component/Form/CHANGELOG.md @@ -1,6 +1,11 @@ CHANGELOG ========= +3.4.0 +----- + + * added `DebugCommand` + 3.3.0 ----- diff --git a/src/Symfony/Component/Form/Command/DebugCommand.php b/src/Symfony/Component/Form/Command/DebugCommand.php index d646ffa154305..d9b3eee838244 100644 --- a/src/Symfony/Component/Form/Command/DebugCommand.php +++ b/src/Symfony/Component/Form/Command/DebugCommand.php @@ -12,6 +12,7 @@ namespace Symfony\Component\Form\Command; use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Exception\InvalidArgumentException; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; @@ -31,13 +32,19 @@ class DebugCommand extends Command private $formRegistry; private $namespaces; + private $types; + private $extensions; + private $guessers; - public function __construct(FormRegistryInterface $formRegistry, array $namespaces = array('Symfony\Component\Form\Extension\Core\Type')) + public function __construct(FormRegistryInterface $formRegistry, array $namespaces = array('Symfony\Component\Form\Extension\Core\Type'), array $types = array(), array $extensions = array(), array $guessers = array()) { parent::__construct(); $this->formRegistry = $formRegistry; $this->namespaces = $namespaces; + $this->types = $types; + $this->extensions = $extensions; + $this->guessers = $guessers; } /** @@ -47,18 +54,25 @@ protected function configure() { $this ->setDefinition(array( - new InputArgument('class', InputArgument::REQUIRED, 'The form type class'), + new InputArgument('class', InputArgument::OPTIONAL, 'The form type class'), new InputOption('format', null, InputOption::VALUE_REQUIRED, 'The output format (txt or json)', 'txt'), )) ->setDescription('Displays form type information') ->setHelp(<<<'EOF' -The %command.name% command displays information about a form type. +The %command.name% command displays information about form types. -Either the fully-qualified class name or the short class name can be used: + php %command.full_name% + +The command lists all built-in types, services types, type extensions and guessers currently available. php %command.full_name% Symfony\Component\Form\Extension\Core\Type\ChoiceType php %command.full_name% ChoiceType +The command lists all defined options that contains the given form type, as well as their parents and type extensions. + + php %command.full_name% --format=json + +The command lists everything in a machine readable json format. EOF ) ; @@ -71,12 +85,18 @@ protected function execute(InputInterface $input, OutputInterface $output) { $io = new SymfonyStyle($input, $output); - if (!class_exists($class = $input->getArgument('class'))) { - $class = $this->getFqcnTypeClass($input, $io, $class); + if (null === $class = $input->getArgument('class')) { + $object = null; + $options['types'] = $this->types; + $options['extensions'] = $this->extensions; + $options['guessers'] = $this->guessers; + } else { + if (!class_exists($class)) { + $class = $this->getFqcnTypeClass($input, $io, $class); + } + $object = $this->formRegistry->getType($class); } - $object = $this->formRegistry->getType($class); - $helper = new DescriptorHelper(); $options['format'] = $input->getOption('format'); $helper->describe($io, $object, $options); @@ -92,13 +112,13 @@ private function getFqcnTypeClass(InputInterface $input, SymfonyStyle $io, $shor } if (0 === $count = count($classes)) { - throw new \InvalidArgumentException(sprintf("Could not find type \"%s\" into the following namespaces:\n %s", $shortClassName, implode("\n ", $this->namespaces))); + throw new InvalidArgumentException(sprintf("Could not find type \"%s\" into the following namespaces:\n %s", $shortClassName, implode("\n ", $this->namespaces))); } if (1 === $count) { return $classes[0]; } if (!$input->isInteractive()) { - throw new \InvalidArgumentException(sprintf("The type \"%s\" is ambiguous.\nDid you mean one of these?\n %s", $shortClassName, implode("\n ", $classes))); + throw new InvalidArgumentException(sprintf("The type \"%s\" is ambiguous.\nDid you mean one of these?\n %s", $shortClassName, implode("\n ", $classes))); } return $io->choice(sprintf("The type \"%s\" is ambiguous.\n\n Select one of the following form types to display its information:", $shortClassName), $classes, $classes[0]); diff --git a/src/Symfony/Component/Form/Console/Descriptor/Descriptor.php b/src/Symfony/Component/Form/Console/Descriptor/Descriptor.php index af77f19931244..c72a19d7993f1 100644 --- a/src/Symfony/Component/Form/Console/Descriptor/Descriptor.php +++ b/src/Symfony/Component/Form/Console/Descriptor/Descriptor.php @@ -12,8 +12,12 @@ namespace Symfony\Component\Form\Console\Descriptor; use Symfony\Component\Console\Descriptor\DescriptorInterface; +use Symfony\Component\Console\Input\ArrayInput; use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Style\StyleInterface; use Symfony\Component\Console\Style\SymfonyStyle; +use Symfony\Component\Form\Extension\Core\CoreExtension; +use Symfony\Component\Form\FormTypeInterface; use Symfony\Component\Form\ResolvedFormTypeInterface; use Symfony\Component\Form\Util\OptionsResolverWrapper; use Symfony\Component\OptionsResolver\OptionsResolver; @@ -25,9 +29,7 @@ */ abstract class Descriptor implements DescriptorInterface { - /** - * @var SymfonyStyle - */ + /** @var StyleInterface */ protected $output; protected $type; protected $ownOptions = array(); @@ -43,9 +45,12 @@ abstract class Descriptor implements DescriptorInterface */ public function describe(OutputInterface $output, $object, array $options = array()) { - $this->output = $output; + $this->output = $output instanceof StyleInterface ? $output : new SymfonyStyle(new ArrayInput(array()), $output); switch (true) { + case null === $object: + $this->describeDefaults($options); + break; case $object instanceof ResolvedFormTypeInterface: $this->describeResolvedFormType($object, $options); break; @@ -54,8 +59,24 @@ public function describe(OutputInterface $output, $object, array $options = arra } } + abstract protected function describeDefaults(array $options = array()); + abstract protected function describeResolvedFormType(ResolvedFormTypeInterface $resolvedFormType, array $options = array()); + protected function getCoreTypes() + { + $coreExtension = new CoreExtension(); + $coreExtensionRefObject = new \ReflectionObject($coreExtension); + $loadTypesRefMethod = $coreExtensionRefObject->getMethod('loadTypes'); + $loadTypesRefMethod->setAccessible(true); + $coreTypes = $loadTypesRefMethod->invoke($coreExtension); + + $coreTypes = array_map(function (FormTypeInterface $type) { return get_class($type); }, $coreTypes); + sort($coreTypes); + + return $coreTypes; + } + protected function collectOptions(ResolvedFormTypeInterface $type) { $this->parents = array(); diff --git a/src/Symfony/Component/Form/Console/Descriptor/JsonDescriptor.php b/src/Symfony/Component/Form/Console/Descriptor/JsonDescriptor.php index 638ea7a5ff71e..7616d616f1441 100644 --- a/src/Symfony/Component/Form/Console/Descriptor/JsonDescriptor.php +++ b/src/Symfony/Component/Form/Console/Descriptor/JsonDescriptor.php @@ -20,6 +20,16 @@ */ class JsonDescriptor extends Descriptor { + protected function describeDefaults(array $options = array()) + { + $data['builtin_form_types'] = $this->getCoreTypes(); + $data['service_form_types'] = array_values(array_diff($options['types'], $data['builtin_form_types'])); + $data['type_extensions'] = $options['extensions']; + $data['type_guessers'] = $options['guessers']; + + $this->writeData($data, $options); + } + protected function describeResolvedFormType(ResolvedFormTypeInterface $resolvedFormType, array $options = array()) { $this->collectOptions($resolvedFormType); diff --git a/src/Symfony/Component/Form/Console/Descriptor/TextDescriptor.php b/src/Symfony/Component/Form/Console/Descriptor/TextDescriptor.php index b12a22bb9e26a..d5072f1e9a632 100644 --- a/src/Symfony/Component/Form/Console/Descriptor/TextDescriptor.php +++ b/src/Symfony/Component/Form/Console/Descriptor/TextDescriptor.php @@ -21,6 +21,26 @@ */ class TextDescriptor extends Descriptor { + protected function describeDefaults(array $options = array()) + { + $coreTypes = $this->getCoreTypes(); + + $this->output->section('Built-in form types (Symfony\Component\Form\Extension\Core\Type)'); + $shortClassNames = array_map(function ($fqcn) { return array_slice(explode('\\', $fqcn), -1)[0]; }, $coreTypes); + for ($i = 0; $i * 5 < count($shortClassNames); ++$i) { + $this->output->writeln(' '.implode(', ', array_slice($shortClassNames, $i * 5, 5))); + } + + $this->output->section('Service form types'); + $this->output->listing(array_diff($options['types'], $coreTypes)); + + $this->output->section('Type extensions'); + $this->output->listing($options['extensions']); + + $this->output->section('Type guessers'); + $this->output->listing($options['guessers']); + } + protected function describeResolvedFormType(ResolvedFormTypeInterface $resolvedFormType, array $options = array()) { $this->collectOptions($resolvedFormType); diff --git a/src/Symfony/Component/Form/DependencyInjection/FormPass.php b/src/Symfony/Component/Form/DependencyInjection/FormPass.php index ff1ac8af60658..bed74532d1571 100644 --- a/src/Symfony/Component/Form/DependencyInjection/FormPass.php +++ b/src/Symfony/Component/Form/DependencyInjection/FormPass.php @@ -77,6 +77,7 @@ private function processFormTypes(ContainerBuilder $container) if ($container->hasDefinition($this->formDebugCommandService)) { $commandDefinition = $container->getDefinition($this->formDebugCommandService); $commandDefinition->setArgument(1, array_keys($namespaces)); + $commandDefinition->setArgument(2, array_keys($servicesMap)); } return ServiceLocatorTagPass::register($container, $servicesMap); @@ -85,6 +86,7 @@ private function processFormTypes(ContainerBuilder $container) private function processFormTypeExtensions(ContainerBuilder $container) { $typeExtensions = array(); + $typeExtensionsClasses = array(); foreach ($this->findAndSortTaggedServices($this->formTypeExtensionTag, $container) as $reference) { $serviceId = (string) $reference; $serviceDefinition = $container->getDefinition($serviceId); @@ -97,20 +99,35 @@ private function processFormTypeExtensions(ContainerBuilder $container) } $typeExtensions[$extendedType][] = new Reference($serviceId); + $typeExtensionsClasses[] = $serviceDefinition->getClass(); } foreach ($typeExtensions as $extendedType => $extensions) { $typeExtensions[$extendedType] = new IteratorArgument($extensions); } + if ($container->hasDefinition($this->formDebugCommandService)) { + $commandDefinition = $container->getDefinition($this->formDebugCommandService); + $commandDefinition->setArgument(3, $typeExtensionsClasses); + } + return $typeExtensions; } private function processFormTypeGuessers(ContainerBuilder $container) { $guessers = array(); + $guessersClasses = array(); foreach ($container->findTaggedServiceIds($this->formTypeGuesserTag, true) as $serviceId => $tags) { $guessers[] = new Reference($serviceId); + + $serviceDefinition = $container->getDefinition($serviceId); + $guessersClasses[] = $serviceDefinition->getClass(); + } + + if ($container->hasDefinition($this->formDebugCommandService)) { + $commandDefinition = $container->getDefinition($this->formDebugCommandService); + $commandDefinition->setArgument(4, $guessersClasses); } return new IteratorArgument($guessers); diff --git a/src/Symfony/Component/Form/Tests/Command/DebugCommandTest.php b/src/Symfony/Component/Form/Tests/Command/DebugCommandTest.php index c2083ea12ce4d..610f6197d62cb 100644 --- a/src/Symfony/Component/Form/Tests/Command/DebugCommandTest.php +++ b/src/Symfony/Component/Form/Tests/Command/DebugCommandTest.php @@ -21,6 +21,15 @@ class DebugCommandTest extends TestCase { + public function testDebugDefaults() + { + $tester = $this->createCommandTester(); + $ret = $tester->execute(array(), array('decorated' => false)); + + $this->assertEquals(0, $ret, 'Returns 0 in case of success'); + $this->assertContains('Built-in form types', $tester->getDisplay()); + } + public function testDebugSingleFormType() { $tester = $this->createCommandTester(); diff --git a/src/Symfony/Component/Form/Tests/Console/Descriptor/AbstractDescriptorTest.php b/src/Symfony/Component/Form/Tests/Console/Descriptor/AbstractDescriptorTest.php index c760e5ecf972c..3a5efcefeb684 100644 --- a/src/Symfony/Component/Form/Tests/Console/Descriptor/AbstractDescriptorTest.php +++ b/src/Symfony/Component/Form/Tests/Console/Descriptor/AbstractDescriptorTest.php @@ -24,6 +24,19 @@ abstract class AbstractDescriptorTest extends TestCase { + /** @dataProvider getDescribeDefaultsTestData */ + public function testDescribeDefaults($object, array $options, $fixtureName) + { + $expectedDescription = $this->getExpectedDescription($fixtureName); + $describedObject = $this->getObjectDescription($object, $options); + + if ('json' === $this->getFormat()) { + $this->assertEquals(json_encode(json_decode($expectedDescription), JSON_PRETTY_PRINT), json_encode(json_decode($describedObject), JSON_PRETTY_PRINT)); + } else { + $this->assertEquals(trim($expectedDescription), trim(str_replace(PHP_EOL, "\n", $describedObject))); + } + } + /** @dataProvider getDescribeResolvedFormTypeTestData */ public function testDescribeResolvedFormType(ResolvedFormTypeInterface $type, array $options, $fixtureName) { @@ -37,6 +50,15 @@ public function testDescribeResolvedFormType(ResolvedFormTypeInterface $type, ar } } + public function getDescribeDefaultsTestData() + { + $options['types'] = array('Symfony\Bridge\Doctrine\Form\Type\EntityType'); + $options['extensions'] = array('Symfony\Component\Form\Extension\Csrf\Type\FormTypeCsrfExtension'); + $options['guessers'] = array('Symfony\Component\Form\Extension\Validator\ValidatorTypeGuesser'); + + yield array(null, $options, 'defaults_1'); + } + public function getDescribeResolvedFormTypeTestData() { $typeExtensions = array( diff --git a/src/Symfony/Component/Form/Tests/Fixtures/Descriptor/defaults_1.json b/src/Symfony/Component/Form/Tests/Fixtures/Descriptor/defaults_1.json new file mode 100644 index 0000000000000..565c17601ed1e --- /dev/null +++ b/src/Symfony/Component/Form/Tests/Fixtures/Descriptor/defaults_1.json @@ -0,0 +1,45 @@ +{ + "builtin_form_types": [ + "Symfony\\Component\\Form\\Extension\\Core\\Type\\BirthdayType", + "Symfony\\Component\\Form\\Extension\\Core\\Type\\ButtonType", + "Symfony\\Component\\Form\\Extension\\Core\\Type\\CheckboxType", + "Symfony\\Component\\Form\\Extension\\Core\\Type\\ChoiceType", + "Symfony\\Component\\Form\\Extension\\Core\\Type\\CollectionType", + "Symfony\\Component\\Form\\Extension\\Core\\Type\\CountryType", + "Symfony\\Component\\Form\\Extension\\Core\\Type\\CurrencyType", + "Symfony\\Component\\Form\\Extension\\Core\\Type\\DateIntervalType", + "Symfony\\Component\\Form\\Extension\\Core\\Type\\DateTimeType", + "Symfony\\Component\\Form\\Extension\\Core\\Type\\DateType", + "Symfony\\Component\\Form\\Extension\\Core\\Type\\EmailType", + "Symfony\\Component\\Form\\Extension\\Core\\Type\\FileType", + "Symfony\\Component\\Form\\Extension\\Core\\Type\\FormType", + "Symfony\\Component\\Form\\Extension\\Core\\Type\\HiddenType", + "Symfony\\Component\\Form\\Extension\\Core\\Type\\IntegerType", + "Symfony\\Component\\Form\\Extension\\Core\\Type\\LanguageType", + "Symfony\\Component\\Form\\Extension\\Core\\Type\\LocaleType", + "Symfony\\Component\\Form\\Extension\\Core\\Type\\MoneyType", + "Symfony\\Component\\Form\\Extension\\Core\\Type\\NumberType", + "Symfony\\Component\\Form\\Extension\\Core\\Type\\PasswordType", + "Symfony\\Component\\Form\\Extension\\Core\\Type\\PercentType", + "Symfony\\Component\\Form\\Extension\\Core\\Type\\RadioType", + "Symfony\\Component\\Form\\Extension\\Core\\Type\\RangeType", + "Symfony\\Component\\Form\\Extension\\Core\\Type\\RepeatedType", + "Symfony\\Component\\Form\\Extension\\Core\\Type\\ResetType", + "Symfony\\Component\\Form\\Extension\\Core\\Type\\SearchType", + "Symfony\\Component\\Form\\Extension\\Core\\Type\\SubmitType", + "Symfony\\Component\\Form\\Extension\\Core\\Type\\TextType", + "Symfony\\Component\\Form\\Extension\\Core\\Type\\TextareaType", + "Symfony\\Component\\Form\\Extension\\Core\\Type\\TimeType", + "Symfony\\Component\\Form\\Extension\\Core\\Type\\TimezoneType", + "Symfony\\Component\\Form\\Extension\\Core\\Type\\UrlType" + ], + "service_form_types": [ + "Symfony\\Bridge\\Doctrine\\Form\\Type\\EntityType" + ], + "type_extensions": [ + "Symfony\\Component\\Form\\Extension\\Csrf\\Type\\FormTypeCsrfExtension" + ], + "type_guessers": [ + "Symfony\\Component\\Form\\Extension\\Validator\\ValidatorTypeGuesser" + ] +} diff --git a/src/Symfony/Component/Form/Tests/Fixtures/Descriptor/defaults_1.txt b/src/Symfony/Component/Form/Tests/Fixtures/Descriptor/defaults_1.txt new file mode 100644 index 0000000000000..dd08d5f7a64c3 --- /dev/null +++ b/src/Symfony/Component/Form/Tests/Fixtures/Descriptor/defaults_1.txt @@ -0,0 +1,27 @@ + +Built-in form types (Symfony\Component\Form\Extension\Core\Type) +---------------------------------------------------------------- + + BirthdayType, ButtonType, CheckboxType, ChoiceType, CollectionType + CountryType, CurrencyType, DateIntervalType, DateTimeType, DateType + EmailType, FileType, FormType, HiddenType, IntegerType + LanguageType, LocaleType, MoneyType, NumberType, PasswordType + PercentType, RadioType, RangeType, RepeatedType, ResetType + SearchType, SubmitType, TextType, TextareaType, TimeType + TimezoneType, UrlType + +Service form types +------------------ + + * Symfony\Bridge\Doctrine\Form\Type\EntityType + +Type extensions +--------------- + + * Symfony\Component\Form\Extension\Csrf\Type\FormTypeCsrfExtension + +Type guessers +------------- + + * Symfony\Component\Form\Extension\Validator\ValidatorTypeGuesser + From 15fd8631128e9d5dfb61c2cbc59e066bb1a98242 Mon Sep 17 00:00:00 2001 From: GDIBass Date: Fri, 15 Sep 2017 09:32:24 -0700 Subject: [PATCH 0840/1099] Updated Test name and exception name to be more accurate --- .../Component/Workflow/EventListener/GuardListener.php | 2 +- .../Workflow/Tests/EventListener/GuardListenerTest.php | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Component/Workflow/EventListener/GuardListener.php b/src/Symfony/Component/Workflow/EventListener/GuardListener.php index 8726e4bddca47..4d1065299de05 100644 --- a/src/Symfony/Component/Workflow/EventListener/GuardListener.php +++ b/src/Symfony/Component/Workflow/EventListener/GuardListener.php @@ -57,7 +57,7 @@ private function getVariables(GuardEvent $event) $token = $this->tokenStorage->getToken(); if (null === $token) { - throw new InvalidTokenConfigurationException(sprintf('There are no token available for workflow %s', $event->getWorkflowName())); + throw new InvalidTokenConfigurationException(sprintf('There are no tokens available for workflow %s.', $event->getWorkflowName())); } if (null !== $this->roleHierarchy) { diff --git a/src/Symfony/Component/Workflow/Tests/EventListener/GuardListenerTest.php b/src/Symfony/Component/Workflow/Tests/EventListener/GuardListenerTest.php index 0e2dbc13bc53d..741dcf0930579 100644 --- a/src/Symfony/Component/Workflow/Tests/EventListener/GuardListenerTest.php +++ b/src/Symfony/Component/Workflow/Tests/EventListener/GuardListenerTest.php @@ -71,9 +71,9 @@ public function testWithSupportedEventAndAccept() /** * @expectedException \Symfony\Component\Workflow\Exception\InvalidTokenConfigurationException - * @expectedExceptionMessage There are no token available for workflow unnamed + * @expectedExceptionMessage There are no tokens available for workflow unnamed. */ - public function testWithNoTokenStorage() + public function testWithNoTokensInTokenStorage() { $event = $this->createEvent(); $this->tokenStorage->setToken(null); From 183307b741d0015abab34323c7feb0c835c07eec Mon Sep 17 00:00:00 2001 From: Roland Franssen Date: Mon, 24 Jul 2017 17:43:04 +0200 Subject: [PATCH 0841/1099] [Form] Add input + regions options to TimezoneType --- UPGRADE-3.4.md | 32 ++++++++ UPGRADE-4.0.md | 29 +++++++ src/Symfony/Component/Form/CHANGELOG.md | 2 + .../DateTimeZoneToStringTransformer.php | 82 +++++++++++++++++++ .../Form/Extension/Core/Type/TimezoneType.php | 49 +++++++++-- .../DateTimeZoneToStringTransformerTest.php | 56 +++++++++++++ .../Extension/Core/Type/TimezoneTypeTest.php | 27 ++++++ 7 files changed, 272 insertions(+), 5 deletions(-) create mode 100644 src/Symfony/Component/Form/Extension/Core/DataTransformer/DateTimeZoneToStringTransformer.php create mode 100644 src/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/DateTimeZoneToStringTransformerTest.php diff --git a/UPGRADE-3.4.md b/UPGRADE-3.4.md index c5def31a9603e..33147c4cc9ad1 100644 --- a/UPGRADE-3.4.md +++ b/UPGRADE-3.4.md @@ -74,6 +74,38 @@ Finder deprecated and will be removed in 4.0 as it used to fix a bug which existed before version 5.5.23/5.6.7. +Form +---- + + * Deprecated `ChoiceLoaderInterface` implementation in `TimezoneType`. Use the "choice_loader" option instead. + + Before: + ```php + class MyTimezoneType extends TimezoneType + { + public function loadChoices() + { + // override the method + } + } + ``` + + After: + ```php + class MyTimezoneType extends AbstractType + { + public function. getParent() + { + return TimezoneType::class; + } + + public function configureOptions(OptionsResolver $resolver) + { + $resolver->setDefault('choice_loader', ...); // override the option instead + } + } + ``` + FrameworkBundle --------------- diff --git a/UPGRADE-4.0.md b/UPGRADE-4.0.md index e5a69675a2fa0..6c32bad70c90b 100644 --- a/UPGRADE-4.0.md +++ b/UPGRADE-4.0.md @@ -282,6 +282,35 @@ Form )); ``` + * Removed `ChoiceLoaderInterface` implementation in `TimezoneType`. Use the "choice_loader" option instead. + + Before: + ```php + class MyTimezoneType extends TimezoneType + { + public function loadChoices() + { + // override the method + } + } + ``` + + After: + ```php + class MyTimezoneType extends AbstractType + { + public function. getParent() + { + return TimezoneType::class; + } + + public function configureOptions(OptionsResolver $resolver) + { + $resolver->setDefault('choice_loader', ...); // override the option instead + } + } + ``` + FrameworkBundle --------------- diff --git a/src/Symfony/Component/Form/CHANGELOG.md b/src/Symfony/Component/Form/CHANGELOG.md index 8af1a324dca95..62c52a897d3f2 100644 --- a/src/Symfony/Component/Form/CHANGELOG.md +++ b/src/Symfony/Component/Form/CHANGELOG.md @@ -5,6 +5,8 @@ CHANGELOG ----- * added `DebugCommand` + * deprecated `ChoiceLoaderInterface` implementation in `TimezoneType` + * added options "input" and "regions" to `TimezoneType` 3.3.0 ----- diff --git a/src/Symfony/Component/Form/Extension/Core/DataTransformer/DateTimeZoneToStringTransformer.php b/src/Symfony/Component/Form/Extension/Core/DataTransformer/DateTimeZoneToStringTransformer.php new file mode 100644 index 0000000000000..7e133c2e9b3b9 --- /dev/null +++ b/src/Symfony/Component/Form/Extension/Core/DataTransformer/DateTimeZoneToStringTransformer.php @@ -0,0 +1,82 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Extension\Core\DataTransformer; + +use Symfony\Component\Form\DataTransformerInterface; +use Symfony\Component\Form\Exception\TransformationFailedException; + +/** + * Transforms between a timezone identifier string and a DateTimeZone object. + * + * @author Roland Franssen + */ +class DateTimeZoneToStringTransformer implements DataTransformerInterface +{ + private $multiple; + + public function __construct($multiple = false) + { + $this->multiple = $multiple; + } + + /** + * {@inheritdoc} + */ + public function transform($dateTimeZone) + { + if (null === $dateTimeZone) { + return; + } + + if ($this->multiple) { + if (!is_array($dateTimeZone)) { + throw new TransformationFailedException('Expected an array.'); + } + + return array_map(array(new self(), 'transform'), $dateTimeZone); + } + + if (!$dateTimeZone instanceof \DateTimeZone) { + throw new TransformationFailedException('Expected a \DateTimeZone.'); + } + + return $dateTimeZone->getName(); + } + + /** + * {@inheritdoc} + */ + public function reverseTransform($value) + { + if (null === $value) { + return; + } + + if ($this->multiple) { + if (!is_array($value)) { + throw new TransformationFailedException('Expected an array.'); + } + + return array_map(array(new self(), 'reverseTransform'), $value); + } + + if (!is_string($value)) { + throw new TransformationFailedException('Expected a string.'); + } + + try { + return new \DateTimeZone($value); + } catch (\Exception $e) { + throw new TransformationFailedException($e->getMessage(), $e->getCode(), $e); + } + } +} diff --git a/src/Symfony/Component/Form/Extension/Core/Type/TimezoneType.php b/src/Symfony/Component/Form/Extension/Core/Type/TimezoneType.php index 196c7400bbb65..0a0ea56ef9ea6 100644 --- a/src/Symfony/Component/Form/Extension/Core/Type/TimezoneType.php +++ b/src/Symfony/Component/Form/Extension/Core/Type/TimezoneType.php @@ -13,7 +13,10 @@ use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\ChoiceList\ArrayChoiceList; +use Symfony\Component\Form\ChoiceList\Loader\CallbackChoiceLoader; use Symfony\Component\Form\ChoiceList\Loader\ChoiceLoaderInterface; +use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeZoneToStringTransformer; +use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\OptionsResolver\Options; use Symfony\Component\OptionsResolver\OptionsResolver; @@ -25,9 +28,21 @@ class TimezoneType extends AbstractType implements ChoiceLoaderInterface * The choices are generated from the ICU function \DateTimeZone::listIdentifiers(). * * @var ArrayChoiceList + * + * @deprecated since version 3.4, to be removed in 4.0 */ private $choiceList; + /** + * {@inheritdoc} + */ + public function buildForm(FormBuilderInterface $builder, array $options) + { + if ('datetimezone' === $options['input']) { + $builder->addModelTransformer(new DateTimeZoneToStringTransformer($options['multiple'])); + } + } + /** * {@inheritdoc} */ @@ -41,10 +56,20 @@ public function configureOptions(OptionsResolver $resolver) return null; } - return $this; + $regions = $options['regions']; + + return new CallbackChoiceLoader(function () use ($regions) { + return self::getTimezones($regions); + }); }, 'choice_translation_domain' => false, + 'input' => 'string', + 'regions' => \DateTimeZone::ALL, )); + + $resolver->setAllowedValues('input', array('string', 'datetimezone')); + + $resolver->setAllowedTypes('regions', 'int'); } /** @@ -65,21 +90,29 @@ public function getBlockPrefix() /** * {@inheritdoc} + * + * @deprecated since version 3.4, to be removed in 4.0 */ public function loadChoiceList($value = null) { + @trigger_error(sprintf('Method "%s" is deprecated since version 3.4 and will be removed in 4.0.', __METHOD__), E_USER_DEPRECATED); + if (null !== $this->choiceList) { return $this->choiceList; } - return $this->choiceList = new ArrayChoiceList(self::getTimezones(), $value); + return $this->choiceList = new ArrayChoiceList(self::getTimezones(\DateTimeZone::ALL), $value); } /** * {@inheritdoc} + * + * @deprecated since version 3.4, to be removed in 4.0 */ public function loadChoicesForValues(array $values, $value = null) { + @trigger_error(sprintf('Method "%s" is deprecated since version 3.4 and will be removed in 4.0.', __METHOD__), E_USER_DEPRECATED); + // Optimize $values = array_filter($values); if (empty($values)) { @@ -96,9 +129,13 @@ public function loadChoicesForValues(array $values, $value = null) /** * {@inheritdoc} + * + * @deprecated since version 3.4, to be removed in 4.0 */ public function loadValuesForChoices(array $choices, $value = null) { + @trigger_error(sprintf('Method "%s" is deprecated since version 3.4 and will be removed in 4.0.', __METHOD__), E_USER_DEPRECATED); + // Optimize $choices = array_filter($choices); if (empty($choices)) { @@ -116,13 +153,15 @@ public function loadValuesForChoices(array $choices, $value = null) /** * Returns a normalized array of timezone choices. * + * @param int $regions + * * @return array The timezone choices */ - private static function getTimezones() + private static function getTimezones($regions) { $timezones = array(); - foreach (\DateTimeZone::listIdentifiers() as $timezone) { + foreach (\DateTimeZone::listIdentifiers($regions) as $timezone) { $parts = explode('/', $timezone); if (count($parts) > 2) { @@ -139,6 +178,6 @@ private static function getTimezones() $timezones[$region][str_replace('_', ' ', $name)] = $timezone; } - return $timezones; + return 1 === count($timezones) ? reset($timezones) : $timezones; } } diff --git a/src/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/DateTimeZoneToStringTransformerTest.php b/src/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/DateTimeZoneToStringTransformerTest.php new file mode 100644 index 0000000000000..51442ecbf9053 --- /dev/null +++ b/src/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/DateTimeZoneToStringTransformerTest.php @@ -0,0 +1,56 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Tests\Extension\Core\DataTransformer; + +use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeZoneToStringTransformer; +use PHPUnit\Framework\TestCase; + +class DateTimeZoneToStringTransformerTest extends TestCase +{ + public function testSingle() + { + $transformer = new DateTimeZoneToStringTransformer(); + + $this->assertNull($transformer->transform(null)); + $this->assertNull($transformer->reverseTransform(null)); + + $this->assertSame('Europe/Amsterdam', $transformer->transform(new \DateTimeZone('Europe/Amsterdam'))); + $this->assertEquals(new \DateTimeZone('Europe/Amsterdam'), $transformer->reverseTransform('Europe/Amsterdam')); + } + + public function testMultiple() + { + $transformer = new DateTimeZoneToStringTransformer(true); + + $this->assertNull($transformer->transform(null)); + $this->assertNull($transformer->reverseTransform(null)); + + $this->assertSame(array('Europe/Amsterdam'), $transformer->transform(array(new \DateTimeZone('Europe/Amsterdam')))); + $this->assertEquals(array(new \DateTimeZone('Europe/Amsterdam')), $transformer->reverseTransform(array('Europe/Amsterdam'))); + } + + /** + * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException + */ + public function testInvalidTimezone() + { + (new DateTimeZoneToStringTransformer())->transform(1); + } + + /** + * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException + */ + public function testUnknownTimezone() + { + (new DateTimeZoneToStringTransformer(true))->reverseTransform(array('Foo/Bar')); + } +} diff --git a/src/Symfony/Component/Form/Tests/Extension/Core/Type/TimezoneTypeTest.php b/src/Symfony/Component/Form/Tests/Extension/Core/Type/TimezoneTypeTest.php index 8682efed69356..51578bd6ad298 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Core/Type/TimezoneTypeTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Core/Type/TimezoneTypeTest.php @@ -33,4 +33,31 @@ public function testSubmitNull($expected = null, $norm = null, $view = null) { parent::testSubmitNull($expected, $norm, ''); } + + public function testDateTimeZoneInput() + { + $form = $this->factory->create(static::TESTED_TYPE, new \DateTimeZone('America/New_York'), array('input' => 'datetimezone')); + + $this->assertSame('America/New_York', $form->createView()->vars['value']); + + $form->submit('Europe/Amsterdam'); + + $this->assertEquals(new \DateTimeZone('Europe/Amsterdam'), $form->getData()); + + $form = $this->factory->create(static::TESTED_TYPE, array(new \DateTimeZone('America/New_York')), array('input' => 'datetimezone', 'multiple' => true)); + + $this->assertSame(array('America/New_York'), $form->createView()->vars['value']); + + $form->submit(array('Europe/Amsterdam', 'Europe/Paris')); + + $this->assertEquals(array(new \DateTimeZone('Europe/Amsterdam'), new \DateTimeZone('Europe/Paris')), $form->getData()); + } + + public function testFilterByRegions() + { + $choices = $this->factory->create(static::TESTED_TYPE, null, array('regions' => \DateTimeZone::EUROPE)) + ->createView()->vars['choices']; + + $this->assertContains(new ChoiceView('Europe/Amsterdam', 'Europe/Amsterdam', 'Amsterdam'), $choices, '', false, false); + } } From b0c5cf0d9d98d893e89029ca8aafe43083831d0f Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Fri, 15 Sep 2017 23:40:40 +0200 Subject: [PATCH 0842/1099] [Serializer] Add local cache to normalizers --- .../Normalizer/AbstractObjectNormalizer.php | 5 +-- .../Normalizer/ArrayDenormalizer.php | 2 +- .../Normalizer/CustomNormalizer.php | 10 ++++-- .../Normalizer/DataUriNormalizer.php | 14 ++++---- .../Normalizer/DateTimeNormalizer.php | 14 ++++---- .../Normalizer/GetSetMethodNormalizer.php | 5 +-- .../Normalizer/PropertyNormalizer.php | 6 ++-- .../Component/Serializer/Serializer.php | 36 +++++-------------- 8 files changed, 42 insertions(+), 50 deletions(-) diff --git a/src/Symfony/Component/Serializer/Normalizer/AbstractObjectNormalizer.php b/src/Symfony/Component/Serializer/Normalizer/AbstractObjectNormalizer.php index 5a49cfec91b41..93e85c6fe67de 100644 --- a/src/Symfony/Component/Serializer/Normalizer/AbstractObjectNormalizer.php +++ b/src/Symfony/Component/Serializer/Normalizer/AbstractObjectNormalizer.php @@ -36,6 +36,7 @@ abstract class AbstractObjectNormalizer extends AbstractNormalizer private $propertyTypeExtractor; private $attributesCache = array(); + private $cache = array(); public function __construct(ClassMetadataFactoryInterface $classMetadataFactory = null, NameConverterInterface $nameConverter = null, PropertyTypeExtractorInterface $propertyTypeExtractor = null) { @@ -49,7 +50,7 @@ public function __construct(ClassMetadataFactoryInterface $classMetadataFactory */ public function supportsNormalization($data, $format = null) { - return is_object($data) && !$data instanceof \Traversable; + return \is_object($data) && !$data instanceof \Traversable; } /** @@ -163,7 +164,7 @@ abstract protected function getAttributeValue($object, $attribute, $format = nul */ public function supportsDenormalization($data, $type, $format = null) { - return class_exists($type); + return isset($this->cache[$type]) ? $this->cache[$type] : $this->cache[$type] = class_exists($type); } /** diff --git a/src/Symfony/Component/Serializer/Normalizer/ArrayDenormalizer.php b/src/Symfony/Component/Serializer/Normalizer/ArrayDenormalizer.php index 7a94d59aad467..14b23d01a073f 100644 --- a/src/Symfony/Component/Serializer/Normalizer/ArrayDenormalizer.php +++ b/src/Symfony/Component/Serializer/Normalizer/ArrayDenormalizer.php @@ -66,7 +66,7 @@ public function denormalize($data, $class, $format = null, array $context = arra */ public function supportsDenormalization($data, $type, $format = null/*, array $context = array()*/) { - $context = func_num_args() > 3 ? func_get_arg(3) : array(); + $context = \func_num_args() > 3 ? func_get_arg(3) : array(); return '[]' === substr($type, -2) && $this->serializer->supportsDenormalization($data, substr($type, 0, -2), $format, $context); diff --git a/src/Symfony/Component/Serializer/Normalizer/CustomNormalizer.php b/src/Symfony/Component/Serializer/Normalizer/CustomNormalizer.php index 688590ef02a10..fd8bbca274211 100644 --- a/src/Symfony/Component/Serializer/Normalizer/CustomNormalizer.php +++ b/src/Symfony/Component/Serializer/Normalizer/CustomNormalizer.php @@ -19,6 +19,8 @@ */ class CustomNormalizer implements NormalizerInterface, DenormalizerInterface, SerializerAwareInterface { + private $cache = array(); + use SerializerAwareTrait; /** @@ -64,10 +66,14 @@ public function supportsNormalization($data, $format = null) */ public function supportsDenormalization($data, $type, $format = null) { + if (isset($this->cache[$type])) { + return $this->cache[$type]; + } + if (!class_exists($type)) { - return false; + return $this->cache[$type] = false; } - return is_subclass_of($type, 'Symfony\Component\Serializer\Normalizer\DenormalizableInterface'); + return $this->cache[$type] = is_subclass_of($type, 'Symfony\Component\Serializer\Normalizer\DenormalizableInterface'); } } diff --git a/src/Symfony/Component/Serializer/Normalizer/DataUriNormalizer.php b/src/Symfony/Component/Serializer/Normalizer/DataUriNormalizer.php index 9e5af130d03b7..66a9ed6bd8d55 100644 --- a/src/Symfony/Component/Serializer/Normalizer/DataUriNormalizer.php +++ b/src/Symfony/Component/Serializer/Normalizer/DataUriNormalizer.php @@ -25,6 +25,12 @@ */ class DataUriNormalizer implements NormalizerInterface, DenormalizerInterface { + private static $supportedTypes = array( + \SplFileInfo::class => true, + \SplFileObject::class => true, + File::class => true, + ); + /** * @var MimeTypeGuesserInterface */ @@ -107,13 +113,7 @@ public function denormalize($data, $class, $format = null, array $context = arra */ public function supportsDenormalization($data, $type, $format = null) { - $supportedTypes = array( - \SplFileInfo::class => true, - \SplFileObject::class => true, - 'Symfony\Component\HttpFoundation\File\File' => true, - ); - - return isset($supportedTypes[$type]); + return isset(self::$supportedTypes[$type]); } /** diff --git a/src/Symfony/Component/Serializer/Normalizer/DateTimeNormalizer.php b/src/Symfony/Component/Serializer/Normalizer/DateTimeNormalizer.php index 35b0b5f0e5cd6..26fd9c6201afd 100644 --- a/src/Symfony/Component/Serializer/Normalizer/DateTimeNormalizer.php +++ b/src/Symfony/Component/Serializer/Normalizer/DateTimeNormalizer.php @@ -31,6 +31,12 @@ class DateTimeNormalizer implements NormalizerInterface, DenormalizerInterface private $format; private $timezone; + private static $supportedTypes = array( + \DateTimeInterface::class => true, + \DateTimeImmutable::class => true, + \DateTime::class => true, + ); + /** * @param string $format * @param \DateTimeZone|null $timezone @@ -115,13 +121,7 @@ public function denormalize($data, $class, $format = null, array $context = arra */ public function supportsDenormalization($data, $type, $format = null) { - $supportedTypes = array( - \DateTimeInterface::class => true, - \DateTimeImmutable::class => true, - \DateTime::class => true, - ); - - return isset($supportedTypes[$type]); + return isset(self::$supportedTypes[$type]); } /** diff --git a/src/Symfony/Component/Serializer/Normalizer/GetSetMethodNormalizer.php b/src/Symfony/Component/Serializer/Normalizer/GetSetMethodNormalizer.php index 3d2c0665be60f..426ae562fb730 100644 --- a/src/Symfony/Component/Serializer/Normalizer/GetSetMethodNormalizer.php +++ b/src/Symfony/Component/Serializer/Normalizer/GetSetMethodNormalizer.php @@ -35,13 +35,14 @@ class GetSetMethodNormalizer extends AbstractObjectNormalizer { private static $setterAccessibleCache = array(); + private $cache = array(); /** * {@inheritdoc} */ public function supportsNormalization($data, $format = null) { - return parent::supportsNormalization($data, $format) && $this->supports(get_class($data)); + return parent::supportsNormalization($data, $format) && (isset($this->cache[$type = \get_class($data)]) ? $this->cache[$type] : $this->cache[$type] = $this->supports($type)); } /** @@ -49,7 +50,7 @@ public function supportsNormalization($data, $format = null) */ public function supportsDenormalization($data, $type, $format = null) { - return parent::supportsDenormalization($data, $type, $format) && $this->supports($type); + return parent::supportsDenormalization($data, $type, $format) && (isset($this->cache[$type]) ? $this->cache[$type] : $this->cache[$type] = $this->supports($type)); } /** diff --git a/src/Symfony/Component/Serializer/Normalizer/PropertyNormalizer.php b/src/Symfony/Component/Serializer/Normalizer/PropertyNormalizer.php index 9795ec4bc85e9..2d96608ff2400 100644 --- a/src/Symfony/Component/Serializer/Normalizer/PropertyNormalizer.php +++ b/src/Symfony/Component/Serializer/Normalizer/PropertyNormalizer.php @@ -30,12 +30,14 @@ */ class PropertyNormalizer extends AbstractObjectNormalizer { + private $cache = array(); + /** * {@inheritdoc} */ public function supportsNormalization($data, $format = null) { - return parent::supportsNormalization($data, $format) && $this->supports(get_class($data)); + return parent::supportsNormalization($data, $format) && (isset($this->cache[$type = \get_class($data)]) ? $this->cache[$type] : $this->cache[$type] = $this->supports($type)); } /** @@ -43,7 +45,7 @@ public function supportsNormalization($data, $format = null) */ public function supportsDenormalization($data, $type, $format = null) { - return parent::supportsDenormalization($data, $type, $format) && $this->supports($type); + return parent::supportsDenormalization($data, $type, $format) && (isset($this->cache[$type]) ? $this->cache[$type] : $this->cache[$type] = $this->supports($type)); } /** diff --git a/src/Symfony/Component/Serializer/Serializer.php b/src/Symfony/Component/Serializer/Serializer.php index 36752465ac149..4c5cec1653ced 100644 --- a/src/Symfony/Component/Serializer/Serializer.php +++ b/src/Symfony/Component/Serializer/Serializer.php @@ -171,7 +171,15 @@ public function normalize($data, $format = null, array $context = array()) */ public function denormalize($data, $type, $format = null, array $context = array()) { - return $this->denormalizeObject($data, $type, $format, $context); + if (!$this->normalizers) { + throw new LogicException('You must register at least one normalizer to be able to denormalize objects.'); + } + + if ($normalizer = $this->getDenormalizer($data, $type, $format, $context)) { + return $normalizer->denormalize($data, $type, $format, $context); + } + + throw new UnexpectedValueException(sprintf('Could not denormalize object of type %s, no supporting normalizer found.', $type)); } /** @@ -269,32 +277,6 @@ final public function decode($data, $format, array $context = array()) return $this->decoder->decode($data, $format, $context); } - /** - * Denormalizes data back into an object of the given class. - * - * @param mixed $data data to restore - * @param string $class the expected class to instantiate - * @param string $format format name, present to give the option to normalizers to act differently based on formats - * @param array $context The context data for this particular denormalization - * - * @return object - * - * @throws LogicException - * @throws UnexpectedValueException - */ - private function denormalizeObject($data, $class, $format, array $context = array()) - { - if (!$this->normalizers) { - throw new LogicException('You must register at least one normalizer to be able to denormalize objects.'); - } - - if ($normalizer = $this->getDenormalizer($data, $class, $format, $context)) { - return $normalizer->denormalize($data, $class, $format, $context); - } - - throw new UnexpectedValueException(sprintf('Could not denormalize object of type %s, no supporting normalizer found.', $class)); - } - /** * {@inheritdoc} */ From d761a7614a0226c4109525ed2d1d1754a45ec6ae Mon Sep 17 00:00:00 2001 From: Pascal Luna Date: Sat, 16 Sep 2017 14:21:39 +0100 Subject: [PATCH 0843/1099] Require v3.4+ of the var-dumper component --- src/Symfony/Bundle/DebugBundle/composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Bundle/DebugBundle/composer.json b/src/Symfony/Bundle/DebugBundle/composer.json index 7b59b82c765f6..c5224da2e45b8 100644 --- a/src/Symfony/Bundle/DebugBundle/composer.json +++ b/src/Symfony/Bundle/DebugBundle/composer.json @@ -20,7 +20,7 @@ "ext-xml": "*", "symfony/http-kernel": "~2.8|~3.0|~4.0", "symfony/twig-bridge": "~2.8|~3.0|~4.0", - "symfony/var-dumper": "~2.8|~3.0|~4.0" + "symfony/var-dumper": "~3.4|~4.0" }, "require-dev": { "symfony/config": "~3.3|~4.0", From dce1eb95ff57d306ba49d1974e78f3a5c35bb09a Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Sat, 16 Sep 2017 18:00:00 +0200 Subject: [PATCH 0844/1099] [Bridge\Doctrine] Add "DoctrineType::reset()" method --- src/Symfony/Bridge/Doctrine/Form/Type/DoctrineType.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/Symfony/Bridge/Doctrine/Form/Type/DoctrineType.php b/src/Symfony/Bridge/Doctrine/Form/Type/DoctrineType.php index 17010990497cb..25b0aefecfe8c 100644 --- a/src/Symfony/Bridge/Doctrine/Form/Type/DoctrineType.php +++ b/src/Symfony/Bridge/Doctrine/Form/Type/DoctrineType.php @@ -280,4 +280,9 @@ public function getParent() { return 'Symfony\Component\Form\Extension\Core\Type\ChoiceType'; } + + public function reset() + { + $this->choiceLoaders = array(); + } } From 2a30908bcd3dd6e25ee49c7db3e45bc73a6a8c3a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Sat, 16 Sep 2017 20:19:07 +0200 Subject: [PATCH 0845/1099] [DI] Fix decorated service merge in ResolveInstanceofConditionalsPass --- .../ResolveInstanceofConditionalsPass.php | 1 + .../ResolveInstanceofConditionalsPassTest.php | 26 +++++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/src/Symfony/Component/DependencyInjection/Compiler/ResolveInstanceofConditionalsPass.php b/src/Symfony/Component/DependencyInjection/Compiler/ResolveInstanceofConditionalsPass.php index 32d7ad2911408..35ab241ef4fab 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/ResolveInstanceofConditionalsPass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/ResolveInstanceofConditionalsPass.php @@ -119,6 +119,7 @@ private function processDefinition(ContainerBuilder $container, $id, Definition $abstract ->setArguments(array()) ->setMethodCalls(array()) + ->setDecoratedService(null) ->setTags(array()) ->setAbstract(true); } diff --git a/src/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveInstanceofConditionalsPassTest.php b/src/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveInstanceofConditionalsPassTest.php index 164ab25941d64..e68e83ad9e3dc 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveInstanceofConditionalsPassTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveInstanceofConditionalsPassTest.php @@ -224,4 +224,30 @@ public function testProcessThrowsExceptionForArguments() (new ResolveInstanceofConditionalsPass())->process($container); } + + public function testMergeReset() + { + $container = new ContainerBuilder(); + + $container + ->register('bar', self::class) + ->addArgument('a') + ->addMethodCall('setB') + ->setDecoratedService('foo') + ->addTag('t') + ->setInstanceofConditionals(array( + parent::class => (new ChildDefinition(''))->addTag('bar'), + )) + ; + + (new ResolveInstanceofConditionalsPass())->process($container); + + $abstract = $container->getDefinition('abstract.instanceof.bar'); + + $this->assertEmpty($abstract->getArguments()); + $this->assertEmpty($abstract->getMethodCalls()); + $this->assertNull($abstract->getDecoratedService()); + $this->assertEmpty($abstract->getTags()); + $this->assertTrue($abstract->isAbstract()); + } } From c388b25cbbb15297ef663bac8cd6236cce42f237 Mon Sep 17 00:00:00 2001 From: Vladimir Tsykun Date: Sun, 17 Sep 2017 09:12:04 +0300 Subject: [PATCH 0846/1099] [WebProfilerBundle] Added missing link to profile token --- .../Resources/views/Collector/request.html.twig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/request.html.twig b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/request.html.twig index 5fe45a0f4ed39..8f94f6f5f0bd3 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/request.html.twig +++ b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/request.html.twig @@ -274,7 +274,7 @@ {{ helper.set_handler(child.getcollector('request').controller) }} - (token = {{ child.token }}) + (token = {{ child.token }}) {{ include('@WebProfiler/Profiler/bag.html.twig', { bag: child.getcollector('request').requestattributes }, with_context = false) }} From d94b9ac3086d7776c8a7ba6f1b99e4d48f8dd09d Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Sun, 17 Sep 2017 12:10:12 +0200 Subject: [PATCH 0847/1099] CS fixes --- .../Tests/DependencyInjection/FrameworkExtensionTest.php | 1 + src/Symfony/Component/VarDumper/Cloner/Data.php | 1 + src/Symfony/Component/Yaml/Inline.php | 2 ++ 3 files changed, 4 insertions(+) diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php index eee6169ae15da..11795e54cb6bd 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php @@ -1052,6 +1052,7 @@ private function assertCachePoolServiceDefinitionIsCreated(ContainerBuilder $con if (ChainAdapter::class === $parentDefinition->getClass()) { break; } + // no break case 'cache.adapter.filesystem': $this->assertSame(FilesystemAdapter::class, $parentDefinition->getClass()); break; diff --git a/src/Symfony/Component/VarDumper/Cloner/Data.php b/src/Symfony/Component/VarDumper/Cloner/Data.php index 3adaa6e55b091..73d9b38319b8e 100644 --- a/src/Symfony/Component/VarDumper/Cloner/Data.php +++ b/src/Symfony/Component/VarDumper/Cloner/Data.php @@ -247,6 +247,7 @@ public function seek($key) $keys[] = Caster::PREFIX_PROTECTED.$key; $keys[] = Caster::PREFIX_VIRTUAL.$key; $keys[] = "\0$item->class\0$key"; + // no break case Stub::TYPE_ARRAY: case Stub::TYPE_RESOURCE: break; diff --git a/src/Symfony/Component/Yaml/Inline.php b/src/Symfony/Component/Yaml/Inline.php index ecf2033adfa0e..c5e7f97a588aa 100644 --- a/src/Symfony/Component/Yaml/Inline.php +++ b/src/Symfony/Component/Yaml/Inline.php @@ -656,11 +656,13 @@ private static function evaluateScalar($scalar, $flags, $references = array()) } // Optimize for returning strings. + // no break case '+' === $scalar[0] || '-' === $scalar[0] || '.' === $scalar[0] || is_numeric($scalar[0]): switch (true) { case Parser::preg_match('{^[+-]?[0-9][0-9_]*$}', $scalar): $scalar = str_replace('_', '', (string) $scalar); // omitting the break / return as integers are handled in the next case + // no break case ctype_digit($scalar): $raw = $scalar; $cast = (int) $scalar; From 2bc11505f4c2a932101748bfbc582993c91274fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Auswo=CC=88ger?= Date: Thu, 6 Apr 2017 20:04:32 +0200 Subject: [PATCH 0848/1099] [Filesystem] Fixed makePathRelative --- .../Component/Filesystem/Filesystem.php | 42 +++++++++---------- .../Filesystem/Tests/FilesystemTest.php | 12 ++++++ 2 files changed, 32 insertions(+), 22 deletions(-) diff --git a/src/Symfony/Component/Filesystem/Filesystem.php b/src/Symfony/Component/Filesystem/Filesystem.php index edfc1b9d46a23..ac2a1c7857030 100644 --- a/src/Symfony/Component/Filesystem/Filesystem.php +++ b/src/Symfony/Component/Filesystem/Filesystem.php @@ -358,25 +358,28 @@ public function makePathRelative($endPath, $startPath) $startPath = str_replace('\\', '/', $startPath); } + $stripDriveLetter = function ($path) { + if (strlen($path) > 2 && ':' === $path[1] && '/' === $path[2] && ctype_alpha($path[0])) { + return substr($path, 2); + } + + return $path; + }; + + $endPath = $stripDriveLetter($endPath); + $startPath = $stripDriveLetter($startPath); + // Split the paths into arrays $startPathArr = explode('/', trim($startPath, '/')); $endPathArr = explode('/', trim($endPath, '/')); - if ('/' !== $startPath[0]) { - array_shift($startPathArr); - } - - if ('/' !== $endPath[0]) { - array_shift($endPathArr); - } - - $normalizePathArray = function ($pathSegments) { + $normalizePathArray = function ($pathSegments, $absolute) { $result = array(); foreach ($pathSegments as $segment) { - if ('..' === $segment) { + if ('..' === $segment && ($absolute || count($result))) { array_pop($result); - } else { + } elseif ('.' !== $segment) { $result[] = $segment; } } @@ -384,8 +387,8 @@ public function makePathRelative($endPath, $startPath) return $result; }; - $startPathArr = $normalizePathArray($startPathArr); - $endPathArr = $normalizePathArray($endPathArr); + $startPathArr = $normalizePathArray($startPathArr, static::isAbsolutePath($startPath)); + $endPathArr = $normalizePathArray($endPathArr, static::isAbsolutePath($endPath)); // Find for which directory the common path stops $index = 0; @@ -394,19 +397,14 @@ public function makePathRelative($endPath, $startPath) } // Determine how deep the start path is relative to the common path (ie, "web/bundles" = 2 levels) - if (count($startPathArr) === 1 && $startPathArr[0] === '') { + if (1 === count($startPathArr) && '' === $startPathArr[0]) { $depth = 0; } else { $depth = count($startPathArr) - $index; } - // When we need to traverse from the start, and we are starting from a root path, don't add '../' - if ('/' === $startPath[0] && 0 === $index && 0 === $depth) { - $traverser = ''; - } else { - // Repeated "../" for each level need to reach the common path - $traverser = str_repeat('../', $depth); - } + // Repeated "../" for each level need to reach the common path + $traverser = str_repeat('../', $depth); $endPathRemainder = implode('/', array_slice($endPathArr, $index)); @@ -500,7 +498,7 @@ public function isAbsolutePath($file) { return strspn($file, '/\\', 0, 1) || (strlen($file) > 3 && ctype_alpha($file[0]) - && substr($file, 1, 1) === ':' + && ':' === substr($file, 1, 1) && strspn($file, '/\\', 2, 1) ) || null !== parse_url($file, PHP_URL_SCHEME) diff --git a/src/Symfony/Component/Filesystem/Tests/FilesystemTest.php b/src/Symfony/Component/Filesystem/Tests/FilesystemTest.php index ab2395cd001c0..d2058d0a01cf3 100644 --- a/src/Symfony/Component/Filesystem/Tests/FilesystemTest.php +++ b/src/Symfony/Component/Filesystem/Tests/FilesystemTest.php @@ -847,6 +847,7 @@ public function providePathsForMakePathRelative() array('/var/lib/symfony/src/Symfony', '/var/lib/symfony/src/Symfony/Component/', '../'), array('var/lib/symfony/', 'var/lib/symfony/src/Symfony/Component', '../../../'), array('/usr/lib/symfony/', '/var/lib/symfony/src/Symfony/Component', '../../../../../../usr/lib/symfony/'), + array('usr/lib/symfony/', 'var/lib/symfony/src/Symfony/Component', '../../../../../../usr/lib/symfony/'), array('/var/lib/symfony/src/Symfony/', '/var/lib/symfony/', 'src/Symfony/'), array('/aa/bb', '/aa/bb', './'), array('/aa/bb', '/aa/bb/', './'), @@ -878,6 +879,17 @@ public function providePathsForMakePathRelative() array('C:/aa/bb/../../cc', 'C:/aa/../dd/..', 'cc/'), array('C:/../aa/bb/cc', 'C:/aa/dd/..', 'bb/cc/'), array('C:/../../aa/../bb/cc', 'C:/aa/dd/..', '../bb/cc/'), + array('aa/bb', 'aa/cc', '../bb/'), + array('aa/cc', 'bb/cc', '../../aa/cc/'), + array('aa/bb', 'aa/./cc', '../bb/'), + array('aa/./bb', 'aa/cc', '../bb/'), + array('aa/./bb', 'aa/./cc', '../bb/'), + array('../../', '../../', './'), + array('../aa/bb/', 'aa/bb/', '../../../aa/bb/'), + array('../../../', '../../', '../'), + array('', '', './'), + array('', 'aa/', '../'), + array('aa/', '', 'aa/'), ); if ('\\' === DIRECTORY_SEPARATOR) { From 081c1e4f812342902b1e3bfa228b83a593074bdc Mon Sep 17 00:00:00 2001 From: Roland Franssen Date: Sun, 17 Sep 2017 18:42:13 +0200 Subject: [PATCH 0849/1099] [WebProfiler] Fix z-index for pinned AJAX block --- .../Resources/views/Profiler/toolbar.css.twig | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/toolbar.css.twig b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/toolbar.css.twig index ac2e38eea1842..670dd47e1c728 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/toolbar.css.twig +++ b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/toolbar.css.twig @@ -310,6 +310,9 @@ position: relative; z-index: 10002; } +.sf-toolbar-block-ajax.hover .sf-toolbar-info { + z-index: 10001; +} .sf-toolbar-block:hover .sf-toolbar-info, .sf-toolbar-block.hover .sf-toolbar-info { display: block; From 47993a8abd833a79afbda9b9ab2aafd5e65b3242 Mon Sep 17 00:00:00 2001 From: Maxime Steinhausser Date: Sun, 17 Sep 2017 20:01:07 +0200 Subject: [PATCH 0850/1099] [Form] Remove deprecated ChoiceLoaderInterface implementation in TimezoneType --- src/Symfony/Component/Form/CHANGELOG.md | 1 + .../Form/Extension/Core/Type/TimezoneType.php | 77 +------------------ 2 files changed, 2 insertions(+), 76 deletions(-) diff --git a/src/Symfony/Component/Form/CHANGELOG.md b/src/Symfony/Component/Form/CHANGELOG.md index b28d44740d770..f6912fa3b80bd 100644 --- a/src/Symfony/Component/Form/CHANGELOG.md +++ b/src/Symfony/Component/Form/CHANGELOG.md @@ -18,6 +18,7 @@ CHANGELOG * removed passing a `ValueExporter` instance to the `FormDataExtractor::__construct()` method * removed passing guesser services ids as the fourth argument of `DependencyInjectionExtension::__construct()` * removed the ability to validate an unsubmitted form. + * removed `ChoiceLoaderInterface` implementation in `TimezoneType` 3.4.0 ----- diff --git a/src/Symfony/Component/Form/Extension/Core/Type/TimezoneType.php b/src/Symfony/Component/Form/Extension/Core/Type/TimezoneType.php index 1ba5a13604c65..3f1a223d371ab 100644 --- a/src/Symfony/Component/Form/Extension/Core/Type/TimezoneType.php +++ b/src/Symfony/Component/Form/Extension/Core/Type/TimezoneType.php @@ -12,27 +12,14 @@ namespace Symfony\Component\Form\Extension\Core\Type; use Symfony\Component\Form\AbstractType; -use Symfony\Component\Form\ChoiceList\ArrayChoiceList; use Symfony\Component\Form\ChoiceList\Loader\CallbackChoiceLoader; -use Symfony\Component\Form\ChoiceList\Loader\ChoiceLoaderInterface; use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeZoneToStringTransformer; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\OptionsResolver\Options; use Symfony\Component\OptionsResolver\OptionsResolver; -class TimezoneType extends AbstractType implements ChoiceLoaderInterface +class TimezoneType extends AbstractType { - /** - * Timezone loaded choice list. - * - * The choices are generated from the ICU function \DateTimeZone::listIdentifiers(). - * - * @var ArrayChoiceList - * - * @deprecated since version 3.4, to be removed in 4.0 - */ - private $choiceList; - /** * {@inheritdoc} */ @@ -82,68 +69,6 @@ public function getBlockPrefix() return 'timezone'; } - /** - * {@inheritdoc} - * - * @deprecated since version 3.4, to be removed in 4.0 - */ - public function loadChoiceList($value = null) - { - @trigger_error(sprintf('Method "%s" is deprecated since version 3.4 and will be removed in 4.0.', __METHOD__), E_USER_DEPRECATED); - - if (null !== $this->choiceList) { - return $this->choiceList; - } - - return $this->choiceList = new ArrayChoiceList(self::getTimezones(\DateTimeZone::ALL), $value); - } - - /** - * {@inheritdoc} - * - * @deprecated since version 3.4, to be removed in 4.0 - */ - public function loadChoicesForValues(array $values, $value = null) - { - @trigger_error(sprintf('Method "%s" is deprecated since version 3.4 and will be removed in 4.0.', __METHOD__), E_USER_DEPRECATED); - - // Optimize - $values = array_filter($values); - if (empty($values)) { - return array(); - } - - // If no callable is set, values are the same as choices - if (null === $value) { - return $values; - } - - return $this->loadChoiceList($value)->getChoicesForValues($values); - } - - /** - * {@inheritdoc} - * - * @deprecated since version 3.4, to be removed in 4.0 - */ - public function loadValuesForChoices(array $choices, $value = null) - { - @trigger_error(sprintf('Method "%s" is deprecated since version 3.4 and will be removed in 4.0.', __METHOD__), E_USER_DEPRECATED); - - // Optimize - $choices = array_filter($choices); - if (empty($choices)) { - return array(); - } - - // If no callable is set, choices are the same as values - if (null === $value) { - return $choices; - } - - return $this->loadChoiceList($value)->getValuesForChoices($choices); - } - /** * Returns a normalized array of timezone choices. * From 893df5804e82150dc6b3a3b32f53a7e93642e58e Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Thu, 14 Sep 2017 14:29:42 +0200 Subject: [PATCH 0851/1099] deprecate relative paths in makePathRelative() --- UPGRADE-3.4.md | 1 + UPGRADE-4.0.md | 1 + src/Symfony/Component/Filesystem/CHANGELOG.md | 1 + src/Symfony/Component/Filesystem/Filesystem.php | 6 +++++- .../Component/Filesystem/Tests/FilesystemTest.php | 10 +++++++++- 5 files changed, 17 insertions(+), 2 deletions(-) diff --git a/UPGRADE-3.4.md b/UPGRADE-3.4.md index 33147c4cc9ad1..7c575cfc2d436 100644 --- a/UPGRADE-3.4.md +++ b/UPGRADE-3.4.md @@ -66,6 +66,7 @@ Filesystem * The `Symfony\Component\Filesystem\LockHandler` class has been deprecated, use the `Symfony\Component\Lock\Store\FlockStore` class or the `Symfony\Component\Lock\Store\FlockStore\SemaphoreStore` class directly instead. + * Support for passing relative paths to `Filesystem::makePathRelative()` is deprecated and will be removed in 4.0. Finder ------ diff --git a/UPGRADE-4.0.md b/UPGRADE-4.0.md index 6c32bad70c90b..983c7f72fbe93 100644 --- a/UPGRADE-4.0.md +++ b/UPGRADE-4.0.md @@ -200,6 +200,7 @@ Filesystem * The `Symfony\Component\Filesystem\LockHandler` has been removed, use the `Symfony\Component\Lock\Store\FlockStore` class or the `Symfony\Component\Lock\Store\FlockStore\SemaphoreStore` class directly instead. + * Support for passing relative paths to `Filesystem::makePathRelative()` has been removed. Finder ------ diff --git a/src/Symfony/Component/Filesystem/CHANGELOG.md b/src/Symfony/Component/Filesystem/CHANGELOG.md index 4a275e86f0cad..ba3eff0f0d1e4 100644 --- a/src/Symfony/Component/Filesystem/CHANGELOG.md +++ b/src/Symfony/Component/Filesystem/CHANGELOG.md @@ -5,6 +5,7 @@ CHANGELOG ----- * added `appendToFile()` to append contents to existing files + * support for passing relative paths to `Filesystem::makePathRelative()` is deprecated and will be removed in 4.0 3.2.0 ----- diff --git a/src/Symfony/Component/Filesystem/Filesystem.php b/src/Symfony/Component/Filesystem/Filesystem.php index 2e742d532a641..2548c196463c5 100644 --- a/src/Symfony/Component/Filesystem/Filesystem.php +++ b/src/Symfony/Component/Filesystem/Filesystem.php @@ -446,6 +446,10 @@ public function readlink($path, $canonicalize = false) */ public function makePathRelative($endPath, $startPath) { + if (!$this->isAbsolutePath($endPath) || !$this->isAbsolutePath($startPath)) { + @trigger_error(sprintf('Support for passing relative paths to %s() is deprecated since version 3.4 and will be removed in 4.0.', __METHOD__), E_USER_DEPRECATED); + } + // Normalize separators on Windows if ('\\' === DIRECTORY_SEPARATOR) { $endPath = str_replace('\\', '/', $endPath); @@ -596,7 +600,7 @@ public function isAbsolutePath($file) { return strspn($file, '/\\', 0, 1) || (strlen($file) > 3 && ctype_alpha($file[0]) - && ':' === substr($file, 1, 1) + && ':' === $file[1] && strspn($file, '/\\', 2, 1) ) || null !== parse_url($file, PHP_URL_SCHEME) diff --git a/src/Symfony/Component/Filesystem/Tests/FilesystemTest.php b/src/Symfony/Component/Filesystem/Tests/FilesystemTest.php index 4420e8fb855c3..9b6da0d66d53d 100644 --- a/src/Symfony/Component/Filesystem/Tests/FilesystemTest.php +++ b/src/Symfony/Component/Filesystem/Tests/FilesystemTest.php @@ -1103,7 +1103,6 @@ public function providePathsForMakePathRelative() array('/var/lib/symfony/src/Symfony/', '/var/lib/symfony/src/Symfony/Component/', '../'), array('/var/lib/symfony/src/Symfony', '/var/lib/symfony/src/Symfony/Component', '../'), array('/var/lib/symfony/src/Symfony', '/var/lib/symfony/src/Symfony/Component/', '../'), - array('var/lib/symfony/', 'var/lib/symfony/src/Symfony/Component', '../../../'), array('/usr/lib/symfony/', '/var/lib/symfony/src/Symfony/Component', '../../../../../../usr/lib/symfony/'), array('/var/lib/symfony/src/Symfony/', '/var/lib/symfony/', 'src/Symfony/'), array('/aa/bb', '/aa/bb', './'), @@ -1145,6 +1144,15 @@ public function providePathsForMakePathRelative() return $paths; } + /** + * @group legacy + * @expectedDeprecation Support for passing relative paths to Symfony\Component\Filesystem\Filesystem::makePathRelative() is deprecated since version 3.4 and will be removed in 4.0. + */ + public function testMakePathRelativeWithRelativePaths() + { + $this->assertSame('../../../', $this->filesystem->makePathRelative('var/lib/symfony/', 'var/lib/symfony/src/Symfony/Component')); + } + public function testMirrorCopiesFilesAndDirectoriesRecursively() { $sourcePath = $this->workspace.DIRECTORY_SEPARATOR.'source'.DIRECTORY_SEPARATOR; From cde5a47e8fb587f447403546e554f913427086ec Mon Sep 17 00:00:00 2001 From: Roland Franssen Date: Sun, 17 Sep 2017 11:49:29 +0200 Subject: [PATCH 0852/1099] [Validator] Clarify UUID validator behavior --- .../Component/Validator/Constraints/UuidValidator.php | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/Validator/Constraints/UuidValidator.php b/src/Symfony/Component/Validator/Constraints/UuidValidator.php index 6dcda078a418e..6bbef2d05fbe7 100644 --- a/src/Symfony/Component/Validator/Constraints/UuidValidator.php +++ b/src/Symfony/Component/Validator/Constraints/UuidValidator.php @@ -18,13 +18,19 @@ use Symfony\Component\Validator\Exception\UnexpectedTypeException; /** - * Validates whether the value is a valid UUID per RFC 4122. + * Validates whether the value is a valid UUID (also known as GUID). + * + * Strict validation will allow a UUID as specified per RFC 4122. + * Loose validation will allow any type of UUID. + * + * For better compatibility, both loose and strict, you should consider using a specialized UUID library like "ramsey/uuid" instead. * * @author Colin O'Dell * @author Bernhard Schussek * * @see http://tools.ietf.org/html/rfc4122 * @see https://en.wikipedia.org/wiki/Universally_unique_identifier + * @see https://github.com/ramsey/uuid */ class UuidValidator extends ConstraintValidator { From e39e7a4fa9ba81c4a364b10f66c2cbf73067f54e Mon Sep 17 00:00:00 2001 From: HeahDude Date: Sun, 30 Jul 2017 18:55:50 +0200 Subject: [PATCH 0853/1099] [Form] Fixed GroupSequence with "constraints" option --- .../Validator/Constraints/FormValidator.php | 40 ++++++++++++++----- .../Constraints/FormValidatorTest.php | 5 ++- .../Type/FormTypeValidatorExtensionTest.php | 31 +++++++++++++- 3 files changed, 62 insertions(+), 14 deletions(-) diff --git a/src/Symfony/Component/Form/Extension/Validator/Constraints/FormValidator.php b/src/Symfony/Component/Form/Extension/Validator/Constraints/FormValidator.php index b5a06156c0db4..3bf57df048c60 100644 --- a/src/Symfony/Component/Form/Extension/Validator/Constraints/FormValidator.php +++ b/src/Symfony/Component/Form/Extension/Validator/Constraints/FormValidator.php @@ -65,18 +65,38 @@ public function validate($form, Constraint $constraint) // Validate the data against the constraints defined // in the form $constraints = $config->getOption('constraints', array()); - foreach ($constraints as $constraint) { - foreach ($groups as $group) { - if (in_array($group, $constraint->groups)) { - if ($validator) { - $validator->atPath('data')->validate($form->getData(), $constraint, $group); - } else { - // 2.4 API - $this->context->validateValue($form->getData(), $constraint, 'data', $group); + + if ($groups instanceof GroupSequence) { + if ($validator) { + $validator->atPath('data')->validate($form->getData(), $constraints, $groups); + } else { + // 2.4 API + foreach ($groups as $group) { + foreach ($constraints as $constraint) { + if (in_array($group, $constraint->groups)) { + $this->context->validateValue($form->getData(), $constraint, 'data', $group); + } } - // Prevent duplicate validation - continue 2; + if (count($this->context->getViolations()) > 0) { + break; + } + } + } + } else { + foreach ($constraints as $constraint) { + foreach ($groups as $group) { + if (in_array($group, $constraint->groups)) { + if ($validator) { + $validator->atPath('data')->validate($form->getData(), $constraint, $group); + } else { + // 2.4 API + $this->context->validateValue($form->getData(), $constraint, 'data', $group); + } + + // Prevent duplicate validation + continue 2; + } } } } diff --git a/src/Symfony/Component/Form/Tests/Extension/Validator/Constraints/FormValidatorTest.php b/src/Symfony/Component/Form/Tests/Extension/Validator/Constraints/FormValidatorTest.php index 8cd2dabc023e9..78015b504940b 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Validator/Constraints/FormValidatorTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Validator/Constraints/FormValidatorTest.php @@ -342,7 +342,7 @@ function () { throw new TransformationFailedException(); } $this->assertNoViolation(); } - public function testHandleCallbackValidationGroups() + public function testHandleGroupSequenceValidationGroups() { $object = $this->getMockBuilder('\stdClass')->getMock(); $options = array('validation_groups' => new GroupSequence(array('group1', 'group2'))); @@ -351,13 +351,14 @@ public function testHandleCallbackValidationGroups() ->getForm(); $this->expectValidateAt(0, 'data', $object, new GroupSequence(array('group1', 'group2'))); + $this->expectValidateAt(1, 'data', $object, new GroupSequence(array('group1', 'group2'))); $this->validator->validate($form, new Form()); $this->assertNoViolation(); } - public function testHandleGroupSequenceValidationGroups() + public function testHandleCallbackValidationGroups() { $object = $this->getMockBuilder('\stdClass')->getMock(); $options = array('validation_groups' => array($this, 'getValidationGroups')); diff --git a/src/Symfony/Component/Form/Tests/Extension/Validator/Type/FormTypeValidatorExtensionTest.php b/src/Symfony/Component/Form/Tests/Extension/Validator/Type/FormTypeValidatorExtensionTest.php index 79e4dc78f7ac6..e0de1c1ff82db 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Validator/Type/FormTypeValidatorExtensionTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Validator/Type/FormTypeValidatorExtensionTest.php @@ -12,14 +12,22 @@ namespace Symfony\Component\Form\Tests\Extension\Validator\Type; use Symfony\Component\Form\Extension\Validator\Type\FormTypeValidatorExtension; +use Symfony\Component\Form\Extension\Validator\ValidatorExtension; +use Symfony\Component\Form\Forms; +use Symfony\Component\Form\Tests\Extension\Core\Type\FormTypeTest; +use Symfony\Component\Form\Tests\Extension\Core\Type\TextTypeTest; +use Symfony\Component\Validator\Constraints\Email; +use Symfony\Component\Validator\Constraints\GroupSequence; +use Symfony\Component\Validator\Constraints\Length; use Symfony\Component\Validator\ConstraintViolationList; +use Symfony\Component\Validator\Validation; class FormTypeValidatorExtensionTest extends BaseValidatorExtensionTest { public function testSubmitValidatesData() { $builder = $this->factory->createBuilder( - 'form', + FormTypeTest::TESTED_TYPE, null, array( 'validation_groups' => 'group', @@ -63,8 +71,27 @@ public function testInvalidValidatorInterface() new FormTypeValidatorExtension(null); } + public function testGroupSequenceWithConstraintsOption() + { + $form = Forms::createFormFactoryBuilder() + ->addExtension(new ValidatorExtension(Validation::createValidator())) + ->getFormFactory() + ->create(FormTypeTest::TESTED_TYPE, null, (array('validation_groups' => new GroupSequence(array('First', 'Second'))))) + ->add('field', TextTypeTest::TESTED_TYPE, array( + 'constraints' => array( + new Length(array('min' => 10, 'groups' => array('First'))), + new Email(array('groups' => array('Second'))), + ), + )) + ; + + $form->submit(array('field' => 'wrong')); + + $this->assertCount(1, $form->getErrors(true)); + } + protected function createForm(array $options = array()) { - return $this->factory->create('form', null, $options); + return $this->factory->create(FormTypeTest::TESTED_TYPE, null, $options); } } From 3da645efed0d564bdeb5d4c519eee2d848445c39 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Mon, 18 Sep 2017 17:50:14 +0200 Subject: [PATCH 0854/1099] [DI] remove confusing code --- .../Compiler/ResolveParameterPlaceHoldersPass.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/DependencyInjection/Compiler/ResolveParameterPlaceHoldersPass.php b/src/Symfony/Component/DependencyInjection/Compiler/ResolveParameterPlaceHoldersPass.php index a35f84cbe4a80..905549897f8ba 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/ResolveParameterPlaceHoldersPass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/ResolveParameterPlaceHoldersPass.php @@ -64,7 +64,7 @@ public function process(ContainerBuilder $container) $aliases = array(); foreach ($container->getAliases() as $name => $target) { - $aliases[$parameterBag->resolveValue($name)] = $parameterBag->resolveValue($target); + $aliases[$parameterBag->resolveValue($name)] = $target; } $container->setAliases($aliases); From 9948b09c6d356f363def065a300eafb4ca56f5a3 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Sun, 17 Sep 2017 11:49:41 +0200 Subject: [PATCH 0855/1099] [DI] Turn services and aliases private by default, with BC layer --- UPGRADE-3.4.md | 11 +-- UPGRADE-4.0.md | 15 +++-- .../Tests/LazyProxy/Dumper/PhpDumperTest.php | 2 +- .../FrameworkExtension.php | 6 +- .../Kernel/MicroKernelTrait.php | 1 + .../Functional/app/AutowiringTypes/config.yml | 1 + .../Functional/app/ContainerDebug/config.yml | 1 + .../Functional/app/Serializer/config.yml | 1 + .../Tests/Kernel/ConcreteMicroKernel.php | 2 +- .../DependencyInjection/SecurityExtension.php | 2 +- .../Tests/Functional/app/Acl/config.yml | 1 + .../Functional/app/AutowiringTypes/config.yml | 1 + .../AddConsoleCommandPass.php | 5 +- src/Symfony/Component/Console/composer.json | 4 +- .../Component/DependencyInjection/Alias.php | 4 +- .../DependencyInjection/CHANGELOG.md | 1 + .../Compiler/AutoAliasServicePass.php | 2 +- .../Compiler/CheckDefinitionValidityPass.php | 2 +- .../Compiler/DecoratorServicePass.php | 2 +- .../Compiler/RegisterEnvVarProcessorsPass.php | 1 + .../ReplaceAliasByActualDefinitionPass.php | 2 +- .../Compiler/ResolveChildDefinitionsPass.php | 2 + .../ResolveReferencesToAliasesPass.php | 2 +- .../DependencyInjection/Definition.php | 3 +- .../DependencyInjection/Dumper/XmlDumper.php | 8 +-- .../DependencyInjection/Dumper/YamlDumper.php | 8 +-- .../Loader/XmlFileLoader.php | 7 +- .../Loader/YamlFileLoader.php | 14 ++-- .../ResolveChildDefinitionsPassTest.php | 4 +- .../Tests/Dumper/PhpDumperTest.php | 67 ++++++++++++------- .../Tests/Dumper/XmlDumperTest.php | 10 +-- .../Tests/Dumper/YamlDumperTest.php | 3 +- .../Tests/Fixtures/containers/container10.php | 1 + .../Tests/Fixtures/containers/container11.php | 1 + .../Tests/Fixtures/containers/container12.php | 1 + .../Tests/Fixtures/containers/container13.php | 2 + .../Tests/Fixtures/containers/container15.php | 1 + .../Tests/Fixtures/containers/container16.php | 1 + .../Tests/Fixtures/containers/container17.php | 1 + .../Tests/Fixtures/containers/container19.php | 2 + .../Tests/Fixtures/containers/container21.php | 1 + .../Tests/Fixtures/containers/container24.php | 1 + .../Tests/Fixtures/containers/container33.php | 4 +- .../Tests/Fixtures/containers/container9.php | 24 ++++++- .../containers/container_abstract.php | 1 + .../container_uninitialized_ref.php | 3 + .../Tests/Fixtures/php/services1-1.php | 3 + .../Tests/Fixtures/php/services1.php | 3 + .../Tests/Fixtures/php/services10.php | 3 + .../Tests/Fixtures/php/services12.php | 3 + .../Tests/Fixtures/php/services13.php | 3 + .../Tests/Fixtures/php/services19.php | 3 + .../Tests/Fixtures/php/services24.php | 3 + .../Tests/Fixtures/php/services26.php | 3 + .../Tests/Fixtures/php/services33.php | 3 + .../Tests/Fixtures/php/services8.php | 3 + .../Tests/Fixtures/php/services9_as_files.txt | 1 + .../Tests/Fixtures/php/services9_compiled.php | 1 + .../Fixtures/php/services_array_params.php | 3 + .../Fixtures/php/services_base64_env.php | 3 + .../Fixtures/php/services_legacy_privates.php | 13 +--- .../Tests/Fixtures/php/services_locator.php | 1 + .../Fixtures/php/services_private_frozen.php | 1 + .../php/services_private_in_expression.php | 1 + .../Tests/Fixtures/php/services_rot13_env.php | 3 + .../Fixtures/php/services_subscriber.php | 1 + .../php/services_uninitialized_ref.php | 1 + .../Tests/Fixtures/xml/services21.xml | 2 +- .../Tests/Fixtures/xml/services24.xml | 2 +- .../Tests/Fixtures/xml/services9.xml | 44 ++++++------ .../Tests/Fixtures/xml/services_abstract.xml | 2 +- .../Fixtures/xml/services_without_id.xml | 1 + .../Tests/Fixtures/yaml/services24.yml | 1 + .../Tests/Fixtures/yaml/services26.yml | 1 + .../Tests/Fixtures/yaml/services9.yml | 28 +++++++- .../Tests/Fixtures/yaml/services_inline.yml | 1 + .../yaml/services_legacy_privates.yml | 3 +- .../Tests/Loader/XmlFileLoaderTest.php | 2 +- 78 files changed, 264 insertions(+), 121 deletions(-) diff --git a/UPGRADE-3.4.md b/UPGRADE-3.4.md index 33147c4cc9ad1..cdc062008bf4b 100644 --- a/UPGRADE-3.4.md +++ b/UPGRADE-3.4.md @@ -4,6 +4,9 @@ UPGRADE FROM 3.3 to 3.4 DependencyInjection ------------------- + * Definitions and aliases will be made private by default in 4.0. You should either use service injection + or explicitly define your services as public if you really need to inject the container. + * Relying on service auto-registration while autowiring is deprecated and won't be supported in Symfony 4.0. Explicitly inject your dependencies or create services whose ids are their fully-qualified class name. @@ -154,7 +157,7 @@ FrameworkBundle * The `Symfony\Bundle\FrameworkBundle\Translation\TranslationLoader` class has been deprecated and will be removed in 4.0. Use the `Symfony\Component\Translation\Reader\TranslationReader` class instead. - + * The `translation.loader` service has been deprecated and will be removed in 4.0. Use the `translation.reader` service instead.. @@ -269,9 +272,9 @@ SecurityBundle Translation ----------- - * `Symfony\Component\Translation\Writer\TranslationWriter::writeTranslations` has been deprecated - and will be removed in 4.0, use `Symfony\Component\Translation\Writer\TranslationWriter::write` - instead. + * `Symfony\Component\Translation\Writer\TranslationWriter::writeTranslations` has been deprecated + and will be removed in 4.0, use `Symfony\Component\Translation\Writer\TranslationWriter::write` + instead. * Passing a `Symfony\Component\Translation\MessageSelector` to `Translator` has been deprecated. You should pass a message formatter instead diff --git a/UPGRADE-4.0.md b/UPGRADE-4.0.md index 6c32bad70c90b..fba86ef01c971 100644 --- a/UPGRADE-4.0.md +++ b/UPGRADE-4.0.md @@ -77,6 +77,9 @@ Debug DependencyInjection ------------------- + * Definitions and aliases are now private by default in 4.0. You should either use service injection + or explicitly define your services as public if you really need to inject the container. + * Relying on service auto-registration while autowiring is not supported anymore. Explicitly inject your dependencies or create services whose ids are their fully-qualified class name. @@ -449,14 +452,14 @@ FrameworkBundle * The `Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\TranslatorPass` class has been removed. Use the `Symfony\Component\Translation\DependencyInjection\TranslatorPass` class instead. - + * The `Symfony\Bundle\FrameworkBundle\Translation\TranslationLoader` class has been deprecated and will be removed in 4.0. Use the `Symfony\Component\Translation\Reader\TranslationReader` class instead. * The `translation.loader` service has been removed. Use the `translation.reader` service instead. - + * `AssetsInstallCommand::__construct()` now requires an instance of `Symfony\Component\Filesystem\Filesystem` as first argument. @@ -673,11 +676,11 @@ Translation ----------- * Removed the backup feature from the file dumper classes. - + * The default value of the `$readerServiceId` argument of `TranslatorPass::__construct()` has been changed to `"translation.reader"`. - - * Removed `Symfony\Component\Translation\Writer\TranslationWriter::writeTranslations`, - use `Symfony\Component\Translation\Writer\TranslationWriter::write` instead. + + * Removed `Symfony\Component\Translation\Writer\TranslationWriter::writeTranslations`, + use `Symfony\Component\Translation\Writer\TranslationWriter::write` instead. * Removed support for passing `Symfony\Component\Translation\MessageSelector` as a second argument to the `Translator::__construct()`. You should pass an instance of `Symfony\Component\Translation\Formatter\MessageFormatterInterface` instead. diff --git a/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/Dumper/PhpDumperTest.php b/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/Dumper/PhpDumperTest.php index 62cc3cd38d38f..7c7464133315a 100644 --- a/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/Dumper/PhpDumperTest.php +++ b/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/Dumper/PhpDumperTest.php @@ -61,7 +61,7 @@ private function dumpLazyServiceProjectServiceContainer() { $container = new ContainerBuilder(); - $container->register('foo', 'stdClass'); + $container->register('foo', 'stdClass')->setPublic(true); $container->getDefinition('foo')->setLazy(true); $container->compile(); diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php index f687b71870338..e0d7258902f4d 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php @@ -1012,12 +1012,12 @@ private function registerTemplatingConfiguration(array $config, ContainerBuilder // Use a delegation unless only a single engine was registered if (1 === count($engines)) { - $container->setAlias('templating', (string) reset($engines)); + $container->setAlias('templating', (string) reset($engines))->setPublic(true); } else { foreach ($engines as $engine) { $container->getDefinition('templating.engine.delegating')->addMethodCall('addEngine', array($engine)); } - $container->setAlias('templating', 'templating.engine.delegating'); + $container->setAlias('templating', 'templating.engine.delegating')->setPublic(true); } $container->getDefinition('fragment.renderer.hinclude') @@ -1213,7 +1213,7 @@ private function registerTranslatorConfiguration(array $config, ContainerBuilder $container->getDefinition('translation.writer')->setPrivate(true); // Use the "real" translator instead of the identity default - $container->setAlias('translator', 'translator.default'); + $container->setAlias('translator', 'translator.default')->setPublic(true); $container->setAlias('translator.formatter', new Alias($config['formatter'], false)); $translator = $container->findDefinition('translator.default'); $translator->addMethodCall('setFallbackLocales', array($config['fallbacks'])); diff --git a/src/Symfony/Bundle/FrameworkBundle/Kernel/MicroKernelTrait.php b/src/Symfony/Bundle/FrameworkBundle/Kernel/MicroKernelTrait.php index ef632ca04cc61..a596beafdc4c9 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Kernel/MicroKernelTrait.php +++ b/src/Symfony/Bundle/FrameworkBundle/Kernel/MicroKernelTrait.php @@ -72,6 +72,7 @@ public function registerContainerConfiguration(LoaderInterface $loader) if ($this instanceof EventSubscriberInterface) { $container->register('kernel', static::class) ->setSynthetic(true) + ->setPublic(true) ->addTag('kernel.event_subscriber') ; } diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/AutowiringTypes/config.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/AutowiringTypes/config.yml index a44078cc499b3..1b47c1100a159 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/AutowiringTypes/config.yml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/AutowiringTypes/config.yml @@ -2,6 +2,7 @@ imports: - { resource: ../config/default.yml } services: + _defaults: { public: true } test.autowiring_types.autowired_services: class: Symfony\Bundle\FrameworkBundle\Tests\Functional\Bundle\TestBundle\AutowiringTypes\AutowiredServices autowire: true diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/ContainerDebug/config.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/ContainerDebug/config.yml index f4a5425808440..d00d6f235ec67 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/ContainerDebug/config.yml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/ContainerDebug/config.yml @@ -2,6 +2,7 @@ imports: - { resource: ../config/default.yml } services: + _defaults: { public: true } public: class: Symfony\Bundle\FrameworkBundle\Tests\Fixtures\DeclaredClass private_alias: diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/Serializer/config.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/Serializer/config.yml index fe3de69299946..e4090041bb196 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/Serializer/config.yml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/Serializer/config.yml @@ -2,6 +2,7 @@ imports: - { resource: ../config/default.yml } services: + _defaults: { public: true } test.property_info: '@property_info' framework: diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Kernel/ConcreteMicroKernel.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Kernel/ConcreteMicroKernel.php index 5337050d0e37c..f476945f3da0c 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Kernel/ConcreteMicroKernel.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Kernel/ConcreteMicroKernel.php @@ -82,7 +82,7 @@ protected function configureContainer(ContainerBuilder $c, LoaderInterface $load )); $c->setParameter('halloween', 'Have a great day!'); - $c->register('halloween', 'stdClass'); + $c->register('halloween', 'stdClass')->setPublic(true); } /** diff --git a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php index 95e382b7b4226..21fc056e382f2 100644 --- a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php +++ b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php @@ -185,7 +185,7 @@ private function configureDbalAclProvider(array $config, ContainerBuilder $conta $container->getAlias('security.acl.provider')->setPrivate(true); if (null !== $config['connection']) { - $container->setAlias('security.acl.dbal.connection', sprintf('doctrine.dbal.%s_connection', $config['connection'])); + $container->setAlias('security.acl.dbal.connection', sprintf('doctrine.dbal.%s_connection', $config['connection']))->setPrivate(true); } $container diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/Acl/config.yml b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/Acl/config.yml index 49191e01d85c2..45f8e24d4f81e 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/Acl/config.yml +++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/Acl/config.yml @@ -2,6 +2,7 @@ imports: - { resource: ./../config/framework.yml } services: + _defaults: { public: true } test.security.acl.provider: '@security.acl.provider' doctrine: diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/AutowiringTypes/config.yml b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/AutowiringTypes/config.yml index bb3ef5a2dc70f..2045118e1b9f1 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/AutowiringTypes/config.yml +++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/AutowiringTypes/config.yml @@ -2,6 +2,7 @@ imports: - { resource: ../config/framework.yml } services: + _defaults: { public: true } test.autowiring_types.autowired_services: class: Symfony\Bundle\SecurityBundle\Tests\Functional\Bundle\AutowiringBundle\AutowiredServices autowire: true diff --git a/src/Symfony/Component/Console/DependencyInjection/AddConsoleCommandPass.php b/src/Symfony/Component/Console/DependencyInjection/AddConsoleCommandPass.php index dcc023cb222da..39d53ef8e37d3 100644 --- a/src/Symfony/Component/Console/DependencyInjection/AddConsoleCommandPass.php +++ b/src/Symfony/Component/Console/DependencyInjection/AddConsoleCommandPass.php @@ -65,8 +65,8 @@ public function process(ContainerBuilder $container) if (isset($serviceIds[$commandId]) || $container->hasAlias($commandId)) { $commandId = $commandId.'_'.$id; } - if (!$definition->isPublic()) { - $container->setAlias($commandId, $id); + if (!$definition->isPublic() || $definition->isPrivate()) { + $container->setAlias($commandId, $id)->setPublic(true); $id = $commandId; } $serviceIds[$commandId] = $id; @@ -97,6 +97,7 @@ public function process(ContainerBuilder $container) $container ->register($this->commandLoaderServiceId, ContainerCommandLoader::class) + ->setPublic(true) ->setArguments(array(ServiceLocatorTagPass::register($container, $lazyCommandRefs), $lazyCommandMap)); $container->setParameter('console.command.ids', $serviceIds); diff --git a/src/Symfony/Component/Console/composer.json b/src/Symfony/Component/Console/composer.json index 95164005e7ba5..e9d10e0c7f887 100644 --- a/src/Symfony/Component/Console/composer.json +++ b/src/Symfony/Component/Console/composer.json @@ -23,7 +23,7 @@ "require-dev": { "symfony/config": "~3.3|~4.0", "symfony/event-dispatcher": "~2.8|~3.0|~4.0", - "symfony/dependency-injection": "~3.3|~4.0", + "symfony/dependency-injection": "~3.4|~4.0", "symfony/lock": "~3.4|~4.0", "symfony/process": "~3.3|~4.0", "psr/log": "~1.0" @@ -35,7 +35,7 @@ "psr/log": "For using the console logger" }, "conflict": { - "symfony/dependency-injection": "<3.3", + "symfony/dependency-injection": "<3.4", "symfony/process": "<3.3" }, "autoload": { diff --git a/src/Symfony/Component/DependencyInjection/Alias.php b/src/Symfony/Component/DependencyInjection/Alias.php index ee43bd399f92b..8773b8389110f 100644 --- a/src/Symfony/Component/DependencyInjection/Alias.php +++ b/src/Symfony/Component/DependencyInjection/Alias.php @@ -15,7 +15,7 @@ class Alias { private $id; private $public; - private $private = false; + private $private; /** * @param string $id Alias identifier @@ -25,6 +25,7 @@ public function __construct($id, $public = true) { $this->id = (string) $id; $this->public = $public; + $this->private = 2 > func_num_args(); } /** @@ -47,6 +48,7 @@ public function isPublic() public function setPublic($boolean) { $this->public = (bool) $boolean; + $this->private = false; return $this; } diff --git a/src/Symfony/Component/DependencyInjection/CHANGELOG.md b/src/Symfony/Component/DependencyInjection/CHANGELOG.md index e0cd5dbf6053b..bc8fd3051870c 100644 --- a/src/Symfony/Component/DependencyInjection/CHANGELOG.md +++ b/src/Symfony/Component/DependencyInjection/CHANGELOG.md @@ -4,6 +4,7 @@ CHANGELOG 3.4.0 ----- + * deprecated "public-by-default" definitions and aliases, the new default will be "private" in 4.0 * added `EnvVarProcessorInterface` and corresponding "container.env_var_processor" tag for processing env vars * added support for ignore-on-uninitialized references * deprecated service auto-registration while autowiring diff --git a/src/Symfony/Component/DependencyInjection/Compiler/AutoAliasServicePass.php b/src/Symfony/Component/DependencyInjection/Compiler/AutoAliasServicePass.php index c1f05e03ec02c..03420683a205a 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/AutoAliasServicePass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/AutoAliasServicePass.php @@ -33,7 +33,7 @@ public function process(ContainerBuilder $container) $aliasId = $container->getParameterBag()->resolveValue($tag['format']); if ($container->hasDefinition($aliasId) || $container->hasAlias($aliasId)) { - $container->setAlias($serviceId, new Alias($aliasId)); + $container->setAlias($serviceId, new Alias($aliasId, true)); } } } diff --git a/src/Symfony/Component/DependencyInjection/Compiler/CheckDefinitionValidityPass.php b/src/Symfony/Component/DependencyInjection/Compiler/CheckDefinitionValidityPass.php index 815dbcae4915d..9a7ee4d3520bb 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/CheckDefinitionValidityPass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/CheckDefinitionValidityPass.php @@ -39,7 +39,7 @@ public function process(ContainerBuilder $container) { foreach ($container->getDefinitions() as $id => $definition) { // synthetic service is public - if ($definition->isSynthetic() && (!$definition->isPublic() || $definition->isPrivate())) { + if ($definition->isSynthetic() && !($definition->isPublic() || $definition->isPrivate())) { throw new RuntimeException(sprintf('A synthetic service ("%s") must be public.', $id)); } diff --git a/src/Symfony/Component/DependencyInjection/Compiler/DecoratorServicePass.php b/src/Symfony/Component/DependencyInjection/Compiler/DecoratorServicePass.php index 0e9a68e7f0026..99234812d65ca 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/DecoratorServicePass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/DecoratorServicePass.php @@ -67,7 +67,7 @@ public function process(ContainerBuilder $container) $container->setDefinition($renamedId, $decoratedDefinition); } - $container->setAlias($inner, $id)->setPublic($public && !$private)->setPrivate($private); + $container->setAlias($inner, $id)->setPublic($public)->setPrivate($private); } } } diff --git a/src/Symfony/Component/DependencyInjection/Compiler/RegisterEnvVarProcessorsPass.php b/src/Symfony/Component/DependencyInjection/Compiler/RegisterEnvVarProcessorsPass.php index 247f5b69ad40f..68f2f9a41c134 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/RegisterEnvVarProcessorsPass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/RegisterEnvVarProcessorsPass.php @@ -52,6 +52,7 @@ public function process(ContainerBuilder $container) $bag->setProvidedTypes($types); } $container->register('container.env_var_processors_locator', ServiceLocator::class) + ->setPublic(true) ->setArguments(array($processors)) ; } diff --git a/src/Symfony/Component/DependencyInjection/Compiler/ReplaceAliasByActualDefinitionPass.php b/src/Symfony/Component/DependencyInjection/Compiler/ReplaceAliasByActualDefinitionPass.php index 124bd08b6f92c..bc575e1fc536b 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/ReplaceAliasByActualDefinitionPass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/ReplaceAliasByActualDefinitionPass.php @@ -45,7 +45,7 @@ public function process(ContainerBuilder $container) } // Check if target needs to be replaces if (isset($replacements[$targetId])) { - $container->setAlias($definitionId, $replacements[$targetId]); + $container->setAlias($definitionId, $replacements[$targetId])->setPublic($target->isPublic())->setPrivate($target->isPrivate()); } // No need to process the same target twice if (isset($seenAliasTargets[$targetId])) { diff --git a/src/Symfony/Component/DependencyInjection/Compiler/ResolveChildDefinitionsPass.php b/src/Symfony/Component/DependencyInjection/Compiler/ResolveChildDefinitionsPass.php index 7625377793769..460fb55e472be 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/ResolveChildDefinitionsPass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/ResolveChildDefinitionsPass.php @@ -36,12 +36,14 @@ public function process(ContainerBuilder $container) foreach ($container->getDefinitions() as $definition) { if ($definition->isPrivate()) { $definition->setPublic(false); + $definition->setPrivate(true); } } foreach ($container->getAliases() as $alias) { if ($alias->isPrivate()) { $alias->setPublic(false); + $alias->setPrivate(true); } } } diff --git a/src/Symfony/Component/DependencyInjection/Compiler/ResolveReferencesToAliasesPass.php b/src/Symfony/Component/DependencyInjection/Compiler/ResolveReferencesToAliasesPass.php index 7ab97044bfe7b..a46c74fbb65f1 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/ResolveReferencesToAliasesPass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/ResolveReferencesToAliasesPass.php @@ -32,7 +32,7 @@ public function process(ContainerBuilder $container) foreach ($container->getAliases() as $id => $alias) { $aliasId = (string) $alias; if ($aliasId !== $defId = $this->getDefinitionId($aliasId, $container)) { - $container->setAlias($id, $defId)->setPublic($alias->isPublic() && !$alias->isPrivate())->setPrivate($alias->isPrivate()); + $container->setAlias($id, $defId)->setPublic($alias->isPublic())->setPrivate($alias->isPrivate()); } } } diff --git a/src/Symfony/Component/DependencyInjection/Definition.php b/src/Symfony/Component/DependencyInjection/Definition.php index 7a660eef1d6e0..34d6f46cacca4 100644 --- a/src/Symfony/Component/DependencyInjection/Definition.php +++ b/src/Symfony/Component/DependencyInjection/Definition.php @@ -35,7 +35,7 @@ class Definition private $configurator; private $tags = array(); private $public = true; - private $private = false; + private $private = true; private $synthetic = false; private $abstract = false; private $lazy = false; @@ -603,6 +603,7 @@ public function setPublic($boolean) $this->changes['public'] = true; $this->public = (bool) $boolean; + $this->private = false; return $this; } diff --git a/src/Symfony/Component/DependencyInjection/Dumper/XmlDumper.php b/src/Symfony/Component/DependencyInjection/Dumper/XmlDumper.php index 0631ddaf3ef9f..fb307a76e8ca7 100644 --- a/src/Symfony/Component/DependencyInjection/Dumper/XmlDumper.php +++ b/src/Symfony/Component/DependencyInjection/Dumper/XmlDumper.php @@ -122,8 +122,8 @@ private function addService($definition, $id, \DOMElement $parent) if (!$definition->isShared()) { $service->setAttribute('shared', 'false'); } - if (!$definition->isPublic()) { - $service->setAttribute('public', 'false'); + if (!$definition->isPrivate()) { + $service->setAttribute('public', $definition->isPublic() ? 'true' : 'false'); } if ($definition->isSynthetic()) { $service->setAttribute('synthetic', 'true'); @@ -242,8 +242,8 @@ private function addServiceAlias($alias, Alias $id, \DOMElement $parent) $service = $this->document->createElement('service'); $service->setAttribute('id', $alias); $service->setAttribute('alias', $id); - if (!$id->isPublic()) { - $service->setAttribute('public', 'false'); + if (!$id->isPrivate()) { + $service->setAttribute('public', $id->isPublic() ? 'true' : 'false'); } $parent->appendChild($service); } diff --git a/src/Symfony/Component/DependencyInjection/Dumper/YamlDumper.php b/src/Symfony/Component/DependencyInjection/Dumper/YamlDumper.php index d8f07edc08e5c..916a2317b3893 100644 --- a/src/Symfony/Component/DependencyInjection/Dumper/YamlDumper.php +++ b/src/Symfony/Component/DependencyInjection/Dumper/YamlDumper.php @@ -74,8 +74,8 @@ private function addService($id, $definition) $code .= sprintf(" class: %s\n", $this->dumper->dump($class)); } - if (!$definition->isPublic()) { - $code .= " public: false\n"; + if (!$definition->isPrivate()) { + $code .= sprintf(" public: %s\n", $definition->isPublic() ? 'true' : 'false'); } $tagsCode = ''; @@ -178,11 +178,11 @@ private function addService($id, $definition) */ private function addServiceAlias($alias, $id) { - if ($id->isPublic()) { + if ($id->isPrivate()) { return sprintf(" %s: '@%s'\n", $alias, $id); } - return sprintf(" %s:\n alias: %s\n public: false\n", $alias, $id); + return sprintf(" %s:\n alias: %s\n public: %s\n", $alias, $id, $id->isPublic() ? 'true' : 'false'); } /** diff --git a/src/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php b/src/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php index 4a16d75e36c5c..6bebf2133c57b 100644 --- a/src/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php +++ b/src/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php @@ -203,13 +203,12 @@ private function parseDefinition(\DOMElement $service, $file, array $defaults) if ($alias = $service->getAttribute('alias')) { $this->validateAlias($service, $file); - $public = true; + $this->container->setAlias((string) $service->getAttribute('id'), $alias = new Alias($alias)); if ($publicAttr = $service->getAttribute('public')) { - $public = XmlUtils::phpize($publicAttr); + $alias->setPublic(XmlUtils::phpize($publicAttr)); } elseif (isset($defaults['public'])) { - $public = $defaults['public']; + $alias->setPublic($defaults['public']); } - $this->container->setAlias((string) $service->getAttribute('id'), new Alias($alias, $public)); return; } diff --git a/src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php b/src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php index b57ead2c89015..be0c75b2cac73 100644 --- a/src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php +++ b/src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php @@ -336,8 +336,10 @@ private function parseDefinition($id, $service, $file, array $defaults) @trigger_error(sprintf('Service names that start with an underscore are deprecated since Symfony 3.3 and will be reserved in 4.0. Rename the "%s" service or define it in XML instead.', $id), E_USER_DEPRECATED); } if (is_string($service) && 0 === strpos($service, '@')) { - $public = isset($defaults['public']) ? $defaults['public'] : true; - $this->container->setAlias($id, new Alias(substr($service, 1), $public)); + $this->container->setAlias($id, $alias = new Alias(substr($service, 1))); + if (isset($defaults['public'])) { + $alias->setPublic($defaults['public']); + } return; } @@ -357,8 +359,12 @@ private function parseDefinition($id, $service, $file, array $defaults) $this->checkDefinition($id, $service, $file); if (isset($service['alias'])) { - $public = array_key_exists('public', $service) ? (bool) $service['public'] : (isset($defaults['public']) ? $defaults['public'] : true); - $this->container->setAlias($id, new Alias($service['alias'], $public)); + $this->container->setAlias($id, $alias = new Alias($service['alias'])); + if (array_key_exists('public', $service)) { + $alias->setPublic($service['public']); + } elseif (isset($defaults['public'])) { + $alias->setPublic($defaults['public']); + } foreach ($service as $key => $value) { if (!in_array($key, array('alias', 'public'))) { diff --git a/src/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveChildDefinitionsPassTest.php b/src/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveChildDefinitionsPassTest.php index cb9a879a05d48..c8135b965e80d 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveChildDefinitionsPassTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveChildDefinitionsPassTest.php @@ -402,13 +402,13 @@ public function testPrivateHasHigherPrecedenceThanPublic() $container = new ContainerBuilder(); $container->register('foo', 'stdClass') - ->setPrivate(true) ->setPublic(true) + ->setPrivate(true) ; $container->setAlias('bar', 'foo') - ->setPrivate(false) ->setPublic(false) + ->setPrivate(false) ; $this->process($container); diff --git a/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php b/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php index 4ea8290cfc725..f4c25cd9d2bb1 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php @@ -18,6 +18,7 @@ use Symfony\Component\DependencyInjection\Argument\IteratorArgument; use Symfony\Component\DependencyInjection\Argument\RewindableGenerator; use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument; +use Symfony\Component\DependencyInjection\ChildDefinition; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\ContainerInterface as SymfonyContainerInterface; use Symfony\Component\DependencyInjection\Dumper\PhpDumper; @@ -71,6 +72,7 @@ public function testDumpOptimizationString() 'optimize concatenation from the start' => '%empty_value%start', 'optimize concatenation at the end' => 'end%empty_value%', )); + $definition->setPublic(true); $container = new ContainerBuilder(); $container->setResourceTracking(false); @@ -89,6 +91,7 @@ public function testDumpRelativeDir() $definition->setClass('stdClass'); $definition->addArgument('%foo%'); $definition->addArgument(array('%foo%' => '%buz%/')); + $definition->setPublic(true); $container = new ContainerBuilder(); $container->setDefinition('test', $definition); @@ -151,7 +154,7 @@ public function testAddService() $this->assertStringEqualsFile(self::$fixturesPath.'/php/services9_compiled.php', str_replace(str_replace('\\', '\\\\', self::$fixturesPath.DIRECTORY_SEPARATOR.'includes'.DIRECTORY_SEPARATOR), '%path%', $dumper->dump()), '->dump() dumps services'); $container = new ContainerBuilder(); - $container->register('foo', 'FooClass')->addArgument(new \stdClass()); + $container->register('foo', 'FooClass')->addArgument(new \stdClass())->setPublic(true); $container->compile(); $dumper = new PhpDumper($container); try { @@ -188,8 +191,8 @@ public function testAddServiceIdWithUnsupportedCharacters() { $class = 'Symfony_DI_PhpDumper_Test_Unsupported_Characters'; $container = new ContainerBuilder(); - $container->register('bar$', 'FooClass'); - $container->register('bar$!', 'FooClass'); + $container->register('bar$', 'FooClass')->setPublic(true); + $container->register('bar$!', 'FooClass')->setPublic(true); $container->compile(); $dumper = new PhpDumper($container); eval('?>'.$dumper->dump(array('class' => $class))); @@ -202,8 +205,8 @@ public function testConflictingServiceIds() { $class = 'Symfony_DI_PhpDumper_Test_Conflicting_Service_Ids'; $container = new ContainerBuilder(); - $container->register('foo_bar', 'FooClass'); - $container->register('foobar', 'FooClass'); + $container->register('foo_bar', 'FooClass')->setPublic(true); + $container->register('foobar', 'FooClass')->setPublic(true); $container->compile(); $dumper = new PhpDumper($container); eval('?>'.$dumper->dump(array('class' => $class))); @@ -216,8 +219,8 @@ public function testConflictingMethodsWithParent() { $class = 'Symfony_DI_PhpDumper_Test_Conflicting_Method_With_Parent'; $container = new ContainerBuilder(); - $container->register('bar', 'FooClass'); - $container->register('foo_bar', 'FooClass'); + $container->register('bar', 'FooClass')->setPublic(true); + $container->register('foo_bar', 'FooClass')->setPublic(true); $container->compile(); $dumper = new PhpDumper($container); eval('?>'.$dumper->dump(array( @@ -238,6 +241,7 @@ public function testInvalidFactories($factory) { $container = new ContainerBuilder(); $def = new Definition('stdClass'); + $def->setPublic(true); $def->setFactory($factory); $container->setDefinition('bar', $def); $container->compile(); @@ -319,9 +323,9 @@ public function testOverrideServiceWhenUsingADumpedContainerAndServiceIsUsedFrom public function testCircularReference() { $container = new ContainerBuilder(); - $container->register('foo', 'stdClass')->addArgument(new Reference('bar')); + $container->register('foo', 'stdClass')->addArgument(new Reference('bar'))->setPublic(true); $container->register('bar', 'stdClass')->setPublic(false)->addMethodCall('setA', array(new Reference('baz'))); - $container->register('baz', 'stdClass')->addMethodCall('setA', array(new Reference('foo'))); + $container->register('baz', 'stdClass')->addMethodCall('setA', array(new Reference('foo')))->setPublic(true); $container->compile(); $dumper = new PhpDumper($container); @@ -394,7 +398,7 @@ public function testCustomEnvParameters() $container = new ContainerBuilder(); $container->setParameter('env(foo)', str_rot13('world')); $container->setParameter('hello', '%env(rot13:foo)%'); - $container->register(Rot13EnvVarProcessor::class)->addTag('container.env_var_processor'); + $container->register(Rot13EnvVarProcessor::class)->addTag('container.env_var_processor')->setPublic(true); $container->compile(); $dumper = new PhpDumper($container); @@ -459,7 +463,7 @@ public function testInlinedDefinitionReferencingServiceContainer() { $container = new ContainerBuilder(); $container->register('foo', 'stdClass')->addMethodCall('add', array(new Reference('service_container')))->setPublic(false); - $container->register('bar', 'stdClass')->addArgument(new Reference('foo')); + $container->register('bar', 'stdClass')->addArgument(new Reference('foo'))->setPublic(true); $container->compile(); $dumper = new PhpDumper($container); @@ -471,8 +475,9 @@ public function testInitializePropertiesBeforeMethodCalls() require_once self::$fixturesPath.'/includes/classes.php'; $container = new ContainerBuilder(); - $container->register('foo', 'stdClass'); + $container->register('foo', 'stdClass')->setPublic(true); $container->register('bar', 'MethodCallClass') + ->setPublic(true) ->setProperty('simple', 'bar') ->setProperty('complex', new Reference('foo')) ->addMethodCall('callMe'); @@ -488,8 +493,8 @@ public function testInitializePropertiesBeforeMethodCalls() public function testCircularReferenceAllowanceForLazyServices() { $container = new ContainerBuilder(); - $container->register('foo', 'stdClass')->addArgument(new Reference('bar')); - $container->register('bar', 'stdClass')->setLazy(true)->addArgument(new Reference('foo')); + $container->register('foo', 'stdClass')->addArgument(new Reference('bar'))->setPublic(true); + $container->register('bar', 'stdClass')->setLazy(true)->addArgument(new Reference('foo'))->setPublic(true); $container->compile(); $dumper = new PhpDumper($container); @@ -514,14 +519,16 @@ public function testCircularReferenceAllowanceForInlinedDefinitionsForLazyServic $eventManagerDefinition = new Definition('stdClass'); - $connectionDefinition = $container->register('connection', 'stdClass'); + $connectionDefinition = $container->register('connection', 'stdClass')->setPublic(true); $connectionDefinition->addArgument($eventManagerDefinition); $container->register('entity_manager', 'stdClass') + ->setPublic(true) ->setLazy(true) ->addArgument(new Reference('connection')); $lazyServiceDefinition = $container->register('lazy_service', 'stdClass'); + $lazyServiceDefinition->setPublic(true); $lazyServiceDefinition->setLazy(true); $lazyServiceDefinition->addArgument(new Reference('entity_manager')); @@ -542,9 +549,10 @@ public function testLazyArgumentProvideGenerator() require_once self::$fixturesPath.'/includes/classes.php'; $container = new ContainerBuilder(); - $container->register('lazy_referenced', 'stdClass'); + $container->register('lazy_referenced', 'stdClass')->setPublic(true); $container ->register('lazy_context', 'LazyContext') + ->setPublic(true) ->setArguments(array( new IteratorArgument(array('k1' => new Reference('lazy_referenced'), 'k2' => new Reference('service_container'))), new IteratorArgument(array()), @@ -592,8 +600,8 @@ public function testNormalizedId() public function testDumpContainerBuilderWithFrozenConstructorIncludingPrivateServices() { $container = new ContainerBuilder(); - $container->register('foo_service', 'stdClass')->setArguments(array(new Reference('baz_service'))); - $container->register('bar_service', 'stdClass')->setArguments(array(new Reference('baz_service'))); + $container->register('foo_service', 'stdClass')->setArguments(array(new Reference('baz_service')))->setPublic(true); + $container->register('bar_service', 'stdClass')->setArguments(array(new Reference('baz_service')))->setPublic(true); $container->register('baz_service', 'stdClass')->setPublic(false); $container->compile(); @@ -606,6 +614,7 @@ public function testServiceLocator() { $container = new ContainerBuilder(); $container->register('foo_service', ServiceLocator::class) + ->setPublic(true) ->addArgument(array( 'bar' => new ServiceClosureArgument(new Reference('bar_service')), 'baz' => new ServiceClosureArgument(new TypedReference('baz_service', 'stdClass')), @@ -614,40 +623,43 @@ public function testServiceLocator() ; // no method calls - $container->register('translator.loader_1', 'stdClass'); + $container->register('translator.loader_1', 'stdClass')->setPublic(true); $container->register('translator.loader_1_locator', ServiceLocator::class) ->setPublic(false) ->addArgument(array( 'translator.loader_1' => new ServiceClosureArgument(new Reference('translator.loader_1')), )); $container->register('translator_1', StubbedTranslator::class) + ->setPublic(true) ->addArgument(new Reference('translator.loader_1_locator')); // one method calls - $container->register('translator.loader_2', 'stdClass'); + $container->register('translator.loader_2', 'stdClass')->setPublic(true); $container->register('translator.loader_2_locator', ServiceLocator::class) ->setPublic(false) ->addArgument(array( 'translator.loader_2' => new ServiceClosureArgument(new Reference('translator.loader_2')), )); $container->register('translator_2', StubbedTranslator::class) + ->setPublic(true) ->addArgument(new Reference('translator.loader_2_locator')) ->addMethodCall('addResource', array('db', new Reference('translator.loader_2'), 'nl')); // two method calls - $container->register('translator.loader_3', 'stdClass'); + $container->register('translator.loader_3', 'stdClass')->setPublic(true); $container->register('translator.loader_3_locator', ServiceLocator::class) ->setPublic(false) ->addArgument(array( 'translator.loader_3' => new ServiceClosureArgument(new Reference('translator.loader_3')), )); $container->register('translator_3', StubbedTranslator::class) + ->setPublic(true) ->addArgument(new Reference('translator.loader_3_locator')) ->addMethodCall('addResource', array('db', new Reference('translator.loader_3'), 'nl')) ->addMethodCall('addResource', array('db', new Reference('translator.loader_3'), 'en')); $nil->setValues(array(null)); - $container->register('bar_service', 'stdClass')->setArguments(array(new Reference('baz_service'))); + $container->register('bar_service', 'stdClass')->setArguments(array(new Reference('baz_service')))->setPublic(true); $container->register('baz_service', 'stdClass')->setPublic(false); $container->compile(); @@ -660,6 +672,7 @@ public function testServiceSubscriber() { $container = new ContainerBuilder(); $container->register('foo_service', TestServiceSubscriber::class) + ->setPublic(true) ->setAutowired(true) ->addArgument(new Reference(ContainerInterface::class)) ->addTag('container.service_subscriber', array( @@ -667,7 +680,7 @@ public function testServiceSubscriber() 'id' => TestServiceSubscriber::class, )) ; - $container->register(TestServiceSubscriber::class, TestServiceSubscriber::class); + $container->register(TestServiceSubscriber::class, TestServiceSubscriber::class)->setPublic(true); $container->register(CustomDefinition::class, CustomDefinition::class) ->setPublic(false); @@ -686,6 +699,7 @@ public function testPrivateWithIgnoreOnInvalidReference() $container->register('not_invalid', 'BazClass') ->setPublic(false); $container->register('bar', 'BarClass') + ->setPublic(true) ->addMethodCall('setBaz', array(new Reference('not_invalid', SymfonyContainerInterface::IGNORE_ON_INVALID_REFERENCE))); $container->compile(); @@ -702,6 +716,7 @@ public function testArrayParameters() $container->setParameter('array_1', array(123)); $container->setParameter('array_2', array(__DIR__)); $container->register('bar', 'BarClass') + ->setPublic(true) ->addMethodCall('setBaz', array('%array_1%', '%array_2%', '%%array_1%%', array(123))); $container->compile(); @@ -718,6 +733,7 @@ public function testExpressionReferencingPrivateService() $container->register('private_foo', 'stdClass') ->setPublic(false); $container->register('public_foo', 'stdClass') + ->setPublic(true) ->addArgument(new Expression('service("private_foo")')); $container->compile(); @@ -767,7 +783,7 @@ public function testUninitializedReference() public function testDumpHandlesLiteralClassWithRootNamespace() { $container = new ContainerBuilder(); - $container->register('foo', '\\stdClass'); + $container->register('foo', '\\stdClass')->setPublic(true); $container->compile(); $dumper = new PhpDumper($container); @@ -795,6 +811,9 @@ public function testLegacyPrivateServices() $loader = new YamlFileLoader($container, new FileLocator(self::$fixturesPath.'/yaml')); $loader->load('services_legacy_privates.yml'); + $container->setDefinition('private_child', new ChildDefinition('foo')); + $container->setDefinition('private_parent', new ChildDefinition('private')); + $container->getDefinition('private')->setPrivate(true); $container->getDefinition('private_not_inlined')->setPrivate(true); $container->getDefinition('private_not_removed')->setPrivate(true); diff --git a/src/Symfony/Component/DependencyInjection/Tests/Dumper/XmlDumperTest.php b/src/Symfony/Component/DependencyInjection/Tests/Dumper/XmlDumperTest.php index 8a34a2b19a297..7904ed0c9e6db 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Dumper/XmlDumperTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Dumper/XmlDumperTest.php @@ -57,7 +57,7 @@ public function testAddService() $this->assertEquals(str_replace('%path%', self::$fixturesPath.DIRECTORY_SEPARATOR.'includes'.DIRECTORY_SEPARATOR, file_get_contents(self::$fixturesPath.'/xml/services9.xml')), $dumper->dump(), '->dump() dumps services'); $dumper = new XmlDumper($container = new ContainerBuilder()); - $container->register('foo', 'FooClass')->addArgument(new \stdClass()); + $container->register('foo', 'FooClass')->addArgument(new \stdClass())->setPublic(true); try { $dumper->dump(); $this->fail('->dump() throws a RuntimeException if the container to be dumped has reference to objects or resources'); @@ -75,7 +75,7 @@ public function testDumpAnonymousServices() - + @@ -99,7 +99,7 @@ public function testDumpEntities() - + foo<>&bar @@ -128,7 +128,7 @@ public function provideDecoratedServicesData() - + @@ -138,7 +138,7 @@ public function provideDecoratedServicesData() - + diff --git a/src/Symfony/Component/DependencyInjection/Tests/Dumper/YamlDumperTest.php b/src/Symfony/Component/DependencyInjection/Tests/Dumper/YamlDumperTest.php index 85ce181461419..2a34692c5862d 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Dumper/YamlDumperTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Dumper/YamlDumperTest.php @@ -52,7 +52,7 @@ public function testAddService() $this->assertEqualYamlStructure(str_replace('%path%', self::$fixturesPath.DIRECTORY_SEPARATOR.'includes'.DIRECTORY_SEPARATOR, file_get_contents(self::$fixturesPath.'/yaml/services9.yml')), $dumper->dump(), '->dump() dumps services'); $dumper = new YamlDumper($container = new ContainerBuilder()); - $container->register('foo', 'FooClass')->addArgument(new \stdClass()); + $container->register('foo', 'FooClass')->addArgument(new \stdClass())->setPublic(true); try { $dumper->dump(); $this->fail('->dump() throws a RuntimeException if the container to be dumped has reference to objects or resources'); @@ -85,6 +85,7 @@ public function testInlineServices() { $container = new ContainerBuilder(); $container->register('foo', 'Class1') + ->setPublic(true) ->addArgument((new Definition('Class2')) ->addArgument(new Definition('Class2')) ) diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container10.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container10.php index a16ca9fff87d8..4f5492ad5a843 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container10.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container10.php @@ -9,6 +9,7 @@ $container-> register('foo', 'FooClass')-> addArgument(new Reference('bar')) + ->setPublic(true) ; return $container; diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container11.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container11.php index 3e6cafca24f90..150cd7921ee1b 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container11.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container11.php @@ -7,6 +7,7 @@ $container-> register('foo', 'FooClass')-> addArgument(new Definition('BarClass', array(new Definition('BazClass')))) + ->setPublic(true) ; return $container; diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container12.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container12.php index 73c5b4ef176e2..bc527eb79e78d 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container12.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container12.php @@ -7,6 +7,7 @@ register('foo', 'FooClass\\Foo')-> addArgument('foo<>&bar')-> addTag('foo"bar\\bar', array('foo' => 'foo"barřž€')) + ->setPublic(true) ; return $container; diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container13.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container13.php index cc716c78f04f5..df598d4ea5fae 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container13.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container13.php @@ -7,9 +7,11 @@ $container-> register('foo', 'FooClass')-> addArgument(new Reference('bar')) + ->setPublic(true) ; $container-> register('bar', 'BarClass') + ->setPublic(true) ; $container->compile(); diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container15.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container15.php index bb41ea3c4f175..7949247558f34 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container15.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container15.php @@ -6,6 +6,7 @@ $container ->register('foo', 'FooClass\\Foo') ->setDecoratedService('bar', 'bar.woozy') + ->setPublic(true) ; return $container; diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container16.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container16.php index 67b4d353db4d2..88619ec50e267 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container16.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container16.php @@ -6,6 +6,7 @@ $container ->register('foo', 'FooClass\\Foo') ->setDecoratedService('bar') + ->setPublic(true) ; return $container; diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container17.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container17.php index d902ec2a39306..7f1db6762981e 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container17.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container17.php @@ -5,6 +5,7 @@ $container = new ContainerBuilder(); $container ->register('foo', '%foo.class%') + ->setPublic(true) ; return $container; diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container19.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container19.php index 64b8f066dca10..823a77f534f52 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container19.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container19.php @@ -10,6 +10,7 @@ $container ->register('service_from_anonymous_factory', 'Bar\FooClass') ->setFactory(array(new Definition('Bar\FooClass'), 'getInstance')) + ->setPublic(true) ; $anonymousServiceWithFactory = new Definition('Bar\FooClass'); @@ -17,6 +18,7 @@ $container ->register('service_with_method_call_and_factory', 'Bar\FooClass') ->addMethodCall('setBar', array($anonymousServiceWithFactory)) + ->setPublic(true) ; return $container; diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container21.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container21.php index d0467386140a9..298c9266a9e2b 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container21.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container21.php @@ -15,6 +15,7 @@ ->register('foo', 'Foo') ->setFactory(array($fooFactory, 'createFoo')) ->setConfigurator(array($bar, 'configureFoo')) + ->setPublic(true) ; return $container; diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container24.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container24.php index cba10b526b2a8..b9d0b91f10eb8 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container24.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container24.php @@ -7,6 +7,7 @@ $container ->register('foo', 'Foo') ->setAutowired(true) + ->setPublic(true) ; return $container; diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container33.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container33.php index ec68f929d449e..673abe204cd9e 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container33.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container33.php @@ -6,7 +6,7 @@ $container = new ContainerBuilder(); -$container->register(\Foo\Foo::class); -$container->register(\Bar\Foo::class); +$container->register(\Foo\Foo::class)->setPublic(true); +$container->register(\Bar\Foo::class)->setPublic(true); return $container; diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container9.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container9.php index 2906004828a59..91a9af43d9a1f 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container9.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container9.php @@ -21,21 +21,25 @@ ->addMethodCall('setBar', array(new Reference('bar'))) ->addMethodCall('initialize') ->setConfigurator('sc_configure') + ->setPublic(true) ; $container ->register('foo.baz', '%baz_class%') ->setFactory(array('%baz_class%', 'getInstance')) ->setConfigurator(array('%baz_class%', 'configureStatic1')) + ->setPublic(true) ; $container ->register('bar', 'Bar\FooClass') ->setArguments(array('foo', new Reference('foo.baz'), new Parameter('foo_bar'))) ->setConfigurator(array(new Reference('foo.baz'), 'configure')) + ->setPublic(true) ; $container ->register('foo_bar', '%foo_class%') ->addArgument(new Reference('deprecated_service')) ->setShared(false) + ->setPublic(true) ; $container->getParameterBag()->clear(); $container->getParameterBag()->add(array( @@ -43,8 +47,8 @@ 'foo_class' => 'Bar\FooClass', 'foo' => 'bar', )); -$container->setAlias('alias_for_foo', 'foo'); -$container->setAlias('alias_for_alias', 'alias_for_foo'); +$container->setAlias('alias_for_foo', 'foo')->setPublic(true); +$container->setAlias('alias_for_alias', 'alias_for_foo')->setPublic(true); $container ->register('method_call1', 'Bar\FooClass') ->setFile(realpath(__DIR__.'/../includes/foo.php')) @@ -53,10 +57,12 @@ ->addMethodCall('setBar', array(new Reference('foo3', ContainerInterface::IGNORE_ON_INVALID_REFERENCE))) ->addMethodCall('setBar', array(new Reference('foobaz', ContainerInterface::IGNORE_ON_INVALID_REFERENCE))) ->addMethodCall('setBar', array(new Expression('service("foo").foo() ~ (container.hasParameter("foo") ? parameter("foo") : "default")'))) + ->setPublic(true) ; $container ->register('foo_with_inline', 'Foo') ->addMethodCall('setBar', array(new Reference('inlined'))) + ->setPublic(true) ; $container ->register('inlined', 'Bar') @@ -67,10 +73,12 @@ $container ->register('baz', 'Baz') ->addMethodCall('setFoo', array(new Reference('foo_with_inline'))) + ->setPublic(true) ; $container ->register('request', 'Request') ->setSynthetic(true) + ->setPublic(true) ; $container ->register('configurator_service', 'ConfClass') @@ -80,6 +88,7 @@ $container ->register('configured_service', 'stdClass') ->setConfigurator(array(new Reference('configurator_service'), 'configureStdClass')) + ->setPublic(true) ; $container ->register('configurator_service_simple', 'ConfClass') @@ -89,21 +98,26 @@ $container ->register('configured_service_simple', 'stdClass') ->setConfigurator(array(new Reference('configurator_service_simple'), 'configureStdClass')) + ->setPublic(true) ; $container ->register('decorated', 'stdClass') + ->setPublic(true) ; $container ->register('decorator_service', 'stdClass') ->setDecoratedService('decorated') + ->setPublic(true) ; $container ->register('decorator_service_with_name', 'stdClass') ->setDecoratedService('decorated', 'decorated.pif-pouf') + ->setPublic(true) ; $container ->register('deprecated_service', 'stdClass') ->setDeprecated(true) + ->setPublic(true) ; $container ->register('new_factory', 'FactoryClass') @@ -113,15 +127,18 @@ $container ->register('factory_service', 'Bar') ->setFactory(array(new Reference('foo.baz'), 'getInstance')) + ->setPublic(true) ; $container ->register('new_factory_service', 'FooBarBaz') ->setProperty('foo', 'bar') ->setFactory(array(new Reference('new_factory'), 'getInstance')) + ->setPublic(true) ; $container ->register('service_from_static_method', 'Bar\FooClass') ->setFactory(array('Bar\FooClass', 'getInstance')) + ->setPublic(true) ; $container ->register('factory_simple', 'SimpleFactoryClass') @@ -132,14 +149,17 @@ $container ->register('factory_service_simple', 'Bar') ->setFactory(array(new Reference('factory_simple'), 'getInstance')) + ->setPublic(true) ; $container ->register('lazy_context', 'LazyContext') ->setArguments(array(new IteratorArgument(array('k1' => new Reference('foo.baz'), 'k2' => new Reference('service_container'))), new IteratorArgument(array()))) + ->setPublic(true) ; $container ->register('lazy_context_ignore_invalid_ref', 'LazyContext') ->setArguments(array(new IteratorArgument(array(new Reference('foo.baz'), new Reference('invalid', ContainerInterface::IGNORE_ON_INVALID_REFERENCE))), new IteratorArgument(array()))) + ->setPublic(true) ; return $container; diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container_abstract.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container_abstract.php index 9622a273d3806..308e22524132f 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container_abstract.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container_abstract.php @@ -7,6 +7,7 @@ $container ->register('foo', 'Foo') ->setAbstract(true) + ->setPublic(true) ; return $container; diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container_uninitialized_ref.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container_uninitialized_ref.php index 9ecf7c909f04a..7aeefb4d5227f 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container_uninitialized_ref.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container_uninitialized_ref.php @@ -9,6 +9,7 @@ $container ->register('foo1', 'stdClass') + ->setPublic(true) ; $container @@ -24,6 +25,7 @@ $container ->register('baz', 'stdClass') ->setProperty('foo3', new Reference('foo3')) + ->setPublic(true) ; $container @@ -41,6 +43,7 @@ 'foo2' => new Reference('foo2', $container::IGNORE_ON_UNINITIALIZED_REFERENCE), 'foo3' => new Reference('foo3', $container::IGNORE_ON_UNINITIALIZED_REFERENCE), ))) + ->setPublic(true) ; return $container; diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services1-1.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services1-1.php index 44631328ce606..d87e61e14aa19 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services1-1.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services1-1.php @@ -29,6 +29,9 @@ class Container extends AbstractContainer public function __construct() { $this->services = array(); + $this->privates = array( + 'service_container' => true, + ); $this->aliases = array(); } diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services1.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services1.php index 9ad021ece802b..69fc82e056966 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services1.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services1.php @@ -27,6 +27,9 @@ class ProjectServiceContainer extends Container public function __construct() { $this->services = array(); + $this->privates = array( + 'service_container' => true, + ); $this->aliases = array(); } diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services10.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services10.php index d8478d677f4ff..26c73706168d3 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services10.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services10.php @@ -32,6 +32,9 @@ public function __construct() $this->methodMap = array( 'test' => 'getTestService', ); + $this->privates = array( + 'service_container' => true, + ); $this->aliases = array(); } diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services12.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services12.php index 976c720768752..65891c77b994d 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services12.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services12.php @@ -36,6 +36,9 @@ public function __construct() $this->methodMap = array( 'test' => 'getTestService', ); + $this->privates = array( + 'service_container' => true, + ); $this->aliases = array(); } diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services13.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services13.php index 42b9e78963662..1525115f5b74a 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services13.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services13.php @@ -30,6 +30,9 @@ public function __construct() $this->methodMap = array( 'bar' => 'getBarService', ); + $this->privates = array( + 'service_container' => true, + ); $this->aliases = array(); } diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services19.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services19.php index 3af42c502c0b4..44822ac27d8b0 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services19.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services19.php @@ -31,6 +31,9 @@ public function __construct() 'service_from_anonymous_factory' => 'getServiceFromAnonymousFactoryService', 'service_with_method_call_and_factory' => 'getServiceWithMethodCallAndFactoryService', ); + $this->privates = array( + 'service_container' => true, + ); $this->aliases = array(); } diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services24.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services24.php index 116972d25b8fc..8fbfc408caa4c 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services24.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services24.php @@ -30,6 +30,9 @@ public function __construct() $this->methodMap = array( 'foo' => 'getFooService', ); + $this->privates = array( + 'service_container' => true, + ); $this->aliases = array(); } diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services26.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services26.php index 3a38cff1a1539..d3349f02b3007 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services26.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services26.php @@ -36,6 +36,9 @@ public function __construct() $this->methodMap = array( 'test' => 'getTestService', ); + $this->privates = array( + 'service_container' => true, + ); $this->aliases = array(); } diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services33.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services33.php index 20eda55d99e0f..327d9e1c4136c 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services33.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services33.php @@ -35,6 +35,9 @@ public function __construct() 'Bar\\Foo' => 'getFooService', 'Foo\\Foo' => 'getFoo2Service', ); + $this->privates = array( + 'service_container' => true, + ); $this->aliases = array(); } diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services8.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services8.php index 1689a9658668a..f46835ef9dfc1 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services8.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services8.php @@ -29,6 +29,9 @@ public function __construct() $this->parameters = $this->getDefaultParameters(); $this->services = array(); + $this->privates = array( + 'service_container' => true, + ); $this->aliases = array(); } diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_as_files.txt b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_as_files.txt index 059f0912815ca..0af1392afd0f6 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_as_files.txt +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_as_files.txt @@ -295,6 +295,7 @@ class Container%s extends Container ); $this->privates = array( 'factory_simple' => true, + 'service_container' => true, ); $this->aliases = array( 'alias_for_alias' => 'foo', diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_compiled.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_compiled.php index 103bb0de34d88..3478d54ec52be 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_compiled.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_compiled.php @@ -52,6 +52,7 @@ public function __construct() ); $this->privates = array( 'factory_simple' => true, + 'service_container' => true, ); $this->aliases = array( 'alias_for_alias' => 'foo', diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_array_params.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_array_params.php index d848941013388..872b5179532b6 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_array_params.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_array_params.php @@ -36,6 +36,9 @@ public function __construct() $this->methodMap = array( 'bar' => 'getBarService', ); + $this->privates = array( + 'service_container' => true, + ); $this->aliases = array(); } diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_base64_env.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_base64_env.php index 4f4c7e79df38b..8ebd8f0580c58 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_base64_env.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_base64_env.php @@ -29,6 +29,9 @@ public function __construct() $this->parameters = $this->getDefaultParameters(); $this->services = array(); + $this->privates = array( + 'service_container' => true, + ); $this->aliases = array(); } diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_legacy_privates.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_legacy_privates.php index 70e781bdfd9e9..aa154e2c435aa 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_legacy_privates.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_legacy_privates.php @@ -38,7 +38,6 @@ public function __construct() 'private_alias_decorator' => 'getPrivateAliasDecoratorService', 'private_child' => 'getPrivateChildService', 'private_decorator' => 'getPrivateDecoratorService', - 'private_decorator.inner' => 'getPrivateDecorator_InnerService', 'private_not_inlined' => 'getPrivateNotInlinedService', 'private_not_removed' => 'getPrivateNotRemovedService', 'private_parent' => 'getPrivateParentService', @@ -50,10 +49,10 @@ public function __construct() 'private' => true, 'private_alias' => true, 'private_child' => true, - 'private_decorator.inner' => true, 'private_not_inlined' => true, 'private_not_removed' => true, 'private_parent' => true, + 'service_container' => true, ); $this->aliases = array( 'alias_to_private' => 'private', @@ -158,16 +157,6 @@ protected function getPrivateChildService() return $this->services['private_child'] = new \stdClass(); } - /** - * Gets the private 'private_decorator.inner' shared service. - * - * @return \stdClass - */ - protected function getPrivateDecorator_InnerService() - { - return $this->services['private_decorator.inner'] = new \stdClass(); - } - /** * Gets the private 'private_not_inlined' shared service. * diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_locator.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_locator.php index 751ad8e4fa454..fb2bbbcde8a5a 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_locator.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_locator.php @@ -40,6 +40,7 @@ public function __construct() ); $this->privates = array( 'baz_service' => true, + 'service_container' => true, ); $this->aliases = array(); diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_private_frozen.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_private_frozen.php index a6717fd6abf8f..6c24edc01801c 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_private_frozen.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_private_frozen.php @@ -34,6 +34,7 @@ public function __construct() ); $this->privates = array( 'baz_service' => true, + 'service_container' => true, ); $this->aliases = array(); diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_private_in_expression.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_private_in_expression.php index e5129d4f36566..121951a26f998 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_private_in_expression.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_private_in_expression.php @@ -33,6 +33,7 @@ public function __construct() ); $this->privates = array( 'private_foo' => true, + 'service_container' => true, ); $this->aliases = array(); diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_rot13_env.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_rot13_env.php index 2e08cdcb42f92..22496e69a4dce 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_rot13_env.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_rot13_env.php @@ -36,6 +36,9 @@ public function __construct() 'Symfony\\Component\\DependencyInjection\\Tests\\Dumper\\Rot13EnvVarProcessor' => 'getRot13EnvVarProcessorService', 'container.env_var_processors_locator' => 'getContainer_EnvVarProcessorsLocatorService', ); + $this->privates = array( + 'service_container' => true, + ); $this->aliases = array(); } diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_subscriber.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_subscriber.php index 3d7cc80336831..21fcf03c1efe3 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_subscriber.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_subscriber.php @@ -38,6 +38,7 @@ public function __construct() ); $this->privates = array( 'Symfony\\Component\\DependencyInjection\\Tests\\Fixtures\\CustomDefinition' => true, + 'service_container' => true, ); $this->aliases = array(); diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_uninitialized_ref.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_uninitialized_ref.php index 4c26d58d70c28..5a2990e303840 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_uninitialized_ref.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_uninitialized_ref.php @@ -35,6 +35,7 @@ public function __construct() ); $this->privates = array( 'foo3' => true, + 'service_container' => true, ); $this->aliases = array(); diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services21.xml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services21.xml index 2ed88fee5a0d4..34fd11ef097c2 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services21.xml +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services21.xml @@ -2,7 +2,7 @@ - + diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services24.xml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services24.xml index c4e32cb634e0c..7183435842f13 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services24.xml +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services24.xml @@ -2,7 +2,7 @@ - + diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services9.xml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services9.xml index c7884fb11d6ab..59fa6b102ab42 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services9.xml +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services9.xml @@ -7,7 +7,7 @@ - + foo @@ -31,20 +31,20 @@ - + - + foo %foo_bar% - + - + %path%foo.php @@ -62,7 +62,7 @@ service("foo").foo() ~ (container.hasParameter("foo") ? parameter("foo") : "default") - + @@ -73,60 +73,60 @@ - + - + - + bar - + - - - - + + + + The "%service_id%" service is deprecated. You should stop using it, as it will soon be removed. bar - + - + bar - + foo The "%service_id%" service is deprecated. You should stop using it, as it will soon be removed. - + - + - + @@ -135,7 +135,7 @@ - - + + diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services_abstract.xml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services_abstract.xml index 334e8b045f237..bf9e07e5b083c 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services_abstract.xml +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services_abstract.xml @@ -2,7 +2,7 @@ - + diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services_without_id.xml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services_without_id.xml index afabf3d891d39..bc0f719bd5330 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services_without_id.xml +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services_without_id.xml @@ -1,6 +1,7 @@ + diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services24.yml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services24.yml index afed157017f4d..5faf830410afc 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services24.yml +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services24.yml @@ -5,6 +5,7 @@ services: synthetic: true foo: class: Foo + public: true autowire: true Psr\Container\ContainerInterface: alias: service_container diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services26.yml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services26.yml index d573e810dbe23..aa44b4d77a941 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services26.yml +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services26.yml @@ -9,6 +9,7 @@ parameters: services: test: + public: true class: '%env(FOO)%' arguments: - '%env(Bar)%' diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services9.yml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services9.yml index 01b67d78ac553..1744611a1a7e0 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services9.yml +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services9.yml @@ -20,18 +20,22 @@ services: factory: [Bar\FooClass, getInstance] configurator: sc_configure + public: true foo.baz: class: '%baz_class%' factory: ['%baz_class%', getInstance] configurator: ['%baz_class%', configureStatic1] + public: true bar: class: Bar\FooClass arguments: [foo, '@foo.baz', '%foo_bar%'] configurator: ['@foo.baz', configure] + public: true foo_bar: class: '%foo_class%' shared: false arguments: ['@deprecated_service'] + public: true method_call1: class: Bar\FooClass file: '%path%foo.php' @@ -41,11 +45,13 @@ services: - [setBar, ['@?foo3']] - [setBar, ['@?foobaz']] - [setBar, ['@=service("foo").foo() ~ (container.hasParameter("foo") ? parameter("foo") : "default")']] + public: true foo_with_inline: class: Foo calls: - [setBar, ['@inlined']] + public: true inlined: class: Bar @@ -58,10 +64,12 @@ services: class: Baz calls: - [setFoo, ['@foo_with_inline']] + public: true request: class: Request synthetic: true + public: true configurator_service: class: ConfClass public: false @@ -71,6 +79,7 @@ services: configured_service: class: stdClass configurator: ['@configurator_service', configureStdClass] + public: true configurator_service_simple: class: ConfClass public: false @@ -78,18 +87,23 @@ services: configured_service_simple: class: stdClass configurator: ['@configurator_service_simple', configureStdClass] + public: true decorated: class: stdClass + public: true decorator_service: class: stdClass decorates: decorated + public: true decorator_service_with_name: class: stdClass decorates: decorated decoration_inner_name: decorated.pif-pouf + public: true deprecated_service: class: stdClass deprecated: The "%service_id%" service is deprecated. You should stop using it, as it will soon be removed. + public: true new_factory: class: FactoryClass public: false @@ -97,13 +111,16 @@ services: factory_service: class: Bar factory: ['@foo.baz', getInstance] + public: true new_factory_service: class: FooBarBaz properties: { foo: bar } factory: ['@new_factory', getInstance] + public: true service_from_static_method: class: Bar\FooClass factory: [Bar\FooClass, getInstance] + public: true factory_simple: class: SimpleFactoryClass deprecated: The "%service_id%" service is deprecated. You should stop using it, as it will soon be removed. @@ -112,14 +129,21 @@ services: factory_service_simple: class: Bar factory: ['@factory_simple', getInstance] + public: true lazy_context: class: LazyContext arguments: [!iterator {'k1': '@foo.baz', 'k2': '@service_container'}, !iterator []] + public: true lazy_context_ignore_invalid_ref: class: LazyContext arguments: [!iterator ['@foo.baz', '@?invalid'], !iterator []] - alias_for_foo: '@foo' - alias_for_alias: '@foo' + public: true + alias_for_foo: + alias: 'foo' + public: true + alias_for_alias: + alias: 'foo' + public: true Psr\Container\ContainerInterface: alias: service_container public: false diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services_inline.yml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services_inline.yml index 14adedf32dde0..15d78b50a7725 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services_inline.yml +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services_inline.yml @@ -5,6 +5,7 @@ services: synthetic: true foo: class: Class1 + public: true arguments: [!service { class: Class2, arguments: [!service { class: Class2 }] }] Psr\Container\ContainerInterface: alias: service_container diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services_legacy_privates.yml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services_legacy_privates.yml index ac54a57dff013..0fd20446e7964 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services_legacy_privates.yml +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services_legacy_privates.yml @@ -1,4 +1,5 @@ services: + _defaults: {public: true} foo: {class: stdClass, public: false} @@ -23,6 +24,4 @@ services: private_not_inlined: {class: stdClass, public: false} private_not_removed: {class: stdClass, public: false} - private_child: {parent: foo} - private_parent: {parent: private} public_child: {parent: private, public: true} diff --git a/src/Symfony/Component/DependencyInjection/Tests/Loader/XmlFileLoaderTest.php b/src/Symfony/Component/DependencyInjection/Tests/Loader/XmlFileLoaderTest.php index 8f6467c05eb76..a30567a2546e6 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Loader/XmlFileLoaderTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Loader/XmlFileLoaderTest.php @@ -234,7 +234,7 @@ public function testLoadAnonymousServices() /** * @group legacy - * @expectedDeprecation Top-level anonymous services are deprecated since Symfony 3.4, the "id" attribute will be required in version 4.0 in %sservices_without_id.xml at line 4. + * @expectedDeprecation Top-level anonymous services are deprecated since Symfony 3.4, the "id" attribute will be required in version 4.0 in %sservices_without_id.xml at line 5. */ public function testLoadAnonymousServicesWithoutId() { From 1db99f316d67db6a344777b125cc88bbcaf1829e Mon Sep 17 00:00:00 2001 From: Kevin Verschaeve Date: Tue, 19 Sep 2017 12:46:10 +0200 Subject: [PATCH 0856/1099] [TwigBundle] Break long lines in exceptions --- .../Bundle/TwigBundle/Resources/views/Exception/trace.html.twig | 2 +- .../Bundle/TwigBundle/Resources/views/exception.css.twig | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Bundle/TwigBundle/Resources/views/Exception/trace.html.twig b/src/Symfony/Bundle/TwigBundle/Resources/views/Exception/trace.html.twig index 1d8125a38f84b..4e6c85a420bff 100644 --- a/src/Symfony/Bundle/TwigBundle/Resources/views/Exception/trace.html.twig +++ b/src/Symfony/Bundle/TwigBundle/Resources/views/Exception/trace.html.twig @@ -1,4 +1,4 @@ -
+
{% if trace.file|default(false) %} {{ include('@Twig/images/icon-minus-square.svg') }} {{ include('@Twig/images/icon-plus-square.svg') }} diff --git a/src/Symfony/Bundle/TwigBundle/Resources/views/exception.css.twig b/src/Symfony/Bundle/TwigBundle/Resources/views/exception.css.twig index 9f12edece1e71..87a60d4197072 100644 --- a/src/Symfony/Bundle/TwigBundle/Resources/views/exception.css.twig +++ b/src/Symfony/Bundle/TwigBundle/Resources/views/exception.css.twig @@ -105,7 +105,7 @@ header .container { display: flex; justify-content: space-between; } .trace-line a { color: #222; } .trace-line .icon { opacity: .4; position: absolute; left: 10px; top: 11px; } .trace-line .icon svg { height: 16px; width: 16px; } -.trace-line-header { padding-left: 36px; } +.trace-line-header { padding-left: 36px; padding-right: 10px; } .trace-file-path, .trace-file-path a { color: #222; font-size: 13px; } .trace-class { color: #B0413E; } From f13081d12c7fe27da12db5d079cf42826af39403 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Haso=C5=88?= Date: Tue, 19 Sep 2017 13:52:15 +0200 Subject: [PATCH 0857/1099] [Form] Fix phpdoc --- src/Symfony/Component/Form/FormConfigInterface.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/Form/FormConfigInterface.php b/src/Symfony/Component/Form/FormConfigInterface.php index 47a2ac35a89a5..e66570cf5f1e6 100644 --- a/src/Symfony/Component/Form/FormConfigInterface.php +++ b/src/Symfony/Component/Form/FormConfigInterface.php @@ -167,7 +167,7 @@ public function getData(); /** * Returns the class of the form data or null if the data is scalar or an array. * - * @return string The data class or null + * @return null|string The data class or null */ public function getDataClass(); From e2d4904a843652b4d43e570fcde9d8cfbb8d7658 Mon Sep 17 00:00:00 2001 From: Yonel Ceruto Date: Fri, 15 Sep 2017 10:30:52 -0400 Subject: [PATCH 0858/1099] Render all line breaks according to the exception message --- src/Symfony/Component/Console/Application.php | 7 +++---- .../Component/Console/Tests/ApplicationTest.php | 16 ++++++++++++++++ .../application_renderexception_linebreaks.txt | 11 +++++++++++ 3 files changed, 30 insertions(+), 4 deletions(-) create mode 100644 src/Symfony/Component/Console/Tests/Fixtures/application_renderexception_linebreaks.txt diff --git a/src/Symfony/Component/Console/Application.php b/src/Symfony/Component/Console/Application.php index 21b2e8ea5c40a..37f3dc4885118 100644 --- a/src/Symfony/Component/Console/Application.php +++ b/src/Symfony/Component/Console/Application.php @@ -681,7 +681,7 @@ public function renderException($e, $output) $width = 1 << 31; } $lines = array(); - foreach (preg_split('/\r?\n/', $e->getMessage()) as $line) { + foreach (preg_split('/\r?\n/', trim($e->getMessage())) as $line) { foreach ($this->splitStringByWidth($line, $width - 4) as $line) { // pre-format lines to get the right string length $lineLength = Helper::strlen($line) + 4; @@ -1133,9 +1133,8 @@ private function splitStringByWidth($string, $width) $lines[] = str_pad($line, $width); $line = $char; } - if ('' !== $line) { - $lines[] = count($lines) ? str_pad($line, $width) : $line; - } + + $lines[] = count($lines) ? str_pad($line, $width) : $line; mb_convert_variables($encoding, 'utf8', $lines); diff --git a/src/Symfony/Component/Console/Tests/ApplicationTest.php b/src/Symfony/Component/Console/Tests/ApplicationTest.php index af92f6c4ba579..8ffc5d695174b 100644 --- a/src/Symfony/Component/Console/Tests/ApplicationTest.php +++ b/src/Symfony/Component/Console/Tests/ApplicationTest.php @@ -608,6 +608,22 @@ public function testRenderExceptionEscapesLines() $this->assertStringEqualsFile(self::$fixturesPath.'/application_renderexception_escapeslines.txt', $tester->getDisplay(true), '->renderException() escapes lines containing formatting'); } + public function testRenderExceptionLineBreaks() + { + $application = $this->getMockBuilder('Symfony\Component\Console\Application')->setMethods(array('getTerminalWidth'))->getMock(); + $application->setAutoExit(false); + $application->expects($this->any()) + ->method('getTerminalWidth') + ->will($this->returnValue(120)); + $application->register('foo')->setCode(function () { + throw new \InvalidArgumentException("\n\nline 1 with extra spaces \nline 2\n\nline 4\n"); + }); + $tester = new ApplicationTester($application); + + $tester->run(array('command' => 'foo'), array('decorated' => false)); + $this->assertStringEqualsFile(self::$fixturesPath.'/application_renderexception_linebreaks.txt', $tester->getDisplay(true), '->renderException() keep multiple line breaks'); + } + public function testRun() { $application = new Application(); diff --git a/src/Symfony/Component/Console/Tests/Fixtures/application_renderexception_linebreaks.txt b/src/Symfony/Component/Console/Tests/Fixtures/application_renderexception_linebreaks.txt new file mode 100644 index 0000000000000..e9a9518b4aead --- /dev/null +++ b/src/Symfony/Component/Console/Tests/Fixtures/application_renderexception_linebreaks.txt @@ -0,0 +1,11 @@ + + + [InvalidArgumentException] + line 1 with extra spaces + line 2 + + line 4 + + +foo + From ff2ab5831a9fcaf2847e3dc48afd97c52a026165 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Tue, 19 Sep 2017 22:53:21 +0200 Subject: [PATCH 0859/1099] [DI] Fix private-by-default BC layer --- .../Tests/LazyProxy/ContainerBuilderTest.php | 2 +- .../FrameworkExtensionTest.php | 1 + .../WebProfilerExtensionTest.php | 14 +++++--- .../DependencyInjection/ChildDefinition.php | 1 + .../Compiler/RemoveUnusedDefinitionsPass.php | 2 +- .../DependencyInjection/ContainerBuilder.php | 30 ++++++++++++---- .../Loader/XmlFileLoader.php | 6 +--- .../Tests/ContainerBuilderTest.php | 34 ++++++++++++------- .../Tests/Dumper/XmlDumperTest.php | 8 ++--- .../Tests/Fixtures/php/services1-1.php | 3 -- .../Tests/Fixtures/php/services1.php | 3 -- .../Tests/Fixtures/php/services10.php | 3 -- .../Tests/Fixtures/php/services12.php | 3 -- .../Tests/Fixtures/php/services13.php | 3 -- .../Tests/Fixtures/php/services19.php | 3 -- .../Tests/Fixtures/php/services24.php | 3 -- .../Tests/Fixtures/php/services26.php | 3 -- .../Tests/Fixtures/php/services33.php | 3 -- .../Tests/Fixtures/php/services8.php | 3 -- .../Tests/Fixtures/php/services9_as_files.txt | 1 - .../Tests/Fixtures/php/services9_compiled.php | 1 - .../Fixtures/php/services_array_params.php | 3 -- .../Fixtures/php/services_base64_env.php | 3 -- .../Fixtures/php/services_legacy_privates.php | 1 - .../Tests/Fixtures/php/services_locator.php | 1 - .../Fixtures/php/services_private_frozen.php | 1 - .../php/services_private_in_expression.php | 1 - .../Tests/Fixtures/php/services_rot13_env.php | 3 -- .../Fixtures/php/services_subscriber.php | 1 - .../php/services_uninitialized_ref.php | 1 - .../Tests/Fixtures/xml/services1.xml | 2 +- .../Tests/Fixtures/xml/services21.xml | 2 +- .../Tests/Fixtures/xml/services24.xml | 2 +- .../Tests/Fixtures/xml/services8.xml | 2 +- .../Tests/Fixtures/xml/services9.xml | 2 +- .../Tests/Fixtures/xml/services_abstract.xml | 2 +- .../Tests/Fixtures/xml/services_dump_load.xml | 2 +- .../Tests/Fixtures/yaml/services1.yml | 1 + .../Tests/Fixtures/yaml/services24.yml | 1 + .../Tests/Fixtures/yaml/services8.yml | 1 + .../Tests/Fixtures/yaml/services9.yml | 1 + .../Tests/Fixtures/yaml/services_inline.yml | 1 + .../DependencyInjection/FormPassTest.php | 15 ++++---- .../ResettableServicePassTest.php | 3 ++ .../ServiceResetListenerTest.php | 5 +-- .../Component/HttpKernel/Tests/KernelTest.php | 2 +- 46 files changed, 91 insertions(+), 98 deletions(-) diff --git a/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/ContainerBuilderTest.php b/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/ContainerBuilderTest.php index 858e9d76b64c9..fc5af78fac182 100644 --- a/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/ContainerBuilderTest.php +++ b/src/Symfony/Bridge/ProxyManager/Tests/LazyProxy/ContainerBuilderTest.php @@ -31,7 +31,7 @@ public function testCreateProxyServiceWithRuntimeInstantiator() $builder->setProxyInstantiator(new RuntimeInstantiator()); - $builder->register('foo1', 'ProxyManagerBridgeFooClass')->setFile(__DIR__.'/Fixtures/includes/foo.php'); + $builder->register('foo1', 'ProxyManagerBridgeFooClass')->setFile(__DIR__.'/Fixtures/includes/foo.php')->setPublic(true); $builder->getDefinition('foo1')->setLazy(true); $builder->compile(); diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php index e32db4097da64..89f8f48182157 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php @@ -953,6 +953,7 @@ public function testEventDispatcherService() $this->loadFromFile($container, 'default_config'); $container ->register('foo', \stdClass::class) + ->setPublic(true) ->setProperty('dispatcher', new Reference('event_dispatcher')); $container->compile(); $this->assertInstanceOf(EventDispatcherInterface::class, $container->get('foo')->dispatcher); diff --git a/src/Symfony/Bundle/WebProfilerBundle/Tests/DependencyInjection/WebProfilerExtensionTest.php b/src/Symfony/Bundle/WebProfilerBundle/Tests/DependencyInjection/WebProfilerExtensionTest.php index 25e352e7124ce..fbb3ca072046e 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Tests/DependencyInjection/WebProfilerExtensionTest.php +++ b/src/Symfony/Bundle/WebProfilerBundle/Tests/DependencyInjection/WebProfilerExtensionTest.php @@ -52,11 +52,11 @@ protected function setUp() $this->kernel = $this->getMockBuilder('Symfony\\Component\\HttpKernel\\KernelInterface')->getMock(); $this->container = new ContainerBuilder(); - $this->container->register('event_dispatcher', EventDispatcher::class); - $this->container->register('router', $this->getMockClass('Symfony\\Component\\Routing\\RouterInterface')); - $this->container->register('twig', 'Twig\Environment'); - $this->container->register('twig_loader', 'Twig\Loader\ArrayLoader')->addArgument(array()); - $this->container->register('twig', 'Twig\Environment')->addArgument(new Reference('twig_loader')); + $this->container->register('event_dispatcher', EventDispatcher::class)->setPublic(true); + $this->container->register('router', $this->getMockClass('Symfony\\Component\\Routing\\RouterInterface'))->setPublic(true); + $this->container->register('twig', 'Twig\Environment')->setPublic(true); + $this->container->register('twig_loader', 'Twig\Loader\ArrayLoader')->addArgument(array())->setPublic(true); + $this->container->register('twig', 'Twig\Environment')->addArgument(new Reference('twig_loader'))->setPublic(true); $this->container->setParameter('kernel.bundles', array()); $this->container->setParameter('kernel.cache_dir', __DIR__); $this->container->setParameter('kernel.debug', false); @@ -65,6 +65,7 @@ protected function setUp() $this->container->setParameter('debug.file_link_format', null); $this->container->setParameter('profiler.class', array('Symfony\\Component\\HttpKernel\\Profiler\\Profiler')); $this->container->register('profiler', $this->getMockClass('Symfony\\Component\\HttpKernel\\Profiler\\Profiler')) + ->setPublic(true) ->addArgument(new Definition($this->getMockClass('Symfony\\Component\\HttpKernel\\Profiler\\ProfilerStorageInterface'))); $this->container->setParameter('data_collector.templates', array()); $this->container->set('kernel', $this->kernel); @@ -123,6 +124,9 @@ public function getDebugModes() private function getCompiledContainer() { + if ($this->container->has('web_profiler.debug_toolbar')) { + $this->container->getDefinition('web_profiler.debug_toolbar')->setPublic(true); + } $this->container->compile(); $this->container->set('kernel', $this->kernel); diff --git a/src/Symfony/Component/DependencyInjection/ChildDefinition.php b/src/Symfony/Component/DependencyInjection/ChildDefinition.php index d72c762c5c6dd..f363a64829c24 100644 --- a/src/Symfony/Component/DependencyInjection/ChildDefinition.php +++ b/src/Symfony/Component/DependencyInjection/ChildDefinition.php @@ -30,6 +30,7 @@ class ChildDefinition extends Definition public function __construct($parent) { $this->parent = $parent; + $this->setPrivate(false); } /** diff --git a/src/Symfony/Component/DependencyInjection/Compiler/RemoveUnusedDefinitionsPass.php b/src/Symfony/Component/DependencyInjection/Compiler/RemoveUnusedDefinitionsPass.php index 7fcf6cc634283..9a200499fa69a 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/RemoveUnusedDefinitionsPass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/RemoveUnusedDefinitionsPass.php @@ -68,8 +68,8 @@ public function process(ContainerBuilder $container) if (1 === count($referencingAliases) && false === $isReferenced) { $container->setDefinition((string) reset($referencingAliases), $definition); - $definition->setPrivate(reset($referencingAliases)->isPrivate()); $definition->setPublic(!$definition->isPrivate()); + $definition->setPrivate(reset($referencingAliases)->isPrivate()); $container->removeDefinition($id); $container->log($this, sprintf('Removed service "%s"; reason: replaces alias %s.', $id, reset($referencingAliases))); } elseif (0 === count($referencingAliases) && false === $isReferenced) { diff --git a/src/Symfony/Component/DependencyInjection/ContainerBuilder.php b/src/Symfony/Component/DependencyInjection/ContainerBuilder.php index 4881f828f1c6f..d46da389f05b4 100644 --- a/src/Symfony/Component/DependencyInjection/ContainerBuilder.php +++ b/src/Symfony/Component/DependencyInjection/ContainerBuilder.php @@ -126,7 +126,7 @@ public function __construct(ParameterBagInterface $parameterBag = null) parent::__construct($parameterBag); $this->trackResources = interface_exists('Symfony\Component\Config\Resource\ResourceInterface'); - $this->setDefinition('service_container', (new Definition(ContainerInterface::class))->setSynthetic(true)); + $this->setDefinition('service_container', (new Definition(ContainerInterface::class))->setSynthetic(true)->setPublic(true)); $this->setAlias(PsrContainerInterface::class, new Alias('service_container', false)); $this->setAlias(ContainerInterface::class, new Alias('service_container', false)); } @@ -562,6 +562,22 @@ public function has($id) * @see Reference */ public function get($id, $invalidBehavior = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE) + { + if ($this->isCompiled()) { + $id = $this->normalizeId($id); + + if (isset($this->definitions[$id]) && $this->definitions[$id]->isPrivate()) { + @trigger_error(sprintf('Fetching the "%s" private service is deprecated and will fail in Symfony 4.0. Make the service public instead.', $id), E_USER_DEPRECATED); + } + if (isset($this->aliasDefinitions[$id]) && $this->aliasDefinitions[$id]->isPrivate()) { + @trigger_error(sprintf('Fetching the "%s" private alias is deprecated and will fail in Symfony 4.0. Make the alias public instead.', $id), E_USER_DEPRECATED); + } + } + + return $this->doGet($id, $invalidBehavior); + } + + private function doGet($id, $invalidBehavior = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE) { $id = $this->normalizeId($id); @@ -573,7 +589,7 @@ public function get($id, $invalidBehavior = ContainerInterface::EXCEPTION_ON_INV } if (!isset($this->definitions[$id]) && isset($this->aliasDefinitions[$id])) { - return $this->get((string) $this->aliasDefinitions[$id], $invalidBehavior); + return $this->doGet((string) $this->aliasDefinitions[$id], $invalidBehavior); } try { @@ -1122,7 +1138,7 @@ private function createService(Definition $definition, $id, $tryProxy = true) $callable[0] = $parameterBag->resolveValue($callable[0]); if ($callable[0] instanceof Reference) { - $callable[0] = $this->get((string) $callable[0], $callable[0]->getInvalidBehavior()); + $callable[0] = $this->doGet((string) $callable[0], $callable[0]->getInvalidBehavior()); } elseif ($callable[0] instanceof Definition) { $callable[0] = $this->createService($callable[0], null); } @@ -1166,7 +1182,7 @@ public function resolveServices($value) } } foreach (self::getInitializedConditionals($v) as $s) { - if (!$this->get($s, ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE)) { + if (!$this->doGet($s, ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE)) { continue 2; } } @@ -1182,7 +1198,7 @@ public function resolveServices($value) } } foreach (self::getInitializedConditionals($v) as $s) { - if (!$this->get($s, ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE)) { + if (!$this->doGet($s, ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE)) { continue 2; } } @@ -1193,7 +1209,7 @@ public function resolveServices($value) return $count; }); } elseif ($value instanceof Reference) { - $value = $this->get((string) $value, $value->getInvalidBehavior()); + $value = $this->doGet((string) $value, $value->getInvalidBehavior()); } elseif ($value instanceof Definition) { $value = $this->createService($value, null); } elseif ($value instanceof Expression) { @@ -1518,7 +1534,7 @@ private function callMethod($service, $call) } } foreach (self::getInitializedConditionals($call[1]) as $s) { - if (!$this->get($s, ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE)) { + if (!$this->doGet($s, ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE)) { return; } } diff --git a/src/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php b/src/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php index 6bebf2133c57b..f152d462676e2 100644 --- a/src/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php +++ b/src/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php @@ -255,11 +255,7 @@ private function parseDefinition(\DOMElement $service, $file, array $defaults) $definition->setChanges(array()); } - if ($publicAttr = $service->getAttribute('public')) { - $definition->setPublic(XmlUtils::phpize($publicAttr)); - } - - foreach (array('class', 'shared', 'synthetic', 'lazy', 'abstract') as $key) { + foreach (array('class', 'public', 'shared', 'synthetic', 'lazy', 'abstract') as $key) { if ($value = $service->getAttribute($key)) { $method = 'set'.$key; $definition->$method(XmlUtils::phpize($value)); diff --git a/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php b/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php index d074189cbeab7..80c9eb4559809 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php @@ -630,6 +630,7 @@ public function testCompileWithResolveEnv() $container->setParameter('env(HTTP_DUMMY_VAR)', '123'); $container->register('teatime', 'stdClass') ->setProperty('foo', '%env(DUMMY_ENV_VAR)%') + ->setPublic(true) ; $container->compile(true); @@ -687,9 +688,11 @@ public function testCastEnv() $container = new ContainerBuilder(); $container->setParameter('env(FAKE)', '123'); - $container->register('foo', 'stdClass')->setProperties(array( - 'fake' => '%env(int:FAKE)%', - )); + $container->register('foo', 'stdClass') + ->setPublic(true) + ->setProperties(array( + 'fake' => '%env(int:FAKE)%', + )); $container->compile(true); @@ -701,7 +704,9 @@ public function testEnvAreNullable() $container = new ContainerBuilder(); $container->setParameter('env(FAKE)', null); - $container->register('foo', 'stdClass')->setProperties(array( + $container->register('foo', 'stdClass') + ->setPublic(true) + ->setProperties(array( 'fake' => '%env(int:FAKE)%', )); @@ -860,7 +865,7 @@ public function testCompilesClassDefinitionsOfLazyServices() $this->assertEmpty($container->getResources(), 'No resources get registered without resource tracking'); - $container->register('foo', 'BarClass'); + $container->register('foo', 'BarClass')->setPublic(true); $container->getDefinition('foo')->setLazy(true); $container->compile(); @@ -959,7 +964,7 @@ public function testPrivateServiceUser() $container->addDefinitions(array( 'bar' => $fooDefinition, - 'bar_user' => $fooUserDefinition, + 'bar_user' => $fooUserDefinition->setPublic(true), )); $container->compile(); @@ -973,7 +978,7 @@ public function testThrowsExceptionWhenSetServiceOnACompiledContainer() { $container = new ContainerBuilder(); $container->setResourceTracking(false); - $container->setDefinition('a', new Definition('stdClass')); + $container->register('a', 'stdClass')->setPublic(true); $container->compile(); $container->set('a', new \stdClass()); } @@ -990,7 +995,7 @@ public function testNoExceptionWhenSetSyntheticServiceOnACompiledContainer() { $container = new ContainerBuilder(); $def = new Definition('stdClass'); - $def->setSynthetic(true); + $def->setSynthetic(true)->setPublic(true); $container->setDefinition('a', $def); $container->compile(); $container->set('a', $a = new \stdClass()); @@ -1031,10 +1036,10 @@ public function testAbstractAlias() $container = new ContainerBuilder(); $abstract = new Definition('AbstractClass'); - $abstract->setAbstract(true); + $abstract->setAbstract(true)->setPublic(true); $container->setDefinition('abstract_service', $abstract); - $container->setAlias('abstract_alias', 'abstract_service'); + $container->setAlias('abstract_alias', 'abstract_service')->setPublic(true); $container->compile(); @@ -1048,6 +1053,7 @@ public function testLazyLoadedService() $container->set('a', new \BazClass()); $definition = new Definition('BazClass'); $definition->setLazy(true); + $definition->setPublic(true); $container->setDefinition('a', $definition); }); @@ -1075,6 +1081,7 @@ public function testInitializePropertiesBeforeMethodCalls() $container = new ContainerBuilder(); $container->register('foo', 'stdClass'); $container->register('bar', 'MethodCallClass') + ->setPublic(true) ->setProperty('simple', 'bar') ->setProperty('complex', new Reference('foo')) ->addMethodCall('callMe'); @@ -1088,9 +1095,10 @@ public function testAutowiring() { $container = new ContainerBuilder(); - $container->register(A::class); + $container->register(A::class)->setPublic(true); $bDefinition = $container->register('b', __NAMESPACE__.'\B'); $bDefinition->setAutowired(true); + $bDefinition->setPublic(true); $container->compile(); @@ -1149,12 +1157,13 @@ public function testServiceLocator() { $container = new ContainerBuilder(); $container->register('foo_service', ServiceLocator::class) + ->setPublic(true) ->addArgument(array( 'bar' => new ServiceClosureArgument(new Reference('bar_service')), 'baz' => new ServiceClosureArgument(new TypedReference('baz_service', 'stdClass')), )) ; - $container->register('bar_service', 'stdClass')->setArguments(array(new Reference('baz_service'))); + $container->register('bar_service', 'stdClass')->setArguments(array(new Reference('baz_service')))->setPublic(true); $container->register('baz_service', 'stdClass')->setPublic(false); $container->compile(); @@ -1234,6 +1243,7 @@ public function testParameterWithMixedCase() { $container = new ContainerBuilder(new ParameterBag(array('foo' => 'bar'))); $container->register('foo', 'stdClass') + ->setPublic(true) ->setProperty('foo', '%FOO%'); $container->compile(); diff --git a/src/Symfony/Component/DependencyInjection/Tests/Dumper/XmlDumperTest.php b/src/Symfony/Component/DependencyInjection/Tests/Dumper/XmlDumperTest.php index 7904ed0c9e6db..2e4ccf1fdbe4c 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Dumper/XmlDumperTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Dumper/XmlDumperTest.php @@ -74,7 +74,7 @@ public function testDumpAnonymousServices() $this->assertEquals(' - + @@ -98,7 +98,7 @@ public function testDumpEntities() $this->assertEquals(" - + foo<>&bar @@ -127,7 +127,7 @@ public function provideDecoratedServicesData() array(" - + @@ -137,7 +137,7 @@ public function provideDecoratedServicesData() array(" - + diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services1-1.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services1-1.php index d87e61e14aa19..44631328ce606 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services1-1.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services1-1.php @@ -29,9 +29,6 @@ class Container extends AbstractContainer public function __construct() { $this->services = array(); - $this->privates = array( - 'service_container' => true, - ); $this->aliases = array(); } diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services1.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services1.php index 69fc82e056966..9ad021ece802b 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services1.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services1.php @@ -27,9 +27,6 @@ class ProjectServiceContainer extends Container public function __construct() { $this->services = array(); - $this->privates = array( - 'service_container' => true, - ); $this->aliases = array(); } diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services10.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services10.php index 26c73706168d3..d8478d677f4ff 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services10.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services10.php @@ -32,9 +32,6 @@ public function __construct() $this->methodMap = array( 'test' => 'getTestService', ); - $this->privates = array( - 'service_container' => true, - ); $this->aliases = array(); } diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services12.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services12.php index 65891c77b994d..976c720768752 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services12.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services12.php @@ -36,9 +36,6 @@ public function __construct() $this->methodMap = array( 'test' => 'getTestService', ); - $this->privates = array( - 'service_container' => true, - ); $this->aliases = array(); } diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services13.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services13.php index 1525115f5b74a..42b9e78963662 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services13.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services13.php @@ -30,9 +30,6 @@ public function __construct() $this->methodMap = array( 'bar' => 'getBarService', ); - $this->privates = array( - 'service_container' => true, - ); $this->aliases = array(); } diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services19.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services19.php index 44822ac27d8b0..3af42c502c0b4 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services19.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services19.php @@ -31,9 +31,6 @@ public function __construct() 'service_from_anonymous_factory' => 'getServiceFromAnonymousFactoryService', 'service_with_method_call_and_factory' => 'getServiceWithMethodCallAndFactoryService', ); - $this->privates = array( - 'service_container' => true, - ); $this->aliases = array(); } diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services24.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services24.php index 8fbfc408caa4c..116972d25b8fc 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services24.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services24.php @@ -30,9 +30,6 @@ public function __construct() $this->methodMap = array( 'foo' => 'getFooService', ); - $this->privates = array( - 'service_container' => true, - ); $this->aliases = array(); } diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services26.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services26.php index d3349f02b3007..3a38cff1a1539 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services26.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services26.php @@ -36,9 +36,6 @@ public function __construct() $this->methodMap = array( 'test' => 'getTestService', ); - $this->privates = array( - 'service_container' => true, - ); $this->aliases = array(); } diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services33.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services33.php index 327d9e1c4136c..20eda55d99e0f 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services33.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services33.php @@ -35,9 +35,6 @@ public function __construct() 'Bar\\Foo' => 'getFooService', 'Foo\\Foo' => 'getFoo2Service', ); - $this->privates = array( - 'service_container' => true, - ); $this->aliases = array(); } diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services8.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services8.php index f46835ef9dfc1..1689a9658668a 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services8.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services8.php @@ -29,9 +29,6 @@ public function __construct() $this->parameters = $this->getDefaultParameters(); $this->services = array(); - $this->privates = array( - 'service_container' => true, - ); $this->aliases = array(); } diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_as_files.txt b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_as_files.txt index 0af1392afd0f6..059f0912815ca 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_as_files.txt +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_as_files.txt @@ -295,7 +295,6 @@ class Container%s extends Container ); $this->privates = array( 'factory_simple' => true, - 'service_container' => true, ); $this->aliases = array( 'alias_for_alias' => 'foo', diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_compiled.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_compiled.php index 3478d54ec52be..103bb0de34d88 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_compiled.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_compiled.php @@ -52,7 +52,6 @@ public function __construct() ); $this->privates = array( 'factory_simple' => true, - 'service_container' => true, ); $this->aliases = array( 'alias_for_alias' => 'foo', diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_array_params.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_array_params.php index 872b5179532b6..d848941013388 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_array_params.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_array_params.php @@ -36,9 +36,6 @@ public function __construct() $this->methodMap = array( 'bar' => 'getBarService', ); - $this->privates = array( - 'service_container' => true, - ); $this->aliases = array(); } diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_base64_env.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_base64_env.php index 8ebd8f0580c58..4f4c7e79df38b 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_base64_env.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_base64_env.php @@ -29,9 +29,6 @@ public function __construct() $this->parameters = $this->getDefaultParameters(); $this->services = array(); - $this->privates = array( - 'service_container' => true, - ); $this->aliases = array(); } diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_legacy_privates.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_legacy_privates.php index aa154e2c435aa..611b0cf4acadd 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_legacy_privates.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_legacy_privates.php @@ -52,7 +52,6 @@ public function __construct() 'private_not_inlined' => true, 'private_not_removed' => true, 'private_parent' => true, - 'service_container' => true, ); $this->aliases = array( 'alias_to_private' => 'private', diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_locator.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_locator.php index fb2bbbcde8a5a..751ad8e4fa454 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_locator.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_locator.php @@ -40,7 +40,6 @@ public function __construct() ); $this->privates = array( 'baz_service' => true, - 'service_container' => true, ); $this->aliases = array(); diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_private_frozen.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_private_frozen.php index 6c24edc01801c..a6717fd6abf8f 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_private_frozen.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_private_frozen.php @@ -34,7 +34,6 @@ public function __construct() ); $this->privates = array( 'baz_service' => true, - 'service_container' => true, ); $this->aliases = array(); diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_private_in_expression.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_private_in_expression.php index 121951a26f998..e5129d4f36566 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_private_in_expression.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_private_in_expression.php @@ -33,7 +33,6 @@ public function __construct() ); $this->privates = array( 'private_foo' => true, - 'service_container' => true, ); $this->aliases = array(); diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_rot13_env.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_rot13_env.php index 22496e69a4dce..2e08cdcb42f92 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_rot13_env.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_rot13_env.php @@ -36,9 +36,6 @@ public function __construct() 'Symfony\\Component\\DependencyInjection\\Tests\\Dumper\\Rot13EnvVarProcessor' => 'getRot13EnvVarProcessorService', 'container.env_var_processors_locator' => 'getContainer_EnvVarProcessorsLocatorService', ); - $this->privates = array( - 'service_container' => true, - ); $this->aliases = array(); } diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_subscriber.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_subscriber.php index 21fcf03c1efe3..3d7cc80336831 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_subscriber.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_subscriber.php @@ -38,7 +38,6 @@ public function __construct() ); $this->privates = array( 'Symfony\\Component\\DependencyInjection\\Tests\\Fixtures\\CustomDefinition' => true, - 'service_container' => true, ); $this->aliases = array(); diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_uninitialized_ref.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_uninitialized_ref.php index 5a2990e303840..4c26d58d70c28 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_uninitialized_ref.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_uninitialized_ref.php @@ -35,7 +35,6 @@ public function __construct() ); $this->privates = array( 'foo3' => true, - 'service_container' => true, ); $this->aliases = array(); diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services1.xml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services1.xml index fd7bb3cf9b080..6dc3ea6618c6d 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services1.xml +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services1.xml @@ -1,7 +1,7 @@ - + diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services21.xml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services21.xml index 34fd11ef097c2..36fc8cfd81c68 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services21.xml +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services21.xml @@ -1,7 +1,7 @@ - + diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services24.xml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services24.xml index 7183435842f13..abf389bc8d632 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services24.xml +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services24.xml @@ -1,7 +1,7 @@ - + diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services8.xml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services8.xml index 533d2a38d765e..bc1186bd93ccf 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services8.xml +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services8.xml @@ -20,7 +20,7 @@ - + diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services9.xml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services9.xml index 59fa6b102ab42..06f314f5eff73 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services9.xml +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services9.xml @@ -6,7 +6,7 @@ bar - + diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services_abstract.xml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services_abstract.xml index bf9e07e5b083c..22abf54681f6a 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services_abstract.xml +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services_abstract.xml @@ -1,7 +1,7 @@ - + diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services_dump_load.xml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services_dump_load.xml index e763aa870a028..e70be185c0ee1 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services_dump_load.xml +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services_dump_load.xml @@ -1,7 +1,7 @@ - + diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services1.yml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services1.yml index 7b0d3dc697852..071742f2e0519 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services1.yml +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services1.yml @@ -1,6 +1,7 @@ services: service_container: class: Symfony\Component\DependencyInjection\ContainerInterface + public: true synthetic: true Psr\Container\ContainerInterface: alias: service_container diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services24.yml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services24.yml index 5faf830410afc..f59354e3e2509 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services24.yml +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services24.yml @@ -2,6 +2,7 @@ services: service_container: class: Symfony\Component\DependencyInjection\ContainerInterface + public: true synthetic: true foo: class: Foo diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services8.yml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services8.yml index 9efdf3e0d4d0a..4e37bc9315c9b 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services8.yml +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services8.yml @@ -8,6 +8,7 @@ parameters: services: service_container: class: Symfony\Component\DependencyInjection\ContainerInterface + public: true synthetic: true Psr\Container\ContainerInterface: alias: service_container diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services9.yml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services9.yml index 1744611a1a7e0..b6b76da513106 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services9.yml +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services9.yml @@ -6,6 +6,7 @@ parameters: services: service_container: class: Symfony\Component\DependencyInjection\ContainerInterface + public: true synthetic: true foo: class: Bar\FooClass diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services_inline.yml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services_inline.yml index 15d78b50a7725..b985cabd9649e 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services_inline.yml +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services_inline.yml @@ -2,6 +2,7 @@ services: service_container: class: Symfony\Component\DependencyInjection\ContainerInterface + public: true synthetic: true foo: class: Class1 diff --git a/src/Symfony/Component/Form/Tests/DependencyInjection/FormPassTest.php b/src/Symfony/Component/Form/Tests/DependencyInjection/FormPassTest.php index 4e9971ea8ccf3..f045e3f9f5d50 100644 --- a/src/Symfony/Component/Form/Tests/DependencyInjection/FormPassTest.php +++ b/src/Symfony/Component/Form/Tests/DependencyInjection/FormPassTest.php @@ -51,8 +51,8 @@ public function testAddTaggedTypes() $container = $this->createContainerBuilder(); $container->setDefinition('form.extension', $this->createExtensionDefinition()); - $container->register('my.type1', __CLASS__.'_Type1')->addTag('form.type'); - $container->register('my.type2', __CLASS__.'_Type2')->addTag('form.type'); + $container->register('my.type1', __CLASS__.'_Type1')->addTag('form.type')->setPublic(true); + $container->register('my.type2', __CLASS__.'_Type2')->addTag('form.type')->setPublic(true); $container->compile(); @@ -73,8 +73,8 @@ public function testAddTaggedTypesToDebugCommand() $container->setDefinition('form.extension', $this->createExtensionDefinition()); $container->setDefinition(DebugCommand::class, $this->createDebugCommandDefinition()); - $container->register('my.type1', __CLASS__.'_Type1')->addTag('form.type'); - $container->register('my.type2', __CLASS__.'_Type2')->addTag('form.type'); + $container->register('my.type1', __CLASS__.'_Type1')->addTag('form.type')->setPublic(true); + $container->register('my.type2', __CLASS__.'_Type2')->addTag('form.type')->setPublic(true); $container->compile(); @@ -163,6 +163,7 @@ public function testAddTaggedFormTypeExtensionWithoutExtendedTypeAttribute() $container->setDefinition('form.extension', $this->createExtensionDefinition()); $container->register('my.type_extension', 'stdClass') + ->setPublic(true) ->addTag('form.type_extension'); $container->compile(); @@ -178,8 +179,8 @@ public function testAddTaggedGuessers() $definition2->addTag('form.type_guesser'); $container->setDefinition('form.extension', $this->createExtensionDefinition()); - $container->setDefinition('my.guesser1', $definition1); - $container->setDefinition('my.guesser2', $definition2); + $container->setDefinition('my.guesser1', $definition1)->setPublic(true); + $container->setDefinition('my.guesser2', $definition2)->setPublic(true); $container->compile(); @@ -249,6 +250,7 @@ function (ContainerBuilder $container) { private function createExtensionDefinition() { $definition = new Definition('Symfony\Component\Form\Extension\DependencyInjection\DependencyInjectionExtension'); + $definition->setPublic(true); $definition->setArguments(array( array(), array(), @@ -261,6 +263,7 @@ private function createExtensionDefinition() private function createDebugCommandDefinition() { $definition = new Definition('Symfony\Component\Form\Command\DebugCommand'); + $definition->setPublic(true); $definition->setArguments(array( $formRegistry = $this->getMockBuilder(FormRegistryInterface::class)->getMock(), array(), diff --git a/src/Symfony/Component/HttpKernel/Tests/DependencyInjection/ResettableServicePassTest.php b/src/Symfony/Component/HttpKernel/Tests/DependencyInjection/ResettableServicePassTest.php index 7363586f99588..c998ef2eaf086 100644 --- a/src/Symfony/Component/HttpKernel/Tests/DependencyInjection/ResettableServicePassTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/DependencyInjection/ResettableServicePassTest.php @@ -18,11 +18,14 @@ public function testCompilerPass() { $container = new ContainerBuilder(); $container->register('one', ResettableService::class) + ->setPublic(true) ->addTag('kernel.reset', array('method' => 'reset')); $container->register('two', ClearableService::class) + ->setPublic(true) ->addTag('kernel.reset', array('method' => 'clear')); $container->register(ServiceResetListener::class) + ->setPublic(true) ->setArguments(array(null, array())); $container->addCompilerPass(new ResettableServicePass('kernel.reset')); diff --git a/src/Symfony/Component/HttpKernel/Tests/EventListener/ServiceResetListenerTest.php b/src/Symfony/Component/HttpKernel/Tests/EventListener/ServiceResetListenerTest.php index 4675fbe71e5a2..603d11b2bf412 100644 --- a/src/Symfony/Component/HttpKernel/Tests/EventListener/ServiceResetListenerTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/EventListener/ServiceResetListenerTest.php @@ -56,10 +56,11 @@ public function testResetServicesTwice() private function buildContainer() { $container = new ContainerBuilder(); - $container->register('one', ResettableService::class); - $container->register('two', ClearableService::class); + $container->register('one', ResettableService::class)->setPublic(true); + $container->register('two', ClearableService::class)->setPublic(true); $container->register('reset_subscriber', ServiceResetListener::class) + ->setPublic(true) ->addArgument(new IteratorArgument(array( 'one' => new Reference('one', ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE), 'two' => new Reference('two', ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE), diff --git a/src/Symfony/Component/HttpKernel/Tests/KernelTest.php b/src/Symfony/Component/HttpKernel/Tests/KernelTest.php index 4a093472b9df1..a408f87f87a32 100644 --- a/src/Symfony/Component/HttpKernel/Tests/KernelTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/KernelTest.php @@ -824,7 +824,7 @@ public function testKernelReset() $this->assertFileExists($containerFile); unlink(__DIR__.'/Fixtures/cache/custom/FixturesCustomDebugProjectContainer.php.meta'); - $kernel = new CustomProjectDirKernel(function ($container) { $container->register('foo', 'stdClass'); }); + $kernel = new CustomProjectDirKernel(function ($container) { $container->register('foo', 'stdClass')->setPublic(true); }); $kernel->boot(); $this->assertTrue(get_class($kernel->getContainer()) !== $containerClass); From 0e73d7126ee4c387a657b36ada1d1456e9cb3b39 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Tue, 19 Sep 2017 23:53:27 +0200 Subject: [PATCH 0860/1099] fixes --- .../AddExpressionLanguageProvidersPassTest.php | 16 ++++++++-------- .../Compiler/FormPassTest.php | 8 ++++++-- .../Functional/app/CachePoolClear/config.yml | 1 + 3 files changed, 15 insertions(+), 10 deletions(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/AddExpressionLanguageProvidersPassTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/AddExpressionLanguageProvidersPassTest.php index 0934fe31c0c40..d2fa0f4bdfb69 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/AddExpressionLanguageProvidersPassTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/AddExpressionLanguageProvidersPassTest.php @@ -26,9 +26,9 @@ public function testProcessForRouter() $definition = new Definition('Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\Compiler\TestProvider'); $definition->addTag('routing.expression_language_provider'); - $container->setDefinition('some_routing_provider', $definition); + $container->setDefinition('some_routing_provider', $definition->setPublic(true)); - $container->register('router', '\stdClass'); + $container->register('router', '\stdClass')->setPublic(true); $container->compile(); $router = $container->getDefinition('router'); @@ -45,9 +45,9 @@ public function testProcessForRouterAlias() $definition = new Definition('Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\Compiler\TestProvider'); $definition->addTag('routing.expression_language_provider'); - $container->setDefinition('some_routing_provider', $definition); + $container->setDefinition('some_routing_provider', $definition->setPublic(true)); - $container->register('my_router', '\stdClass'); + $container->register('my_router', '\stdClass')->setPublic(true); $container->setAlias('router', 'my_router'); $container->compile(); @@ -65,9 +65,9 @@ public function testProcessForSecurity() $definition = new Definition('Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\Compiler\TestProvider'); $definition->addTag('security.expression_language_provider'); - $container->setDefinition('some_security_provider', $definition); + $container->setDefinition('some_security_provider', $definition->setPublic(true)); - $container->register('security.access.expression_voter', '\stdClass'); + $container->register('security.access.expression_voter', '\stdClass')->setPublic(true); $container->compile(); $router = $container->getDefinition('security.access.expression_voter'); @@ -84,9 +84,9 @@ public function testProcessForSecurityAlias() $definition = new Definition('Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\Compiler\TestProvider'); $definition->addTag('security.expression_language_provider'); - $container->setDefinition('some_security_provider', $definition); + $container->setDefinition('some_security_provider', $definition->setPublic(true)); - $container->register('my_security.access.expression_voter', '\stdClass'); + $container->register('my_security.access.expression_voter', '\stdClass')->setPublic(true); $container->setAlias('security.access.expression_voter', 'my_security.access.expression_voter'); $container->compile(); diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/FormPassTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/FormPassTest.php index 9adbaf8da9062..58dbd2efd9c02 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/FormPassTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/FormPassTest.php @@ -41,6 +41,7 @@ public function testAddTaggedTypes() $container->addCompilerPass(new FormPass()); $extDefinition = new Definition('Symfony\Component\Form\Extension\DependencyInjection\DependencyInjectionExtension'); + $extDefinition->setPublic(true); $extDefinition->setArguments(array( new Reference('service_container'), array(), @@ -49,8 +50,8 @@ public function testAddTaggedTypes() )); $container->setDefinition('form.extension', $extDefinition); - $container->register('my.type1', __CLASS__.'_Type1')->addTag('form.type'); - $container->register('my.type2', __CLASS__.'_Type2')->addTag('form.type'); + $container->register('my.type1', __CLASS__.'_Type1')->addTag('form.type')->setPublic(true); + $container->register('my.type2', __CLASS__.'_Type2')->addTag('form.type')->setPublic(true); $container->compile(); @@ -76,6 +77,7 @@ public function testAddTaggedTypeExtensions(array $extensions, array $expectedRe array(), array(), )); + $extDefinition->setPublic(true); $container->setDefinition('form.extension', $extDefinition); @@ -138,6 +140,7 @@ public function testAddTaggedFormTypeExtensionWithoutExtendedTypeAttribute() array(), array(), )); + $extDefinition->setPublic(true); $container->setDefinition('form.extension', $extDefinition); $container->register('my.type_extension', 'stdClass') @@ -152,6 +155,7 @@ public function testAddTaggedGuessers() $container->addCompilerPass(new FormPass()); $extDefinition = new Definition('Symfony\Component\Form\Extension\DependencyInjection\DependencyInjectionExtension'); + $extDefinition->setPublic(true); $extDefinition->setArguments(array( new Reference('service_container'), array(), diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/CachePoolClear/config.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/CachePoolClear/config.yml index 75107485ee65f..b991dd593148d 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/CachePoolClear/config.yml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/CachePoolClear/config.yml @@ -5,6 +5,7 @@ services: dummy: class: Symfony\Bundle\FrameworkBundle\Tests\Fixtures\DeclaredClass arguments: ['@cache.private_pool'] + public: true custom_clearer: parent: cache.default_clearer tags: From cc2abd9d1c3e977b9d29e8b3c10fd259af0b1edb Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Wed, 20 Sep 2017 06:13:06 +0200 Subject: [PATCH 0861/1099] fix merge --- .../Compiler/ResolveChildDefinitionsPass.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/DependencyInjection/Compiler/ResolveChildDefinitionsPass.php b/src/Symfony/Component/DependencyInjection/Compiler/ResolveChildDefinitionsPass.php index c9b2d2f7c05cb..84447b853c78c 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/ResolveChildDefinitionsPass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/ResolveChildDefinitionsPass.php @@ -142,7 +142,7 @@ private function doResolveDefinition(ChildDefinition $definition) if (isset($changes['public'])) { $def->setPublic($definition->isPublic()); } else { - $def->setPrivate($parentDef->isPrivate()); + $def->setPrivate($definition->isPrivate() || $parentDef->isPrivate()); } if (isset($changes['lazy'])) { $def->setLazy($definition->isLazy()); From f433c9a79dc0983e6067be9db7aeacc81646f4ca Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Mon, 11 Sep 2017 10:46:30 +0200 Subject: [PATCH 0862/1099] [Routing] Add PHP fluent DSL for configuring routes --- .../Configurator/CollectionConfigurator.php | 79 ++++++++++ .../Configurator/ImportConfigurator.php | 49 +++++++ .../Loader/Configurator/RouteConfigurator.php | 31 ++++ .../Configurator/RoutingConfigurator.php | 54 +++++++ .../Loader/Configurator/Traits/AddTrait.php | 54 +++++++ .../Loader/Configurator/Traits/RouteTrait.php | 137 ++++++++++++++++++ .../Routing/Loader/PhpFileLoader.php | 35 +++-- .../Routing/Tests/Fixtures/php_dsl.php | 21 +++ .../Routing/Tests/Fixtures/php_dsl_sub.php | 14 ++ .../Tests/Loader/PhpFileLoaderTest.php | 37 +++++ 10 files changed, 498 insertions(+), 13 deletions(-) create mode 100644 src/Symfony/Component/Routing/Loader/Configurator/CollectionConfigurator.php create mode 100644 src/Symfony/Component/Routing/Loader/Configurator/ImportConfigurator.php create mode 100644 src/Symfony/Component/Routing/Loader/Configurator/RouteConfigurator.php create mode 100644 src/Symfony/Component/Routing/Loader/Configurator/RoutingConfigurator.php create mode 100644 src/Symfony/Component/Routing/Loader/Configurator/Traits/AddTrait.php create mode 100644 src/Symfony/Component/Routing/Loader/Configurator/Traits/RouteTrait.php create mode 100644 src/Symfony/Component/Routing/Tests/Fixtures/php_dsl.php create mode 100644 src/Symfony/Component/Routing/Tests/Fixtures/php_dsl_sub.php diff --git a/src/Symfony/Component/Routing/Loader/Configurator/CollectionConfigurator.php b/src/Symfony/Component/Routing/Loader/Configurator/CollectionConfigurator.php new file mode 100644 index 0000000000000..67d5c77de5459 --- /dev/null +++ b/src/Symfony/Component/Routing/Loader/Configurator/CollectionConfigurator.php @@ -0,0 +1,79 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing\Loader\Configurator; + +use Symfony\Component\Routing\Route; +use Symfony\Component\Routing\RouteCollection; + +/** + * @author Nicolas Grekas + */ +class CollectionConfigurator +{ + use Traits\AddTrait; + use Traits\RouteTrait; + + private $parent; + + public function __construct(RouteCollection $parent, $name) + { + $this->parent = $parent; + $this->name = $name; + $this->collection = new RouteCollection(); + $this->route = new Route(''); + } + + public function __destruct() + { + $this->collection->addPrefix(rtrim($this->route->getPath(), '/')); + $this->parent->addCollection($this->collection); + } + + /** + * Adds a route. + * + * @param string $name + * @param string $value + * + * @return RouteConfigurator + */ + final public function add($name, $path) + { + $this->collection->add($this->name.$name, $route = clone $this->route); + + return new RouteConfigurator($this->collection, $route->setPath($path), $this->name); + } + + /** + * Creates a sub-collection. + * + * @return self + */ + final public function collection($name = '') + { + return new self($this->collection, $this->name.$name); + } + + /** + * Sets the prefix to add to the path of all child routes. + * + * @param string $prefix + * + * @return $this + */ + final public function prefix($prefix) + { + $this->route->setPath($prefix); + + return $this; + } +} diff --git a/src/Symfony/Component/Routing/Loader/Configurator/ImportConfigurator.php b/src/Symfony/Component/Routing/Loader/Configurator/ImportConfigurator.php new file mode 100644 index 0000000000000..d0a3c373ff23a --- /dev/null +++ b/src/Symfony/Component/Routing/Loader/Configurator/ImportConfigurator.php @@ -0,0 +1,49 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing\Loader\Configurator; + +use Symfony\Component\Routing\RouteCollection; + +/** + * @author Nicolas Grekas + */ +class ImportConfigurator +{ + use Traits\RouteTrait; + + private $parent; + + public function __construct(RouteCollection $parent, RouteCollection $route) + { + $this->parent = $parent; + $this->route = $route; + } + + public function __destruct() + { + $this->parent->addCollection($this->route); + } + + /** + * Sets the prefix to add to the path of all child routes. + * + * @param string $prefix + * + * @return $this + */ + final public function prefix($prefix) + { + $this->route->addPrefix($prefix); + + return $this; + } +} diff --git a/src/Symfony/Component/Routing/Loader/Configurator/RouteConfigurator.php b/src/Symfony/Component/Routing/Loader/Configurator/RouteConfigurator.php new file mode 100644 index 0000000000000..b8d87025435e0 --- /dev/null +++ b/src/Symfony/Component/Routing/Loader/Configurator/RouteConfigurator.php @@ -0,0 +1,31 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing\Loader\Configurator; + +use Symfony\Component\Routing\Route; +use Symfony\Component\Routing\RouteCollection; + +/** + * @author Nicolas Grekas + */ +class RouteConfigurator +{ + use Traits\AddTrait; + use Traits\RouteTrait; + + public function __construct(RouteCollection $collection, Route $route, $name = '') + { + $this->collection = $collection; + $this->route = $route; + $this->name = $name; + } +} diff --git a/src/Symfony/Component/Routing/Loader/Configurator/RoutingConfigurator.php b/src/Symfony/Component/Routing/Loader/Configurator/RoutingConfigurator.php new file mode 100644 index 0000000000000..4591a86ba5cf9 --- /dev/null +++ b/src/Symfony/Component/Routing/Loader/Configurator/RoutingConfigurator.php @@ -0,0 +1,54 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing\Loader\Configurator; + +use Symfony\Component\Routing\Loader\PhpFileLoader; +use Symfony\Component\Routing\RouteCollection; + +/** + * @author Nicolas Grekas + */ +class RoutingConfigurator +{ + use Traits\AddTrait; + + private $loader; + private $path; + private $file; + + public function __construct(RouteCollection $collection, PhpFileLoader $loader, $path, $file) + { + $this->collection = $collection; + $this->loader = $loader; + $this->path = $path; + $this->file = $file; + } + + /** + * @return ImportConfigurator + */ + final public function import($resource, $type = null, $ignoreErrors = false) + { + $this->loader->setCurrentDir(dirname($this->path)); + $subCollection = $this->loader->import($resource, $type, $ignoreErrors, $this->file); + + return new ImportConfigurator($this->collection, $subCollection); + } + + /** + * @return CollectionConfigurator + */ + final public function collection($name = '') + { + return new CollectionConfigurator($this->collection, $name); + } +} diff --git a/src/Symfony/Component/Routing/Loader/Configurator/Traits/AddTrait.php b/src/Symfony/Component/Routing/Loader/Configurator/Traits/AddTrait.php new file mode 100644 index 0000000000000..abaf868c9c698 --- /dev/null +++ b/src/Symfony/Component/Routing/Loader/Configurator/Traits/AddTrait.php @@ -0,0 +1,54 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing\Loader\Configurator\Traits; + +use Symfony\Component\Routing\Loader\Configurator\RouteConfigurator; +use Symfony\Component\Routing\Route; +use Symfony\Component\Routing\RouteCollection; + +trait AddTrait +{ + /** + * @var RouteCollection + */ + private $collection; + + private $name = ''; + + /** + * Adds a route. + * + * @param string $name + * @param string $value + * + * @return RouteConfigurator + */ + final public function add($name, $path) + { + $this->collection->add($this->name.$name, $route = new Route($path)); + + return new RouteConfigurator($this->collection, $route); + } + + /** + * Adds a route. + * + * @param string $name + * @param string $path + * + * @return RouteConfigurator + */ + final public function __invoke($name, $path) + { + return $this->add($name, $path); + } +} diff --git a/src/Symfony/Component/Routing/Loader/Configurator/Traits/RouteTrait.php b/src/Symfony/Component/Routing/Loader/Configurator/Traits/RouteTrait.php new file mode 100644 index 0000000000000..8eb3276500d89 --- /dev/null +++ b/src/Symfony/Component/Routing/Loader/Configurator/Traits/RouteTrait.php @@ -0,0 +1,137 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing\Loader\Configurator\Traits; + +use Symfony\Component\Routing\Route; +use Symfony\Component\Routing\RouteCollection; + +trait RouteTrait +{ + /** + * @var RouteCollection|Route + */ + private $route; + + /** + * Adds defaults. + * + * @param array $defaults + * + * @return $this + */ + final public function defaults(array $defaults) + { + $this->route->addDefaults($defaults); + + return $this; + } + + /** + * Adds requirements. + * + * @param array $requirements + * + * @return $this + */ + final public function requirements(array $requirements) + { + $this->route->addRequirements($requirements); + + return $this; + } + + /** + * Adds options. + * + * @param array $options + * + * @return $this + */ + final public function options(array $options) + { + $this->route->addOptions($options); + + return $this; + } + + /** + * Sets the condition. + * + * @param string $condition + * + * @return $this + */ + final public function condition($condition) + { + $this->route->setCondition($condition); + + return $this; + } + + /** + * Sets the pattern for the host. + * + * @param string $pattern + * + * @return $this + */ + final public function host($pattern) + { + $this->route->setHost($pattern); + + return $this; + } + + /** + * Sets the schemes (e.g. 'https') this route is restricted to. + * So an empty array means that any scheme is allowed. + * + * @param array $schemes + * + * @return $this + */ + final public function schemes(array $schemes) + { + $this->route->setSchemes($schemes); + + return $this; + } + + /** + * Sets the HTTP methods (e.g. 'POST') this route is restricted to. + * So an empty array means that any method is allowed. + * + * @param array $methods + * + * @return $this + */ + final public function methods(array $methods) + { + $this->route->setMethods($methods); + + return $this; + } + + /** + * Adds the "_controller" entry to defaults. + * + * @param callable $controller a callable or parseable pseudo-callable + * + * @return $this + */ + final public function controller($controller) + { + $this->route->addDefaults(array('_controller' => $controller)); + + return $this; + } +} diff --git a/src/Symfony/Component/Routing/Loader/PhpFileLoader.php b/src/Symfony/Component/Routing/Loader/PhpFileLoader.php index b4ba5fbc7f8ba..3fcd692f92562 100644 --- a/src/Symfony/Component/Routing/Loader/PhpFileLoader.php +++ b/src/Symfony/Component/Routing/Loader/PhpFileLoader.php @@ -13,6 +13,7 @@ use Symfony\Component\Config\Loader\FileLoader; use Symfony\Component\Config\Resource\FileResource; +use Symfony\Component\Routing\Loader\Configurator\RoutingConfigurator; use Symfony\Component\Routing\RouteCollection; /** @@ -37,7 +38,21 @@ public function load($file, $type = null) $path = $this->locator->locate($file); $this->setCurrentDir(dirname($path)); - $collection = self::includeFile($path, $this); + // the closure forbids access to the private scope in the included file + $loader = $this; + $load = \Closure::bind(function ($file) use ($loader) { + return include $file; + }, null, ProtectedPhpFileLoader::class); + + $result = $load($path); + + if ($result instanceof \Closure) { + $collection = new RouteCollection(); + $result(new RoutingConfigurator($collection, $this, $path, $file), $this); + } else { + $collection = $result; + } + $collection->addResource(new FileResource($path)); return $collection; @@ -50,17 +65,11 @@ public function supports($resource, $type = null) { return is_string($resource) && 'php' === pathinfo($resource, PATHINFO_EXTENSION) && (!$type || 'php' === $type); } +} - /** - * Safe include. Used for scope isolation. - * - * @param string $file File to include - * @param PhpFileLoader $loader the loader variable is exposed to the included file below - * - * @return RouteCollection - */ - private static function includeFile($file, PhpFileLoader $loader) - { - return include $file; - } +/** + * @internal + */ +final class ProtectedPhpFileLoader extends PhpFileLoader +{ } diff --git a/src/Symfony/Component/Routing/Tests/Fixtures/php_dsl.php b/src/Symfony/Component/Routing/Tests/Fixtures/php_dsl.php new file mode 100644 index 0000000000000..04f6d7ed6eab2 --- /dev/null +++ b/src/Symfony/Component/Routing/Tests/Fixtures/php_dsl.php @@ -0,0 +1,21 @@ +add('foo', '/foo') + ->condition('abc') + ->options(array('utf8' => true)) + ->add('buz', 'zub') + ->controller('foo:act'); + + $routes->import('php_dsl_sub.php') + ->prefix('/sub') + ->requirements(array('id' => '\d+')); + + $routes->add('ouf', '/ouf') + ->schemes(array('https')) + ->methods(array('GET')) + ->defaults(array('id' => 0)); +}; diff --git a/src/Symfony/Component/Routing/Tests/Fixtures/php_dsl_sub.php b/src/Symfony/Component/Routing/Tests/Fixtures/php_dsl_sub.php new file mode 100644 index 0000000000000..9eb444ded0c1c --- /dev/null +++ b/src/Symfony/Component/Routing/Tests/Fixtures/php_dsl_sub.php @@ -0,0 +1,14 @@ +collection('c_') + ->prefix('pub'); + + $add('bar', '/bar'); + + $add->collection('pub_') + ->host('host') + ->add('buz', 'buz'); +}; diff --git a/src/Symfony/Component/Routing/Tests/Loader/PhpFileLoaderTest.php b/src/Symfony/Component/Routing/Tests/Loader/PhpFileLoaderTest.php index bda64236f6022..608d84ed7a20f 100644 --- a/src/Symfony/Component/Routing/Tests/Loader/PhpFileLoaderTest.php +++ b/src/Symfony/Component/Routing/Tests/Loader/PhpFileLoaderTest.php @@ -13,7 +13,10 @@ use PHPUnit\Framework\TestCase; use Symfony\Component\Config\FileLocator; +use Symfony\Component\Config\Resource\FileResource; use Symfony\Component\Routing\Loader\PhpFileLoader; +use Symfony\Component\Routing\Route; +use Symfony\Component\Routing\RouteCollection; class PhpFileLoaderTest extends TestCase { @@ -80,4 +83,38 @@ public function testThatDefiningVariableInConfigFileHasNoSideEffects() (string) $fileResource ); } + + public function testRoutingConfigurator() + { + $locator = new FileLocator(array(__DIR__.'/../Fixtures')); + $loader = new PhpFileLoader($locator); + $routeCollection = $loader->load('php_dsl.php'); + + $expectedCollection = new RouteCollection(); + + $expectedCollection->add('foo', (new Route('/foo')) + ->setOptions(array('utf8' => true)) + ->setCondition('abc') + ); + $expectedCollection->add('buz', (new Route('/zub')) + ->setDefaults(array('_controller' => 'foo:act')) + ); + $expectedCollection->add('c_bar', (new Route('/sub/pub/bar')) + ->setRequirements(array('id' => '\d+')) + ); + $expectedCollection->add('c_pub_buz', (new Route('/sub/pub/buz')) + ->setHost('host') + ->setRequirements(array('id' => '\d+')) + ); + $expectedCollection->add('ouf', (new Route('/ouf')) + ->setSchemes(array('https')) + ->setMethods(array('GET')) + ->setDefaults(array('id' => 0)) + ); + + $expectedCollection->addResource(new FileResource(realpath(__DIR__.'/../Fixtures/php_dsl_sub.php'))); + $expectedCollection->addResource(new FileResource(realpath(__DIR__.'/../Fixtures/php_dsl.php'))); + + $this->assertEquals($expectedCollection, $routeCollection); + } } From 814cc31e577b2b68eeb1b990a865016387605c71 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Tue, 8 Aug 2017 19:11:20 +0200 Subject: [PATCH 0863/1099] [DI] Add "PHP fluent format" for configuring the container --- .../Configurator/AbstractConfigurator.php | 102 ++++++++++++ .../AbstractServiceConfigurator.php | 118 ++++++++++++++ .../Loader/Configurator/AliasConfigurator.php | 30 ++++ .../Configurator/ContainerConfigurator.php | 128 +++++++++++++++ .../Configurator/DefaultsConfigurator.php | 68 ++++++++ .../InlineServiceConfigurator.php | 36 ++++ .../Configurator/InstanceofConfigurator.php | 43 +++++ .../Configurator/ParametersConfigurator.php | 57 +++++++ .../Configurator/PrototypeConfigurator.php | 84 ++++++++++ .../Configurator/ReferenceConfigurator.php | 63 +++++++ .../Configurator/ServiceConfigurator.php | 68 ++++++++ .../Configurator/ServicesConfigurator.php | 154 ++++++++++++++++++ .../Configurator/Traits/AbstractTrait.php | 35 ++++ .../Configurator/Traits/ArgumentTrait.php | 44 +++++ .../Traits/AutoconfigureTrait.php | 36 ++++ .../Configurator/Traits/AutowireTrait.php | 29 ++++ .../Loader/Configurator/Traits/BindTrait.php | 43 +++++ .../Loader/Configurator/Traits/CallTrait.php | 34 ++++ .../Loader/Configurator/Traits/ClassTrait.php | 32 ++++ .../Configurator/Traits/ConfiguratorTrait.php | 29 ++++ .../Configurator/Traits/DecorateTrait.php | 35 ++++ .../Configurator/Traits/DeprecateTrait.php | 34 ++++ .../Configurator/Traits/FactoryTrait.php | 29 ++++ .../Loader/Configurator/Traits/FileTrait.php | 29 ++++ .../Loader/Configurator/Traits/LazyTrait.php | 29 ++++ .../Configurator/Traits/ParentTrait.php | 53 ++++++ .../Configurator/Traits/PropertyTrait.php | 30 ++++ .../Configurator/Traits/PublicTrait.php | 39 +++++ .../Loader/Configurator/Traits/ShareTrait.php | 29 ++++ .../Configurator/Traits/SyntheticTrait.php | 30 ++++ .../Loader/Configurator/Traits/TagTrait.php | 43 +++++ .../Loader/PhpFileLoader.php | 20 ++- .../Tests/Fixtures/Prototype/Foo.php | 7 + .../Tests/Fixtures/config/basic.expected.yml | 10 ++ .../Tests/Fixtures/config/basic.php | 13 ++ .../Tests/Fixtures/config/child.expected.yml | 15 ++ .../Tests/Fixtures/config/child.php | 24 +++ .../Fixtures/config/defaults.expected.yml | 27 +++ .../Tests/Fixtures/config/defaults.php | 23 +++ .../Fixtures/config/instanceof.expected.yml | 21 +++ .../Tests/Fixtures/config/instanceof.php | 24 +++ .../Tests/Fixtures/config/php7.expected.yml | 19 +++ .../Tests/Fixtures/config/php7.php | 21 +++ .../Fixtures/config/prototype.expected.yml | 25 +++ .../Tests/Fixtures/config/prototype.php | 24 +++ .../Tests/Fixtures/config/services9.php | 122 ++++++++++++++ .../Tests/Loader/PhpFileLoaderTest.php | 41 +++++ 47 files changed, 2048 insertions(+), 1 deletion(-) create mode 100644 src/Symfony/Component/DependencyInjection/Loader/Configurator/AbstractConfigurator.php create mode 100644 src/Symfony/Component/DependencyInjection/Loader/Configurator/AbstractServiceConfigurator.php create mode 100644 src/Symfony/Component/DependencyInjection/Loader/Configurator/AliasConfigurator.php create mode 100644 src/Symfony/Component/DependencyInjection/Loader/Configurator/ContainerConfigurator.php create mode 100644 src/Symfony/Component/DependencyInjection/Loader/Configurator/DefaultsConfigurator.php create mode 100644 src/Symfony/Component/DependencyInjection/Loader/Configurator/InlineServiceConfigurator.php create mode 100644 src/Symfony/Component/DependencyInjection/Loader/Configurator/InstanceofConfigurator.php create mode 100644 src/Symfony/Component/DependencyInjection/Loader/Configurator/ParametersConfigurator.php create mode 100644 src/Symfony/Component/DependencyInjection/Loader/Configurator/PrototypeConfigurator.php create mode 100644 src/Symfony/Component/DependencyInjection/Loader/Configurator/ReferenceConfigurator.php create mode 100644 src/Symfony/Component/DependencyInjection/Loader/Configurator/ServiceConfigurator.php create mode 100644 src/Symfony/Component/DependencyInjection/Loader/Configurator/ServicesConfigurator.php create mode 100644 src/Symfony/Component/DependencyInjection/Loader/Configurator/Traits/AbstractTrait.php create mode 100644 src/Symfony/Component/DependencyInjection/Loader/Configurator/Traits/ArgumentTrait.php create mode 100644 src/Symfony/Component/DependencyInjection/Loader/Configurator/Traits/AutoconfigureTrait.php create mode 100644 src/Symfony/Component/DependencyInjection/Loader/Configurator/Traits/AutowireTrait.php create mode 100644 src/Symfony/Component/DependencyInjection/Loader/Configurator/Traits/BindTrait.php create mode 100644 src/Symfony/Component/DependencyInjection/Loader/Configurator/Traits/CallTrait.php create mode 100644 src/Symfony/Component/DependencyInjection/Loader/Configurator/Traits/ClassTrait.php create mode 100644 src/Symfony/Component/DependencyInjection/Loader/Configurator/Traits/ConfiguratorTrait.php create mode 100644 src/Symfony/Component/DependencyInjection/Loader/Configurator/Traits/DecorateTrait.php create mode 100644 src/Symfony/Component/DependencyInjection/Loader/Configurator/Traits/DeprecateTrait.php create mode 100644 src/Symfony/Component/DependencyInjection/Loader/Configurator/Traits/FactoryTrait.php create mode 100644 src/Symfony/Component/DependencyInjection/Loader/Configurator/Traits/FileTrait.php create mode 100644 src/Symfony/Component/DependencyInjection/Loader/Configurator/Traits/LazyTrait.php create mode 100644 src/Symfony/Component/DependencyInjection/Loader/Configurator/Traits/ParentTrait.php create mode 100644 src/Symfony/Component/DependencyInjection/Loader/Configurator/Traits/PropertyTrait.php create mode 100644 src/Symfony/Component/DependencyInjection/Loader/Configurator/Traits/PublicTrait.php create mode 100644 src/Symfony/Component/DependencyInjection/Loader/Configurator/Traits/ShareTrait.php create mode 100644 src/Symfony/Component/DependencyInjection/Loader/Configurator/Traits/SyntheticTrait.php create mode 100644 src/Symfony/Component/DependencyInjection/Loader/Configurator/Traits/TagTrait.php create mode 100644 src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/basic.expected.yml create mode 100644 src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/basic.php create mode 100644 src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/child.expected.yml create mode 100644 src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/child.php create mode 100644 src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/defaults.expected.yml create mode 100644 src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/defaults.php create mode 100644 src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/instanceof.expected.yml create mode 100644 src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/instanceof.php create mode 100644 src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/php7.expected.yml create mode 100644 src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/php7.php create mode 100644 src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/prototype.expected.yml create mode 100644 src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/prototype.php create mode 100644 src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/services9.php diff --git a/src/Symfony/Component/DependencyInjection/Loader/Configurator/AbstractConfigurator.php b/src/Symfony/Component/DependencyInjection/Loader/Configurator/AbstractConfigurator.php new file mode 100644 index 0000000000000..2c4538e20144a --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Loader/Configurator/AbstractConfigurator.php @@ -0,0 +1,102 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Loader\Configurator; + +use Symfony\Component\DependencyInjection\Argument\ArgumentInterface; +use Symfony\Component\DependencyInjection\Definition; +use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; +use Symfony\Component\DependencyInjection\Parameter; +use Symfony\Component\DependencyInjection\Reference; +use Symfony\Component\ExpressionLanguage\Expression; + +abstract class AbstractConfigurator +{ + const FACTORY = 'unknown'; + + public function __call($method, $args) + { + if (method_exists($this, 'set'.$method)) { + return call_user_func_array(array($this, 'set'.$method), $args); + } + + throw new \BadMethodCallException(sprintf('Call to undefined method %s::%s()', get_class($this), $method)); + } + + /** + * Checks that a value is valid, optionally replacing Definition and Reference configurators by their configure value. + * + * @param mixed $value + * @param bool $allowServices whether Definition and Reference are allowed; by default, only scalars and arrays are + * + * @return mixed the value, optionaly cast to a Definition/Reference + */ + public static function processValue($value, $allowServices = false) + { + if (is_array($value)) { + foreach ($value as $k => $v) { + $value[$k] = static::processValue($v, $allowServices); + } + + return $value; + } + + if ($value instanceof ReferenceConfigurator) { + static $refCast; + + if (!$refCast) { + $refCast = \Closure::bind(function ($value) { + return new Reference($value->id, $value->invalidBehavior); + }, null, $value); + } + + // cast ReferenceConfigurator to Reference + return $refCast($value); + } + + if ($value instanceof InlineServiceConfigurator) { + static $defCast; + + if (!$defCast) { + $defCast = \Closure::bind(function ($value) { + $def = $value->definition; + $value->definition = null; + + return $def; + }, null, $value); + } + + // cast InlineServiceConfigurator to Definition + return $defCast($value); + } + + if ($value instanceof self) { + throw new InvalidArgumentException(sprintf('"%s()" can be used only at the root of service configuration files.', $value::FACTORY)); + } + + switch (true) { + case null === $value: + case is_scalar($value): + return $value; + + case $value instanceof ArgumentInterface: + case $value instanceof Definition: + case $value instanceof Expression: + case $value instanceof Parameter: + case $value instanceof Reference: + if ($allowServices) { + return $value; + } + } + + throw new InvalidArgumentException(sprintf('Cannot use values of type "%s" in service configuration files.', is_object($value) ? get_class($value) : gettype($value))); + } +} diff --git a/src/Symfony/Component/DependencyInjection/Loader/Configurator/AbstractServiceConfigurator.php b/src/Symfony/Component/DependencyInjection/Loader/Configurator/AbstractServiceConfigurator.php new file mode 100644 index 0000000000000..72ca7320b9f69 --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Loader/Configurator/AbstractServiceConfigurator.php @@ -0,0 +1,118 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Loader\Configurator; + +use Symfony\Component\DependencyInjection\Definition; +use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException; + +abstract class AbstractServiceConfigurator extends AbstractConfigurator +{ + protected $parent; + protected $definition; + protected $id; + protected $defaultTags = array(); + + public function __construct(ServicesConfigurator $parent, Definition $definition, $id = null, array $defaultTags = array()) + { + $this->parent = $parent; + $this->definition = $definition; + $this->id = $id; + $this->defaultTags = $defaultTags; + } + + public function __destruct() + { + // default tags should be added last + foreach ($this->defaultTags as $name => $attributes) { + foreach ($attributes as $attributes) { + $this->definition->addTag($name, $attributes); + } + } + $this->defaultTags = array(); + } + + /** + * Registers a service. + * + * @param string $id + * @param string|null $class + * + * @return ServiceConfigurator + */ + final public function set($id, $class = null) + { + $this->__destruct(); + + return $this->parent->set($id, $class); + } + + /** + * Creates an alias. + * + * @param string $id + * @param string $ref + * + * @return AliasConfigurator + */ + final public function alias($id, $referencedId) + { + $this->__destruct(); + + return $this->parent->alias($id, $referencedId); + } + + /** + * Registers a PSR-4 namespace using a glob pattern. + * + * @param string $namespace + * @param string $resource + * + * @return PrototypeConfigurator + */ + final public function load($namespace, $resource) + { + $this->__destruct(); + + return $this->parent->load($namespace, $resource); + } + + /** + * Gets an already defined service definition. + * + * @param string $id + * + * @return ServiceConfigurator + * + * @throws ServiceNotFoundException if the service definition does not exist + */ + final public function get($id) + { + $this->__destruct(); + + return $this->parent->get($id); + } + + /** + * Registers a service. + * + * @param string $id + * @param string|null $class + * + * @return ServiceConfigurator + */ + final public function __invoke($id, $class = null) + { + $this->__destruct(); + + return $this->parent->set($id, $class); + } +} diff --git a/src/Symfony/Component/DependencyInjection/Loader/Configurator/AliasConfigurator.php b/src/Symfony/Component/DependencyInjection/Loader/Configurator/AliasConfigurator.php new file mode 100644 index 0000000000000..cb00f58c049d4 --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Loader/Configurator/AliasConfigurator.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\Component\DependencyInjection\Loader\Configurator; + +use Symfony\Component\DependencyInjection\Alias; + +/** + * @author Nicolas Grekas + */ +class AliasConfigurator extends AbstractServiceConfigurator +{ + const FACTORY = 'alias'; + + use Traits\PublicTrait; + + public function __construct(ServicesConfigurator $parent, Alias $alias) + { + $this->parent = $parent; + $this->definition = $alias; + } +} diff --git a/src/Symfony/Component/DependencyInjection/Loader/Configurator/ContainerConfigurator.php b/src/Symfony/Component/DependencyInjection/Loader/Configurator/ContainerConfigurator.php new file mode 100644 index 0000000000000..132529087ab1d --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Loader/Configurator/ContainerConfigurator.php @@ -0,0 +1,128 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Loader\Configurator; + +use Symfony\Component\DependencyInjection\Argument\IteratorArgument; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Definition; +use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; +use Symfony\Component\DependencyInjection\Loader\PhpFileLoader; +use Symfony\Component\ExpressionLanguage\Expression; + +/** + * @author Nicolas Grekas + */ +class ContainerConfigurator extends AbstractConfigurator +{ + const FACTORY = 'container'; + + private $container; + private $loader; + private $instanceof; + private $path; + private $file; + + public function __construct(ContainerBuilder $container, PhpFileLoader $loader, &$instanceof, $path, $file) + { + $this->container = $container; + $this->loader = $loader; + $this->instanceof = &$instanceof; + $this->path = $path; + $this->file = $file; + } + + final public function extension($namespace, array $config) + { + if (!$this->container->hasExtension($namespace)) { + $extensions = array_filter(array_map(function ($ext) { return $ext->getAlias(); }, $this->container->getExtensions())); + throw new InvalidArgumentException(sprintf( + 'There is no extension able to load the configuration for "%s" (in %s). Looked for namespace "%s", found %s', + $namespace, + $this->file, + $namespace, + $extensions ? sprintf('"%s"', implode('", "', $extensions)) : 'none' + )); + } + + $this->container->loadFromExtension($namespace, static::processValue($config)); + } + + final public function import($resource, $type = null, $ignoreErrors = false) + { + $this->loader->setCurrentDir(dirname($this->path)); + $this->loader->import($resource, $type, $ignoreErrors, $this->file); + } + + /** + * @return ParametersConfigurator + */ + public function parameters() + { + return new ParametersConfigurator($this->container); + } + + /** + * @return ServicesConfigurator + */ + public function services() + { + return new ServicesConfigurator($this->container, $this->loader, $this->instanceof); + } +} + +/** + * Creates a service reference. + * + * @param string $id + * + * @return ReferenceConfigurator + */ +function ref($id) +{ + return new ReferenceConfigurator($id); +} + +/** + * Creates an inline service. + * + * @param string|null $class + * + * @return InlineServiceConfigurator + */ +function inline($class = null) +{ + return new InlineServiceConfigurator(new Definition($class)); +} + +/** + * Creates a lazy iterator. + * + * @param ReferenceConfigurator[] $values + * + * @return IteratorArgument + */ +function iterator(array $values) +{ + return new IteratorArgument(AbstractConfigurator::processValue($values, true)); +} + +/** + * Creates an expression. + * + * @param string $expression an expression + * + * @return Expression + */ +function expr($expression) +{ + return new Expression($expression); +} diff --git a/src/Symfony/Component/DependencyInjection/Loader/Configurator/DefaultsConfigurator.php b/src/Symfony/Component/DependencyInjection/Loader/Configurator/DefaultsConfigurator.php new file mode 100644 index 0000000000000..4c3f1dc0f8c31 --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Loader/Configurator/DefaultsConfigurator.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\Component\DependencyInjection\Loader\Configurator; + +use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; + +/** + * @author Nicolas Grekas + * + * @method InstanceofConfigurator instanceof(string $fqcn) + */ +class DefaultsConfigurator extends AbstractServiceConfigurator +{ + const FACTORY = 'defaults'; + + use Traits\AutoconfigureTrait; + use Traits\AutowireTrait; + use Traits\BindTrait; + use Traits\PublicTrait; + + /** + * Adds a tag for this definition. + * + * @param string $name The tag name + * @param array $attributes An array of attributes + * + * @return $this + * + * @throws InvalidArgumentException when an invalid tag name or attribute is provided + */ + final public function tag($name, array $attributes = array()) + { + if (!is_string($name) || '' === $name) { + throw new InvalidArgumentException(sprintf('The tag name in "_defaults" must be a non-empty string.')); + } + + foreach ($attributes as $attribute => $value) { + if (!is_scalar($value) && null !== $value) { + throw new InvalidArgumentException(sprintf('Tag "%s", attribute "%s" in "_defaults" must be of a scalar-type.', $name, $attribute)); + } + } + + $this->definition->addTag($name, $attributes); + + return $this; + } + + /** + * Defines an instanceof-conditional to be applied to following service definitions. + * + * @param string $fqcn + * + * @return InstanceofConfigurator + */ + final protected function setInstanceof($fqcn) + { + return $this->parent->instanceof($fqcn); + } +} diff --git a/src/Symfony/Component/DependencyInjection/Loader/Configurator/InlineServiceConfigurator.php b/src/Symfony/Component/DependencyInjection/Loader/Configurator/InlineServiceConfigurator.php new file mode 100644 index 0000000000000..362b374e55970 --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Loader/Configurator/InlineServiceConfigurator.php @@ -0,0 +1,36 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Loader\Configurator; + +use Symfony\Component\DependencyInjection\Definition; + +/** + * @author Nicolas Grekas + */ +class InlineServiceConfigurator extends AbstractConfigurator +{ + const FACTORY = 'inline'; + + use Traits\ArgumentTrait; + use Traits\AutowireTrait; + use Traits\BindTrait; + use Traits\FactoryTrait; + use Traits\FileTrait; + use Traits\LazyTrait; + use Traits\ParentTrait; + use Traits\TagTrait; + + public function __construct(Definition $definition) + { + $this->definition = $definition; + } +} diff --git a/src/Symfony/Component/DependencyInjection/Loader/Configurator/InstanceofConfigurator.php b/src/Symfony/Component/DependencyInjection/Loader/Configurator/InstanceofConfigurator.php new file mode 100644 index 0000000000000..1d3975bf8794e --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Loader/Configurator/InstanceofConfigurator.php @@ -0,0 +1,43 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Loader\Configurator; + +/** + * @author Nicolas Grekas + * + * @method InstanceofConfigurator instanceof(string $fqcn) + */ +class InstanceofConfigurator extends AbstractServiceConfigurator +{ + const FACTORY = 'instanceof'; + + use Traits\AutowireTrait; + use Traits\CallTrait; + use Traits\ConfiguratorTrait; + use Traits\LazyTrait; + use Traits\PropertyTrait; + use Traits\PublicTrait; + use Traits\ShareTrait; + use Traits\TagTrait; + + /** + * Defines an instanceof-conditional to be applied to following service definitions. + * + * @param string $fqcn + * + * @return InstanceofConfigurator + */ + final protected function setInstanceof($fqcn) + { + return $this->parent->instanceof($fqcn); + } +} diff --git a/src/Symfony/Component/DependencyInjection/Loader/Configurator/ParametersConfigurator.php b/src/Symfony/Component/DependencyInjection/Loader/Configurator/ParametersConfigurator.php new file mode 100644 index 0000000000000..0d81869e8bb50 --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Loader/Configurator/ParametersConfigurator.php @@ -0,0 +1,57 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Loader\Configurator; + +use Symfony\Component\DependencyInjection\ContainerBuilder; + +/** + * @author Nicolas Grekas + */ +class ParametersConfigurator extends AbstractConfigurator +{ + const FACTORY = 'parameters'; + + private $container; + + public function __construct(ContainerBuilder $container) + { + $this->container = $container; + } + + /** + * Creates a parameter. + * + * @param string $name + * @param string $value + * + * @return $this + */ + final public function set($name, $value) + { + $this->container->setParameter($name, static::processValue($value, true)); + + return $this; + } + + /** + * Creates a parameter. + * + * @param string $name + * @param string $value + * + * @return $this + */ + final public function __invoke($name, $value) + { + return $this->set($name, $value); + } +} diff --git a/src/Symfony/Component/DependencyInjection/Loader/Configurator/PrototypeConfigurator.php b/src/Symfony/Component/DependencyInjection/Loader/Configurator/PrototypeConfigurator.php new file mode 100644 index 0000000000000..76e7829e8fe99 --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Loader/Configurator/PrototypeConfigurator.php @@ -0,0 +1,84 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Loader\Configurator; + +use Symfony\Component\DependencyInjection\Definition; +use Symfony\Component\DependencyInjection\Loader\PhpFileLoader; + +/** + * @author Nicolas Grekas + */ +class PrototypeConfigurator extends AbstractServiceConfigurator +{ + const FACTORY = 'load'; + + use Traits\AbstractTrait; + use Traits\ArgumentTrait; + use Traits\AutoconfigureTrait; + use Traits\AutowireTrait; + use Traits\BindTrait; + use Traits\CallTrait; + use Traits\ConfiguratorTrait; + use Traits\DeprecateTrait; + use Traits\FactoryTrait; + use Traits\LazyTrait; + use Traits\ParentTrait; + use Traits\PropertyTrait; + use Traits\PublicTrait; + use Traits\ShareTrait; + use Traits\TagTrait; + + private $loader; + private $resource; + private $exclude; + private $allowParent; + + public function __construct(ServicesConfigurator $parent, PhpFileLoader $loader, Definition $defaults, $namespace, $resource, $allowParent) + { + $definition = new Definition(); + $definition->setPublic($defaults->isPublic()); + $definition->setAutowired($defaults->isAutowired()); + $definition->setAutoconfigured($defaults->isAutoconfigured()); + $definition->setBindings($defaults->getBindings()); + $definition->setChanges(array()); + + $this->loader = $loader; + $this->resource = $resource; + $this->allowParent = $allowParent; + + parent::__construct($parent, $definition, $namespace, $defaults->getTags()); + } + + public function __destruct() + { + parent::__destruct(); + + if ($this->loader) { + $this->loader->registerClasses($this->definition, $this->id, $this->resource, $this->exclude); + } + $this->loader = null; + } + + /** + * Excludes files from registration using a glob pattern. + * + * @param string $exclude + * + * @return $this + */ + final public function exclude($exclude) + { + $this->exclude = $exclude; + + return $this; + } +} diff --git a/src/Symfony/Component/DependencyInjection/Loader/Configurator/ReferenceConfigurator.php b/src/Symfony/Component/DependencyInjection/Loader/Configurator/ReferenceConfigurator.php new file mode 100644 index 0000000000000..93fdf3960e0dd --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Loader/Configurator/ReferenceConfigurator.php @@ -0,0 +1,63 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Loader\Configurator; + +use Symfony\Component\DependencyInjection\ContainerInterface; + +/** + * @author Nicolas Grekas + */ +class ReferenceConfigurator +{ + private $id; + private $invalidBehavior = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE; + + public function __construct($id) + { + $this->id = $id; + } + + /** + * @return $this + */ + final public function ignoreOnInvalid() + { + $this->invalidBehavior = ContainerInterface::IGNORE_ON_INVALID_REFERENCE; + + return $this; + } + + /** + * @return $this + */ + final public function nullOnInvalid() + { + $this->invalidBehavior = ContainerInterface::NULL_ON_INVALID_REFERENCE; + + return $this; + } + + /** + * @return $this + */ + final public function ignoreOnUninitialized() + { + $this->invalidBehavior = ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE; + + return $this; + } + + public function __toString() + { + return $this->id; + } +} diff --git a/src/Symfony/Component/DependencyInjection/Loader/Configurator/ServiceConfigurator.php b/src/Symfony/Component/DependencyInjection/Loader/Configurator/ServiceConfigurator.php new file mode 100644 index 0000000000000..12054cad0c021 --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Loader/Configurator/ServiceConfigurator.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\Component\DependencyInjection\Loader\Configurator; + +use Symfony\Component\DependencyInjection\ChildDefinition; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Definition; + +/** + * @author Nicolas Grekas + */ +class ServiceConfigurator extends AbstractServiceConfigurator +{ + const FACTORY = 'services'; + + use Traits\AbstractTrait; + use Traits\ArgumentTrait; + use Traits\AutoconfigureTrait; + use Traits\AutowireTrait; + use Traits\BindTrait; + use Traits\CallTrait; + use Traits\ClassTrait; + use Traits\ConfiguratorTrait; + use Traits\DecorateTrait; + use Traits\DeprecateTrait; + use Traits\FactoryTrait; + use Traits\FileTrait; + use Traits\LazyTrait; + use Traits\ParentTrait; + use Traits\PropertyTrait; + use Traits\PublicTrait; + use Traits\ShareTrait; + use Traits\SyntheticTrait; + use Traits\TagTrait; + + private $container; + private $instanceof; + private $allowParent; + + public function __construct(ContainerBuilder $container, array $instanceof, $allowParent, ServicesConfigurator $parent, Definition $definition, $id, array $defaultTags) + { + $this->container = $container; + $this->instanceof = $instanceof; + $this->allowParent = $allowParent; + + parent::__construct($parent, $definition, $id, $defaultTags); + } + + public function __destruct() + { + parent::__destruct(); + + if (!$this->definition instanceof ChildDefinition) { + $this->container->setDefinition($this->id, $this->definition->setInstanceofConditionals($this->instanceof)); + } else { + $this->container->setDefinition($this->id, $this->definition); + } + } +} diff --git a/src/Symfony/Component/DependencyInjection/Loader/Configurator/ServicesConfigurator.php b/src/Symfony/Component/DependencyInjection/Loader/Configurator/ServicesConfigurator.php new file mode 100644 index 0000000000000..390a0796988ca --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Loader/Configurator/ServicesConfigurator.php @@ -0,0 +1,154 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Loader\Configurator; + +use Symfony\Component\DependencyInjection\Alias; +use Symfony\Component\DependencyInjection\ChildDefinition; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Definition; +use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException; +use Symfony\Component\DependencyInjection\Loader\PhpFileLoader; + +/** + * @author Nicolas Grekas + * + * @method InstanceofConfigurator instanceof($fqcn) + */ +class ServicesConfigurator extends AbstractConfigurator +{ + const FACTORY = 'services'; + + private $defaults; + private $container; + private $loader; + private $instanceof; + + public function __construct(ContainerBuilder $container, PhpFileLoader $loader, array &$instanceof) + { + $this->defaults = new Definition(); + $this->container = $container; + $this->loader = $loader; + $this->instanceof = &$instanceof; + $instanceof = array(); + } + + /** + * Defines a set of defaults for following service definitions. + * + * @return DefaultsConfigurator + */ + public function defaults() + { + return new DefaultsConfigurator($this, $this->defaults = new Definition()); + } + + /** + * Defines an instanceof-conditional to be applied to following service definitions. + * + * @param string $fqcn + * + * @return InstanceofConfigurator + */ + final protected function setInstanceof($fqcn) + { + $this->instanceof[$fqcn] = $definition = new ChildDefinition(''); + + return new InstanceofConfigurator($this, $definition, $fqcn); + } + + /** + * Registers a service. + * + * @param string $id + * @param string|null $class + * + * @return ServiceConfigurator + */ + final public function set($id, $class = null) + { + $defaults = $this->defaults; + $allowParent = !$defaults->getChanges() && empty($this->instanceof); + + $definition = new Definition(); + $definition->setPublic($defaults->isPublic()); + $definition->setAutowired($defaults->isAutowired()); + $definition->setAutoconfigured($defaults->isAutoconfigured()); + $definition->setBindings($defaults->getBindings()); + $definition->setChanges(array()); + + $configurator = new ServiceConfigurator($this->container, $this->instanceof, $allowParent, $this, $definition, $id, $defaults->getTags()); + + return null !== $class ? $configurator->class($class) : $configurator; + } + + /** + * Creates an alias. + * + * @param string $id + * @param string $referencedId + * + * @return AliasConfigurator + */ + final public function alias($id, $referencedId) + { + $ref = static::processValue($referencedId, true); + $alias = new Alias((string) $ref, $this->defaults->isPublic()); + $this->container->setAlias($id, $alias); + + return new AliasConfigurator($this, $alias); + } + + /** + * Registers a PSR-4 namespace using a glob pattern. + * + * @param string $namespace + * @param string $resource + * + * @return PrototypeConfigurator + */ + final public function load($namespace, $resource) + { + $allowParent = !$this->defaults->getChanges() && empty($this->instanceof); + + return new PrototypeConfigurator($this, $this->loader, $this->defaults, $namespace, $resource, $allowParent); + } + + /** + * Gets an already defined service definition. + * + * @param string $id + * + * @return ServiceConfigurator + * + * @throws ServiceNotFoundException if the service definition does not exist + */ + final public function get($id) + { + $allowParent = !$this->defaults->getChanges() && empty($this->instanceof); + $definition = $this->container->getDefinition($id); + + return new ServiceConfigurator($this->container, $definition->getInstanceofConditionals(), $allowParent, $this, $definition, $id, array()); + } + + /** + * Registers a service. + * + * @param string $id + * @param string|null $class + * + * @return ServiceConfigurator + */ + final public function __invoke($id, $class = null) + { + return $this->set($id, $class); + } +} diff --git a/src/Symfony/Component/DependencyInjection/Loader/Configurator/Traits/AbstractTrait.php b/src/Symfony/Component/DependencyInjection/Loader/Configurator/Traits/AbstractTrait.php new file mode 100644 index 0000000000000..47e0dee287e0e --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Loader/Configurator/Traits/AbstractTrait.php @@ -0,0 +1,35 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Loader\Configurator\Traits; + +use Symfony\Component\DependencyInjection\Definition; + +/** + * @method $this abstract(bool $abstract = true) + */ +trait AbstractTrait +{ + /** + * Whether this definition is abstract, that means it merely serves as a + * template for other definitions. + * + * @param bool $abstract + * + * @return $this + */ + final protected function setAbstract($abstract = true) + { + $this->definition->setAbstract($abstract); + + return $this; + } +} diff --git a/src/Symfony/Component/DependencyInjection/Loader/Configurator/Traits/ArgumentTrait.php b/src/Symfony/Component/DependencyInjection/Loader/Configurator/Traits/ArgumentTrait.php new file mode 100644 index 0000000000000..7ec8c51d478e8 --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Loader/Configurator/Traits/ArgumentTrait.php @@ -0,0 +1,44 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Loader\Configurator\Traits; + +trait ArgumentTrait +{ + /** + * Sets the arguments to pass to the service constructor/factory method. + * + * @param array $arguments An array of arguments + * + * @return $this + */ + final public function args(array $arguments) + { + $this->definition->setArguments(static::processValue($arguments, true)); + + return $this; + } + + /** + * Sets one argument to pass to the service constructor/factory method. + * + * @param string|int $key + * @param mixed $value + * + * @return $this + */ + final public function arg($key, $value) + { + $this->definition->setArgument($key, static::processValue($value, true)); + + return $this; + } +} diff --git a/src/Symfony/Component/DependencyInjection/Loader/Configurator/Traits/AutoconfigureTrait.php b/src/Symfony/Component/DependencyInjection/Loader/Configurator/Traits/AutoconfigureTrait.php new file mode 100644 index 0000000000000..e3dccc9656951 --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Loader/Configurator/Traits/AutoconfigureTrait.php @@ -0,0 +1,36 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Loader\Configurator\Traits; + +use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; + +trait AutoconfigureTrait +{ + /** + * Sets whether or not instanceof conditionals should be prepended with a global set. + * + * @param bool $autoconfigured + * + * @return $this + * + * @throws InvalidArgumentException when a parent is already set + */ + final public function autoconfigure($autoconfigured = true) + { + if ($autoconfigured && $this->definition instanceof ChildDefinition) { + throw new InvalidArgumentException(sprintf('The service "%s" cannot have a "parent" and also have "autoconfigure". Try disabling autoconfiguration for the service.', $this->id)); + } + $this->definition->setAutoconfigured($autoconfigured); + + return $this; + } +} diff --git a/src/Symfony/Component/DependencyInjection/Loader/Configurator/Traits/AutowireTrait.php b/src/Symfony/Component/DependencyInjection/Loader/Configurator/Traits/AutowireTrait.php new file mode 100644 index 0000000000000..3d4b2e854b4c7 --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Loader/Configurator/Traits/AutowireTrait.php @@ -0,0 +1,29 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Loader\Configurator\Traits; + +trait AutowireTrait +{ + /** + * Enables/disables autowiring. + * + * @param bool $autowired + * + * @return $this + */ + final public function autowire($autowired = true) + { + $this->definition->setAutowired($autowired); + + return $this; + } +} diff --git a/src/Symfony/Component/DependencyInjection/Loader/Configurator/Traits/BindTrait.php b/src/Symfony/Component/DependencyInjection/Loader/Configurator/Traits/BindTrait.php new file mode 100644 index 0000000000000..4511ed659d4e5 --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Loader/Configurator/Traits/BindTrait.php @@ -0,0 +1,43 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Loader\Configurator\Traits; + +use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; +use Symfony\Component\DependencyInjection\Reference; + +trait BindTrait +{ + /** + * Sets bindings. + * + * Bindings map $named or FQCN arguments to values that should be + * injected in the matching parameters (of the constructor, of methods + * called and of controller actions). + * + * @param string $nameOrFqcn A parameter name with its "$" prefix, or a FQCN + * @param mixed $valueOrRef The value or reference to bind + * + * @return $this + */ + final public function bind($nameOrFqcn, $valueOrRef) + { + $valueOrRef = static::processValue($valueOrRef, true); + if (isset($nameOrFqcn[0]) && '$' !== $nameOrFqcn[0] && !$valueOrRef instanceof Reference) { + throw new InvalidArgumentException(sprintf('Invalid binding for service "%s": named arguments must start with a "$", and FQCN must map to references. Neither applies to binding "%s".', $this->id, $nameOrFqcn)); + } + $bindings = $this->definition->getBindings(); + $bindings[$nameOrFqcn] = $valueOrRef; + $this->definition->setBindings($bindings); + + return $this; + } +} diff --git a/src/Symfony/Component/DependencyInjection/Loader/Configurator/Traits/CallTrait.php b/src/Symfony/Component/DependencyInjection/Loader/Configurator/Traits/CallTrait.php new file mode 100644 index 0000000000000..abc14e2155591 --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Loader/Configurator/Traits/CallTrait.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\Component\DependencyInjection\Loader\Configurator\Traits; + +use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; + +trait CallTrait +{ + /** + * Adds a method to call after service initialization. + * + * @param string $method The method name to call + * @param array $arguments An array of arguments to pass to the method call + * + * @return $this + * + * @throws InvalidArgumentException on empty $method param + */ + final public function call($method, array $arguments = array()) + { + $this->definition->addMethodCall($method, static::processValue($arguments, true)); + + return $this; + } +} diff --git a/src/Symfony/Component/DependencyInjection/Loader/Configurator/Traits/ClassTrait.php b/src/Symfony/Component/DependencyInjection/Loader/Configurator/Traits/ClassTrait.php new file mode 100644 index 0000000000000..ae5b1c0a3d0c5 --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Loader/Configurator/Traits/ClassTrait.php @@ -0,0 +1,32 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Loader\Configurator\Traits; + +/** + * @method $this class(string $class) + */ +trait ClassTrait +{ + /** + * Sets the service class. + * + * @param string $class The service class + * + * @return $this + */ + final protected function setClass($class) + { + $this->definition->setClass($class); + + return $this; + } +} diff --git a/src/Symfony/Component/DependencyInjection/Loader/Configurator/Traits/ConfiguratorTrait.php b/src/Symfony/Component/DependencyInjection/Loader/Configurator/Traits/ConfiguratorTrait.php new file mode 100644 index 0000000000000..a38283b0e739b --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Loader/Configurator/Traits/ConfiguratorTrait.php @@ -0,0 +1,29 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Loader\Configurator\Traits; + +trait ConfiguratorTrait +{ + /** + * Sets a configurator to call after the service is fully initialized. + * + * @param string|array $configurator A PHP callable reference + * + * @return $this + */ + final public function configurator($configurator) + { + $this->definition->setConfigurator(static::processValue($configurator, true)); + + return $this; + } +} diff --git a/src/Symfony/Component/DependencyInjection/Loader/Configurator/Traits/DecorateTrait.php b/src/Symfony/Component/DependencyInjection/Loader/Configurator/Traits/DecorateTrait.php new file mode 100644 index 0000000000000..0891fd90612d4 --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Loader/Configurator/Traits/DecorateTrait.php @@ -0,0 +1,35 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Loader\Configurator\Traits; + +use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; + +trait DecorateTrait +{ + /** + * Sets the service that this service is decorating. + * + * @param null|string $id The decorated service id, use null to remove decoration + * @param null|string $renamedId The new decorated service id + * @param int $priority The priority of decoration + * + * @return $this + * + * @throws InvalidArgumentException in case the decorated service id and the new decorated service id are equals + */ + final public function decorate($id, $renamedId = null, $priority = 0) + { + $this->definition->setDecoratedService($id, $renamedId, $priority); + + return $this; + } +} diff --git a/src/Symfony/Component/DependencyInjection/Loader/Configurator/Traits/DeprecateTrait.php b/src/Symfony/Component/DependencyInjection/Loader/Configurator/Traits/DeprecateTrait.php new file mode 100644 index 0000000000000..331be473e216c --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Loader/Configurator/Traits/DeprecateTrait.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\Component\DependencyInjection\Loader\Configurator\Traits; + +use Symfony\Component\DependencyInjection\Definition; +use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; + +trait DeprecateTrait +{ + /** + * Whether this definition is deprecated, that means it should not be called anymore. + * + * @param string $template Template message to use if the definition is deprecated + * + * @return $this + * + * @throws InvalidArgumentException when the message template is invalid + */ + final public function deprecate($template = null) + { + $this->definition->setDeprecated(true, $template); + + return $this; + } +} diff --git a/src/Symfony/Component/DependencyInjection/Loader/Configurator/Traits/FactoryTrait.php b/src/Symfony/Component/DependencyInjection/Loader/Configurator/Traits/FactoryTrait.php new file mode 100644 index 0000000000000..71c15906cc9af --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Loader/Configurator/Traits/FactoryTrait.php @@ -0,0 +1,29 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Loader\Configurator\Traits; + +trait FactoryTrait +{ + /** + * Sets a factory. + * + * @param string|array $factory A PHP callable reference + * + * @return $this + */ + final public function factory($factory) + { + $this->definition->setFactory(static::processValue($factory, true)); + + return $this; + } +} diff --git a/src/Symfony/Component/DependencyInjection/Loader/Configurator/Traits/FileTrait.php b/src/Symfony/Component/DependencyInjection/Loader/Configurator/Traits/FileTrait.php new file mode 100644 index 0000000000000..895f5304c3e74 --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Loader/Configurator/Traits/FileTrait.php @@ -0,0 +1,29 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Loader\Configurator\Traits; + +trait FileTrait +{ + /** + * Sets a file to require before creating the service. + * + * @param string $file A full pathname to include + * + * @return $this + */ + final public function file($file) + { + $this->definition->setFile($file); + + return $this; + } +} diff --git a/src/Symfony/Component/DependencyInjection/Loader/Configurator/Traits/LazyTrait.php b/src/Symfony/Component/DependencyInjection/Loader/Configurator/Traits/LazyTrait.php new file mode 100644 index 0000000000000..d7ea8b27f5ea3 --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Loader/Configurator/Traits/LazyTrait.php @@ -0,0 +1,29 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Loader\Configurator\Traits; + +trait LazyTrait +{ + /** + * Sets the lazy flag of this service. + * + * @param bool $lazy + * + * @return $this + */ + final public function lazy($lazy = true) + { + $this->definition->setLazy($lazy); + + return $this; + } +} diff --git a/src/Symfony/Component/DependencyInjection/Loader/Configurator/Traits/ParentTrait.php b/src/Symfony/Component/DependencyInjection/Loader/Configurator/Traits/ParentTrait.php new file mode 100644 index 0000000000000..651f94e617129 --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Loader/Configurator/Traits/ParentTrait.php @@ -0,0 +1,53 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Loader\Configurator\Traits; + +use Symfony\Component\DependencyInjection\ChildDefinition; +use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; + +/** + * @method $this parent(string $parent) + */ +trait ParentTrait +{ + /** + * Sets the Definition to inherit from. + * + * @param string $parent + * + * @return $this + * + * @throws InvalidArgumentException when parent cannot be set + */ + final protected function setParent($parent) + { + if (!$this->allowParent) { + throw new InvalidArgumentException(sprintf('A parent cannot be defined when either "_instanceof" or "_defaults" are also defined for service prototype "%s".', $this->id)); + } + + if ($this->definition instanceof ChildDefinition) { + $this->definition->setParent($parent); + } elseif ($this->definition->isAutoconfigured()) { + throw new InvalidArgumentException(sprintf('The service "%s" cannot have a "parent" and also have "autoconfigure". Try disabling autoconfiguration for the service.', $this->id)); + } else { + // cast Definition to ChildDefinition + $definition = serialize($this->definition); + $definition = substr_replace($definition, '53', 2, 2); + $definition = substr_replace($definition, 'Child', 44, 0); + $definition = unserialize($definition); + + $this->definition = $definition->setParent($parent); + } + + return $this; + } +} diff --git a/src/Symfony/Component/DependencyInjection/Loader/Configurator/Traits/PropertyTrait.php b/src/Symfony/Component/DependencyInjection/Loader/Configurator/Traits/PropertyTrait.php new file mode 100644 index 0000000000000..d5d938708e0a8 --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Loader/Configurator/Traits/PropertyTrait.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\Component\DependencyInjection\Loader\Configurator\Traits; + +trait PropertyTrait +{ + /** + * Sets a specific property. + * + * @param string $name + * @param mixed $value + * + * @return $this + */ + final public function property($name, $value) + { + $this->definition->setProperty($name, static::processValue($value, true)); + + return $this; + } +} diff --git a/src/Symfony/Component/DependencyInjection/Loader/Configurator/Traits/PublicTrait.php b/src/Symfony/Component/DependencyInjection/Loader/Configurator/Traits/PublicTrait.php new file mode 100644 index 0000000000000..8f7f79f1cc218 --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Loader/Configurator/Traits/PublicTrait.php @@ -0,0 +1,39 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Loader\Configurator\Traits; + +/** + * @method $this public() + * @method $this private() + */ +trait PublicTrait +{ + /** + * @return $this + */ + final protected function setPublic() + { + $this->definition->setPublic(true); + + return $this; + } + + /** + * @return $this + */ + final protected function setPrivate() + { + $this->definition->setPublic(false); + + return $this; + } +} diff --git a/src/Symfony/Component/DependencyInjection/Loader/Configurator/Traits/ShareTrait.php b/src/Symfony/Component/DependencyInjection/Loader/Configurator/Traits/ShareTrait.php new file mode 100644 index 0000000000000..1c2f97b59761c --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Loader/Configurator/Traits/ShareTrait.php @@ -0,0 +1,29 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Loader\Configurator\Traits; + +trait ShareTrait +{ + /** + * Sets if the service must be shared or not. + * + * @param bool $shared Whether the service must be shared or not + * + * @return $this + */ + final public function share($shared = true) + { + $this->definition->setShared($shared); + + return $this; + } +} diff --git a/src/Symfony/Component/DependencyInjection/Loader/Configurator/Traits/SyntheticTrait.php b/src/Symfony/Component/DependencyInjection/Loader/Configurator/Traits/SyntheticTrait.php new file mode 100644 index 0000000000000..81eceff43d86d --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Loader/Configurator/Traits/SyntheticTrait.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\Component\DependencyInjection\Loader\Configurator\Traits; + +trait SyntheticTrait +{ + /** + * Sets whether this definition is synthetic, that is not constructed by the + * container, but dynamically injected. + * + * @param bool $synthetic + * + * @return $this + */ + final public function synthetic($synthetic = true) + { + $this->definition->setSynthetic($synthetic); + + return $this; + } +} diff --git a/src/Symfony/Component/DependencyInjection/Loader/Configurator/Traits/TagTrait.php b/src/Symfony/Component/DependencyInjection/Loader/Configurator/Traits/TagTrait.php new file mode 100644 index 0000000000000..4094acdbfce91 --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Loader/Configurator/Traits/TagTrait.php @@ -0,0 +1,43 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Loader\Configurator\Traits; + +use Symfony\Component\DependencyInjection\Definition; +use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; + +trait TagTrait +{ + /** + * Adds a tag for this definition. + * + * @param string $name The tag name + * @param array $attributes An array of attributes + * + * @return $this + */ + final public function tag($name, array $attributes = array()) + { + if (!is_string($name) || '' === $name) { + throw new InvalidArgumentException(sprintf('The tag name for service "%s" must be a non-empty string.', $this->id)); + } + + foreach ($attributes as $attribute => $value) { + if (!is_scalar($value) && null !== $value) { + throw new InvalidArgumentException(sprintf('A tag attribute must be of a scalar-type for service "%s", tag "%s", attribute "%s".', $this->id, $name, $attribute)); + } + } + + $this->definition->addTag($name, $attributes); + + return $this; + } +} diff --git a/src/Symfony/Component/DependencyInjection/Loader/PhpFileLoader.php b/src/Symfony/Component/DependencyInjection/Loader/PhpFileLoader.php index 9d887e4af03f6..f0be7534ea67d 100644 --- a/src/Symfony/Component/DependencyInjection/Loader/PhpFileLoader.php +++ b/src/Symfony/Component/DependencyInjection/Loader/PhpFileLoader.php @@ -11,6 +11,8 @@ namespace Symfony\Component\DependencyInjection\Loader; +use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator; + /** * PhpFileLoader loads service definitions from a PHP file. * @@ -34,7 +36,16 @@ public function load($resource, $type = null) $this->setCurrentDir(dirname($path)); $this->container->fileExists($path); - include $path; + // the closure forbids access to the private scope in the included file + $load = \Closure::bind(function ($path) use ($container, $loader, $resource, $type) { + return include $path; + }, $this, ProtectedPhpFileLoader::class); + + $callback = $load($path); + + if ($callback instanceof \Closure) { + $callback(new ContainerConfigurator($this->container, $this, $this->instanceof, $path, $resource), $this->container, $this); + } } /** @@ -53,3 +64,10 @@ public function supports($resource, $type = null) return 'php' === $type; } } + +/** + * @internal + */ +final class ProtectedPhpFileLoader extends PhpFileLoader +{ +} diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/Prototype/Foo.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/Prototype/Foo.php index 1e4f283c8f16e..ee533fecd9019 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/Prototype/Foo.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/Prototype/Foo.php @@ -4,4 +4,11 @@ class Foo { + public function __construct($bar = null) + { + } + + function setFoo(self $foo) + { + } } diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/basic.expected.yml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/basic.expected.yml new file mode 100644 index 0000000000000..1137961ade139 --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/basic.expected.yml @@ -0,0 +1,10 @@ + +services: + service_container: + class: Symfony\Component\DependencyInjection\ContainerInterface + public: true + synthetic: true + App\BarService: + class: App\BarService + public: true + arguments: [!service { class: FooClass }] diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/basic.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/basic.php new file mode 100644 index 0000000000000..bab4e1ec83f04 --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/basic.php @@ -0,0 +1,13 @@ +services(); + $s->set(BarService::class) + ->args(array(inline('FooClass'))); + +}; diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/child.expected.yml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/child.expected.yml new file mode 100644 index 0000000000000..aaab7131c4697 --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/child.expected.yml @@ -0,0 +1,15 @@ + +services: + service_container: + class: Symfony\Component\DependencyInjection\ContainerInterface + public: true + synthetic: true + foo: + class: Class2 + public: true + file: file.php + lazy: true + arguments: [!service { class: Class1, public: false }] + bar: + alias: foo + public: true diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/child.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/child.php new file mode 100644 index 0000000000000..30178217b6924 --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/child.php @@ -0,0 +1,24 @@ +services() + ->set('bar', 'Class1') + ->set(BarService::class) + ->abstract(true) + ->lazy() + ->set('foo') + ->parent(BarService::class) + ->decorate('bar', 'b', 1) + ->args(array(ref('b'))) + ->class('Class2') + ->file('file.php') + ->parent('bar') + ->parent(BarService::class) + ; + +}; diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/defaults.expected.yml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/defaults.expected.yml new file mode 100644 index 0000000000000..a534f7267a078 --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/defaults.expected.yml @@ -0,0 +1,27 @@ + +services: + service_container: + class: Symfony\Component\DependencyInjection\ContainerInterface + public: true + synthetic: true + App\BarService: + class: App\BarService + public: true + arguments: [!service { class: FooClass }] + Symfony\Component\DependencyInjection\Tests\Fixtures\Prototype\Foo: + class: Symfony\Component\DependencyInjection\Tests\Fixtures\Prototype\Foo + public: true + tags: + - { name: t, a: b } + autowire: true + autoconfigure: true + arguments: ['@bar'] + bar: + class: Symfony\Component\DependencyInjection\Tests\Fixtures\Prototype\Foo + public: false + tags: + - { name: t, a: b } + autowire: true + calls: + - [setFoo, ['@bar']] + diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/defaults.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/defaults.php new file mode 100644 index 0000000000000..7fa93d2a91d73 --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/defaults.php @@ -0,0 +1,23 @@ +import('basic.php'); + + $s = $c->services()->defaults() + ->public() + ->private() + ->autoconfigure() + ->autowire() + ->tag('t', array('a' => 'b')) + ->bind(Foo::class, ref('bar')) + ->private(); + + $s->set(Foo::class)->args(array(ref('bar')))->public(); + $s->set('bar', Foo::class)->call('setFoo')->autoconfigure(false); + +}; diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/instanceof.expected.yml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/instanceof.expected.yml new file mode 100644 index 0000000000000..b12a304221dd8 --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/instanceof.expected.yml @@ -0,0 +1,21 @@ + +services: + service_container: + class: Symfony\Component\DependencyInjection\ContainerInterface + public: true + synthetic: true + Symfony\Component\DependencyInjection\Tests\Fixtures\Prototype\Foo: + class: Symfony\Component\DependencyInjection\Tests\Fixtures\Prototype\Foo + public: true + tags: + - { name: tag, k: v } + lazy: true + properties: { p: 1 } + calls: + - [setFoo, ['@foo']] + + shared: false + configurator: c + foo: + class: App\FooService + public: true diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/instanceof.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/instanceof.php new file mode 100644 index 0000000000000..13d0213bf11e5 --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/instanceof.php @@ -0,0 +1,24 @@ +services(); + $s->instanceof(Prototype\Foo::class) + ->property('p', 0) + ->call('setFoo', array(ref('foo'))) + ->tag('tag', array('k' => 'v')) + ->share(false) + ->lazy() + ->configurator('c') + ->property('p', 1); + + $s->load(Prototype::class.'\\', '../Prototype')->exclude('../Prototype/*/*'); + + $s->set('foo', FooService::class); + +}; diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/php7.expected.yml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/php7.expected.yml new file mode 100644 index 0000000000000..7c5b714ffbd7e --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/php7.expected.yml @@ -0,0 +1,19 @@ +parameters: + foo: Foo + bar: Bar + +services: + service_container: + class: Symfony\Component\DependencyInjection\ContainerInterface + public: true + synthetic: true + Symfony\Component\DependencyInjection\Tests\Fixtures\Prototype\Foo: + class: Symfony\Component\DependencyInjection\Tests\Fixtures\Prototype\Foo + public: true + arguments: ['@bar'] + bar: + class: Symfony\Component\DependencyInjection\Tests\Fixtures\Prototype\Foo + public: true + calls: + - [setFoo, { }] + diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/php7.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/php7.php new file mode 100644 index 0000000000000..22a98c2c571d5 --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/php7.php @@ -0,0 +1,21 @@ +parameters() + ('foo', 'Foo') + ('bar', 'Bar') + ; + $c->services() + (Foo::class) + ->arg('$bar', ref('bar')) + ->public() + ('bar', Foo::class) + ->call('setFoo') + ; + +}; diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/prototype.expected.yml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/prototype.expected.yml new file mode 100644 index 0000000000000..5394535caf1d8 --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/prototype.expected.yml @@ -0,0 +1,25 @@ + +services: + service_container: + class: Symfony\Component\DependencyInjection\ContainerInterface + public: true + synthetic: true + Symfony\Component\DependencyInjection\Tests\Fixtures\Prototype\Foo: + class: Symfony\Component\DependencyInjection\Tests\Fixtures\Prototype\Foo + public: true + tags: + - { name: foo } + - { name: baz } + deprecated: %service_id% + arguments: [1] + factory: f + Symfony\Component\DependencyInjection\Tests\Fixtures\Prototype\Sub\Bar: + class: Symfony\Component\DependencyInjection\Tests\Fixtures\Prototype\Sub\Bar + public: true + tags: + - { name: foo } + - { name: baz } + deprecated: %service_id% + lazy: true + arguments: [1] + factory: f diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/prototype.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/prototype.php new file mode 100644 index 0000000000000..77bc132dcb78a --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/prototype.php @@ -0,0 +1,24 @@ +services()->defaults() + ->tag('baz'); + $di->load(Prototype::class.'\\', '../Prototype') + ->autoconfigure() + ->exclude('../Prototype/{OtherDir}') + ->factory('f') + ->deprecate('%service_id%') + ->args(array(0)) + ->args(array(1)) + ->autoconfigure(false) + ->tag('foo') + ->parent('foo'); + $di->set('foo')->lazy()->abstract(); + $di->get(Prototype\Foo::class)->lazy(false); + +}; diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/services9.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/services9.php new file mode 100644 index 0000000000000..85543b6ebbcc7 --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/services9.php @@ -0,0 +1,122 @@ +parameters(); + $p->set('baz_class', 'BazClass'); + $p->set('foo_class', FooClass::class) + ->set('foo', 'bar'); + + $s = $c->services(); + $s->set('foo') + ->args(array('foo', ref('foo.baz'), array('%foo%' => 'foo is %foo%', 'foobar' => '%foo%'), true, ref('service_container'))) + ->class(FooClass::class) + ->tag('foo', array('foo' => 'foo')) + ->tag('foo', array('bar' => 'bar', 'baz' => 'baz')) + ->factory(array(FooClass::class, 'getInstance')) + ->property('foo', 'bar') + ->property('moo', ref('foo.baz')) + ->property('qux', array('%foo%' => 'foo is %foo%', 'foobar' => '%foo%')) + ->call('setBar', array(ref('bar'))) + ->call('initialize') + ->configurator('sc_configure'); + + $s->set('foo.baz', '%baz_class%') + ->factory(array('%baz_class%', 'getInstance')) + ->configurator(array('%baz_class%', 'configureStatic1')); + + $s->set('bar', FooClass::class) + ->args(array('foo', ref('foo.baz'), new Parameter('foo_bar'))) + ->configurator(array(ref('foo.baz'), 'configure')); + + $s->set('foo_bar', '%foo_class%') + ->args(array(ref('deprecated_service'))) + ->share(false); + + $s->alias('alias_for_foo', 'foo')->private()->public(); + $s->alias('alias_for_alias', ref('alias_for_foo')); + + $s->set('method_call1', 'Bar\FooClass') + ->file(realpath(__DIR__.'/../includes/foo.php')) + ->call('setBar', array(ref('foo'))) + ->call('setBar', array(ref('foo2')->nullOnInvalid())) + ->call('setBar', array(ref('foo3')->ignoreOnInvalid())) + ->call('setBar', array(ref('foobaz')->ignoreOnInvalid())) + ->call('setBar', array(expr('service("foo").foo() ~ (container.hasParameter("foo") ? parameter("foo") : "default")'))); + + $s->set('foo_with_inline', 'Foo') + ->call('setBar', array(ref('inlined'))); + + $s->set('inlined', 'Bar') + ->property('pub', 'pub') + ->call('setBaz', array(ref('baz'))) + ->private(); + + $s->set('baz', 'Baz') + ->call('setFoo', array(ref('foo_with_inline'))); + + $s->set('request', 'Request') + ->synthetic(); + + $s->set('configurator_service', 'ConfClass') + ->private() + ->call('setFoo', array(ref('baz'))); + + $s->set('configured_service', 'stdClass') + ->configurator(array(ref('configurator_service'), 'configureStdClass')); + + $s->set('configurator_service_simple', 'ConfClass') + ->args(array('bar')) + ->private(); + + $s->set('configured_service_simple', 'stdClass') + ->configurator(array(ref('configurator_service_simple'), 'configureStdClass')); + + $s->set('decorated', 'stdClass'); + + $s->set('decorator_service', 'stdClass') + ->decorate('decorated'); + + $s->set('decorator_service_with_name', 'stdClass') + ->decorate('decorated', 'decorated.pif-pouf'); + + $s->set('deprecated_service', 'stdClass') + ->deprecate(); + + $s->set('new_factory', 'FactoryClass') + ->property('foo', 'bar') + ->private(); + + $s->set('factory_service', 'Bar') + ->factory(array(ref('foo.baz'), 'getInstance')); + + $s->set('new_factory_service', 'FooBarBaz') + ->property('foo', 'bar') + ->factory(array(ref('new_factory'), 'getInstance')); + + $s->set('service_from_static_method', 'Bar\FooClass') + ->factory(array('Bar\FooClass', 'getInstance')); + + $s->set('factory_simple', 'SimpleFactoryClass') + ->deprecate() + ->args(array('foo')) + ->private(); + + $s->set('factory_service_simple', 'Bar') + ->factory(array(ref('factory_simple'), 'getInstance')); + + $s->set('lazy_context', 'LazyContext') + ->args(array(iterator(array('k1' => ref('foo.baz'), 'k2' => ref('service_container'))), iterator(array()))); + + $s->set('lazy_context_ignore_invalid_ref', 'LazyContext') + ->args(array(iterator(array(ref('foo.baz'), ref('invalid')->ignoreOnInvalid())), iterator(array()))); + +}; diff --git a/src/Symfony/Component/DependencyInjection/Tests/Loader/PhpFileLoaderTest.php b/src/Symfony/Component/DependencyInjection/Tests/Loader/PhpFileLoaderTest.php index 4e01e6fae9c25..02f84311e689c 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Loader/PhpFileLoaderTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Loader/PhpFileLoaderTest.php @@ -13,6 +13,8 @@ use PHPUnit\Framework\TestCase; use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Dumper\PhpDumper; +use Symfony\Component\DependencyInjection\Dumper\YamlDumper; use Symfony\Component\DependencyInjection\Loader\PhpFileLoader; use Symfony\Component\Config\FileLocator; @@ -35,4 +37,43 @@ public function testLoad() $this->assertEquals('foo', $container->getParameter('foo'), '->load() loads a PHP file resource'); } + + public function testConfigServices() + { + $fixtures = realpath(__DIR__.'/../Fixtures'); + $loader = new PhpFileLoader($container = new ContainerBuilder(), new FileLocator()); + $loader->load($fixtures.'/config/services9.php'); + + $container->compile(); + $dumper = new PhpDumper($container); + $this->assertStringEqualsFile($fixtures.'/php/services9_compiled.php', str_replace(str_replace('\\', '\\\\', $fixtures.DIRECTORY_SEPARATOR.'includes'.DIRECTORY_SEPARATOR), '%path%', $dumper->dump())); + } + + /** + * @dataProvider provideConfig + */ + public function testConfig($file) + { + $fixtures = realpath(__DIR__.'/../Fixtures'); + $loader = new PhpFileLoader($container = new ContainerBuilder(), new FileLocator()); + $loader->load($fixtures.'/config/'.$file.'.php'); + + $container->compile(); + + $dumper = new YamlDumper($container); + $this->assertStringEqualsFile($fixtures.'/config/'.$file.'.expected.yml', $dumper->dump()); + } + + public function provideConfig() + { + yield array('basic'); + yield array('defaults'); + yield array('instanceof'); + yield array('prototype'); + yield array('child'); + + if (\PHP_VERSION_ID >= 70000) { + yield array('php7'); + } + } } From 6973a1ae3bb171024a1ce21f68d3bcc978aa476c Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Tue, 19 Sep 2017 12:45:06 +0200 Subject: [PATCH 0864/1099] [HttpKernel][DI] Enable Kernel to implement CompilerPassInterface --- UPGRADE-4.0.md | 2 ++ .../DependencyInjection/CHANGELOG.md | 1 + .../Compiler/PassConfig.php | 2 +- src/Symfony/Component/HttpKernel/CHANGELOG.md | 1 + src/Symfony/Component/HttpKernel/Kernel.php | 5 ++++ .../Component/HttpKernel/Tests/KernelTest.php | 23 +++++++++++++++++++ 6 files changed, 33 insertions(+), 1 deletion(-) diff --git a/UPGRADE-4.0.md b/UPGRADE-4.0.md index fba86ef01c971..3aecb70070f0d 100644 --- a/UPGRADE-4.0.md +++ b/UPGRADE-4.0.md @@ -184,6 +184,8 @@ DependencyInjection * Top-level anonymous services in XML are no longer supported. + * The `ExtensionCompilerPass` has been moved to before-optimization passes with priority -1000. + EventDispatcher --------------- diff --git a/src/Symfony/Component/DependencyInjection/CHANGELOG.md b/src/Symfony/Component/DependencyInjection/CHANGELOG.md index bc8fd3051870c..cea65b20b7504 100644 --- a/src/Symfony/Component/DependencyInjection/CHANGELOG.md +++ b/src/Symfony/Component/DependencyInjection/CHANGELOG.md @@ -4,6 +4,7 @@ CHANGELOG 3.4.0 ----- + * moved the `ExtensionCompilerPass` to before-optimization passes with priority -1000 * deprecated "public-by-default" definitions and aliases, the new default will be "private" in 4.0 * added `EnvVarProcessorInterface` and corresponding "container.env_var_processor" tag for processing env vars * added support for ignore-on-uninitialized references diff --git a/src/Symfony/Component/DependencyInjection/Compiler/PassConfig.php b/src/Symfony/Component/DependencyInjection/Compiler/PassConfig.php index 9e00be6827109..79792bee4a106 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/PassConfig.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/PassConfig.php @@ -45,10 +45,10 @@ public function __construct() new ResolveInstanceofConditionalsPass(), new RegisterEnvVarProcessorsPass(), ), + -1000 => array(new ExtensionCompilerPass()), ); $this->optimizationPasses = array(array( - new ExtensionCompilerPass(), new ResolveChildDefinitionsPass(), new ServiceLocatorTagPass(), new DecoratorServicePass(), diff --git a/src/Symfony/Component/HttpKernel/CHANGELOG.md b/src/Symfony/Component/HttpKernel/CHANGELOG.md index 702394ade5bd4..8732b17dd83f5 100644 --- a/src/Symfony/Component/HttpKernel/CHANGELOG.md +++ b/src/Symfony/Component/HttpKernel/CHANGELOG.md @@ -4,6 +4,7 @@ CHANGELOG 3.4.0 ----- + * made kernels implementing `CompilerPassInterface` able to process the container * deprecated bundle inheritance * added `RebootableInterface` and implemented it in `Kernel` * deprecated commands auto registration diff --git a/src/Symfony/Component/HttpKernel/Kernel.php b/src/Symfony/Component/HttpKernel/Kernel.php index 4f7ec2c289bac..cd4c26063d5d9 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -13,6 +13,8 @@ use Symfony\Bridge\ProxyManager\LazyProxy\Instantiator\RuntimeInstantiator; use Symfony\Bridge\ProxyManager\LazyProxy\PhpDumper\ProxyDumper; +use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; +use Symfony\Component\DependencyInjection\Compiler\PassConfig; use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Dumper\PhpDumper; @@ -767,6 +769,9 @@ protected function getContainerBuilder() $container = new ContainerBuilder(); $container->getParameterBag()->add($this->getKernelParameters()); + if ($this instanceof CompilerPassInterface) { + $container->addCompilerPass($this, PassConfig::TYPE_BEFORE_OPTIMIZATION, -10000); + } if (class_exists('ProxyManager\Configuration') && class_exists('Symfony\Bridge\ProxyManager\LazyProxy\Instantiator\RuntimeInstantiator')) { $container->setProxyInstantiator(new RuntimeInstantiator()); } diff --git a/src/Symfony/Component/HttpKernel/Tests/KernelTest.php b/src/Symfony/Component/HttpKernel/Tests/KernelTest.php index a408f87f87a32..fd7f6f09da13d 100644 --- a/src/Symfony/Component/HttpKernel/Tests/KernelTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/KernelTest.php @@ -13,6 +13,7 @@ use PHPUnit\Framework\TestCase; use Symfony\Component\Config\Loader\LoaderInterface; +use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\Filesystem\Filesystem; use Symfony\Component\HttpKernel\Bundle\BundleInterface; @@ -831,6 +832,14 @@ public function testKernelReset() $this->assertFileNotExists($containerFile); } + public function testKernelPass() + { + $kernel = new PassKernel(); + $kernel->boot(); + + $this->assertTrue($kernel->getContainer()->getParameter('test.processed')); + } + /** * Returns a mock for the BundleInterface. * @@ -967,3 +976,17 @@ protected function build(ContainerBuilder $container) } } } + +class PassKernel extends CustomProjectDirKernel implements CompilerPassInterface +{ + public function __construct(\Closure $buildContainer = null) + { + parent::__construct(); + Kernel::__construct('pass', true); + } + + public function process(ContainerBuilder $container) + { + $container->setParameter('test.processed', true); + } +} From 03cd9e553b26008707b82388f41910c49cbb9f7f Mon Sep 17 00:00:00 2001 From: Roland Franssen Date: Sun, 17 Sep 2017 20:41:33 +0200 Subject: [PATCH 0865/1099] [TwigBundle] Hide logs if unavailable, i.e. webprofiler --- .../Resources/views/Exception/exception.html.twig | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Bundle/TwigBundle/Resources/views/Exception/exception.html.twig b/src/Symfony/Bundle/TwigBundle/Resources/views/Exception/exception.html.twig index d42a9dec47c58..2f29571ae3278 100644 --- a/src/Symfony/Bundle/TwigBundle/Resources/views/Exception/exception.html.twig +++ b/src/Symfony/Bundle/TwigBundle/Resources/views/Exception/exception.html.twig @@ -54,14 +54,15 @@
-
+ {% if logger %} +

Logs {% if logger.counterrors ?? false %}{{ logger.counterrors }}{% endif %}

- {% if logger %} + {% if logger.logs %} {{ include('@Twig/Exception/logs.html.twig', { logs: logger.logs }, with_context = false) }} {% else %}
@@ -70,6 +71,7 @@ {% endif %}
+ {% endif %}

From 0c10f97f986797347ecdfdfd4b7c53f4ecd87435 Mon Sep 17 00:00:00 2001 From: Roland Franssen Date: Sun, 17 Sep 2017 21:22:24 +0200 Subject: [PATCH 0866/1099] [TwigBundle] Make deprecations scream in logs --- .../Resources/views/Exception/logs.html.twig | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Bundle/TwigBundle/Resources/views/Exception/logs.html.twig b/src/Symfony/Bundle/TwigBundle/Resources/views/Exception/logs.html.twig index 02d2b546e8559..f2a190ad23743 100644 --- a/src/Symfony/Bundle/TwigBundle/Resources/views/Exception/logs.html.twig +++ b/src/Symfony/Bundle/TwigBundle/Resources/views/Exception/logs.html.twig @@ -11,7 +11,15 @@ {% for log in logs %} - + {% if log.priority >= 400 %} + {% set status = 'error' %} + {% elseif log.priority >= 300 %} + {% set status = 'warning' %} + {% else %} + {% set severity = log.context.exception.severity|default(false) %} + {% set status = severity is constant('E_DEPRECATED') or severity is constant('E_USER_DEPRECATED') ? 'warning' : 'normal' %} + {% endif %} + {{ log.priorityName }} {{ log.timestamp|date('H:i:s') }} From ea4b0966aba8a6c9c223aefe74412929492ac58c Mon Sep 17 00:00:00 2001 From: Roland Franssen Date: Wed, 20 Sep 2017 21:17:51 +0200 Subject: [PATCH 0867/1099] [WebProfilerBundle] Hide inactive tabs from CSS --- .../Resources/views/Profiler/profiler.css.twig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/profiler.css.twig b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/profiler.css.twig index 5b6647df8866a..ca55b28672d03 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/profiler.css.twig +++ b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/profiler.css.twig @@ -832,6 +832,8 @@ tr.status-warning td { .tab-navigation li .badge.status-warning { background: {{ colors.warning|raw }}; color: #FFF; } .tab-navigation li .badge.status-error { background: {{ colors.error|raw }}; color: #FFF; } +.sf-tabs .tab:not(:first-child) { display: none; } + {# Toggles ========================================================================= #} .sf-toggle-content { From 1c595fcf48d689b49ca9f4b8790cdf5cd9275caf Mon Sep 17 00:00:00 2001 From: Roland Franssen Date: Thu, 21 Sep 2017 19:21:40 +0200 Subject: [PATCH 0868/1099] [TwigBundle][WebProfilerBundle] Switch to DOMContentLoaded event --- src/Symfony/Bundle/TwigBundle/Resources/views/base_js.html.twig | 2 +- .../Resources/views/Profiler/base_js.html.twig | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Bundle/TwigBundle/Resources/views/base_js.html.twig b/src/Symfony/Bundle/TwigBundle/Resources/views/base_js.html.twig index 036af2b025904..46016cb3747ba 100644 --- a/src/Symfony/Bundle/TwigBundle/Resources/views/base_js.html.twig +++ b/src/Symfony/Bundle/TwigBundle/Resources/views/base_js.html.twig @@ -525,7 +525,7 @@ }; })(); - Sfjs.addEventListener(window, 'load', function() { + Sfjs.addEventListener(document, 'DOMContentLoaded', function() { Sfjs.createTabs(); Sfjs.createToggles(); }); diff --git a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/base_js.html.twig b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/base_js.html.twig index b5f08f869168d..12a1e07bd74c6 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/base_js.html.twig +++ b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/base_js.html.twig @@ -525,7 +525,7 @@ }; })(); - Sfjs.addEventListener(window, 'load', function() { + Sfjs.addEventListener(document, 'DOMContentLoaded', function() { Sfjs.createTabs(); Sfjs.createToggles(); }); From 02dcdca01444bf303938971924e920f5aacaf515 Mon Sep 17 00:00:00 2001 From: Roland Franssen Date: Thu, 21 Sep 2017 20:21:04 +0200 Subject: [PATCH 0869/1099] [TwigBundle] Remove profiler related scripting --- .../Resources/views/base_js.html.twig | 362 +----------------- .../views/Profiler/base_js.html.twig | 8 +- 2 files changed, 6 insertions(+), 364 deletions(-) diff --git a/src/Symfony/Bundle/TwigBundle/Resources/views/base_js.html.twig b/src/Symfony/Bundle/TwigBundle/Resources/views/base_js.html.twig index 036af2b025904..e2cd23e948fcf 100644 --- a/src/Symfony/Bundle/TwigBundle/Resources/views/base_js.html.twig +++ b/src/Symfony/Bundle/TwigBundle/Resources/views/base_js.html.twig @@ -1,5 +1,5 @@ -{# This file is duplicated in WebProfilerBundle/Resources/views/Profiler/base_js.html.twig. - If you make any change in this file, do the same change in the other file. #} +{# This file is diverged from WebProfilerBundle/Resources/views/Profiler/base_js.html.twig. + If you make any change in this file, verify the same change is needed in the other file. #} /* 1) { - setTimeout(function(){ - options.maxTries--; - request(url, onSuccess, onError, payload, options); - }, 500); - - return null; - } - - if (200 === xhr.status) { - (onSuccess || noop)(xhr); - } else { - (onError || noop)(xhr); - } - }; - xhr.send(payload || ''); - }; - - var getPreference = function(name) { - if (!window.localStorage) { - return null; - } - - return localStorage.getItem(profilerStorageKey + name); - }; - - var setPreference = function(name, value) { - if (!window.localStorage) { - return null; - } - - localStorage.setItem(profilerStorageKey + name, value); - }; - - var requestStack = []; - - var extractHeaders = function(xhr, stackElement) { - /* Here we avoid to call xhr.getResponseHeader in order to */ - /* prevent polluting the console with CORS security errors */ - var allHeaders = xhr.getAllResponseHeaders(); - var ret; - - if (ret = allHeaders.match(/^x-debug-token:\s+(.*)$/im)) { - stackElement.profile = ret[1]; - } - if (ret = allHeaders.match(/^x-debug-token-link:\s+(.*)$/im)) { - stackElement.profilerUrl = ret[1]; - } - }; - - var successStreak = 4; - var pendingRequests = 0; - var renderAjaxRequests = function() { - var requestCounter = document.querySelector('.sf-toolbar-ajax-request-counter'); - if (!requestCounter) { - return; - } - requestCounter.textContent = requestStack.length; - - var infoSpan = document.querySelector(".sf-toolbar-ajax-info"); - if (infoSpan) { - infoSpan.textContent = requestStack.length + ' AJAX request' + (requestStack.length !== 1 ? 's' : ''); - } - - var ajaxToolbarPanel = document.querySelector('.sf-toolbar-block-ajax'); - if (requestStack.length) { - ajaxToolbarPanel.style.display = 'block'; - } else { - ajaxToolbarPanel.style.display = 'none'; - } - if (pendingRequests > 0) { - addClass(ajaxToolbarPanel, 'sf-ajax-request-loading'); - } else if (successStreak < 4) { - addClass(ajaxToolbarPanel, 'sf-toolbar-status-red'); - removeClass(ajaxToolbarPanel, 'sf-ajax-request-loading'); - } else { - removeClass(ajaxToolbarPanel, 'sf-ajax-request-loading'); - removeClass(ajaxToolbarPanel, 'sf-toolbar-status-red'); - } - }; - - var startAjaxRequest = function(index) { - var tbody = document.querySelector('.sf-toolbar-ajax-request-list'); - if (!tbody) { - return; - } - - var request = requestStack[index]; - pendingRequests++; - var row = document.createElement('tr'); - request.DOMNode = row; - - var methodCell = document.createElement('td'); - methodCell.textContent = request.method; - row.appendChild(methodCell); - - var typeCell = document.createElement('td'); - typeCell.textContent = request.type; - row.appendChild(typeCell); - - var statusCodeCell = document.createElement('td'); - var statusCode = document.createElement('span'); - statusCode.textContent = 'n/a'; - statusCodeCell.appendChild(statusCode); - row.appendChild(statusCodeCell); - - var pathCell = document.createElement('td'); - pathCell.className = 'sf-ajax-request-url'; - if ('GET' === request.method) { - var pathLink = document.createElement('a'); - pathLink.setAttribute('href', request.url); - pathLink.textContent = request.url; - pathCell.appendChild(pathLink); - } else { - pathCell.textContent = request.url; - } - pathCell.setAttribute('title', request.url); - row.appendChild(pathCell); - - var durationCell = document.createElement('td'); - durationCell.className = 'sf-ajax-request-duration'; - durationCell.textContent = 'n/a'; - row.appendChild(durationCell); - - var profilerCell = document.createElement('td'); - profilerCell.textContent = 'n/a'; - row.appendChild(profilerCell); - - row.className = 'sf-ajax-request sf-ajax-request-loading'; - tbody.insertBefore(row, tbody.firstChild); - - renderAjaxRequests(); - }; - - var finishAjaxRequest = function(index) { - var request = requestStack[index]; - if (!request.DOMNode) { - return; - } - pendingRequests--; - var row = request.DOMNode; - /* Unpack the children from the row */ - var methodCell = row.children[0]; - var statusCodeCell = row.children[2]; - var statusCodeElem = statusCodeCell.children[0]; - var durationCell = row.children[4]; - var profilerCell = row.children[5]; - - if (request.error) { - row.className = 'sf-ajax-request sf-ajax-request-error'; - methodCell.className = 'sf-ajax-request-error'; - successStreak = 0; - } else { - row.className = 'sf-ajax-request sf-ajax-request-ok'; - successStreak++; - } - - if (request.statusCode) { - if (request.statusCode < 300) { - statusCodeElem.setAttribute('class', 'sf-toolbar-status'); - } else if (request.statusCode < 400) { - statusCodeElem.setAttribute('class', 'sf-toolbar-status sf-toolbar-status-yellow'); - } else { - statusCodeElem.setAttribute('class', 'sf-toolbar-status sf-toolbar-status-red'); - } - statusCodeElem.textContent = request.statusCode; - } else { - statusCodeElem.setAttribute('class', 'sf-toolbar-status sf-toolbar-status-red'); - } - - if (request.duration) { - durationCell.textContent = request.duration + 'ms'; - } - - if (request.profilerUrl) { - profilerCell.textContent = ''; - var profilerLink = document.createElement('a'); - profilerLink.setAttribute('href', request.profilerUrl); - profilerLink.textContent = request.profile; - profilerCell.appendChild(profilerLink); - } - - renderAjaxRequests(); - }; - var addEventListener; var el = document.createElement('div'); @@ -235,163 +33,9 @@ }; } - {% if excluded_ajax_paths is defined %} - if (window.fetch && window.fetch.polyfill === undefined) { - var oldFetch = window.fetch; - window.fetch = function () { - var promise = oldFetch.apply(this, arguments); - var url = arguments[0]; - var params = arguments[1]; - var paramType = Object.prototype.toString.call(arguments[0]); - if (paramType === '[object Request]') { - url = arguments[0].url; - params = { - method: arguments[0].method, - credentials: arguments[0].credentials, - headers: arguments[0].headers, - mode: arguments[0].mode, - redirect: arguments[0].redirect - }; - } - if (!url.match(new RegExp({{ excluded_ajax_paths|json_encode|raw }}))) { - var method = 'GET'; - if (params && params.method !== undefined) { - method = params.method; - } - - var stackElement = { - error: false, - url: url, - method: method, - type: 'fetch', - start: new Date() - }; - - var idx = requestStack.push(stackElement) - 1; - promise.then(function (r) { - stackElement.duration = new Date() - stackElement.start; - stackElement.error = r.status < 200 || r.status >= 400; - stackElement.statusCode = r.status; - stackElement.profile = r.headers.get('x-debug-token'); - stackElement.profilerUrl = r.headers.get('x-debug-token-link'); - finishAjaxRequest(idx); - }, function (e){ - stackElement.error = true; - finishAjaxRequest(idx); - }); - startAjaxRequest(idx); - } - - return promise; - }; - } - if (window.XMLHttpRequest && XMLHttpRequest.prototype.addEventListener) { - var proxied = XMLHttpRequest.prototype.open; - - XMLHttpRequest.prototype.open = function(method, url, async, user, pass) { - var self = this; - - /* prevent logging AJAX calls to static and inline files, like templates */ - var path = url; - if (url.substr(0, 1) === '/') { - if (0 === url.indexOf('{{ request.basePath|e('js') }}')) { - path = url.substr({{ request.basePath|length }}); - } - } - else if (0 === url.indexOf('{{ (request.schemeAndHttpHost ~ request.basePath)|e('js') }}')) { - path = url.substr({{ (request.schemeAndHttpHost ~ request.basePath)|length }}); - } - - if (!path.match(new RegExp({{ excluded_ajax_paths|json_encode|raw }}))) { - var stackElement = { - error: false, - url: url, - method: method, - type: 'xhr', - start: new Date() - }; - - var idx = requestStack.push(stackElement) - 1; - - this.addEventListener('readystatechange', function() { - if (self.readyState == 4) { - stackElement.duration = new Date() - stackElement.start; - stackElement.error = self.status < 200 || self.status >= 400; - stackElement.statusCode = self.status; - extractHeaders(self, stackElement); - - finishAjaxRequest(idx); - } - }, false); - - startAjaxRequest(idx); - } - - proxied.apply(this, Array.prototype.slice.call(arguments)); - }; - } - {% endif %} - return { - hasClass: hasClass, - - removeClass: removeClass, - - addClass: addClass, - - toggleClass: toggleClass, - - getPreference: getPreference, - - setPreference: setPreference, - addEventListener: addEventListener, - request: request, - - renderAjaxRequests: renderAjaxRequests, - - load: function(selector, url, onSuccess, onError, options) { - var el = document.getElementById(selector); - - if (el && el.getAttribute('data-sfurl') !== url) { - request( - url, - function(xhr) { - el.innerHTML = xhr.responseText; - el.setAttribute('data-sfurl', url); - removeClass(el, 'loading'); - for (var i = 0; i < requestStack.length; i++) { - startAjaxRequest(i); - if (requestStack[i].duration) { - finishAjaxRequest(i); - } - } - (onSuccess || noop)(xhr, el); - }, - function(xhr) { (onError || noop)(xhr, el); }, - '', - options - ); - } - - return this; - }, - - toggle: function(selector, elOn, elOff) { - var tmp = elOn.style.display, - el = document.getElementById(selector); - - elOn.style.display = elOff.style.display; - elOff.style.display = tmp; - - if (el) { - el.style.display = 'none' === tmp ? 'none' : 'block'; - } - - return this; - }, - createTabs: function() { var tabGroups = document.querySelectorAll('.sf-tabs'); diff --git a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/base_js.html.twig b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/base_js.html.twig index b5f08f869168d..d382f8a2591c2 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/base_js.html.twig +++ b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/base_js.html.twig @@ -1,5 +1,5 @@ -{# This file is duplicated in TwigBundle/Resources/views/base_js.html.twig. If you - make any change in this file, do the same change in the other file. #} +{# This file is partially duplicated in TwigBundle/Resources/views/base_js.html.twig. If you + make any change in this file, verify the same change is needed in the other file. #} /* Date: Fri, 22 Sep 2017 11:57:45 +0100 Subject: [PATCH 0870/1099] [DI] Dont use JSON_BIGINT_AS_STRING --- src/Symfony/Component/DependencyInjection/EnvVarProcessor.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/DependencyInjection/EnvVarProcessor.php b/src/Symfony/Component/DependencyInjection/EnvVarProcessor.php index 51a19367e2179..73514712e8b71 100644 --- a/src/Symfony/Component/DependencyInjection/EnvVarProcessor.php +++ b/src/Symfony/Component/DependencyInjection/EnvVarProcessor.php @@ -119,7 +119,7 @@ public function getEnv($prefix, $name, \Closure $getEnv) } if ('json' === $prefix) { - $env = json_decode($env, true, JSON_BIGINT_AS_STRING); + $env = json_decode($env, true); if (JSON_ERROR_NONE !== json_last_error()) { throw new RuntimeException(sprintf('Invalid JSON in env var "%s": '.json_last_error_msg(), $name)); From cb935e789e397d3134f7d32be0bb58324d5a5405 Mon Sep 17 00:00:00 2001 From: Maarten de Boer Date: Thu, 21 Sep 2017 14:46:00 +0200 Subject: [PATCH 0871/1099] [Serializer] Getter for extra attributes in ExtraAttributesException --- src/Symfony/Component/Serializer/CHANGELOG.md | 1 + .../Exception/ExtraAttributesException.php | 14 ++++++++++++++ 2 files changed, 15 insertions(+) diff --git a/src/Symfony/Component/Serializer/CHANGELOG.md b/src/Symfony/Component/Serializer/CHANGELOG.md index ef59f22499264..9e48c5c41e927 100644 --- a/src/Symfony/Component/Serializer/CHANGELOG.md +++ b/src/Symfony/Component/Serializer/CHANGELOG.md @@ -7,6 +7,7 @@ CHANGELOG * added `AbstractObjectNormalizer::DISABLE_TYPE_ENFORCEMENT` context option to disable throwing an `UnexpectedValueException` on a type mismatch * added support for serializing `DateInterval` objects + * added getter for extra attributes in `ExtraAttributesException` 3.3.0 ----- diff --git a/src/Symfony/Component/Serializer/Exception/ExtraAttributesException.php b/src/Symfony/Component/Serializer/Exception/ExtraAttributesException.php index d321618b8eb11..74d87f87f5e8d 100644 --- a/src/Symfony/Component/Serializer/Exception/ExtraAttributesException.php +++ b/src/Symfony/Component/Serializer/Exception/ExtraAttributesException.php @@ -18,10 +18,24 @@ */ class ExtraAttributesException extends RuntimeException { + private $extraAttributes; + public function __construct(array $extraAttributes, \Exception $previous = null) { $msg = sprintf('Extra attributes are not allowed ("%s" are unknown).', implode('", "', $extraAttributes)); + $this->extraAttributes = $extraAttributes; + parent::__construct($msg, 0, $previous); } + + /** + * Get the extra attributes that are not allowed. + * + * @return array + */ + public function getExtraAttributes() + { + return $this->extraAttributes; + } } From e46b366fc52eb4c2bee683797b8569dc4186c9a9 Mon Sep 17 00:00:00 2001 From: "Alexander M. Turek" Date: Fri, 22 Sep 2017 20:41:17 +0200 Subject: [PATCH 0872/1099] Reset the authentication token between requests. --- .../Bundle/SecurityBundle/Resources/config/security.xml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Bundle/SecurityBundle/Resources/config/security.xml b/src/Symfony/Bundle/SecurityBundle/Resources/config/security.xml index 79a4866d8cbe4..049d67f5a05b1 100644 --- a/src/Symfony/Bundle/SecurityBundle/Resources/config/security.xml +++ b/src/Symfony/Bundle/SecurityBundle/Resources/config/security.xml @@ -21,7 +21,9 @@ - + + + From 35f9c0ba2d26cb21eca8f75f135a35052ca22ef3 Mon Sep 17 00:00:00 2001 From: Maxime Steinhausser Date: Fri, 22 Sep 2017 22:13:43 +0200 Subject: [PATCH 0873/1099] [Form] Add ambiguous & exception debug:form tests --- .../Component/Form/Command/DebugCommand.php | 2 +- .../Form/Tests/Command/DebugCommandTest.php | 99 +++++++++++++------ .../Tests/Fixtures/Debug/A/AmbiguousType.php | 18 ++++ .../Tests/Fixtures/Debug/B/AmbiguousType.php | 18 ++++ 4 files changed, 104 insertions(+), 33 deletions(-) create mode 100644 src/Symfony/Component/Form/Tests/Fixtures/Debug/A/AmbiguousType.php create mode 100644 src/Symfony/Component/Form/Tests/Fixtures/Debug/B/AmbiguousType.php diff --git a/src/Symfony/Component/Form/Command/DebugCommand.php b/src/Symfony/Component/Form/Command/DebugCommand.php index d9b3eee838244..d8e1f5a0789b0 100644 --- a/src/Symfony/Component/Form/Command/DebugCommand.php +++ b/src/Symfony/Component/Form/Command/DebugCommand.php @@ -118,7 +118,7 @@ private function getFqcnTypeClass(InputInterface $input, SymfonyStyle $io, $shor return $classes[0]; } if (!$input->isInteractive()) { - throw new InvalidArgumentException(sprintf("The type \"%s\" is ambiguous.\nDid you mean one of these?\n %s", $shortClassName, implode("\n ", $classes))); + throw new InvalidArgumentException(sprintf("The type \"%s\" is ambiguous.\n\nDid you mean one of these?\n %s", $shortClassName, implode("\n ", $classes))); } return $io->choice(sprintf("The type \"%s\" is ambiguous.\n\n Select one of the following form types to display its information:", $shortClassName), $classes, $classes[0]); diff --git a/src/Symfony/Component/Form/Tests/Command/DebugCommandTest.php b/src/Symfony/Component/Form/Tests/Command/DebugCommandTest.php index 610f6197d62cb..d24af0a4b1bc5 100644 --- a/src/Symfony/Component/Form/Tests/Command/DebugCommandTest.php +++ b/src/Symfony/Component/Form/Tests/Command/DebugCommandTest.php @@ -13,11 +13,11 @@ use PHPUnit\Framework\TestCase; use Symfony\Component\Console\Application; +use Symfony\Component\Console\Exception\InvalidArgumentException; use Symfony\Component\Console\Tester\CommandTester; use Symfony\Component\Form\Command\DebugCommand; -use Symfony\Component\Form\Extension\Core\Type\FormType; -use Symfony\Component\Form\FormRegistryInterface; -use Symfony\Component\Form\ResolvedFormTypeInterface; +use Symfony\Component\Form\FormRegistry; +use Symfony\Component\Form\ResolvedFormTypeFactory; class DebugCommandTest extends TestCase { @@ -39,6 +39,67 @@ public function testDebugSingleFormType() $this->assertContains('Symfony\Component\Form\Extension\Core\Type\FormType (Block prefix: "form")', $tester->getDisplay()); } + /** + * @expectedException \Symfony\Component\Console\Exception\InvalidArgumentException + * @expectedExceptionMessage Could not find type "NonExistentType" + */ + public function testDebugSingleFormTypeNotFound() + { + $tester = $this->createCommandTester(); + $tester->execute(array('class' => 'NonExistentType'), array('decorated' => false, 'interactive' => false)); + } + + public function testDebugAmbiguousFormType() + { + $expectedMessage = <<expectException(InvalidArgumentException::class); + $this->expectExceptionMessage($expectedMessage); + } else { + $this->setExpectedException(InvalidArgumentException::class, $expectedMessage); + } + + $tester = $this->createCommandTester(array( + 'Symfony\Component\Form\Tests\Fixtures\Debug\A', + 'Symfony\Component\Form\Tests\Fixtures\Debug\B', + )); + + $tester->execute(array('class' => 'AmbiguousType'), array('decorated' => false, 'interactive' => false)); + } + + public function testDebugAmbiguousFormTypeInteractive() + { + $tester = $this->createCommandTester(array( + 'Symfony\Component\Form\Tests\Fixtures\Debug\A', + 'Symfony\Component\Form\Tests\Fixtures\Debug\B', + )); + + $tester->setInputs(array(0)); + $tester->execute(array('class' => 'AmbiguousType'), array('decorated' => false, 'interactive' => true)); + + $this->assertEquals(0, $tester->getStatusCode(), 'Returns 0 in case of success'); + $output = $tester->getDisplay(true); + $this->assertStringMatchesFormat(<<createCommandTester()->execute(array('class' => 'test')); } - /** - * @return CommandTester - */ - private function createCommandTester() + private function createCommandTester(array $namespaces = null) { - $resolvedFormType = $this->getMockBuilder(ResolvedFormTypeInterface::class)->getMock(); - $resolvedFormType - ->expects($this->any()) - ->method('getParent') - ->willReturn(null) - ; - $resolvedFormType - ->expects($this->any()) - ->method('getInnerType') - ->willReturn(new FormType()) - ; - $resolvedFormType - ->expects($this->any()) - ->method('getTypeExtensions') - ->willReturn(array()) - ; - - $formRegistry = $this->getMockBuilder(FormRegistryInterface::class)->getMock(); - $formRegistry - ->expects($this->any()) - ->method('getType') - ->will($this->returnValue($resolvedFormType)) - ; - - $command = new DebugCommand($formRegistry); + $formRegistry = new FormRegistry(array(), new ResolvedFormTypeFactory()); + $command = null === $namespaces ? new DebugCommand($formRegistry) : new DebugCommand($formRegistry, $namespaces); $application = new Application(); $application->add($command); diff --git a/src/Symfony/Component/Form/Tests/Fixtures/Debug/A/AmbiguousType.php b/src/Symfony/Component/Form/Tests/Fixtures/Debug/A/AmbiguousType.php new file mode 100644 index 0000000000000..e6e183902882c --- /dev/null +++ b/src/Symfony/Component/Form/Tests/Fixtures/Debug/A/AmbiguousType.php @@ -0,0 +1,18 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Tests\Fixtures\Debug\A; + +use Symfony\Component\Form\AbstractType; + +class AmbiguousType extends AbstractType +{ +} diff --git a/src/Symfony/Component/Form/Tests/Fixtures/Debug/B/AmbiguousType.php b/src/Symfony/Component/Form/Tests/Fixtures/Debug/B/AmbiguousType.php new file mode 100644 index 0000000000000..c670e8e925bdf --- /dev/null +++ b/src/Symfony/Component/Form/Tests/Fixtures/Debug/B/AmbiguousType.php @@ -0,0 +1,18 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Tests\Fixtures\Debug\B; + +use Symfony\Component\Form\AbstractType; + +class AmbiguousType extends AbstractType +{ +} From 42f0984e71fa38c72bf95ff58264274456e3f115 Mon Sep 17 00:00:00 2001 From: Freek Van der Herten Date: Thu, 21 Sep 2017 18:42:43 +0200 Subject: [PATCH 0874/1099] [VarDumper] Make `dump()` a little bit more easier to use --- .../Component/VarDumper/Resources/functions/dump.php | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/Symfony/Component/VarDumper/Resources/functions/dump.php b/src/Symfony/Component/VarDumper/Resources/functions/dump.php index b6c243c8b6e2f..0e5216abc2958 100644 --- a/src/Symfony/Component/VarDumper/Resources/functions/dump.php +++ b/src/Symfony/Component/VarDumper/Resources/functions/dump.php @@ -20,5 +20,11 @@ function dump($var) foreach (func_get_args() as $var) { VarDumper::dump($var); } + + if ($moreVars) { + return func_get_args(); + } + + return $var; } } From cb6ead1635a13875a486814b5314a1d4feb08c01 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Sun, 24 Sep 2017 10:13:45 +0100 Subject: [PATCH 0875/1099] allow forms without translations and validator --- .../DependencyInjection/FrameworkExtension.php | 18 ++++++++++++------ .../Resources/config/form_csrf.xml | 2 +- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php index e0d7258902f4d..4a940a70f0b76 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php @@ -74,6 +74,7 @@ use Symfony\Component\Serializer\Normalizer\NormalizerInterface; use Symfony\Component\Stopwatch\Stopwatch; use Symfony\Component\Translation\Command\XliffLintCommand as BaseXliffLintCommand; +use Symfony\Component\Translation\Translator; use Symfony\Component\Validator\ConstraintValidatorInterface; use Symfony\Component\Validator\ObjectInitializerInterface; use Symfony\Component\WebLink\HttpHeaderSerializer; @@ -189,15 +190,13 @@ public function load(array $configs, ContainerBuilder $container) throw new LogicException('Translation support cannot be enabled as the Translation component is not installed.'); } - if (!class_exists('Symfony\Component\Translation\Translator') && $this->isConfigEnabled($container, $config['form'])) { - throw new LogicException('Form support cannot be enabled as the Translation component is not installed.'); - } - if (!class_exists('Symfony\Component\Translation\Translator') && $this->isConfigEnabled($container, $config['validation'])) { throw new LogicException('Validation support cannot be enabled as the Translation component is not installed.'); } - $loader->load('identity_translator.xml'); + if (class_exists(Translator::class)) { + $loader->load('identity_translator.xml'); + } } if (isset($config['secret'])) { @@ -250,7 +249,10 @@ public function load(array $configs, ContainerBuilder $container) $config['validation']['enabled'] = true; if (!class_exists('Symfony\Component\Validator\Validation')) { - throw new LogicException('The Validator component is required to use the Form component.'); + $container->setParameter('validator.translation_domain', 'validators'); + + $container->removeDefinition('form.type_extension.form.validator'); + $container->removeDefinition('form.type_guesser.validator'); } } else { $container->removeDefinition('Symfony\Component\Form\Command\DebugCommand'); @@ -448,6 +450,10 @@ private function registerFormConfiguration($config, ContainerBuilder $container, } else { $container->setParameter('form.type_extension.csrf.enabled', false); } + + if (!class_exists(Translator::class)) { + $container->removeDefinition('form.type_extension.upload.validator'); + } } /** diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/form_csrf.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/form_csrf.xml index 22b0c119e2084..d0162ea09816c 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/form_csrf.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/form_csrf.xml @@ -12,7 +12,7 @@ %form.type_extension.csrf.enabled% %form.type_extension.csrf.field_name% - + %validator.translation_domain% From 1ebc31aa9f62e0c715ab7074be71211c1bd0cd6f Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Sun, 24 Sep 2017 15:31:29 +0200 Subject: [PATCH 0876/1099] Fix tests --- .../Tests/Functional/app/ContainerDebug/config.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/ContainerDebug/config.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/ContainerDebug/config.yml index f4a5425808440..d00d6f235ec67 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/ContainerDebug/config.yml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/ContainerDebug/config.yml @@ -2,6 +2,7 @@ imports: - { resource: ../config/default.yml } services: + _defaults: { public: true } public: class: Symfony\Bundle\FrameworkBundle\Tests\Fixtures\DeclaredClass private_alias: From f0f9a6691cef3ffe2491009143a314008c047845 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Sun, 24 Sep 2017 11:49:51 +0200 Subject: [PATCH 0877/1099] [HttpKernel] Make array vs "::" controller definitions consistent --- .../ContainerControllerResolver.php | 15 ++++++ .../ContainerControllerResolverTest.php | 50 +++++++++++++++++++ 2 files changed, 65 insertions(+) diff --git a/src/Symfony/Component/HttpKernel/Controller/ContainerControllerResolver.php b/src/Symfony/Component/HttpKernel/Controller/ContainerControllerResolver.php index 1a107c62f60b1..fbcecad25e18a 100644 --- a/src/Symfony/Component/HttpKernel/Controller/ContainerControllerResolver.php +++ b/src/Symfony/Component/HttpKernel/Controller/ContainerControllerResolver.php @@ -13,6 +13,7 @@ use Psr\Container\ContainerInterface; use Psr\Log\LoggerInterface; +use Symfony\Component\HttpFoundation\Request; /** * A controller resolver searching for a controller in a psr-11 container when using the "service:method" notation. @@ -31,6 +32,20 @@ public function __construct(ContainerInterface $container, LoggerInterface $logg parent::__construct($logger); } + /** + * {@inheritdoc} + */ + public function getController(Request $request) + { + $controller = parent::getController($request); + + if (is_array($controller) && isset($controller[0]) && is_string($controller[0]) && $this->container->has($controller[0])) { + $controller[0] = $this->instantiateController($controller[0]); + } + + return $controller; + } + /** * Returns a callable for the given controller. * diff --git a/src/Symfony/Component/HttpKernel/Tests/Controller/ContainerControllerResolverTest.php b/src/Symfony/Component/HttpKernel/Tests/Controller/ContainerControllerResolverTest.php index 30b535e825f67..b3deb03c9138a 100644 --- a/src/Symfony/Component/HttpKernel/Tests/Controller/ContainerControllerResolverTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/Controller/ContainerControllerResolverTest.php @@ -88,6 +88,49 @@ public function testGetControllerInvokableServiceWithClassNameAsName() $this->assertEquals($invokableController, $controller); } + public function testNonInstantiableController() + { + $container = $this->createMockContainer(); + $container->expects($this->once()) + ->method('has') + ->with(NonInstantiableController::class) + ->will($this->returnValue(false)) + ; + + $resolver = $this->createControllerResolver(null, $container); + $request = Request::create('/'); + $request->attributes->set('_controller', array(NonInstantiableController::class, 'action')); + + $controller = $resolver->getController($request); + + $this->assertSame(array(NonInstantiableController::class, 'action'), $controller); + } + + public function testNonInstantiableControllerWithCorrespondingService() + { + $service = new \stdClass(); + + $container = $this->createMockContainer(); + $container->expects($this->atLeastOnce()) + ->method('has') + ->with(NonInstantiableController::class) + ->will($this->returnValue(true)) + ; + $container->expects($this->atLeastOnce()) + ->method('get') + ->with(NonInstantiableController::class) + ->will($this->returnValue($service)) + ; + + $resolver = $this->createControllerResolver(null, $container); + $request = Request::create('/'); + $request->attributes->set('_controller', array(NonInstantiableController::class, 'action')); + + $controller = $resolver->getController($request); + + $this->assertSame(array($service, 'action'), $controller); + } + /** * @dataProvider getUndefinedControllers */ @@ -146,3 +189,10 @@ public function __invoke() { } } + +abstract class NonInstantiableController +{ + public static function action() + { + } +} From e17426c65cda22b71d19f4a6ed918003f9eda587 Mon Sep 17 00:00:00 2001 From: Oskar Stark Date: Fri, 22 Sep 2017 13:07:23 +0200 Subject: [PATCH 0878/1099] added missing @author tag for new class --- src/Symfony/Component/DependencyInjection/EnvVarProcessor.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Symfony/Component/DependencyInjection/EnvVarProcessor.php b/src/Symfony/Component/DependencyInjection/EnvVarProcessor.php index 73514712e8b71..63bb5bc8c0079 100644 --- a/src/Symfony/Component/DependencyInjection/EnvVarProcessor.php +++ b/src/Symfony/Component/DependencyInjection/EnvVarProcessor.php @@ -15,6 +15,9 @@ use Symfony\Component\DependencyInjection\Exception\EnvNotFoundException; use Symfony\Component\DependencyInjection\Exception\RuntimeException; +/** + * @author Nicolas Grekas + */ class EnvVarProcessor implements EnvVarProcessorInterface { private $container; From a69c1b2ae1dd3f35ce255c0bf5ca66f4d7f1f888 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Sun, 24 Sep 2017 11:20:06 +0200 Subject: [PATCH 0879/1099] [FrameworkBundle] Fix Routing\DelegatingLoader --- .../Bundle/FrameworkBundle/Routing/DelegatingLoader.php | 2 +- .../Functional/Bundle/TestBundle/Resources/config/routing.yml | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/Routing/DelegatingLoader.php b/src/Symfony/Bundle/FrameworkBundle/Routing/DelegatingLoader.php index 29f3072a897cd..fa07f832f894b 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Routing/DelegatingLoader.php +++ b/src/Symfony/Bundle/FrameworkBundle/Routing/DelegatingLoader.php @@ -85,7 +85,7 @@ public function load($resource, $type = null) $this->loading = false; foreach ($collection->all() as $route) { - if (!$controller = $route->getDefault('_controller')) { + if (!is_string($controller = $route->getDefault('_controller')) || !$controller) { continue; } diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/TestBundle/Resources/config/routing.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/TestBundle/Resources/config/routing.yml index 57d83eb9c649c..11b85a86d3299 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/TestBundle/Resources/config/routing.yml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/TestBundle/Resources/config/routing.yml @@ -44,3 +44,7 @@ fragment_home: fragment_inlined: path: /fragment_inlined defaults: { _controller: TestBundle:Fragment:inlined } + +array_controller: + path: /array_controller + defaults: { _controller: [ArrayController, someAction] } From e66e5381d3b86c94628194f5c5dd8ec5cdc79f73 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9my=20Deruss=C3=A9?= Date: Sun, 24 Sep 2017 17:01:32 +0200 Subject: [PATCH 0880/1099] Add missing methods in LockInterface --- src/Symfony/Component/Lock/Lock.php | 6 ++---- src/Symfony/Component/Lock/LockInterface.php | 12 ++++++++++++ 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/src/Symfony/Component/Lock/Lock.php b/src/Symfony/Component/Lock/Lock.php index d8271569d8c05..07807a915c2c3 100644 --- a/src/Symfony/Component/Lock/Lock.php +++ b/src/Symfony/Component/Lock/Lock.php @@ -133,7 +133,7 @@ public function release() } /** - * @return bool + * {@inheritdoc} */ public function isExpired() { @@ -141,9 +141,7 @@ public function isExpired() } /** - * Returns the remaining lifetime. - * - * @return float|null Remaining lifetime in seconds. Null when the lock won't expire. + * {@inheritdoc} */ public function getRemainingLifetime() { diff --git a/src/Symfony/Component/Lock/LockInterface.php b/src/Symfony/Component/Lock/LockInterface.php index 437a4cc2770c8..4a3cc3f5bec86 100644 --- a/src/Symfony/Component/Lock/LockInterface.php +++ b/src/Symfony/Component/Lock/LockInterface.php @@ -56,4 +56,16 @@ public function isAcquired(); * @throws LockReleasingException If the lock can not be released */ public function release(); + + /** + * @return bool + */ + public function isExpired(); + + /** + * Returns the remaining lifetime. + * + * @return float|null Remaining lifetime in seconds. Null when the lock won't expire. + */ + public function getRemainingLifetime(); } From 88549fff5b4eb4c2739562d666ebfaf12aca56ba Mon Sep 17 00:00:00 2001 From: Maxime Steinhausser Date: Sat, 23 Sep 2017 12:08:51 +0200 Subject: [PATCH 0881/1099] [DI][DX] Throw exception on some ContainerBuilder methods used from extensions --- .../MergeExtensionConfigurationPass.php | 46 ++++++++++++++++++- .../MergeExtensionConfigurationPassTest.php | 17 +++++++ 2 files changed, 62 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/DependencyInjection/Compiler/MergeExtensionConfigurationPass.php b/src/Symfony/Component/DependencyInjection/Compiler/MergeExtensionConfigurationPass.php index c3b4d78dd622d..af3a6baf0b898 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/MergeExtensionConfigurationPass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/MergeExtensionConfigurationPass.php @@ -12,10 +12,13 @@ namespace Symfony\Component\DependencyInjection\Compiler; use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Exception\LogicException; use Symfony\Component\DependencyInjection\Extension\ConfigurationExtensionInterface; use Symfony\Component\DependencyInjection\Extension\Extension; +use Symfony\Component\DependencyInjection\Extension\ExtensionInterface; use Symfony\Component\DependencyInjection\Extension\PrependExtensionInterface; use Symfony\Component\DependencyInjection\ParameterBag\EnvPlaceholderParameterBag; +use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface; /** * Merges extension configs into the container builder. @@ -52,7 +55,7 @@ public function process(ContainerBuilder $container) } $config = $resolvingBag->resolveValue($config); - $tmpContainer = new ContainerBuilder($resolvingBag); + $tmpContainer = new MergeExtensionConfigurationContainerBuilder($extension, $resolvingBag); $tmpContainer->setResourceTracking($container->isTrackingResources()); $tmpContainer->addObjectResource($extension); if ($extension instanceof ConfigurationExtensionInterface && null !== $configuration = $extension->getConfiguration($config, $tmpContainer)) { @@ -121,3 +124,44 @@ public function getEnvPlaceholders() return null !== $this->processedEnvPlaceholders ? $this->processedEnvPlaceholders : parent::getEnvPlaceholders(); } } + +/** + * A container builder preventing using methods that wouldn't have any effect from extensions. + * + * @internal + */ +class MergeExtensionConfigurationContainerBuilder extends ContainerBuilder +{ + private $extensionClass; + + public function __construct(ExtensionInterface $extension, ParameterBagInterface $parameterBag = null) + { + parent::__construct($parameterBag); + + $this->extensionClass = get_class($extension); + } + + /** + * {@inheritdoc} + */ + public function addCompilerPass(CompilerPassInterface $pass, $type = PassConfig::TYPE_BEFORE_OPTIMIZATION/*, int $priority = 0*/) + { + throw new LogicException(sprintf('You cannot add compiler pass "%s" from extension "%s". Compiler passes must be registered before the container is compiled.', get_class($pass), $this->extensionClass)); + } + + /** + * {@inheritdoc} + */ + public function registerExtension(ExtensionInterface $extension) + { + throw new LogicException(sprintf('You cannot register extension "%s" from "%s". Extensions must be registered before the container is compiled.', get_class($extension), $this->extensionClass)); + } + + /** + * {@inheritdoc} + */ + public function compile($resolveEnvPlaceholders = false) + { + throw new LogicException(sprintf('Cannot compile the container in extension "%s".', $this->extensionClass)); + } +} diff --git a/src/Symfony/Component/DependencyInjection/Tests/Compiler/MergeExtensionConfigurationPassTest.php b/src/Symfony/Component/DependencyInjection/Tests/Compiler/MergeExtensionConfigurationPassTest.php index 44d1933a80fa8..57bb634f4bff0 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Compiler/MergeExtensionConfigurationPassTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Compiler/MergeExtensionConfigurationPassTest.php @@ -16,6 +16,7 @@ use Symfony\Component\Config\Definition\ConfigurationInterface; use Symfony\Component\Config\Resource\FileResource; use Symfony\Component\DependencyInjection\Compiler\MergeExtensionConfigurationPass; +use Symfony\Component\DependencyInjection\Compiler\MergeExtensionConfigurationContainerBuilder; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Extension\Extension; use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag; @@ -54,6 +55,22 @@ public function testExpressionLanguageProviderForwarding() $this->assertEquals(array($provider), $tmpProviders); } + public function testExtensionLoadGetAMergeExtensionConfigurationContainerBuilderInstance() + { + $extension = $this->getMockBuilder(FooExtension::class)->setMethods(array('load'))->getMock(); + $extension->expects($this->once()) + ->method('load') + ->with($this->isType('array'), $this->isInstanceOf(MergeExtensionConfigurationContainerBuilder::class)) + ; + + $container = new ContainerBuilder(new ParameterBag()); + $container->registerExtension($extension); + $container->prependExtensionConfig('foo', array()); + + $pass = new MergeExtensionConfigurationPass(); + $pass->process($container); + } + public function testExtensionConfigurationIsTrackedByDefault() { $extension = $this->getMockBuilder(FooExtension::class)->setMethods(array('getConfiguration'))->getMock(); From 1ba4dd9b449288005af310bf6173a67229cec9a8 Mon Sep 17 00:00:00 2001 From: Iltar van der Berg Date: Mon, 25 Sep 2017 09:46:32 +0200 Subject: [PATCH 0882/1099] Added null as explicit return type (?TokenInterface) --- .../Component/Security/Http/Firewall/ContextListener.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/Security/Http/Firewall/ContextListener.php b/src/Symfony/Component/Security/Http/Firewall/ContextListener.php index b443fa14881a4..43af1105bf76e 100644 --- a/src/Symfony/Component/Security/Http/Firewall/ContextListener.php +++ b/src/Symfony/Component/Security/Http/Firewall/ContextListener.php @@ -174,7 +174,7 @@ protected function refreshUser(TokenInterface $token) } if ($userNotFoundByProvider) { - return; + return null; } throw new \RuntimeException(sprintf('There is no user provider for user "%s".', get_class($user))); From 14c91f2bc98978c400eef484cdf7d274b1aa002c Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Fri, 15 Sep 2017 22:03:33 +0200 Subject: [PATCH 0883/1099] [Cache] Add ResettableInterface to allow resetting any pool's local state --- .../Compiler/CachePoolPass.php | 11 +++- .../FrameworkExtension.php | 3 ++ .../Resources/config/cache.xml | 4 +- .../Cache/Adapter/AbstractAdapter.php | 3 +- .../Component/Cache/Adapter/ArrayAdapter.php | 3 +- .../Component/Cache/Adapter/ChainAdapter.php | 15 +++++- .../Cache/Adapter/PhpArrayAdapter.php | 22 ++++---- .../Component/Cache/Adapter/ProxyAdapter.php | 8 ++- .../Cache/Adapter/SimpleCacheAdapter.php | 8 ++- .../Cache/Adapter/TagAwareAdapter.php | 51 ++++++++----------- .../Cache/Adapter/TraceableAdapter.php | 36 ++++++++++++- .../Component/Cache/DoctrineProvider.php | 21 +++++++- .../Component/Cache/ResettableInterface.php | 20 ++++++++ .../Component/Cache/Simple/AbstractCache.php | 3 +- .../Component/Cache/Simple/ArrayCache.php | 3 +- .../Component/Cache/Simple/ChainCache.php | 15 +++++- .../Component/Cache/Simple/PhpArrayCache.php | 20 ++++---- .../Component/Cache/Simple/Psr6Cache.php | 8 ++- .../Component/Cache/Simple/TraceableCache.php | 36 ++++++++++++- .../Tests/Adapter/PhpArrayAdapterTest.php | 1 + .../PhpArrayAdapterWithFallbackTest.php | 1 + .../Cache/Tests/Adapter/ProxyAdapterTest.php | 1 + .../Tests/Adapter/SimpleCacheAdapterTest.php | 4 ++ .../Tests/Adapter/TraceableAdapterTest.php | 4 ++ .../Cache/Tests/Simple/PhpArrayCacheTest.php | 1 + .../Simple/PhpArrayCacheWithFallbackTest.php | 1 + .../Cache/Tests/Simple/Psr6CacheTest.php | 4 ++ .../Cache/Tests/Simple/TraceableCacheTest.php | 4 ++ .../Component/Cache/Traits/AbstractTrait.php | 11 ++++ .../Component/Cache/Traits/ArrayTrait.php | 8 +++ .../Component/Cache/Traits/DoctrineTrait.php | 9 ++++ .../Component/Cache/Traits/PhpArrayTrait.php | 5 +- .../Component/Cache/Traits/ProxyTrait.php | 41 +++++++++++++++ 33 files changed, 315 insertions(+), 70 deletions(-) create mode 100644 src/Symfony/Component/Cache/ResettableInterface.php create mode 100644 src/Symfony/Component/Cache/Traits/ProxyTrait.php diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/CachePoolPass.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/CachePoolPass.php index 6a633c7b25361..dafe0b7b8fce4 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/CachePoolPass.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/CachePoolPass.php @@ -43,6 +43,7 @@ public function process(ContainerBuilder $container) 'provider', 'namespace', 'default_lifetime', + 'reset', ); foreach ($container->findTaggedServiceIds('cache.pool') as $id => $tags) { $adapter = $pool = $container->getDefinition($id); @@ -73,13 +74,19 @@ public function process(ContainerBuilder $container) } $i = 0; foreach ($attributes as $attr) { - if (isset($tags[0][$attr]) && ('namespace' !== $attr || ArrayAdapter::class !== $adapter->getClass())) { + if (!isset($tags[0][$attr])) { + // no-op + } elseif ('reset' === $attr) { + if ($tags[0][$attr]) { + $pool->addTag('kernel.reset', array('method' => $tags[0][$attr])); + } + } elseif ('namespace' !== $attr || ArrayAdapter::class !== $adapter->getClass()) { $pool->replaceArgument($i++, $tags[0][$attr]); } unset($tags[0][$attr]); } if (!empty($tags[0])) { - throw new InvalidArgumentException(sprintf('Invalid "cache.pool" tag for service "%s": accepted attributes are "clearer", "provider", "namespace" and "default_lifetime", found "%s".', $id, implode('", "', array_keys($tags[0])))); + throw new InvalidArgumentException(sprintf('Invalid "cache.pool" tag for service "%s": accepted attributes are "clearer", "provider", "namespace", "default_lifetime" and "reset", found "%s".', $id, implode('", "', array_keys($tags[0])))); } if (null !== $clearer) { diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php index 489bfed43c146..69d8fa64aa09b 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php @@ -25,6 +25,7 @@ use Symfony\Bundle\FrameworkBundle\Routing\AnnotatedRouteControllerLoader; use Symfony\Component\Cache\Adapter\AdapterInterface; use Symfony\Component\Cache\Adapter\ArrayAdapter; +use Symfony\Component\Cache\ResettableInterface; use Symfony\Component\Config\FileLocator; use Symfony\Component\Config\Loader\LoaderInterface; use Symfony\Component\Config\Resource\DirectoryResource; @@ -336,6 +337,8 @@ public function load(array $configs, ContainerBuilder $container) ->addTag('kernel.cache_warmer'); $container->registerForAutoconfiguration(EventSubscriberInterface::class) ->addTag('kernel.event_subscriber'); + $container->registerForAutoconfiguration(ResettableInterface::class) + ->addTag('kernel.reset', array('method' => 'reset')); $container->registerForAutoconfiguration(PropertyListExtractorInterface::class) ->addTag('property_info.list_extractor'); $container->registerForAutoconfiguration(PropertyTypeExtractorInterface::class) diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/cache.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/cache.xml index cbed70e4e11a1..16b15a661768c 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/cache.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/cache.xml @@ -8,7 +8,7 @@ - + @@ -90,7 +90,7 @@ - + diff --git a/src/Symfony/Component/Cache/Adapter/AbstractAdapter.php b/src/Symfony/Component/Cache/Adapter/AbstractAdapter.php index 6b38991b77e1e..a2fae2fc2f548 100644 --- a/src/Symfony/Component/Cache/Adapter/AbstractAdapter.php +++ b/src/Symfony/Component/Cache/Adapter/AbstractAdapter.php @@ -17,12 +17,13 @@ use Psr\Log\NullLogger; use Symfony\Component\Cache\CacheItem; use Symfony\Component\Cache\Exception\InvalidArgumentException; +use Symfony\Component\Cache\ResettableInterface; use Symfony\Component\Cache\Traits\AbstractTrait; /** * @author Nicolas Grekas */ -abstract class AbstractAdapter implements AdapterInterface, LoggerAwareInterface +abstract class AbstractAdapter implements AdapterInterface, LoggerAwareInterface, ResettableInterface { use AbstractTrait; diff --git a/src/Symfony/Component/Cache/Adapter/ArrayAdapter.php b/src/Symfony/Component/Cache/Adapter/ArrayAdapter.php index 45c19c7a6c7af..2118e9c6ffa57 100644 --- a/src/Symfony/Component/Cache/Adapter/ArrayAdapter.php +++ b/src/Symfony/Component/Cache/Adapter/ArrayAdapter.php @@ -14,12 +14,13 @@ use Psr\Cache\CacheItemInterface; use Psr\Log\LoggerAwareInterface; use Symfony\Component\Cache\CacheItem; +use Symfony\Component\Cache\ResettableInterface; use Symfony\Component\Cache\Traits\ArrayTrait; /** * @author Nicolas Grekas */ -class ArrayAdapter implements AdapterInterface, LoggerAwareInterface +class ArrayAdapter implements AdapterInterface, LoggerAwareInterface, ResettableInterface { use ArrayTrait; diff --git a/src/Symfony/Component/Cache/Adapter/ChainAdapter.php b/src/Symfony/Component/Cache/Adapter/ChainAdapter.php index c38949975d884..6bdf6b2d54f14 100644 --- a/src/Symfony/Component/Cache/Adapter/ChainAdapter.php +++ b/src/Symfony/Component/Cache/Adapter/ChainAdapter.php @@ -16,6 +16,7 @@ use Symfony\Component\Cache\CacheItem; use Symfony\Component\Cache\Exception\InvalidArgumentException; use Symfony\Component\Cache\PruneableInterface; +use Symfony\Component\Cache\ResettableInterface; /** * Chains several adapters together. @@ -25,7 +26,7 @@ * * @author Kévin Dunglas */ -class ChainAdapter implements AdapterInterface, PruneableInterface +class ChainAdapter implements AdapterInterface, PruneableInterface, ResettableInterface { private $adapters = array(); private $adapterCount; @@ -248,4 +249,16 @@ public function prune() return $pruned; } + + /** + * {@inheritdoc} + */ + public function reset() + { + foreach ($this->adapters as $adapter) { + if ($adapter instanceof ResettableInterface) { + $adapter->reset(); + } + } + } } diff --git a/src/Symfony/Component/Cache/Adapter/PhpArrayAdapter.php b/src/Symfony/Component/Cache/Adapter/PhpArrayAdapter.php index 7e9686a01855e..511224f854202 100644 --- a/src/Symfony/Component/Cache/Adapter/PhpArrayAdapter.php +++ b/src/Symfony/Component/Cache/Adapter/PhpArrayAdapter.php @@ -15,6 +15,8 @@ use Psr\Cache\CacheItemPoolInterface; use Symfony\Component\Cache\CacheItem; use Symfony\Component\Cache\Exception\InvalidArgumentException; +use Symfony\Component\Cache\PruneableInterface; +use Symfony\Component\Cache\ResettableInterface; use Symfony\Component\Cache\Traits\PhpArrayTrait; /** @@ -24,7 +26,7 @@ * @author Titouan Galopin * @author Nicolas Grekas */ -class PhpArrayAdapter implements AdapterInterface +class PhpArrayAdapter implements AdapterInterface, PruneableInterface, ResettableInterface { use PhpArrayTrait; @@ -37,7 +39,7 @@ class PhpArrayAdapter implements AdapterInterface public function __construct($file, AdapterInterface $fallbackPool) { $this->file = $file; - $this->fallbackPool = $fallbackPool; + $this->pool = $fallbackPool; $this->zendDetectUnicode = ini_get('zend.detect_unicode'); $this->createCacheItem = \Closure::bind( function ($key, $value, $isHit) { @@ -89,7 +91,7 @@ public function getItem($key) $this->initialize(); } if (!isset($this->values[$key])) { - return $this->fallbackPool->getItem($key); + return $this->pool->getItem($key); } $value = $this->values[$key]; @@ -144,7 +146,7 @@ public function hasItem($key) $this->initialize(); } - return isset($this->values[$key]) || $this->fallbackPool->hasItem($key); + return isset($this->values[$key]) || $this->pool->hasItem($key); } /** @@ -159,7 +161,7 @@ public function deleteItem($key) $this->initialize(); } - return !isset($this->values[$key]) && $this->fallbackPool->deleteItem($key); + return !isset($this->values[$key]) && $this->pool->deleteItem($key); } /** @@ -186,7 +188,7 @@ public function deleteItems(array $keys) } if ($fallbackKeys) { - $deleted = $this->fallbackPool->deleteItems($fallbackKeys) && $deleted; + $deleted = $this->pool->deleteItems($fallbackKeys) && $deleted; } return $deleted; @@ -201,7 +203,7 @@ public function save(CacheItemInterface $item) $this->initialize(); } - return !isset($this->values[$item->getKey()]) && $this->fallbackPool->save($item); + return !isset($this->values[$item->getKey()]) && $this->pool->save($item); } /** @@ -213,7 +215,7 @@ public function saveDeferred(CacheItemInterface $item) $this->initialize(); } - return !isset($this->values[$item->getKey()]) && $this->fallbackPool->saveDeferred($item); + return !isset($this->values[$item->getKey()]) && $this->pool->saveDeferred($item); } /** @@ -221,7 +223,7 @@ public function saveDeferred(CacheItemInterface $item) */ public function commit() { - return $this->fallbackPool->commit(); + return $this->pool->commit(); } /** @@ -259,7 +261,7 @@ private function generateItems(array $keys) } if ($fallbackKeys) { - foreach ($this->fallbackPool->getItems($fallbackKeys) as $key => $item) { + foreach ($this->pool->getItems($fallbackKeys) as $key => $item) { yield $key => $item; } } diff --git a/src/Symfony/Component/Cache/Adapter/ProxyAdapter.php b/src/Symfony/Component/Cache/Adapter/ProxyAdapter.php index cd310be062069..82c95c5b04582 100644 --- a/src/Symfony/Component/Cache/Adapter/ProxyAdapter.php +++ b/src/Symfony/Component/Cache/Adapter/ProxyAdapter.php @@ -14,13 +14,17 @@ use Psr\Cache\CacheItemInterface; use Psr\Cache\CacheItemPoolInterface; use Symfony\Component\Cache\CacheItem; +use Symfony\Component\Cache\PruneableInterface; +use Symfony\Component\Cache\ResettableInterface; +use Symfony\Component\Cache\Traits\ProxyTrait; /** * @author Nicolas Grekas */ -class ProxyAdapter implements AdapterInterface +class ProxyAdapter implements AdapterInterface, PruneableInterface, ResettableInterface { - private $pool; + use ProxyTrait; + private $namespace; private $namespaceLen; private $createCacheItem; diff --git a/src/Symfony/Component/Cache/Adapter/SimpleCacheAdapter.php b/src/Symfony/Component/Cache/Adapter/SimpleCacheAdapter.php index f17662441041b..24db5d504ab68 100644 --- a/src/Symfony/Component/Cache/Adapter/SimpleCacheAdapter.php +++ b/src/Symfony/Component/Cache/Adapter/SimpleCacheAdapter.php @@ -12,13 +12,17 @@ namespace Symfony\Component\Cache\Adapter; use Psr\SimpleCache\CacheInterface; +use Symfony\Component\Cache\PruneableInterface; +use Symfony\Component\Cache\ResettableInterface; +use Symfony\Component\Cache\Traits\ProxyTrait; /** * @author Nicolas Grekas */ -class SimpleCacheAdapter extends AbstractAdapter +class SimpleCacheAdapter extends AbstractAdapter implements PruneableInterface, ResettableInterface { - private $pool; + use ProxyTrait; + private $miss; public function __construct(CacheInterface $pool, $namespace = '', $defaultLifetime = 0) diff --git a/src/Symfony/Component/Cache/Adapter/TagAwareAdapter.php b/src/Symfony/Component/Cache/Adapter/TagAwareAdapter.php index 96df1128bb895..cb71ed3fd8cb8 100644 --- a/src/Symfony/Component/Cache/Adapter/TagAwareAdapter.php +++ b/src/Symfony/Component/Cache/Adapter/TagAwareAdapter.php @@ -15,26 +15,29 @@ use Psr\Cache\InvalidArgumentException; use Symfony\Component\Cache\CacheItem; use Symfony\Component\Cache\PruneableInterface; +use Symfony\Component\Cache\ResettableInterface; +use Symfony\Component\Cache\Traits\ProxyTrait; /** * @author Nicolas Grekas */ -class TagAwareAdapter implements TagAwareAdapterInterface, PruneableInterface +class TagAwareAdapter implements TagAwareAdapterInterface, PruneableInterface, ResettableInterface { const TAGS_PREFIX = "\0tags\0"; - private $itemsAdapter; + use ProxyTrait; + private $deferred = array(); private $createCacheItem; private $setCacheItemTags; private $getTagsByKey; private $invalidateTags; - private $tagsAdapter; + private $tagsPool; - public function __construct(AdapterInterface $itemsAdapter, AdapterInterface $tagsAdapter = null) + public function __construct(AdapterInterface $itemsPool, AdapterInterface $tagsPool = null) { - $this->itemsAdapter = $itemsAdapter; - $this->tagsAdapter = $tagsAdapter ?: $itemsAdapter; + $this->pool = $itemsPool; + $this->tags = $tagsPool ?: $itemsPool; $this->createCacheItem = \Closure::bind( function ($key, $value, CacheItem $protoItem) { $item = new CacheItem(); @@ -110,7 +113,7 @@ public function invalidateTags(array $tags) } $f = $this->invalidateTags; - return $f($this->tagsAdapter, $tags); + return $f($this->tags, $tags); } /** @@ -121,10 +124,10 @@ public function hasItem($key) if ($this->deferred) { $this->commit(); } - if (!$this->itemsAdapter->hasItem($key)) { + if (!$this->pool->hasItem($key)) { return false; } - if (!$itemTags = $this->itemsAdapter->getItem(static::TAGS_PREFIX.$key)->get()) { + if (!$itemTags = $this->pool->getItem(static::TAGS_PREFIX.$key)->get()) { return true; } @@ -165,9 +168,9 @@ public function getItems(array $keys = array()) } try { - $items = $this->itemsAdapter->getItems($tagKeys + $keys); + $items = $this->pool->getItems($tagKeys + $keys); } catch (InvalidArgumentException $e) { - $this->itemsAdapter->getItems($keys); // Should throw an exception + $this->pool->getItems($keys); // Should throw an exception throw $e; } @@ -182,7 +185,7 @@ public function clear() { $this->deferred = array(); - return $this->itemsAdapter->clear(); + return $this->pool->clear(); } /** @@ -204,7 +207,7 @@ public function deleteItems(array $keys) } } - return $this->itemsAdapter->deleteItems($keys); + return $this->pool->deleteItems($keys); } /** @@ -243,7 +246,7 @@ public function commit() if ($this->deferred) { $items = $this->deferred; foreach ($items as $key => $item) { - if (!$this->itemsAdapter->saveDeferred($item)) { + if (!$this->pool->saveDeferred($item)) { unset($this->deferred[$key]); $ok = false; } @@ -257,17 +260,17 @@ public function commit() foreach ($tagsByKey as $key => $tags) { if ($tags) { - $this->itemsAdapter->saveDeferred($f(static::TAGS_PREFIX.$key, array_intersect_key($tagVersions, $tags), $items[$key])); + $this->pool->saveDeferred($f(static::TAGS_PREFIX.$key, array_intersect_key($tagVersions, $tags), $items[$key])); } else { $deletedTags[] = static::TAGS_PREFIX.$key; } } if ($deletedTags) { - $this->itemsAdapter->deleteItems($deletedTags); + $this->pool->deleteItems($deletedTags); } } - return $this->itemsAdapter->commit() && $ok; + return $this->pool->commit() && $ok; } public function __destruct() @@ -328,23 +331,11 @@ private function getTagVersions(array $tagsByKey) $tagVersions[$tag] = $tag.static::TAGS_PREFIX; $tags[$tag.static::TAGS_PREFIX] = $tag; } - foreach ($this->tagsAdapter->getItems($tagVersions) as $tag => $version) { + foreach ($this->tags->getItems($tagVersions) as $tag => $version) { $tagVersions[$tags[$tag]] = $version->get() ?: 0; } } return $tagVersions; } - - /** - * {@inheritdoc} - */ - public function prune() - { - if ($this->itemsAdapter instanceof PruneableInterface) { - return $this->itemsAdapter->prune(); - } - - return false; - } } diff --git a/src/Symfony/Component/Cache/Adapter/TraceableAdapter.php b/src/Symfony/Component/Cache/Adapter/TraceableAdapter.php index 9959199f67ccc..e8563521baef8 100644 --- a/src/Symfony/Component/Cache/Adapter/TraceableAdapter.php +++ b/src/Symfony/Component/Cache/Adapter/TraceableAdapter.php @@ -12,6 +12,8 @@ namespace Symfony\Component\Cache\Adapter; use Psr\Cache\CacheItemInterface; +use Symfony\Component\Cache\PruneableInterface; +use Symfony\Component\Cache\ResettableInterface; /** * An adapter that collects data about all cache calls. @@ -20,7 +22,7 @@ * @author Tobias Nyholm * @author Nicolas Grekas */ -class TraceableAdapter implements AdapterInterface +class TraceableAdapter implements AdapterInterface, PruneableInterface, ResettableInterface { protected $pool; private $calls = array(); @@ -168,6 +170,38 @@ public function commit() } } + /** + * {@inheritdoc} + */ + public function prune() + { + if (!$this->pool instanceof PruneableInterface) { + return false; + } + $event = $this->start(__FUNCTION__); + try { + return $event->result = $this->pool->prune(); + } finally { + $event->end = microtime(true); + } + } + + /** + * {@inheritdoc} + */ + public function reset() + { + if (!$this->pool instanceof ResettableInterface) { + return; + } + $event = $this->start(__FUNCTION__); + try { + $this->pool->reset(); + } finally { + $event->end = microtime(true); + } + } + public function getCalls() { try { diff --git a/src/Symfony/Component/Cache/DoctrineProvider.php b/src/Symfony/Component/Cache/DoctrineProvider.php index 5d9c2faed7187..cebe95fbc7733 100644 --- a/src/Symfony/Component/Cache/DoctrineProvider.php +++ b/src/Symfony/Component/Cache/DoctrineProvider.php @@ -17,7 +17,7 @@ /** * @author Nicolas Grekas */ -class DoctrineProvider extends CacheProvider +class DoctrineProvider extends CacheProvider implements PruneableInterface, ResettableInterface { private $pool; @@ -26,6 +26,25 @@ public function __construct(CacheItemPoolInterface $pool) $this->pool = $pool; } + /** + * {@inheritdoc} + */ + public function prune() + { + return $this->pool instanceof PruneableInterface && $this->pool->prune(); + } + + /** + * {@inheritdoc} + */ + public function reset() + { + if ($this->pool instanceof ResettableInterface) { + $this->pool->reset(); + } + $this->setNamespace($this->getNamespace()); + } + /** * {@inheritdoc} */ diff --git a/src/Symfony/Component/Cache/ResettableInterface.php b/src/Symfony/Component/Cache/ResettableInterface.php new file mode 100644 index 0000000000000..6be72861e709c --- /dev/null +++ b/src/Symfony/Component/Cache/ResettableInterface.php @@ -0,0 +1,20 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache; + +/** + * Resets a pool's local state. + */ +interface ResettableInterface +{ + public function reset(); +} diff --git a/src/Symfony/Component/Cache/Simple/AbstractCache.php b/src/Symfony/Component/Cache/Simple/AbstractCache.php index 264eb60653339..e666effaf93f9 100644 --- a/src/Symfony/Component/Cache/Simple/AbstractCache.php +++ b/src/Symfony/Component/Cache/Simple/AbstractCache.php @@ -16,11 +16,12 @@ use Symfony\Component\Cache\CacheItem; use Symfony\Component\Cache\Exception\InvalidArgumentException; use Symfony\Component\Cache\Traits\AbstractTrait; +use Symfony\Component\Cache\ResettableInterface; /** * @author Nicolas Grekas */ -abstract class AbstractCache implements CacheInterface, LoggerAwareInterface +abstract class AbstractCache implements CacheInterface, LoggerAwareInterface, ResettableInterface { use AbstractTrait { deleteItems as private; diff --git a/src/Symfony/Component/Cache/Simple/ArrayCache.php b/src/Symfony/Component/Cache/Simple/ArrayCache.php index a89768b0e2331..8d027cd2a3722 100644 --- a/src/Symfony/Component/Cache/Simple/ArrayCache.php +++ b/src/Symfony/Component/Cache/Simple/ArrayCache.php @@ -15,12 +15,13 @@ use Psr\SimpleCache\CacheInterface; use Symfony\Component\Cache\CacheItem; use Symfony\Component\Cache\Exception\InvalidArgumentException; +use Symfony\Component\Cache\ResettableInterface; use Symfony\Component\Cache\Traits\ArrayTrait; /** * @author Nicolas Grekas */ -class ArrayCache implements CacheInterface, LoggerAwareInterface +class ArrayCache implements CacheInterface, LoggerAwareInterface, ResettableInterface { use ArrayTrait { ArrayTrait::deleteItem as delete; diff --git a/src/Symfony/Component/Cache/Simple/ChainCache.php b/src/Symfony/Component/Cache/Simple/ChainCache.php index 8bb944fd4773f..9d0c75870eb7e 100644 --- a/src/Symfony/Component/Cache/Simple/ChainCache.php +++ b/src/Symfony/Component/Cache/Simple/ChainCache.php @@ -14,6 +14,7 @@ use Psr\SimpleCache\CacheInterface; use Symfony\Component\Cache\Exception\InvalidArgumentException; use Symfony\Component\Cache\PruneableInterface; +use Symfony\Component\Cache\ResettableInterface; /** * Chains several caches together. @@ -23,7 +24,7 @@ * * @author Nicolas Grekas */ -class ChainCache implements CacheInterface, PruneableInterface +class ChainCache implements CacheInterface, PruneableInterface, ResettableInterface { private $miss; private $caches = array(); @@ -236,4 +237,16 @@ public function prune() return $pruned; } + + /** + * {@inheritdoc} + */ + public function reset() + { + foreach ($this->caches as $cache) { + if ($cache instanceof ResettableInterface) { + $cache->reset(); + } + } + } } diff --git a/src/Symfony/Component/Cache/Simple/PhpArrayCache.php b/src/Symfony/Component/Cache/Simple/PhpArrayCache.php index 92180e63168bc..3db8a2ac1c044 100644 --- a/src/Symfony/Component/Cache/Simple/PhpArrayCache.php +++ b/src/Symfony/Component/Cache/Simple/PhpArrayCache.php @@ -14,6 +14,8 @@ use Psr\SimpleCache\CacheInterface; use Symfony\Component\Cache\Exception\InvalidArgumentException; use Symfony\Component\Cache\Traits\PhpArrayTrait; +use Symfony\Component\Cache\PruneableInterface; +use Symfony\Component\Cache\ResettableInterface; /** * Caches items at warm up time using a PHP array that is stored in shared memory by OPCache since PHP 7.0. @@ -22,7 +24,7 @@ * @author Titouan Galopin * @author Nicolas Grekas */ -class PhpArrayCache implements CacheInterface +class PhpArrayCache implements CacheInterface, PruneableInterface, ResettableInterface { use PhpArrayTrait; @@ -33,7 +35,7 @@ class PhpArrayCache implements CacheInterface public function __construct($file, CacheInterface $fallbackPool) { $this->file = $file; - $this->fallbackPool = $fallbackPool; + $this->pool = $fallbackPool; $this->zendDetectUnicode = ini_get('zend.detect_unicode'); } @@ -68,7 +70,7 @@ public function get($key, $default = null) $this->initialize(); } if (!isset($this->values[$key])) { - return $this->fallbackPool->get($key, $default); + return $this->pool->get($key, $default); } $value = $this->values[$key]; @@ -124,7 +126,7 @@ public function has($key) $this->initialize(); } - return isset($this->values[$key]) || $this->fallbackPool->has($key); + return isset($this->values[$key]) || $this->pool->has($key); } /** @@ -139,7 +141,7 @@ public function delete($key) $this->initialize(); } - return !isset($this->values[$key]) && $this->fallbackPool->delete($key); + return !isset($this->values[$key]) && $this->pool->delete($key); } /** @@ -170,7 +172,7 @@ public function deleteMultiple($keys) } if ($fallbackKeys) { - $deleted = $this->fallbackPool->deleteMultiple($fallbackKeys) && $deleted; + $deleted = $this->pool->deleteMultiple($fallbackKeys) && $deleted; } return $deleted; @@ -188,7 +190,7 @@ public function set($key, $value, $ttl = null) $this->initialize(); } - return !isset($this->values[$key]) && $this->fallbackPool->set($key, $value, $ttl); + return !isset($this->values[$key]) && $this->pool->set($key, $value, $ttl); } /** @@ -216,7 +218,7 @@ public function setMultiple($values, $ttl = null) } if ($fallbackValues) { - $saved = $this->fallbackPool->setMultiple($fallbackValues, $ttl) && $saved; + $saved = $this->pool->setMultiple($fallbackValues, $ttl) && $saved; } return $saved; @@ -249,7 +251,7 @@ private function generateItems(array $keys, $default) } if ($fallbackKeys) { - foreach ($this->fallbackPool->getMultiple($fallbackKeys, $default) as $key => $item) { + foreach ($this->pool->getMultiple($fallbackKeys, $default) as $key => $item) { yield $key => $item; } } diff --git a/src/Symfony/Component/Cache/Simple/Psr6Cache.php b/src/Symfony/Component/Cache/Simple/Psr6Cache.php index 55fa98da1274c..81f14d4a7045c 100644 --- a/src/Symfony/Component/Cache/Simple/Psr6Cache.php +++ b/src/Symfony/Component/Cache/Simple/Psr6Cache.php @@ -18,13 +18,17 @@ use Symfony\Component\Cache\Adapter\AbstractAdapter; use Symfony\Component\Cache\CacheItem; use Symfony\Component\Cache\Exception\InvalidArgumentException; +use Symfony\Component\Cache\PruneableInterface; +use Symfony\Component\Cache\ResettableInterface; +use Symfony\Component\Cache\Traits\ProxyTrait; /** * @author Nicolas Grekas */ -class Psr6Cache implements CacheInterface +class Psr6Cache implements CacheInterface, PruneableInterface, ResettableInterface { - private $pool; + use ProxyTrait; + private $createCacheItem; public function __construct(CacheItemPoolInterface $pool) diff --git a/src/Symfony/Component/Cache/Simple/TraceableCache.php b/src/Symfony/Component/Cache/Simple/TraceableCache.php index 29cc10bbb27a1..756403bf1430e 100644 --- a/src/Symfony/Component/Cache/Simple/TraceableCache.php +++ b/src/Symfony/Component/Cache/Simple/TraceableCache.php @@ -12,13 +12,15 @@ namespace Symfony\Component\Cache\Simple; use Psr\SimpleCache\CacheInterface; +use Symfony\Component\Cache\PruneableInterface; +use Symfony\Component\Cache\ResettableInterface; /** * An adapter that collects data about all cache calls. * * @author Nicolas Grekas */ -class TraceableCache implements CacheInterface +class TraceableCache implements CacheInterface, PruneableInterface, ResettableInterface { private $pool; private $miss; @@ -177,6 +179,38 @@ public function deleteMultiple($keys) } } + /** + * {@inheritdoc} + */ + public function prune() + { + if (!$this->pool instanceof PruneableInterface) { + return false; + } + $event = $this->start(__FUNCTION__); + try { + return $event->result = $this->pool->prune(); + } finally { + $event->end = microtime(true); + } + } + + /** + * {@inheritdoc} + */ + public function reset() + { + if (!$this->pool instanceof ResettableInterface) { + return; + } + $event = $this->start(__FUNCTION__); + try { + $this->pool->reset(); + } finally { + $event->end = microtime(true); + } + } + public function getCalls() { try { diff --git a/src/Symfony/Component/Cache/Tests/Adapter/PhpArrayAdapterTest.php b/src/Symfony/Component/Cache/Tests/Adapter/PhpArrayAdapterTest.php index 134dba7c90444..14b61263c5892 100644 --- a/src/Symfony/Component/Cache/Tests/Adapter/PhpArrayAdapterTest.php +++ b/src/Symfony/Component/Cache/Tests/Adapter/PhpArrayAdapterTest.php @@ -50,6 +50,7 @@ class PhpArrayAdapterTest extends AdapterTestCase 'testDeleteItemsInvalidKeys' => 'PhpArrayAdapter does not throw exceptions on invalid key.', 'testDefaultLifeTime' => 'PhpArrayAdapter does not allow configuring a default lifetime.', + 'testPrune' => 'PhpArrayAdapter just proxies', ); protected static $file; diff --git a/src/Symfony/Component/Cache/Tests/Adapter/PhpArrayAdapterWithFallbackTest.php b/src/Symfony/Component/Cache/Tests/Adapter/PhpArrayAdapterWithFallbackTest.php index 45a50d2323a61..1a23198c2f98d 100644 --- a/src/Symfony/Component/Cache/Tests/Adapter/PhpArrayAdapterWithFallbackTest.php +++ b/src/Symfony/Component/Cache/Tests/Adapter/PhpArrayAdapterWithFallbackTest.php @@ -25,6 +25,7 @@ class PhpArrayAdapterWithFallbackTest extends AdapterTestCase 'testHasItemInvalidKeys' => 'PhpArrayAdapter does not throw exceptions on invalid key.', 'testDeleteItemInvalidKeys' => 'PhpArrayAdapter does not throw exceptions on invalid key.', 'testDeleteItemsInvalidKeys' => 'PhpArrayAdapter does not throw exceptions on invalid key.', + 'testPrune' => 'PhpArrayAdapter just proxies', ); protected static $file; diff --git a/src/Symfony/Component/Cache/Tests/Adapter/ProxyAdapterTest.php b/src/Symfony/Component/Cache/Tests/Adapter/ProxyAdapterTest.php index c0174dd248222..5e6abd16c18c4 100644 --- a/src/Symfony/Component/Cache/Tests/Adapter/ProxyAdapterTest.php +++ b/src/Symfony/Component/Cache/Tests/Adapter/ProxyAdapterTest.php @@ -24,6 +24,7 @@ class ProxyAdapterTest extends AdapterTestCase protected $skippedTests = array( 'testDeferredSaveWithoutCommit' => 'Assumes a shared cache which ArrayAdapter is not.', 'testSaveWithoutExpire' => 'Assumes a shared cache which ArrayAdapter is not.', + 'testPrune' => 'ProxyAdapter just proxies', ); public function createCachePool($defaultLifetime = 0) diff --git a/src/Symfony/Component/Cache/Tests/Adapter/SimpleCacheAdapterTest.php b/src/Symfony/Component/Cache/Tests/Adapter/SimpleCacheAdapterTest.php index 1e0297c69e993..d5795d52e7128 100644 --- a/src/Symfony/Component/Cache/Tests/Adapter/SimpleCacheAdapterTest.php +++ b/src/Symfony/Component/Cache/Tests/Adapter/SimpleCacheAdapterTest.php @@ -19,6 +19,10 @@ */ class SimpleCacheAdapterTest extends AdapterTestCase { + protected $skippedTests = array( + 'testPrune' => 'SimpleCache just proxies', + ); + public function createCachePool($defaultLifetime = 0) { return new SimpleCacheAdapter(new FilesystemCache(), '', $defaultLifetime); diff --git a/src/Symfony/Component/Cache/Tests/Adapter/TraceableAdapterTest.php b/src/Symfony/Component/Cache/Tests/Adapter/TraceableAdapterTest.php index dec2f255555be..3755e88db5f15 100644 --- a/src/Symfony/Component/Cache/Tests/Adapter/TraceableAdapterTest.php +++ b/src/Symfony/Component/Cache/Tests/Adapter/TraceableAdapterTest.php @@ -19,6 +19,10 @@ */ class TraceableAdapterTest extends AdapterTestCase { + protected $skippedTests = array( + 'testPrune' => 'TraceableAdapter just proxies', + ); + public function createCachePool($defaultLifetime = 0) { return new TraceableAdapter(new FilesystemAdapter('', $defaultLifetime)); diff --git a/src/Symfony/Component/Cache/Tests/Simple/PhpArrayCacheTest.php b/src/Symfony/Component/Cache/Tests/Simple/PhpArrayCacheTest.php index 57361905f8869..1bd0ca2778bb4 100644 --- a/src/Symfony/Component/Cache/Tests/Simple/PhpArrayCacheTest.php +++ b/src/Symfony/Component/Cache/Tests/Simple/PhpArrayCacheTest.php @@ -44,6 +44,7 @@ class PhpArrayCacheTest extends CacheTestCase 'testSetValidData' => 'PhpArrayCache does no validation', 'testDefaultLifeTime' => 'PhpArrayCache does not allow configuring a default lifetime.', + 'testPrune' => 'PhpArrayCache just proxies', ); protected static $file; diff --git a/src/Symfony/Component/Cache/Tests/Simple/PhpArrayCacheWithFallbackTest.php b/src/Symfony/Component/Cache/Tests/Simple/PhpArrayCacheWithFallbackTest.php index a624fa73e783a..4b6a94f709b6d 100644 --- a/src/Symfony/Component/Cache/Tests/Simple/PhpArrayCacheWithFallbackTest.php +++ b/src/Symfony/Component/Cache/Tests/Simple/PhpArrayCacheWithFallbackTest.php @@ -31,6 +31,7 @@ class PhpArrayCacheWithFallbackTest extends CacheTestCase 'testSetMultipleInvalidKeys' => 'PhpArrayCache does no validation', 'testSetMultipleInvalidTtl' => 'PhpArrayCache does no validation', 'testHasInvalidKeys' => 'PhpArrayCache does no validation', + 'testPrune' => 'PhpArrayCache just proxies', ); protected static $file; diff --git a/src/Symfony/Component/Cache/Tests/Simple/Psr6CacheTest.php b/src/Symfony/Component/Cache/Tests/Simple/Psr6CacheTest.php index 16e21d0c0b63b..78582894fbe1e 100644 --- a/src/Symfony/Component/Cache/Tests/Simple/Psr6CacheTest.php +++ b/src/Symfony/Component/Cache/Tests/Simple/Psr6CacheTest.php @@ -19,6 +19,10 @@ */ class Psr6CacheTest extends CacheTestCase { + protected $skippedTests = array( + 'testPrune' => 'Psr6Cache just proxies', + ); + public function createSimpleCache($defaultLifetime = 0) { return new Psr6Cache(new FilesystemAdapter('', $defaultLifetime)); diff --git a/src/Symfony/Component/Cache/Tests/Simple/TraceableCacheTest.php b/src/Symfony/Component/Cache/Tests/Simple/TraceableCacheTest.php index 7feccba1af905..535f93da4be5a 100644 --- a/src/Symfony/Component/Cache/Tests/Simple/TraceableCacheTest.php +++ b/src/Symfony/Component/Cache/Tests/Simple/TraceableCacheTest.php @@ -19,6 +19,10 @@ */ class TraceableCacheTest extends CacheTestCase { + protected $skippedTests = array( + 'testPrune' => 'TraceableCache just proxies', + ); + public function createSimpleCache($defaultLifetime = 0) { return new TraceableCache(new FilesystemCache('', $defaultLifetime)); diff --git a/src/Symfony/Component/Cache/Traits/AbstractTrait.php b/src/Symfony/Component/Cache/Traits/AbstractTrait.php index 108ac67c8e12f..d7af3b559e0ee 100644 --- a/src/Symfony/Component/Cache/Traits/AbstractTrait.php +++ b/src/Symfony/Component/Cache/Traits/AbstractTrait.php @@ -189,6 +189,17 @@ public function enableVersioning($enable = true) return $wasEnabled; } + /** + * {@inheritdoc} + */ + public function reset() + { + if ($this->deferred) { + $this->commit(); + } + $this->namespaceVersion = ''; + } + /** * Like the native unserialize() function but throws an exception if anything goes wrong. * diff --git a/src/Symfony/Component/Cache/Traits/ArrayTrait.php b/src/Symfony/Component/Cache/Traits/ArrayTrait.php index 3fb5fa36bef2c..b7d2ad6d6299c 100644 --- a/src/Symfony/Component/Cache/Traits/ArrayTrait.php +++ b/src/Symfony/Component/Cache/Traits/ArrayTrait.php @@ -69,6 +69,14 @@ public function deleteItem($key) return true; } + /** + * {@inheritdoc} + */ + public function reset() + { + $this->clear(); + } + private function generateItems(array $keys, $now, $f) { foreach ($keys as $i => $key) { diff --git a/src/Symfony/Component/Cache/Traits/DoctrineTrait.php b/src/Symfony/Component/Cache/Traits/DoctrineTrait.php index be351cf53a552..c87ecabafc803 100644 --- a/src/Symfony/Component/Cache/Traits/DoctrineTrait.php +++ b/src/Symfony/Component/Cache/Traits/DoctrineTrait.php @@ -20,6 +20,15 @@ trait DoctrineTrait { private $provider; + /** + * {@inheritdoc} + */ + public function reset() + { + parent::reset(); + $this->provider->setNamespace($this->provider->getNamespace()); + } + /** * {@inheritdoc} */ diff --git a/src/Symfony/Component/Cache/Traits/PhpArrayTrait.php b/src/Symfony/Component/Cache/Traits/PhpArrayTrait.php index ccc48886d0cc3..ae634d6baa295 100644 --- a/src/Symfony/Component/Cache/Traits/PhpArrayTrait.php +++ b/src/Symfony/Component/Cache/Traits/PhpArrayTrait.php @@ -22,9 +22,10 @@ */ trait PhpArrayTrait { + use ProxyTrait; + private $file; private $values; - private $fallbackPool; private $zendDetectUnicode; /** @@ -119,7 +120,7 @@ public function clear() $cleared = @unlink($this->file) || !file_exists($this->file); - return $this->fallbackPool->clear() && $cleared; + return $this->pool->clear() && $cleared; } /** diff --git a/src/Symfony/Component/Cache/Traits/ProxyTrait.php b/src/Symfony/Component/Cache/Traits/ProxyTrait.php new file mode 100644 index 0000000000000..06dba7e59bf7e --- /dev/null +++ b/src/Symfony/Component/Cache/Traits/ProxyTrait.php @@ -0,0 +1,41 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Cache\Traits; + +use Symfony\Component\Cache\PruneableInterface; +use Symfony\Component\Cache\ResettableInterface; + +/** + * @author Nicolas Grekas + */ +trait ProxyTrait +{ + private $pool; + + /** + * {@inheritdoc} + */ + public function prune() + { + return $this->pool instanceof PruneableInterface && $this->pool->prune(); + } + + /** + * {@inheritdoc} + */ + public function reset() + { + if ($this->pool instanceof ResettableInterface) { + $this->pool->reset(); + } + } +} From dc55dd2c99a337d9baf803f017f139f1b280124b Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Sun, 24 Sep 2017 00:04:06 +0200 Subject: [PATCH 0884/1099] [DI] Add AutowireRequiredMethodsPass to fix bindings for `@required` methods --- .../Compiler/AbstractRecursivePass.php | 18 +- .../Compiler/AutowirePass.php | 60 +-- .../Compiler/AutowireRequiredMethodsPass.php | 70 ++++ .../Compiler/PassConfig.php | 1 + .../Compiler/ResolveNamedArgumentsPass.php | 6 +- .../Tests/Compiler/AutowirePassTest.php | 342 +---------------- .../AutowireRequiredMethodsPassTest.php | 80 ++++ .../Compiler/ResolveBindingsPassTest.php | 16 + .../Fixtures/includes/autowiring_classes.php | 343 ++++++++++++++++++ 9 files changed, 535 insertions(+), 401 deletions(-) create mode 100644 src/Symfony/Component/DependencyInjection/Compiler/AutowireRequiredMethodsPass.php create mode 100644 src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowireRequiredMethodsPassTest.php create mode 100644 src/Symfony/Component/DependencyInjection/Tests/Fixtures/includes/autowiring_classes.php diff --git a/src/Symfony/Component/DependencyInjection/Compiler/AbstractRecursivePass.php b/src/Symfony/Component/DependencyInjection/Compiler/AbstractRecursivePass.php index bbe869b935e5c..ddc7d004da40d 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/AbstractRecursivePass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/AbstractRecursivePass.php @@ -90,7 +90,7 @@ protected function getConstructor(Definition $definition, $required) { if (is_string($factory = $definition->getFactory())) { if (!function_exists($factory)) { - throw new RuntimeException(sprintf('Unable to resolve service "%s": function "%s" does not exist.', $this->currentId, $factory)); + throw new RuntimeException(sprintf('Invalid service "%s": function "%s" does not exist.', $this->currentId, $factory)); } $r = new \ReflectionFunction($factory); if (false !== $r->getFileName() && file_exists($r->getFileName())) { @@ -108,7 +108,7 @@ protected function getConstructor(Definition $definition, $required) $class = $definition->getClass(); } if ('__construct' === $method) { - throw new RuntimeException(sprintf('Unable to resolve service "%s": "__construct()" cannot be used as a factory method.', $this->currentId)); + throw new RuntimeException(sprintf('Invalid service "%s": "__construct()" cannot be used as a factory method.', $this->currentId)); } return $this->getReflectionMethod(new Definition($class), $method); @@ -117,14 +117,14 @@ protected function getConstructor(Definition $definition, $required) $class = $definition->getClass(); if (!$r = $this->container->getReflectionClass($class)) { - throw new RuntimeException(sprintf('Unable to resolve service "%s": class "%s" does not exist.', $this->currentId, $class)); + throw new RuntimeException(sprintf('Invalid service "%s": class "%s" does not exist.', $this->currentId, $class)); } if (!$r = $r->getConstructor()) { if ($required) { - throw new RuntimeException(sprintf('Unable to resolve service "%s": class%s has no constructor.', $this->currentId, sprintf($class !== $this->currentId ? ' "%s"' : '', $class))); + throw new RuntimeException(sprintf('Invalid service "%s": class%s has no constructor.', $this->currentId, sprintf($class !== $this->currentId ? ' "%s"' : '', $class))); } } elseif (!$r->isPublic()) { - throw new RuntimeException(sprintf('Unable to resolve service "%s": %s must be public.', $this->currentId, sprintf($class !== $this->currentId ? 'constructor of class "%s"' : 'its constructor', $class))); + throw new RuntimeException(sprintf('Invalid service "%s": %s must be public.', $this->currentId, sprintf($class !== $this->currentId ? 'constructor of class "%s"' : 'its constructor', $class))); } return $r; @@ -145,20 +145,20 @@ protected function getReflectionMethod(Definition $definition, $method) } if (!$class = $definition->getClass()) { - throw new RuntimeException(sprintf('Unable to resolve service "%s": the class is not set.', $this->currentId)); + throw new RuntimeException(sprintf('Invalid service "%s": the class is not set.', $this->currentId)); } if (!$r = $this->container->getReflectionClass($class)) { - throw new RuntimeException(sprintf('Unable to resolve service "%s": class "%s" does not exist.', $this->currentId, $class)); + throw new RuntimeException(sprintf('Invalid service "%s": class "%s" does not exist.', $this->currentId, $class)); } if (!$r->hasMethod($method)) { - throw new RuntimeException(sprintf('Unable to resolve service "%s": method "%s()" does not exist.', $this->currentId, $class !== $this->currentId ? $class.'::'.$method : $method)); + throw new RuntimeException(sprintf('Invalid service "%s": method "%s()" does not exist.', $this->currentId, $class !== $this->currentId ? $class.'::'.$method : $method)); } $r = $r->getMethod($method); if (!$r->isPublic()) { - throw new RuntimeException(sprintf('Unable to resolve service "%s": method "%s()" must be public.', $this->currentId, $class !== $this->currentId ? $class.'::'.$method : $method)); + throw new RuntimeException(sprintf('Invalid service "%s": method "%s()" must be public.', $this->currentId, $class !== $this->currentId ? $class.'::'.$method : $method)); } return $r; diff --git a/src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php b/src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php index 8cb1978ef675d..ace116fb9b515 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php @@ -130,7 +130,6 @@ private function doProcessValue($value, $isRoot = false) return $value; } - $autowiredMethods = $this->getMethodsToAutowire($reflectionClass); $methodCalls = $value->getMethodCalls(); try { @@ -143,7 +142,7 @@ private function doProcessValue($value, $isRoot = false) array_unshift($methodCalls, array($constructor, $value->getArguments())); } - $methodCalls = $this->autowireCalls($reflectionClass, $methodCalls, $autowiredMethods); + $methodCalls = $this->autowireCalls($reflectionClass, $methodCalls); if ($constructor) { list(, $arguments) = array_shift($methodCalls); @@ -161,61 +160,18 @@ private function doProcessValue($value, $isRoot = false) } /** - * Gets the list of methods to autowire. - * * @param \ReflectionClass $reflectionClass - * - * @return \ReflectionMethod[] - */ - private function getMethodsToAutowire(\ReflectionClass $reflectionClass) - { - $methodsToAutowire = array(); - - foreach ($reflectionClass->getMethods() as $reflectionMethod) { - $r = $reflectionMethod; - - if ($r->isConstructor()) { - continue; - } - - while (true) { - if (false !== $doc = $r->getDocComment()) { - if (false !== stripos($doc, '@required') && preg_match('#(?:^/\*\*|\n\s*+\*)\s*+@required(?:\s|\*/$)#i', $doc)) { - $methodsToAutowire[strtolower($reflectionMethod->name)] = $reflectionMethod; - break; - } - if (false === stripos($doc, '@inheritdoc') || !preg_match('#(?:^/\*\*|\n\s*+\*)\s*+(?:\{@inheritdoc\}|@inheritdoc)(?:\s|\*/$)#i', $doc)) { - break; - } - } - try { - $r = $r->getPrototype(); - } catch (\ReflectionException $e) { - break; // method has no prototype - } - } - } - - return $methodsToAutowire; - } - - /** - * @param \ReflectionClass $reflectionClass - * @param array $methodCalls - * @param \ReflectionMethod[] $autowiredMethods + * @param array $methodCalls * * @return array */ - private function autowireCalls(\ReflectionClass $reflectionClass, array $methodCalls, array $autowiredMethods) + private function autowireCalls(\ReflectionClass $reflectionClass, array $methodCalls) { foreach ($methodCalls as $i => $call) { list($method, $arguments) = $call; if ($method instanceof \ReflectionFunctionAbstract) { $reflectionMethod = $method; - } elseif (isset($autowiredMethods[$lcMethod = strtolower($method)]) && $autowiredMethods[$lcMethod]->isPublic()) { - $reflectionMethod = $autowiredMethods[$lcMethod]; - unset($autowiredMethods[$lcMethod]); } else { $reflectionMethod = $this->getReflectionMethod(new Definition($reflectionClass->name), $method); } @@ -227,16 +183,6 @@ private function autowireCalls(\ReflectionClass $reflectionClass, array $methodC } } - foreach ($autowiredMethods as $lcMethod => $reflectionMethod) { - $method = $reflectionMethod->name; - - if (!$reflectionMethod->isPublic()) { - $class = $reflectionClass->name; - throw new AutowiringFailedException($this->currentId, sprintf('Cannot autowire service "%s": method "%s()" must be public.', $this->currentId, $class !== $this->currentId ? $class.'::'.$method : $method)); - } - $methodCalls[] = array($method, $this->autowireMethod($reflectionMethod, array())); - } - return $methodCalls; } diff --git a/src/Symfony/Component/DependencyInjection/Compiler/AutowireRequiredMethodsPass.php b/src/Symfony/Component/DependencyInjection/Compiler/AutowireRequiredMethodsPass.php new file mode 100644 index 0000000000000..6c744f88f6a94 --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Compiler/AutowireRequiredMethodsPass.php @@ -0,0 +1,70 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Compiler; + +use Symfony\Component\DependencyInjection\Definition; + +/** + * Looks for definitions with autowiring enabled and registers their corresponding "@required" methods as setters. + * + * @author Nicolas Grekas + */ +class AutowireRequiredMethodsPass extends AbstractRecursivePass +{ + /** + * {@inheritdoc} + */ + protected function processValue($value, $isRoot = false) + { + $value = parent::processValue($value, $isRoot); + + if (!$value instanceof Definition || !$value->isAutowired() || $value->isAbstract() || !$value->getClass()) { + return $value; + } + if (!$reflectionClass = $this->container->getReflectionClass($value->getClass(), false)) { + return $value; + } + + $alreadyCalledMethods = array(); + + foreach ($value->getMethodCalls() as list($method)) { + $alreadyCalledMethods[strtolower($method)] = true; + } + + foreach ($reflectionClass->getMethods() as $reflectionMethod) { + $r = $reflectionMethod; + + if ($r->isConstructor() || isset($alreadyCalledMethods[strtolower($r->name)])) { + continue; + } + + while (true) { + if (false !== $doc = $r->getDocComment()) { + if (false !== stripos($doc, '@required') && preg_match('#(?:^/\*\*|\n\s*+\*)\s*+@required(?:\s|\*/$)#i', $doc)) { + $value->addMethodCall($reflectionMethod->name); + break; + } + if (false === stripos($doc, '@inheritdoc') || !preg_match('#(?:^/\*\*|\n\s*+\*)\s*+(?:\{@inheritdoc\}|@inheritdoc)(?:\s|\*/$)#i', $doc)) { + break; + } + } + try { + $r = $r->getPrototype(); + } catch (\ReflectionException $e) { + break; // method has no prototype + } + } + } + + return $value; + } +} diff --git a/src/Symfony/Component/DependencyInjection/Compiler/PassConfig.php b/src/Symfony/Component/DependencyInjection/Compiler/PassConfig.php index 79792bee4a106..e80b8e6cc8623 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/PassConfig.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/PassConfig.php @@ -58,6 +58,7 @@ public function __construct() new CheckDefinitionValidityPass(), new RegisterServiceSubscribersPass(), new ResolveNamedArgumentsPass(), + new AutowireRequiredMethodsPass(), new ResolveBindingsPass(), $autowirePass = new AutowirePass(false), new ResolveServiceSubscribersPass(), diff --git a/src/Symfony/Component/DependencyInjection/Compiler/ResolveNamedArgumentsPass.php b/src/Symfony/Component/DependencyInjection/Compiler/ResolveNamedArgumentsPass.php index e4d592d0c6473..a96f981d074b4 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/ResolveNamedArgumentsPass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/ResolveNamedArgumentsPass.php @@ -61,11 +61,11 @@ protected function processValue($value, $isRoot = false) } } - throw new InvalidArgumentException(sprintf('Unable to resolve service "%s": method "%s()" has no argument named "%s". Check your service definition.', $this->currentId, $class !== $this->currentId ? $class.'::'.$method : $method, $key)); + throw new InvalidArgumentException(sprintf('Invalid service "%s": method "%s()" has no argument named "%s". Check your service definition.', $this->currentId, $class !== $this->currentId ? $class.'::'.$method : $method, $key)); } if (null !== $argument && !$argument instanceof Reference && !$argument instanceof Definition) { - throw new InvalidArgumentException(sprintf('Unable to resolve service "%s": the value of argument "%s" of method "%s()" must be null, an instance of %s or an instance of %s, %s given.', $this->currentId, $key, $class !== $this->currentId ? $class.'::'.$method : $method, Reference::class, Definition::class, gettype($argument))); + throw new InvalidArgumentException(sprintf('Invalid service "%s": the value of argument "%s" of method "%s()" must be null, an instance of %s or an instance of %s, %s given.', $this->currentId, $key, $class !== $this->currentId ? $class.'::'.$method : $method, Reference::class, Definition::class, gettype($argument))); } foreach ($parameters as $j => $p) { @@ -76,7 +76,7 @@ protected function processValue($value, $isRoot = false) } } - throw new InvalidArgumentException(sprintf('Unable to resolve service "%s": method "%s()" has no argument type-hinted as "%s". Check your service definition.', $this->currentId, $class !== $this->currentId ? $class.'::'.$method : $method, $key)); + throw new InvalidArgumentException(sprintf('Invalid service "%s": method "%s()" has no argument type-hinted as "%s". Check your service definition.', $this->currentId, $class !== $this->currentId ? $class.'::'.$method : $method, $key)); } if ($resolvedArguments !== $call[1]) { diff --git a/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowirePassTest.php b/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowirePassTest.php index 94666df608391..dbf839b4eac83 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowirePassTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowirePassTest.php @@ -12,6 +12,7 @@ namespace Symfony\Component\DependencyInjection\Tests\Compiler; use PHPUnit\Framework\TestCase; +use Symfony\Component\DependencyInjection\Compiler\AutowireRequiredMethodsPass; use Symfony\Component\DependencyInjection\Compiler\AutowirePass; use Symfony\Component\DependencyInjection\Compiler\ResolveClassPass; use Symfony\Component\DependencyInjection\ContainerBuilder; @@ -20,6 +21,8 @@ use Symfony\Component\DependencyInjection\Tests\Fixtures\includes\FooVariadic; use Symfony\Component\DependencyInjection\TypedReference; +require_once __DIR__.'/../Fixtures/includes/autowiring_classes.php'; + /** * @author Kévin Dunglas */ @@ -174,7 +177,7 @@ public function testExceptionsAreStored() /** * @expectedException \Symfony\Component\DependencyInjection\Exception\AutowiringFailedException - * @expectedExceptionMessage Unable to resolve service "private_service": constructor of class "Symfony\Component\DependencyInjection\Tests\Compiler\PrivateConstructor" must be public. + * @expectedExceptionMessage Invalid service "private_service": constructor of class "Symfony\Component\DependencyInjection\Tests\Compiler\PrivateConstructor" must be public. */ public function testPrivateConstructorThrowsAutowireException() { @@ -554,6 +557,7 @@ public function testSetterInjection() ; (new ResolveClassPass())->process($container); + (new AutowireRequiredMethodsPass())->process($container); (new AutowirePass())->process($container); $methodCalls = $container->getDefinition('setter_injection')->getMethodCalls(); @@ -590,6 +594,7 @@ public function testExplicitMethodInjection() ; (new ResolveClassPass())->process($container); + (new AutowireRequiredMethodsPass())->process($container); (new AutowirePass())->process($container); $methodCalls = $container->getDefinition('setter_injection')->getMethodCalls(); @@ -687,6 +692,8 @@ public function testSetterInjectionCollisionThrowsException() $aDefinition = $container->register('setter_injection_collision', SetterInjectionCollision::class); $aDefinition->setAutowired(true); + (new AutowireRequiredMethodsPass())->process($container); + $pass = new AutowirePass(); $pass->process($container); } @@ -770,6 +777,7 @@ public function testNotWireableCalls($method, $expectedMsg) } (new ResolveClassPass())->process($container); + (new AutowireRequiredMethodsPass())->process($container); (new AutowirePass())->process($container); } @@ -778,7 +786,7 @@ public function provideNotWireableCalls() return array( array('setNotAutowireable', 'Cannot autowire service "foo": argument "$n" of method "Symfony\Component\DependencyInjection\Tests\Compiler\NotWireable::setNotAutowireable()" has type "Symfony\Component\DependencyInjection\Tests\Compiler\NotARealClass" but this class cannot be loaded.'), array('setDifferentNamespace', 'Cannot autowire service "foo": argument "$n" of method "Symfony\Component\DependencyInjection\Tests\Compiler\NotWireable::setDifferentNamespace()" references class "stdClass" but no such service exists. It cannot be auto-registered because it is from a different root namespace.'), - array(null, 'Cannot autowire service "foo": method "Symfony\Component\DependencyInjection\Tests\Compiler\NotWireable::setProtectedMethod()" must be public.'), + array(null, 'Invalid service "foo": method "Symfony\Component\DependencyInjection\Tests\Compiler\NotWireable::setProtectedMethod()" must be public.'), ); } @@ -859,333 +867,3 @@ public function testExceptionWhenAliasDoesNotExist() $pass->process($container); } } - -class Foo -{ -} - -class Bar -{ - public function __construct(Foo $foo) - { - } -} - -interface AInterface -{ -} - -class A implements AInterface -{ - public static function create(Foo $foo) - { - } -} - -class B extends A -{ -} - -class C -{ - public function __construct(A $a) - { - } -} - -interface DInterface -{ -} - -interface EInterface extends DInterface -{ -} - -interface IInterface -{ -} - -class I implements IInterface -{ -} - -class F extends I implements EInterface -{ -} - -class G -{ - public function __construct(DInterface $d, EInterface $e, IInterface $i) - { - } -} - -class H -{ - public function __construct(B $b, DInterface $d) - { - } -} - -class D -{ - public function __construct(A $a, DInterface $d) - { - } -} - -class E -{ - public function __construct(D $d = null) - { - } -} - -class J -{ - public function __construct(I $i) - { - } -} - -interface CollisionInterface -{ -} - -class CollisionA implements CollisionInterface -{ -} - -class CollisionB implements CollisionInterface -{ -} - -class CannotBeAutowired -{ - public function __construct(CollisionInterface $collision) - { - } -} - -class CannotBeAutowiredForwardOrder -{ - public function __construct(CollisionA $a, CollisionInterface $b, CollisionB $c) - { - } -} - -class CannotBeAutowiredReverseOrder -{ - public function __construct(CollisionA $a, CollisionB $c, CollisionInterface $b) - { - } -} - -class Lille -{ -} - -class Dunglas -{ - public function __construct(Lille $l) - { - } -} - -class LesTilleuls -{ - public function __construct(Dunglas $j, Dunglas $k) - { - } -} - -class OptionalParameter -{ - public function __construct(CollisionInterface $c = null, A $a, Foo $f = null) - { - } -} - -class BadTypeHintedArgument -{ - public function __construct(Dunglas $k, NotARealClass $r) - { - } -} -class BadParentTypeHintedArgument -{ - public function __construct(Dunglas $k, OptionalServiceClass $r) - { - } -} -class NotGuessableArgument -{ - public function __construct(Foo $k) - { - } -} -class NotGuessableArgumentForSubclass -{ - public function __construct(A $k) - { - } -} -class MultipleArguments -{ - public function __construct(A $k, $foo, Dunglas $dunglas) - { - } -} - -class MultipleArgumentsOptionalScalar -{ - public function __construct(A $a, $foo = 'default_val', Lille $lille = null) - { - } -} -class MultipleArgumentsOptionalScalarLast -{ - public function __construct(A $a, Lille $lille, $foo = 'some_val') - { - } -} -class MultipleArgumentsOptionalScalarNotReallyOptional -{ - public function __construct(A $a, $foo = 'default_val', Lille $lille) - { - } -} - -/* - * Classes used for testing createResourceForClass - */ -class ClassForResource -{ - public function __construct($foo, Bar $bar = null) - { - } - - public function setBar(Bar $bar) - { - } -} -class IdenticalClassResource extends ClassForResource -{ -} - -class ClassChangedConstructorArgs extends ClassForResource -{ - public function __construct($foo, Bar $bar, $baz) - { - } -} - -class SetterInjection extends SetterInjectionParent -{ - /** - * @required - */ - public function setFoo(Foo $foo) - { - // should be called - } - - /** @inheritdoc*/ - public function setDependencies(Foo $foo, A $a) - { - // should be called - } - - /** {@inheritdoc} */ - public function setWithCallsConfigured(A $a) - { - // this method has a calls configured on it - } - - public function notASetter(A $a) - { - // should be called only when explicitly specified - } - - /** - * @required*/ - public function setChildMethodWithoutDocBlock(A $a) - { - } -} - -class SetterInjectionParent -{ - /** @required*/ - public function setDependencies(Foo $foo, A $a) - { - // should be called - } - - public function notASetter(A $a) - { - // @required should be ignored when the child does not add @inheritdoc - } - - /** @required prefix is on purpose */ - public function setWithCallsConfigured(A $a) - { - } - - /** @required */ - public function setChildMethodWithoutDocBlock(A $a) - { - } -} - -class SetterInjectionCollision -{ - /** - * @required - */ - public function setMultipleInstancesForOneArg(CollisionInterface $collision) - { - // The CollisionInterface cannot be autowired - there are multiple - - // should throw an exception - } -} - -class NotWireable -{ - public function setNotAutowireable(NotARealClass $n) - { - } - - public function setBar() - { - } - - public function setOptionalNotAutowireable(NotARealClass $n = null) - { - } - - public function setDifferentNamespace(\stdClass $n) - { - } - - public function setOptionalNoTypeHint($foo = null) - { - } - - public function setOptionalArgNoAutowireable($other = 'default_val') - { - } - - /** @required */ - protected function setProtectedMethod(A $a) - { - } -} - -class PrivateConstructor -{ - private function __construct() - { - } -} diff --git a/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowireRequiredMethodsPassTest.php b/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowireRequiredMethodsPassTest.php new file mode 100644 index 0000000000000..3b067150ff5a1 --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowireRequiredMethodsPassTest.php @@ -0,0 +1,80 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Tests\Compiler; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\DependencyInjection\Compiler\ResolveClassPass; +use Symfony\Component\DependencyInjection\Compiler\AutowireRequiredMethodsPass; +use Symfony\Component\DependencyInjection\ContainerBuilder; + +require_once __DIR__.'/../Fixtures/includes/autowiring_classes.php'; + +class AutowireRequiredMethodsPassTest extends TestCase +{ + public function testSetterInjection() + { + $container = new ContainerBuilder(); + $container->register(Foo::class); + $container->register(A::class); + $container->register(CollisionA::class); + $container->register(CollisionB::class); + + // manually configure *one* call, to override autowiring + $container + ->register('setter_injection', SetterInjection::class) + ->setAutowired(true) + ->addMethodCall('setWithCallsConfigured', array('manual_arg1', 'manual_arg2')); + + (new ResolveClassPass())->process($container); + (new AutowireRequiredMethodsPass())->process($container); + + $methodCalls = $container->getDefinition('setter_injection')->getMethodCalls(); + + $this->assertEquals( + array('setWithCallsConfigured', 'setFoo', 'setDependencies', 'setChildMethodWithoutDocBlock'), + array_column($methodCalls, 0) + ); + + // test setWithCallsConfigured args + $this->assertEquals( + array('manual_arg1', 'manual_arg2'), + $methodCalls[0][1] + ); + // test setFoo args + $this->assertEquals(array(), $methodCalls[1][1]); + } + + public function testExplicitMethodInjection() + { + $container = new ContainerBuilder(); + $container->register(Foo::class); + $container->register(A::class); + $container->register(CollisionA::class); + $container->register(CollisionB::class); + + $container + ->register('setter_injection', SetterInjection::class) + ->setAutowired(true) + ->addMethodCall('notASetter', array()); + + (new ResolveClassPass())->process($container); + (new AutowireRequiredMethodsPass())->process($container); + + $methodCalls = $container->getDefinition('setter_injection')->getMethodCalls(); + + $this->assertEquals( + array('notASetter', 'setFoo', 'setDependencies', 'setWithCallsConfigured', 'setChildMethodWithoutDocBlock'), + array_column($methodCalls, 0) + ); + $this->assertEquals(array(), $methodCalls[0][1]); + } +} diff --git a/src/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveBindingsPassTest.php b/src/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveBindingsPassTest.php index f7e29d2110ff1..16e486afafe2e 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveBindingsPassTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveBindingsPassTest.php @@ -13,6 +13,7 @@ use PHPUnit\Framework\TestCase; use Symfony\Component\DependencyInjection\Argument\BoundArgument; +use Symfony\Component\DependencyInjection\Compiler\AutowireRequiredMethodsPass; use Symfony\Component\DependencyInjection\Compiler\ResolveBindingsPass; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Reference; @@ -20,6 +21,8 @@ use Symfony\Component\DependencyInjection\Tests\Fixtures\CaseSensitiveClass; use Symfony\Component\DependencyInjection\TypedReference; +require_once __DIR__.'/../Fixtures/includes/autowiring_classes.php'; + class ResolveBindingsPassTest extends TestCase { public function testProcess() @@ -79,4 +82,17 @@ public function testTypedReferenceSupport() $this->assertEquals(array($typedRef), $container->getDefinition('def1')->getArguments()); $this->assertEquals(array(new Reference('foo')), $container->getDefinition('def2')->getArguments()); } + + public function testScalarSetter() + { + $container = new ContainerBuilder(); + + $definition = $container->autowire('foo', ScalarSetter::class); + $definition->setBindings(array('$defaultLocale' => 'fr')); + + (new AutowireRequiredMethodsPass())->process($container); + (new ResolveBindingsPass())->process($container); + + $this->assertEquals(array(array('setDefaultLocale', array('fr'))), $definition->getMethodCalls()); + } } diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/includes/autowiring_classes.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/includes/autowiring_classes.php new file mode 100644 index 0000000000000..bf99eff6a2838 --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/includes/autowiring_classes.php @@ -0,0 +1,343 @@ + prefix is on purpose */ + public function setWithCallsConfigured(A $a) + { + } + + /** @required */ + public function setChildMethodWithoutDocBlock(A $a) + { + } +} + +class NotWireable +{ + public function setNotAutowireable(NotARealClass $n) + { + } + + public function setBar() + { + } + + public function setOptionalNotAutowireable(NotARealClass $n = null) + { + } + + public function setDifferentNamespace(\stdClass $n) + { + } + + public function setOptionalNoTypeHint($foo = null) + { + } + + public function setOptionalArgNoAutowireable($other = 'default_val') + { + } + + /** @required */ + protected function setProtectedMethod(A $a) + { + } +} + +class PrivateConstructor +{ + private function __construct() + { + } +} + +class ScalarSetter +{ + /** + * @required + */ + public function setDefaultLocale($defaultLocale) + { + } +} From a85b37a0e68e4a5b23113f41f79d6a88b53a61b8 Mon Sep 17 00:00:00 2001 From: Ryan Weaver Date: Fri, 22 Sep 2017 13:54:05 -0400 Subject: [PATCH 0885/1099] Adding Definition::addError() and a compiler pass to throw errors as exceptions --- .../Compiler/AbstractRecursivePass.php | 3 ++ .../Compiler/AutowireExceptionPass.php | 4 ++ .../Compiler/AutowirePass.php | 7 ++- .../Compiler/CheckArgumentsValidityPass.php | 35 ++++++++++-- .../Compiler/DefinitionErrorExceptionPass.php | 39 ++++++++++++++ .../Compiler/InlineServiceDefinitionsPass.php | 4 ++ .../Compiler/PassConfig.php | 8 +-- .../DependencyInjection/Definition.php | 21 ++++++++ .../Compiler/AutowireExceptionPassTest.php | 3 ++ .../Tests/Compiler/AutowirePassTest.php | 3 ++ .../CheckArgumentsValidityPassTest.php | 11 ++++ .../DefinitionErrorExceptionPassTest.php | 53 +++++++++++++++++++ .../InlineServiceDefinitionsPassTest.php | 3 ++ .../Tests/DefinitionTest.php | 9 ++++ 14 files changed, 194 insertions(+), 9 deletions(-) create mode 100644 src/Symfony/Component/DependencyInjection/Compiler/DefinitionErrorExceptionPass.php create mode 100644 src/Symfony/Component/DependencyInjection/Tests/Compiler/DefinitionErrorExceptionPassTest.php diff --git a/src/Symfony/Component/DependencyInjection/Compiler/AbstractRecursivePass.php b/src/Symfony/Component/DependencyInjection/Compiler/AbstractRecursivePass.php index bbe869b935e5c..0851d33e7e9cf 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/AbstractRecursivePass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/AbstractRecursivePass.php @@ -22,6 +22,9 @@ */ abstract class AbstractRecursivePass implements CompilerPassInterface { + /** + * @var ContainerBuilder + */ protected $container; protected $currentId; diff --git a/src/Symfony/Component/DependencyInjection/Compiler/AutowireExceptionPass.php b/src/Symfony/Component/DependencyInjection/Compiler/AutowireExceptionPass.php index 12be3d915fd10..f01617dd633c6 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/AutowireExceptionPass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/AutowireExceptionPass.php @@ -11,11 +11,15 @@ namespace Symfony\Component\DependencyInjection\Compiler; +@trigger_error('The '.__NAMESPACE__.'\AutowireExceptionPass class is deprecated since version 3.4 and will be removed in 4.0. Use the DefinitionErrorExceptionPass class instead.', E_USER_DEPRECATED); + use Symfony\Component\DependencyInjection\ContainerBuilder; /** * Throws autowire exceptions from AutowirePass for definitions that still exist. * + * @deprecated since version 3.4, will be removed in 4.0. + * * @author Ryan Weaver */ class AutowireExceptionPass implements CompilerPassInterface diff --git a/src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php b/src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php index 8cb1978ef675d..607b70c85fb61 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php @@ -36,7 +36,7 @@ class AutowirePass extends AbstractRecursivePass private $autowiringExceptions = array(); /** - * @param bool $throwOnAutowireException If false, retrieved errors via getAutowiringExceptions + * @param bool $throwOnAutowireException Errors can be retrieved via Definition::getErrors() */ public function __construct($throwOnAutowireException = true) { @@ -44,10 +44,14 @@ public function __construct($throwOnAutowireException = true) } /** + * @deprecated since version 3.4, to be removed in 4.0. + * * @return AutowiringFailedException[] */ public function getAutowiringExceptions() { + @trigger_error('Calling AutowirePass::getAutowiringExceptions() is deprecated since Symfony 3.4 and will be removed in 4.0. Use Definition::getErrors() instead.', E_USER_DEPRECATED); + return $this->autowiringExceptions; } @@ -106,6 +110,7 @@ protected function processValue($value, $isRoot = false) } $this->autowiringExceptions[] = $e; + $this->container->getDefinition($this->currentId)->addError($e->getMessage()); return parent::processValue($value, $isRoot); } diff --git a/src/Symfony/Component/DependencyInjection/Compiler/CheckArgumentsValidityPass.php b/src/Symfony/Component/DependencyInjection/Compiler/CheckArgumentsValidityPass.php index 6b48a156919da..7f032058ab139 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/CheckArgumentsValidityPass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/CheckArgumentsValidityPass.php @@ -22,6 +22,13 @@ */ class CheckArgumentsValidityPass extends AbstractRecursivePass { + private $throwExceptions; + + public function __construct($throwExceptions = true) + { + $this->throwExceptions = $throwExceptions; + } + /** * {@inheritdoc} */ @@ -35,10 +42,20 @@ protected function processValue($value, $isRoot = false) foreach ($value->getArguments() as $k => $v) { if ($k !== $i++) { if (!is_int($k)) { - throw new RuntimeException(sprintf('Invalid constructor argument for service "%s": integer expected but found string "%s". Check your service definition.', $this->currentId, $k)); + $msg = sprintf('Invalid constructor argument for service "%s": integer expected but found string "%s". Check your service definition.', $this->currentId, $k); + $value->addError($msg); + if ($this->throwExceptions) { + throw new RuntimeException($msg); + } + + break; } - throw new RuntimeException(sprintf('Invalid constructor argument %d for service "%s": argument %d must be defined before. Check your service definition.', 1 + $k, $this->currentId, $i)); + $msg = sprintf('Invalid constructor argument %d for service "%s": argument %d must be defined before. Check your service definition.', 1 + $k, $this->currentId, $i); + $value->addError($msg); + if ($this->throwExceptions) { + throw new RuntimeException($msg); + } } } @@ -47,10 +64,20 @@ protected function processValue($value, $isRoot = false) foreach ($methodCall[1] as $k => $v) { if ($k !== $i++) { if (!is_int($k)) { - throw new RuntimeException(sprintf('Invalid argument for method call "%s" of service "%s": integer expected but found string "%s". Check your service definition.', $methodCall[0], $this->currentId, $k)); + $msg = sprintf('Invalid argument for method call "%s" of service "%s": integer expected but found string "%s". Check your service definition.', $methodCall[0], $this->currentId, $k); + $value->addError($msg); + if ($this->throwExceptions) { + throw new RuntimeException($msg); + } + + break; } - throw new RuntimeException(sprintf('Invalid argument %d for method call "%s" of service "%s": argument %d must be defined before. Check your service definition.', 1 + $k, $methodCall[0], $this->currentId, $i)); + $msg = sprintf('Invalid argument %d for method call "%s" of service "%s": argument %d must be defined before. Check your service definition.', 1 + $k, $methodCall[0], $this->currentId, $i); + $value->addError($msg); + if ($this->throwExceptions) { + throw new RuntimeException($msg); + } } } } diff --git a/src/Symfony/Component/DependencyInjection/Compiler/DefinitionErrorExceptionPass.php b/src/Symfony/Component/DependencyInjection/Compiler/DefinitionErrorExceptionPass.php new file mode 100644 index 0000000000000..69cd899f2a5d4 --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Compiler/DefinitionErrorExceptionPass.php @@ -0,0 +1,39 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Compiler; + +use Symfony\Component\DependencyInjection\Definition; +use Symfony\Component\DependencyInjection\Exception\RuntimeException; + +/** + * Throws an exception for any Definitions that have errors and still exist. + * + * @author Ryan Weaver + */ +class DefinitionErrorExceptionPass extends AbstractRecursivePass +{ + /** + * {@inheritdoc} + */ + protected function processValue($value, $isRoot = false) + { + if (!$value instanceof Definition || empty($value->getErrors())) { + return parent::processValue($value, $isRoot); + } + + // only show the first error so they user can focus on it + $errors = $value->getErrors(); + $message = reset($errors); + + throw new RuntimeException($message); + } +} diff --git a/src/Symfony/Component/DependencyInjection/Compiler/InlineServiceDefinitionsPass.php b/src/Symfony/Component/DependencyInjection/Compiler/InlineServiceDefinitionsPass.php index 73f75b30a982c..05e7786798d2c 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/InlineServiceDefinitionsPass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/InlineServiceDefinitionsPass.php @@ -38,10 +38,14 @@ public function setRepeatedPass(RepeatedPass $repeatedPass) * * The key is the inlined service id and its value is the list of services it was inlined into. * + * @deprecated since version 3.4, to be removed in 4.0. + * * @return array */ public function getInlinedServiceIds() { + @trigger_error('Calling InlineServiceDefinitionsPass::getInlinedServiceIds() is deprecated since Symfony 3.4 and will be removed in 4.0.', E_USER_DEPRECATED); + return $this->inlinedServiceIds; } diff --git a/src/Symfony/Component/DependencyInjection/Compiler/PassConfig.php b/src/Symfony/Component/DependencyInjection/Compiler/PassConfig.php index 79792bee4a106..1edc4c21b10f0 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/PassConfig.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/PassConfig.php @@ -59,14 +59,14 @@ public function __construct() new RegisterServiceSubscribersPass(), new ResolveNamedArgumentsPass(), new ResolveBindingsPass(), - $autowirePass = new AutowirePass(false), + new AutowirePass(false), new ResolveServiceSubscribersPass(), new ResolveReferencesToAliasesPass(), new ResolveInvalidReferencesPass(), new AnalyzeServiceReferencesPass(true), new CheckCircularReferencesPass(), new CheckReferenceValidityPass(), - new CheckArgumentsValidityPass(), + new CheckArgumentsValidityPass(false), )); $this->removingPasses = array(array( @@ -75,11 +75,11 @@ public function __construct() new RemoveAbstractDefinitionsPass(), new RepeatedPass(array( new AnalyzeServiceReferencesPass(), - $inlinedServicePass = new InlineServiceDefinitionsPass(), + new InlineServiceDefinitionsPass(), new AnalyzeServiceReferencesPass(), new RemoveUnusedDefinitionsPass(), )), - new AutowireExceptionPass($autowirePass, $inlinedServicePass), + new DefinitionErrorExceptionPass(), new CheckExceptionOnInvalidReferenceBehaviorPass(), )); } diff --git a/src/Symfony/Component/DependencyInjection/Definition.php b/src/Symfony/Component/DependencyInjection/Definition.php index 34d6f46cacca4..464932fc0acae 100644 --- a/src/Symfony/Component/DependencyInjection/Definition.php +++ b/src/Symfony/Component/DependencyInjection/Definition.php @@ -44,6 +44,7 @@ class Definition private $autowiringTypes = array(); private $changes = array(); private $bindings = array(); + private $errors = array(); protected $arguments = array(); @@ -959,4 +960,24 @@ public function setBindings(array $bindings) return $this; } + + /** + * Add an error that occurred when building this Definition. + * + * @param string $error + */ + public function addError($error) + { + $this->errors[] = $error; + } + + /** + * Returns any errors that occurred while building this Definition. + * + * @return array + */ + public function getErrors() + { + return $this->errors; + } } diff --git a/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowireExceptionPassTest.php b/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowireExceptionPassTest.php index 4f0b3d6c2566c..a9c3445cefdd8 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowireExceptionPassTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowireExceptionPassTest.php @@ -18,6 +18,9 @@ use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Exception\AutowiringFailedException; +/** + * @group legacy + */ class AutowireExceptionPassTest extends TestCase { public function testThrowsException() diff --git a/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowirePassTest.php b/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowirePassTest.php index 94666df608391..3a48cfae8d6dc 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowirePassTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowirePassTest.php @@ -157,6 +157,9 @@ public function testCompleteExistingDefinitionWithNotDefinedArguments() $this->assertEquals(DInterface::class, (string) $container->getDefinition('h')->getArgument(1)); } + /** + * @group legacy + */ public function testExceptionsAreStored() { $container = new ContainerBuilder(); diff --git a/src/Symfony/Component/DependencyInjection/Tests/Compiler/CheckArgumentsValidityPassTest.php b/src/Symfony/Component/DependencyInjection/Tests/Compiler/CheckArgumentsValidityPassTest.php index 891acbeee0d89..d121689ff9c6a 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Compiler/CheckArgumentsValidityPassTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Compiler/CheckArgumentsValidityPassTest.php @@ -64,4 +64,15 @@ public function definitionProvider() array(array(), array(array('baz', array(1 => 1)))), ); } + + public function testNoException() + { + $container = new ContainerBuilder(); + $definition = $container->register('foo'); + $definition->setArguments(array(null, 'a' => 'a')); + + $pass = new CheckArgumentsValidityPass(false); + $pass->process($container); + $this->assertCount(1, $definition->getErrors()); + } } diff --git a/src/Symfony/Component/DependencyInjection/Tests/Compiler/DefinitionErrorExceptionPassTest.php b/src/Symfony/Component/DependencyInjection/Tests/Compiler/DefinitionErrorExceptionPassTest.php new file mode 100644 index 0000000000000..e0585e21324b3 --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Tests/Compiler/DefinitionErrorExceptionPassTest.php @@ -0,0 +1,53 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Tests\Compiler; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\DependencyInjection\Compiler\DefinitionErrorExceptionPass; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Definition; + +class DefinitionErrorExceptionPassTest extends TestCase +{ + /** + * @expectedException \Symfony\Component\DependencyInjection\Exception\RuntimeException + * @expectedExceptionMessage Things went wrong! + */ + public function testThrowsException() + { + $container = new ContainerBuilder(); + $def = new Definition(); + $def->addError('Things went wrong!'); + $def->addError('Now something else!'); + $container->register('foo_service_id') + ->setArguments(array( + $def, + )); + + $pass = new DefinitionErrorExceptionPass(); + $pass->process($container); + } + + public function testNoExceptionThrown() + { + $container = new ContainerBuilder(); + $def = new Definition(); + $container->register('foo_service_id') + ->setArguments(array( + $def, + )); + + $pass = new DefinitionErrorExceptionPass(); + $pass->process($container); + $this->assertSame($def, $container->getDefinition('foo_service_id')->getArgument(0)); + } +} diff --git a/src/Symfony/Component/DependencyInjection/Tests/Compiler/InlineServiceDefinitionsPassTest.php b/src/Symfony/Component/DependencyInjection/Tests/Compiler/InlineServiceDefinitionsPassTest.php index 26b24fa713242..6154080c8bc0e 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Compiler/InlineServiceDefinitionsPassTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Compiler/InlineServiceDefinitionsPassTest.php @@ -252,6 +252,9 @@ public function testProcessDoesNotSetLazyArgumentValuesAfterInlining() $this->assertSame('inline', (string) $values[0]); } + /** + * @group legacy + */ public function testGetInlinedServiceIdData() { $container = new ContainerBuilder(); diff --git a/src/Symfony/Component/DependencyInjection/Tests/DefinitionTest.php b/src/Symfony/Component/DependencyInjection/Tests/DefinitionTest.php index 2821dc17c0dc2..5fe4236ad9384 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/DefinitionTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/DefinitionTest.php @@ -387,4 +387,13 @@ public function testShouldAutoconfigure() $def->setAutoconfigured(true); $this->assertTrue($def->isAutoconfigured()); } + + public function testAddError() + { + $def = new Definition('stdClass'); + $this->assertEmpty($def->getErrors()); + $def->addError('First error'); + $def->addError('Second error'); + $this->assertSame(array('First error', 'Second error'), $def->getErrors()); + } } From 709f134dc8f5c62a1f116d922e7ce3ee66c92f39 Mon Sep 17 00:00:00 2001 From: Javier Eguiluz Date: Mon, 25 Sep 2017 17:11:48 +0200 Subject: [PATCH 0886/1099] Removed unneeded wrapping quotes around a Twig key --- .../views/Form/bootstrap_4_horizontal_layout.html.twig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_4_horizontal_layout.html.twig b/src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_4_horizontal_layout.html.twig index 046cf3cdd1703..32b4944bab3d0 100644 --- a/src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_4_horizontal_layout.html.twig +++ b/src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_4_horizontal_layout.html.twig @@ -7,7 +7,7 @@
{%- else -%} {%- if expanded is not defined or not expanded -%} - {%- set label_attr = label_attr|merge({'class': (label_attr.class|default('') ~ ' col-form-label')|trim}) -%} + {%- set label_attr = label_attr|merge({class: (label_attr.class|default('') ~ ' col-form-label')|trim}) -%} {%- endif -%} {%- set label_attr = label_attr|merge({class: (label_attr.class|default('') ~ ' ' ~ block('form_label_class'))|trim}) -%} {{- parent() -}} From f12e5887ff51266519226c8eea9ffb268f1273d0 Mon Sep 17 00:00:00 2001 From: Javier Eguiluz Date: Mon, 25 Sep 2017 17:12:23 +0200 Subject: [PATCH 0887/1099] Removed unneeded wrapping quotes around a Twig key --- .../Twig/Resources/views/Form/bootstrap_4_layout.html.twig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_4_layout.html.twig b/src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_4_layout.html.twig index b3c71a74ea5aa..7dda32ace2fc4 100644 --- a/src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_4_layout.html.twig +++ b/src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_4_layout.html.twig @@ -72,9 +72,9 @@ {% block form_label -%} {%- if expanded is defined and expanded -%} {%- set element = 'legend' -%} - {%- set label_attr = label_attr|merge({'class': (label_attr.class|default('') ~ ' col-form-legend')|trim}) -%} + {%- set label_attr = label_attr|merge({class: (label_attr.class|default('') ~ ' col-form-legend')|trim}) -%} {%- endif -%} - {%- set label_attr = label_attr|merge({'class': (label_attr.class|default('') ~ ' form-control-label')|trim}) -%} + {%- set label_attr = label_attr|merge({class: (label_attr.class|default('') ~ ' form-control-label')|trim}) -%} {{- parent() -}} {%- endblock form_label %} From 9becb8ae34b70208f0f47968309ad6612243bd3d Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Tue, 19 Sep 2017 10:04:34 +0100 Subject: [PATCH 0888/1099] [Yaml] support parsing files --- src/Symfony/Component/Yaml/CHANGELOG.md | 2 + src/Symfony/Component/Yaml/Inline.php | 56 ++++++++-------- src/Symfony/Component/Yaml/Parser.php | 64 ++++++++++++++----- .../Yaml/Tests/Fixtures/not_readable.yml | 18 ++++++ .../Component/Yaml/Tests/InlineTest.php | 23 +++++-- .../Component/Yaml/Tests/ParserTest.php | 41 +++++++++++- src/Symfony/Component/Yaml/Yaml.php | 23 +++++++ 7 files changed, 177 insertions(+), 50 deletions(-) create mode 100644 src/Symfony/Component/Yaml/Tests/Fixtures/not_readable.yml diff --git a/src/Symfony/Component/Yaml/CHANGELOG.md b/src/Symfony/Component/Yaml/CHANGELOG.md index cdd49352d5185..1b07b239cd6e5 100644 --- a/src/Symfony/Component/Yaml/CHANGELOG.md +++ b/src/Symfony/Component/Yaml/CHANGELOG.md @@ -4,6 +4,8 @@ CHANGELOG 3.4.0 ----- + * added support for parsing YAML files using the `Yaml::parseFile()` or `Parser::parseFile()` method + * the `Dumper`, `Parser`, and `Yaml` classes are marked as final * Deprecated the `!php/object:` tag which will be replaced by the diff --git a/src/Symfony/Component/Yaml/Inline.php b/src/Symfony/Component/Yaml/Inline.php index 4410d221c7df7..b1653137fc135 100644 --- a/src/Symfony/Component/Yaml/Inline.php +++ b/src/Symfony/Component/Yaml/Inline.php @@ -26,7 +26,8 @@ class Inline { const REGEX_QUOTED_STRING = '(?:"([^"\\\\]*+(?:\\\\.[^"\\\\]*+)*+)"|\'([^\']*+(?:\'\'[^\']*+)*+)\')'; - public static $parsedLineNumber; + public static $parsedLineNumber = -1; + public static $parsedFilename; private static $exceptionOnInvalidType = false; private static $objectSupport = false; @@ -34,19 +35,18 @@ class Inline private static $constantSupport = false; /** - * @param int $flags - * @param int|null $parsedLineNumber + * @param int $flags + * @param int|null $parsedLineNumber + * @param string|null $parsedFilename */ - public static function initialize($flags, $parsedLineNumber = null) + public static function initialize($flags, $parsedLineNumber = null, $parsedFilename = null) { self::$exceptionOnInvalidType = (bool) (Yaml::PARSE_EXCEPTION_ON_INVALID_TYPE & $flags); self::$objectSupport = (bool) (Yaml::PARSE_OBJECT & $flags); self::$objectForMap = (bool) (Yaml::PARSE_OBJECT_FOR_MAP & $flags); self::$constantSupport = (bool) (Yaml::PARSE_CONSTANT & $flags); - - if (null !== $parsedLineNumber) { - self::$parsedLineNumber = $parsedLineNumber; - } + self::$parsedFilename = $parsedFilename; + self::$parsedLineNumber = null !== $parsedLineNumber ? $parsedLineNumber : -1; } /** @@ -128,7 +128,7 @@ public static function parse($value, $flags = 0, $references = array()) // some comments are allowed at the end if (preg_replace('/\s+#.*$/A', '', substr($value, $i))) { - throw new ParseException(sprintf('Unexpected characters near "%s".', substr($value, $i))); + throw new ParseException(sprintf('Unexpected characters near "%s".', substr($value, $i)), self::$parsedLineNumber, $value, self::$parsedFilename); } if (isset($mbEncoding)) { @@ -322,7 +322,7 @@ public static function parseScalar($scalar, $flags = 0, $delimiters = null, &$i if (null !== $delimiters) { $tmp = ltrim(substr($scalar, $i), ' '); if (!in_array($tmp[0], $delimiters)) { - throw new ParseException(sprintf('Unexpected characters (%s).', substr($scalar, $i))); + throw new ParseException(sprintf('Unexpected characters (%s).', substr($scalar, $i)), self::$parsedLineNumber, $scalar, self::$parsedFilename); } } } else { @@ -339,12 +339,12 @@ public static function parseScalar($scalar, $flags = 0, $delimiters = null, &$i $output = $match[1]; $i += strlen($output); } else { - throw new ParseException(sprintf('Malformed inline YAML string: %s.', $scalar)); + throw new ParseException(sprintf('Malformed inline YAML string: %s.', $scalar), self::$parsedLineNumber, null, self::$parsedFilename); } // a non-quoted string cannot start with @ or ` (reserved) nor with a scalar indicator (| or >) if ($output && ('@' === $output[0] || '`' === $output[0] || '|' === $output[0] || '>' === $output[0])) { - throw new ParseException(sprintf('The reserved indicator "%s" cannot start a plain scalar; you need to quote the scalar.', $output[0])); + throw new ParseException(sprintf('The reserved indicator "%s" cannot start a plain scalar; you need to quote the scalar.', $output[0]), self::$parsedLineNumber, $output, self::$parsedFilename); } if ($output && '%' === $output[0]) { @@ -372,7 +372,7 @@ public static function parseScalar($scalar, $flags = 0, $delimiters = null, &$i private static function parseQuotedScalar($scalar, &$i) { if (!Parser::preg_match('/'.self::REGEX_QUOTED_STRING.'/Au', substr($scalar, $i), $match)) { - throw new ParseException(sprintf('Malformed inline YAML string: %s.', substr($scalar, $i))); + throw new ParseException(sprintf('Malformed inline YAML string: %s.', substr($scalar, $i)), self::$parsedLineNumber, $scalar, self::$parsedFilename); } $output = substr($match[0], 1, strlen($match[0]) - 2); @@ -455,7 +455,7 @@ private static function parseSequence($sequence, $flags, &$i = 0, $references = ++$i; } - throw new ParseException(sprintf('Malformed inline YAML string: %s.', $sequence)); + throw new ParseException(sprintf('Malformed inline YAML string: %s.', $sequence), self::$parsedLineNumber, null, self::$parsedFilename); } /** @@ -572,7 +572,7 @@ private static function parseMapping($mapping, $flags, &$i = 0, $references = ar } } - throw new ParseException(sprintf('Malformed inline YAML string: %s.', $mapping)); + throw new ParseException(sprintf('Malformed inline YAML string: %s.', $mapping), self::$parsedLineNumber, null, self::$parsedFilename); } /** @@ -600,11 +600,11 @@ private static function evaluateScalar($scalar, $flags, $references = array()) // an unquoted * if (false === $value || '' === $value) { - throw new ParseException('A reference must contain at least one character.'); + throw new ParseException('A reference must contain at least one character.', self::$parsedLineNumber, $value, self::$parsedFilename); } if (!array_key_exists($value, $references)) { - throw new ParseException(sprintf('Reference "%s" does not exist.', $value)); + throw new ParseException(sprintf('Reference "%s" does not exist.', $value), self::$parsedLineNumber, $value, self::$parsedFilename); } return $references[$value]; @@ -639,7 +639,7 @@ private static function evaluateScalar($scalar, $flags, $references = array()) } if (self::$exceptionOnInvalidType) { - throw new ParseException('Object support when parsing a YAML file has been disabled.'); + throw new ParseException('Object support when parsing a YAML file has been disabled.', self::$parsedLineNumber, $scalar, self::$parsedFilename); } return; @@ -651,7 +651,7 @@ private static function evaluateScalar($scalar, $flags, $references = array()) } if (self::$exceptionOnInvalidType) { - throw new ParseException('Object support when parsing a YAML file has been disabled.'); + throw new ParseException('Object support when parsing a YAML file has been disabled.', self::$parsedLineNumber, $scalar, self::$parsedFilename); } return; @@ -661,7 +661,7 @@ private static function evaluateScalar($scalar, $flags, $references = array()) } if (self::$exceptionOnInvalidType) { - throw new ParseException('Object support when parsing a YAML file has been disabled.'); + throw new ParseException('Object support when parsing a YAML file has been disabled.', self::$parsedLineNumber, $scalar, self::$parsedFilename); } return; @@ -673,10 +673,10 @@ private static function evaluateScalar($scalar, $flags, $references = array()) return constant($const); } - throw new ParseException(sprintf('The constant "%s" is not defined.', $const)); + throw new ParseException(sprintf('The constant "%s" is not defined.', $const), self::$parsedLineNumber, $scalar, self::$parsedFilename); } if (self::$exceptionOnInvalidType) { - throw new ParseException(sprintf('The string "%s" could not be parsed as a constant. Have you forgotten to pass the "Yaml::PARSE_CONSTANT" flag to the parser?', $scalar)); + throw new ParseException(sprintf('The string "%s" could not be parsed as a constant. Have you forgotten to pass the "Yaml::PARSE_CONSTANT" flag to the parser?', $scalar), self::$parsedLineNumber, $scalar, self::$parsedFilename); } return; @@ -686,10 +686,10 @@ private static function evaluateScalar($scalar, $flags, $references = array()) return constant($const); } - throw new ParseException(sprintf('The constant "%s" is not defined.', $const)); + throw new ParseException(sprintf('The constant "%s" is not defined.', $const), self::$parsedLineNumber, $scalar, self::$parsedFilename); } if (self::$exceptionOnInvalidType) { - throw new ParseException(sprintf('The string "%s" could not be parsed as a constant. Have you forgotten to pass the "Yaml::PARSE_CONSTANT" flag to the parser?', $scalar)); + throw new ParseException(sprintf('The string "%s" could not be parsed as a constant. Have you forgotten to pass the "Yaml::PARSE_CONSTANT" flag to the parser?', $scalar), self::$parsedLineNumber, $scalar, self::$parsedFilename); } return; @@ -781,7 +781,7 @@ private static function parseTag($value, &$i, $flags) // Built-in tags if ($tag && '!' === $tag[0]) { - throw new ParseException(sprintf('The built-in tag "!%s" is not implemented.', $tag)); + throw new ParseException(sprintf('The built-in tag "!%s" is not implemented.', $tag), self::$parsedLineNumber, $value, self::$parsedFilename); } if (Yaml::PARSE_CUSTOM_TAGS & $flags) { @@ -790,7 +790,7 @@ private static function parseTag($value, &$i, $flags) return $tag; } - throw new ParseException(sprintf('Tags support is not enabled. Enable the `Yaml::PARSE_CUSTOM_TAGS` flag to use "!%s".', $tag)); + throw new ParseException(sprintf('Tags support is not enabled. Enable the `Yaml::PARSE_CUSTOM_TAGS` flag to use "!%s".', $tag), self::$parsedLineNumber, $value, self::$parsedFilename); } /** @@ -805,11 +805,11 @@ public static function evaluateBinaryScalar($scalar) $parsedBinaryData = self::parseScalar(preg_replace('/\s/', '', $scalar)); if (0 !== (strlen($parsedBinaryData) % 4)) { - throw new ParseException(sprintf('The normalized base64 encoded data (data without whitespace characters) length must be a multiple of four (%d bytes given).', strlen($parsedBinaryData))); + throw new ParseException(sprintf('The normalized base64 encoded data (data without whitespace characters) length must be a multiple of four (%d bytes given).', strlen($parsedBinaryData)), self::$parsedLineNumber, $scalar, self::$parsedFilename); } if (!Parser::preg_match('#^[A-Z0-9+/]+={0,2}$#i', $parsedBinaryData)) { - throw new ParseException(sprintf('The base64 encoded data (%s) contains invalid characters.', $parsedBinaryData)); + throw new ParseException(sprintf('The base64 encoded data (%s) contains invalid characters.', $parsedBinaryData), self::$parsedLineNumber, $scalar, self::$parsedFilename); } return base64_decode($parsedBinaryData, true); diff --git a/src/Symfony/Component/Yaml/Parser.php b/src/Symfony/Component/Yaml/Parser.php index 49eae8f0cc633..be1c13cddbf98 100644 --- a/src/Symfony/Component/Yaml/Parser.php +++ b/src/Symfony/Component/Yaml/Parser.php @@ -26,6 +26,7 @@ class Parser const TAG_PATTERN = '(?P![\w!.\/:-]+)'; const BLOCK_SCALAR_HEADER_PATTERN = '(?P\||>)(?P\+|\-|\d+|\+\d+|\-\d+|\d+\+|\d+\-)?(?P +#.*)?'; + private $filename; private $offset = 0; private $totalNumberOfLines; private $lines = array(); @@ -50,6 +51,35 @@ public function __construct() } } + /** + * Parses a YAML file into a PHP value. + * + * @param string $filename The path to the YAML file to be parsed + * @param int $flags A bit field of PARSE_* constants to customize the YAML parser behavior + * + * @return mixed The YAML converted to a PHP value + * + * @throws ParseException If the file could not be read or the YAML is not valid + */ + public function parseFile($filename, $flags = 0) + { + if (!is_file($filename)) { + throw new ParseException(sprintf('File "%s" does not exist.', $filename)); + } + + if (!is_readable($filename)) { + throw new ParseException(sprintf('File "%s" cannot be read.', $filename)); + } + + $this->filename = $filename; + + try { + return $this->parse(file_get_contents($filename), $flags); + } finally { + $this->filename = null; + } + } + /** * Parses a YAML string to a PHP value. * @@ -93,7 +123,7 @@ public function parse($value, $flags = 0) } if (false === preg_match('//u', $value)) { - throw new ParseException('The YAML value does not appear to be valid UTF-8.'); + throw new ParseException('The YAML value does not appear to be valid UTF-8.', -1, null, $this->filename); } $this->refs = array(); @@ -168,13 +198,13 @@ private function doParse($value, $flags) // tab? if ("\t" === $this->currentLine[0]) { - throw new ParseException('A YAML file cannot contain tabs as indentation.', $this->getRealCurrentLineNb() + 1, $this->currentLine); + throw new ParseException('A YAML file cannot contain tabs as indentation.', $this->getRealCurrentLineNb() + 1, $this->currentLine, $this->filename); } $isRef = $mergeNode = false; if (self::preg_match('#^\-((?P\s+)(?P.+))?$#u', rtrim($this->currentLine), $values)) { if ($context && 'mapping' == $context) { - throw new ParseException('You cannot define a sequence item when in a mapping', $this->getRealCurrentLineNb() + 1, $this->currentLine); + throw new ParseException('You cannot define a sequence item when in a mapping', $this->getRealCurrentLineNb() + 1, $this->currentLine, $this->filename); } $context = 'sequence'; @@ -218,11 +248,11 @@ private function doParse($value, $flags) && (false === strpos($values['key'], ' #') || in_array($values['key'][0], array('"', "'"))) ) { if ($context && 'sequence' == $context) { - throw new ParseException('You cannot define a mapping item when in a sequence', $this->currentLineNb + 1, $this->currentLine); + throw new ParseException('You cannot define a mapping item when in a sequence', $this->currentLineNb + 1, $this->currentLine, $this->filename); } $context = 'mapping'; - Inline::initialize($flags, $this->getRealCurrentLineNb()); + Inline::initialize($flags, $this->getRealCurrentLineNb(), $this->filename); try { $i = 0; $evaluateKey = !(Yaml::PARSE_KEYS_AS_STRINGS & $flags); @@ -256,13 +286,13 @@ private function doParse($value, $flags) if (isset($values['value']) && 0 === strpos($values['value'], '*')) { $refName = substr(rtrim($values['value']), 1); if (!array_key_exists($refName, $this->refs)) { - throw new ParseException(sprintf('Reference "%s" does not exist.', $refName), $this->getRealCurrentLineNb() + 1, $this->currentLine); + throw new ParseException(sprintf('Reference "%s" does not exist.', $refName), $this->getRealCurrentLineNb() + 1, $this->currentLine, $this->filename); } $refValue = $this->refs[$refName]; if (!is_array($refValue)) { - throw new ParseException('YAML merge keys used with a scalar value instead of an array.', $this->getRealCurrentLineNb() + 1, $this->currentLine); + throw new ParseException('YAML merge keys used with a scalar value instead of an array.', $this->getRealCurrentLineNb() + 1, $this->currentLine, $this->filename); } $data += $refValue; // array union @@ -275,7 +305,7 @@ private function doParse($value, $flags) $parsed = $this->parseBlock($this->getRealCurrentLineNb() + 1, $value, $flags); if (!is_array($parsed)) { - throw new ParseException('YAML merge keys used with a scalar value instead of an array.', $this->getRealCurrentLineNb() + 1, $this->currentLine); + throw new ParseException('YAML merge keys used with a scalar value instead of an array.', $this->getRealCurrentLineNb() + 1, $this->currentLine, $this->filename); } if (isset($parsed[0])) { @@ -284,7 +314,7 @@ private function doParse($value, $flags) // in the sequence override keys specified in later mapping nodes. foreach ($parsed as $parsedItem) { if (!is_array($parsedItem)) { - throw new ParseException('Merge items must be arrays.', $this->getRealCurrentLineNb() + 1, $parsedItem); + throw new ParseException('Merge items must be arrays.', $this->getRealCurrentLineNb() + 1, $parsedItem, $this->filename); } $data += $parsedItem; // array union @@ -350,7 +380,7 @@ private function doParse($value, $flags) } else { // multiple documents are not supported if ('---' === $this->currentLine) { - throw new ParseException('Multiple documents are not supported.', $this->currentLineNb + 1, $this->currentLine); + throw new ParseException('Multiple documents are not supported.', $this->currentLineNb + 1, $this->currentLine, $this->filename); } if (isset($this->currentLine[1]) && '?' === $this->currentLine[0] && ' ' === $this->currentLine[1]) { @@ -412,7 +442,7 @@ private function doParse($value, $flags) } } - throw new ParseException('Unable to parse.', $this->getRealCurrentLineNb() + 1, $this->currentLine); + throw new ParseException('Unable to parse.', $this->getRealCurrentLineNb() + 1, $this->currentLine, $this->filename); } } while ($this->moveToNextLine()); @@ -515,7 +545,7 @@ private function getNextEmbedBlock($indentation = null, $inSequence = false) $unindentedEmbedBlock = $this->isStringUnIndentedCollectionItem(); if (!$this->isCurrentLineEmpty() && 0 === $newIndent && !$unindentedEmbedBlock) { - throw new ParseException('Indentation problem.', $this->getRealCurrentLineNb() + 1, $this->currentLine); + throw new ParseException('Indentation problem.', $this->getRealCurrentLineNb() + 1, $this->currentLine, $this->filename); } } else { $newIndent = $indentation; @@ -594,7 +624,7 @@ private function getNextEmbedBlock($indentation = null, $inSequence = false) break; } else { - throw new ParseException('Indentation problem.', $this->getRealCurrentLineNb() + 1, $this->currentLine); + throw new ParseException('Indentation problem.', $this->getRealCurrentLineNb() + 1, $this->currentLine, $this->filename); } } @@ -654,7 +684,7 @@ private function parseValue($value, $flags, $context) } if (!array_key_exists($value, $this->refs)) { - throw new ParseException(sprintf('Reference "%s" does not exist.', $value), $this->currentLineNb + 1, $this->currentLine); + throw new ParseException(sprintf('Reference "%s" does not exist.', $value), $this->currentLineNb + 1, $this->currentLine, $this->filename); } return $this->refs[$value]; @@ -704,7 +734,7 @@ private function parseValue($value, $flags, $context) $parsedValue = Inline::parse($value, $flags, $this->refs); if ('mapping' === $context && is_string($parsedValue) && '"' !== $value[0] && "'" !== $value[0] && '[' !== $value[0] && '{' !== $value[0] && '!' !== $value[0] && false !== strpos($parsedValue, ': ')) { - throw new ParseException('A colon cannot be used in an unquoted mapping value.'); + throw new ParseException('A colon cannot be used in an unquoted mapping value.', $this->getRealCurrentLineNb() + 1, $value, $this->filename); } return $parsedValue; @@ -1044,13 +1074,13 @@ private function getLineTag($value, $flags, $nextLineCheck = true) // Built-in tags if ($tag && '!' === $tag[0]) { - throw new ParseException(sprintf('The built-in tag "!%s" is not implemented.', $tag)); + throw new ParseException(sprintf('The built-in tag "!%s" is not implemented.', $tag), $this->getRealCurrentLineNb() + 1, $value, $this->filename); } if (Yaml::PARSE_CUSTOM_TAGS & $flags) { return $tag; } - throw new ParseException(sprintf('Tags support is not enabled. You must use the flag `Yaml::PARSE_CUSTOM_TAGS` to use "%s".', $matches['tag'])); + throw new ParseException(sprintf('Tags support is not enabled. You must use the flag `Yaml::PARSE_CUSTOM_TAGS` to use "%s".', $matches['tag']), $this->getRealCurrentLineNb() + 1, $value, $this->filename); } } diff --git a/src/Symfony/Component/Yaml/Tests/Fixtures/not_readable.yml b/src/Symfony/Component/Yaml/Tests/Fixtures/not_readable.yml new file mode 100644 index 0000000000000..3216a89ebbc39 --- /dev/null +++ b/src/Symfony/Component/Yaml/Tests/Fixtures/not_readable.yml @@ -0,0 +1,18 @@ +- escapedCharacters +- sfComments +- sfCompact +- sfTests +- sfObjects +- sfMergeKey +- sfQuotes +- YtsAnchorAlias +- YtsBasicTests +- YtsBlockMapping +- YtsDocumentSeparator +- YtsErrorTests +- YtsFlowCollections +- YtsFoldedScalars +- YtsNullsAndEmpties +- YtsSpecificationExamples +- YtsTypeTransfers +- unindentedCollections diff --git a/src/Symfony/Component/Yaml/Tests/InlineTest.php b/src/Symfony/Component/Yaml/Tests/InlineTest.php index 2933ee67ceea9..5fdf2957fb7ac 100644 --- a/src/Symfony/Component/Yaml/Tests/InlineTest.php +++ b/src/Symfony/Component/Yaml/Tests/InlineTest.php @@ -18,6 +18,11 @@ class InlineTest extends TestCase { + protected function setUp() + { + Inline::initialize(0); + } + /** * @dataProvider getTestsForParse */ @@ -283,11 +288,16 @@ public function testParseUnquotedAsteriskFollowedByAComment() /** * @dataProvider getReservedIndicators - * @expectedException \Symfony\Component\Yaml\Exception\ParseException - * @expectedExceptionMessage cannot start a plain scalar; you need to quote the scalar. */ public function testParseUnquotedScalarStartingWithReservedIndicator($indicator) { + if (method_exists($this, 'expectExceptionMessage')) { + $this->expectException(ParseException::class); + $this->expectExceptionMessage(sprintf('cannot start a plain scalar; you need to quote the scalar (near "%sfoo ").', $indicator)); + } else { + $this->setExpectedException(ParseException::class, sprintf('cannot start a plain scalar; you need to quote the scalar (near "%sfoo ").', $indicator)); + } + Inline::parse(sprintf('{ foo: %sfoo }', $indicator)); } @@ -298,11 +308,16 @@ public function getReservedIndicators() /** * @dataProvider getScalarIndicators - * @expectedException \Symfony\Component\Yaml\Exception\ParseException - * @expectedExceptionMessage cannot start a plain scalar; you need to quote the scalar. */ public function testParseUnquotedScalarStartingWithScalarIndicator($indicator) { + if (method_exists($this, 'expectExceptionMessage')) { + $this->expectException(ParseException::class); + $this->expectExceptionMessage(sprintf('cannot start a plain scalar; you need to quote the scalar (near "%sfoo ").', $indicator)); + } else { + $this->setExpectedException(ParseException::class, sprintf('cannot start a plain scalar; you need to quote the scalar (near "%sfoo ").', $indicator)); + } + Inline::parse(sprintf('{ foo: %sfoo }', $indicator)); } diff --git a/src/Symfony/Component/Yaml/Tests/ParserTest.php b/src/Symfony/Component/Yaml/Tests/ParserTest.php index 59e7b4986a302..553b762384c29 100644 --- a/src/Symfony/Component/Yaml/Tests/ParserTest.php +++ b/src/Symfony/Component/Yaml/Tests/ParserTest.php @@ -30,6 +30,8 @@ protected function setUp() protected function tearDown() { $this->parser = null; + + chmod(__DIR__.'/Fixtures/not_readable.yml', 0644); } /** @@ -1696,7 +1698,7 @@ public function testUnsupportedTagWithScalar() /** * @expectedException \Symfony\Component\Yaml\Exception\ParseException - * @expectedExceptionMessage The built-in tag "!!foo" is not implemented. + * @expectedExceptionMessage The built-in tag "!!foo" is not implemented at line 1 (near "!!foo"). */ public function testExceptionWhenUsingUnsuportedBuiltInTags() { @@ -1903,6 +1905,43 @@ public function testPhpConstantTagMappingKeyWithKeysCastToStrings() $this->assertSame($expected, $this->parser->parse($yaml, Yaml::PARSE_CONSTANT | Yaml::PARSE_KEYS_AS_STRINGS)); } + + public function testFilenamesAreParsedAsStringsWithoutFlag() + { + $file = __DIR__.'/Fixtures/index.yml'; + + $this->assertSame($file, $this->parser->parse($file)); + } + + public function testParseFile() + { + $this->assertInternalType('array', $this->parser->parseFile(__DIR__.'/Fixtures/index.yml')); + } + + /** + * @expectedException \Symfony\Component\Yaml\Exception\ParseException + * @expectedExceptionMessageRegExp #^File ".+/Fixtures/nonexistent.yml" does not exist\.$# + */ + public function testParsingNonExistentFilesThrowsException() + { + $this->parser->parseFile(__DIR__.'/Fixtures/nonexistent.yml'); + } + + /** + * @expectedException \Symfony\Component\Yaml\Exception\ParseException + * @expectedExceptionMessageRegExp #^File ".+/Fixtures/not_readable.yml" cannot be read\.$# + */ + public function testParsingNotReadableFilesThrowsException() + { + if ('\\' === DIRECTORY_SEPARATOR) { + $this->markTestSkipped('chmod is not supported on Windows'); + } + + $file = __DIR__.'/Fixtures/not_readable.yml'; + chmod($file, 0200); + + $this->parser->parseFile($file); + } } class B diff --git a/src/Symfony/Component/Yaml/Yaml.php b/src/Symfony/Component/Yaml/Yaml.php index 52a064f70b5fb..24e3e95cba32d 100644 --- a/src/Symfony/Component/Yaml/Yaml.php +++ b/src/Symfony/Component/Yaml/Yaml.php @@ -39,6 +39,29 @@ class Yaml */ const PARSE_KEYS_AS_STRINGS = 2048; + /** + * Parses a YAML file into a PHP value. + * + * Usage: + * + * $array = Yaml::parseFile('config.yml'); + * print_r($array); + * + * + * @param string $filename The path to the YAML file to be parsed + * @param int $flags A bit field of PARSE_* constants to customize the YAML parser behavior + * + * @return mixed The YAML converted to a PHP value + * + * @throws ParseException If the file could not be read or the YAML is not valid + */ + public static function parseFile($filename, $flags = 0) + { + $yaml = new Parser(); + + return $yaml->parseFile($filename, $flags); + } + /** * Parses YAML into a PHP value. * From 8bf465f48d3560f97b0a27b37222e812f6a3fd09 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Mon, 25 Sep 2017 21:59:34 +0200 Subject: [PATCH 0889/1099] use the parseFile() method of the YAML parser --- .../Component/DependencyInjection/Loader/YamlFileLoader.php | 2 +- src/Symfony/Component/Routing/Loader/YamlFileLoader.php | 2 +- src/Symfony/Component/Routing/composer.json | 4 ++-- .../Component/Serializer/Mapping/Loader/YamlFileLoader.php | 2 +- src/Symfony/Component/Translation/Loader/YamlFileLoader.php | 2 +- src/Symfony/Component/Translation/composer.json | 4 ++-- .../Component/Validator/Mapping/Loader/YamlFileLoader.php | 2 +- 7 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php b/src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php index be0c75b2cac73..d9fd24c3d71a6 100644 --- a/src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php +++ b/src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php @@ -654,7 +654,7 @@ protected function loadFile($file) } try { - $configuration = $this->yamlParser->parse(file_get_contents($file), Yaml::PARSE_CONSTANT | Yaml::PARSE_CUSTOM_TAGS); + $configuration = $this->yamlParser->parseFile($file, Yaml::PARSE_CONSTANT | Yaml::PARSE_CUSTOM_TAGS); } catch (ParseException $e) { throw new InvalidArgumentException(sprintf('The file "%s" does not contain valid YAML.', $file), 0, $e); } diff --git a/src/Symfony/Component/Routing/Loader/YamlFileLoader.php b/src/Symfony/Component/Routing/Loader/YamlFileLoader.php index 5a087513215a6..f3072c927b73e 100644 --- a/src/Symfony/Component/Routing/Loader/YamlFileLoader.php +++ b/src/Symfony/Component/Routing/Loader/YamlFileLoader.php @@ -58,7 +58,7 @@ public function load($file, $type = null) } try { - $parsedConfig = $this->yamlParser->parse(file_get_contents($path)); + $parsedConfig = $this->yamlParser->parseFile($path); } catch (ParseException $e) { throw new \InvalidArgumentException(sprintf('The file "%s" does not contain valid YAML.', $path), 0, $e); } diff --git a/src/Symfony/Component/Routing/composer.json b/src/Symfony/Component/Routing/composer.json index 1226ffde886d7..2ad746ec53c24 100644 --- a/src/Symfony/Component/Routing/composer.json +++ b/src/Symfony/Component/Routing/composer.json @@ -21,7 +21,7 @@ "require-dev": { "symfony/config": "~2.8|~3.0|~4.0", "symfony/http-foundation": "~2.8|~3.0|~4.0", - "symfony/yaml": "~3.3|~4.0", + "symfony/yaml": "~3.4|~4.0", "symfony/expression-language": "~2.8|~3.0|~4.0", "symfony/dependency-injection": "~3.3|~4.0", "doctrine/annotations": "~1.0", @@ -31,7 +31,7 @@ "conflict": { "symfony/config": "<2.8", "symfony/dependency-injection": "<3.3", - "symfony/yaml": "<3.3" + "symfony/yaml": "<3.4" }, "suggest": { "symfony/http-foundation": "For using a Symfony Request object", diff --git a/src/Symfony/Component/Serializer/Mapping/Loader/YamlFileLoader.php b/src/Symfony/Component/Serializer/Mapping/Loader/YamlFileLoader.php index e3afa4763271e..970241d34767f 100644 --- a/src/Symfony/Component/Serializer/Mapping/Loader/YamlFileLoader.php +++ b/src/Symfony/Component/Serializer/Mapping/Loader/YamlFileLoader.php @@ -113,7 +113,7 @@ private function getClassesFromYaml() $this->yamlParser = new Parser(); } - $classes = $this->yamlParser->parse(file_get_contents($this->file)); + $classes = $this->yamlParser->parseFile($this->file); if (empty($classes)) { return array(); diff --git a/src/Symfony/Component/Translation/Loader/YamlFileLoader.php b/src/Symfony/Component/Translation/Loader/YamlFileLoader.php index 41e390d0e967d..874fa3a8943e8 100644 --- a/src/Symfony/Component/Translation/Loader/YamlFileLoader.php +++ b/src/Symfony/Component/Translation/Loader/YamlFileLoader.php @@ -39,7 +39,7 @@ protected function loadResource($resource) } try { - $messages = $this->yamlParser->parse(file_get_contents($resource)); + $messages = $this->yamlParser->parseFile($resource); } catch (ParseException $e) { throw new InvalidResourceException(sprintf('Error parsing YAML, invalid file "%s"', $resource), 0, $e); } diff --git a/src/Symfony/Component/Translation/composer.json b/src/Symfony/Component/Translation/composer.json index 48873b98268c4..3a1e1589f5460 100644 --- a/src/Symfony/Component/Translation/composer.json +++ b/src/Symfony/Component/Translation/composer.json @@ -23,14 +23,14 @@ "symfony/config": "~2.8|~3.0|~4.0", "symfony/dependency-injection": "~3.4|~4.0", "symfony/intl": "^2.8.18|^3.2.5|~4.0", - "symfony/yaml": "~3.3|~4.0", + "symfony/yaml": "~3.4|~4.0", "symfony/finder": "~2.8|~3.0|~4.0", "psr/log": "~1.0" }, "conflict": { "symfony/config": "<2.8", "symfony/dependency-injection": "<3.4", - "symfony/yaml": "<3.3" + "symfony/yaml": "<3.4" }, "suggest": { "symfony/config": "", diff --git a/src/Symfony/Component/Validator/Mapping/Loader/YamlFileLoader.php b/src/Symfony/Component/Validator/Mapping/Loader/YamlFileLoader.php index ff6c65d05e763..e5e84c38c35dd 100644 --- a/src/Symfony/Component/Validator/Mapping/Loader/YamlFileLoader.php +++ b/src/Symfony/Component/Validator/Mapping/Loader/YamlFileLoader.php @@ -116,7 +116,7 @@ protected function parseNodes(array $nodes) private function parseFile($path) { try { - $classes = $this->yamlParser->parse(file_get_contents($path), Yaml::PARSE_CONSTANT); + $classes = $this->yamlParser->parseFile($path, Yaml::PARSE_CONSTANT); } catch (ParseException $e) { throw new \InvalidArgumentException(sprintf('The file "%s" does not contain valid YAML.', $path), 0, $e); } From af9e2534df64b202ecceffa6d62db2bbab154d2c Mon Sep 17 00:00:00 2001 From: Maxime Steinhausser Date: Tue, 26 Sep 2017 08:23:35 +0200 Subject: [PATCH 0890/1099] Fix merge --- .../Compiler/MergeExtensionConfigurationPass.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/DependencyInjection/Compiler/MergeExtensionConfigurationPass.php b/src/Symfony/Component/DependencyInjection/Compiler/MergeExtensionConfigurationPass.php index af3a6baf0b898..c801f473cf25c 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/MergeExtensionConfigurationPass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/MergeExtensionConfigurationPass.php @@ -144,7 +144,7 @@ public function __construct(ExtensionInterface $extension, ParameterBagInterface /** * {@inheritdoc} */ - public function addCompilerPass(CompilerPassInterface $pass, $type = PassConfig::TYPE_BEFORE_OPTIMIZATION/*, int $priority = 0*/) + public function addCompilerPass(CompilerPassInterface $pass, $type = PassConfig::TYPE_BEFORE_OPTIMIZATION, int $priority = 0) { throw new LogicException(sprintf('You cannot add compiler pass "%s" from extension "%s". Compiler passes must be registered before the container is compiled.', get_class($pass), $this->extensionClass)); } @@ -160,7 +160,7 @@ public function registerExtension(ExtensionInterface $extension) /** * {@inheritdoc} */ - public function compile($resolveEnvPlaceholders = false) + public function compile(bool $resolveEnvPlaceholders = false) { throw new LogicException(sprintf('Cannot compile the container in extension "%s".', $this->extensionClass)); } From 7a475595e2dd64790b3f1caf56f5b57cefcef27f Mon Sep 17 00:00:00 2001 From: Qingshan Luo Date: Tue, 26 Sep 2017 10:03:27 +0800 Subject: [PATCH 0891/1099] Use PHP_MAXPATHLEN in Filesystem. --- src/Symfony/Component/Filesystem/Filesystem.php | 12 ++++++++---- .../Component/Filesystem/Tests/FilesystemTest.php | 7 ++----- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/src/Symfony/Component/Filesystem/Filesystem.php b/src/Symfony/Component/Filesystem/Filesystem.php index 223e116090d6f..1c10366cee414 100644 --- a/src/Symfony/Component/Filesystem/Filesystem.php +++ b/src/Symfony/Component/Filesystem/Filesystem.php @@ -117,9 +117,11 @@ public function mkdir($dirs, $mode = 0777) */ public function exists($files) { + $maxPathLength = PHP_MAXPATHLEN - 2; + foreach ($this->toIterator($files) as $file) { - if ('\\' === DIRECTORY_SEPARATOR && strlen($file) > 258) { - throw new IOException('Could not check if file exist because path length exceeds 258 characters.', 0, null, $file); + if (strlen($file) > $maxPathLength) { + throw new IOException(sprintf('Could not check if file exist because path length exceeds %d characters.', $maxPathLength), 0, null, $file); } if (!file_exists($file)) { @@ -301,8 +303,10 @@ public function rename($origin, $target, $overwrite = false) */ private function isReadable($filename) { - if ('\\' === DIRECTORY_SEPARATOR && strlen($filename) > 258) { - throw new IOException('Could not check if file is readable because path length exceeds 258 characters.', 0, null, $filename); + $maxPathLength = PHP_MAXPATHLEN - 2; + + if (strlen($filename) > $maxPathLength) { + throw new IOException(sprintf('Could not check if file is readable because path length exceeds %d characters.', $maxPathLength), 0, null, $filename); } return is_readable($filename); diff --git a/src/Symfony/Component/Filesystem/Tests/FilesystemTest.php b/src/Symfony/Component/Filesystem/Tests/FilesystemTest.php index 1228b2d8e2afc..fb6c135f925b3 100644 --- a/src/Symfony/Component/Filesystem/Tests/FilesystemTest.php +++ b/src/Symfony/Component/Filesystem/Tests/FilesystemTest.php @@ -374,16 +374,13 @@ public function testFilesExists() */ public function testFilesExistsFails() { - if ('\\' !== DIRECTORY_SEPARATOR) { - $this->markTestSkipped('Test covers edge case on Windows only.'); - } - $basePath = $this->workspace.'\\directory\\'; + $maxPathLength = PHP_MAXPATHLEN - 2; $oldPath = getcwd(); mkdir($basePath); chdir($basePath); - $file = str_repeat('T', 259 - strlen($basePath)); + $file = str_repeat('T', $maxPathLength - strlen($basePath) + 1); $path = $basePath.$file; exec('TYPE NUL >>'.$file); // equivalent of touch, we can not use the php touch() here because it suffers from the same limitation $this->longPathNamesWindows[] = $path; // save this so we can clean up later From 484e3fd3f240fc80a0d7f4963c7ea11247bce37a Mon Sep 17 00:00:00 2001 From: Kamil Kokot Date: Tue, 26 Sep 2017 11:35:56 +0200 Subject: [PATCH 0892/1099] Use correct verb form in the pull request template When "forget" is used with a gerund, it refers to an action that has already happened. --- .github/PULL_REQUEST_TEMPLATE.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 1bad363eca810..04567c68e04e8 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -2,9 +2,9 @@ | ------------- | --- | Branch? | 3.4 or master / 2.7, 2.8 or 3.3 | Bug fix? | yes/no -| New feature? | yes/no +| New feature? | yes/no | BC breaks? | yes/no -| Deprecations? | yes/no +| Deprecations? | yes/no | Tests pass? | yes/no | Fixed tickets | #... | License | MIT From 091f943900059df01bafef2c5579b244ca1c9075 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Sun, 24 Sep 2017 19:51:14 +0200 Subject: [PATCH 0893/1099] [DI] Fix tracking of bound arguments when using autoconfiguration --- .../Compiler/ResolveInstanceofConditionalsPass.php | 3 +++ .../Loader/Configurator/Traits/ParentTrait.php | 2 ++ .../RegisterControllerArgumentLocatorsPass.php | 10 ++++------ 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/src/Symfony/Component/DependencyInjection/Compiler/ResolveInstanceofConditionalsPass.php b/src/Symfony/Component/DependencyInjection/Compiler/ResolveInstanceofConditionalsPass.php index 32d7ad2911408..f6603b1499c9f 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/ResolveInstanceofConditionalsPass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/ResolveInstanceofConditionalsPass.php @@ -90,9 +90,11 @@ private function processDefinition(ContainerBuilder $container, $id, Definition } if ($parent) { + $bindings = $definition->getBindings(); $abstract = $container->setDefinition('abstract.instanceof.'.$id, $definition); // cast Definition to ChildDefinition + $definition->setBindings(array()); $definition = serialize($definition); $definition = substr_replace($definition, '53', 2, 2); $definition = substr_replace($definition, 'Child', 44, 0); @@ -117,6 +119,7 @@ private function processDefinition(ContainerBuilder $container, $id, Definition // reset fields with "merge" behavior $abstract + ->setBindings($bindings) ->setArguments(array()) ->setMethodCalls(array()) ->setTags(array()) diff --git a/src/Symfony/Component/DependencyInjection/Loader/Configurator/Traits/ParentTrait.php b/src/Symfony/Component/DependencyInjection/Loader/Configurator/Traits/ParentTrait.php index 651f94e617129..43f1223e324a6 100644 --- a/src/Symfony/Component/DependencyInjection/Loader/Configurator/Traits/ParentTrait.php +++ b/src/Symfony/Component/DependencyInjection/Loader/Configurator/Traits/ParentTrait.php @@ -38,6 +38,8 @@ final protected function setParent($parent) $this->definition->setParent($parent); } elseif ($this->definition->isAutoconfigured()) { throw new InvalidArgumentException(sprintf('The service "%s" cannot have a "parent" and also have "autoconfigure". Try disabling autoconfiguration for the service.', $this->id)); + } elseif ($this->definition->getBindings()) { + throw new InvalidArgumentException(sprintf('The service "%s" cannot have a "parent" and also "bind" arguments.', $this->id)); } else { // cast Definition to ChildDefinition $definition = serialize($this->definition); diff --git a/src/Symfony/Component/HttpKernel/DependencyInjection/RegisterControllerArgumentLocatorsPass.php b/src/Symfony/Component/HttpKernel/DependencyInjection/RegisterControllerArgumentLocatorsPass.php index 6c15b427ecc42..6a9f0586f7b77 100644 --- a/src/Symfony/Component/HttpKernel/DependencyInjection/RegisterControllerArgumentLocatorsPass.php +++ b/src/Symfony/Component/HttpKernel/DependencyInjection/RegisterControllerArgumentLocatorsPass.php @@ -14,7 +14,6 @@ use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\DependencyInjection\ChildDefinition; use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; -use Symfony\Component\DependencyInjection\Compiler\ResolveBindingsPass; use Symfony\Component\DependencyInjection\Compiler\ServiceLocatorTagPass; use Symfony\Component\DependencyInjection\ContainerAwareInterface; use Symfony\Component\DependencyInjection\ContainerBuilder; @@ -54,11 +53,13 @@ public function process(ContainerBuilder $container) $def->setPublic(true); $class = $def->getClass(); $autowire = $def->isAutowired(); + $bindings = $def->getBindings(); // resolve service class, taking parent definitions into account - while (!$class && $def instanceof ChildDefinition) { + while ($def instanceof ChildDefinition) { $def = $container->findDefinition($def->getParent()); - $class = $def->getClass(); + $class = $class ?: $def->getClass(); + $bindings = $def->getBindings(); } $class = $parameterBag->resolveValue($class); @@ -111,9 +112,6 @@ public function process(ContainerBuilder $container) } } - // not validated, they are later in ResolveBindingsPass - $bindings = $def->getBindings(); - foreach ($methods as list($r, $parameters)) { /** @var \ReflectionMethod $r */ From 6522c05876939234117c5fcdc93afb7b3d0708bc Mon Sep 17 00:00:00 2001 From: Iltar van der Berg Date: Tue, 26 Sep 2017 12:02:43 +0200 Subject: [PATCH 0894/1099] Removed unused private property --- .../Component/Security/Http/Firewall/ContextListener.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/Symfony/Component/Security/Http/Firewall/ContextListener.php b/src/Symfony/Component/Security/Http/Firewall/ContextListener.php index 43af1105bf76e..6a9ba672b21e1 100644 --- a/src/Symfony/Component/Security/Http/Firewall/ContextListener.php +++ b/src/Symfony/Component/Security/Http/Firewall/ContextListener.php @@ -33,7 +33,6 @@ class ContextListener implements ListenerInterface { private $tokenStorage; - private $contextKey; private $sessionKey; private $logger; private $userProviders; @@ -54,7 +53,6 @@ public function __construct(TokenStorageInterface $tokenStorage, array $userProv $this->tokenStorage = $tokenStorage; $this->userProviders = $userProviders; - $this->contextKey = $contextKey; $this->sessionKey = '_security_'.$contextKey; $this->logger = $logger; $this->dispatcher = $dispatcher; From eb520e1e5bd31c08be73ac0a4c6b9a9382f29768 Mon Sep 17 00:00:00 2001 From: Javier Eguiluz Date: Tue, 26 Sep 2017 12:10:40 +0200 Subject: [PATCH 0895/1099] Minor reword --- src/Symfony/Bundle/TwigBundle/Resources/views/base_js.html.twig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Bundle/TwigBundle/Resources/views/base_js.html.twig b/src/Symfony/Bundle/TwigBundle/Resources/views/base_js.html.twig index e2cd23e948fcf..cb85328d9ad67 100644 --- a/src/Symfony/Bundle/TwigBundle/Resources/views/base_js.html.twig +++ b/src/Symfony/Bundle/TwigBundle/Resources/views/base_js.html.twig @@ -1,4 +1,4 @@ -{# This file is diverged from WebProfilerBundle/Resources/views/Profiler/base_js.html.twig. +{# This file is based on WebProfilerBundle/Resources/views/Profiler/base_js.html.twig. If you make any change in this file, verify the same change is needed in the other file. #} /* Date: Tue, 19 Sep 2017 10:03:04 +0200 Subject: [PATCH 0896/1099] Set a NullLogger in ApcuAdapter when Apcu is disabled in CLI Same check as in https://github.com/symfony/symfony/pull/23390/files#diff-a5185cd58702e8e073786794a423cb27R112 --- src/Symfony/Component/Cache/Adapter/AbstractAdapter.php | 2 +- src/Symfony/Component/PropertyAccess/PropertyAccessor.php | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/Cache/Adapter/AbstractAdapter.php b/src/Symfony/Component/Cache/Adapter/AbstractAdapter.php index 6b38991b77e1e..6bfedd3bc39cf 100644 --- a/src/Symfony/Component/Cache/Adapter/AbstractAdapter.php +++ b/src/Symfony/Component/Cache/Adapter/AbstractAdapter.php @@ -116,7 +116,7 @@ public static function createSystemCache($namespace, $defaultLifetime, $version, } $apcu = new ApcuAdapter($namespace, (int) $defaultLifetime / 5, $version); - if ('cli' === PHP_SAPI && !ini_get('apc.enable_cli')) { + if ('cli' === \PHP_SAPI && !ini_get('apc.enable_cli')) { $apcu->setLogger(new NullLogger()); } elseif (null !== $logger) { $apcu->setLogger($logger); diff --git a/src/Symfony/Component/PropertyAccess/PropertyAccessor.php b/src/Symfony/Component/PropertyAccess/PropertyAccessor.php index b4c27f928421b..1d2558a4cc688 100644 --- a/src/Symfony/Component/PropertyAccess/PropertyAccessor.php +++ b/src/Symfony/Component/PropertyAccess/PropertyAccessor.php @@ -13,6 +13,7 @@ use Psr\Cache\CacheItemPoolInterface; use Psr\Log\LoggerInterface; +use Psr\Log\NullLogger; use Symfony\Component\Cache\Adapter\AdapterInterface; use Symfony\Component\Cache\Adapter\ApcuAdapter; use Symfony\Component\Cache\Adapter\NullAdapter; @@ -928,7 +929,9 @@ public static function createCache($namespace, $defaultLifetime, $version, Logge } $apcu = new ApcuAdapter($namespace, $defaultLifetime / 5, $version); - if (null !== $logger) { + if ('cli' === \PHP_SAPI && !ini_get('apc.enable_cli')) { + $apcu->setLogger(new NullLogger()); + } elseif (null !== $logger) { $apcu->setLogger($logger); } From d0235a00cc36c173ca3885991f8ed07609e2238e Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Tue, 26 Sep 2017 12:29:00 +0200 Subject: [PATCH 0897/1099] register class metadata factory alias --- .../Bundle/FrameworkBundle/Resources/config/serializer.xml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/serializer.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/serializer.xml index 924ebf18d8b0f..5fed443127d5a 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/serializer.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/serializer.xml @@ -52,6 +52,8 @@ null
+ + From b6b6d31b71b3b0eca74409b3a4198e48e38cbb00 Mon Sep 17 00:00:00 2001 From: Fabien Lucas Date: Thu, 14 Sep 2017 09:57:27 +0100 Subject: [PATCH 0898/1099] Added an alias for FlashBagInterface in config --- src/Symfony/Bundle/FrameworkBundle/Resources/config/session.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/session.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/session.xml index 0cb86362a231e..335c14a8a6611 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/session.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/session.xml @@ -38,6 +38,7 @@ + From 22f525b01fdace2f42b457ac807bef1528a19811 Mon Sep 17 00:00:00 2001 From: Iltar van der Berg Date: Mon, 14 Aug 2017 10:19:33 +0200 Subject: [PATCH 0899/1099] [Security] Deprecated not being logged out after user change --- UPGRADE-3.4.md | 4 +++ UPGRADE-4.0.md | 6 ++++ .../Bundle/SecurityBundle/CHANGELOG.md | 3 ++ .../DependencyInjection/MainConfiguration.php | 15 ++++++++ .../DependencyInjection/SecurityExtension.php | 12 +++++-- .../Fixtures/php/container1.php | 3 ++ .../Fixtures/php/firewall_provider.php | 2 ++ .../php/firewall_undefined_provider.php | 1 + .../Fixtures/php/listener_provider.php | 1 + .../php/listener_undefined_provider.php | 1 + .../Fixtures/php/merge.php | 1 + .../Fixtures/php/merge_import.php | 1 + .../Fixtures/php/no_custom_user_checker.php | 3 +- .../Fixtures/php/remember_me_options.php | 1 + .../Fixtures/xml/container1.xml | 4 +-- .../Fixtures/xml/firewall_provider.xml | 2 +- .../xml/firewall_undefined_provider.xml | 2 +- .../Fixtures/xml/listener_provider.xml | 2 +- .../xml/listener_undefined_provider.xml | 2 +- .../Fixtures/xml/merge.xml | 2 +- .../Fixtures/xml/merge_import.xml | 2 +- .../Fixtures/xml/remember_me_options.xml | 2 +- .../Fixtures/yml/container1.yml | 2 ++ .../Fixtures/yml/firewall_provider.yml | 2 ++ .../yml/firewall_undefined_provider.yml | 1 + .../Fixtures/yml/listener_provider.yml | 1 + .../yml/listener_undefined_provider.yml | 1 + .../Fixtures/yml/merge.yml | 1 + .../Fixtures/yml/merge_import.yml | 1 + .../Fixtures/yml/remember_me_options.yml | 1 + .../MainConfigurationTest.php | 3 ++ .../SecurityExtensionTest.php | 29 ++++++++++++++++ src/Symfony/Component/Security/CHANGELOG.md | 4 +++ .../Http/Firewall/ContextListener.php | 30 ++++++++++++++-- .../Tests/Firewall/ContextListenerTest.php | 34 ++++++++++++++++--- 35 files changed, 161 insertions(+), 21 deletions(-) diff --git a/UPGRADE-3.4.md b/UPGRADE-3.4.md index cdc062008bf4b..44afe9be5dc63 100644 --- a/UPGRADE-3.4.md +++ b/UPGRADE-3.4.md @@ -269,6 +269,10 @@ SecurityBundle as first argument. Not passing it is deprecated and will throw a `TypeError` in 4.0. + * Added `logout_on_user_change` to the firewall options. This config item will + trigger a logout when the user has changed. Should be set to true to avoid + deprecations in the configuration. + Translation ----------- diff --git a/UPGRADE-4.0.md b/UPGRADE-4.0.md index 3aecb70070f0d..2fc980b92fafc 100644 --- a/UPGRADE-4.0.md +++ b/UPGRADE-4.0.md @@ -642,6 +642,9 @@ Security * Support for defining voters that don't implement the `VoterInterface` has been removed. + * Calling `ContextListener::setLogoutOnUserChange(false)` won't have any + effect anymore. + SecurityBundle -------------- @@ -660,6 +663,9 @@ SecurityBundle `Symfony\Component\Security\Acl\Model\MutableAclProviderInterfaceConnection` as first argument. + * The firewall option `logout_on_user_change` is now always true, which will + trigger a logout if the user changes between requests. + Serializer ---------- diff --git a/src/Symfony/Bundle/SecurityBundle/CHANGELOG.md b/src/Symfony/Bundle/SecurityBundle/CHANGELOG.md index 0c62ce6e2aa9e..b60e2e7e882e0 100644 --- a/src/Symfony/Bundle/SecurityBundle/CHANGELOG.md +++ b/src/Symfony/Bundle/SecurityBundle/CHANGELOG.md @@ -13,6 +13,9 @@ CHANGELOG * `SetAclCommand::__construct()` now takes an instance of `Symfony\Component\Security\Acl\Model\MutableAclProviderInterfaceConnection` as first argument + * Added `logout_on_user_change` to the firewall options. This config item will + trigger a logout when the user has changed. Should be set to true to avoid + deprecations in the configuration. 3.3.0 ----- diff --git a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/MainConfiguration.php b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/MainConfiguration.php index 35db5bd83949a..e9863145e798f 100644 --- a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/MainConfiguration.php +++ b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/MainConfiguration.php @@ -252,6 +252,10 @@ private function addFirewallsSection(ArrayNodeDefinition $rootNode, array $facto ->scalarNode('provider')->end() ->booleanNode('stateless')->defaultFalse()->end() ->scalarNode('context')->cannotBeEmpty()->end() + ->booleanNode('logout_on_user_change') + ->defaultFalse() + ->info('When true, it will trigger a logout for the user if something has changed. This will be the default behavior as of Syfmony 4.0.') + ->end() ->arrayNode('logout') ->treatTrueLike(array()) ->canBeUnset() @@ -340,6 +344,17 @@ private function addFirewallsSection(ArrayNodeDefinition $rootNode, array $facto return $firewall; }) ->end() + ->validate() + ->ifTrue(function ($v) { + return (isset($v['stateless']) && true === $v['stateless']) || (isset($v['security']) && false === $v['security']); + }) + ->then(function ($v) { + // this option doesn't change behavior when true when stateless, so prevent deprecations + $v['logout_on_user_change'] = true; + + return $v; + }) + ->end() ; } diff --git a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php index 21fc056e382f2..b19f6b1b8d58c 100644 --- a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php +++ b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php @@ -265,14 +265,14 @@ private function createFirewalls($config, ContainerBuilder $container) $providerIds = $this->createUserProviders($config, $container); // make the ContextListener aware of the configured user providers - $definition = $container->getDefinition('security.context_listener'); - $arguments = $definition->getArguments(); + $contextListenerDefinition = $container->getDefinition('security.context_listener'); + $arguments = $contextListenerDefinition->getArguments(); $userProviders = array(); foreach ($providerIds as $userProviderId) { $userProviders[] = new Reference($userProviderId); } $arguments[1] = new IteratorArgument($userProviders); - $definition->setArguments($arguments); + $contextListenerDefinition->setArguments($arguments); $customUserChecker = false; @@ -284,6 +284,12 @@ private function createFirewalls($config, ContainerBuilder $container) $customUserChecker = true; } + if (!isset($firewall['logout_on_user_change']) || !$firewall['logout_on_user_change']) { + @trigger_error('Setting logout_on_user_change to false is deprecated as of 3.4 and will always be true in 4.0. Set logout_on_user_change to true in your firewall configuration.', E_USER_DEPRECATED); + } + + $contextListenerDefinition->addMethodCall('setLogoutOnUserChange', array($firewall['logout_on_user_change'])); + $configId = 'security.firewall.map.config.'.$name; list($matcher, $listeners, $exceptionListener) = $this->createFirewall($container, $name, $firewall, $authenticationProviders, $providerIds, $configId); diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/container1.php b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/container1.php index fc9b07c4f18b2..581407fcc05a5 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/container1.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/container1.php @@ -73,6 +73,7 @@ 'logout' => true, 'remember_me' => array('secret' => 'TheSecret'), 'user_checker' => null, + 'logout_on_user_change' => true, ), 'host' => array( 'pattern' => '/test', @@ -80,11 +81,13 @@ 'methods' => array('GET', 'POST'), 'anonymous' => true, 'http_basic' => true, + 'logout_on_user_change' => true, ), 'with_user_checker' => array( 'user_checker' => 'app.user_checker', 'anonymous' => true, 'http_basic' => true, + 'logout_on_user_change' => true, ), ), diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/firewall_provider.php b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/firewall_provider.php index ff9d9f6b89df6..da218fc61c9cf 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/firewall_provider.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/firewall_provider.php @@ -15,10 +15,12 @@ 'main' => array( 'provider' => 'default', 'form_login' => true, + 'logout_on_user_change' => true, ), 'other' => array( 'provider' => 'with-dash', 'form_login' => true, + 'logout_on_user_change' => true, ), ), )); diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/firewall_undefined_provider.php b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/firewall_undefined_provider.php index 78d461efe38d1..46a51f91fdd22 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/firewall_undefined_provider.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/firewall_undefined_provider.php @@ -12,6 +12,7 @@ 'main' => array( 'provider' => 'undefined', 'form_login' => true, + 'logout_on_user_change' => true, ), ), )); diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/listener_provider.php b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/listener_provider.php index d7f1cd6973f36..072b70b078a58 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/listener_provider.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/listener_provider.php @@ -11,6 +11,7 @@ 'firewalls' => array( 'main' => array( 'form_login' => array('provider' => 'default'), + 'logout_on_user_change' => true, ), ), )); diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/listener_undefined_provider.php b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/listener_undefined_provider.php index da54f025d1a70..567f8a0d4b2d7 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/listener_undefined_provider.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/listener_undefined_provider.php @@ -11,6 +11,7 @@ 'firewalls' => array( 'main' => array( 'form_login' => array('provider' => 'undefined'), + 'logout_on_user_change' => true, ), ), )); diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/merge.php b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/merge.php index 50ef504ea4d43..eb34a6a6f64b6 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/merge.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/merge.php @@ -11,6 +11,7 @@ 'main' => array( 'form_login' => false, 'http_basic' => null, + 'logout_on_user_change' => true, ), ), diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/merge_import.php b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/merge_import.php index 912b9127ef369..6ed2d18a36709 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/merge_import.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/merge_import.php @@ -6,6 +6,7 @@ 'form_login' => array( 'login_path' => '/login', ), + 'logout_on_user_change' => true, ), ), 'role_hierarchy' => array( diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/no_custom_user_checker.php b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/no_custom_user_checker.php index b08d9c60c82f8..91c475418b450 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/no_custom_user_checker.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/no_custom_user_checker.php @@ -12,7 +12,8 @@ ), 'firewalls' => array( 'simple' => array('pattern' => '/login', 'security' => false), - 'secure' => array('stateless' => true, + 'secure' => array( + 'stateless' => true, 'http_basic' => true, 'http_digest' => array('secret' => 'TheSecret'), 'form_login' => true, diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/remember_me_options.php b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/remember_me_options.php index e0ca4f6dedf3e..a61fde3dc7309 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/remember_me_options.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/remember_me_options.php @@ -13,6 +13,7 @@ 'catch_exceptions' => false, 'token_provider' => 'token_provider_id', ), + 'logout_on_user_change' => true, ), ), )); diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/container1.xml b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/container1.xml index 19167551025e2..e5049f2033e51 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/container1.xml +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/container1.xml @@ -60,12 +60,12 @@ - + - + app.user_checker diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/firewall_provider.xml b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/firewall_provider.xml index bd87fee4abae9..9d37164e8d409 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/firewall_provider.xml +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/firewall_provider.xml @@ -11,7 +11,7 @@ - + diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/firewall_undefined_provider.xml b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/firewall_undefined_provider.xml index f596ac5a6240b..6a05d48e539b9 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/firewall_undefined_provider.xml +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/firewall_undefined_provider.xml @@ -11,7 +11,7 @@ - + diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/listener_provider.xml b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/listener_provider.xml index b1bcd8eae8155..f53b91b00ef78 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/listener_provider.xml +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/listener_provider.xml @@ -11,7 +11,7 @@ - + diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/listener_undefined_provider.xml b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/listener_undefined_provider.xml index 725e85a1d0f27..75271ad075f37 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/listener_undefined_provider.xml +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/listener_undefined_provider.xml @@ -11,7 +11,7 @@ - + diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/merge.xml b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/merge.xml index 8a17f6db23c55..42dc91c9975ef 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/merge.xml +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/merge.xml @@ -12,7 +12,7 @@ - + diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/merge_import.xml b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/merge_import.xml index 81b8cffd68d9e..051e2a40b3a16 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/merge_import.xml +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/merge_import.xml @@ -6,7 +6,7 @@ xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd"> - + diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/remember_me_options.xml b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/remember_me_options.xml index b6ade91a07970..583720ea1de9b 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/remember_me_options.xml +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/remember_me_options.xml @@ -9,7 +9,7 @@ - + diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/container1.yml b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/container1.yml index e8ed61ef031b9..a2b57201bfbd2 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/container1.yml +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/container1.yml @@ -64,11 +64,13 @@ security: methods: [GET,POST] anonymous: true http_basic: true + logout_on_user_change: true with_user_checker: anonymous: ~ http_basic: ~ user_checker: app.user_checker + logout_on_user_change: true role_hierarchy: ROLE_ADMIN: ROLE_USER diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/firewall_provider.yml b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/firewall_provider.yml index 11c329aa8e2fe..b8da52b6e45d3 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/firewall_provider.yml +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/firewall_provider.yml @@ -11,6 +11,8 @@ security: main: provider: default form_login: true + logout_on_user_change: true other: provider: with-dash form_login: true + logout_on_user_change: true diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/firewall_undefined_provider.yml b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/firewall_undefined_provider.yml index ec2664054009c..3385fc3485a0e 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/firewall_undefined_provider.yml +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/firewall_undefined_provider.yml @@ -8,3 +8,4 @@ security: main: provider: undefined form_login: true + logout_on_user_change: true diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/listener_provider.yml b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/listener_provider.yml index 652f23b5f0425..53e2784c4b3a9 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/listener_provider.yml +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/listener_provider.yml @@ -8,3 +8,4 @@ security: main: form_login: provider: default + logout_on_user_change: true diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/listener_undefined_provider.yml b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/listener_undefined_provider.yml index 1916df4c2e7ca..ba5f69ede665d 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/listener_undefined_provider.yml +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/listener_undefined_provider.yml @@ -8,3 +8,4 @@ security: main: form_login: provider: undefined + logout_on_user_change: true diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/merge.yml b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/merge.yml index 60c0bbea558e7..d8f443c62f34e 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/merge.yml +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/merge.yml @@ -9,6 +9,7 @@ security: main: form_login: false http_basic: ~ + logout_on_user_change: true role_hierarchy: FOO: [MOO] diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/merge_import.yml b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/merge_import.yml index 4f8db0a09f7b4..a081003a49578 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/merge_import.yml +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/merge_import.yml @@ -3,6 +3,7 @@ security: main: form_login: login_path: /login + logout_on_user_change: true role_hierarchy: FOO: BAR diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/remember_me_options.yml b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/remember_me_options.yml index a521c8c6a803d..716cd4cf99d14 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/remember_me_options.yml +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/remember_me_options.yml @@ -10,3 +10,4 @@ security: secret: TheSecret catch_exceptions: false token_provider: token_provider_id + logout_on_user_change: true diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/MainConfigurationTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/MainConfigurationTest.php index a64c4fe4101f1..02e8062c269f4 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/MainConfigurationTest.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/MainConfigurationTest.php @@ -31,6 +31,7 @@ class MainConfigurationTest extends TestCase ), 'firewalls' => array( 'stub' => array(), + 'logout_on_user_change' => true, ), ); @@ -78,6 +79,7 @@ public function testCsrfAliases() 'csrf_token_generator' => 'a_token_generator', 'csrf_token_id' => 'a_token_id', ), + 'logout_on_user_change' => true, ), ), ); @@ -107,6 +109,7 @@ public function testUserCheckers() 'firewalls' => array( 'stub' => array( 'user_checker' => 'app.henk_checker', + 'logout_on_user_change' => true, ), ), ); diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/SecurityExtensionTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/SecurityExtensionTest.php index 72ef2e0c3ed56..1055e4afd40f6 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/SecurityExtensionTest.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/SecurityExtensionTest.php @@ -38,6 +38,7 @@ public function testInvalidCheckPath() 'form_login' => array( 'check_path' => '/some_area/login_check', ), + 'logout_on_user_change' => true, ), ), )); @@ -61,6 +62,7 @@ public function testFirewallWithoutAuthenticationListener() 'firewalls' => array( 'some_firewall' => array( 'pattern' => '/.*', + 'logout_on_user_change' => true, ), ), )); @@ -88,6 +90,7 @@ public function testFirewallWithInvalidUserProvider() 'some_firewall' => array( 'pattern' => '/.*', 'http_basic' => array(), + 'logout_on_user_change' => true, ), ), )); @@ -110,6 +113,7 @@ public function testDisableRoleHierarchyVoter() 'some_firewall' => array( 'pattern' => '/.*', 'http_basic' => null, + 'logout_on_user_change' => true, ), ), )); @@ -119,6 +123,31 @@ public function testDisableRoleHierarchyVoter() $this->assertFalse($container->hasDefinition('security.access.role_hierarchy_voter')); } + /** + * @group legacy + * @expectedDeprecation Setting logout_on_user_change to false is deprecated as of 3.4 and will always be true in 4.0. Set logout_on_user_change to true in your firewall configuration. + */ + public function testDeprecationForUserLogout() + { + $container = $this->getRawContainer(); + + $container->loadFromExtension('security', array( + 'providers' => array( + 'default' => array('id' => 'foo'), + ), + + 'firewalls' => array( + 'some_firewall' => array( + 'pattern' => '/.*', + 'http_basic' => null, + 'logout_on_user_change' => false, + ), + ), + )); + + $container->compile(); + } + protected function getRawContainer() { $container = new ContainerBuilder(); diff --git a/src/Symfony/Component/Security/CHANGELOG.md b/src/Symfony/Component/Security/CHANGELOG.md index 292c304fc68c7..99032dae9da9b 100644 --- a/src/Symfony/Component/Security/CHANGELOG.md +++ b/src/Symfony/Component/Security/CHANGELOG.md @@ -6,6 +6,10 @@ CHANGELOG * Using voters that do not implement the `VoterInterface`is now deprecated in the `AccessDecisionManager` and this functionality will be removed in 4.0. + * Using the `ContextListener` without setting the `logoutOnUserChange` + property will trigger a deprecation when the user has changed. As of 4.0 + the user will always be logged out when the user has changed between + requests. 3.3.0 ----- diff --git a/src/Symfony/Component/Security/Http/Firewall/ContextListener.php b/src/Symfony/Component/Security/Http/Firewall/ContextListener.php index cd26d83ef7291..e018f704dd659 100644 --- a/src/Symfony/Component/Security/Http/Firewall/ContextListener.php +++ b/src/Symfony/Component/Security/Http/Firewall/ContextListener.php @@ -44,6 +44,7 @@ class ContextListener implements ListenerInterface private $dispatcher; private $registered; private $trustResolver; + private $logoutOnUserChange = false; /** * @param TokenStorageInterface $tokenStorage @@ -68,6 +69,16 @@ public function __construct(TokenStorageInterface $tokenStorage, $userProviders, $this->trustResolver = $trustResolver ?: new AuthenticationTrustResolver(AnonymousToken::class, RememberMeToken::class); } + /** + * Enables deauthentication during refreshUser when the user has changed. + * + * @param bool $logoutOnUserChange + */ + public function setLogoutOnUserChange($logoutOnUserChange) + { + $this->logoutOnUserChange = (bool) $logoutOnUserChange; + } + /** * Reads the Security Token from the session. * @@ -122,14 +133,14 @@ public function onKernelResponse(FilterResponseEvent $event) return; } - if (!$event->getRequest()->hasSession()) { + $request = $event->getRequest(); + + if (!$request->hasSession()) { return; } $this->dispatcher->removeListener(KernelEvents::RESPONSE, array($this, 'onKernelResponse')); $this->registered = false; - - $request = $event->getRequest(); $session = $request->getSession(); if ((null === $token = $this->tokenStorage->getToken()) || $this->trustResolver->isAnonymous($token)) { @@ -172,6 +183,19 @@ protected function refreshUser(TokenInterface $token) $refreshedUser = $provider->refreshUser($user); $token->setUser($refreshedUser); + // tokens can be deauthenticated if the user has been changed. + if (!$token->isAuthenticated()) { + if ($this->logoutOnUserChange) { + if (null !== $this->logger) { + $this->logger->debug('Token was deauthenticated after trying to refresh it.', array('username' => $refreshedUser->getUsername(), 'provider' => get_class($provider))); + } + + return null; + } + + @trigger_error('Refreshing a deauthenticated user is deprecated as of 3.4 and will trigger a logout in 4.0.', E_USER_DEPRECATED); + } + if (null !== $this->logger) { $context = array('provider' => get_class($provider), 'username' => $refreshedUser->getUsername()); diff --git a/src/Symfony/Component/Security/Http/Tests/Firewall/ContextListenerTest.php b/src/Symfony/Component/Security/Http/Tests/Firewall/ContextListenerTest.php index 66cf4458bc4de..d27569fa3a0ba 100644 --- a/src/Symfony/Component/Security/Http/Tests/Firewall/ContextListenerTest.php +++ b/src/Symfony/Component/Security/Http/Tests/Firewall/ContextListenerTest.php @@ -249,7 +249,11 @@ public function testHandleRemovesTokenIfNoPreviousSessionWasFound() $listener->handle($event); } - public function testTryAllUserProvidersUntilASupportingUserProviderIsFound() + /** + * @group legacy + * @expectedDeprecation Refreshing a deauthenticated user is deprecated as of 3.4 and will trigger a logout in 4.0. + */ + public function testIfTokenIsDeauthenticatedTriggersDeprecations() { $tokenStorage = new TokenStorage(); $refreshedUser = new User('foobar', 'baz'); @@ -258,11 +262,29 @@ public function testTryAllUserProvidersUntilASupportingUserProviderIsFound() $this->assertSame($refreshedUser, $tokenStorage->getToken()->getUser()); } + public function testIfTokenIsDeauthenticated() + { + $tokenStorage = new TokenStorage(); + $refreshedUser = new User('foobar', 'baz'); + $this->handleEventWithPreviousSession($tokenStorage, array(new NotSupportingUserProvider(), new SupportingUserProvider($refreshedUser)), null, true); + + $this->assertNull($tokenStorage->getToken()); + } + + public function testTryAllUserProvidersUntilASupportingUserProviderIsFound() + { + $tokenStorage = new TokenStorage(); + $refreshedUser = new User('foobar', 'baz'); + $this->handleEventWithPreviousSession($tokenStorage, array(new NotSupportingUserProvider(), new SupportingUserProvider($refreshedUser)), $refreshedUser); + + $this->assertSame($refreshedUser, $tokenStorage->getToken()->getUser()); + } + public function testNextSupportingUserProviderIsTriedIfPreviousSupportingUserProviderDidNotLoadTheUser() { $tokenStorage = new TokenStorage(); $refreshedUser = new User('foobar', 'baz'); - $this->handleEventWithPreviousSession($tokenStorage, array(new SupportingUserProvider(), new SupportingUserProvider($refreshedUser))); + $this->handleEventWithPreviousSession($tokenStorage, array(new SupportingUserProvider(), new SupportingUserProvider($refreshedUser)), $refreshedUser); $this->assertSame($refreshedUser, $tokenStorage->getToken()->getUser()); } @@ -287,7 +309,7 @@ public function testAcceptsProvidersAsTraversable() { $tokenStorage = new TokenStorage(); $refreshedUser = new User('foobar', 'baz'); - $this->handleEventWithPreviousSession($tokenStorage, new \ArrayObject(array(new NotSupportingUserProvider(), new SupportingUserProvider($refreshedUser)))); + $this->handleEventWithPreviousSession($tokenStorage, new \ArrayObject(array(new NotSupportingUserProvider(), new SupportingUserProvider($refreshedUser))), $refreshedUser); $this->assertSame($refreshedUser, $tokenStorage->getToken()->getUser()); } @@ -320,16 +342,18 @@ protected function runSessionOnKernelResponse($newToken, $original = null) return $session; } - private function handleEventWithPreviousSession(TokenStorageInterface $tokenStorage, $userProviders) + private function handleEventWithPreviousSession(TokenStorageInterface $tokenStorage, $userProviders, UserInterface $user = null, $logoutOnUserChange = false) { + $user = $user ?: new User('foo', 'bar'); $session = new Session(new MockArraySessionStorage()); - $session->set('_security_context_key', serialize(new UsernamePasswordToken(new User('foo', 'bar'), '', 'context_key'))); + $session->set('_security_context_key', serialize(new UsernamePasswordToken($user, '', 'context_key', array('ROLE_USER')))); $request = new Request(); $request->setSession($session); $request->cookies->set('MOCKSESSID', true); $listener = new ContextListener($tokenStorage, $userProviders, 'context_key'); + $listener->setLogoutOnUserChange($logoutOnUserChange); $listener->handle(new GetResponseEvent($this->getMockBuilder('Symfony\Component\HttpKernel\HttpKernelInterface')->getMock(), $request, HttpKernelInterface::MASTER_REQUEST)); } } From e3b7dc54243fe54e952e9d45301903561cb31453 Mon Sep 17 00:00:00 2001 From: Robin Chalas Date: Mon, 25 Sep 2017 11:36:55 +0200 Subject: [PATCH 0900/1099] [SecurityBundle] Deprecate ACL related code --- UPGRADE-3.4.md | 9 +- UPGRADE-4.0.md | 7 +- .../Bundle/SecurityBundle/CHANGELOG.md | 7 +- .../SecurityBundle/Command/InitAclCommand.php | 17 ++- .../SecurityBundle/Command/SetAclCommand.php | 15 ++- .../DependencyInjection/MainConfiguration.php | 1 + .../CompleteConfigurationTest.php | 31 ++++-- .../Fixtures/php/container1.php | 1 - .../Fixtures/php/container1_with_acl.php | 102 ++++++++++++++++++ .../Fixtures/xml/container1.xml | 2 - .../Fixtures/xml/container1_with_acl.xml | 81 ++++++++++++++ .../Fixtures/yml/container1.yml | 1 - .../Fixtures/yml/container1_with_acl.yml | 83 ++++++++++++++ .../Tests/Functional/SetAclCommandTest.php | 4 +- 14 files changed, 315 insertions(+), 46 deletions(-) create mode 100644 src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/container1_with_acl.php create mode 100644 src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/container1_with_acl.xml create mode 100644 src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/container1_with_acl.yml diff --git a/UPGRADE-3.4.md b/UPGRADE-3.4.md index 44afe9be5dc63..ca244024ea259 100644 --- a/UPGRADE-3.4.md +++ b/UPGRADE-3.4.md @@ -264,10 +264,11 @@ SecurityBundle `Doctrine\DBAL\Connection` as first argument. Not passing it is deprecated and will throw a `TypeError` in 4.0. - * `SetAclCommand::__construct()` now takes an instance of - `Symfony\Component\Security\Acl\Model\MutableAclProviderInterfaceConnection` - as first argument. Not passing it is deprecated and will throw a `TypeError` - in 4.0. + * The `acl:set` command has been deprecated along with the `SetAclCommand` class, + both will be removed in 4.0. Install symfony/acl-bundle instead + + * The `init:acl` command has been deprecated along with the `InitAclCommand` class, + both will be removed in 4.0. Install symfony/acl-bundle and use `acl:init` instead * Added `logout_on_user_change` to the firewall options. This config item will trigger a logout when the user has changed. Should be set to true to avoid diff --git a/UPGRADE-4.0.md b/UPGRADE-4.0.md index 2fc980b92fafc..5dd6e56fdb668 100644 --- a/UPGRADE-4.0.md +++ b/UPGRADE-4.0.md @@ -656,12 +656,9 @@ SecurityBundle * `UserPasswordEncoderCommand` does not extend `ContainerAwareCommand` nor implement `ContainerAwareInterface` anymore. - * `InitAclCommand::__construct()` now requires an instance of - `Doctrine\DBAL\Connection` as first argument. + * `InitAclCommand` has been removed. Use `Symfony\Bundle\AclBundle\Command\InitAclCommand` instead - * `SetAclCommand::__construct()` now requires an instance of - `Symfony\Component\Security\Acl\Model\MutableAclProviderInterfaceConnection` - as first argument. + * `SetAclCommand` has been removed. Use `Symfony\Bundle\AclBundle\Command\SetAclCommand` instead * The firewall option `logout_on_user_change` is now always true, which will trigger a logout if the user changes between requests. diff --git a/src/Symfony/Bundle/SecurityBundle/CHANGELOG.md b/src/Symfony/Bundle/SecurityBundle/CHANGELOG.md index b60e2e7e882e0..deb2eacdc266a 100644 --- a/src/Symfony/Bundle/SecurityBundle/CHANGELOG.md +++ b/src/Symfony/Bundle/SecurityBundle/CHANGELOG.md @@ -8,14 +8,11 @@ CHANGELOG `VoterInterface` on the class is now deprecated and will be removed in 4.0. * [BC BREAK] `FirewallContext::getListeners()` now returns `\Traversable|array` * added info about called security listeners in profiler - * `InitAclCommand::__construct()` now takes an instance of - `Doctrine\DBAL\Connection` as first argument - * `SetAclCommand::__construct()` now takes an instance of - `Symfony\Component\Security\Acl\Model\MutableAclProviderInterfaceConnection` - as first argument * Added `logout_on_user_change` to the firewall options. This config item will trigger a logout when the user has changed. Should be set to true to avoid deprecations in the configuration. + * deprecated command `acl:set` along with `SetAclCommand` class + * deprecated command `init:acl` along with `InitAclCommand` class 3.3.0 ----- diff --git a/src/Symfony/Bundle/SecurityBundle/Command/InitAclCommand.php b/src/Symfony/Bundle/SecurityBundle/Command/InitAclCommand.php index 72e62c3f48d10..42e4f8825d888 100644 --- a/src/Symfony/Bundle/SecurityBundle/Command/InitAclCommand.php +++ b/src/Symfony/Bundle/SecurityBundle/Command/InitAclCommand.php @@ -11,9 +11,13 @@ namespace Symfony\Bundle\SecurityBundle\Command; +@trigger_error(sprintf('Class "%s" is deprecated since version 3.4 and will be removed in 4.0. Use Symfony\Bundle\AclBundle\Command\SetAclCommand instead.', SetAclCommand::class), E_USER_DEPRECATED); + use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand; use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\ConsoleOutputInterface; use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Style\SymfonyStyle; use Symfony\Component\Security\Acl\Dbal\Schema; use Doctrine\DBAL\Connection; use Doctrine\DBAL\Schema\SchemaException; @@ -23,7 +27,7 @@ * * @author Johannes M. Schmitt * - * @final since version 3.4 + * @deprecated since version 3.4, to be removed in 4.0. See Symfony\Bundle\AclBundle\Command\SetAclCommand instead. */ class InitAclCommand extends ContainerAwareCommand { @@ -32,15 +36,9 @@ class InitAclCommand extends ContainerAwareCommand private $connection; private $schema; - /** - * @param Connection $connection - * @param Schema $schema - */ public function __construct($connection = null, Schema $schema = null) { if (!$connection instanceof Connection) { - @trigger_error(sprintf('%s() expects an instance of "%s" as first argument since version 3.4. Not passing it is deprecated and will throw a TypeError in 4.0.', __METHOD__, Connection::class), E_USER_DEPRECATED); - parent::__construct($connection); return; @@ -54,8 +52,6 @@ public function __construct($connection = null, Schema $schema = null) /** * {@inheritdoc} - * - * BC to be removed in 4.0 */ public function isEnabled() { @@ -93,7 +89,8 @@ protected function configure() */ protected function execute(InputInterface $input, OutputInterface $output) { - // BC to be removed in 4.0 + (new SymfonyStyle($input, $output instanceof ConsoleOutputInterface ? $output->getErrorOutput() : $output))->warning('Command "init:acl" is deprecated since version 3.4 and will be removed from SecurityBundle in 4.0. Install symfony/acl-bundle and use "acl:init" instead.'); + if (null === $this->connection) { $this->connection = $this->getContainer()->get('security.acl.dbal.connection'); $this->schema = $this->getContainer()->get('security.acl.dbal.schema'); diff --git a/src/Symfony/Bundle/SecurityBundle/Command/SetAclCommand.php b/src/Symfony/Bundle/SecurityBundle/Command/SetAclCommand.php index 8782ae7281ce1..c0c51eff4e8c7 100644 --- a/src/Symfony/Bundle/SecurityBundle/Command/SetAclCommand.php +++ b/src/Symfony/Bundle/SecurityBundle/Command/SetAclCommand.php @@ -11,11 +11,15 @@ namespace Symfony\Bundle\SecurityBundle\Command; +@trigger_error(sprintf('Class "%s" is deprecated since version 3.4 and will be removed in 4.0. Use Symfony\Bundle\AclBundle\Command\SetAclCommand instead.', SetAclCommand::class), E_USER_DEPRECATED); + use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; +use Symfony\Component\Console\Output\ConsoleOutputInterface; use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Style\SymfonyStyle; use Symfony\Component\Security\Acl\Domain\ObjectIdentity; use Symfony\Component\Security\Acl\Domain\RoleSecurityIdentity; use Symfony\Component\Security\Acl\Domain\UserSecurityIdentity; @@ -28,7 +32,7 @@ * * @author Kévin Dunglas * - * @final since version 3.4 + * @deprecated since version 3.4, to be removed in 4.0. See Symfony\Bundle\AclBundle\Command\SetAclCommand instead. */ class SetAclCommand extends ContainerAwareCommand { @@ -42,8 +46,6 @@ class SetAclCommand extends ContainerAwareCommand public function __construct($provider = null) { if (!$provider instanceof MutableAclProviderInterface) { - @trigger_error(sprintf('%s() expects an instance of "%s" as first argument since version 3.4. Not passing it is deprecated and will throw a TypeError in 4.0.', __METHOD__, MutableAclProviderInterface::class), E_USER_DEPRECATED); - parent::__construct($provider); return; @@ -56,8 +58,6 @@ public function __construct($provider = null) /** * {@inheritdoc} - * - * BC to be removed in 4.0 */ public function isEnabled() { @@ -117,7 +117,8 @@ protected function configure() */ protected function execute(InputInterface $input, OutputInterface $output) { - // BC to be removed in 4.0 + (new SymfonyStyle($input, $output instanceof ConsoleOutputInterface ? $output->getErrorOutput() : $output))->warning('Command "acl:set" is deprecated since version 3.4 and will be removed from SecurityBundle in 4.0. Install symfony/acl-bundle to use this command.'); + if (null === $this->provider) { $this->provider = $this->getContainer()->get('security.acl.provider'); } @@ -192,8 +193,6 @@ protected function execute(InputInterface $input, OutputInterface $output) /** * Gets the mask builder. * - * BC to be removed in 4.0 - * * @return MaskBuilder */ protected function getMaskBuilder() diff --git a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/MainConfiguration.php b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/MainConfiguration.php index e9863145e798f..533b52cd4b1c6 100644 --- a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/MainConfiguration.php +++ b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/MainConfiguration.php @@ -121,6 +121,7 @@ private function addAclSection(ArrayNodeDefinition $rootNode) $rootNode ->children() ->arrayNode('acl') + ->setDeprecated('The "security.acl" configuration key is deprecated since version 3.4 and will be removed in 4.0. Install symfony/acl-bundle and use the "acl" key instead.') ->children() ->scalarNode('connection') ->defaultNull() diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/CompleteConfigurationTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/CompleteConfigurationTest.php index c7451496d48c2..ce387de9f5bdf 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/CompleteConfigurationTest.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/CompleteConfigurationTest.php @@ -22,8 +22,6 @@ abstract class CompleteConfigurationTest extends TestCase { - private static $containerCache = array(); - abstract protected function getLoader(ContainerBuilder $container); abstract protected function getFileExtension(); @@ -38,6 +36,20 @@ public function testRolesHierarchy() ), $container->getParameter('security.role_hierarchy.roles')); } + /** + * @group legacy + * @expectedDeprecation The "security.acl" configuration key is deprecated since version 3.4 and will be removed in 4.0. Install symfony/acl-bundle and use the "acl" key instead. + */ + public function testRolesHierarchyWithAcl() + { + $container = $this->getContainer('container1_with_acl'); + $this->assertEquals(array( + 'ROLE_ADMIN' => array('ROLE_USER'), + 'ROLE_SUPER_ADMIN' => array('ROLE_USER', 'ROLE_ADMIN', 'ROLE_ALLOWED_TO_SWITCH'), + 'ROLE_REMOTE' => array('ROLE_USER', 'ROLE_ADMIN'), + ), $container->getParameter('security.role_hierarchy.roles')); + } + public function testUserProviders() { $container = $this->getContainer('container1'); @@ -314,14 +326,22 @@ public function testEncoders() )), $container->getDefinition('security.encoder_factory.generic')->getArguments()); } + /** + * @group legacy + * @expectedDeprecation The "security.acl" configuration key is deprecated since version 3.4 and will be removed in 4.0. Install symfony/acl-bundle and use the "acl" key instead. + */ public function testAcl() { - $container = $this->getContainer('container1'); + $container = $this->getContainer('container1_with_acl'); $this->assertTrue($container->hasDefinition('security.acl.dbal.provider')); $this->assertEquals('security.acl.dbal.provider', (string) $container->getAlias('security.acl.provider')); } + /** + * @group legacy + * @expectedDeprecation The "security.acl" configuration key is deprecated since version 3.4 and will be removed in 4.0. Install symfony/acl-bundle and use the "acl" key instead. + */ public function testCustomAclProvider() { $container = $this->getContainer('custom_acl_provider'); @@ -421,9 +441,6 @@ protected function getContainer($file) { $file = $file.'.'.$this->getFileExtension(); - if (isset(self::$containerCache[$file])) { - return self::$containerCache[$file]; - } $container = new ContainerBuilder(); $security = new SecurityExtension(); $container->registerExtension($security); @@ -436,6 +453,6 @@ protected function getContainer($file) $container->getCompilerPassConfig()->setRemovingPasses(array()); $container->compile(); - return self::$containerCache[$file] = $container; + return $container; } } diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/container1.php b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/container1.php index 581407fcc05a5..2860e6f587822 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/container1.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/container1.php @@ -1,7 +1,6 @@ loadFromExtension('security', array( - 'acl' => array(), 'encoders' => array( 'JMS\FooBundle\Entity\User1' => 'plaintext', 'JMS\FooBundle\Entity\User2' => array( diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/container1_with_acl.php b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/container1_with_acl.php new file mode 100644 index 0000000000000..fc9b07c4f18b2 --- /dev/null +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/container1_with_acl.php @@ -0,0 +1,102 @@ +loadFromExtension('security', array( + 'acl' => array(), + 'encoders' => array( + 'JMS\FooBundle\Entity\User1' => 'plaintext', + 'JMS\FooBundle\Entity\User2' => array( + 'algorithm' => 'sha1', + 'encode_as_base64' => false, + 'iterations' => 5, + ), + 'JMS\FooBundle\Entity\User3' => array( + 'algorithm' => 'md5', + ), + 'JMS\FooBundle\Entity\User4' => array( + 'id' => 'security.encoder.foo', + ), + 'JMS\FooBundle\Entity\User5' => array( + 'algorithm' => 'pbkdf2', + 'hash_algorithm' => 'sha1', + 'encode_as_base64' => false, + 'iterations' => 5, + 'key_length' => 30, + ), + 'JMS\FooBundle\Entity\User6' => array( + 'algorithm' => 'bcrypt', + 'cost' => 15, + ), + ), + 'providers' => array( + 'default' => array( + 'memory' => array( + 'users' => array( + 'foo' => array('password' => 'foo', 'roles' => 'ROLE_USER'), + ), + ), + ), + 'digest' => array( + 'memory' => array( + 'users' => array( + 'foo' => array('password' => 'foo', 'roles' => 'ROLE_USER, ROLE_ADMIN'), + ), + ), + ), + 'basic' => array( + 'memory' => array( + 'users' => array( + 'foo' => array('password' => '0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33', 'roles' => 'ROLE_SUPER_ADMIN'), + 'bar' => array('password' => '0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33', 'roles' => array('ROLE_USER', 'ROLE_ADMIN')), + ), + ), + ), + 'service' => array( + 'id' => 'user.manager', + ), + 'chain' => array( + 'chain' => array( + 'providers' => array('service', 'basic'), + ), + ), + ), + + 'firewalls' => array( + 'simple' => array('pattern' => '/login', 'security' => false), + 'secure' => array('stateless' => true, + 'http_basic' => true, + 'http_digest' => array('secret' => 'TheSecret'), + 'form_login' => true, + 'anonymous' => true, + 'switch_user' => true, + 'x509' => true, + 'remote_user' => true, + 'logout' => true, + 'remember_me' => array('secret' => 'TheSecret'), + 'user_checker' => null, + ), + 'host' => array( + 'pattern' => '/test', + 'host' => 'foo\\.example\\.org', + 'methods' => array('GET', 'POST'), + 'anonymous' => true, + 'http_basic' => true, + ), + 'with_user_checker' => array( + 'user_checker' => 'app.user_checker', + 'anonymous' => true, + 'http_basic' => true, + ), + ), + + 'access_control' => array( + array('path' => '/blog/524', 'role' => 'ROLE_USER', 'requires_channel' => 'https', 'methods' => array('get', 'POST')), + array('path' => '/blog/.*', 'role' => 'IS_AUTHENTICATED_ANONYMOUSLY'), + array('path' => '/blog/524', 'role' => 'IS_AUTHENTICATED_ANONYMOUSLY', 'allow_if' => "token.getUsername() matches '/^admin/'"), + ), + + 'role_hierarchy' => array( + 'ROLE_ADMIN' => 'ROLE_USER', + 'ROLE_SUPER_ADMIN' => array('ROLE_USER', 'ROLE_ADMIN', 'ROLE_ALLOWED_TO_SWITCH'), + 'ROLE_REMOTE' => 'ROLE_USER,ROLE_ADMIN', + ), +)); diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/container1.xml b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/container1.xml index e5049f2033e51..da02e78d0af34 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/container1.xml +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/container1.xml @@ -6,8 +6,6 @@ xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd"> - - diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/container1_with_acl.xml b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/container1_with_acl.xml new file mode 100644 index 0000000000000..6d43fcdc4ff80 --- /dev/null +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/container1_with_acl.xml @@ -0,0 +1,81 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + app.user_checker + + + ROLE_USER + ROLE_USER,ROLE_ADMIN,ROLE_ALLOWED_TO_SWITCH + ROLE_USER,ROLE_ADMIN + + + + + + diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/container1.yml b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/container1.yml index a2b57201bfbd2..d45846ee5892b 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/container1.yml +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/container1.yml @@ -1,5 +1,4 @@ security: - acl: ~ encoders: JMS\FooBundle\Entity\User1: plaintext JMS\FooBundle\Entity\User2: diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/container1_with_acl.yml b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/container1_with_acl.yml new file mode 100644 index 0000000000000..e8ed61ef031b9 --- /dev/null +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/container1_with_acl.yml @@ -0,0 +1,83 @@ +security: + acl: ~ + encoders: + JMS\FooBundle\Entity\User1: plaintext + JMS\FooBundle\Entity\User2: + algorithm: sha1 + encode_as_base64: false + iterations: 5 + JMS\FooBundle\Entity\User3: + algorithm: md5 + JMS\FooBundle\Entity\User4: + id: security.encoder.foo + JMS\FooBundle\Entity\User5: + algorithm: pbkdf2 + hash_algorithm: sha1 + encode_as_base64: false + iterations: 5 + key_length: 30 + JMS\FooBundle\Entity\User6: + algorithm: bcrypt + cost: 15 + + providers: + default: + memory: + users: + foo: { password: foo, roles: ROLE_USER } + digest: + memory: + users: + foo: { password: foo, roles: 'ROLE_USER, ROLE_ADMIN' } + basic: + memory: + users: + foo: { password: 0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33, roles: ROLE_SUPER_ADMIN } + bar: { password: 0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33, roles: [ROLE_USER, ROLE_ADMIN] } + service: + id: user.manager + chain: + chain: + providers: [service, basic] + + + firewalls: + simple: { pattern: /login, security: false } + secure: + stateless: true + http_basic: true + http_digest: + secret: TheSecret + form_login: true + anonymous: true + switch_user: true + x509: true + remote_user: true + logout: true + remember_me: + secret: TheSecret + user_checker: ~ + + host: + pattern: /test + host: foo\.example\.org + methods: [GET,POST] + anonymous: true + http_basic: true + + with_user_checker: + anonymous: ~ + http_basic: ~ + user_checker: app.user_checker + + role_hierarchy: + ROLE_ADMIN: ROLE_USER + ROLE_SUPER_ADMIN: [ROLE_USER, ROLE_ADMIN, ROLE_ALLOWED_TO_SWITCH] + ROLE_REMOTE: ROLE_USER,ROLE_ADMIN + + access_control: + - { path: /blog/524, role: ROLE_USER, requires_channel: https, methods: [get, POST]} + - + path: /blog/.* + role: IS_AUTHENTICATED_ANONYMOUSLY + - { path: /blog/524, role: IS_AUTHENTICATED_ANONYMOUSLY, allow_if: "token.getUsername() matches '/^admin/'" } diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/SetAclCommandTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/SetAclCommandTest.php index 803109ec2097c..85f6cf86a403d 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/SetAclCommandTest.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/SetAclCommandTest.php @@ -33,15 +33,13 @@ * * @author Kévin Dunglas * @requires extension pdo_sqlite + * @group legacy */ class SetAclCommandTest extends WebTestCase { const OBJECT_CLASS = 'Symfony\Bundle\SecurityBundle\Tests\Functional\Bundle\AclBundle\Entity\Car'; const SECURITY_CLASS = 'Symfony\Component\Security\Core\User\User'; - /** - * @group legacy - */ public function testSetAclUser() { $objectId = 1; From 3deb3940ab194d3f16985a2ed8a31d9576e2753f Mon Sep 17 00:00:00 2001 From: Alexandru Furculita Date: Sun, 17 Sep 2017 15:54:32 +0300 Subject: [PATCH 0901/1099] [HttpFoundation] Deprecate compatibility with PHP <5.4 sessions --- UPGRADE-3.4.md | 18 +++++++++ UPGRADE-4.0.md | 7 ++++ .../Bridge/Twig/Tests/AppVariableTest.php | 8 ++-- .../Tests/Controller/ControllerTraitTest.php | 2 +- .../Component/HttpFoundation/CHANGELOG.md | 7 ++++ .../Handler/MemcacheSessionHandler.php | 2 - .../Handler/MemcachedSessionHandler.php | 2 - .../Storage/Handler/MongoDbSessionHandler.php | 2 - .../Handler/NativeFileSessionHandler.php | 5 +-- .../Storage/Handler/NativeSessionHandler.php | 5 ++- .../Storage/Handler/NullSessionHandler.php | 2 - .../Session/Storage/MetadataBag.php | 2 - .../Storage/MockArraySessionStorage.php | 2 - .../Storage/MockFileSessionStorage.php | 2 - .../Session/Storage/NativeSessionStorage.php | 31 +++++++------- .../Storage/PhpBridgeSessionStorage.php | 9 +---- .../Session/Storage/Proxy/AbstractProxy.php | 4 +- .../Session/Storage/Proxy/NativeProxy.php | 6 ++- .../Storage/Proxy/SessionHandlerProxy.php | 9 ++--- .../Handler/NativeSessionHandlerTest.php | 1 + .../Storage/Proxy/AbstractProxyTest.php | 40 +++---------------- .../Session/Storage/Proxy/NativeProxyTest.php | 2 + .../Storage/Proxy/SessionHandlerProxyTest.php | 1 + 23 files changed, 79 insertions(+), 90 deletions(-) diff --git a/UPGRADE-3.4.md b/UPGRADE-3.4.md index cdc062008bf4b..04d107e512c59 100644 --- a/UPGRADE-3.4.md +++ b/UPGRADE-3.4.md @@ -205,6 +205,24 @@ FrameworkBundle `TranslationDebugCommand`, `TranslationUpdateCommand`, `XliffLintCommand` and `YamlLintCommand` classes have been marked as final +HttpFoundation +-------------- + + * The `Symfony\Component\HttpFoundation\Session\Storage\Handler\NativeSessionHandler` + class has been deprecated and will be removed in 4.0. Use the `\SessionHandler` class instead. + + * The `Symfony\Component\HttpFoundation\Session\Storage\Proxy\AbstractProxy` class has been + deprecated and will be removed in 4.0. Use your `\SessionHandlerInterface` implementation directly. + + * The `Symfony\Component\HttpFoundation\Session\Storage\Proxy\NativeProxy` class has been + deprecated and will be removed in 4.0. Use your `\SessionHandlerInterface` implementation directly. + + * The `Symfony\Component\HttpFoundation\Session\Storage\Proxy\SessionHandlerProxy` class has been + deprecated and will be removed in 4.0. Use your `\SessionHandlerInterface` implementation directly. + + * `NativeSessionStorage::setSaveHandler()` now takes an instance of `\SessionHandlerInterface` as argument. + Not passing it is deprecated and will throw a `TypeError` in 4.0. + HttpKernel ---------- diff --git a/UPGRADE-4.0.md b/UPGRADE-4.0.md index 3aecb70070f0d..dc0bd0d82503d 100644 --- a/UPGRADE-4.0.md +++ b/UPGRADE-4.0.md @@ -524,6 +524,13 @@ HttpFoundation * The ability to check only for cacheable HTTP methods using `Request::isMethodSafe()` is not supported anymore, use `Request::isMethodCacheable()` instead. + * The `Symfony\Component\HttpFoundation\Session\Storage\Handler\NativeSessionHandler`, + `Symfony\Component\HttpFoundation\Session\Storage\Proxy\AbstractProxy`, + `Symfony\Component\HttpFoundation\Session\Storage\Proxy\NativeProxy` and + `Symfony\Component\HttpFoundation\Session\Storage\Proxy\SessionHandlerProxy` classes have been removed. + + * `NativeSessionStorage::setSaveHandler()` now requires an instance of `\SessionHandlerInterface` as argument. + HttpKernel ---------- diff --git a/src/Symfony/Bridge/Twig/Tests/AppVariableTest.php b/src/Symfony/Bridge/Twig/Tests/AppVariableTest.php index 2a97c269031c8..c258ad41a1465 100644 --- a/src/Symfony/Bridge/Twig/Tests/AppVariableTest.php +++ b/src/Symfony/Bridge/Twig/Tests/AppVariableTest.php @@ -47,8 +47,9 @@ public function testEnvironment() public function testGetSession() { + $session = $this->getMockBuilder(Session::class)->disableOriginalConstructor()->getMock(); $request = $this->getMockBuilder('Symfony\Component\HttpFoundation\Request')->getMock(); - $request->method('getSession')->willReturn($session = new Session()); + $request->method('getSession')->willReturn($session); $this->setRequestStack($request); @@ -167,8 +168,9 @@ public function testGetFlashesWithNoRequest() public function testGetFlashesWithNoSessionStarted() { + $session = $this->getMockBuilder(Session::class)->disableOriginalConstructor()->getMock(); $request = $this->getMockBuilder('Symfony\Component\HttpFoundation\Request')->getMock(); - $request->method('getSession')->willReturn(new Session()); + $request->method('getSession')->willReturn($session); $this->setRequestStack($request); @@ -257,7 +259,7 @@ private function setFlashMessages() $flashBag = new FlashBag(); $flashBag->initialize($flashMessages); - $session = $this->getMockBuilder('Symfony\Component\HttpFoundation\Session\Session')->getMock(); + $session = $this->getMockBuilder('Symfony\Component\HttpFoundation\Session\Session')->disableOriginalConstructor()->getMock(); $session->method('isStarted')->willReturn(true); $session->method('getFlashBag')->willReturn($flashBag); diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/ControllerTraitTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/ControllerTraitTest.php index 3feabfd12e273..71e6f581e7389 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/ControllerTraitTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/ControllerTraitTest.php @@ -376,7 +376,7 @@ public function testRedirectToRoute() public function testAddFlash() { $flashBag = new FlashBag(); - $session = $this->getMockBuilder('Symfony\Component\HttpFoundation\Session\Session')->getMock(); + $session = $this->getMockBuilder('Symfony\Component\HttpFoundation\Session\Session')->disableOriginalConstructor()->getMock(); $session->expects($this->once())->method('getFlashBag')->willReturn($flashBag); $container = new Container(); diff --git a/src/Symfony/Component/HttpFoundation/CHANGELOG.md b/src/Symfony/Component/HttpFoundation/CHANGELOG.md index e1fdf77b9b8ae..d60ebdfe8daaa 100644 --- a/src/Symfony/Component/HttpFoundation/CHANGELOG.md +++ b/src/Symfony/Component/HttpFoundation/CHANGELOG.md @@ -1,6 +1,13 @@ CHANGELOG ========= +3.4.0 +----- + + * deprecated the `NativeSessionHandler` class, + * deprecated the `AbstractProxy`, `NativeProxy` and `SessionHandlerProxy` classes, + * deprecated setting session save handlers that do not implement `\SessionHandlerInterface` in `NativeSessionStorage::setSaveHandler()` + 3.3.0 ----- diff --git a/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/MemcacheSessionHandler.php b/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/MemcacheSessionHandler.php index 4e490a05d4ce0..26a0a17e98ff0 100644 --- a/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/MemcacheSessionHandler.php +++ b/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/MemcacheSessionHandler.php @@ -12,8 +12,6 @@ namespace Symfony\Component\HttpFoundation\Session\Storage\Handler; /** - * MemcacheSessionHandler. - * * @author Drak */ class MemcacheSessionHandler implements \SessionHandlerInterface diff --git a/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/MemcachedSessionHandler.php b/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/MemcachedSessionHandler.php index dfe2fee0d44be..5e9ba7103bdfe 100644 --- a/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/MemcachedSessionHandler.php +++ b/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/MemcachedSessionHandler.php @@ -12,8 +12,6 @@ namespace Symfony\Component\HttpFoundation\Session\Storage\Handler; /** - * MemcachedSessionHandler. - * * Memcached based session storage handler based on the Memcached class * provided by the PHP memcached extension. * diff --git a/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/MongoDbSessionHandler.php b/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/MongoDbSessionHandler.php index 8408f000cdbf8..cfc427bceaed5 100644 --- a/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/MongoDbSessionHandler.php +++ b/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/MongoDbSessionHandler.php @@ -12,8 +12,6 @@ namespace Symfony\Component\HttpFoundation\Session\Storage\Handler; /** - * MongoDB session handler. - * * @author Markus Bachmann */ class MongoDbSessionHandler implements \SessionHandlerInterface diff --git a/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/NativeFileSessionHandler.php b/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/NativeFileSessionHandler.php index 1be0a39837333..4e9704bd5858f 100644 --- a/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/NativeFileSessionHandler.php +++ b/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/NativeFileSessionHandler.php @@ -12,8 +12,6 @@ namespace Symfony\Component\HttpFoundation\Session\Storage\Handler; /** - * NativeFileSessionHandler. - * * Native session handler using PHP's built in file storage. * * @author Drak @@ -21,8 +19,6 @@ class NativeFileSessionHandler extends NativeSessionHandler { /** - * Constructor. - * * @param string $savePath Path of directory to save session files * Default null will leave setting as defined by PHP. * '/path', 'N;/path', or 'N;octal-mode;/path @@ -30,6 +26,7 @@ class NativeFileSessionHandler extends NativeSessionHandler * @see http://php.net/session.configuration.php#ini.session.save-path for further details. * * @throws \InvalidArgumentException On invalid $savePath + * @throws \RuntimeException When failing to create the save directory */ public function __construct($savePath = null) { diff --git a/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/NativeSessionHandler.php b/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/NativeSessionHandler.php index 4ae410f9b9e1f..daa7dbd15b7c8 100644 --- a/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/NativeSessionHandler.php +++ b/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/NativeSessionHandler.php @@ -11,9 +11,10 @@ namespace Symfony\Component\HttpFoundation\Session\Storage\Handler; +@trigger_error('The '.__NAMESPACE__.'\NativeSessionHandler class is deprecated since version 3.4 and will be removed in 4.0. Use the \SessionHandler class instead.', E_USER_DEPRECATED); + /** - * Adds SessionHandler functionality if available. - * + * @deprecated since version 3.4, to be removed in 4.0. Use \SessionHandler instead. * @see http://php.net/sessionhandler */ class NativeSessionHandler extends \SessionHandler diff --git a/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/NullSessionHandler.php b/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/NullSessionHandler.php index 1516d4314a430..981d96d93a978 100644 --- a/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/NullSessionHandler.php +++ b/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/NullSessionHandler.php @@ -12,8 +12,6 @@ namespace Symfony\Component\HttpFoundation\Session\Storage\Handler; /** - * NullSessionHandler. - * * Can be used in unit testing or in a situations where persisted sessions are not desired. * * @author Drak diff --git a/src/Symfony/Component/HttpFoundation/Session/Storage/MetadataBag.php b/src/Symfony/Component/HttpFoundation/Session/Storage/MetadataBag.php index 322dd560f8087..6f59af486981e 100644 --- a/src/Symfony/Component/HttpFoundation/Session/Storage/MetadataBag.php +++ b/src/Symfony/Component/HttpFoundation/Session/Storage/MetadataBag.php @@ -54,8 +54,6 @@ class MetadataBag implements SessionBagInterface private $updateThreshold; /** - * Constructor. - * * @param string $storageKey The key used to store bag in the session * @param int $updateThreshold The time to wait between two UPDATED updates */ diff --git a/src/Symfony/Component/HttpFoundation/Session/Storage/MockArraySessionStorage.php b/src/Symfony/Component/HttpFoundation/Session/Storage/MockArraySessionStorage.php index 348fd23018a03..0349a43367d76 100644 --- a/src/Symfony/Component/HttpFoundation/Session/Storage/MockArraySessionStorage.php +++ b/src/Symfony/Component/HttpFoundation/Session/Storage/MockArraySessionStorage.php @@ -63,8 +63,6 @@ class MockArraySessionStorage implements SessionStorageInterface protected $bags = array(); /** - * Constructor. - * * @param string $name Session name * @param MetadataBag $metaBag MetadataBag instance */ diff --git a/src/Symfony/Component/HttpFoundation/Session/Storage/MockFileSessionStorage.php b/src/Symfony/Component/HttpFoundation/Session/Storage/MockFileSessionStorage.php index 71f9e555121fa..8c1bf73caefb3 100644 --- a/src/Symfony/Component/HttpFoundation/Session/Storage/MockFileSessionStorage.php +++ b/src/Symfony/Component/HttpFoundation/Session/Storage/MockFileSessionStorage.php @@ -30,8 +30,6 @@ class MockFileSessionStorage extends MockArraySessionStorage private $savePath; /** - * Constructor. - * * @param string $savePath Path of directory to save session files * @param string $name Session name * @param MetadataBag $metaBag MetadataBag instance diff --git a/src/Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.php b/src/Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.php index 97161b8d0f8a1..48bef335bae31 100644 --- a/src/Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.php +++ b/src/Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.php @@ -13,7 +13,6 @@ use Symfony\Component\Debug\Exception\ContextErrorException; use Symfony\Component\HttpFoundation\Session\SessionBagInterface; -use Symfony\Component\HttpFoundation\Session\Storage\Handler\NativeSessionHandler; use Symfony\Component\HttpFoundation\Session\Storage\Proxy\AbstractProxy; use Symfony\Component\HttpFoundation\Session\Storage\Proxy\SessionHandlerProxy; @@ -25,8 +24,6 @@ class NativeSessionStorage implements SessionStorageInterface { /** - * Array of SessionBagInterface. - * * @var SessionBagInterface[] */ protected $bags; @@ -42,7 +39,7 @@ class NativeSessionStorage implements SessionStorageInterface protected $closed = false; /** - * @var AbstractProxy + * @var AbstractProxy|\SessionHandlerInterface */ protected $saveHandler; @@ -52,8 +49,6 @@ class NativeSessionStorage implements SessionStorageInterface protected $metadataBag; /** - * Constructor. - * * Depending on how you want the storage driver to behave you probably * want to override this constructor entirely. * @@ -97,9 +92,9 @@ 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 AbstractProxy|NativeSessionHandler|\SessionHandlerInterface|null $handler - * @param MetadataBag $metaBag MetadataBag + * @param array $options Session configuration options + * @param \SessionHandlerInterface|null $handler + * @param MetadataBag $metaBag MetadataBag */ public function __construct(array $options = array(), $handler = null, MetadataBag $metaBag = null) { @@ -116,7 +111,7 @@ public function __construct(array $options = array(), $handler = null, MetadataB /** * Gets the save handler instance. * - * @return AbstractProxy + * @return AbstractProxy|\SessionHandlerInterface */ public function getSaveHandler() { @@ -276,7 +271,7 @@ public function getBag($name) throw new \InvalidArgumentException(sprintf('The SessionBagInterface %s is not registered.', $name)); } - if ($this->saveHandler->isActive() && !$this->started) { + if (!$this->started && $this->saveHandler->isActive()) { $this->loadSession(); } elseif (!$this->started) { $this->start(); @@ -358,7 +353,7 @@ public function setOptions(array $options) * ini_set('session.save_handler', 'files'); * ini_set('session.save_path', '/tmp'); * - * or pass in a NativeSessionHandler instance which configures session.save_handler in the + * or pass in a \SessionHandler instance which configures session.save_handler in the * constructor, for a template see NativeFileSessionHandler or use handlers in * composer package drak/native-session * @@ -367,17 +362,23 @@ public function setOptions(array $options) * @see http://php.net/sessionhandler * @see http://github.com/drak/NativeSession * - * @param AbstractProxy|NativeSessionHandler|\SessionHandlerInterface|null $saveHandler + * @param \SessionHandlerInterface|null $saveHandler * * @throws \InvalidArgumentException */ public function setSaveHandler($saveHandler = null) { if (!$saveHandler instanceof AbstractProxy && - !$saveHandler instanceof NativeSessionHandler && !$saveHandler instanceof \SessionHandlerInterface && null !== $saveHandler) { - throw new \InvalidArgumentException('Must be instance of AbstractProxy or NativeSessionHandler; implement \SessionHandlerInterface; or be null.'); + throw new \InvalidArgumentException('Must be instance of AbstractProxy; implement \SessionHandlerInterface; or be null.'); + } + + if ($saveHandler instanceof AbstractProxy) { + @trigger_error( + 'Using session save handlers that are instances of AbstractProxy is deprecated since version 3.4 and will be removed in 4.0.', + E_USER_DEPRECATED + ); } // Wrap $saveHandler in proxy and prevent double wrapping of proxy diff --git a/src/Symfony/Component/HttpFoundation/Session/Storage/PhpBridgeSessionStorage.php b/src/Symfony/Component/HttpFoundation/Session/Storage/PhpBridgeSessionStorage.php index 6f02a7fd73d23..662ed5015adec 100644 --- a/src/Symfony/Component/HttpFoundation/Session/Storage/PhpBridgeSessionStorage.php +++ b/src/Symfony/Component/HttpFoundation/Session/Storage/PhpBridgeSessionStorage.php @@ -11,9 +11,6 @@ namespace Symfony\Component\HttpFoundation\Session\Storage; -use Symfony\Component\HttpFoundation\Session\Storage\Proxy\AbstractProxy; -use Symfony\Component\HttpFoundation\Session\Storage\Handler\NativeSessionHandler; - /** * Allows session to be started by PHP and managed by Symfony. * @@ -22,10 +19,8 @@ class PhpBridgeSessionStorage extends NativeSessionStorage { /** - * Constructor. - * - * @param AbstractProxy|NativeSessionHandler|\SessionHandlerInterface|null $handler - * @param MetadataBag $metaBag MetadataBag + * @param \SessionHandlerInterface|null $handler + * @param MetadataBag $metaBag MetadataBag */ public function __construct($handler = null, MetadataBag $metaBag = null) { diff --git a/src/Symfony/Component/HttpFoundation/Session/Storage/Proxy/AbstractProxy.php b/src/Symfony/Component/HttpFoundation/Session/Storage/Proxy/AbstractProxy.php index a7478656d672d..c1c8b9b1f7dd2 100644 --- a/src/Symfony/Component/HttpFoundation/Session/Storage/Proxy/AbstractProxy.php +++ b/src/Symfony/Component/HttpFoundation/Session/Storage/Proxy/AbstractProxy.php @@ -11,8 +11,10 @@ namespace Symfony\Component\HttpFoundation\Session\Storage\Proxy; +@trigger_error('The '.__NAMESPACE__.'\AbstractProxy class is deprecated since version 3.4 and will be removed in 4.0. Use your session handler implementation directly.', E_USER_DEPRECATED); + /** - * AbstractProxy. + * @deprecated since version 3.4, to be removed in 4.0. Use your session handler implementation directly. * * @author Drak */ diff --git a/src/Symfony/Component/HttpFoundation/Session/Storage/Proxy/NativeProxy.php b/src/Symfony/Component/HttpFoundation/Session/Storage/Proxy/NativeProxy.php index 0db34aa28d385..e75497d57c3b3 100644 --- a/src/Symfony/Component/HttpFoundation/Session/Storage/Proxy/NativeProxy.php +++ b/src/Symfony/Component/HttpFoundation/Session/Storage/Proxy/NativeProxy.php @@ -11,10 +11,12 @@ namespace Symfony\Component\HttpFoundation\Session\Storage\Proxy; +@trigger_error('The '.__NAMESPACE__.'\NativeProxy class is deprecated since version 3.4 and will be removed in 4.0. Use your session handler implementation directly.', E_USER_DEPRECATED); + /** - * NativeProxy. + * This proxy is built-in session handlers in PHP 5.3.x. * - * This proxy is built-in session handlers in PHP 5.3.x + * @deprecated since version 3.4, to be removed in 4.0. Use your session handler implementation directly. * * @author Drak */ diff --git a/src/Symfony/Component/HttpFoundation/Session/Storage/Proxy/SessionHandlerProxy.php b/src/Symfony/Component/HttpFoundation/Session/Storage/Proxy/SessionHandlerProxy.php index 68ed713c22ffe..d6adef82dbf65 100644 --- a/src/Symfony/Component/HttpFoundation/Session/Storage/Proxy/SessionHandlerProxy.php +++ b/src/Symfony/Component/HttpFoundation/Session/Storage/Proxy/SessionHandlerProxy.php @@ -11,8 +11,10 @@ namespace Symfony\Component\HttpFoundation\Session\Storage\Proxy; +@trigger_error('The '.__NAMESPACE__.'\SessionHandlerProxy class is deprecated since version 3.4 and will be removed in 4.0. Use your session handler implementation directly.', E_USER_DEPRECATED); + /** - * SessionHandler proxy. + * @deprecated since version 3.4, to be removed in 4.0. Use your session handler implementation directly. * * @author Drak */ @@ -23,11 +25,6 @@ class SessionHandlerProxy extends AbstractProxy implements \SessionHandlerInterf */ protected $handler; - /** - * Constructor. - * - * @param \SessionHandlerInterface $handler - */ public function __construct(\SessionHandlerInterface $handler) { $this->handler = $handler; diff --git a/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/NativeSessionHandlerTest.php b/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/NativeSessionHandlerTest.php index 5486b2d655ea8..fe4cc72d23b56 100644 --- a/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/NativeSessionHandlerTest.php +++ b/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/NativeSessionHandlerTest.php @@ -21,6 +21,7 @@ * * @runTestsInSeparateProcesses * @preserveGlobalState disabled + * @group legacy */ class NativeSessionHandlerTest extends TestCase { diff --git a/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Proxy/AbstractProxyTest.php b/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Proxy/AbstractProxyTest.php index ef1da130a2a1a..f2be722c8f522 100644 --- a/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Proxy/AbstractProxyTest.php +++ b/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Proxy/AbstractProxyTest.php @@ -13,43 +13,13 @@ use PHPUnit\Framework\TestCase; use Symfony\Component\HttpFoundation\Session\Storage\Proxy\AbstractProxy; - -// Note until PHPUnit_Mock_Objects 1.2 is released you cannot mock abstracts due to -// https://github.com/sebastianbergmann/phpunit-mock-objects/issues/73 -class ConcreteProxy extends AbstractProxy -{ -} - -class ConcreteSessionHandlerInterfaceProxy extends AbstractProxy implements \SessionHandlerInterface -{ - public function open($savePath, $sessionName) - { - } - - public function close() - { - } - - public function read($id) - { - } - - public function write($id, $data) - { - } - - public function destroy($id) - { - } - - public function gc($maxlifetime) - { - } -} +use Symfony\Component\HttpFoundation\Session\Storage\Proxy\SessionHandlerProxy; /** * Test class for AbstractProxy. * + * @group legacy + * * @author Drak */ class AbstractProxyTest extends TestCase @@ -61,7 +31,7 @@ class AbstractProxyTest extends TestCase protected function setUp() { - $this->proxy = new ConcreteProxy(); + $this->proxy = $this->getMockForAbstractClass(AbstractProxy::class); } protected function tearDown() @@ -77,7 +47,7 @@ public function testGetSaveHandlerName() public function testIsSessionHandlerInterface() { $this->assertFalse($this->proxy->isSessionHandlerInterface()); - $sh = new ConcreteSessionHandlerInterfaceProxy(); + $sh = new SessionHandlerProxy(new \SessionHandler()); $this->assertTrue($sh->isSessionHandlerInterface()); } diff --git a/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Proxy/NativeProxyTest.php b/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Proxy/NativeProxyTest.php index 8ec3053441366..ed4fee6bfec0f 100644 --- a/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Proxy/NativeProxyTest.php +++ b/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Proxy/NativeProxyTest.php @@ -17,6 +17,8 @@ /** * Test class for NativeProxy. * + * @group legacy + * * @author Drak */ class NativeProxyTest extends TestCase diff --git a/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Proxy/SessionHandlerProxyTest.php b/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Proxy/SessionHandlerProxyTest.php index 682825356a724..fdd1dae254198 100644 --- a/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Proxy/SessionHandlerProxyTest.php +++ b/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Proxy/SessionHandlerProxyTest.php @@ -21,6 +21,7 @@ * * @runTestsInSeparateProcesses * @preserveGlobalState disabled + * @group legacy */ class SessionHandlerProxyTest extends TestCase { From 685c3538fbf7584ad10d4b639d95572af06bfa08 Mon Sep 17 00:00:00 2001 From: Matthias Pigulla Date: Sun, 30 Apr 2017 17:08:55 +0200 Subject: [PATCH 0902/1099] Extract method refactoring for ResourceCheckerConfigCache --- .../Config/ResourceCheckerConfigCache.php | 54 +++++++++++-------- 1 file changed, 32 insertions(+), 22 deletions(-) diff --git a/src/Symfony/Component/Config/ResourceCheckerConfigCache.php b/src/Symfony/Component/Config/ResourceCheckerConfigCache.php index c0aef1d8f9560..421db6408af91 100644 --- a/src/Symfony/Component/Config/ResourceCheckerConfigCache.php +++ b/src/Symfony/Component/Config/ResourceCheckerConfigCache.php @@ -73,37 +73,19 @@ public function isFresh() } $metadata = $this->getMetaFile(); + if (!is_file($metadata)) { return false; } - $e = null; - $meta = false; - $time = filemtime($this->file); - $signalingException = new \UnexpectedValueException(); - $prevUnserializeHandler = ini_set('unserialize_callback_func', ''); - $prevErrorHandler = set_error_handler(function ($type, $msg, $file, $line, $context) use (&$prevErrorHandler, $signalingException) { - if (E_WARNING === $type && 'Class __PHP_Incomplete_Class has no unserializer' === $msg) { - throw $signalingException; - } - - return $prevErrorHandler ? $prevErrorHandler($type, $msg, $file, $line, $context) : false; - }); + $meta = $this->safelyUnserialize($metadata); - try { - $meta = unserialize(file_get_contents($metadata)); - } catch (\Error $e) { - } catch (\Exception $e) { - } - restore_error_handler(); - ini_set('unserialize_callback_func', $prevUnserializeHandler); - if (null !== $e && $e !== $signalingException) { - throw $e; - } if (false === $meta) { return false; } + $time = filemtime($this->file); + foreach ($meta as $resource) { /* @var ResourceInterface $resource */ foreach ($this->resourceCheckers as $checker) { @@ -161,4 +143,32 @@ private function getMetaFile() { return $this->file.'.meta'; } + + private function safelyUnserialize($file) + { + $e = null; + $meta = false; + $signalingException = new \UnexpectedValueException(); + $prevUnserializeHandler = ini_set('unserialize_callback_func', ''); + $prevErrorHandler = set_error_handler(function ($type, $msg, $file, $line, $context) use (&$prevErrorHandler, $signalingException) { + if (E_WARNING === $type && 'Class __PHP_Incomplete_Class has no unserializer' === $msg) { + throw $signalingException; + } + + return $prevErrorHandler ? $prevErrorHandler($type, $msg, $file, $line, $context) : false; + }); + + try { + $meta = unserialize(file_get_contents($file)); + } catch (\Error $e) { + } catch (\Exception $e) { + } + restore_error_handler(); + ini_set('unserialize_callback_func', $prevUnserializeHandler); + if (null !== $e && $e !== $signalingException) { + throw $e; + } + + return $meta; + } } From 4812e6054c14994eab0513d6dc4ba108c2d0f156 Mon Sep 17 00:00:00 2001 From: Kevin Bond Date: Wed, 24 May 2017 11:00:21 -0400 Subject: [PATCH 0903/1099] add ability to configure catching exceptions --- src/Symfony/Component/HttpKernel/CHANGELOG.md | 1 + src/Symfony/Component/HttpKernel/Client.php | 13 ++++++++++++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/HttpKernel/CHANGELOG.md b/src/Symfony/Component/HttpKernel/CHANGELOG.md index 8732b17dd83f5..66e3b38e25ce6 100644 --- a/src/Symfony/Component/HttpKernel/CHANGELOG.md +++ b/src/Symfony/Component/HttpKernel/CHANGELOG.md @@ -11,6 +11,7 @@ CHANGELOG * added `AddCacheClearerPass` * added `AddCacheWarmerPass` * deprecated `EnvParametersResource` + * added `Symfony\Component\HttpKernel\Client::catchExceptions()` 3.3.0 ----- diff --git a/src/Symfony/Component/HttpKernel/Client.php b/src/Symfony/Component/HttpKernel/Client.php index 94f70cd6f7a02..4a86564c9f9f2 100644 --- a/src/Symfony/Component/HttpKernel/Client.php +++ b/src/Symfony/Component/HttpKernel/Client.php @@ -31,6 +31,7 @@ class Client extends BaseClient { protected $kernel; + private $catchExceptions = true; /** * Constructor. @@ -49,6 +50,16 @@ public function __construct(HttpKernelInterface $kernel, array $server = array() parent::__construct($server, $history, $cookieJar); } + /** + * Sets whether to catch exceptions when the kernel is handling a request. + * + * @param bool $catchExceptions Whether to catch exceptions + */ + public function catchExceptions($catchExceptions) + { + $this->catchExceptions = $catchExceptions; + } + /** * Makes a request. * @@ -58,7 +69,7 @@ public function __construct(HttpKernelInterface $kernel, array $server = array() */ protected function doRequest($request) { - $response = $this->kernel->handle($request); + $response = $this->kernel->handle($request, HttpKernelInterface::MASTER_REQUEST, $this->catchExceptions); if ($this->kernel instanceof TerminableInterface) { $this->kernel->terminate($request, $response); From 24dcb5202c898e0c6f1a97cca53b6863bb43ca7c Mon Sep 17 00:00:00 2001 From: Craig Duncan Date: Mon, 10 Jul 2017 22:30:02 +0100 Subject: [PATCH 0904/1099] Add a method to check if any results were found --- src/Symfony/Component/Finder/CHANGELOG.md | 1 + src/Symfony/Component/Finder/Finder.php | 14 ++++++++++++++ src/Symfony/Component/Finder/Tests/FinderTest.php | 14 ++++++++++++++ 3 files changed, 29 insertions(+) diff --git a/src/Symfony/Component/Finder/CHANGELOG.md b/src/Symfony/Component/Finder/CHANGELOG.md index 1c6419658bff5..53c34be860c56 100644 --- a/src/Symfony/Component/Finder/CHANGELOG.md +++ b/src/Symfony/Component/Finder/CHANGELOG.md @@ -5,6 +5,7 @@ CHANGELOG ----- * deprecated `Symfony\Component\Finder\Iterator\FilterIterator` + * added Finder::hasResults() method to check if any results were found 3.3.0 ----- diff --git a/src/Symfony/Component/Finder/Finder.php b/src/Symfony/Component/Finder/Finder.php index 9a1b31a1ae861..8ea457ddeb0a9 100644 --- a/src/Symfony/Component/Finder/Finder.php +++ b/src/Symfony/Component/Finder/Finder.php @@ -613,6 +613,20 @@ public function append($iterator) return $this; } + /** + * Check if the any results were found. + * + * @return bool + */ + public function hasResults() + { + foreach ($this->getIterator() as $_) { + return true; + } + + return false; + } + /** * Counts all the results collected by the iterators. * diff --git a/src/Symfony/Component/Finder/Tests/FinderTest.php b/src/Symfony/Component/Finder/Tests/FinderTest.php index f4050d1f765e1..7e75f14128a99 100644 --- a/src/Symfony/Component/Finder/Tests/FinderTest.php +++ b/src/Symfony/Component/Finder/Tests/FinderTest.php @@ -424,6 +424,20 @@ public function testCountWithoutIn() count($finder); } + public function testHasResults() + { + $finder = $this->buildFinder(); + $finder->in(__DIR__); + $this->assertTrue($finder->hasResults()); + } + + public function testNoResults() + { + $finder = $this->buildFinder(); + $finder->in(__DIR__)->name('DoesNotExist'); + $this->assertFalse($finder->hasResults()); + } + /** * @dataProvider getContainsTestData */ From ab47c7878ed9fc20884b10bc522fd07cf3369e48 Mon Sep 17 00:00:00 2001 From: Tim Jabs Date: Tue, 26 Sep 2017 17:16:57 +0200 Subject: [PATCH 0905/1099] Added improvement for accuracy in MoneyToLocalizedStringTransformer. --- .../MoneyToLocalizedStringTransformer.php | 10 ++++------ .../MoneyToLocalizedStringTransformerTest.php | 8 ++++++++ 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/src/Symfony/Component/Form/Extension/Core/DataTransformer/MoneyToLocalizedStringTransformer.php b/src/Symfony/Component/Form/Extension/Core/DataTransformer/MoneyToLocalizedStringTransformer.php index 5993c01cb0da9..7449fedfc69cc 100644 --- a/src/Symfony/Component/Form/Extension/Core/DataTransformer/MoneyToLocalizedStringTransformer.php +++ b/src/Symfony/Component/Form/Extension/Core/DataTransformer/MoneyToLocalizedStringTransformer.php @@ -54,12 +54,11 @@ public function __construct($scale = 2, $grouping = true, $roundingMode = self:: */ public function transform($value) { - if (null !== $value) { + if (null !== $value && 1 !== $this->divisor) { if (!is_numeric($value)) { throw new TransformationFailedException('Expected a numeric.'); } - - $value /= $this->divisor; + $value = (string) ($value / $this->divisor); } return parent::transform($value); @@ -78,9 +77,8 @@ public function transform($value) public function reverseTransform($value) { $value = parent::reverseTransform($value); - - if (null !== $value) { - $value *= $this->divisor; + if (null !== $value && 1 !== $this->divisor) { + $value = (float) (string) ($value * $this->divisor); } return $value; diff --git a/src/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/MoneyToLocalizedStringTransformerTest.php b/src/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/MoneyToLocalizedStringTransformerTest.php index 68face130b535..1ad3aa1615c98 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/MoneyToLocalizedStringTransformerTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/MoneyToLocalizedStringTransformerTest.php @@ -72,4 +72,12 @@ public function testReverseTransformEmpty() $this->assertNull($transformer->reverseTransform('')); } + + public function testFloatToIntConversionMismatchOnReversTransform() + { + $transformer = new MoneyToLocalizedStringTransformer(null, null, null, 100); + IntlTestHelper::requireFullIntl($this, false); + \Locale::setDefault('de_AT'); + $this->assertSame(3655, (int) $transformer->reverseTransform('36,55')); + } } From fba7e543d17833453f0c7b53d57e46338c6d489a Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Tue, 26 Sep 2017 19:24:24 +0200 Subject: [PATCH 0906/1099] added foward compatibility for the removal of bundle inheritance in 4.0 --- .../Controller/ControllerNameParser.php | 5 +++++ .../Command/TranslationDebugCommandTest.php | 16 ++++++++++++---- .../Command/TranslationUpdateCommandTest.php | 15 +++++++++++---- .../Controller/ControllerNameParserTest.php | 14 +++++++++++--- .../DependencyInjection/TwigExtension.php | 2 +- 5 files changed, 40 insertions(+), 12 deletions(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/Controller/ControllerNameParser.php b/src/Symfony/Bundle/FrameworkBundle/Controller/ControllerNameParser.php index 323c5122a531f..cf1ebdc128e42 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Controller/ControllerNameParser.php +++ b/src/Symfony/Bundle/FrameworkBundle/Controller/ControllerNameParser.php @@ -73,6 +73,11 @@ public function parse($controller) throw new \InvalidArgumentException($message, 0, $e); } + if (!is_array($allBundles)) { + // happens when HttpKernel is version 4+ + $allBundles = array($allBundles); + } + foreach ($allBundles as $b) { $try = $b->getNamespace().'\\Controller\\'.$controller.'Controller'; if (class_exists($try)) { diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/TranslationDebugCommandTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/TranslationDebugCommandTest.php index 55ed4c7449f27..7e516c7cc5589 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/TranslationDebugCommandTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/TranslationDebugCommandTest.php @@ -16,6 +16,7 @@ use Symfony\Component\Console\Tester\CommandTester; use Symfony\Bundle\FrameworkBundle\Command\TranslationDebugCommand; use Symfony\Component\Filesystem\Filesystem; +use Symfony\Component\HttpKernel; class TranslationDebugCommandTest extends TestCase { @@ -141,14 +142,21 @@ private function createCommandTester($extractedMessages = array(), $loadedMessag ); if (null === $kernel) { + $returnValues = array( + array('foo', $this->getBundle($this->translationDir)), + array('test', $this->getBundle('test')), + ); + if (HttpKernel\Kernel::VERSION_ID < 40000) { + $returnValues = array( + array('foo', true, $this->getBundle($this->translationDir)), + array('test', true, $this->getBundle('test')), + ); + } $kernel = $this->getMockBuilder('Symfony\Component\HttpKernel\KernelInterface')->getMock(); $kernel ->expects($this->any()) ->method('getBundle') - ->will($this->returnValueMap(array( - array('foo', true, $this->getBundle($this->translationDir)), - array('test', true, $this->getBundle('test')), - ))); + ->will($this->returnValueMap($returnValues)); } $kernel diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/TranslationUpdateCommandTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/TranslationUpdateCommandTest.php index c7c93d533a301..2cb8e0e2593d9 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/TranslationUpdateCommandTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/TranslationUpdateCommandTest.php @@ -120,14 +120,21 @@ private function createCommandTester($extractedMessages = array(), $loadedMessag ); if (null === $kernel) { + $returnValues = array( + array('foo', $this->getBundle($this->translationDir)), + array('test', $this->getBundle('test')), + ); + if (HttpKernel\Kernel::VERSION_ID < 40000) { + $returnValues = array( + array('foo', true, $this->getBundle($this->translationDir)), + array('test', true, $this->getBundle('test')), + ); + } $kernel = $this->getMockBuilder('Symfony\Component\HttpKernel\KernelInterface')->getMock(); $kernel ->expects($this->any()) ->method('getBundle') - ->will($this->returnValueMap(array( - array('foo', true, $this->getBundle($this->translationDir)), - array('test', true, $this->getBundle('test')), - ))); + ->will($this->returnValueMap($returnValues)); } $kernel diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/ControllerNameParserTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/ControllerNameParserTest.php index 57eaf269f4424..efe72b5b8029f 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/ControllerNameParserTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/ControllerNameParserTest.php @@ -14,6 +14,7 @@ use Composer\Autoload\ClassLoader; use Symfony\Bundle\FrameworkBundle\Tests\TestCase; use Symfony\Bundle\FrameworkBundle\Controller\ControllerNameParser; +use Symfony\Component\HttpKernel\Kernel; class ControllerNameParserTest extends TestCase { @@ -98,10 +99,17 @@ public function testMissingControllers($name) public function getMissingControllersTest() { - return array( - array('FooBundle:Fake:index'), // a normal bundle - array('SensioFooBundle:Fake:index'), // a bundle with children + // a normal bundle + $bundles = array( + array('FooBundle:Fake:index'), ); + + // a bundle with children + if (Kernel::VERSION_ID < 40000) { + $bundles[] = array('SensioFooBundle:Fake:index'); + } + + return $bundles; } /** diff --git a/src/Symfony/Bundle/TwigBundle/DependencyInjection/TwigExtension.php b/src/Symfony/Bundle/TwigBundle/DependencyInjection/TwigExtension.php index d4450f531c322..262594a5f4768 100644 --- a/src/Symfony/Bundle/TwigBundle/DependencyInjection/TwigExtension.php +++ b/src/Symfony/Bundle/TwigBundle/DependencyInjection/TwigExtension.php @@ -214,7 +214,7 @@ private function getBundleHierarchy(ContainerBuilder $container, array $config) } $container->addResource(new FileExistenceResource($dir)); - if (null === $bundle['parent']) { + if (!isset($bundle['parent']) || null === $bundle['parent']) { continue; } From 11fe79d77fb4ebae8cf77c0a4ce09d20fa363df9 Mon Sep 17 00:00:00 2001 From: Maxime Steinhausser Date: Tue, 26 Sep 2017 19:05:58 +0200 Subject: [PATCH 0907/1099] [Security][SecurityBundle] Deprecate the HTTP digest auth --- UPGRADE-3.4.md | 10 ++ UPGRADE-4.0.md | 7 + .../Bundle/SecurityBundle/CHANGELOG.md | 1 + .../Security/Factory/HttpDigestFactory.php | 10 ++ .../Bundle/SecurityBundle/SecurityBundle.php | 2 +- .../CompleteConfigurationTest.php | 125 ++++++++++++++++++ .../Fixtures/php/container1.php | 1 - .../Fixtures/php/container1_with_digest.php | 105 +++++++++++++++ .../Fixtures/php/no_custom_user_checker.php | 1 - .../Fixtures/xml/container1.xml | 1 - .../Fixtures/xml/container1_with_digest.xml | 82 ++++++++++++ .../Fixtures/xml/no_custom_user_checker.xml | 1 - .../Fixtures/yml/container1.yml | 2 - .../Fixtures/yml/container1_with_digest.yml | 85 ++++++++++++ .../Fixtures/yml/no_custom_user_checker.yml | 2 - src/Symfony/Component/Security/CHANGELOG.md | 1 + .../Core/Exception/NonceExpiredException.php | 4 + .../DigestAuthenticationEntryPoint.php | 4 + .../Firewall/DigestAuthenticationListener.php | 9 ++ .../DigestAuthenticationEntryPointTest.php | 3 + .../DigestAuthenticationListenerTest.php | 3 + .../Http/Tests/Firewall/DigestDataTest.php | 3 + 22 files changed, 453 insertions(+), 9 deletions(-) create mode 100644 src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/container1_with_digest.php create mode 100644 src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/container1_with_digest.xml create mode 100644 src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/container1_with_digest.yml diff --git a/UPGRADE-3.4.md b/UPGRADE-3.4.md index 44afe9be5dc63..8edd0e1ba67b6 100644 --- a/UPGRADE-3.4.md +++ b/UPGRADE-3.4.md @@ -252,6 +252,13 @@ Profiler * The `profiler.matcher` option has been deprecated. +Security +-------- + + * Deprecated the HTTP digest authentication: `NonceExpiredException`, + `DigestAuthenticationListener` and `DigestAuthenticationEntryPoint` will be + removed in 4.0. Use another authentication system like `http_basic` instead. + SecurityBundle -------------- @@ -272,6 +279,9 @@ SecurityBundle * Added `logout_on_user_change` to the firewall options. This config item will trigger a logout when the user has changed. Should be set to true to avoid deprecations in the configuration. + + * Deprecated the HTTP digest authentication: `HttpDigestFactory` will be removed in 4.0. + Use another authentication system like `http_basic` instead. Translation ----------- diff --git a/UPGRADE-4.0.md b/UPGRADE-4.0.md index 2fc980b92fafc..e7774c1f9e83b 100644 --- a/UPGRADE-4.0.md +++ b/UPGRADE-4.0.md @@ -645,6 +645,10 @@ Security * Calling `ContextListener::setLogoutOnUserChange(false)` won't have any effect anymore. + * Removed the HTTP digest authentication system. The `NonceExpiredException`, + `DigestAuthenticationListener` and `DigestAuthenticationEntryPoint` classes + have been removed. Use another authentication system like `http_basic` instead. + SecurityBundle -------------- @@ -665,6 +669,9 @@ SecurityBundle * The firewall option `logout_on_user_change` is now always true, which will trigger a logout if the user changes between requests. + + * Removed the HTTP digest authentication system. The `HttpDigestFactory` class + has been removed. Use another authentication system like `http_basic` instead. Serializer ---------- diff --git a/src/Symfony/Bundle/SecurityBundle/CHANGELOG.md b/src/Symfony/Bundle/SecurityBundle/CHANGELOG.md index b60e2e7e882e0..7b8647081163d 100644 --- a/src/Symfony/Bundle/SecurityBundle/CHANGELOG.md +++ b/src/Symfony/Bundle/SecurityBundle/CHANGELOG.md @@ -16,6 +16,7 @@ CHANGELOG * Added `logout_on_user_change` to the firewall options. This config item will trigger a logout when the user has changed. Should be set to true to avoid deprecations in the configuration. + * deprecated HTTP digest authentication 3.3.0 ----- diff --git a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/HttpDigestFactory.php b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/HttpDigestFactory.php index bedc87864c235..8d764795c1b64 100644 --- a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/HttpDigestFactory.php +++ b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/HttpDigestFactory.php @@ -20,9 +20,18 @@ * HttpDigestFactory creates services for HTTP digest authentication. * * @author Fabien Potencier + * + * @deprecated since 3.4, to be removed in 4.0 */ class HttpDigestFactory implements SecurityFactoryInterface { + public function __construct($triggerDeprecation = true) + { + if ($triggerDeprecation) { + @trigger_error(sprintf('The %s class and the whole HTTP digest authentication system is deprecated since 3.4 and will be removed in 4.0.', __CLASS__), E_USER_DEPRECATED); + } + } + public function create(ContainerBuilder $container, $id, $config, $userProvider, $defaultEntryPoint) { $provider = 'security.authentication.provider.dao.'.$id; @@ -59,6 +68,7 @@ public function getKey() public function addConfiguration(NodeDefinition $node) { $node + ->setDeprecated('The HTTP digest authentication is deprecated since 3.4 and will be removed in 4.0.') ->children() ->scalarNode('provider')->end() ->scalarNode('realm')->defaultValue('Secured Area')->end() diff --git a/src/Symfony/Bundle/SecurityBundle/SecurityBundle.php b/src/Symfony/Bundle/SecurityBundle/SecurityBundle.php index 3b8f6dda85580..4f17e12236659 100644 --- a/src/Symfony/Bundle/SecurityBundle/SecurityBundle.php +++ b/src/Symfony/Bundle/SecurityBundle/SecurityBundle.php @@ -47,7 +47,7 @@ public function build(ContainerBuilder $container) $extension->addSecurityListenerFactory(new JsonLoginFactory()); $extension->addSecurityListenerFactory(new HttpBasicFactory()); $extension->addSecurityListenerFactory(new HttpBasicLdapFactory()); - $extension->addSecurityListenerFactory(new HttpDigestFactory()); + $extension->addSecurityListenerFactory(new HttpDigestFactory(false)); $extension->addSecurityListenerFactory(new RememberMeFactory()); $extension->addSecurityListenerFactory(new X509Factory()); $extension->addSecurityListenerFactory(new RemoteUserFactory()); diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/CompleteConfigurationTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/CompleteConfigurationTest.php index c7451496d48c2..9a461285f5e0f 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/CompleteConfigurationTest.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/CompleteConfigurationTest.php @@ -86,6 +86,131 @@ public function testFirewalls() $configs[0][2] = strtolower($configs[0][2]); $configs[2][2] = strtolower($configs[2][2]); + $this->assertEquals(array( + array( + 'simple', + 'security.user_checker', + 'security.request_matcher.6tndozi', + false, + ), + array( + 'secure', + 'security.user_checker', + null, + true, + true, + 'security.user.provider.concrete.default', + null, + 'security.authentication.form_entry_point.secure', + null, + null, + array( + 'logout', + 'switch_user', + 'x509', + 'remote_user', + 'form_login', + 'http_basic', + 'remember_me', + 'anonymous', + ), + array( + 'parameter' => '_switch_user', + 'role' => 'ROLE_ALLOWED_TO_SWITCH', + ), + ), + array( + 'host', + 'security.user_checker', + 'security.request_matcher.and0kk1', + true, + false, + 'security.user.provider.concrete.default', + 'host', + 'security.authentication.basic_entry_point.host', + null, + null, + array( + 'http_basic', + 'anonymous', + ), + null, + ), + array( + 'with_user_checker', + 'app.user_checker', + null, + true, + false, + 'security.user.provider.concrete.default', + 'with_user_checker', + 'security.authentication.basic_entry_point.with_user_checker', + null, + null, + array( + 'http_basic', + 'anonymous', + ), + null, + ), + ), $configs); + + $this->assertEquals(array( + array(), + array( + 'security.channel_listener', + 'security.logout_listener.secure', + 'security.authentication.listener.x509.secure', + 'security.authentication.listener.remote_user.secure', + 'security.authentication.listener.form.secure', + 'security.authentication.listener.basic.secure', + 'security.authentication.listener.rememberme.secure', + 'security.authentication.listener.anonymous.secure', + 'security.authentication.switchuser_listener.secure', + 'security.access_listener', + ), + array( + 'security.channel_listener', + 'security.context_listener.0', + 'security.authentication.listener.basic.host', + 'security.authentication.listener.anonymous.host', + 'security.access_listener', + ), + array( + 'security.channel_listener', + 'security.context_listener.1', + 'security.authentication.listener.basic.with_user_checker', + 'security.authentication.listener.anonymous.with_user_checker', + 'security.access_listener', + ), + ), $listeners); + + $this->assertFalse($container->hasAlias('Symfony\Component\Security\Core\User\UserCheckerInterface', 'No user checker alias is registered when custom user checker services are registered')); + } + + /** + * @group legacy + */ + public function testFirewallsWithDigest() + { + $container = $this->getContainer('container1_with_digest'); + $arguments = $container->getDefinition('security.firewall.map')->getArguments(); + $listeners = array(); + $configs = array(); + foreach (array_keys($arguments[1]->getValues()) as $contextId) { + $contextDef = $container->getDefinition($contextId); + $arguments = $contextDef->getArguments(); + $listeners[] = array_map('strval', $arguments['index_0']->getValues()); + + $configDef = $container->getDefinition((string) $arguments['index_2']); + $configs[] = array_values($configDef->getArguments()); + } + + // the IDs of the services are case sensitive or insensitive depending on + // the Symfony version. Transform them to lowercase to simplify tests. + $configs[0][2] = strtolower($configs[0][2]); + $configs[2][2] = strtolower($configs[2][2]); + $this->assertEquals(array( array( 'simple', diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/container1.php b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/container1.php index 581407fcc05a5..3748f05012b87 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/container1.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/container1.php @@ -64,7 +64,6 @@ 'simple' => array('pattern' => '/login', 'security' => false), 'secure' => array('stateless' => true, 'http_basic' => true, - 'http_digest' => array('secret' => 'TheSecret'), 'form_login' => true, 'anonymous' => true, 'switch_user' => true, diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/container1_with_digest.php b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/container1_with_digest.php new file mode 100644 index 0000000000000..581407fcc05a5 --- /dev/null +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/container1_with_digest.php @@ -0,0 +1,105 @@ +loadFromExtension('security', array( + 'acl' => array(), + 'encoders' => array( + 'JMS\FooBundle\Entity\User1' => 'plaintext', + 'JMS\FooBundle\Entity\User2' => array( + 'algorithm' => 'sha1', + 'encode_as_base64' => false, + 'iterations' => 5, + ), + 'JMS\FooBundle\Entity\User3' => array( + 'algorithm' => 'md5', + ), + 'JMS\FooBundle\Entity\User4' => array( + 'id' => 'security.encoder.foo', + ), + 'JMS\FooBundle\Entity\User5' => array( + 'algorithm' => 'pbkdf2', + 'hash_algorithm' => 'sha1', + 'encode_as_base64' => false, + 'iterations' => 5, + 'key_length' => 30, + ), + 'JMS\FooBundle\Entity\User6' => array( + 'algorithm' => 'bcrypt', + 'cost' => 15, + ), + ), + 'providers' => array( + 'default' => array( + 'memory' => array( + 'users' => array( + 'foo' => array('password' => 'foo', 'roles' => 'ROLE_USER'), + ), + ), + ), + 'digest' => array( + 'memory' => array( + 'users' => array( + 'foo' => array('password' => 'foo', 'roles' => 'ROLE_USER, ROLE_ADMIN'), + ), + ), + ), + 'basic' => array( + 'memory' => array( + 'users' => array( + 'foo' => array('password' => '0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33', 'roles' => 'ROLE_SUPER_ADMIN'), + 'bar' => array('password' => '0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33', 'roles' => array('ROLE_USER', 'ROLE_ADMIN')), + ), + ), + ), + 'service' => array( + 'id' => 'user.manager', + ), + 'chain' => array( + 'chain' => array( + 'providers' => array('service', 'basic'), + ), + ), + ), + + 'firewalls' => array( + 'simple' => array('pattern' => '/login', 'security' => false), + 'secure' => array('stateless' => true, + 'http_basic' => true, + 'http_digest' => array('secret' => 'TheSecret'), + 'form_login' => true, + 'anonymous' => true, + 'switch_user' => true, + 'x509' => true, + 'remote_user' => true, + 'logout' => true, + 'remember_me' => array('secret' => 'TheSecret'), + 'user_checker' => null, + 'logout_on_user_change' => true, + ), + 'host' => array( + 'pattern' => '/test', + 'host' => 'foo\\.example\\.org', + 'methods' => array('GET', 'POST'), + 'anonymous' => true, + 'http_basic' => true, + 'logout_on_user_change' => true, + ), + 'with_user_checker' => array( + 'user_checker' => 'app.user_checker', + 'anonymous' => true, + 'http_basic' => true, + 'logout_on_user_change' => true, + ), + ), + + 'access_control' => array( + array('path' => '/blog/524', 'role' => 'ROLE_USER', 'requires_channel' => 'https', 'methods' => array('get', 'POST')), + array('path' => '/blog/.*', 'role' => 'IS_AUTHENTICATED_ANONYMOUSLY'), + array('path' => '/blog/524', 'role' => 'IS_AUTHENTICATED_ANONYMOUSLY', 'allow_if' => "token.getUsername() matches '/^admin/'"), + ), + + 'role_hierarchy' => array( + 'ROLE_ADMIN' => 'ROLE_USER', + 'ROLE_SUPER_ADMIN' => array('ROLE_USER', 'ROLE_ADMIN', 'ROLE_ALLOWED_TO_SWITCH'), + 'ROLE_REMOTE' => 'ROLE_USER,ROLE_ADMIN', + ), +)); diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/no_custom_user_checker.php b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/no_custom_user_checker.php index 91c475418b450..3889752f8f928 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/no_custom_user_checker.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/no_custom_user_checker.php @@ -15,7 +15,6 @@ 'secure' => array( 'stateless' => true, 'http_basic' => true, - 'http_digest' => array('secret' => 'TheSecret'), 'form_login' => true, 'anonymous' => true, 'switch_user' => true, diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/container1.xml b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/container1.xml index e5049f2033e51..05c31e1854c93 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/container1.xml +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/container1.xml @@ -49,7 +49,6 @@ - diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/container1_with_digest.xml b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/container1_with_digest.xml new file mode 100644 index 0000000000000..e5049f2033e51 --- /dev/null +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/container1_with_digest.xml @@ -0,0 +1,82 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + app.user_checker + + + ROLE_USER + ROLE_USER,ROLE_ADMIN,ROLE_ALLOWED_TO_SWITCH + ROLE_USER,ROLE_ADMIN + + + + + + diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/no_custom_user_checker.xml b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/no_custom_user_checker.xml index 7d648ae1baec2..b97d39adb5a78 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/no_custom_user_checker.xml +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/no_custom_user_checker.xml @@ -15,7 +15,6 @@ - diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/container1.yml b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/container1.yml index a2b57201bfbd2..b016adb851e98 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/container1.yml +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/container1.yml @@ -46,8 +46,6 @@ security: secure: stateless: true http_basic: true - http_digest: - secret: TheSecret form_login: true anonymous: true switch_user: true diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/container1_with_digest.yml b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/container1_with_digest.yml new file mode 100644 index 0000000000000..a2b57201bfbd2 --- /dev/null +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/container1_with_digest.yml @@ -0,0 +1,85 @@ +security: + acl: ~ + encoders: + JMS\FooBundle\Entity\User1: plaintext + JMS\FooBundle\Entity\User2: + algorithm: sha1 + encode_as_base64: false + iterations: 5 + JMS\FooBundle\Entity\User3: + algorithm: md5 + JMS\FooBundle\Entity\User4: + id: security.encoder.foo + JMS\FooBundle\Entity\User5: + algorithm: pbkdf2 + hash_algorithm: sha1 + encode_as_base64: false + iterations: 5 + key_length: 30 + JMS\FooBundle\Entity\User6: + algorithm: bcrypt + cost: 15 + + providers: + default: + memory: + users: + foo: { password: foo, roles: ROLE_USER } + digest: + memory: + users: + foo: { password: foo, roles: 'ROLE_USER, ROLE_ADMIN' } + basic: + memory: + users: + foo: { password: 0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33, roles: ROLE_SUPER_ADMIN } + bar: { password: 0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33, roles: [ROLE_USER, ROLE_ADMIN] } + service: + id: user.manager + chain: + chain: + providers: [service, basic] + + + firewalls: + simple: { pattern: /login, security: false } + secure: + stateless: true + http_basic: true + http_digest: + secret: TheSecret + form_login: true + anonymous: true + switch_user: true + x509: true + remote_user: true + logout: true + remember_me: + secret: TheSecret + user_checker: ~ + + host: + pattern: /test + host: foo\.example\.org + methods: [GET,POST] + anonymous: true + http_basic: true + logout_on_user_change: true + + with_user_checker: + anonymous: ~ + http_basic: ~ + user_checker: app.user_checker + logout_on_user_change: true + + role_hierarchy: + ROLE_ADMIN: ROLE_USER + ROLE_SUPER_ADMIN: [ROLE_USER, ROLE_ADMIN, ROLE_ALLOWED_TO_SWITCH] + ROLE_REMOTE: ROLE_USER,ROLE_ADMIN + + access_control: + - { path: /blog/524, role: ROLE_USER, requires_channel: https, methods: [get, POST]} + - + path: /blog/.* + role: IS_AUTHENTICATED_ANONYMOUSLY + - { path: /blog/524, role: IS_AUTHENTICATED_ANONYMOUSLY, allow_if: "token.getUsername() matches '/^admin/'" } diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/no_custom_user_checker.yml b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/no_custom_user_checker.yml index 23afa8cd9b3c5..6a196597c51e7 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/no_custom_user_checker.yml +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/no_custom_user_checker.yml @@ -10,8 +10,6 @@ security: secure: stateless: true http_basic: true - http_digest: - secret: TheSecret form_login: true anonymous: true switch_user: true diff --git a/src/Symfony/Component/Security/CHANGELOG.md b/src/Symfony/Component/Security/CHANGELOG.md index 99032dae9da9b..a48ee0cd871e9 100644 --- a/src/Symfony/Component/Security/CHANGELOG.md +++ b/src/Symfony/Component/Security/CHANGELOG.md @@ -10,6 +10,7 @@ CHANGELOG property will trigger a deprecation when the user has changed. As of 4.0 the user will always be logged out when the user has changed between requests. + * deprecated HTTP digest authentication 3.3.0 ----- diff --git a/src/Symfony/Component/Security/Core/Exception/NonceExpiredException.php b/src/Symfony/Component/Security/Core/Exception/NonceExpiredException.php index 998e987e403de..bc03a03ac70d4 100644 --- a/src/Symfony/Component/Security/Core/Exception/NonceExpiredException.php +++ b/src/Symfony/Component/Security/Core/Exception/NonceExpiredException.php @@ -11,12 +11,16 @@ namespace Symfony\Component\Security\Core\Exception; +@trigger_error(sprintf('The %s class and the whole HTTP digest authentication system is deprecated since 3.4 and will be removed in 4.0.', NonceExpiredException::class), E_USER_DEPRECATED); + /** * NonceExpiredException is thrown when an authentication is rejected because * the digest nonce has expired. * * @author Fabien Potencier * @author Alexander + * + * @deprecated since 3.4, to be removed in 4.0 */ class NonceExpiredException extends AuthenticationException { diff --git a/src/Symfony/Component/Security/Http/EntryPoint/DigestAuthenticationEntryPoint.php b/src/Symfony/Component/Security/Http/EntryPoint/DigestAuthenticationEntryPoint.php index 9dfd5929459fb..185426599187e 100644 --- a/src/Symfony/Component/Security/Http/EntryPoint/DigestAuthenticationEntryPoint.php +++ b/src/Symfony/Component/Security/Http/EntryPoint/DigestAuthenticationEntryPoint.php @@ -21,6 +21,8 @@ * DigestAuthenticationEntryPoint starts an HTTP Digest authentication. * * @author Fabien Potencier + * + * @deprecated since 3.4, to be removed in 4.0 */ class DigestAuthenticationEntryPoint implements AuthenticationEntryPointInterface { @@ -31,6 +33,8 @@ class DigestAuthenticationEntryPoint implements AuthenticationEntryPointInterfac public function __construct($realmName, $secret, $nonceValiditySeconds = 300, LoggerInterface $logger = null) { + @trigger_error(sprintf('The %s class and the whole HTTP digest authentication system is deprecated since 3.4 and will be removed in 4.0.', __CLASS__), E_USER_DEPRECATED); + $this->realmName = $realmName; $this->secret = $secret; $this->nonceValiditySeconds = $nonceValiditySeconds; diff --git a/src/Symfony/Component/Security/Http/Firewall/DigestAuthenticationListener.php b/src/Symfony/Component/Security/Http/Firewall/DigestAuthenticationListener.php index 4479a5cae9dc1..ce8e435aa8f82 100644 --- a/src/Symfony/Component/Security/Http/Firewall/DigestAuthenticationListener.php +++ b/src/Symfony/Component/Security/Http/Firewall/DigestAuthenticationListener.php @@ -28,6 +28,8 @@ * DigestAuthenticationListener implements Digest HTTP authentication. * * @author Fabien Potencier + * + * @deprecated since 3.4, to be removed in 4.0 */ class DigestAuthenticationListener implements ListenerInterface { @@ -39,6 +41,8 @@ class DigestAuthenticationListener implements ListenerInterface public function __construct(TokenStorageInterface $tokenStorage, UserProviderInterface $provider, $providerKey, DigestAuthenticationEntryPoint $authenticationEntryPoint, LoggerInterface $logger = null) { + @trigger_error(sprintf('The %s class and the whole HTTP digest authentication system is deprecated since 3.4 and will be removed in 4.0.', __CLASS__), E_USER_DEPRECATED); + if (empty($providerKey)) { throw new \InvalidArgumentException('$providerKey must not be empty.'); } @@ -137,6 +141,9 @@ private function fail(GetResponseEvent $event, Request $request, AuthenticationE } } +/** + * @deprecated since 3.4, to be removed in 4.0. + */ class DigestData { private $elements = array(); @@ -145,6 +152,8 @@ class DigestData public function __construct($header) { + @trigger_error(sprintf('The %s class and the whole HTTP digest authentication system is deprecated since 3.4 and will be removed in 4.0.', __CLASS__), E_USER_DEPRECATED); + $this->header = $header; preg_match_all('/(\w+)=("((?:[^"\\\\]|\\\\.)+)"|([^\s,$]+))/', $header, $matches, PREG_SET_ORDER); foreach ($matches as $match) { diff --git a/src/Symfony/Component/Security/Http/Tests/EntryPoint/DigestAuthenticationEntryPointTest.php b/src/Symfony/Component/Security/Http/Tests/EntryPoint/DigestAuthenticationEntryPointTest.php index e08570dbbd9fc..035a5baae99cf 100644 --- a/src/Symfony/Component/Security/Http/Tests/EntryPoint/DigestAuthenticationEntryPointTest.php +++ b/src/Symfony/Component/Security/Http/Tests/EntryPoint/DigestAuthenticationEntryPointTest.php @@ -16,6 +16,9 @@ use Symfony\Component\Security\Core\Exception\AuthenticationException; use Symfony\Component\Security\Core\Exception\NonceExpiredException; +/** + * @group legacy + */ class DigestAuthenticationEntryPointTest extends TestCase { public function testStart() diff --git a/src/Symfony/Component/Security/Http/Tests/Firewall/DigestAuthenticationListenerTest.php b/src/Symfony/Component/Security/Http/Tests/Firewall/DigestAuthenticationListenerTest.php index 495dae4262162..b6f7efa8b5aa3 100644 --- a/src/Symfony/Component/Security/Http/Tests/Firewall/DigestAuthenticationListenerTest.php +++ b/src/Symfony/Component/Security/Http/Tests/Firewall/DigestAuthenticationListenerTest.php @@ -8,6 +8,9 @@ use Symfony\Component\Security\Http\EntryPoint\DigestAuthenticationEntryPoint; use Symfony\Component\Security\Http\Firewall\DigestAuthenticationListener; +/** + * @group legacy + */ class DigestAuthenticationListenerTest extends TestCase { public function testHandleWithValidDigest() diff --git a/src/Symfony/Component/Security/Http/Tests/Firewall/DigestDataTest.php b/src/Symfony/Component/Security/Http/Tests/Firewall/DigestDataTest.php index 7317e2f83c7cc..185055efceb68 100644 --- a/src/Symfony/Component/Security/Http/Tests/Firewall/DigestDataTest.php +++ b/src/Symfony/Component/Security/Http/Tests/Firewall/DigestDataTest.php @@ -14,6 +14,9 @@ use PHPUnit\Framework\TestCase; use Symfony\Component\Security\Http\Firewall\DigestData; +/** + * @group legacy + */ class DigestDataTest extends TestCase { public function testGetResponse() From 7473981c1499a030893213488a86c4fb58e37476 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ole=20R=C3=B6=C3=9Fner?= Date: Wed, 12 Jul 2017 10:05:49 +0200 Subject: [PATCH 0908/1099] [Config] extracted the xml parsing from XmlUtils::loadFile into XmlUtils::parse --- .../Config/Tests/Util/XmlUtilsTest.php | 16 +++++- .../Util/Exception/InvalidXmlException.php | 21 +++++++ .../Util/Exception/XmlParsingException.php | 21 +++++++ .../Component/Config/Util/XmlUtils.php | 56 ++++++++++++++----- 4 files changed, 98 insertions(+), 16 deletions(-) create mode 100644 src/Symfony/Component/Config/Util/Exception/InvalidXmlException.php create mode 100644 src/Symfony/Component/Config/Util/Exception/XmlParsingException.php diff --git a/src/Symfony/Component/Config/Tests/Util/XmlUtilsTest.php b/src/Symfony/Component/Config/Tests/Util/XmlUtilsTest.php index 161dc61721c12..a26a994d91050 100644 --- a/src/Symfony/Component/Config/Tests/Util/XmlUtilsTest.php +++ b/src/Symfony/Component/Config/Tests/Util/XmlUtilsTest.php @@ -55,13 +55,27 @@ public function testLoadFile() XmlUtils::loadFile($fixtures.'valid.xml', array($mock, 'validate')); $this->fail(); } catch (\InvalidArgumentException $e) { - $this->assertContains('is not valid', $e->getMessage()); + $this->assertRegExp('/The XML file "[\w:\/\\\.]+" is not valid\./', $e->getMessage()); } $this->assertInstanceOf('DOMDocument', XmlUtils::loadFile($fixtures.'valid.xml', array($mock, 'validate'))); $this->assertSame(array(), libxml_get_errors()); } + /** + * @expectedException \Symfony\Component\Config\Util\Exception\InvalidXmlException + * @expectedExceptionMessage The XML is not valid + */ + public function testParseWithInvalidValidatorCallable() + { + $fixtures = __DIR__.'/../Fixtures/Util/'; + + $mock = $this->getMockBuilder(__NAMESPACE__.'\Validator')->getMock(); + $mock->expects($this->once())->method('validate')->willReturn(false); + + XmlUtils::parse(file_get_contents($fixtures.'valid.xml'), array($mock, 'validate')); + } + public function testLoadFileWithInternalErrorsEnabled() { $internalErrors = libxml_use_internal_errors(true); diff --git a/src/Symfony/Component/Config/Util/Exception/InvalidXmlException.php b/src/Symfony/Component/Config/Util/Exception/InvalidXmlException.php new file mode 100644 index 0000000000000..a335bbd2eed7c --- /dev/null +++ b/src/Symfony/Component/Config/Util/Exception/InvalidXmlException.php @@ -0,0 +1,21 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Config\Util\Exception; + +/** + * Exception class for when XML parsing with an XSD schema file path or a callable validator produces errors unrelated + * to the actual XML parsing. + * + * @author Ole Rößner + */ +class InvalidXmlException extends XmlParsingException +{ +} diff --git a/src/Symfony/Component/Config/Util/Exception/XmlParsingException.php b/src/Symfony/Component/Config/Util/Exception/XmlParsingException.php new file mode 100644 index 0000000000000..9bceed660baed --- /dev/null +++ b/src/Symfony/Component/Config/Util/Exception/XmlParsingException.php @@ -0,0 +1,21 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Config\Util\Exception; + +/** + * Exception class for when XML cannot be parsed properly. + * + * @author Ole Rößner + */ +class XmlParsingException extends \InvalidArgumentException +{ +} diff --git a/src/Symfony/Component/Config/Util/XmlUtils.php b/src/Symfony/Component/Config/Util/XmlUtils.php index 9c7ac126ef1ca..130384ea87030 100644 --- a/src/Symfony/Component/Config/Util/XmlUtils.php +++ b/src/Symfony/Component/Config/Util/XmlUtils.php @@ -11,6 +11,9 @@ namespace Symfony\Component\Config\Util; +use Symfony\Component\Config\Util\Exception\InvalidXmlException; +use Symfony\Component\Config\Util\Exception\XmlParsingException; + /** * XMLUtils is a bunch of utility methods to XML operations. * @@ -18,6 +21,7 @@ * * @author Fabien Potencier * @author Martin Hasoň + * @author Ole Rößner */ class XmlUtils { @@ -29,27 +33,23 @@ private function __construct() } /** - * Loads an XML file. + * Parses an XML string. * - * @param string $file An XML file path + * @param string $content An XML string * @param string|callable|null $schemaOrCallable An XSD schema file path, a callable, or null to disable validation * * @return \DOMDocument * - * @throws \InvalidArgumentException When loading of XML file returns error - * @throws \RuntimeException When DOM extension is missing + * @throws \Symfony\Component\Config\Util\Exception\XmlParsingException When parsing of XML file returns error + * @throws \Symfony\Component\Config\Util\Exception\InvalidXmlException When parsing of XML with schema or callable produces any errors unrelated to the XML parsing itself + * @throws \RuntimeException When DOM extension is missing */ - public static function loadFile($file, $schemaOrCallable = null) + public static function parse($content, $schemaOrCallable = null) { if (!extension_loaded('dom')) { throw new \RuntimeException('Extension DOM is required.'); } - $content = @file_get_contents($file); - if ('' === trim($content)) { - throw new \InvalidArgumentException(sprintf('File %s does not contain valid XML, it is empty.', $file)); - } - $internalErrors = libxml_use_internal_errors(true); $disableEntities = libxml_disable_entity_loader(true); libxml_clear_errors(); @@ -59,7 +59,7 @@ public static function loadFile($file, $schemaOrCallable = null) if (!$dom->loadXML($content, LIBXML_NONET | (defined('LIBXML_COMPACT') ? LIBXML_COMPACT : 0))) { libxml_disable_entity_loader($disableEntities); - throw new \InvalidArgumentException(implode("\n", static::getXmlErrors($internalErrors))); + throw new XmlParsingException(implode("\n", static::getXmlErrors($internalErrors))); } $dom->normalizeDocument(); @@ -69,7 +69,7 @@ public static function loadFile($file, $schemaOrCallable = null) foreach ($dom->childNodes as $child) { if (XML_DOCUMENT_TYPE_NODE === $child->nodeType) { - throw new \InvalidArgumentException('Document types are not allowed.'); + throw new XmlParsingException('Document types are not allowed.'); } } @@ -90,15 +90,15 @@ public static function loadFile($file, $schemaOrCallable = null) } else { libxml_use_internal_errors($internalErrors); - throw new \InvalidArgumentException('The schemaOrCallable argument has to be a valid path to XSD file or callable.'); + throw new XmlParsingException('The schemaOrCallable argument has to be a valid path to XSD file or callable.'); } if (!$valid) { $messages = static::getXmlErrors($internalErrors); if (empty($messages)) { - $messages = array(sprintf('The XML file "%s" is not valid.', $file)); + throw new InvalidXmlException('The XML is not valid.', 0, $e); } - throw new \InvalidArgumentException(implode("\n", $messages), 0, $e); + throw new XmlParsingException(implode("\n", $messages), 0, $e); } } @@ -108,6 +108,32 @@ public static function loadFile($file, $schemaOrCallable = null) return $dom; } + /** + * Loads an XML file. + * + * @param string $file An XML file path + * @param string|callable|null $schemaOrCallable An XSD schema file path, a callable, or null to disable validation + * + * @return \DOMDocument + * + * @throws \InvalidArgumentException When loading of XML file returns error + * @throws \Symfony\Component\Config\Util\Exception\XmlParsingException when XML parsing returns any errors + * @throws \RuntimeException When DOM extension is missing + */ + public static function loadFile($file, $schemaOrCallable = null) + { + $content = @file_get_contents($file); + if ('' === trim($content)) { + throw new \InvalidArgumentException(sprintf('File %s does not contain valid XML, it is empty.', $file)); + } + + try { + return static::parse($content, $schemaOrCallable); + } catch (InvalidXmlException $e) { + throw new XmlParsingException(sprintf('The XML file "%s" is not valid.', $file), 0, $e->getPrevious()); + } + } + /** * Converts a \DomElement object to a PHP array. * From 6fcb0756836a3c24a340d88d7f8300bf430d8d3c Mon Sep 17 00:00:00 2001 From: Maxime Steinhausser Date: Tue, 26 Sep 2017 22:01:10 +0200 Subject: [PATCH 0909/1099] Fix changelog and minor tweak for #23485 --- src/Symfony/Component/Config/CHANGELOG.md | 1 + src/Symfony/Component/Config/Util/XmlUtils.php | 12 ++++++------ 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/Symfony/Component/Config/CHANGELOG.md b/src/Symfony/Component/Config/CHANGELOG.md index ffa347dbf4976..f8a2028e558db 100644 --- a/src/Symfony/Component/Config/CHANGELOG.md +++ b/src/Symfony/Component/Config/CHANGELOG.md @@ -5,6 +5,7 @@ CHANGELOG ----- * added `setDeprecated()` method to indicate a deprecated node + * added `XmlUtils::parse()` method to parse an XML string 3.3.0 ----- diff --git a/src/Symfony/Component/Config/Util/XmlUtils.php b/src/Symfony/Component/Config/Util/XmlUtils.php index 130384ea87030..c6e1869f9be51 100644 --- a/src/Symfony/Component/Config/Util/XmlUtils.php +++ b/src/Symfony/Component/Config/Util/XmlUtils.php @@ -40,9 +40,9 @@ private function __construct() * * @return \DOMDocument * - * @throws \Symfony\Component\Config\Util\Exception\XmlParsingException When parsing of XML file returns error - * @throws \Symfony\Component\Config\Util\Exception\InvalidXmlException When parsing of XML with schema or callable produces any errors unrelated to the XML parsing itself - * @throws \RuntimeException When DOM extension is missing + * @throws XmlParsingException When parsing of XML file returns error + * @throws InvalidXmlException When parsing of XML with schema or callable produces any errors unrelated to the XML parsing itself + * @throws \RuntimeException When DOM extension is missing */ public static function parse($content, $schemaOrCallable = null) { @@ -116,9 +116,9 @@ public static function parse($content, $schemaOrCallable = null) * * @return \DOMDocument * - * @throws \InvalidArgumentException When loading of XML file returns error - * @throws \Symfony\Component\Config\Util\Exception\XmlParsingException when XML parsing returns any errors - * @throws \RuntimeException When DOM extension is missing + * @throws \InvalidArgumentException When loading of XML file returns error + * @throws XmlParsingException When XML parsing returns any errors + * @throws \RuntimeException When DOM extension is missing */ public static function loadFile($file, $schemaOrCallable = null) { From 4205f1bc686c75f0a925134642f797acd17962c1 Mon Sep 17 00:00:00 2001 From: VJ Date: Wed, 19 Apr 2017 12:13:04 -0400 Subject: [PATCH 0910/1099] Passing the newly generated security token to the event during user switching. Event allows listeners to easily switch out the token if custom token updates are required --- src/Symfony/Component/Security/CHANGELOG.md | 2 + .../Security/Http/Event/SwitchUserEvent.php | 18 ++++++++- .../Http/Firewall/SwitchUserListener.php | 7 +++- .../Tests/Firewall/SwitchUserListenerTest.php | 39 +++++++++++++++++++ 4 files changed, 63 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Component/Security/CHANGELOG.md b/src/Symfony/Component/Security/CHANGELOG.md index 292c304fc68c7..7d30f22f777e7 100644 --- a/src/Symfony/Component/Security/CHANGELOG.md +++ b/src/Symfony/Component/Security/CHANGELOG.md @@ -4,6 +4,8 @@ CHANGELOG 3.4.0 ----- + * added a `setToken()` method to the `SwitchUserEvent` class to allow to replace the created token while switching users + when custom token generation is required by application. * Using voters that do not implement the `VoterInterface`is now deprecated in the `AccessDecisionManager` and this functionality will be removed in 4.0. diff --git a/src/Symfony/Component/Security/Http/Event/SwitchUserEvent.php b/src/Symfony/Component/Security/Http/Event/SwitchUserEvent.php index 7cf94a70d3136..2681fb6c602bd 100644 --- a/src/Symfony/Component/Security/Http/Event/SwitchUserEvent.php +++ b/src/Symfony/Component/Security/Http/Event/SwitchUserEvent.php @@ -12,6 +12,7 @@ namespace Symfony\Component\Security\Http\Event; use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; use Symfony\Component\Security\Core\User\UserInterface; use Symfony\Component\EventDispatcher\Event; @@ -24,11 +25,13 @@ class SwitchUserEvent extends Event { private $request; private $targetUser; + private $token; - public function __construct(Request $request, UserInterface $targetUser) + public function __construct(Request $request, UserInterface $targetUser, TokenInterface $token = null) { $this->request = $request; $this->targetUser = $targetUser; + $this->token = $token; } /** @@ -46,4 +49,17 @@ public function getTargetUser() { return $this->targetUser; } + + /** + * @return TokenInterface|null + */ + public function getToken() + { + return $this->token; + } + + public function setToken(TokenInterface $token) + { + $this->token = $token; + } } diff --git a/src/Symfony/Component/Security/Http/Firewall/SwitchUserListener.php b/src/Symfony/Component/Security/Http/Firewall/SwitchUserListener.php index 2caab2a35363b..2fc06140cfd37 100644 --- a/src/Symfony/Component/Security/Http/Firewall/SwitchUserListener.php +++ b/src/Symfony/Component/Security/Http/Firewall/SwitchUserListener.php @@ -145,8 +145,10 @@ private function attemptSwitchUser(Request $request) $token = new UsernamePasswordToken($user, $user->getPassword(), $this->providerKey, $roles); if (null !== $this->dispatcher) { - $switchEvent = new SwitchUserEvent($request, $token->getUser()); + $switchEvent = new SwitchUserEvent($request, $token->getUser(), $token); $this->dispatcher->dispatch(SecurityEvents::SWITCH_USER, $switchEvent); + // use the token from the event in case any listeners have replaced it. + $token = $switchEvent->getToken(); } return $token; @@ -169,8 +171,9 @@ private function attemptExitUser(Request $request) if (null !== $this->dispatcher && $original->getUser() instanceof UserInterface) { $user = $this->provider->refreshUser($original->getUser()); - $switchEvent = new SwitchUserEvent($request, $user); + $switchEvent = new SwitchUserEvent($request, $user, $original); $this->dispatcher->dispatch(SecurityEvents::SWITCH_USER, $switchEvent); + $original = $switchEvent->getToken(); } return $original; diff --git a/src/Symfony/Component/Security/Http/Tests/Firewall/SwitchUserListenerTest.php b/src/Symfony/Component/Security/Http/Tests/Firewall/SwitchUserListenerTest.php index 57cba1127a9b1..c97eda759330b 100644 --- a/src/Symfony/Component/Security/Http/Tests/Firewall/SwitchUserListenerTest.php +++ b/src/Symfony/Component/Security/Http/Tests/Firewall/SwitchUserListenerTest.php @@ -227,4 +227,43 @@ public function testSwitchUserKeepsOtherQueryStringParameters() $this->assertSame('page=3§ion=2', $this->request->server->get('QUERY_STRING')); $this->assertInstanceOf('Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken', $this->tokenStorage->getToken()); } + + public function testSwitchUserWithReplacedToken() + { + $user = new User('username', 'password', array()); + $token = new UsernamePasswordToken($user, '', 'provider123', array('ROLE_FOO')); + + $user = new User('replaced', 'password', array()); + $replacedToken = new UsernamePasswordToken($user, '', 'provider123', array('ROLE_BAR')); + + $this->tokenStorage->setToken($token); + $this->request->query->set('_switch_user', 'kuba'); + + $this->accessDecisionManager->expects($this->any()) + ->method('decide')->with($token, array('ROLE_ALLOWED_TO_SWITCH')) + ->will($this->returnValue(true)); + + $this->userProvider->expects($this->any()) + ->method('loadUserByUsername')->with('kuba') + ->will($this->returnValue($user)); + + $dispatcher = $this->getMockBuilder('Symfony\Component\EventDispatcher\EventDispatcherInterface')->getMock(); + $dispatcher + ->expects($this->once()) + ->method('dispatch') + ->with(SecurityEvents::SWITCH_USER, + $this->callback(function (SwitchUserEvent $event) use ($replacedToken, $user) { + if ($user !== $event->getTargetUser()) { + return false; + } + $event->setToken($replacedToken); + + return true; + })); + + $listener = new SwitchUserListener($this->tokenStorage, $this->userProvider, $this->userChecker, 'provider123', $this->accessDecisionManager, null, '_switch_user', 'ROLE_ALLOWED_TO_SWITCH', $dispatcher); + $listener->handle($this->event); + + $this->assertSame($replacedToken, $this->tokenStorage->getToken()); + } } From 8ff716b1f3b2481601e220c0588d62f6b6ee590a Mon Sep 17 00:00:00 2001 From: Maxime Steinhausser Date: Tue, 26 Sep 2017 19:05:58 +0200 Subject: [PATCH 0911/1099] [Security][SecurityBundle] Remove the HTTP digest auth --- UPGRADE-3.4.md | 10 + UPGRADE-4.0.md | 7 + .../Bundle/SecurityBundle/CHANGELOG.md | 2 + .../Security/Factory/HttpDigestFactory.php | 85 ------- .../Resources/config/security_listeners.xml | 11 - .../Bundle/SecurityBundle/SecurityBundle.php | 2 - .../CompleteConfigurationTest.php | 2 - .../Fixtures/php/container1.php | 1 - .../Fixtures/php/no_custom_user_checker.php | 1 - .../Fixtures/xml/container1.xml | 1 - .../Fixtures/xml/no_custom_user_checker.xml | 1 - .../Fixtures/yml/container1.yml | 2 - .../Fixtures/yml/no_custom_user_checker.yml | 2 - src/Symfony/Component/Security/CHANGELOG.md | 2 + .../Core/Exception/NonceExpiredException.php | 30 --- .../Resources/translations/security.ar.xlf | 4 - .../Resources/translations/security.az.xlf | 4 - .../Resources/translations/security.bg.xlf | 4 - .../Resources/translations/security.ca.xlf | 4 - .../Resources/translations/security.cs.xlf | 4 - .../Resources/translations/security.da.xlf | 4 - .../Resources/translations/security.de.xlf | 4 - .../Resources/translations/security.el.xlf | 4 - .../Resources/translations/security.en.xlf | 4 - .../Resources/translations/security.es.xlf | 4 - .../Resources/translations/security.fa.xlf | 4 - .../Resources/translations/security.fr.xlf | 4 - .../Resources/translations/security.gl.xlf | 4 - .../Resources/translations/security.he.xlf | 4 - .../Resources/translations/security.hr.xlf | 4 - .../Resources/translations/security.hu.xlf | 4 - .../Resources/translations/security.id.xlf | 4 - .../Resources/translations/security.it.xlf | 4 - .../Resources/translations/security.ja.xlf | 4 - .../Resources/translations/security.lb.xlf | 4 - .../Resources/translations/security.lt.xlf | 4 - .../Resources/translations/security.lv.xlf | 6 +- .../Resources/translations/security.nl.xlf | 4 - .../Resources/translations/security.no.xlf | 4 - .../Resources/translations/security.pl.xlf | 4 - .../Resources/translations/security.pt_BR.xlf | 4 - .../Resources/translations/security.pt_PT.xlf | 4 - .../Resources/translations/security.ro.xlf | 4 - .../Resources/translations/security.ru.xlf | 4 - .../Resources/translations/security.sk.xlf | 4 - .../Resources/translations/security.sl.xlf | 4 - .../translations/security.sr_Cyrl.xlf | 4 - .../translations/security.sr_Latn.xlf | 4 - .../Resources/translations/security.sv.xlf | 4 - .../Resources/translations/security.th.xlf | 4 - .../Resources/translations/security.tr.xlf | 4 - .../Resources/translations/security.ua.xlf | 4 - .../Resources/translations/security.vi.xlf | 4 - .../Resources/translations/security.zh_CN.xlf | 4 - .../DigestAuthenticationEntryPoint.php | 82 ------- .../Firewall/DigestAuthenticationListener.php | 219 ------------------ .../DigestAuthenticationEntryPointTest.php | 57 ----- .../DigestAuthenticationListenerTest.php | 80 ------- .../Http/Tests/Firewall/DigestDataTest.php | 185 --------------- 59 files changed, 22 insertions(+), 918 deletions(-) delete mode 100644 src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/HttpDigestFactory.php delete mode 100644 src/Symfony/Component/Security/Core/Exception/NonceExpiredException.php delete mode 100644 src/Symfony/Component/Security/Http/EntryPoint/DigestAuthenticationEntryPoint.php delete mode 100644 src/Symfony/Component/Security/Http/Firewall/DigestAuthenticationListener.php delete mode 100644 src/Symfony/Component/Security/Http/Tests/EntryPoint/DigestAuthenticationEntryPointTest.php delete mode 100644 src/Symfony/Component/Security/Http/Tests/Firewall/DigestAuthenticationListenerTest.php delete mode 100644 src/Symfony/Component/Security/Http/Tests/Firewall/DigestDataTest.php diff --git a/UPGRADE-3.4.md b/UPGRADE-3.4.md index 5f44e9785d03b..61cd356096d41 100644 --- a/UPGRADE-3.4.md +++ b/UPGRADE-3.4.md @@ -270,6 +270,13 @@ Profiler * The `profiler.matcher` option has been deprecated. +Security +-------- + + * Deprecated the HTTP digest authentication: `NonceExpiredException`, + `DigestAuthenticationListener` and `DigestAuthenticationEntryPoint` will be + removed in 4.0. Use another authentication system like `http_basic` instead. + SecurityBundle -------------- @@ -290,6 +297,9 @@ SecurityBundle * Added `logout_on_user_change` to the firewall options. This config item will trigger a logout when the user has changed. Should be set to true to avoid deprecations in the configuration. + + * Deprecated the HTTP digest authentication: `HttpDigestFactory` will be removed in 4.0. + Use another authentication system like `http_basic` instead. Translation ----------- diff --git a/UPGRADE-4.0.md b/UPGRADE-4.0.md index 4e567ed50fd11..b416ffb6a75e6 100644 --- a/UPGRADE-4.0.md +++ b/UPGRADE-4.0.md @@ -652,6 +652,10 @@ Security * Calling `ContextListener::setLogoutOnUserChange(false)` won't have any effect anymore. + * Removed the HTTP digest authentication system. The `NonceExpiredException`, + `DigestAuthenticationListener` and `DigestAuthenticationEntryPoint` classes + have been removed. Use another authentication system like `http_basic` instead. + SecurityBundle -------------- @@ -672,6 +676,9 @@ SecurityBundle * The firewall option `logout_on_user_change` is now always true, which will trigger a logout if the user changes between requests. + + * Removed the HTTP digest authentication system. The `HttpDigestFactory` class + has been removed. Use another authentication system like `http_basic` instead. Serializer ---------- diff --git a/src/Symfony/Bundle/SecurityBundle/CHANGELOG.md b/src/Symfony/Bundle/SecurityBundle/CHANGELOG.md index 6e7961d30a294..685560664d88e 100644 --- a/src/Symfony/Bundle/SecurityBundle/CHANGELOG.md +++ b/src/Symfony/Bundle/SecurityBundle/CHANGELOG.md @@ -9,6 +9,7 @@ CHANGELOG * made the first `UserPasswordEncoderCommand::_construct()` argument mandatory * `UserPasswordEncoderCommand` does not extend `ContainerAwareCommand` anymore * removed support for voters that don't implement the `VoterInterface` + * removed HTTP digest authentication 3.4.0 ----- @@ -25,6 +26,7 @@ CHANGELOG * Added `logout_on_user_change` to the firewall options. This config item will trigger a logout when the user has changed. Should be set to true to avoid deprecations in the configuration. + * deprecated HTTP digest authentication 3.3.0 ----- diff --git a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/HttpDigestFactory.php b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/HttpDigestFactory.php deleted file mode 100644 index bedc87864c235..0000000000000 --- a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/HttpDigestFactory.php +++ /dev/null @@ -1,85 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\SecurityBundle\DependencyInjection\Security\Factory; - -use Symfony\Component\Config\Definition\Builder\NodeDefinition; -use Symfony\Component\DependencyInjection\ChildDefinition; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Reference; - -/** - * HttpDigestFactory creates services for HTTP digest authentication. - * - * @author Fabien Potencier - */ -class HttpDigestFactory implements SecurityFactoryInterface -{ - public function create(ContainerBuilder $container, $id, $config, $userProvider, $defaultEntryPoint) - { - $provider = 'security.authentication.provider.dao.'.$id; - $container - ->setDefinition($provider, new ChildDefinition('security.authentication.provider.dao')) - ->replaceArgument(0, new Reference($userProvider)) - ->replaceArgument(1, new Reference('security.user_checker.'.$id)) - ->replaceArgument(2, $id) - ; - - // entry point - $entryPointId = $this->createEntryPoint($container, $id, $config, $defaultEntryPoint); - - // listener - $listenerId = 'security.authentication.listener.digest.'.$id; - $listener = $container->setDefinition($listenerId, new ChildDefinition('security.authentication.listener.digest')); - $listener->replaceArgument(1, new Reference($userProvider)); - $listener->replaceArgument(2, $id); - $listener->replaceArgument(3, new Reference($entryPointId)); - - return array($provider, $listenerId, $entryPointId); - } - - public function getPosition() - { - return 'http'; - } - - public function getKey() - { - return 'http-digest'; - } - - public function addConfiguration(NodeDefinition $node) - { - $node - ->children() - ->scalarNode('provider')->end() - ->scalarNode('realm')->defaultValue('Secured Area')->end() - ->scalarNode('secret')->isRequired()->cannotBeEmpty()->end() - ->end() - ; - } - - protected function createEntryPoint($container, $id, $config, $defaultEntryPoint) - { - if (null !== $defaultEntryPoint) { - return $defaultEntryPoint; - } - - $entryPointId = 'security.authentication.digest_entry_point.'.$id; - $container - ->setDefinition($entryPointId, new ChildDefinition('security.authentication.digest_entry_point')) - ->addArgument($config['realm']) - ->addArgument($config['secret']) - ; - - return $entryPointId; - } -} diff --git a/src/Symfony/Bundle/SecurityBundle/Resources/config/security_listeners.xml b/src/Symfony/Bundle/SecurityBundle/Resources/config/security_listeners.xml index ab9a587ad7d18..829524c2197d4 100644 --- a/src/Symfony/Bundle/SecurityBundle/Resources/config/security_listeners.xml +++ b/src/Symfony/Bundle/SecurityBundle/Resources/config/security_listeners.xml @@ -26,8 +26,6 @@ - - @@ -180,15 +178,6 @@ - - - - - - - - - diff --git a/src/Symfony/Bundle/SecurityBundle/SecurityBundle.php b/src/Symfony/Bundle/SecurityBundle/SecurityBundle.php index 3b8f6dda85580..3fad75f6263ef 100644 --- a/src/Symfony/Bundle/SecurityBundle/SecurityBundle.php +++ b/src/Symfony/Bundle/SecurityBundle/SecurityBundle.php @@ -20,7 +20,6 @@ use Symfony\Bundle\SecurityBundle\DependencyInjection\Security\Factory\FormLoginLdapFactory; use Symfony\Bundle\SecurityBundle\DependencyInjection\Security\Factory\HttpBasicFactory; use Symfony\Bundle\SecurityBundle\DependencyInjection\Security\Factory\HttpBasicLdapFactory; -use Symfony\Bundle\SecurityBundle\DependencyInjection\Security\Factory\HttpDigestFactory; use Symfony\Bundle\SecurityBundle\DependencyInjection\Security\Factory\RememberMeFactory; use Symfony\Bundle\SecurityBundle\DependencyInjection\Security\Factory\X509Factory; use Symfony\Bundle\SecurityBundle\DependencyInjection\Security\Factory\RemoteUserFactory; @@ -47,7 +46,6 @@ public function build(ContainerBuilder $container) $extension->addSecurityListenerFactory(new JsonLoginFactory()); $extension->addSecurityListenerFactory(new HttpBasicFactory()); $extension->addSecurityListenerFactory(new HttpBasicLdapFactory()); - $extension->addSecurityListenerFactory(new HttpDigestFactory()); $extension->addSecurityListenerFactory(new RememberMeFactory()); $extension->addSecurityListenerFactory(new X509Factory()); $extension->addSecurityListenerFactory(new RemoteUserFactory()); diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/CompleteConfigurationTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/CompleteConfigurationTest.php index c7451496d48c2..b567cb197462d 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/CompleteConfigurationTest.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/CompleteConfigurationTest.php @@ -111,7 +111,6 @@ public function testFirewalls() 'remote_user', 'form_login', 'http_basic', - 'http_digest', 'remember_me', 'anonymous', ), @@ -165,7 +164,6 @@ public function testFirewalls() 'security.authentication.listener.remote_user.secure', 'security.authentication.listener.form.secure', 'security.authentication.listener.basic.secure', - 'security.authentication.listener.digest.secure', 'security.authentication.listener.rememberme.secure', 'security.authentication.listener.anonymous.secure', 'security.authentication.switchuser_listener.secure', diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/container1.php b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/container1.php index 581407fcc05a5..3748f05012b87 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/container1.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/container1.php @@ -64,7 +64,6 @@ 'simple' => array('pattern' => '/login', 'security' => false), 'secure' => array('stateless' => true, 'http_basic' => true, - 'http_digest' => array('secret' => 'TheSecret'), 'form_login' => true, 'anonymous' => true, 'switch_user' => true, diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/no_custom_user_checker.php b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/no_custom_user_checker.php index 91c475418b450..3889752f8f928 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/no_custom_user_checker.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/no_custom_user_checker.php @@ -15,7 +15,6 @@ 'secure' => array( 'stateless' => true, 'http_basic' => true, - 'http_digest' => array('secret' => 'TheSecret'), 'form_login' => true, 'anonymous' => true, 'switch_user' => true, diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/container1.xml b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/container1.xml index e5049f2033e51..05c31e1854c93 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/container1.xml +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/container1.xml @@ -49,7 +49,6 @@ - diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/no_custom_user_checker.xml b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/no_custom_user_checker.xml index 7d648ae1baec2..b97d39adb5a78 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/no_custom_user_checker.xml +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/no_custom_user_checker.xml @@ -15,7 +15,6 @@ - diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/container1.yml b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/container1.yml index a2b57201bfbd2..b016adb851e98 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/container1.yml +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/container1.yml @@ -46,8 +46,6 @@ security: secure: stateless: true http_basic: true - http_digest: - secret: TheSecret form_login: true anonymous: true switch_user: true diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/no_custom_user_checker.yml b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/no_custom_user_checker.yml index 23afa8cd9b3c5..6a196597c51e7 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/no_custom_user_checker.yml +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/no_custom_user_checker.yml @@ -10,8 +10,6 @@ security: secure: stateless: true http_basic: true - http_digest: - secret: TheSecret form_login: true anonymous: true switch_user: true diff --git a/src/Symfony/Component/Security/CHANGELOG.md b/src/Symfony/Component/Security/CHANGELOG.md index 69eeb1d9fd395..abfa98bfad65b 100644 --- a/src/Symfony/Component/Security/CHANGELOG.md +++ b/src/Symfony/Component/Security/CHANGELOG.md @@ -10,6 +10,7 @@ CHANGELOG * removed the `RoleInterface` * removed support for voters that don't implement the `VoterInterface` * added a sixth `string $context` argument to `LogoutUrlGenerator::registerListener()` + * removed HTTP digest authentication 3.4.0 ----- @@ -20,6 +21,7 @@ CHANGELOG property will trigger a deprecation when the user has changed. As of 4.0 the user will always be logged out when the user has changed between requests. + * deprecated HTTP digest authentication 3.3.0 ----- diff --git a/src/Symfony/Component/Security/Core/Exception/NonceExpiredException.php b/src/Symfony/Component/Security/Core/Exception/NonceExpiredException.php deleted file mode 100644 index 998e987e403de..0000000000000 --- a/src/Symfony/Component/Security/Core/Exception/NonceExpiredException.php +++ /dev/null @@ -1,30 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Security\Core\Exception; - -/** - * NonceExpiredException is thrown when an authentication is rejected because - * the digest nonce has expired. - * - * @author Fabien Potencier - * @author Alexander - */ -class NonceExpiredException extends AuthenticationException -{ - /** - * {@inheritdoc} - */ - public function getMessageKey() - { - return 'Digest nonce has expired.'; - } -} diff --git a/src/Symfony/Component/Security/Core/Resources/translations/security.ar.xlf b/src/Symfony/Component/Security/Core/Resources/translations/security.ar.xlf index fd18ee6ad9faf..49381ba347f6f 100644 --- a/src/Symfony/Component/Security/Core/Resources/translations/security.ar.xlf +++ b/src/Symfony/Component/Security/Core/Resources/translations/security.ar.xlf @@ -30,10 +30,6 @@ Invalid CSRF token. رمز الموقع غير صحيح. - - Digest nonce has expired. - انتهت صلاحية(digest nonce). - No authentication provider found to support the authentication token. لا يوجد معرف للدخول يدعم الرمز المستخدم للدخول. diff --git a/src/Symfony/Component/Security/Core/Resources/translations/security.az.xlf b/src/Symfony/Component/Security/Core/Resources/translations/security.az.xlf index a974ed0f024c8..d9d5425cefb9c 100644 --- a/src/Symfony/Component/Security/Core/Resources/translations/security.az.xlf +++ b/src/Symfony/Component/Security/Core/Resources/translations/security.az.xlf @@ -30,10 +30,6 @@ Invalid CSRF token. Yanlış CSRF nişanı. - - Digest nonce has expired. - Dərləmə istifadə müddəti bitib. - No authentication provider found to support the authentication token. Doğrulama nişanını dəstəkləyəcək provayder tapılmadı. diff --git a/src/Symfony/Component/Security/Core/Resources/translations/security.bg.xlf b/src/Symfony/Component/Security/Core/Resources/translations/security.bg.xlf index 06692ea66a843..28c1360eb946e 100644 --- a/src/Symfony/Component/Security/Core/Resources/translations/security.bg.xlf +++ b/src/Symfony/Component/Security/Core/Resources/translations/security.bg.xlf @@ -30,10 +30,6 @@ Invalid CSRF token. Невалиден CSRF токен. - - Digest nonce has expired. - Digest nonce е изтекъл. - No authentication provider found to support the authentication token. Не е открит провайдър, който да поддържа този токен за автентикация. diff --git a/src/Symfony/Component/Security/Core/Resources/translations/security.ca.xlf b/src/Symfony/Component/Security/Core/Resources/translations/security.ca.xlf index 7ece2603ae477..b009c6205c362 100644 --- a/src/Symfony/Component/Security/Core/Resources/translations/security.ca.xlf +++ b/src/Symfony/Component/Security/Core/Resources/translations/security.ca.xlf @@ -30,10 +30,6 @@ Invalid CSRF token. Token CSRF no vàlid. - - Digest nonce has expired. - El vector d'inicialització (digest nonce) ha expirat. - No authentication provider found to support the authentication token. No s'ha trobat un proveïdor d'autenticació que suporti el token d'autenticació. diff --git a/src/Symfony/Component/Security/Core/Resources/translations/security.cs.xlf b/src/Symfony/Component/Security/Core/Resources/translations/security.cs.xlf index bd146c68049cb..b455779cb6f20 100644 --- a/src/Symfony/Component/Security/Core/Resources/translations/security.cs.xlf +++ b/src/Symfony/Component/Security/Core/Resources/translations/security.cs.xlf @@ -30,10 +30,6 @@ Invalid CSRF token. Neplatný CSRF token. - - Digest nonce has expired. - Platnost inicializačního vektoru (digest nonce) vypršela. - No authentication provider found to support the authentication token. Poskytovatel pro ověřovací token nebyl nalezen. diff --git a/src/Symfony/Component/Security/Core/Resources/translations/security.da.xlf b/src/Symfony/Component/Security/Core/Resources/translations/security.da.xlf index 2ac41502d2c7f..102c8f1179521 100644 --- a/src/Symfony/Component/Security/Core/Resources/translations/security.da.xlf +++ b/src/Symfony/Component/Security/Core/Resources/translations/security.da.xlf @@ -30,10 +30,6 @@ Invalid CSRF token. Ugyldigt CSRF token. - - Digest nonce has expired. - Digest nonce er udløbet. - No authentication provider found to support the authentication token. Ingen godkendelsesudbyder er fundet til understøttelsen af godkendelsestoken. diff --git a/src/Symfony/Component/Security/Core/Resources/translations/security.de.xlf b/src/Symfony/Component/Security/Core/Resources/translations/security.de.xlf index e5946ed4aa42d..093d92d2d1fa9 100644 --- a/src/Symfony/Component/Security/Core/Resources/translations/security.de.xlf +++ b/src/Symfony/Component/Security/Core/Resources/translations/security.de.xlf @@ -30,10 +30,6 @@ Invalid CSRF token. Ungültiges CSRF-Token. - - Digest nonce has expired. - Digest nonce ist abgelaufen. - No authentication provider found to support the authentication token. Es wurde kein Authentifizierungs-Provider gefunden, der das Authentifizierungs-Token unterstützt. diff --git a/src/Symfony/Component/Security/Core/Resources/translations/security.el.xlf b/src/Symfony/Component/Security/Core/Resources/translations/security.el.xlf index 07eabe7ed29e2..02393d0805252 100644 --- a/src/Symfony/Component/Security/Core/Resources/translations/security.el.xlf +++ b/src/Symfony/Component/Security/Core/Resources/translations/security.el.xlf @@ -30,10 +30,6 @@ Invalid CSRF token. Μη έγκυρο CSRF token. - - Digest nonce has expired. - Το digest nonce έχει λήξει. - No authentication provider found to support the authentication token. Δε βρέθηκε κάποιος πάροχος πιστοποίησης που να υποστηρίζει το token πιστοποίησης. diff --git a/src/Symfony/Component/Security/Core/Resources/translations/security.en.xlf b/src/Symfony/Component/Security/Core/Resources/translations/security.en.xlf index 3640698ce9fb3..3c89e44f9380e 100644 --- a/src/Symfony/Component/Security/Core/Resources/translations/security.en.xlf +++ b/src/Symfony/Component/Security/Core/Resources/translations/security.en.xlf @@ -30,10 +30,6 @@ Invalid CSRF token. Invalid CSRF token. - - Digest nonce has expired. - Digest nonce has expired. - No authentication provider found to support the authentication token. No authentication provider found to support the authentication token. diff --git a/src/Symfony/Component/Security/Core/Resources/translations/security.es.xlf b/src/Symfony/Component/Security/Core/Resources/translations/security.es.xlf index 00cefbb2dad67..369f11b9b41d4 100644 --- a/src/Symfony/Component/Security/Core/Resources/translations/security.es.xlf +++ b/src/Symfony/Component/Security/Core/Resources/translations/security.es.xlf @@ -30,10 +30,6 @@ Invalid CSRF token. Token CSRF no válido. - - Digest nonce has expired. - El vector de inicialización (digest nonce) ha expirado. - No authentication provider found to support the authentication token. No se encontró un proveedor de autenticación que soporte el token de autenticación. diff --git a/src/Symfony/Component/Security/Core/Resources/translations/security.fa.xlf b/src/Symfony/Component/Security/Core/Resources/translations/security.fa.xlf index 0b7629078063c..1b3246feb3d5a 100644 --- a/src/Symfony/Component/Security/Core/Resources/translations/security.fa.xlf +++ b/src/Symfony/Component/Security/Core/Resources/translations/security.fa.xlf @@ -30,10 +30,6 @@ Invalid CSRF token. توکن CSRF معتبر نیست. - - Digest nonce has expired. - Digest nonce منقضی شده است. - No authentication provider found to support the authentication token. هیچ ارایه کننده تعیین اعتباری برای ساپورت توکن تعیین اعتبار پیدا نشد. diff --git a/src/Symfony/Component/Security/Core/Resources/translations/security.fr.xlf b/src/Symfony/Component/Security/Core/Resources/translations/security.fr.xlf index 5a77c6e9ff795..d67dcaefc5029 100644 --- a/src/Symfony/Component/Security/Core/Resources/translations/security.fr.xlf +++ b/src/Symfony/Component/Security/Core/Resources/translations/security.fr.xlf @@ -30,10 +30,6 @@ Invalid CSRF token. Jeton CSRF invalide. - - Digest nonce has expired. - Le digest nonce a expiré. - No authentication provider found to support the authentication token. Aucun fournisseur d'authentification n'a été trouvé pour supporter le jeton d'authentification. diff --git a/src/Symfony/Component/Security/Core/Resources/translations/security.gl.xlf b/src/Symfony/Component/Security/Core/Resources/translations/security.gl.xlf index ed6491f7ef97a..ddc838e66af8b 100644 --- a/src/Symfony/Component/Security/Core/Resources/translations/security.gl.xlf +++ b/src/Symfony/Component/Security/Core/Resources/translations/security.gl.xlf @@ -30,10 +30,6 @@ Invalid CSRF token. Token CSRF non válido. - - Digest nonce has expired. - O vector de inicialización (digest nonce) expirou. - No authentication provider found to support the authentication token. Non se atopou un provedor de autenticación que soporte o token de autenticación. diff --git a/src/Symfony/Component/Security/Core/Resources/translations/security.he.xlf b/src/Symfony/Component/Security/Core/Resources/translations/security.he.xlf index 3640698ce9fb3..3c89e44f9380e 100644 --- a/src/Symfony/Component/Security/Core/Resources/translations/security.he.xlf +++ b/src/Symfony/Component/Security/Core/Resources/translations/security.he.xlf @@ -30,10 +30,6 @@ Invalid CSRF token. Invalid CSRF token. - - Digest nonce has expired. - Digest nonce has expired. - No authentication provider found to support the authentication token. No authentication provider found to support the authentication token. diff --git a/src/Symfony/Component/Security/Core/Resources/translations/security.hr.xlf b/src/Symfony/Component/Security/Core/Resources/translations/security.hr.xlf index 147b6e311a22f..411a48572a097 100644 --- a/src/Symfony/Component/Security/Core/Resources/translations/security.hr.xlf +++ b/src/Symfony/Component/Security/Core/Resources/translations/security.hr.xlf @@ -30,10 +30,6 @@ Invalid CSRF token. Neispravan CSRF token. - - Digest nonce has expired. - Digest nonce je isteko. - No authentication provider found to support the authentication token. Nije pronađen autentifikacijski provider koji bi podržao autentifikacijski token. diff --git a/src/Symfony/Component/Security/Core/Resources/translations/security.hu.xlf b/src/Symfony/Component/Security/Core/Resources/translations/security.hu.xlf index 724397038cb66..f3a163904d367 100644 --- a/src/Symfony/Component/Security/Core/Resources/translations/security.hu.xlf +++ b/src/Symfony/Component/Security/Core/Resources/translations/security.hu.xlf @@ -30,10 +30,6 @@ Invalid CSRF token. Érvénytelen CSRF token. - - Digest nonce has expired. - A kivonat bélyege (nonce) lejárt. - No authentication provider found to support the authentication token. Nem található a hitelesítési tokent támogató hitelesítési szolgáltatás. diff --git a/src/Symfony/Component/Security/Core/Resources/translations/security.id.xlf b/src/Symfony/Component/Security/Core/Resources/translations/security.id.xlf index ab1153b8a27ff..6289481d03265 100644 --- a/src/Symfony/Component/Security/Core/Resources/translations/security.id.xlf +++ b/src/Symfony/Component/Security/Core/Resources/translations/security.id.xlf @@ -30,10 +30,6 @@ Invalid CSRF token. Token CSRF salah. - - Digest nonce has expired. - Digest nonce telah berakhir. - No authentication provider found to support the authentication token. Tidak ditemukan penyedia otentikasi untuk mendukung token otentikasi. diff --git a/src/Symfony/Component/Security/Core/Resources/translations/security.it.xlf b/src/Symfony/Component/Security/Core/Resources/translations/security.it.xlf index 75d81cc8d9312..f2cb0fa48fab5 100644 --- a/src/Symfony/Component/Security/Core/Resources/translations/security.it.xlf +++ b/src/Symfony/Component/Security/Core/Resources/translations/security.it.xlf @@ -30,10 +30,6 @@ Invalid CSRF token. CSRF token non valido. - - Digest nonce has expired. - Il numero di autenticazione è scaduto. - No authentication provider found to support the authentication token. Non è stato trovato un valido fornitore di autenticazione per supportare il token. diff --git a/src/Symfony/Component/Security/Core/Resources/translations/security.ja.xlf b/src/Symfony/Component/Security/Core/Resources/translations/security.ja.xlf index 6a6b062d946c3..2dad8dee6a927 100644 --- a/src/Symfony/Component/Security/Core/Resources/translations/security.ja.xlf +++ b/src/Symfony/Component/Security/Core/Resources/translations/security.ja.xlf @@ -30,10 +30,6 @@ Invalid CSRF token. CSRF トークンが無効です。 - - Digest nonce has expired. - Digest の nonce 値が期限切れです。 - No authentication provider found to support the authentication token. 認証トークンをサポートする認証プロバイダーが見つかりません。 diff --git a/src/Symfony/Component/Security/Core/Resources/translations/security.lb.xlf b/src/Symfony/Component/Security/Core/Resources/translations/security.lb.xlf index 3dc76d5486883..0a7096caea526 100644 --- a/src/Symfony/Component/Security/Core/Resources/translations/security.lb.xlf +++ b/src/Symfony/Component/Security/Core/Resources/translations/security.lb.xlf @@ -30,10 +30,6 @@ Invalid CSRF token. Ongëltegen CSRF-Token. - - Digest nonce has expired. - Den eemolege Schlëssel ass ofgelaf. - No authentication provider found to support the authentication token. Et gouf keen Authentifizéierungs-Provider fonnt deen den Authentifizéierungs-Token ënnerstëtzt. diff --git a/src/Symfony/Component/Security/Core/Resources/translations/security.lt.xlf b/src/Symfony/Component/Security/Core/Resources/translations/security.lt.xlf index da6c332b43829..0b426dcc01f6e 100644 --- a/src/Symfony/Component/Security/Core/Resources/translations/security.lt.xlf +++ b/src/Symfony/Component/Security/Core/Resources/translations/security.lt.xlf @@ -30,10 +30,6 @@ Invalid CSRF token. Neteisingas CSRF raktas. - - Digest nonce has expired. - Prieigos kodas yra pasibaigęs. - No authentication provider found to support the authentication token. Nerastas autentifikacijos tiekėjas, kuris palaikytų autentifikacijos raktą. diff --git a/src/Symfony/Component/Security/Core/Resources/translations/security.lv.xlf b/src/Symfony/Component/Security/Core/Resources/translations/security.lv.xlf index 33c48c617461c..0ad9125e711e9 100644 --- a/src/Symfony/Component/Security/Core/Resources/translations/security.lv.xlf +++ b/src/Symfony/Component/Security/Core/Resources/translations/security.lv.xlf @@ -30,10 +30,6 @@ Invalid CSRF token. Nederīgs CSRF talons. - - Digest nonce has expired. - Vienreiz lietojamās atslēgas darbības laiks ir beidzies. - No authentication provider found to support the authentication token. Nav atrasts, autentifikācijas talonu atbalstošs, autentifikācijas sniedzējs. @@ -68,4 +64,4 @@ - \ No newline at end of file + diff --git a/src/Symfony/Component/Security/Core/Resources/translations/security.nl.xlf b/src/Symfony/Component/Security/Core/Resources/translations/security.nl.xlf index 8969e9ef8ca69..5160143ab7380 100644 --- a/src/Symfony/Component/Security/Core/Resources/translations/security.nl.xlf +++ b/src/Symfony/Component/Security/Core/Resources/translations/security.nl.xlf @@ -30,10 +30,6 @@ Invalid CSRF token. CSRF-code is ongeldig. - - Digest nonce has expired. - Serverauthenticatiesleutel (digest nonce) is verlopen. - No authentication provider found to support the authentication token. Geen authenticatieprovider gevonden die de authenticatietoken ondersteunt. diff --git a/src/Symfony/Component/Security/Core/Resources/translations/security.no.xlf b/src/Symfony/Component/Security/Core/Resources/translations/security.no.xlf index 3635916971476..c5ab83efc5906 100644 --- a/src/Symfony/Component/Security/Core/Resources/translations/security.no.xlf +++ b/src/Symfony/Component/Security/Core/Resources/translations/security.no.xlf @@ -30,10 +30,6 @@ Invalid CSRF token. Ugyldig CSRF token. - - Digest nonce has expired. - Digest nonce er utløpt. - No authentication provider found to support the authentication token. Ingen autentiserings tilbyder funnet som støtter gitt autentiserings token. diff --git a/src/Symfony/Component/Security/Core/Resources/translations/security.pl.xlf b/src/Symfony/Component/Security/Core/Resources/translations/security.pl.xlf index 8d563d21206a9..9940d2940003d 100644 --- a/src/Symfony/Component/Security/Core/Resources/translations/security.pl.xlf +++ b/src/Symfony/Component/Security/Core/Resources/translations/security.pl.xlf @@ -30,10 +30,6 @@ Invalid CSRF token. Nieprawidłowy token CSRF. - - Digest nonce has expired. - Kod dostępu wygasł. - No authentication provider found to support the authentication token. Nie znaleziono mechanizmu uwierzytelniania zdolnego do obsługi przesłanego tokenu. diff --git a/src/Symfony/Component/Security/Core/Resources/translations/security.pt_BR.xlf b/src/Symfony/Component/Security/Core/Resources/translations/security.pt_BR.xlf index 61685d9f052ea..5981976f167ea 100644 --- a/src/Symfony/Component/Security/Core/Resources/translations/security.pt_BR.xlf +++ b/src/Symfony/Component/Security/Core/Resources/translations/security.pt_BR.xlf @@ -30,10 +30,6 @@ Invalid CSRF token. Token CSRF inválido. - - Digest nonce has expired. - Digest nonce expirado. - No authentication provider found to support the authentication token. Nenhum provedor de autenticação encontrado para suportar o token de autenticação. diff --git a/src/Symfony/Component/Security/Core/Resources/translations/security.pt_PT.xlf b/src/Symfony/Component/Security/Core/Resources/translations/security.pt_PT.xlf index f2af13ea3d082..b1a4af5154faa 100644 --- a/src/Symfony/Component/Security/Core/Resources/translations/security.pt_PT.xlf +++ b/src/Symfony/Component/Security/Core/Resources/translations/security.pt_PT.xlf @@ -30,10 +30,6 @@ Invalid CSRF token. Token CSRF inválido. - - Digest nonce has expired. - Digest nonce expirado. - No authentication provider found to support the authentication token. Nenhum fornecedor de autenticação encontrado para suportar o token de autenticação. diff --git a/src/Symfony/Component/Security/Core/Resources/translations/security.ro.xlf b/src/Symfony/Component/Security/Core/Resources/translations/security.ro.xlf index 440f11036770d..f35a2bb815878 100644 --- a/src/Symfony/Component/Security/Core/Resources/translations/security.ro.xlf +++ b/src/Symfony/Component/Security/Core/Resources/translations/security.ro.xlf @@ -30,10 +30,6 @@ Invalid CSRF token. Tokenul CSRF este invalid. - - Digest nonce has expired. - Tokenul temporar a expirat. - No authentication provider found to support the authentication token. Nu a fost găsit nici un agent de autentificare pentru tokenul specificat. diff --git a/src/Symfony/Component/Security/Core/Resources/translations/security.ru.xlf b/src/Symfony/Component/Security/Core/Resources/translations/security.ru.xlf index 1964f95e09a64..3f2690b2d3d7c 100644 --- a/src/Symfony/Component/Security/Core/Resources/translations/security.ru.xlf +++ b/src/Symfony/Component/Security/Core/Resources/translations/security.ru.xlf @@ -30,10 +30,6 @@ Invalid CSRF token. Недействительный токен CSRF. - - Digest nonce has expired. - Время действия одноразового ключа дайджеста истекло. - No authentication provider found to support the authentication token. Не найден провайдер аутентификации, поддерживающий токен аутентификации. diff --git a/src/Symfony/Component/Security/Core/Resources/translations/security.sk.xlf b/src/Symfony/Component/Security/Core/Resources/translations/security.sk.xlf index e6552a6a0914e..1447b4ef5a3c8 100644 --- a/src/Symfony/Component/Security/Core/Resources/translations/security.sk.xlf +++ b/src/Symfony/Component/Security/Core/Resources/translations/security.sk.xlf @@ -30,10 +30,6 @@ Invalid CSRF token. Neplatný CSRF token. - - Digest nonce has expired. - Platnosť inicializačného vektoru (digest nonce) skončila. - No authentication provider found to support the authentication token. Poskytovateľ pre overovací token nebol nájdený. diff --git a/src/Symfony/Component/Security/Core/Resources/translations/security.sl.xlf b/src/Symfony/Component/Security/Core/Resources/translations/security.sl.xlf index ee70c9aaa4af0..bc171812f8de3 100644 --- a/src/Symfony/Component/Security/Core/Resources/translations/security.sl.xlf +++ b/src/Symfony/Component/Security/Core/Resources/translations/security.sl.xlf @@ -30,10 +30,6 @@ Invalid CSRF token. Neveljaven CSRF žeton. - - Digest nonce has expired. - Začasni žeton je potekel. - No authentication provider found to support the authentication token. Ponudnika avtentikacije za podporo prijavnega žetona ni bilo mogoče najti. diff --git a/src/Symfony/Component/Security/Core/Resources/translations/security.sr_Cyrl.xlf b/src/Symfony/Component/Security/Core/Resources/translations/security.sr_Cyrl.xlf index 35e4ddf29b28c..f677254cce202 100644 --- a/src/Symfony/Component/Security/Core/Resources/translations/security.sr_Cyrl.xlf +++ b/src/Symfony/Component/Security/Core/Resources/translations/security.sr_Cyrl.xlf @@ -30,10 +30,6 @@ Invalid CSRF token. Невалидан CSRF токен. - - Digest nonce has expired. - Време криптографског кључа је истекло. - No authentication provider found to support the authentication token. Аутентификациони провајдер за подршку токена није пронађен. diff --git a/src/Symfony/Component/Security/Core/Resources/translations/security.sr_Latn.xlf b/src/Symfony/Component/Security/Core/Resources/translations/security.sr_Latn.xlf index ddc48076a2a6e..a38c75a9f810f 100644 --- a/src/Symfony/Component/Security/Core/Resources/translations/security.sr_Latn.xlf +++ b/src/Symfony/Component/Security/Core/Resources/translations/security.sr_Latn.xlf @@ -30,10 +30,6 @@ Invalid CSRF token. Nevalidan CSRF token. - - Digest nonce has expired. - Vreme kriptografskog ključa je isteklo. - No authentication provider found to support the authentication token. Autentifikacioni provajder za podršku tokena nije pronađen. diff --git a/src/Symfony/Component/Security/Core/Resources/translations/security.sv.xlf b/src/Symfony/Component/Security/Core/Resources/translations/security.sv.xlf index b5f62092365fa..ec3616f58620f 100644 --- a/src/Symfony/Component/Security/Core/Resources/translations/security.sv.xlf +++ b/src/Symfony/Component/Security/Core/Resources/translations/security.sv.xlf @@ -30,10 +30,6 @@ Invalid CSRF token. Ogiltig CSRF-token. - - Digest nonce has expired. - Förfallen digest nonce. - No authentication provider found to support the authentication token. Ingen leverantör för autentisering hittades för angiven autentiseringstoken. diff --git a/src/Symfony/Component/Security/Core/Resources/translations/security.th.xlf b/src/Symfony/Component/Security/Core/Resources/translations/security.th.xlf index a8cb8d5ce7e3b..84ae66769c611 100644 --- a/src/Symfony/Component/Security/Core/Resources/translations/security.th.xlf +++ b/src/Symfony/Component/Security/Core/Resources/translations/security.th.xlf @@ -30,10 +30,6 @@ Invalid CSRF token. CSRF token ไม่ถูกต้อง - - Digest nonce has expired. - Digest nonce หมดอายุ - No authentication provider found to support the authentication token. ไม่พบ authentication provider ที่รองรับสำหรับ authentication token diff --git a/src/Symfony/Component/Security/Core/Resources/translations/security.tr.xlf b/src/Symfony/Component/Security/Core/Resources/translations/security.tr.xlf index 68c44213d18c3..1ffa76e4d4457 100644 --- a/src/Symfony/Component/Security/Core/Resources/translations/security.tr.xlf +++ b/src/Symfony/Component/Security/Core/Resources/translations/security.tr.xlf @@ -30,10 +30,6 @@ Invalid CSRF token. Geçersiz CSRF fişi. - - Digest nonce has expired. - Derleme zaman aşımına uğradı. - No authentication provider found to support the authentication token. Yetkilendirme fişini destekleyecek yetkilendirme sağlayıcısı bulunamadı. diff --git a/src/Symfony/Component/Security/Core/Resources/translations/security.ua.xlf b/src/Symfony/Component/Security/Core/Resources/translations/security.ua.xlf index 79721212068db..f60a9c18eb711 100644 --- a/src/Symfony/Component/Security/Core/Resources/translations/security.ua.xlf +++ b/src/Symfony/Component/Security/Core/Resources/translations/security.ua.xlf @@ -30,10 +30,6 @@ Invalid CSRF token. Невірний токен CSRF. - - Digest nonce has expired. - Закінчився термін дії одноразового ключа дайджесту. - No authentication provider found to support the authentication token. Не знайдено провайдера автентифікації, що підтримує токен автентифікаціії. diff --git a/src/Symfony/Component/Security/Core/Resources/translations/security.vi.xlf b/src/Symfony/Component/Security/Core/Resources/translations/security.vi.xlf index b85a43995fc0a..87e20252183f0 100644 --- a/src/Symfony/Component/Security/Core/Resources/translations/security.vi.xlf +++ b/src/Symfony/Component/Security/Core/Resources/translations/security.vi.xlf @@ -30,10 +30,6 @@ Invalid CSRF token. Mã CSRF không hợp lệ. - - Digest nonce has expired. - Mã dùng một lần đã hết hạn. - No authentication provider found to support the authentication token. Không tìm thấy nhà cung cấp dịch vụ xác thực nào cho mã xác thực mà bạn sử dụng. diff --git a/src/Symfony/Component/Security/Core/Resources/translations/security.zh_CN.xlf b/src/Symfony/Component/Security/Core/Resources/translations/security.zh_CN.xlf index 2d6affecec2cc..460c0ac68bf48 100644 --- a/src/Symfony/Component/Security/Core/Resources/translations/security.zh_CN.xlf +++ b/src/Symfony/Component/Security/Core/Resources/translations/security.zh_CN.xlf @@ -30,10 +30,6 @@ Invalid CSRF token. 无效的 CSRF token 。 - - Digest nonce has expired. - 摘要随机串(digest nonce)已过期。 - No authentication provider found to support the authentication token. 没有找到支持此 token 的身份验证服务提供方。 diff --git a/src/Symfony/Component/Security/Http/EntryPoint/DigestAuthenticationEntryPoint.php b/src/Symfony/Component/Security/Http/EntryPoint/DigestAuthenticationEntryPoint.php deleted file mode 100644 index 9dfd5929459fb..0000000000000 --- a/src/Symfony/Component/Security/Http/EntryPoint/DigestAuthenticationEntryPoint.php +++ /dev/null @@ -1,82 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Security\Http\EntryPoint; - -use Symfony\Component\Security\Core\Exception\AuthenticationException; -use Symfony\Component\Security\Core\Exception\NonceExpiredException; -use Symfony\Component\HttpFoundation\Response; -use Symfony\Component\HttpFoundation\Request; -use Psr\Log\LoggerInterface; - -/** - * DigestAuthenticationEntryPoint starts an HTTP Digest authentication. - * - * @author Fabien Potencier - */ -class DigestAuthenticationEntryPoint implements AuthenticationEntryPointInterface -{ - private $secret; - private $realmName; - private $nonceValiditySeconds; - private $logger; - - public function __construct($realmName, $secret, $nonceValiditySeconds = 300, LoggerInterface $logger = null) - { - $this->realmName = $realmName; - $this->secret = $secret; - $this->nonceValiditySeconds = $nonceValiditySeconds; - $this->logger = $logger; - } - - /** - * {@inheritdoc} - */ - public function start(Request $request, AuthenticationException $authException = null) - { - $expiryTime = microtime(true) + $this->nonceValiditySeconds * 1000; - $signatureValue = md5($expiryTime.':'.$this->secret); - $nonceValue = $expiryTime.':'.$signatureValue; - $nonceValueBase64 = base64_encode($nonceValue); - - $authenticateHeader = sprintf('Digest realm="%s", qop="auth", nonce="%s"', $this->realmName, $nonceValueBase64); - - if ($authException instanceof NonceExpiredException) { - $authenticateHeader .= ', stale="true"'; - } - - if (null !== $this->logger) { - $this->logger->debug('WWW-Authenticate header sent.', array('header' => $authenticateHeader)); - } - - $response = new Response(); - $response->headers->set('WWW-Authenticate', $authenticateHeader); - $response->setStatusCode(401); - - return $response; - } - - /** - * @return string - */ - public function getSecret() - { - return $this->secret; - } - - /** - * @return string - */ - public function getRealmName() - { - return $this->realmName; - } -} diff --git a/src/Symfony/Component/Security/Http/Firewall/DigestAuthenticationListener.php b/src/Symfony/Component/Security/Http/Firewall/DigestAuthenticationListener.php deleted file mode 100644 index 4479a5cae9dc1..0000000000000 --- a/src/Symfony/Component/Security/Http/Firewall/DigestAuthenticationListener.php +++ /dev/null @@ -1,219 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Security\Http\Firewall; - -use Symfony\Component\Security\Core\User\UserProviderInterface; -use Symfony\Component\Security\Http\EntryPoint\DigestAuthenticationEntryPoint; -use Psr\Log\LoggerInterface; -use Symfony\Component\HttpKernel\Event\GetResponseEvent; -use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken; -use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface; -use Symfony\Component\Security\Core\Exception\BadCredentialsException; -use Symfony\Component\Security\Core\Exception\AuthenticationServiceException; -use Symfony\Component\Security\Core\Exception\UsernameNotFoundException; -use Symfony\Component\Security\Core\Exception\NonceExpiredException; -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\Security\Core\Exception\AuthenticationException; - -/** - * DigestAuthenticationListener implements Digest HTTP authentication. - * - * @author Fabien Potencier - */ -class DigestAuthenticationListener implements ListenerInterface -{ - private $tokenStorage; - private $provider; - private $providerKey; - private $authenticationEntryPoint; - private $logger; - - public function __construct(TokenStorageInterface $tokenStorage, UserProviderInterface $provider, $providerKey, DigestAuthenticationEntryPoint $authenticationEntryPoint, LoggerInterface $logger = null) - { - if (empty($providerKey)) { - throw new \InvalidArgumentException('$providerKey must not be empty.'); - } - - $this->tokenStorage = $tokenStorage; - $this->provider = $provider; - $this->providerKey = $providerKey; - $this->authenticationEntryPoint = $authenticationEntryPoint; - $this->logger = $logger; - } - - /** - * Handles digest authentication. - * - * @param GetResponseEvent $event A GetResponseEvent instance - * - * @throws AuthenticationServiceException - */ - public function handle(GetResponseEvent $event) - { - $request = $event->getRequest(); - - if (!$header = $request->server->get('PHP_AUTH_DIGEST')) { - return; - } - - $digestAuth = new DigestData($header); - - if (null !== $token = $this->tokenStorage->getToken()) { - if ($token instanceof UsernamePasswordToken && $token->isAuthenticated() && $token->getUsername() === $digestAuth->getUsername()) { - return; - } - } - - if (null !== $this->logger) { - $this->logger->debug('Digest Authorization header received from user agent.', array('header' => $header)); - } - - try { - $digestAuth->validateAndDecode($this->authenticationEntryPoint->getSecret(), $this->authenticationEntryPoint->getRealmName()); - } catch (BadCredentialsException $e) { - $this->fail($event, $request, $e); - - return; - } - - try { - $user = $this->provider->loadUserByUsername($digestAuth->getUsername()); - - if (null === $user) { - throw new AuthenticationServiceException('Digest User provider returned null, which is an interface contract violation'); - } - - $serverDigestMd5 = $digestAuth->calculateServerDigest($user->getPassword(), $request->getMethod()); - } catch (UsernameNotFoundException $e) { - $this->fail($event, $request, new BadCredentialsException(sprintf('Username %s not found.', $digestAuth->getUsername()))); - - return; - } - - if (!hash_equals($serverDigestMd5, $digestAuth->getResponse())) { - if (null !== $this->logger) { - $this->logger->debug('Unexpected response from the DigestAuth received; is the header returning a clear text passwords?', array('expected' => $serverDigestMd5, 'received' => $digestAuth->getResponse())); - } - - $this->fail($event, $request, new BadCredentialsException('Incorrect response')); - - return; - } - - if ($digestAuth->isNonceExpired()) { - $this->fail($event, $request, new NonceExpiredException('Nonce has expired/timed out.')); - - return; - } - - if (null !== $this->logger) { - $this->logger->info('Digest authentication successful.', array('username' => $digestAuth->getUsername(), 'received' => $digestAuth->getResponse())); - } - - $this->tokenStorage->setToken(new UsernamePasswordToken($user, $user->getPassword(), $this->providerKey)); - } - - private function fail(GetResponseEvent $event, Request $request, AuthenticationException $authException) - { - $token = $this->tokenStorage->getToken(); - if ($token instanceof UsernamePasswordToken && $this->providerKey === $token->getProviderKey()) { - $this->tokenStorage->setToken(null); - } - - if (null !== $this->logger) { - $this->logger->info('Digest authentication failed.', array('exception' => $authException)); - } - - $event->setResponse($this->authenticationEntryPoint->start($request, $authException)); - } -} - -class DigestData -{ - private $elements = array(); - private $header; - private $nonceExpiryTime; - - public function __construct($header) - { - $this->header = $header; - preg_match_all('/(\w+)=("((?:[^"\\\\]|\\\\.)+)"|([^\s,$]+))/', $header, $matches, PREG_SET_ORDER); - foreach ($matches as $match) { - if (isset($match[1]) && isset($match[3])) { - $this->elements[$match[1]] = isset($match[4]) ? $match[4] : $match[3]; - } - } - } - - public function getResponse() - { - return $this->elements['response']; - } - - public function getUsername() - { - return strtr($this->elements['username'], array('\\"' => '"', '\\\\' => '\\')); - } - - public function validateAndDecode($entryPointKey, $expectedRealm) - { - if ($keys = array_diff(array('username', 'realm', 'nonce', 'uri', 'response'), array_keys($this->elements))) { - throw new BadCredentialsException(sprintf('Missing mandatory digest value; received header "%s" (%s)', $this->header, implode(', ', $keys))); - } - - if ('auth' === $this->elements['qop'] && !isset($this->elements['nc'], $this->elements['cnonce'])) { - throw new BadCredentialsException(sprintf('Missing mandatory digest value; received header "%s"', $this->header)); - } - - if ($expectedRealm !== $this->elements['realm']) { - throw new BadCredentialsException(sprintf('Response realm name "%s" does not match system realm name of "%s".', $this->elements['realm'], $expectedRealm)); - } - - if (false === $nonceAsPlainText = base64_decode($this->elements['nonce'])) { - throw new BadCredentialsException(sprintf('Nonce is not encoded in Base64; received nonce "%s".', $this->elements['nonce'])); - } - - $nonceTokens = explode(':', $nonceAsPlainText); - - if (2 !== count($nonceTokens)) { - throw new BadCredentialsException(sprintf('Nonce should have yielded two tokens but was "%s".', $nonceAsPlainText)); - } - - $this->nonceExpiryTime = $nonceTokens[0]; - - if (md5($this->nonceExpiryTime.':'.$entryPointKey) !== $nonceTokens[1]) { - throw new BadCredentialsException(sprintf('Nonce token compromised "%s".', $nonceAsPlainText)); - } - } - - public function calculateServerDigest($password, $httpMethod) - { - $a2Md5 = md5(strtoupper($httpMethod).':'.$this->elements['uri']); - $a1Md5 = md5($this->elements['username'].':'.$this->elements['realm'].':'.$password); - - $digest = $a1Md5.':'.$this->elements['nonce']; - if (!isset($this->elements['qop'])) { - } elseif ('auth' === $this->elements['qop']) { - $digest .= ':'.$this->elements['nc'].':'.$this->elements['cnonce'].':'.$this->elements['qop']; - } else { - throw new \InvalidArgumentException(sprintf('This method does not support a qop: "%s".', $this->elements['qop'])); - } - $digest .= ':'.$a2Md5; - - return md5($digest); - } - - public function isNonceExpired() - { - return $this->nonceExpiryTime < microtime(true); - } -} diff --git a/src/Symfony/Component/Security/Http/Tests/EntryPoint/DigestAuthenticationEntryPointTest.php b/src/Symfony/Component/Security/Http/Tests/EntryPoint/DigestAuthenticationEntryPointTest.php deleted file mode 100644 index e08570dbbd9fc..0000000000000 --- a/src/Symfony/Component/Security/Http/Tests/EntryPoint/DigestAuthenticationEntryPointTest.php +++ /dev/null @@ -1,57 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Security\Http\Tests\EntryPoint; - -use PHPUnit\Framework\TestCase; -use Symfony\Component\Security\Http\EntryPoint\DigestAuthenticationEntryPoint; -use Symfony\Component\Security\Core\Exception\AuthenticationException; -use Symfony\Component\Security\Core\Exception\NonceExpiredException; - -class DigestAuthenticationEntryPointTest extends TestCase -{ - public function testStart() - { - $request = $this->getMockBuilder('Symfony\Component\HttpFoundation\Request')->getMock(); - - $authenticationException = new AuthenticationException('TheAuthenticationExceptionMessage'); - - $entryPoint = new DigestAuthenticationEntryPoint('TheRealmName', 'TheSecret'); - $response = $entryPoint->start($request, $authenticationException); - - $this->assertEquals(401, $response->getStatusCode()); - $this->assertRegExp('/^Digest realm="TheRealmName", qop="auth", nonce="[a-zA-Z0-9\/+]+={0,2}"$/', $response->headers->get('WWW-Authenticate')); - } - - public function testStartWithNoException() - { - $request = $this->getMockBuilder('Symfony\Component\HttpFoundation\Request')->getMock(); - - $entryPoint = new DigestAuthenticationEntryPoint('TheRealmName', 'TheSecret'); - $response = $entryPoint->start($request); - - $this->assertEquals(401, $response->getStatusCode()); - $this->assertRegExp('/^Digest realm="TheRealmName", qop="auth", nonce="[a-zA-Z0-9\/+]+={0,2}"$/', $response->headers->get('WWW-Authenticate')); - } - - public function testStartWithNonceExpiredException() - { - $request = $this->getMockBuilder('Symfony\Component\HttpFoundation\Request')->getMock(); - - $nonceExpiredException = new NonceExpiredException('TheNonceExpiredExceptionMessage'); - - $entryPoint = new DigestAuthenticationEntryPoint('TheRealmName', 'TheSecret'); - $response = $entryPoint->start($request, $nonceExpiredException); - - $this->assertEquals(401, $response->getStatusCode()); - $this->assertRegExp('/^Digest realm="TheRealmName", qop="auth", nonce="[a-zA-Z0-9\/+]+={0,2}", stale="true"$/', $response->headers->get('WWW-Authenticate')); - } -} diff --git a/src/Symfony/Component/Security/Http/Tests/Firewall/DigestAuthenticationListenerTest.php b/src/Symfony/Component/Security/Http/Tests/Firewall/DigestAuthenticationListenerTest.php deleted file mode 100644 index 495dae4262162..0000000000000 --- a/src/Symfony/Component/Security/Http/Tests/Firewall/DigestAuthenticationListenerTest.php +++ /dev/null @@ -1,80 +0,0 @@ -calculateServerDigest($username, $realm, $password, $nc, $nonce, $cnonce, $qop, 'GET', $uri); - - $digestData = - 'username="'.$username.'", realm="'.$realm.'", nonce="'.$nonce.'", '. - 'uri="'.$uri.'", cnonce="'.$cnonce.'", nc='.$nc.', qop="'.$qop.'", '. - 'response="'.$serverDigest.'"' - ; - - $request = new Request(array(), array(), array(), array(), array(), array('PHP_AUTH_DIGEST' => $digestData)); - - $entryPoint = new DigestAuthenticationEntryPoint($realm, $secret); - - $user = $this->getMockBuilder('Symfony\Component\Security\Core\User\UserInterface')->getMock(); - $user->method('getPassword')->willReturn($password); - - $providerKey = 'TheProviderKey'; - - $tokenStorage = $this->getMockBuilder('Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface')->getMock(); - $tokenStorage - ->expects($this->once()) - ->method('getToken') - ->will($this->returnValue(null)) - ; - $tokenStorage - ->expects($this->once()) - ->method('setToken') - ->with($this->equalTo(new UsernamePasswordToken($user, $password, $providerKey))) - ; - - $userProvider = $this->getMockBuilder('Symfony\Component\Security\Core\User\UserProviderInterface')->getMock(); - $userProvider->method('loadUserByUsername')->willReturn($user); - - $listener = new DigestAuthenticationListener($tokenStorage, $userProvider, $providerKey, $entryPoint); - - $event = $this->getMockBuilder('Symfony\Component\HttpKernel\Event\GetResponseEvent')->disableOriginalConstructor()->getMock(); - $event - ->expects($this->any()) - ->method('getRequest') - ->will($this->returnValue($request)) - ; - - $listener->handle($event); - } - - private function calculateServerDigest($username, $realm, $password, $nc, $nonce, $cnonce, $qop, $method, $uri) - { - $response = md5( - md5($username.':'.$realm.':'.$password).':'.$nonce.':'.$nc.':'.$cnonce.':'.$qop.':'.md5($method.':'.$uri) - ); - - return sprintf('username="%s", realm="%s", nonce="%s", uri="%s", cnonce="%s", nc=%s, qop="%s", response="%s"', - $username, $realm, $nonce, $uri, $cnonce, $nc, $qop, $response - ); - } -} diff --git a/src/Symfony/Component/Security/Http/Tests/Firewall/DigestDataTest.php b/src/Symfony/Component/Security/Http/Tests/Firewall/DigestDataTest.php deleted file mode 100644 index 7317e2f83c7cc..0000000000000 --- a/src/Symfony/Component/Security/Http/Tests/Firewall/DigestDataTest.php +++ /dev/null @@ -1,185 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Security\Http\Tests\Firewall; - -use PHPUnit\Framework\TestCase; -use Symfony\Component\Security\Http\Firewall\DigestData; - -class DigestDataTest extends TestCase -{ - public function testGetResponse() - { - $digestAuth = new DigestData( - 'username="user", realm="Welcome, robot!", '. - 'nonce="MTM0NzMyMTgyMy42NzkzOmRlZjM4NmIzOGNjMjE0OWJiNDU0MDAxNzJmYmM1MmZl", '. - 'uri="/path/info?p1=5&p2=5", cnonce="MDIwODkz", nc=00000001, qop="auth", '. - 'response="b52938fc9e6d7c01be7702ece9031b42"' - ); - - $this->assertEquals('b52938fc9e6d7c01be7702ece9031b42', $digestAuth->getResponse()); - } - - public function testGetUsername() - { - $digestAuth = new DigestData( - 'username="user", realm="Welcome, robot!", '. - 'nonce="MTM0NzMyMTgyMy42NzkzOmRlZjM4NmIzOGNjMjE0OWJiNDU0MDAxNzJmYmM1MmZl", '. - 'uri="/path/info?p1=5&p2=5", cnonce="MDIwODkz", nc=00000001, qop="auth", '. - 'response="b52938fc9e6d7c01be7702ece9031b42"' - ); - - $this->assertEquals('user', $digestAuth->getUsername()); - } - - public function testGetUsernameWithQuote() - { - $digestAuth = new DigestData( - 'username="\"user\"", realm="Welcome, robot!", '. - 'nonce="MTM0NzMyMTgyMy42NzkzOmRlZjM4NmIzOGNjMjE0OWJiNDU0MDAxNzJmYmM1MmZl", '. - 'uri="/path/info?p1=5&p2=5", cnonce="MDIwODkz", nc=00000001, qop="auth", '. - 'response="b52938fc9e6d7c01be7702ece9031b42"' - ); - - $this->assertEquals('"user"', $digestAuth->getUsername()); - } - - public function testGetUsernameWithQuoteAndEscape() - { - $digestAuth = new DigestData( - 'username="\"u\\\\\"ser\"", realm="Welcome, robot!", '. - 'nonce="MTM0NzMyMTgyMy42NzkzOmRlZjM4NmIzOGNjMjE0OWJiNDU0MDAxNzJmYmM1MmZl", '. - 'uri="/path/info?p1=5&p2=5", cnonce="MDIwODkz", nc=00000001, qop="auth", '. - 'response="b52938fc9e6d7c01be7702ece9031b42"' - ); - - $this->assertEquals('"u\\"ser"', $digestAuth->getUsername()); - } - - public function testGetUsernameWithSingleQuote() - { - $digestAuth = new DigestData( - 'username="\"u\'ser\"", realm="Welcome, robot!", '. - 'nonce="MTM0NzMyMTgyMy42NzkzOmRlZjM4NmIzOGNjMjE0OWJiNDU0MDAxNzJmYmM1MmZl", '. - 'uri="/path/info?p1=5&p2=5", cnonce="MDIwODkz", nc=00000001, qop="auth", '. - 'response="b52938fc9e6d7c01be7702ece9031b42"' - ); - - $this->assertEquals('"u\'ser"', $digestAuth->getUsername()); - } - - public function testGetUsernameWithSingleQuoteAndEscape() - { - $digestAuth = new DigestData( - 'username="\"u\\\'ser\"", realm="Welcome, robot!", '. - 'nonce="MTM0NzMyMTgyMy42NzkzOmRlZjM4NmIzOGNjMjE0OWJiNDU0MDAxNzJmYmM1MmZl", '. - 'uri="/path/info?p1=5&p2=5", cnonce="MDIwODkz", nc=00000001, qop="auth", '. - 'response="b52938fc9e6d7c01be7702ece9031b42"' - ); - - $this->assertEquals('"u\\\'ser"', $digestAuth->getUsername()); - } - - public function testGetUsernameWithEscape() - { - $digestAuth = new DigestData( - 'username="\"u\\ser\"", realm="Welcome, robot!", '. - 'nonce="MTM0NzMyMTgyMy42NzkzOmRlZjM4NmIzOGNjMjE0OWJiNDU0MDAxNzJmYmM1MmZl", '. - 'uri="/path/info?p1=5&p2=5", cnonce="MDIwODkz", nc=00000001, qop="auth", '. - 'response="b52938fc9e6d7c01be7702ece9031b42"' - ); - - $this->assertEquals('"u\\ser"', $digestAuth->getUsername()); - } - - /** - * @group time-sensitive - */ - public function testValidateAndDecode() - { - $time = microtime(true); - $key = 'ThisIsAKey'; - $nonce = base64_encode($time.':'.md5($time.':'.$key)); - - $digestAuth = new DigestData( - 'username="user", realm="Welcome, robot!", nonce="'.$nonce.'", '. - 'uri="/path/info?p1=5&p2=5", cnonce="MDIwODkz", nc=00000001, qop="auth", '. - 'response="b52938fc9e6d7c01be7702ece9031b42"' - ); - - $digestAuth->validateAndDecode($key, 'Welcome, robot!'); - - sleep(1); - - $this->assertTrue($digestAuth->isNonceExpired()); - } - - public function testCalculateServerDigest() - { - $this->calculateServerDigest('user', 'Welcome, robot!', 'pass,word=password', 'ThisIsAKey', '00000001', 'MDIwODkz', 'auth', 'GET', '/path/info?p1=5&p2=5'); - } - - public function testCalculateServerDigestWithQuote() - { - $this->calculateServerDigest('\"user\"', 'Welcome, \"robot\"!', 'pass,word=password', 'ThisIsAKey', '00000001', 'MDIwODkz', 'auth', 'GET', '/path/info?p1=5&p2=5'); - } - - public function testCalculateServerDigestWithQuoteAndEscape() - { - $this->calculateServerDigest('\"u\\\\\"ser\"', 'Welcome, \"robot\"!', 'pass,word=password', 'ThisIsAKey', '00000001', 'MDIwODkz', 'auth', 'GET', '/path/info?p1=5&p2=5'); - } - - public function testCalculateServerDigestEscape() - { - $this->calculateServerDigest('\"u\\ser\"', 'Welcome, \"robot\"!', 'pass,word=password', 'ThisIsAKey', '00000001', 'MDIwODkz', 'auth', 'GET', '/path/info?p1=5&p2=5'); - $this->calculateServerDigest('\"u\\ser\\\\\"', 'Welcome, \"robot\"!', 'pass,word=password', 'ThisIsAKey', '00000001', 'MDIwODkz', 'auth', 'GET', '/path/info?p1=5&p2=5'); - } - - public function testIsNonceExpired() - { - $time = microtime(true) + 10; - $key = 'ThisIsAKey'; - $nonce = base64_encode($time.':'.md5($time.':'.$key)); - - $digestAuth = new DigestData( - 'username="user", realm="Welcome, robot!", nonce="'.$nonce.'", '. - 'uri="/path/info?p1=5&p2=5", cnonce="MDIwODkz", nc=00000001, qop="auth", '. - 'response="b52938fc9e6d7c01be7702ece9031b42"' - ); - - $digestAuth->validateAndDecode($key, 'Welcome, robot!'); - - $this->assertFalse($digestAuth->isNonceExpired()); - } - - protected function setUp() - { - class_exists('Symfony\Component\Security\Http\Firewall\DigestAuthenticationListener', true); - } - - private function calculateServerDigest($username, $realm, $password, $key, $nc, $cnonce, $qop, $method, $uri) - { - $time = microtime(true); - $nonce = base64_encode($time.':'.md5($time.':'.$key)); - - $response = md5( - md5($username.':'.$realm.':'.$password).':'.$nonce.':'.$nc.':'.$cnonce.':'.$qop.':'.md5($method.':'.$uri) - ); - - $digest = sprintf('username="%s", realm="%s", nonce="%s", uri="%s", cnonce="%s", nc=%s, qop="%s", response="%s"', - $username, $realm, $nonce, $uri, $cnonce, $nc, $qop, $response - ); - - $digestAuth = new DigestData($digest); - - $this->assertEquals($digestAuth->getResponse(), $digestAuth->calculateServerDigest($password, $method)); - } -} From a8a0a2104929e24e9f0440618d2821ed89ad3969 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Mon, 11 Sep 2017 11:36:05 -0700 Subject: [PATCH 0912/1099] [HttpKernel] removed bundle inheritance --- .../Controller/ControllerNameParser.php | 31 +-- .../Controller/ControllerNameParserTest.php | 10 +- .../FrameworkExtensionTest.php | 8 +- .../DependencyInjection/TwigExtension.php | 55 +--- .../Resources/views/layout.html.twig | 1 - .../Resources/views/layout.html.twig | 1 - .../Resources/views/layout.html.twig | 1 - .../Resources/views/layout.html.twig | 1 - .../DependencyInjection/TwigExtensionTest.php | 39 --- .../Component/HttpKernel/Bundle/Bundle.php | 9 - .../HttpKernel/Bundle/BundleInterface.php | 13 - src/Symfony/Component/HttpKernel/Kernel.php | 108 ++------ .../Component/HttpKernel/KernelInterface.php | 12 +- .../Component/HttpKernel/Tests/KernelTest.php | 242 +----------------- 14 files changed, 50 insertions(+), 481 deletions(-) delete mode 100644 src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/Fixtures/Bundle/ChildChildChildChildTwigBundle/Resources/views/layout.html.twig delete mode 100644 src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/Fixtures/Bundle/ChildChildChildTwigBundle/Resources/views/layout.html.twig delete mode 100644 src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/Fixtures/Bundle/ChildChildTwigBundle/Resources/views/layout.html.twig delete mode 100644 src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/Fixtures/Bundle/ChildTwigBundle/Resources/views/layout.html.twig diff --git a/src/Symfony/Bundle/FrameworkBundle/Controller/ControllerNameParser.php b/src/Symfony/Bundle/FrameworkBundle/Controller/ControllerNameParser.php index cf1ebdc128e42..30fa2c352b955 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Controller/ControllerNameParser.php +++ b/src/Symfony/Bundle/FrameworkBundle/Controller/ControllerNameParser.php @@ -52,47 +52,32 @@ public function parse($controller) } $originalController = $controller; - list($bundle, $controller, $action) = $parts; + list($bundleName, $controller, $action) = $parts; $controller = str_replace('/', '\\', $controller); - $bundles = array(); try { // this throws an exception if there is no such bundle - $allBundles = $this->kernel->getBundle($bundle, false, true); + $bundle = $this->kernel->getBundle($bundleName); } catch (\InvalidArgumentException $e) { $message = sprintf( 'The "%s" (from the _controller value "%s") does not exist or is not enabled in your kernel!', - $bundle, + $bundleName, $originalController ); - if ($alternative = $this->findAlternative($bundle)) { + if ($alternative = $this->findAlternative($bundleName)) { $message .= sprintf(' Did you mean "%s:%s:%s"?', $alternative, $controller, $action); } throw new \InvalidArgumentException($message, 0, $e); } - if (!is_array($allBundles)) { - // happens when HttpKernel is version 4+ - $allBundles = array($allBundles); + $try = $bundle->getNamespace().'\\Controller\\'.$controller.'Controller'; + if (class_exists($try)) { + return $try.'::'.$action.'Action'; } - foreach ($allBundles as $b) { - $try = $b->getNamespace().'\\Controller\\'.$controller.'Controller'; - if (class_exists($try)) { - return $try.'::'.$action.'Action'; - } - - $bundles[] = $b->getName(); - $msg = sprintf('The _controller value "%s:%s:%s" maps to a "%s" class, but this class was not found. Create this class or check the spelling of the class and its namespace.', $bundle, $controller, $action, $try); - } - - if (count($bundles) > 1) { - $msg = sprintf('Unable to find controller "%s:%s" in bundles %s.', $bundle, $controller, implode(', ', $bundles)); - } - - throw new \InvalidArgumentException($msg); + throw new \InvalidArgumentException(sprintf('The _controller value "%s:%s:%s" maps to a "%s" class, but this class was not found. Create this class or check the spelling of the class and its namespace.', $bundleName, $controller, $action, $try)); } /** diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/ControllerNameParserTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/ControllerNameParserTest.php index efe72b5b8029f..0dfed269ec20e 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/ControllerNameParserTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/ControllerNameParserTest.php @@ -40,7 +40,6 @@ public function testParse() $this->assertEquals('TestBundle\FooBundle\Controller\DefaultController::indexAction', $parser->parse('FooBundle:Default:index'), '->parse() converts a short a:b:c notation string to a class::method string'); $this->assertEquals('TestBundle\FooBundle\Controller\Sub\DefaultController::indexAction', $parser->parse('FooBundle:Sub\Default:index'), '->parse() converts a short a:b:c notation string to a class::method string'); - $this->assertEquals('TestBundle\Fabpot\FooBundle\Controller\DefaultController::indexAction', $parser->parse('SensioFooBundle:Default:index'), '->parse() converts a short a:b:c notation string to a class::method string'); $this->assertEquals('TestBundle\Sensio\Cms\FooBundle\Controller\DefaultController::indexAction', $parser->parse('SensioCmsFooBundle:Default:index'), '->parse() converts a short a:b:c notation string to a class::method string'); $this->assertEquals('TestBundle\FooBundle\Controller\Test\DefaultController::indexAction', $parser->parse('FooBundle:Test\\Default:index'), '->parse() converts a short a:b:c notation string to a class::method string'); $this->assertEquals('TestBundle\FooBundle\Controller\Test\DefaultController::indexAction', $parser->parse('FooBundle:Test/Default:index'), '->parse() converts a short a:b:c notation string to a class::method string'); @@ -138,7 +137,6 @@ public function getInvalidBundleNameTests() { return array( 'Alternative will be found using levenshtein' => array('FoodBundle:Default:index', 'FooBundle:Default:index'), - 'Alternative will be found using partial match' => array('FabpotFooBund:Default:index', 'FabpotFooBundle:Default:index'), 'Bundle does not exist at all' => array('CrazyBundle:Default:index', false), ); } @@ -146,10 +144,8 @@ public function getInvalidBundleNameTests() private function createParser() { $bundles = array( - 'SensioFooBundle' => array($this->getBundle('TestBundle\Fabpot\FooBundle', 'FabpotFooBundle'), $this->getBundle('TestBundle\Sensio\FooBundle', 'SensioFooBundle')), - 'SensioCmsFooBundle' => array($this->getBundle('TestBundle\Sensio\Cms\FooBundle', 'SensioCmsFooBundle')), - 'FooBundle' => array($this->getBundle('TestBundle\FooBundle', 'FooBundle')), - 'FabpotFooBundle' => array($this->getBundle('TestBundle\Fabpot\FooBundle', 'FabpotFooBundle'), $this->getBundle('TestBundle\Sensio\FooBundle', 'SensioFooBundle')), + 'SensioCmsFooBundle' => $this->getBundle('TestBundle\Sensio\Cms\FooBundle', 'SensioCmsFooBundle'), + 'FooBundle' => $this->getBundle('TestBundle\FooBundle', 'FooBundle'), ); $kernel = $this->getMockBuilder('Symfony\Component\HttpKernel\KernelInterface')->getMock(); @@ -166,11 +162,9 @@ private function createParser() ; $bundles = array( - 'SensioFooBundle' => $this->getBundle('TestBundle\Fabpot\FooBundle', 'FabpotFooBundle'), 'SensioCmsFooBundle' => $this->getBundle('TestBundle\Sensio\Cms\FooBundle', 'SensioCmsFooBundle'), 'FoooooBundle' => $this->getBundle('TestBundle\FooBundle', 'FoooooBundle'), 'FooBundle' => $this->getBundle('TestBundle\FooBundle', 'FooBundle'), - 'FabpotFooBundle' => $this->getBundle('TestBundle\Fabpot\FooBundle', 'FabpotFooBundle'), ); $kernel ->expects($this->any()) diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php index f313518dfc24b..8542a2f4f05c6 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php @@ -605,7 +605,7 @@ public function testValidationPaths() $container = $this->createContainerFromFile('validation_annotations', array( 'kernel.bundles' => array('TestBundle' => 'Symfony\\Bundle\\FrameworkBundle\\Tests\\TestBundle'), - 'kernel.bundles_metadata' => array('TestBundle' => array('namespace' => 'Symfony\\Bundle\\FrameworkBundle\\Tests', 'parent' => null, 'path' => __DIR__.'/Fixtures/TestBundle')), + 'kernel.bundles_metadata' => array('TestBundle' => array('namespace' => 'Symfony\\Bundle\\FrameworkBundle\\Tests', 'path' => __DIR__.'/Fixtures/TestBundle')), )); $calls = $container->getDefinition('validator.builder')->getMethodCalls(); @@ -641,7 +641,7 @@ public function testValidationPathsUsingCustomBundlePath() $container = $this->createContainerFromFile('validation_annotations', array( 'kernel.bundles' => array('CustomPathBundle' => 'Symfony\\Bundle\\FrameworkBundle\\Tests\\CustomPathBundle'), - 'kernel.bundles_metadata' => array('TestBundle' => array('namespace' => 'Symfony\\Bundle\\FrameworkBundle\\Tests', 'parent' => null, 'path' => __DIR__.'/Fixtures/CustomPathBundle')), + 'kernel.bundles_metadata' => array('TestBundle' => array('namespace' => 'Symfony\\Bundle\\FrameworkBundle\\Tests', 'path' => __DIR__.'/Fixtures/CustomPathBundle')), )); $calls = $container->getDefinition('validator.builder')->getMethodCalls(); @@ -848,7 +848,7 @@ public function testSerializerCacheDisabled() public function testSerializerMapping() { - $container = $this->createContainerFromFile('serializer_mapping', array('kernel.bundles_metadata' => array('TestBundle' => array('namespace' => 'Symfony\\Bundle\\FrameworkBundle\\Tests', 'path' => __DIR__.'/Fixtures/TestBundle', 'parent' => null)))); + $container = $this->createContainerFromFile('serializer_mapping', array('kernel.bundles_metadata' => array('TestBundle' => array('namespace' => 'Symfony\\Bundle\\FrameworkBundle\\Tests', 'path' => __DIR__.'/Fixtures/TestBundle')))); $configDir = __DIR__.'/Fixtures/TestBundle/Resources/config'; $expectedLoaders = array( new Definition(AnnotationLoader::class, array(new Reference('annotation_reader'))), @@ -980,7 +980,7 @@ protected function createContainer(array $data = array()) { return new ContainerBuilder(new ParameterBag(array_merge(array( 'kernel.bundles' => array('FrameworkBundle' => 'Symfony\\Bundle\\FrameworkBundle\\FrameworkBundle'), - 'kernel.bundles_metadata' => array('FrameworkBundle' => array('namespace' => 'Symfony\\Bundle\\FrameworkBundle', 'path' => __DIR__.'/../..', 'parent' => null)), + 'kernel.bundles_metadata' => array('FrameworkBundle' => array('namespace' => 'Symfony\\Bundle\\FrameworkBundle', 'path' => __DIR__.'/../..')), 'kernel.cache_dir' => __DIR__, 'kernel.project_dir' => __DIR__, 'kernel.debug' => false, diff --git a/src/Symfony/Bundle/TwigBundle/DependencyInjection/TwigExtension.php b/src/Symfony/Bundle/TwigBundle/DependencyInjection/TwigExtension.php index 408fd802e92c5..e58662406d3a4 100644 --- a/src/Symfony/Bundle/TwigBundle/DependencyInjection/TwigExtension.php +++ b/src/Symfony/Bundle/TwigBundle/DependencyInjection/TwigExtension.php @@ -109,18 +109,9 @@ public function load(array $configs, ContainerBuilder $container) $container->getDefinition('twig.cache_warmer')->replaceArgument(2, $config['paths']); $container->getDefinition('twig.template_iterator')->replaceArgument(2, $config['paths']); - $bundleHierarchy = $this->getBundleHierarchy($container, $config); - - foreach ($bundleHierarchy as $name => $bundle) { + foreach ($this->getBundleTemplatePaths($container, $config) as $name => $paths) { $namespace = $this->normalizeBundleName($name); - - foreach ($bundle['children'] as $child) { - foreach ($bundleHierarchy[$child]['paths'] as $path) { - $twigFilesystemLoaderDefinition->addMethodCall('addPath', array($path, $namespace)); - } - } - - foreach ($bundle['paths'] as $path) { + foreach ($paths as $path) { $twigFilesystemLoaderDefinition->addMethodCall('addPath', array($path, $namespace)); } } @@ -166,58 +157,24 @@ public function load(array $configs, ContainerBuilder $container) $container->registerForAutoconfiguration(RuntimeExtensionInterface::class)->addTag('twig.runtime'); } - private function getBundleHierarchy(ContainerBuilder $container, array $config) + private function getBundleTemplatePaths(ContainerBuilder $container, array $config) { $bundleHierarchy = array(); - foreach ($container->getParameter('kernel.bundles_metadata') as $name => $bundle) { - if (!array_key_exists($name, $bundleHierarchy)) { - $bundleHierarchy[$name] = array( - 'paths' => array(), - 'parents' => array(), - 'children' => array(), - ); - } - if (file_exists($dir = $container->getParameter('kernel.root_dir').'/Resources/'.$name.'/views')) { - $bundleHierarchy[$name]['paths'][] = $dir; + $bundleHierarchy[$name][] = $dir; } $container->addResource(new FileExistenceResource($dir)); if (file_exists($dir = $container->getParameterBag()->resolveValue($config['default_path']).'/bundles/'.$name)) { - $bundleHierarchy[$name]['paths'][] = $dir; + $bundleHierarchy[$name][] = $dir; } $container->addResource(new FileExistenceResource($dir)); if (file_exists($dir = $bundle['path'].'/Resources/views')) { - $bundleHierarchy[$name]['paths'][] = $dir; + $bundleHierarchy[$name][] = $dir; } $container->addResource(new FileExistenceResource($dir)); - - if (!isset($bundle['parent']) || null === $bundle['parent']) { - continue; - } - - $bundleHierarchy[$name]['parents'][] = $bundle['parent']; - - if (!array_key_exists($bundle['parent'], $bundleHierarchy)) { - $bundleHierarchy[$bundle['parent']] = array( - 'paths' => array(), - 'parents' => array(), - 'children' => array(), - ); - } - - $bundleHierarchy[$bundle['parent']]['children'] = array_merge($bundleHierarchy[$name]['children'], array($name), $bundleHierarchy[$bundle['parent']]['children']); - - foreach ($bundleHierarchy[$bundle['parent']]['parents'] as $parent) { - $bundleHierarchy[$name]['parents'][] = $parent; - $bundleHierarchy[$parent]['children'] = array_merge($bundleHierarchy[$name]['children'], array($name), $bundleHierarchy[$parent]['children']); - } - - foreach ($bundleHierarchy[$name]['children'] as $child) { - $bundleHierarchy[$child]['parents'] = array_merge($bundleHierarchy[$child]['parents'], $bundleHierarchy[$name]['parents']); - } } return $bundleHierarchy; diff --git a/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/Fixtures/Bundle/ChildChildChildChildTwigBundle/Resources/views/layout.html.twig b/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/Fixtures/Bundle/ChildChildChildChildTwigBundle/Resources/views/layout.html.twig deleted file mode 100644 index bb07ecfe55a36..0000000000000 --- a/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/Fixtures/Bundle/ChildChildChildChildTwigBundle/Resources/views/layout.html.twig +++ /dev/null @@ -1 +0,0 @@ -This is a layout diff --git a/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/Fixtures/Bundle/ChildChildChildTwigBundle/Resources/views/layout.html.twig b/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/Fixtures/Bundle/ChildChildChildTwigBundle/Resources/views/layout.html.twig deleted file mode 100644 index bb07ecfe55a36..0000000000000 --- a/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/Fixtures/Bundle/ChildChildChildTwigBundle/Resources/views/layout.html.twig +++ /dev/null @@ -1 +0,0 @@ -This is a layout diff --git a/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/Fixtures/Bundle/ChildChildTwigBundle/Resources/views/layout.html.twig b/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/Fixtures/Bundle/ChildChildTwigBundle/Resources/views/layout.html.twig deleted file mode 100644 index bb07ecfe55a36..0000000000000 --- a/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/Fixtures/Bundle/ChildChildTwigBundle/Resources/views/layout.html.twig +++ /dev/null @@ -1 +0,0 @@ -This is a layout diff --git a/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/Fixtures/Bundle/ChildTwigBundle/Resources/views/layout.html.twig b/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/Fixtures/Bundle/ChildTwigBundle/Resources/views/layout.html.twig deleted file mode 100644 index bb07ecfe55a36..0000000000000 --- a/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/Fixtures/Bundle/ChildTwigBundle/Resources/views/layout.html.twig +++ /dev/null @@ -1 +0,0 @@ -This is a layout diff --git a/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/TwigExtensionTest.php b/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/TwigExtensionTest.php index 9d47948d67b77..58756f1e3c8ab 100644 --- a/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/TwigExtensionTest.php +++ b/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/TwigExtensionTest.php @@ -188,23 +188,9 @@ public function testTwigLoaderPaths($format) array('namespaced_path1', 'namespace1'), array('namespaced_path2', 'namespace2'), array('namespaced_path3', 'namespace3'), - array(__DIR__.'/Fixtures/Bundle/ChildChildChildChildTwigBundle/Resources/views', 'ChildChildChildChildTwig'), - array(__DIR__.'/Fixtures/Bundle/ChildChildChildChildTwigBundle/Resources/views', 'ChildChildChildTwig'), - array(__DIR__.'/Fixtures/Bundle/ChildChildChildTwigBundle/Resources/views', 'ChildChildChildTwig'), - array(__DIR__.'/Fixtures/Bundle/ChildChildChildChildTwigBundle/Resources/views', 'Twig'), - array(__DIR__.'/Fixtures/Bundle/ChildChildChildTwigBundle/Resources/views', 'Twig'), - array(__DIR__.'/Fixtures/Bundle/ChildChildTwigBundle/Resources/views', 'Twig'), - array(__DIR__.'/Fixtures/Bundle/ChildTwigBundle/Resources/views', 'Twig'), array(__DIR__.'/Fixtures/Resources/TwigBundle/views', 'Twig'), array(__DIR__.'/Fixtures/templates/bundles/TwigBundle', 'Twig'), array(realpath(__DIR__.'/../..').'/Resources/views', 'Twig'), - array(__DIR__.'/Fixtures/Bundle/ChildChildChildChildTwigBundle/Resources/views', 'ChildTwig'), - array(__DIR__.'/Fixtures/Bundle/ChildChildChildTwigBundle/Resources/views', 'ChildTwig'), - array(__DIR__.'/Fixtures/Bundle/ChildChildTwigBundle/Resources/views', 'ChildTwig'), - array(__DIR__.'/Fixtures/Bundle/ChildTwigBundle/Resources/views', 'ChildTwig'), - array(__DIR__.'/Fixtures/Bundle/ChildChildChildChildTwigBundle/Resources/views', 'ChildChildTwig'), - array(__DIR__.'/Fixtures/Bundle/ChildChildChildTwigBundle/Resources/views', 'ChildChildTwig'), - array(__DIR__.'/Fixtures/Bundle/ChildChildTwigBundle/Resources/views', 'ChildChildTwig'), array(__DIR__.'/Fixtures/Resources/views'), array(__DIR__.'/Fixtures/templates'), ), $paths); @@ -284,37 +270,12 @@ private function createContainer() 'kernel.debug' => false, 'kernel.bundles' => array( 'TwigBundle' => 'Symfony\\Bundle\\TwigBundle\\TwigBundle', - 'ChildTwigBundle' => 'Symfony\\Bundle\\TwigBundle\\Tests\\DependencyInjection\\Fixtures\\Bundle\\ChildTwigBundle\\ChildTwigBundle', - 'ChildChildTwigBundle' => 'Symfony\\Bundle\\TwigBundle\\Tests\\DependencyInjection\\Fixtures\\Bundle\\ChildChildTwigBundle\\ChildChildTwigBundle', - 'ChildChildChildTwigBundle' => 'Symfony\\Bundle\\TwigBundle\\Tests\\DependencyInjection\\Fixtures\\Bundle\\ChildChildChildTwigBundle\\ChildChildChildTwigBundle', - 'ChildChildChildChildTwigBundle' => 'Symfony\\Bundle\\TwigBundle\\Tests\\DependencyInjection\\Fixtures\\Bundle\\ChildChildChildChildTwigBundle\\ChildChildChildChildTwigBundle', ), 'kernel.bundles_metadata' => array( - 'ChildChildChildChildTwigBundle' => array( - 'namespace' => 'Symfony\\Bundle\\TwigBundle\\Tests\\DependencyInjection\\Fixtures\\Bundle\\ChildChildChildChildTwigBundle\\ChildChildChildChildTwigBundle', - 'parent' => 'ChildChildChildTwigBundle', - 'path' => __DIR__.'/Fixtures/Bundle/ChildChildChildChildTwigBundle', - ), 'TwigBundle' => array( 'namespace' => 'Symfony\\Bundle\\TwigBundle', - 'parent' => null, 'path' => realpath(__DIR__.'/../..'), ), - 'ChildTwigBundle' => array( - 'namespace' => 'Symfony\\Bundle\\TwigBundle\\Tests\\DependencyInjection\\Fixtures\\Bundle\\ChildTwigBundle\\ChildTwigBundle', - 'parent' => 'TwigBundle', - 'path' => __DIR__.'/Fixtures/Bundle/ChildTwigBundle', - ), - 'ChildChildChildTwigBundle' => array( - 'namespace' => 'Symfony\\Bundle\\TwigBundle\\Tests\\DependencyInjection\\Fixtures\\Bundle\\ChildChildChildTwigBundle\\ChildChildChildTwigBundle', - 'parent' => 'ChildChildTwigBundle', - 'path' => __DIR__.'/Fixtures/Bundle/ChildChildChildTwigBundle', - ), - 'ChildChildTwigBundle' => array( - 'namespace' => 'Symfony\\Bundle\\TwigBundle\\Tests\\DependencyInjection\\Fixtures\\Bundle\\ChildChildTwigBundle\\ChildChildTwigBundle', - 'parent' => 'ChildTwigBundle', - 'path' => __DIR__.'/Fixtures/Bundle/ChildChildTwigBundle', - ), ), ))); diff --git a/src/Symfony/Component/HttpKernel/Bundle/Bundle.php b/src/Symfony/Component/HttpKernel/Bundle/Bundle.php index 609b48fd074a2..4cc4a2a24516b 100644 --- a/src/Symfony/Component/HttpKernel/Bundle/Bundle.php +++ b/src/Symfony/Component/HttpKernel/Bundle/Bundle.php @@ -128,15 +128,6 @@ public function getPath() return $this->path; } - /** - * Returns the bundle parent name. - * - * @return string|null The Bundle parent name it overrides or null if no parent - */ - public function getParent() - { - } - /** * Returns the bundle name (the class short name). * diff --git a/src/Symfony/Component/HttpKernel/Bundle/BundleInterface.php b/src/Symfony/Component/HttpKernel/Bundle/BundleInterface.php index f4a160c2fd587..1d58422527feb 100644 --- a/src/Symfony/Component/HttpKernel/Bundle/BundleInterface.php +++ b/src/Symfony/Component/HttpKernel/Bundle/BundleInterface.php @@ -48,19 +48,6 @@ public function build(ContainerBuilder $container); */ public function getContainerExtension(); - /** - * Returns the bundle name that this bundle overrides. - * - * Despite its name, this method does not imply any parent/child relationship - * between the bundles, just a way to extend and override an existing - * bundle. - * - * @return string The Bundle name it overrides or null if no parent - * - * @deprecated This method is deprecated as of 3.4 and will be removed in 4.0. - */ - public function getParent(); - /** * Returns the bundle name (the class short name). * diff --git a/src/Symfony/Component/HttpKernel/Kernel.php b/src/Symfony/Component/HttpKernel/Kernel.php index f4e677206c7cf..10fe0213e7578 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -50,7 +50,6 @@ abstract class Kernel implements KernelInterface, RebootableInterface, Terminabl */ protected $bundles = array(); - protected $bundleMap; protected $container; protected $rootDir; protected $environment; @@ -199,26 +198,13 @@ public function getBundles() /** * {@inheritdoc} */ - public function getBundle($name, $first = true/*, $noDeprecation = false */) + public function getBundle($name) { - $noDeprecation = false; - if (func_num_args() >= 3) { - $noDeprecation = func_get_arg(2); - } - - if (!$first && !$noDeprecation) { - @trigger_error(sprintf('Passing "false" as the second argument to %s() is deprecated as of 3.4 and will be removed in 4.0.', __METHOD__), E_USER_DEPRECATED); - } - - if (!isset($this->bundleMap[$name])) { + if (!isset($this->bundles[$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))); } - if (true === $first) { - return $this->bundleMap[$name][0]; - } - - return $this->bundleMap[$name]; + return $this->bundles[$name]; } /** @@ -245,32 +231,27 @@ public function locateResource($name, $dir = null, $first = true) $isResource = 0 === strpos($path, 'Resources') && null !== $dir; $overridePath = substr($path, 9); $resourceBundle = null; - $bundles = $this->getBundle($bundleName, false, true); + $bundle = $this->getBundle($bundleName); $files = array(); - foreach ($bundles as $bundle) { - if ($isResource && file_exists($file = $dir.'/'.$bundle->getName().$overridePath)) { - if (null !== $resourceBundle) { - throw new \RuntimeException(sprintf('"%s" resource is hidden by a resource from the "%s" derived bundle. Create a "%s" file to override the bundle resource.', - $file, - $resourceBundle, - $dir.'/'.$bundles[0]->getName().$overridePath - )); - } - - if ($first) { - return $file; - } - $files[] = $file; + if ($isResource && file_exists($file = $dir.'/'.$bundle->getName().$overridePath)) { + if (null !== $resourceBundle) { + throw new \RuntimeException(sprintf('"%s" resource is hidden by a resource from the "%s" derived bundle. Create a "%s" file to override the bundle resource.', + $file, + $resourceBundle, + $dir.'/'.$bundles[0]->getName().$overridePath + )); } - if (file_exists($file = $bundle->getPath().'/'.$path)) { - if ($first && !$isResource) { - return $file; - } - $files[] = $file; - $resourceBundle = $bundle->getName(); + $files[] = $file; + } + + if (file_exists($file = $bundle->getPath().'/'.$path)) { + if ($first && !$isResource) { + return $file; } + $files[] = $file; + $resourceBundle = $bundle->getName(); } if (count($files) > 0) { @@ -395,68 +376,20 @@ public function getCharset() } /** - * Initializes the data structures related to the bundle management. - * - * - the bundles property maps a bundle name to the bundle instance, - * - the bundleMap property maps a bundle name to the bundle inheritance hierarchy (most derived bundle first). + * Initializes bundles. * * @throws \LogicException if two bundles share a common name - * @throws \LogicException if a bundle tries to extend a non-registered bundle - * @throws \LogicException if a bundle tries to extend itself - * @throws \LogicException if two bundles extend the same ancestor */ protected function initializeBundles() { // init bundles $this->bundles = array(); - $topMostBundles = array(); - $directChildren = array(); - foreach ($this->registerBundles() as $bundle) { $name = $bundle->getName(); if (isset($this->bundles[$name])) { throw new \LogicException(sprintf('Trying to register two bundles with the same name "%s"', $name)); } $this->bundles[$name] = $bundle; - - if ($parentName = $bundle->getParent()) { - @trigger_error('Bundle inheritance is deprecated as of 3.4 and will be removed in 4.0.', E_USER_DEPRECATED); - - if (isset($directChildren[$parentName])) { - throw new \LogicException(sprintf('Bundle "%s" is directly extended by two bundles "%s" and "%s".', $parentName, $name, $directChildren[$parentName])); - } - if ($parentName == $name) { - throw new \LogicException(sprintf('Bundle "%s" can not extend itself.', $name)); - } - $directChildren[$parentName] = $name; - } else { - $topMostBundles[$name] = $bundle; - } - } - - // look for orphans - if (!empty($directChildren) && count($diff = array_diff_key($directChildren, $this->bundles))) { - $diff = array_keys($diff); - - throw new \LogicException(sprintf('Bundle "%s" extends bundle "%s", which is not registered.', $directChildren[$diff[0]], $diff[0])); - } - - // inheritance - $this->bundleMap = array(); - foreach ($topMostBundles as $name => $bundle) { - $bundleMap = array($bundle); - $hierarchy = array($name); - - while (isset($directChildren[$name])) { - $name = $directChildren[$name]; - array_unshift($bundleMap, $this->bundles[$name]); - $hierarchy[] = $name; - } - - foreach ($hierarchy as $hierarchyBundle) { - $this->bundleMap[$hierarchyBundle] = $bundleMap; - array_pop($bundleMap); - } } } @@ -588,7 +521,6 @@ protected function getKernelParameters() foreach ($this->bundles as $name => $bundle) { $bundles[$name] = get_class($bundle); $bundlesMetadata[$name] = array( - 'parent' => $bundle->getParent(), 'path' => $bundle->getPath(), 'namespace' => $bundle->getNamespace(), ); diff --git a/src/Symfony/Component/HttpKernel/KernelInterface.php b/src/Symfony/Component/HttpKernel/KernelInterface.php index 9fd3777889289..65c1a17fba779 100644 --- a/src/Symfony/Component/HttpKernel/KernelInterface.php +++ b/src/Symfony/Component/HttpKernel/KernelInterface.php @@ -58,19 +58,15 @@ public function shutdown(); public function getBundles(); /** - * Returns a bundle and optionally its descendants by its name. + * Returns a bundle. * - * The second argument is deprecated as of 3.4 and will be removed in 4.0. This method - * will always return an instance of BundleInterface in 4.0. + * @param string $name Bundle name * - * @param string $name Bundle name - * @param bool $first Whether to return the first bundle only or together with its descendants - * - * @return BundleInterface|BundleInterface[] A BundleInterface instance or an array of BundleInterface instances if $first is false + * @return BundleInterface A BundleInterface instance * * @throws \InvalidArgumentException when the bundle is not enabled */ - public function getBundle($name, $first = true); + public function getBundle($name); /** * Returns the file path for a given resource. diff --git a/src/Symfony/Component/HttpKernel/Tests/KernelTest.php b/src/Symfony/Component/HttpKernel/Tests/KernelTest.php index 45529fca33468..352e71f4bdc2d 100644 --- a/src/Symfony/Component/HttpKernel/Tests/KernelTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/KernelTest.php @@ -331,7 +331,7 @@ public function testLocateResourceThrowsExceptionWhenResourceDoesNotExist() $kernel ->expects($this->once()) ->method('getBundle') - ->will($this->returnValue(array($this->getBundle(__DIR__.'/Fixtures/Bundle1Bundle')))) + ->will($this->returnValue($this->getBundle(__DIR__.'/Fixtures/Bundle1Bundle'))) ; $kernel->locateResource('@Bundle1Bundle/config/routing.xml'); @@ -343,80 +343,19 @@ public function testLocateResourceReturnsTheFirstThatMatches() $kernel ->expects($this->once()) ->method('getBundle') - ->will($this->returnValue(array($this->getBundle(__DIR__.'/Fixtures/Bundle1Bundle')))) + ->will($this->returnValue($this->getBundle(__DIR__.'/Fixtures/Bundle1Bundle'))) ; $this->assertEquals(__DIR__.'/Fixtures/Bundle1Bundle/foo.txt', $kernel->locateResource('@Bundle1Bundle/foo.txt')); } - /** - * @group legacy - */ - public function testLocateResourceReturnsTheFirstThatMatchesWithParent() - { - $parent = $this->getBundle(__DIR__.'/Fixtures/Bundle1Bundle'); - $child = $this->getBundle(__DIR__.'/Fixtures/Bundle2Bundle'); - - $kernel = $this->getKernel(array('getBundle')); - $kernel - ->expects($this->exactly(2)) - ->method('getBundle') - ->will($this->returnValue(array($child, $parent))) - ; - - $this->assertEquals(__DIR__.'/Fixtures/Bundle2Bundle/foo.txt', $kernel->locateResource('@ParentAABundle/foo.txt')); - $this->assertEquals(__DIR__.'/Fixtures/Bundle1Bundle/bar.txt', $kernel->locateResource('@ParentAABundle/bar.txt')); - } - - /** - * @group legacy - */ - public function testLocateResourceReturnsAllMatches() - { - $parent = $this->getBundle(__DIR__.'/Fixtures/Bundle1Bundle'); - $child = $this->getBundle(__DIR__.'/Fixtures/Bundle2Bundle'); - - $kernel = $this->getKernel(array('getBundle')); - $kernel - ->expects($this->once()) - ->method('getBundle') - ->will($this->returnValue(array($child, $parent))) - ; - - $this->assertEquals(array( - __DIR__.'/Fixtures/Bundle2Bundle/foo.txt', - __DIR__.'/Fixtures/Bundle1Bundle/foo.txt', ), - $kernel->locateResource('@Bundle1Bundle/foo.txt', null, false)); - } - - /** - * @group legacy - */ - public function testLocateResourceReturnsAllMatchesBis() - { - $kernel = $this->getKernel(array('getBundle')); - $kernel - ->expects($this->once()) - ->method('getBundle') - ->will($this->returnValue(array( - $this->getBundle(__DIR__.'/Fixtures/Bundle1Bundle'), - $this->getBundle(__DIR__.'/Foobar'), - ))) - ; - - $this->assertEquals( - array(__DIR__.'/Fixtures/Bundle1Bundle/foo.txt'), - $kernel->locateResource('@Bundle1Bundle/foo.txt', null, false) - ); - } - public function testLocateResourceIgnoresDirOnNonResource() { $kernel = $this->getKernel(array('getBundle')); $kernel ->expects($this->once()) ->method('getBundle') - ->will($this->returnValue(array($this->getBundle(__DIR__.'/Fixtures/Bundle1Bundle')))) + ->will($this->returnValue($this->getBundle(__DIR__.'/Fixtures/Bundle1Bundle'))) ; $this->assertEquals( @@ -431,7 +370,7 @@ public function testLocateResourceReturnsTheDirOneForResources() $kernel ->expects($this->once()) ->method('getBundle') - ->will($this->returnValue(array($this->getBundle(__DIR__.'/Fixtures/FooBundle', null, null, 'FooBundle')))) + ->will($this->returnValue($this->getBundle(__DIR__.'/Fixtures/FooBundle', null, null, 'FooBundle'))) ; $this->assertEquals( @@ -440,73 +379,13 @@ public function testLocateResourceReturnsTheDirOneForResources() ); } - /** - * @group legacy - */ - public function testLocateResourceReturnsTheDirOneForResourcesAndBundleOnes() - { - $kernel = $this->getKernel(array('getBundle')); - $kernel - ->expects($this->once()) - ->method('getBundle') - ->will($this->returnValue(array($this->getBundle(__DIR__.'/Fixtures/Bundle1Bundle', null, null, 'Bundle1Bundle')))) - ; - - $this->assertEquals(array( - __DIR__.'/Fixtures/Resources/Bundle1Bundle/foo.txt', - __DIR__.'/Fixtures/Bundle1Bundle/Resources/foo.txt', ), - $kernel->locateResource('@Bundle1Bundle/Resources/foo.txt', __DIR__.'/Fixtures/Resources', false) - ); - } - - /** - * @group legacy - */ - public function testLocateResourceOverrideBundleAndResourcesFolders() - { - $parent = $this->getBundle(__DIR__.'/Fixtures/BaseBundle', null, 'BaseBundle', 'BaseBundle'); - $child = $this->getBundle(__DIR__.'/Fixtures/ChildBundle', 'ParentBundle', 'ChildBundle', 'ChildBundle'); - - $kernel = $this->getKernel(array('getBundle')); - $kernel - ->expects($this->exactly(4)) - ->method('getBundle') - ->will($this->returnValue(array($child, $parent))) - ; - - $this->assertEquals(array( - __DIR__.'/Fixtures/Resources/ChildBundle/foo.txt', - __DIR__.'/Fixtures/ChildBundle/Resources/foo.txt', - __DIR__.'/Fixtures/BaseBundle/Resources/foo.txt', - ), - $kernel->locateResource('@BaseBundle/Resources/foo.txt', __DIR__.'/Fixtures/Resources', false) - ); - - $this->assertEquals( - __DIR__.'/Fixtures/Resources/ChildBundle/foo.txt', - $kernel->locateResource('@BaseBundle/Resources/foo.txt', __DIR__.'/Fixtures/Resources') - ); - - try { - $kernel->locateResource('@BaseBundle/Resources/hide.txt', __DIR__.'/Fixtures/Resources', false); - $this->fail('Hidden resources should raise an exception when returning an array of matching paths'); - } catch (\RuntimeException $e) { - } - - try { - $kernel->locateResource('@BaseBundle/Resources/hide.txt', __DIR__.'/Fixtures/Resources', true); - $this->fail('Hidden resources should raise an exception when returning the first matching path'); - } catch (\RuntimeException $e) { - } - } - public function testLocateResourceOnDirectories() { $kernel = $this->getKernel(array('getBundle')); $kernel ->expects($this->exactly(2)) ->method('getBundle') - ->will($this->returnValue(array($this->getBundle(__DIR__.'/Fixtures/FooBundle', null, null, 'FooBundle')))) + ->will($this->returnValue($this->getBundle(__DIR__.'/Fixtures/FooBundle', null, null, 'FooBundle'))) ; $this->assertEquals( @@ -522,7 +401,7 @@ public function testLocateResourceOnDirectories() $kernel ->expects($this->exactly(2)) ->method('getBundle') - ->will($this->returnValue(array($this->getBundle(__DIR__.'/Fixtures/Bundle1Bundle', null, null, 'Bundle1Bundle')))) + ->will($this->returnValue($this->getBundle(__DIR__.'/Fixtures/Bundle1Bundle', null, null, 'Bundle1Bundle'))) ; $this->assertEquals( @@ -535,102 +414,6 @@ public function testLocateResourceOnDirectories() ); } - /** - * @group legacy - */ - public function testInitializeBundles() - { - $parent = $this->getBundle(null, null, 'ParentABundle'); - $child = $this->getBundle(null, 'ParentABundle', 'ChildABundle'); - - // use test kernel so we can access getBundleMap() - $kernel = $this->getKernelForTest(array('registerBundles')); - $kernel - ->expects($this->once()) - ->method('registerBundles') - ->will($this->returnValue(array($parent, $child))) - ; - $kernel->boot(); - - $map = $kernel->getBundleMap(); - $this->assertEquals(array($child, $parent), $map['ParentABundle']); - } - - /** - * @group legacy - */ - public function testInitializeBundlesSupportInheritanceCascade() - { - $grandparent = $this->getBundle(null, null, 'GrandParentBBundle'); - $parent = $this->getBundle(null, 'GrandParentBBundle', 'ParentBBundle'); - $child = $this->getBundle(null, 'ParentBBundle', 'ChildBBundle'); - - // use test kernel so we can access getBundleMap() - $kernel = $this->getKernelForTest(array('registerBundles')); - $kernel - ->expects($this->once()) - ->method('registerBundles') - ->will($this->returnValue(array($grandparent, $parent, $child))) - ; - $kernel->boot(); - - $map = $kernel->getBundleMap(); - $this->assertEquals(array($child, $parent, $grandparent), $map['GrandParentBBundle']); - $this->assertEquals(array($child, $parent), $map['ParentBBundle']); - $this->assertEquals(array($child), $map['ChildBBundle']); - } - - /** - * @group legacy - * @expectedException \LogicException - * @expectedExceptionMessage Bundle "ChildCBundle" extends bundle "FooBar", which is not registered. - */ - public function testInitializeBundlesThrowsExceptionWhenAParentDoesNotExists() - { - $child = $this->getBundle(null, 'FooBar', 'ChildCBundle'); - $kernel = $this->getKernel(array(), array($child)); - $kernel->boot(); - } - - /** - * @group legacy - */ - public function testInitializeBundlesSupportsArbitraryBundleRegistrationOrder() - { - $grandparent = $this->getBundle(null, null, 'GrandParentCBundle'); - $parent = $this->getBundle(null, 'GrandParentCBundle', 'ParentCBundle'); - $child = $this->getBundle(null, 'ParentCBundle', 'ChildCBundle'); - - // use test kernel so we can access getBundleMap() - $kernel = $this->getKernelForTest(array('registerBundles')); - $kernel - ->expects($this->once()) - ->method('registerBundles') - ->will($this->returnValue(array($parent, $grandparent, $child))) - ; - $kernel->boot(); - - $map = $kernel->getBundleMap(); - $this->assertEquals(array($child, $parent, $grandparent), $map['GrandParentCBundle']); - $this->assertEquals(array($child, $parent), $map['ParentCBundle']); - $this->assertEquals(array($child), $map['ChildCBundle']); - } - - /** - * @group legacy - * @expectedException \LogicException - * @expectedExceptionMessage Bundle "ParentCBundle" is directly extended by two bundles "ChildC2Bundle" and "ChildC1Bundle". - */ - public function testInitializeBundlesThrowsExceptionWhenABundleIsDirectlyExtendedByTwoBundles() - { - $parent = $this->getBundle(null, null, 'ParentCBundle'); - $child1 = $this->getBundle(null, 'ParentCBundle', 'ChildC1Bundle'); - $child2 = $this->getBundle(null, 'ParentCBundle', 'ChildC2Bundle'); - - $kernel = $this->getKernel(array(), array($parent, $child1, $child2)); - $kernel->boot(); - } - /** * @group legacy * @expectedException \LogicException @@ -645,19 +428,6 @@ public function testInitializeBundleThrowsExceptionWhenRegisteringTwoBundlesWith $kernel->boot(); } - /** - * @group legacy - * @expectedException \LogicException - * @expectedExceptionMessage Bundle "CircularRefBundle" can not extend itself. - */ - public function testInitializeBundleThrowsExceptionWhenABundleExtendsItself() - { - $circularRef = $this->getBundle(null, 'CircularRefBundle', 'CircularRefBundle'); - - $kernel = $this->getKernel(array(), array($circularRef)); - $kernel->boot(); - } - public function testTerminateReturnsSilentlyIfKernelIsNotBooted() { $kernel = $this->getKernel(array('getHttpKernel')); From e17206debdb6079569124ae198916725ddd69b6a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9goire=20Pineau?= Date: Mon, 12 Jun 2017 16:39:22 +0200 Subject: [PATCH 0913/1099] [PhpUnitBridge] Added a CoverageListener to enhance the code coverage report --- src/Symfony/Bridge/PhpUnit/CHANGELOG.md | 5 + .../Bridge/PhpUnit/CoverageListener.php | 44 +++++++ .../PhpUnit/Legacy/CoverageListener.php | 35 ++++++ .../PhpUnit/Legacy/CoverageListenerTrait.php | 113 ++++++++++++++++++ .../PhpUnit/Tests/CoverageListenerTest.php | 35 ++++++ .../coverage/phpunit-with-listener.xml.dist | 32 +++++ .../phpunit-without-listener.xml.dist | 23 ++++ .../Tests/Fixtures/coverage/src/Bar.php | 29 +++++ .../Tests/Fixtures/coverage/src/Foo.php | 20 ++++ .../Tests/Fixtures/coverage/tests/BarTest.php | 29 +++++ .../coverage/tests/CoversDefaultClassTest.php | 23 ++++ .../coverage/tests/CoversNothingTest.php | 23 ++++ .../Fixtures/coverage/tests/CoversTest.php | 23 ++++ .../coverage/tests/SutNotFindTest.php | 20 ++++ .../Fixtures/coverage/tests/bootstrap.php | 19 +++ 15 files changed, 473 insertions(+) create mode 100644 src/Symfony/Bridge/PhpUnit/CoverageListener.php create mode 100644 src/Symfony/Bridge/PhpUnit/Legacy/CoverageListener.php create mode 100644 src/Symfony/Bridge/PhpUnit/Legacy/CoverageListenerTrait.php create mode 100644 src/Symfony/Bridge/PhpUnit/Tests/CoverageListenerTest.php create mode 100644 src/Symfony/Bridge/PhpUnit/Tests/Fixtures/coverage/phpunit-with-listener.xml.dist create mode 100644 src/Symfony/Bridge/PhpUnit/Tests/Fixtures/coverage/phpunit-without-listener.xml.dist create mode 100644 src/Symfony/Bridge/PhpUnit/Tests/Fixtures/coverage/src/Bar.php create mode 100644 src/Symfony/Bridge/PhpUnit/Tests/Fixtures/coverage/src/Foo.php create mode 100644 src/Symfony/Bridge/PhpUnit/Tests/Fixtures/coverage/tests/BarTest.php create mode 100644 src/Symfony/Bridge/PhpUnit/Tests/Fixtures/coverage/tests/CoversDefaultClassTest.php create mode 100644 src/Symfony/Bridge/PhpUnit/Tests/Fixtures/coverage/tests/CoversNothingTest.php create mode 100644 src/Symfony/Bridge/PhpUnit/Tests/Fixtures/coverage/tests/CoversTest.php create mode 100644 src/Symfony/Bridge/PhpUnit/Tests/Fixtures/coverage/tests/SutNotFindTest.php create mode 100644 src/Symfony/Bridge/PhpUnit/Tests/Fixtures/coverage/tests/bootstrap.php diff --git a/src/Symfony/Bridge/PhpUnit/CHANGELOG.md b/src/Symfony/Bridge/PhpUnit/CHANGELOG.md index 1cb07da782b6d..39ae3a881b3b1 100644 --- a/src/Symfony/Bridge/PhpUnit/CHANGELOG.md +++ b/src/Symfony/Bridge/PhpUnit/CHANGELOG.md @@ -1,6 +1,11 @@ CHANGELOG ========= +3.4.0 +----- + + * added a `CoverageListener` to enhance the code coverage report + 3.3.0 ----- diff --git a/src/Symfony/Bridge/PhpUnit/CoverageListener.php b/src/Symfony/Bridge/PhpUnit/CoverageListener.php new file mode 100644 index 0000000000000..e6b4e7ec98b8b --- /dev/null +++ b/src/Symfony/Bridge/PhpUnit/CoverageListener.php @@ -0,0 +1,44 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bridge\PhpUnit; + +use PHPUnit\Framework\BaseTestListener; +use PHPUnit\Framework\Test; +use Symfony\Bridge\PhpUnit\Legacy\CoverageListenerTrait; + +if (class_exists('PHPUnit_Runner_Version') && version_compare(\PHPUnit_Runner_Version::id(), '6.0.0', '<')) { + class_alias('Symfony\Bridge\PhpUnit\Legacy\CoverageListener', 'Symfony\Bridge\PhpUnit\CoverageListener'); +// Using an early return instead of a else does not work when using the PHPUnit +// phar due to some weird PHP behavior (the class gets defined without executing +// the code before it and so the definition is not properly conditional) +} else { + /** + * CoverageListener adds `@covers ` on each test suite when possible + * to make the code coverage more accurate. + * + * @author Grégoire Pineau + */ + class CoverageListener extends BaseTestListener + { + private $trait; + + public function __construct(callable $sutFqcnResolver = null, $warningOnSutNotFound = false) + { + $this->trait = new CoverageListenerTrait($sutFqcnResolver, $warningOnSutNotFound); + } + + public function startTest(Test $test) + { + $this->trait->startTest($test); + } + } +} diff --git a/src/Symfony/Bridge/PhpUnit/Legacy/CoverageListener.php b/src/Symfony/Bridge/PhpUnit/Legacy/CoverageListener.php new file mode 100644 index 0000000000000..0227828515760 --- /dev/null +++ b/src/Symfony/Bridge/PhpUnit/Legacy/CoverageListener.php @@ -0,0 +1,35 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bridge\PhpUnit\Legacy; + +/** + * CoverageListener adds `@covers ` on each test suite when possible + * to make the code coverage more accurate. + * + * @author Grégoire Pineau + * + * @internal + */ +class CoverageListener extends \PHPUnit_Framework_BaseTestListener +{ + private $trait; + + public function __construct(callable $sutFqcnResolver = null, $warningOnSutNotFound = false) + { + $this->trait = new CoverageListenerTrait($sutFqcnResolver, $warningOnSutNotFound); + } + + public function startTest(\PHPUnit_Framework_Test $test) + { + $this->trait->startTest($test); + } +} diff --git a/src/Symfony/Bridge/PhpUnit/Legacy/CoverageListenerTrait.php b/src/Symfony/Bridge/PhpUnit/Legacy/CoverageListenerTrait.php new file mode 100644 index 0000000000000..0a1603e646cbf --- /dev/null +++ b/src/Symfony/Bridge/PhpUnit/Legacy/CoverageListenerTrait.php @@ -0,0 +1,113 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bridge\PhpUnit\Legacy; + +use PHPUnit\Framework\Test; +use PHPUnit\Framework\Warning; + +/** + * PHP 5.3 compatible trait-like shared implementation. + * + * @author Grégoire Pineau + * + * @internal + */ +class CoverageListenerTrait +{ + private $sutFqcnResolver; + private $warningOnSutNotFound; + private $warnings; + + public function __construct(callable $sutFqcnResolver = null, $warningOnSutNotFound = false) + { + $this->sutFqcnResolver = $sutFqcnResolver; + $this->warningOnSutNotFound = $warningOnSutNotFound; + $this->warnings = array(); + } + + public function startTest($test) + { + $annotations = $test->getAnnotations(); + + $ignoredAnnotations = array('covers', 'coversDefaultClass', 'coversNothing'); + + foreach ($ignoredAnnotations as $annotation) { + if (isset($annotations['class'][$annotation]) || isset($annotations['method'][$annotation])) { + return; + } + } + + $sutFqcn = $this->findSutFqcn($test); + if (!$sutFqcn) { + if ($this->warningOnSutNotFound) { + $message = 'Could not find the tested class.'; + // addWarning does not exist on old PHPUnit version + if (method_exists($test->getTestResultObject(), 'addWarning') && class_exists(Warning::class)) { + $test->getTestResultObject()->addWarning($test, new Warning($message), 0); + } else { + $this->warnings[] = sprintf("%s::%s\n%s", get_class($test), $test->getName(), $message); + } + } + + return; + } + + $testClass = \PHPUnit\Util\Test::class; + if (!class_exists($testClass, false)) { + $testClass = \PHPUnit_Util_Test::class; + } + + $r = new \ReflectionProperty($testClass, 'annotationCache'); + $r->setAccessible(true); + + $cache = $r->getValue(); + $cache = array_replace_recursive($cache, array( + get_class($test) => array( + 'covers' => array($sutFqcn), + ), + )); + $r->setValue($testClass, $cache); + } + + private function findSutFqcn($test) + { + if ($this->sutFqcnResolver) { + $resolver = $this->sutFqcnResolver; + + return $resolver($test); + } + + $class = get_class($test); + + $sutFqcn = str_replace('\\Tests\\', '\\', $class); + $sutFqcn = preg_replace('{Test$}', '', $sutFqcn); + + if (!class_exists($sutFqcn)) { + return; + } + + return $sutFqcn; + } + + public function __destruct() + { + if (!$this->warnings) { + return; + } + + echo "\n"; + + foreach ($this->warnings as $key => $warning) { + echo sprintf("%d) %s\n", ++$key, $warning); + } + } +} diff --git a/src/Symfony/Bridge/PhpUnit/Tests/CoverageListenerTest.php b/src/Symfony/Bridge/PhpUnit/Tests/CoverageListenerTest.php new file mode 100644 index 0000000000000..216b860a4bc2c --- /dev/null +++ b/src/Symfony/Bridge/PhpUnit/Tests/CoverageListenerTest.php @@ -0,0 +1,35 @@ +markTestSkipped('This test cannot be run on Windows.'); + } + + if (defined('HHVM_VERSION')) { + $this->markTestSkipped('This test cannot be run on HHVM.'); + } + + $dir = __DIR__.'/../Tests/Fixtures/coverage'; + $php = PHP_BINARY; + $phpunit = $_SERVER['argv'][0]; + + exec("$php -d zend_extension=xdebug.so $phpunit -c $dir/phpunit-without-listener.xml.dist $dir/tests/ --coverage-text", $output); + $output = implode("\n", $output); + $this->assertContains('Foo', $output); + + exec("$php -d zend_extension=xdebug.so $phpunit -c $dir/phpunit-with-listener.xml.dist $dir/tests/ --coverage-text", $output); + $output = implode("\n", $output); + $this->assertNotContains('Foo', $output); + $this->assertContains("SutNotFoundTest::test\nCould not find the tested class.", $output); + $this->assertNotContains("CoversTest::test\nCould not find the tested class.", $output); + $this->assertNotContains("CoversDefaultClassTest::test\nCould not find the tested class.", $output); + $this->assertNotContains("CoversNothingTest::test\nCould not find the tested class.", $output); + } +} diff --git a/src/Symfony/Bridge/PhpUnit/Tests/Fixtures/coverage/phpunit-with-listener.xml.dist b/src/Symfony/Bridge/PhpUnit/Tests/Fixtures/coverage/phpunit-with-listener.xml.dist new file mode 100644 index 0000000000000..1984359ebdd78 --- /dev/null +++ b/src/Symfony/Bridge/PhpUnit/Tests/Fixtures/coverage/phpunit-with-listener.xml.dist @@ -0,0 +1,32 @@ + + + + + + + tests + + + + + + src + + + + + + + + true + + + + diff --git a/src/Symfony/Bridge/PhpUnit/Tests/Fixtures/coverage/phpunit-without-listener.xml.dist b/src/Symfony/Bridge/PhpUnit/Tests/Fixtures/coverage/phpunit-without-listener.xml.dist new file mode 100644 index 0000000000000..6201535933767 --- /dev/null +++ b/src/Symfony/Bridge/PhpUnit/Tests/Fixtures/coverage/phpunit-without-listener.xml.dist @@ -0,0 +1,23 @@ + + + + + + + tests + + + + + + src + + + diff --git a/src/Symfony/Bridge/PhpUnit/Tests/Fixtures/coverage/src/Bar.php b/src/Symfony/Bridge/PhpUnit/Tests/Fixtures/coverage/src/Bar.php new file mode 100644 index 0000000000000..b50305a402634 --- /dev/null +++ b/src/Symfony/Bridge/PhpUnit/Tests/Fixtures/coverage/src/Bar.php @@ -0,0 +1,29 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace PhpUnitCoverageTest; + +class Bar +{ + private $foo; + + public function __construct(Foo $foo) + { + $this->foo = $foo; + } + + public function barZ() + { + $this->foo->fooZ(); + + return 'bar'; + } +} diff --git a/src/Symfony/Bridge/PhpUnit/Tests/Fixtures/coverage/src/Foo.php b/src/Symfony/Bridge/PhpUnit/Tests/Fixtures/coverage/src/Foo.php new file mode 100644 index 0000000000000..f811ae70b10a0 --- /dev/null +++ b/src/Symfony/Bridge/PhpUnit/Tests/Fixtures/coverage/src/Foo.php @@ -0,0 +1,20 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace PhpUnitCoverageTest; + +class Foo +{ + public function fooZ() + { + return 'foo'; + } +} diff --git a/src/Symfony/Bridge/PhpUnit/Tests/Fixtures/coverage/tests/BarTest.php b/src/Symfony/Bridge/PhpUnit/Tests/Fixtures/coverage/tests/BarTest.php new file mode 100644 index 0000000000000..b49fc706a9cfa --- /dev/null +++ b/src/Symfony/Bridge/PhpUnit/Tests/Fixtures/coverage/tests/BarTest.php @@ -0,0 +1,29 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace PhpUnitCoverageTest\Tests; + +use PHPUnit\Framework\TestCase; + +class BarTest extends TestCase +{ + public function testBar() + { + if (!class_exists('PhpUnitCoverageTest\Foo')) { + $this->markTestSkipped('This test is not part of the main Symfony test suite. It\'s here to test the CoverageListener.'); + } + + $foo = new \PhpUnitCoverageTest\Foo(); + $bar = new \PhpUnitCoverageTest\Bar($foo); + + $this->assertSame('bar', $bar->barZ()); + } +} diff --git a/src/Symfony/Bridge/PhpUnit/Tests/Fixtures/coverage/tests/CoversDefaultClassTest.php b/src/Symfony/Bridge/PhpUnit/Tests/Fixtures/coverage/tests/CoversDefaultClassTest.php new file mode 100644 index 0000000000000..d764638d04958 --- /dev/null +++ b/src/Symfony/Bridge/PhpUnit/Tests/Fixtures/coverage/tests/CoversDefaultClassTest.php @@ -0,0 +1,23 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +use PHPUnit\Framework\TestCase; + +/** + * @coversDefaultClass \DateTime + */ +class CoversDefaultClassTest extends TestCase +{ + public function test() + { + $this->assertTrue(true); + } +} diff --git a/src/Symfony/Bridge/PhpUnit/Tests/Fixtures/coverage/tests/CoversNothingTest.php b/src/Symfony/Bridge/PhpUnit/Tests/Fixtures/coverage/tests/CoversNothingTest.php new file mode 100644 index 0000000000000..e60ea97e57bbd --- /dev/null +++ b/src/Symfony/Bridge/PhpUnit/Tests/Fixtures/coverage/tests/CoversNothingTest.php @@ -0,0 +1,23 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +use PHPUnit\Framework\TestCase; + +/** + * @coversNothing + */ +class CoversNothingTest extends TestCase +{ + public function test() + { + $this->assertTrue(true); + } +} diff --git a/src/Symfony/Bridge/PhpUnit/Tests/Fixtures/coverage/tests/CoversTest.php b/src/Symfony/Bridge/PhpUnit/Tests/Fixtures/coverage/tests/CoversTest.php new file mode 100644 index 0000000000000..f6d3406046d86 --- /dev/null +++ b/src/Symfony/Bridge/PhpUnit/Tests/Fixtures/coverage/tests/CoversTest.php @@ -0,0 +1,23 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +use PHPUnit\Framework\TestCase; + +class CoversTest extends TestCase +{ + /** + * @covers \DateTime + */ + public function test() + { + $this->assertTrue(true); + } +} diff --git a/src/Symfony/Bridge/PhpUnit/Tests/Fixtures/coverage/tests/SutNotFindTest.php b/src/Symfony/Bridge/PhpUnit/Tests/Fixtures/coverage/tests/SutNotFindTest.php new file mode 100644 index 0000000000000..934ee77dc1873 --- /dev/null +++ b/src/Symfony/Bridge/PhpUnit/Tests/Fixtures/coverage/tests/SutNotFindTest.php @@ -0,0 +1,20 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +use PHPUnit\Framework\TestCase; + +class SutNotFoundTest extends TestCase +{ + public function test() + { + $this->assertTrue(true); + } +} diff --git a/src/Symfony/Bridge/PhpUnit/Tests/Fixtures/coverage/tests/bootstrap.php b/src/Symfony/Bridge/PhpUnit/Tests/Fixtures/coverage/tests/bootstrap.php new file mode 100644 index 0000000000000..9647a8658d212 --- /dev/null +++ b/src/Symfony/Bridge/PhpUnit/Tests/Fixtures/coverage/tests/bootstrap.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 __DIR__.'/../src/Bar.php'; +require __DIR__.'/../src/Foo.php'; + +require __DIR__.'/../../../../Legacy/CoverageListenerTrait.php'; +if (class_exists('PHPUnit_Runner_Version') && version_compare(\PHPUnit_Runner_Version::id(), '6.0.0', '<')) { + require __DIR__.'/../../../../Legacy/CoverageListener.php'; +} +require __DIR__.'/../../../../CoverageListener.php'; From 4adadbeffa03c3f15fb4d9a14e3e105c38aab033 Mon Sep 17 00:00:00 2001 From: Robin Chalas Date: Wed, 27 Sep 2017 09:53:29 +0200 Subject: [PATCH 0914/1099] Remove unused http_digest fixtures --- .../Fixtures/php/container1_with_digest.php | 105 ------------------ .../Fixtures/xml/container1_with_digest.xml | 82 -------------- .../Fixtures/yml/container1_with_digest.yml | 85 -------------- 3 files changed, 272 deletions(-) delete mode 100644 src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/container1_with_digest.php delete mode 100644 src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/container1_with_digest.xml delete mode 100644 src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/container1_with_digest.yml diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/container1_with_digest.php b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/container1_with_digest.php deleted file mode 100644 index 581407fcc05a5..0000000000000 --- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/container1_with_digest.php +++ /dev/null @@ -1,105 +0,0 @@ -loadFromExtension('security', array( - 'acl' => array(), - 'encoders' => array( - 'JMS\FooBundle\Entity\User1' => 'plaintext', - 'JMS\FooBundle\Entity\User2' => array( - 'algorithm' => 'sha1', - 'encode_as_base64' => false, - 'iterations' => 5, - ), - 'JMS\FooBundle\Entity\User3' => array( - 'algorithm' => 'md5', - ), - 'JMS\FooBundle\Entity\User4' => array( - 'id' => 'security.encoder.foo', - ), - 'JMS\FooBundle\Entity\User5' => array( - 'algorithm' => 'pbkdf2', - 'hash_algorithm' => 'sha1', - 'encode_as_base64' => false, - 'iterations' => 5, - 'key_length' => 30, - ), - 'JMS\FooBundle\Entity\User6' => array( - 'algorithm' => 'bcrypt', - 'cost' => 15, - ), - ), - 'providers' => array( - 'default' => array( - 'memory' => array( - 'users' => array( - 'foo' => array('password' => 'foo', 'roles' => 'ROLE_USER'), - ), - ), - ), - 'digest' => array( - 'memory' => array( - 'users' => array( - 'foo' => array('password' => 'foo', 'roles' => 'ROLE_USER, ROLE_ADMIN'), - ), - ), - ), - 'basic' => array( - 'memory' => array( - 'users' => array( - 'foo' => array('password' => '0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33', 'roles' => 'ROLE_SUPER_ADMIN'), - 'bar' => array('password' => '0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33', 'roles' => array('ROLE_USER', 'ROLE_ADMIN')), - ), - ), - ), - 'service' => array( - 'id' => 'user.manager', - ), - 'chain' => array( - 'chain' => array( - 'providers' => array('service', 'basic'), - ), - ), - ), - - 'firewalls' => array( - 'simple' => array('pattern' => '/login', 'security' => false), - 'secure' => array('stateless' => true, - 'http_basic' => true, - 'http_digest' => array('secret' => 'TheSecret'), - 'form_login' => true, - 'anonymous' => true, - 'switch_user' => true, - 'x509' => true, - 'remote_user' => true, - 'logout' => true, - 'remember_me' => array('secret' => 'TheSecret'), - 'user_checker' => null, - 'logout_on_user_change' => true, - ), - 'host' => array( - 'pattern' => '/test', - 'host' => 'foo\\.example\\.org', - 'methods' => array('GET', 'POST'), - 'anonymous' => true, - 'http_basic' => true, - 'logout_on_user_change' => true, - ), - 'with_user_checker' => array( - 'user_checker' => 'app.user_checker', - 'anonymous' => true, - 'http_basic' => true, - 'logout_on_user_change' => true, - ), - ), - - 'access_control' => array( - array('path' => '/blog/524', 'role' => 'ROLE_USER', 'requires_channel' => 'https', 'methods' => array('get', 'POST')), - array('path' => '/blog/.*', 'role' => 'IS_AUTHENTICATED_ANONYMOUSLY'), - array('path' => '/blog/524', 'role' => 'IS_AUTHENTICATED_ANONYMOUSLY', 'allow_if' => "token.getUsername() matches '/^admin/'"), - ), - - 'role_hierarchy' => array( - 'ROLE_ADMIN' => 'ROLE_USER', - 'ROLE_SUPER_ADMIN' => array('ROLE_USER', 'ROLE_ADMIN', 'ROLE_ALLOWED_TO_SWITCH'), - 'ROLE_REMOTE' => 'ROLE_USER,ROLE_ADMIN', - ), -)); diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/container1_with_digest.xml b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/container1_with_digest.xml deleted file mode 100644 index e5049f2033e51..0000000000000 --- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/container1_with_digest.xml +++ /dev/null @@ -1,82 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - app.user_checker - - - ROLE_USER - ROLE_USER,ROLE_ADMIN,ROLE_ALLOWED_TO_SWITCH - ROLE_USER,ROLE_ADMIN - - - - - - diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/container1_with_digest.yml b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/container1_with_digest.yml deleted file mode 100644 index a2b57201bfbd2..0000000000000 --- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/container1_with_digest.yml +++ /dev/null @@ -1,85 +0,0 @@ -security: - acl: ~ - encoders: - JMS\FooBundle\Entity\User1: plaintext - JMS\FooBundle\Entity\User2: - algorithm: sha1 - encode_as_base64: false - iterations: 5 - JMS\FooBundle\Entity\User3: - algorithm: md5 - JMS\FooBundle\Entity\User4: - id: security.encoder.foo - JMS\FooBundle\Entity\User5: - algorithm: pbkdf2 - hash_algorithm: sha1 - encode_as_base64: false - iterations: 5 - key_length: 30 - JMS\FooBundle\Entity\User6: - algorithm: bcrypt - cost: 15 - - providers: - default: - memory: - users: - foo: { password: foo, roles: ROLE_USER } - digest: - memory: - users: - foo: { password: foo, roles: 'ROLE_USER, ROLE_ADMIN' } - basic: - memory: - users: - foo: { password: 0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33, roles: ROLE_SUPER_ADMIN } - bar: { password: 0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33, roles: [ROLE_USER, ROLE_ADMIN] } - service: - id: user.manager - chain: - chain: - providers: [service, basic] - - - firewalls: - simple: { pattern: /login, security: false } - secure: - stateless: true - http_basic: true - http_digest: - secret: TheSecret - form_login: true - anonymous: true - switch_user: true - x509: true - remote_user: true - logout: true - remember_me: - secret: TheSecret - user_checker: ~ - - host: - pattern: /test - host: foo\.example\.org - methods: [GET,POST] - anonymous: true - http_basic: true - logout_on_user_change: true - - with_user_checker: - anonymous: ~ - http_basic: ~ - user_checker: app.user_checker - logout_on_user_change: true - - role_hierarchy: - ROLE_ADMIN: ROLE_USER - ROLE_SUPER_ADMIN: [ROLE_USER, ROLE_ADMIN, ROLE_ALLOWED_TO_SWITCH] - ROLE_REMOTE: ROLE_USER,ROLE_ADMIN - - access_control: - - { path: /blog/524, role: ROLE_USER, requires_channel: https, methods: [get, POST]} - - - path: /blog/.* - role: IS_AUTHENTICATED_ANONYMOUSLY - - { path: /blog/524, role: IS_AUTHENTICATED_ANONYMOUSLY, allow_if: "token.getUsername() matches '/^admin/'" } From a867ca1d0c8f5384ef18761178b17cc8b0d6d331 Mon Sep 17 00:00:00 2001 From: Robin Chalas Date: Wed, 27 Sep 2017 09:59:35 +0200 Subject: [PATCH 0915/1099] [SecurityBundle] Remove ACL related code --- .../Bundle/SecurityBundle/CHANGELOG.md | 3 + .../SecurityBundle/Command/InitAclCommand.php | 113 ---------- .../SecurityBundle/Command/SetAclCommand.php | 202 ------------------ .../DependencyInjection/MainConfiguration.php | 42 ---- .../DependencyInjection/SecurityExtension.php | 60 ------ .../Resources/config/console.xml | 11 - .../CompleteConfigurationTest.php | 38 ---- .../Fixtures/php/container1_with_acl.php | 101 --------- .../Fixtures/xml/container1_with_acl.xml | 80 ------- .../Fixtures/yml/container1_with_acl.yml | 81 ------- .../Tests/Functional/SetAclCommandTest.php | 177 --------------- 11 files changed, 3 insertions(+), 905 deletions(-) delete mode 100644 src/Symfony/Bundle/SecurityBundle/Command/InitAclCommand.php delete mode 100644 src/Symfony/Bundle/SecurityBundle/Command/SetAclCommand.php delete mode 100644 src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/container1_with_acl.php delete mode 100644 src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/container1_with_acl.xml delete mode 100644 src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/container1_with_acl.yml delete mode 100644 src/Symfony/Bundle/SecurityBundle/Tests/Functional/SetAclCommandTest.php diff --git a/src/Symfony/Bundle/SecurityBundle/CHANGELOG.md b/src/Symfony/Bundle/SecurityBundle/CHANGELOG.md index d5f167f7aeb5e..b5b0f6ec6124e 100644 --- a/src/Symfony/Bundle/SecurityBundle/CHANGELOG.md +++ b/src/Symfony/Bundle/SecurityBundle/CHANGELOG.md @@ -10,6 +10,9 @@ CHANGELOG * `UserPasswordEncoderCommand` does not extend `ContainerAwareCommand` anymore * removed support for voters that don't implement the `VoterInterface` * removed HTTP digest authentication + * removed command `acl:set` along with `SetAclCommand` class + * removed command `init:acl` along with `InitAclCommand` class + * removed `acl` configuration key and related services, use symfony/acl-bundle instead 3.4.0 ----- diff --git a/src/Symfony/Bundle/SecurityBundle/Command/InitAclCommand.php b/src/Symfony/Bundle/SecurityBundle/Command/InitAclCommand.php deleted file mode 100644 index 42e4f8825d888..0000000000000 --- a/src/Symfony/Bundle/SecurityBundle/Command/InitAclCommand.php +++ /dev/null @@ -1,113 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\SecurityBundle\Command; - -@trigger_error(sprintf('Class "%s" is deprecated since version 3.4 and will be removed in 4.0. Use Symfony\Bundle\AclBundle\Command\SetAclCommand instead.', SetAclCommand::class), E_USER_DEPRECATED); - -use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Output\ConsoleOutputInterface; -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Style\SymfonyStyle; -use Symfony\Component\Security\Acl\Dbal\Schema; -use Doctrine\DBAL\Connection; -use Doctrine\DBAL\Schema\SchemaException; - -/** - * Installs the tables required by the ACL system. - * - * @author Johannes M. Schmitt - * - * @deprecated since version 3.4, to be removed in 4.0. See Symfony\Bundle\AclBundle\Command\SetAclCommand instead. - */ -class InitAclCommand extends ContainerAwareCommand -{ - protected static $defaultName = 'init:acl'; - - private $connection; - private $schema; - - public function __construct($connection = null, Schema $schema = null) - { - if (!$connection instanceof Connection) { - parent::__construct($connection); - - return; - } - - parent::__construct(); - - $this->connection = $connection; - $this->schema = $schema; - } - - /** - * {@inheritdoc} - */ - public function isEnabled() - { - if (!$this->connection && !$this->getContainer()->has('security.acl.dbal.connection')) { - return false; - } - - return parent::isEnabled(); - } - - /** - * {@inheritdoc} - */ - protected function configure() - { - $this - ->setDescription('Mounts ACL tables in the database') - ->setHelp(<<<'EOF' -The %command.name% command mounts ACL tables in the database. - - php %command.full_name% - -The name of the DBAL connection must be configured in your app/config/security.yml configuration file in the security.acl.connection variable. - - security: - acl: - connection: default -EOF - ) - ; - } - - /** - * {@inheritdoc} - */ - protected function execute(InputInterface $input, OutputInterface $output) - { - (new SymfonyStyle($input, $output instanceof ConsoleOutputInterface ? $output->getErrorOutput() : $output))->warning('Command "init:acl" is deprecated since version 3.4 and will be removed from SecurityBundle in 4.0. Install symfony/acl-bundle and use "acl:init" instead.'); - - if (null === $this->connection) { - $this->connection = $this->getContainer()->get('security.acl.dbal.connection'); - $this->schema = $this->getContainer()->get('security.acl.dbal.schema'); - } - - try { - $this->schema->addToSchema($this->connection->getSchemaManager()->createSchema()); - } catch (SchemaException $e) { - $output->writeln('Aborting: '.$e->getMessage()); - - return 1; - } - - foreach ($this->schema->toSql($this->connection->getDatabasePlatform()) as $sql) { - $this->connection->exec($sql); - } - - $output->writeln('ACL tables have been initialized successfully.'); - } -} diff --git a/src/Symfony/Bundle/SecurityBundle/Command/SetAclCommand.php b/src/Symfony/Bundle/SecurityBundle/Command/SetAclCommand.php deleted file mode 100644 index c0c51eff4e8c7..0000000000000 --- a/src/Symfony/Bundle/SecurityBundle/Command/SetAclCommand.php +++ /dev/null @@ -1,202 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\SecurityBundle\Command; - -@trigger_error(sprintf('Class "%s" is deprecated since version 3.4 and will be removed in 4.0. Use Symfony\Bundle\AclBundle\Command\SetAclCommand instead.', SetAclCommand::class), E_USER_DEPRECATED); - -use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand; -use Symfony\Component\Console\Input\InputArgument; -use Symfony\Component\Console\Input\InputInterface; -use Symfony\Component\Console\Input\InputOption; -use Symfony\Component\Console\Output\ConsoleOutputInterface; -use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Style\SymfonyStyle; -use Symfony\Component\Security\Acl\Domain\ObjectIdentity; -use Symfony\Component\Security\Acl\Domain\RoleSecurityIdentity; -use Symfony\Component\Security\Acl\Domain\UserSecurityIdentity; -use Symfony\Component\Security\Acl\Exception\AclAlreadyExistsException; -use Symfony\Component\Security\Acl\Permission\MaskBuilder; -use Symfony\Component\Security\Acl\Model\MutableAclProviderInterface; - -/** - * Sets ACL for objects. - * - * @author Kévin Dunglas - * - * @deprecated since version 3.4, to be removed in 4.0. See Symfony\Bundle\AclBundle\Command\SetAclCommand instead. - */ -class SetAclCommand extends ContainerAwareCommand -{ - protected static $defaultName = 'acl:set'; - - private $provider; - - /** - * @param MutableAclProviderInterface $provider - */ - public function __construct($provider = null) - { - if (!$provider instanceof MutableAclProviderInterface) { - parent::__construct($provider); - - return; - } - - parent::__construct(); - - $this->provider = $provider; - } - - /** - * {@inheritdoc} - */ - public function isEnabled() - { - if (null !== $this->provider) { - return parent::isEnabled(); - } - if (!$this->getContainer()->has('security.acl.provider')) { - return false; - } - - $provider = $this->getContainer()->get('security.acl.provider'); - if (!$provider instanceof MutableAclProviderInterface) { - return false; - } - - return parent::isEnabled(); - } - - /** - * {@inheritdoc} - */ - protected function configure() - { - $this - ->setDescription('Sets ACL for objects') - ->setHelp(<<%command.name% command sets ACL. -The ACL system must have been initialized with the init:acl command. - -To set VIEW and EDIT permissions for the user kevin on the instance of -Acme\MyClass having the identifier 42: - - php %command.full_name% --user=Symfony/Component/Security/Core/User/User:kevin VIEW EDIT Acme/MyClass:42 - -Note that you can use / instead of \\ for the namespace delimiter to avoid any -problem. - -To set permissions for a role, use the --role option: - - php %command.full_name% --role=ROLE_USER VIEW Acme/MyClass:1936 - -To set permissions at the class scope, use the --class-scope option: - - php %command.full_name% --class-scope --user=Symfony/Component/Security/Core/User/User:anne OWNER Acme/MyClass:42 - -EOF - ) - ->addArgument('arguments', InputArgument::IS_ARRAY | InputArgument::REQUIRED, 'A list of permissions and object identities (class name and ID separated by a column)') - ->addOption('user', null, InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'A list of security identities') - ->addOption('role', null, InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY, 'A list of roles') - ->addOption('class-scope', null, InputOption::VALUE_NONE, 'Use class-scope entries') - ; - } - - /** - * {@inheritdoc} - */ - protected function execute(InputInterface $input, OutputInterface $output) - { - (new SymfonyStyle($input, $output instanceof ConsoleOutputInterface ? $output->getErrorOutput() : $output))->warning('Command "acl:set" is deprecated since version 3.4 and will be removed from SecurityBundle in 4.0. Install symfony/acl-bundle to use this command.'); - - if (null === $this->provider) { - $this->provider = $this->getContainer()->get('security.acl.provider'); - } - - // Parse arguments - $objectIdentities = array(); - $maskBuilder = $this->getMaskBuilder(); - foreach ($input->getArgument('arguments') as $argument) { - $data = explode(':', $argument, 2); - - if (count($data) > 1) { - $objectIdentities[] = new ObjectIdentity($data[1], strtr($data[0], '/', '\\')); - } else { - $maskBuilder->add($data[0]); - } - } - - // Build permissions mask - $mask = $maskBuilder->get(); - - $userOption = $input->getOption('user'); - $roleOption = $input->getOption('role'); - $classScopeOption = $input->getOption('class-scope'); - - if (empty($userOption) && empty($roleOption)) { - throw new \InvalidArgumentException('A Role or a User must be specified.'); - } - - // Create security identities - $securityIdentities = array(); - - if ($userOption) { - foreach ($userOption as $user) { - $data = explode(':', $user, 2); - - if (1 === count($data)) { - throw new \InvalidArgumentException('The user must follow the format "Acme/MyUser:username".'); - } - - $securityIdentities[] = new UserSecurityIdentity($data[1], strtr($data[0], '/', '\\')); - } - } - - if ($roleOption) { - foreach ($roleOption as $role) { - $securityIdentities[] = new RoleSecurityIdentity($role); - } - } - - // Sets ACL - foreach ($objectIdentities as $objectIdentity) { - // Creates a new ACL if it does not already exist - try { - $this->provider->createAcl($objectIdentity); - } catch (AclAlreadyExistsException $e) { - } - - $acl = $this->provider->findAcl($objectIdentity, $securityIdentities); - - foreach ($securityIdentities as $securityIdentity) { - if ($classScopeOption) { - $acl->insertClassAce($securityIdentity, $mask); - } else { - $acl->insertObjectAce($securityIdentity, $mask); - } - } - - $this->provider->updateAcl($acl); - } - } - - /** - * Gets the mask builder. - * - * @return MaskBuilder - */ - protected function getMaskBuilder() - { - return new MaskBuilder(); - } -} diff --git a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/MainConfiguration.php b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/MainConfiguration.php index 533b52cd4b1c6..078817b3be97e 100644 --- a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/MainConfiguration.php +++ b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/MainConfiguration.php @@ -106,7 +106,6 @@ public function getConfigTreeBuilder() ->end() ; - $this->addAclSection($rootNode); $this->addEncodersSection($rootNode); $this->addProvidersSection($rootNode); $this->addFirewallsSection($rootNode, $this->factories); @@ -116,47 +115,6 @@ public function getConfigTreeBuilder() return $tb; } - private function addAclSection(ArrayNodeDefinition $rootNode) - { - $rootNode - ->children() - ->arrayNode('acl') - ->setDeprecated('The "security.acl" configuration key is deprecated since version 3.4 and will be removed in 4.0. Install symfony/acl-bundle and use the "acl" key instead.') - ->children() - ->scalarNode('connection') - ->defaultNull() - ->info('any name configured in doctrine.dbal section') - ->end() - ->arrayNode('cache') - ->addDefaultsIfNotSet() - ->children() - ->scalarNode('id')->end() - ->scalarNode('prefix')->defaultValue('sf2_acl_')->end() - ->end() - ->end() - ->scalarNode('provider')->end() - ->arrayNode('tables') - ->addDefaultsIfNotSet() - ->children() - ->scalarNode('class')->defaultValue('acl_classes')->end() - ->scalarNode('entry')->defaultValue('acl_entries')->end() - ->scalarNode('object_identity')->defaultValue('acl_object_identities')->end() - ->scalarNode('object_identity_ancestors')->defaultValue('acl_object_identity_ancestors')->end() - ->scalarNode('security_identity')->defaultValue('acl_security_identities')->end() - ->end() - ->end() - ->arrayNode('voter') - ->addDefaultsIfNotSet() - ->children() - ->booleanNode('allow_if_object_identity_unavailable')->defaultTrue()->end() - ->end() - ->end() - ->end() - ->end() - ->end() - ; - } - private function addRoleHierarchySection(ArrayNodeDefinition $rootNode) { $rootNode diff --git a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php index 9462575f3453e..b727c699da4b2 100644 --- a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php +++ b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php @@ -11,8 +11,6 @@ namespace Symfony\Bundle\SecurityBundle\DependencyInjection; -use Symfony\Bundle\SecurityBundle\Command\InitAclCommand; -use Symfony\Bundle\SecurityBundle\Command\SetAclCommand; use Symfony\Bundle\SecurityBundle\Command\UserPasswordEncoderCommand; use Symfony\Bundle\SecurityBundle\DependencyInjection\Security\Factory\SecurityFactoryInterface; use Symfony\Bundle\SecurityBundle\DependencyInjection\Security\UserProvider\UserProviderFactoryInterface; @@ -113,68 +111,10 @@ public function load(array $configs, ContainerBuilder $container) $container->getDefinition(UserPasswordEncoderCommand::class)->replaceArgument(1, array_keys($config['encoders'])); } - // load ACL - if (isset($config['acl'])) { - $this->aclLoad($config['acl'], $container); - } else { - $container->removeDefinition(InitAclCommand::class); - $container->removeDefinition(SetAclCommand::class); - } - $container->registerForAutoconfiguration(VoterInterface::class) ->addTag('security.voter'); } - private function aclLoad($config, ContainerBuilder $container) - { - if (!interface_exists('Symfony\Component\Security\Acl\Model\AclInterface')) { - throw new \LogicException('You must install symfony/security-acl in order to use the ACL functionality.'); - } - - $loader = new XmlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config')); - $loader->load('security_acl.xml'); - - if (isset($config['cache']['id'])) { - $container->setAlias('security.acl.cache', $config['cache']['id'])->setPrivate(true); - } - $container->getDefinition('security.acl.voter.basic_permissions')->addArgument($config['voter']['allow_if_object_identity_unavailable']); - - // custom ACL provider - if (isset($config['provider'])) { - $container->setAlias('security.acl.provider', $config['provider'])->setPrivate(true); - - return; - } - - $this->configureDbalAclProvider($config, $container, $loader); - } - - private function configureDbalAclProvider(array $config, ContainerBuilder $container, $loader) - { - $loader->load('security_acl_dbal.xml'); - - if (null !== $config['connection']) { - $container->setAlias('security.acl.dbal.connection', sprintf('doctrine.dbal.%s_connection', $config['connection']))->setPrivate(true); - } - - $container - ->getDefinition('security.acl.dbal.schema_listener') - ->addTag('doctrine.event_listener', array( - 'connection' => $config['connection'], - 'event' => 'postGenerateSchema', - 'lazy' => true, - )) - ; - - $container->getDefinition('security.acl.cache.doctrine')->addArgument($config['cache']['prefix']); - - $container->setParameter('security.acl.dbal.class_table_name', $config['tables']['class']); - $container->setParameter('security.acl.dbal.entry_table_name', $config['tables']['entry']); - $container->setParameter('security.acl.dbal.oid_table_name', $config['tables']['object_identity']); - $container->setParameter('security.acl.dbal.oid_ancestors_table_name', $config['tables']['object_identity_ancestors']); - $container->setParameter('security.acl.dbal.sid_table_name', $config['tables']['security_identity']); - } - /** * Loads the web configuration. * diff --git a/src/Symfony/Bundle/SecurityBundle/Resources/config/console.xml b/src/Symfony/Bundle/SecurityBundle/Resources/config/console.xml index b375d95effe5c..34feeeb9e8fd5 100644 --- a/src/Symfony/Bundle/SecurityBundle/Resources/config/console.xml +++ b/src/Symfony/Bundle/SecurityBundle/Resources/config/console.xml @@ -7,17 +7,6 @@ - - - - - - - - - - - diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/CompleteConfigurationTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/CompleteConfigurationTest.php index 138c7e9233480..d274d4005e854 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/CompleteConfigurationTest.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/CompleteConfigurationTest.php @@ -36,20 +36,6 @@ public function testRolesHierarchy() ), $container->getParameter('security.role_hierarchy.roles')); } - /** - * @group legacy - * @expectedDeprecation The "security.acl" configuration key is deprecated since version 3.4 and will be removed in 4.0. Install symfony/acl-bundle and use the "acl" key instead. - */ - public function testRolesHierarchyWithAcl() - { - $container = $this->getContainer('container1_with_acl'); - $this->assertEquals(array( - 'ROLE_ADMIN' => array('ROLE_USER'), - 'ROLE_SUPER_ADMIN' => array('ROLE_USER', 'ROLE_ADMIN', 'ROLE_ALLOWED_TO_SWITCH'), - 'ROLE_REMOTE' => array('ROLE_USER', 'ROLE_ADMIN'), - ), $container->getParameter('security.role_hierarchy.roles')); - } - public function testUserProviders() { $container = $this->getContainer('container1'); @@ -324,30 +310,6 @@ public function testEncoders() )), $container->getDefinition('security.encoder_factory.generic')->getArguments()); } - /** - * @group legacy - * @expectedDeprecation The "security.acl" configuration key is deprecated since version 3.4 and will be removed in 4.0. Install symfony/acl-bundle and use the "acl" key instead. - */ - public function testAcl() - { - $container = $this->getContainer('container1_with_acl'); - - $this->assertTrue($container->hasDefinition('security.acl.dbal.provider')); - $this->assertEquals('security.acl.dbal.provider', (string) $container->getAlias('security.acl.provider')); - } - - /** - * @group legacy - * @expectedDeprecation The "security.acl" configuration key is deprecated since version 3.4 and will be removed in 4.0. Install symfony/acl-bundle and use the "acl" key instead. - */ - public function testCustomAclProvider() - { - $container = $this->getContainer('custom_acl_provider'); - - $this->assertFalse($container->hasDefinition('security.acl.dbal.provider')); - $this->assertEquals('foo', (string) $container->getAlias('security.acl.provider')); - } - public function testRememberMeThrowExceptionsDefault() { $container = $this->getContainer('container1'); diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/container1_with_acl.php b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/container1_with_acl.php deleted file mode 100644 index 268ced04dbfb4..0000000000000 --- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/container1_with_acl.php +++ /dev/null @@ -1,101 +0,0 @@ -loadFromExtension('security', array( - 'acl' => array(), - 'encoders' => array( - 'JMS\FooBundle\Entity\User1' => 'plaintext', - 'JMS\FooBundle\Entity\User2' => array( - 'algorithm' => 'sha1', - 'encode_as_base64' => false, - 'iterations' => 5, - ), - 'JMS\FooBundle\Entity\User3' => array( - 'algorithm' => 'md5', - ), - 'JMS\FooBundle\Entity\User4' => array( - 'id' => 'security.encoder.foo', - ), - 'JMS\FooBundle\Entity\User5' => array( - 'algorithm' => 'pbkdf2', - 'hash_algorithm' => 'sha1', - 'encode_as_base64' => false, - 'iterations' => 5, - 'key_length' => 30, - ), - 'JMS\FooBundle\Entity\User6' => array( - 'algorithm' => 'bcrypt', - 'cost' => 15, - ), - ), - 'providers' => array( - 'default' => array( - 'memory' => array( - 'users' => array( - 'foo' => array('password' => 'foo', 'roles' => 'ROLE_USER'), - ), - ), - ), - 'digest' => array( - 'memory' => array( - 'users' => array( - 'foo' => array('password' => 'foo', 'roles' => 'ROLE_USER, ROLE_ADMIN'), - ), - ), - ), - 'basic' => array( - 'memory' => array( - 'users' => array( - 'foo' => array('password' => '0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33', 'roles' => 'ROLE_SUPER_ADMIN'), - 'bar' => array('password' => '0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33', 'roles' => array('ROLE_USER', 'ROLE_ADMIN')), - ), - ), - ), - 'service' => array( - 'id' => 'user.manager', - ), - 'chain' => array( - 'chain' => array( - 'providers' => array('service', 'basic'), - ), - ), - ), - - 'firewalls' => array( - 'simple' => array('pattern' => '/login', 'security' => false), - 'secure' => array('stateless' => true, - 'http_basic' => true, - 'form_login' => true, - 'anonymous' => true, - 'switch_user' => true, - 'x509' => true, - 'remote_user' => true, - 'logout' => true, - 'remember_me' => array('secret' => 'TheSecret'), - 'user_checker' => null, - ), - 'host' => array( - 'pattern' => '/test', - 'host' => 'foo\\.example\\.org', - 'methods' => array('GET', 'POST'), - 'anonymous' => true, - 'http_basic' => true, - ), - 'with_user_checker' => array( - 'user_checker' => 'app.user_checker', - 'anonymous' => true, - 'http_basic' => true, - ), - ), - - 'access_control' => array( - array('path' => '/blog/524', 'role' => 'ROLE_USER', 'requires_channel' => 'https', 'methods' => array('get', 'POST')), - array('path' => '/blog/.*', 'role' => 'IS_AUTHENTICATED_ANONYMOUSLY'), - array('path' => '/blog/524', 'role' => 'IS_AUTHENTICATED_ANONYMOUSLY', 'allow_if' => "token.getUsername() matches '/^admin/'"), - ), - - 'role_hierarchy' => array( - 'ROLE_ADMIN' => 'ROLE_USER', - 'ROLE_SUPER_ADMIN' => array('ROLE_USER', 'ROLE_ADMIN', 'ROLE_ALLOWED_TO_SWITCH'), - 'ROLE_REMOTE' => 'ROLE_USER,ROLE_ADMIN', - ), -)); diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/container1_with_acl.xml b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/container1_with_acl.xml deleted file mode 100644 index 7797c38287193..0000000000000 --- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/container1_with_acl.xml +++ /dev/null @@ -1,80 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - app.user_checker - - - ROLE_USER - ROLE_USER,ROLE_ADMIN,ROLE_ALLOWED_TO_SWITCH - ROLE_USER,ROLE_ADMIN - - - - - - diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/container1_with_acl.yml b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/container1_with_acl.yml deleted file mode 100644 index 40e0f1a81e2f6..0000000000000 --- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/container1_with_acl.yml +++ /dev/null @@ -1,81 +0,0 @@ -security: - acl: ~ - encoders: - JMS\FooBundle\Entity\User1: plaintext - JMS\FooBundle\Entity\User2: - algorithm: sha1 - encode_as_base64: false - iterations: 5 - JMS\FooBundle\Entity\User3: - algorithm: md5 - JMS\FooBundle\Entity\User4: - id: security.encoder.foo - JMS\FooBundle\Entity\User5: - algorithm: pbkdf2 - hash_algorithm: sha1 - encode_as_base64: false - iterations: 5 - key_length: 30 - JMS\FooBundle\Entity\User6: - algorithm: bcrypt - cost: 15 - - providers: - default: - memory: - users: - foo: { password: foo, roles: ROLE_USER } - digest: - memory: - users: - foo: { password: foo, roles: 'ROLE_USER, ROLE_ADMIN' } - basic: - memory: - users: - foo: { password: 0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33, roles: ROLE_SUPER_ADMIN } - bar: { password: 0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33, roles: [ROLE_USER, ROLE_ADMIN] } - service: - id: user.manager - chain: - chain: - providers: [service, basic] - - - firewalls: - simple: { pattern: /login, security: false } - secure: - stateless: true - http_basic: true - form_login: true - anonymous: true - switch_user: true - x509: true - remote_user: true - logout: true - remember_me: - secret: TheSecret - user_checker: ~ - - host: - pattern: /test - host: foo\.example\.org - methods: [GET,POST] - anonymous: true - http_basic: true - - with_user_checker: - anonymous: ~ - http_basic: ~ - user_checker: app.user_checker - - role_hierarchy: - ROLE_ADMIN: ROLE_USER - ROLE_SUPER_ADMIN: [ROLE_USER, ROLE_ADMIN, ROLE_ALLOWED_TO_SWITCH] - ROLE_REMOTE: ROLE_USER,ROLE_ADMIN - - access_control: - - { path: /blog/524, role: ROLE_USER, requires_channel: https, methods: [get, POST]} - - - path: /blog/.* - role: IS_AUTHENTICATED_ANONYMOUSLY - - { path: /blog/524, role: IS_AUTHENTICATED_ANONYMOUSLY, allow_if: "token.getUsername() matches '/^admin/'" } diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/SetAclCommandTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/SetAclCommandTest.php deleted file mode 100644 index a658126fce347..0000000000000 --- a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/SetAclCommandTest.php +++ /dev/null @@ -1,177 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\SecurityBundle\Tests\Functional; - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ -use Symfony\Bundle\FrameworkBundle\Console\Application; -use Symfony\Bundle\SecurityBundle\Command\SetAclCommand; -use Symfony\Component\Console\Tester\CommandTester; -use Symfony\Component\Security\Acl\Domain\ObjectIdentity; -use Symfony\Component\Security\Acl\Domain\RoleSecurityIdentity; -use Symfony\Component\Security\Acl\Domain\UserSecurityIdentity; -use Symfony\Component\Security\Acl\Exception\NoAceFoundException; -use Symfony\Component\Security\Acl\Permission\BasicPermissionMap; - -/** - * Tests SetAclCommand. - * - * @author Kévin Dunglas - * @requires extension pdo_sqlite - * @group legacy - */ -class SetAclCommandTest extends WebTestCase -{ - const OBJECT_CLASS = 'Symfony\Bundle\SecurityBundle\Tests\Functional\Bundle\AclBundle\Entity\Car'; - const SECURITY_CLASS = 'Symfony\Component\Security\Core\User\User'; - - public function testSetAclUser() - { - $objectId = 1; - $securityUsername1 = 'kevin'; - $securityUsername2 = 'anne'; - $grantedPermission1 = 'VIEW'; - $grantedPermission2 = 'EDIT'; - - $application = $this->getApplication(); - $application->add(new SetAclCommand($application->getKernel()->getContainer()->get('test.security.acl.provider'))); - - $setAclCommand = $application->find('acl:set'); - $setAclCommandTester = new CommandTester($setAclCommand); - $setAclCommandTester->execute(array( - 'command' => 'acl:set', - 'arguments' => array($grantedPermission1, $grantedPermission2, sprintf('%s:%s', self::OBJECT_CLASS, $objectId)), - '--user' => array(sprintf('%s:%s', self::SECURITY_CLASS, $securityUsername1), sprintf('%s:%s', self::SECURITY_CLASS, $securityUsername2)), - )); - - $objectIdentity = new ObjectIdentity($objectId, self::OBJECT_CLASS); - $securityIdentity1 = new UserSecurityIdentity($securityUsername1, self::SECURITY_CLASS); - $securityIdentity2 = new UserSecurityIdentity($securityUsername2, self::SECURITY_CLASS); - $permissionMap = new BasicPermissionMap(); - - /** @var \Symfony\Component\Security\Acl\Model\AclProviderInterface $aclProvider */ - $aclProvider = $application->getKernel()->getContainer()->get('test.security.acl.provider'); - $acl = $aclProvider->findAcl($objectIdentity, array($securityIdentity1)); - - $this->assertTrue($acl->isGranted($permissionMap->getMasks($grantedPermission1, null), array($securityIdentity1))); - $this->assertTrue($acl->isGranted($permissionMap->getMasks($grantedPermission1, null), array($securityIdentity2))); - $this->assertTrue($acl->isGranted($permissionMap->getMasks($grantedPermission2, null), array($securityIdentity2))); - - try { - $acl->isGranted($permissionMap->getMasks('OWNER', null), array($securityIdentity1)); - $this->fail('NoAceFoundException not throwed'); - } catch (NoAceFoundException $e) { - } - - try { - $acl->isGranted($permissionMap->getMasks('OPERATOR', null), array($securityIdentity2)); - $this->fail('NoAceFoundException not throwed'); - } catch (NoAceFoundException $e) { - } - } - - public function testSetAclRole() - { - $objectId = 1; - $securityUsername = 'kevin'; - $grantedPermission = 'VIEW'; - $role = 'ROLE_ADMIN'; - - $application = $this->getApplication(); - $application->add(new SetAclCommand($application->getKernel()->getContainer()->get('test.security.acl.provider'))); - - $setAclCommand = $application->find('acl:set'); - $setAclCommandTester = new CommandTester($setAclCommand); - $setAclCommandTester->execute(array( - 'command' => 'acl:set', - 'arguments' => array($grantedPermission, sprintf('%s:%s', str_replace('\\', '/', self::OBJECT_CLASS), $objectId)), - '--role' => array($role), - )); - - $objectIdentity = new ObjectIdentity($objectId, self::OBJECT_CLASS); - $userSecurityIdentity = new UserSecurityIdentity($securityUsername, self::SECURITY_CLASS); - $roleSecurityIdentity = new RoleSecurityIdentity($role); - $permissionMap = new BasicPermissionMap(); - - /** @var \Symfony\Component\Security\Acl\Model\AclProviderInterface $aclProvider */ - $aclProvider = $application->getKernel()->getContainer()->get('test.security.acl.provider'); - $acl = $aclProvider->findAcl($objectIdentity, array($roleSecurityIdentity, $userSecurityIdentity)); - - $this->assertTrue($acl->isGranted($permissionMap->getMasks($grantedPermission, null), array($roleSecurityIdentity))); - $this->assertTrue($acl->isGranted($permissionMap->getMasks($grantedPermission, null), array($roleSecurityIdentity))); - - try { - $acl->isGranted($permissionMap->getMasks('VIEW', null), array($userSecurityIdentity)); - $this->fail('NoAceFoundException not throwed'); - } catch (NoAceFoundException $e) { - } - - try { - $acl->isGranted($permissionMap->getMasks('OPERATOR', null), array($userSecurityIdentity)); - $this->fail('NoAceFoundException not throwed'); - } catch (NoAceFoundException $e) { - } - } - - public function testSetAclClassScope() - { - $objectId = 1; - $grantedPermission = 'VIEW'; - $role = 'ROLE_USER'; - - $application = $this->getApplication(); - $application->add(new SetAclCommand($application->getKernel()->getContainer()->get('test.security.acl.provider'))); - - $setAclCommand = $application->find('acl:set'); - $setAclCommandTester = new CommandTester($setAclCommand); - $setAclCommandTester->execute(array( - 'command' => 'acl:set', - 'arguments' => array($grantedPermission, sprintf('%s:%s', self::OBJECT_CLASS, $objectId)), - '--class-scope' => true, - '--role' => array($role), - )); - - $objectIdentity1 = new ObjectIdentity($objectId, self::OBJECT_CLASS); - $objectIdentity2 = new ObjectIdentity(2, self::OBJECT_CLASS); - $roleSecurityIdentity = new RoleSecurityIdentity($role); - $permissionMap = new BasicPermissionMap(); - - /** @var \Symfony\Component\Security\Acl\Model\AclProviderInterface $aclProvider */ - $aclProvider = $application->getKernel()->getContainer()->get('test.security.acl.provider'); - - $acl1 = $aclProvider->findAcl($objectIdentity1, array($roleSecurityIdentity)); - $this->assertTrue($acl1->isGranted($permissionMap->getMasks($grantedPermission, null), array($roleSecurityIdentity))); - - $acl2 = $aclProvider->createAcl($objectIdentity2); - $this->assertTrue($acl2->isGranted($permissionMap->getMasks($grantedPermission, null), array($roleSecurityIdentity))); - } - - private function getApplication() - { - $kernel = $this->createKernel(array('test_case' => 'Acl')); - $kernel->boot(); - - $application = new Application($kernel); - - $initAclCommand = $application->find('init:acl'); - $initAclCommandTester = new CommandTester($initAclCommand); - $initAclCommandTester->execute(array('command' => 'init:acl')); - - return $application; - } -} From 37d1a212f998ba5865ec7b5d471868afdcd8deba Mon Sep 17 00:00:00 2001 From: Alexandru Furculita Date: Tue, 26 Sep 2017 22:01:24 +0300 Subject: [PATCH 0916/1099] Removed compatibility layer for PHP <5.4 sessions Signed-off-by: Alexandru Furculita --- .../Bridge/Twig/Tests/AppVariableTest.php | 8 +- .../Tests/Controller/ControllerTraitTest.php | 2 +- .../Component/HttpFoundation/CHANGELOG.md | 5 + .../Handler/NativeFileSessionHandler.php | 2 +- .../Storage/Handler/NativeSessionHandler.php | 22 --- .../Session/Storage/NativeSessionStorage.php | 75 ++++------- .../Session/Storage/Proxy/AbstractProxy.php | 126 ------------------ .../Session/Storage/Proxy/NativeProxy.php | 43 ------ .../Storage/Proxy/SessionHandlerProxy.php | 92 ------------- .../Handler/NativeFileSessionHandlerTest.php | 1 - .../Handler/NativeSessionHandlerTest.php | 35 ----- .../Storage/NativeSessionStorageTest.php | 63 ++++++--- .../Storage/PhpBridgeSessionStorageTest.php | 5 +- .../Storage/Proxy/AbstractProxyTest.php | 115 ---------------- .../Session/Storage/Proxy/NativeProxyTest.php | 38 ------ .../Storage/Proxy/SessionHandlerProxyTest.php | 125 ----------------- 16 files changed, 88 insertions(+), 669 deletions(-) delete mode 100644 src/Symfony/Component/HttpFoundation/Session/Storage/Handler/NativeSessionHandler.php delete mode 100644 src/Symfony/Component/HttpFoundation/Session/Storage/Proxy/AbstractProxy.php delete mode 100644 src/Symfony/Component/HttpFoundation/Session/Storage/Proxy/NativeProxy.php delete mode 100644 src/Symfony/Component/HttpFoundation/Session/Storage/Proxy/SessionHandlerProxy.php delete mode 100644 src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/NativeSessionHandlerTest.php delete mode 100644 src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Proxy/AbstractProxyTest.php delete mode 100644 src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Proxy/NativeProxyTest.php delete mode 100644 src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Proxy/SessionHandlerProxyTest.php diff --git a/src/Symfony/Bridge/Twig/Tests/AppVariableTest.php b/src/Symfony/Bridge/Twig/Tests/AppVariableTest.php index c258ad41a1465..2a97c269031c8 100644 --- a/src/Symfony/Bridge/Twig/Tests/AppVariableTest.php +++ b/src/Symfony/Bridge/Twig/Tests/AppVariableTest.php @@ -47,9 +47,8 @@ public function testEnvironment() public function testGetSession() { - $session = $this->getMockBuilder(Session::class)->disableOriginalConstructor()->getMock(); $request = $this->getMockBuilder('Symfony\Component\HttpFoundation\Request')->getMock(); - $request->method('getSession')->willReturn($session); + $request->method('getSession')->willReturn($session = new Session()); $this->setRequestStack($request); @@ -168,9 +167,8 @@ public function testGetFlashesWithNoRequest() public function testGetFlashesWithNoSessionStarted() { - $session = $this->getMockBuilder(Session::class)->disableOriginalConstructor()->getMock(); $request = $this->getMockBuilder('Symfony\Component\HttpFoundation\Request')->getMock(); - $request->method('getSession')->willReturn($session); + $request->method('getSession')->willReturn(new Session()); $this->setRequestStack($request); @@ -259,7 +257,7 @@ private function setFlashMessages() $flashBag = new FlashBag(); $flashBag->initialize($flashMessages); - $session = $this->getMockBuilder('Symfony\Component\HttpFoundation\Session\Session')->disableOriginalConstructor()->getMock(); + $session = $this->getMockBuilder('Symfony\Component\HttpFoundation\Session\Session')->getMock(); $session->method('isStarted')->willReturn(true); $session->method('getFlashBag')->willReturn($flashBag); diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/ControllerTraitTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/ControllerTraitTest.php index 71e6f581e7389..3feabfd12e273 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/ControllerTraitTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/ControllerTraitTest.php @@ -376,7 +376,7 @@ public function testRedirectToRoute() public function testAddFlash() { $flashBag = new FlashBag(); - $session = $this->getMockBuilder('Symfony\Component\HttpFoundation\Session\Session')->disableOriginalConstructor()->getMock(); + $session = $this->getMockBuilder('Symfony\Component\HttpFoundation\Session\Session')->getMock(); $session->expects($this->once())->method('getFlashBag')->willReturn($flashBag); $container = new Container(); diff --git a/src/Symfony/Component/HttpFoundation/CHANGELOG.md b/src/Symfony/Component/HttpFoundation/CHANGELOG.md index ff69bc0b4fe9a..46d5ac73aea6e 100644 --- a/src/Symfony/Component/HttpFoundation/CHANGELOG.md +++ b/src/Symfony/Component/HttpFoundation/CHANGELOG.md @@ -17,6 +17,11 @@ CHANGELOG * checking for cacheable HTTP methods using the `Request::isMethodSafe()` method (by not passing `false` as its argument) is not supported anymore and throws a `\BadMethodCallException` + * the `NativeSessionHandler` class has been removed + * the `AbstractProxy`, `NativeProxy` and `SessionHandlerProxy` classes have been removed + * setting session save handlers that do not implement `\SessionHandlerInterface` in + `NativeSessionStorage::setSaveHandler()` is not supported anymore and throws a + `\TypeError` 3.4.0 ----- diff --git a/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/NativeFileSessionHandler.php b/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/NativeFileSessionHandler.php index 4e9704bd5858f..b052b32dab6cf 100644 --- a/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/NativeFileSessionHandler.php +++ b/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/NativeFileSessionHandler.php @@ -16,7 +16,7 @@ * * @author Drak */ -class NativeFileSessionHandler extends NativeSessionHandler +class NativeFileSessionHandler extends \SessionHandler { /** * @param string $savePath Path of directory to save session files diff --git a/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/NativeSessionHandler.php b/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/NativeSessionHandler.php deleted file mode 100644 index daa7dbd15b7c8..0000000000000 --- a/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/NativeSessionHandler.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Session\Storage\Handler; - -@trigger_error('The '.__NAMESPACE__.'\NativeSessionHandler class is deprecated since version 3.4 and will be removed in 4.0. Use the \SessionHandler class instead.', E_USER_DEPRECATED); - -/** - * @deprecated since version 3.4, to be removed in 4.0. Use \SessionHandler instead. - * @see http://php.net/sessionhandler - */ -class NativeSessionHandler extends \SessionHandler -{ -} diff --git a/src/Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.php b/src/Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.php index 3c22b85af639f..7145bf92c5e23 100644 --- a/src/Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.php +++ b/src/Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.php @@ -12,8 +12,6 @@ namespace Symfony\Component\HttpFoundation\Session\Storage; use Symfony\Component\HttpFoundation\Session\SessionBagInterface; -use Symfony\Component\HttpFoundation\Session\Storage\Proxy\AbstractProxy; -use Symfony\Component\HttpFoundation\Session\Storage\Proxy\SessionHandlerProxy; /** * This provides a base class for session attribute storage. @@ -38,7 +36,7 @@ class NativeSessionStorage implements SessionStorageInterface protected $closed = false; /** - * @var AbstractProxy|\SessionHandlerInterface + * @var \SessionHandlerInterface */ protected $saveHandler; @@ -87,12 +85,8 @@ class NativeSessionStorage implements SessionStorageInterface * sid_bits_per_character, "5" * 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 */ - public function __construct(array $options = array(), $handler = null, MetadataBag $metaBag = null) + public function __construct(array $options = array(), \SessionHandlerInterface $handler = null, MetadataBag $metaBag = null) { session_cache_limiter(''); // disable by default because it's managed by HeaderBag (if used) ini_set('session.use_cookies', 1); @@ -107,7 +101,7 @@ public function __construct(array $options = array(), $handler = null, MetadataB /** * Gets the save handler instance. * - * @return AbstractProxy|\SessionHandlerInterface + * @return \SessionHandlerInterface */ public function getSaveHandler() { @@ -146,15 +140,21 @@ public function start() */ public function getId() { - return $this->saveHandler->getId(); + return session_id(); } /** * {@inheritdoc} + * + * @throws \LogicException When the session is active */ public function setId($id) { - $this->saveHandler->setId($id); + if (\PHP_SESSION_ACTIVE === session_status()) { + throw new \LogicException('Cannot change the ID of an active session'); + } + + session_id($id); } /** @@ -162,15 +162,21 @@ public function setId($id) */ public function getName() { - return $this->saveHandler->getName(); + return session_name(); } /** * {@inheritdoc} + * + * @throws \LogicException When the session is active */ public function setName($name) { - $this->saveHandler->setName($name); + if (\PHP_SESSION_ACTIVE === session_status()) { + throw new \LogicException('Cannot change the name of an active session'); + } + + session_name($name); } /** @@ -217,9 +223,6 @@ public function save() // The default PHP error message is not very helpful, as it does not give any information on the current save handler. // Therefore, we catch this error and trigger a warning with a better error message $handler = $this->getSaveHandler(); - if ($handler instanceof SessionHandlerProxy) { - $handler = $handler->getHandler(); - } restore_error_handler(); trigger_error(sprintf('session_write_close(): Failed to write session data with %s handler', get_class($handler)), E_USER_WARNING); @@ -248,6 +251,8 @@ public function clear() /** * {@inheritdoc} + * + * @throws \LogicException When the session is already started */ public function registerBag(SessionBagInterface $bag) { @@ -267,7 +272,7 @@ public function getBag($name) throw new \InvalidArgumentException(sprintf('The SessionBagInterface %s is not registered.', $name)); } - if (!$this->started && $this->saveHandler->isActive()) { + if (!$this->started && \PHP_SESSION_ACTIVE === session_status()) { $this->loadSession(); } elseif (!$this->started) { $this->start(); @@ -357,37 +362,12 @@ public function setOptions(array $options) * @see http://php.net/sessionhandlerinterface * @see http://php.net/sessionhandler * @see http://github.com/drak/NativeSession - * - * @param \SessionHandlerInterface|null $saveHandler - * - * @throws \InvalidArgumentException */ - public function setSaveHandler($saveHandler = null) + public function setSaveHandler(\SessionHandlerInterface $saveHandler = null) { - if (!$saveHandler instanceof AbstractProxy && - !$saveHandler instanceof \SessionHandlerInterface && - null !== $saveHandler) { - throw new \InvalidArgumentException('Must be instance of AbstractProxy; implement \SessionHandlerInterface; or be null.'); - } + $this->saveHandler = $saveHandler ?: new \SessionHandler(); - if ($saveHandler instanceof AbstractProxy) { - @trigger_error( - 'Using session save handlers that are instances of AbstractProxy is deprecated since version 3.4 and will be removed in 4.0.', - E_USER_DEPRECATED - ); - } - - // Wrap $saveHandler in proxy and prevent double wrapping of proxy - if (!$saveHandler instanceof AbstractProxy && $saveHandler instanceof \SessionHandlerInterface) { - $saveHandler = new SessionHandlerProxy($saveHandler); - } elseif (!$saveHandler instanceof AbstractProxy) { - $saveHandler = new SessionHandlerProxy(new \SessionHandler()); - } - $this->saveHandler = $saveHandler; - - if ($this->saveHandler instanceof \SessionHandlerInterface) { - session_set_save_handler($this->saveHandler, false); - } + session_set_save_handler($this->saveHandler, false); } /** @@ -406,11 +386,12 @@ protected function loadSession(array &$session = null) $session = &$_SESSION; } - $bags = array_merge($this->bags, array($this->metadataBag)); + $bags = $this->bags; + $bags[] = $this->metadataBag; foreach ($bags as $bag) { $key = $bag->getStorageKey(); - $session[$key] = isset($session[$key]) ? $session[$key] : array(); + $session[$key] = $session[$key] ?? array(); $bag->initialize($session[$key]); } diff --git a/src/Symfony/Component/HttpFoundation/Session/Storage/Proxy/AbstractProxy.php b/src/Symfony/Component/HttpFoundation/Session/Storage/Proxy/AbstractProxy.php deleted file mode 100644 index c1c8b9b1f7dd2..0000000000000 --- a/src/Symfony/Component/HttpFoundation/Session/Storage/Proxy/AbstractProxy.php +++ /dev/null @@ -1,126 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Session\Storage\Proxy; - -@trigger_error('The '.__NAMESPACE__.'\AbstractProxy class is deprecated since version 3.4 and will be removed in 4.0. Use your session handler implementation directly.', E_USER_DEPRECATED); - -/** - * @deprecated since version 3.4, to be removed in 4.0. Use your session handler implementation directly. - * - * @author Drak - */ -abstract class AbstractProxy -{ - /** - * Flag if handler wraps an internal PHP session handler (using \SessionHandler). - * - * @var bool - */ - protected $wrapper = false; - - /** - * @var string - */ - protected $saveHandlerName; - - /** - * Gets the session.save_handler name. - * - * @return string - */ - public function getSaveHandlerName() - { - return $this->saveHandlerName; - } - - /** - * Is this proxy handler and instance of \SessionHandlerInterface. - * - * @return bool - */ - public function isSessionHandlerInterface() - { - return $this instanceof \SessionHandlerInterface; - } - - /** - * Returns true if this handler wraps an internal PHP session save handler using \SessionHandler. - * - * @return bool - */ - public function isWrapper() - { - return $this->wrapper; - } - - /** - * Has a session started? - * - * @return bool - */ - public function isActive() - { - return \PHP_SESSION_ACTIVE === session_status(); - } - - /** - * Gets the session ID. - * - * @return string - */ - public function getId() - { - return session_id(); - } - - /** - * Sets the session ID. - * - * @param string $id - * - * @throws \LogicException - */ - public function setId($id) - { - if ($this->isActive()) { - throw new \LogicException('Cannot change the ID of an active session'); - } - - session_id($id); - } - - /** - * Gets the session name. - * - * @return string - */ - public function getName() - { - return session_name(); - } - - /** - * Sets the session name. - * - * @param string $name - * - * @throws \LogicException - */ - public function setName($name) - { - if ($this->isActive()) { - throw new \LogicException('Cannot change the name of an active session'); - } - - session_name($name); - } -} diff --git a/src/Symfony/Component/HttpFoundation/Session/Storage/Proxy/NativeProxy.php b/src/Symfony/Component/HttpFoundation/Session/Storage/Proxy/NativeProxy.php deleted file mode 100644 index e75497d57c3b3..0000000000000 --- a/src/Symfony/Component/HttpFoundation/Session/Storage/Proxy/NativeProxy.php +++ /dev/null @@ -1,43 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Session\Storage\Proxy; - -@trigger_error('The '.__NAMESPACE__.'\NativeProxy class is deprecated since version 3.4 and will be removed in 4.0. Use your session handler implementation directly.', E_USER_DEPRECATED); - -/** - * This proxy is built-in session handlers in PHP 5.3.x. - * - * @deprecated since version 3.4, to be removed in 4.0. Use your session handler implementation directly. - * - * @author Drak - */ -class NativeProxy extends AbstractProxy -{ - /** - * Constructor. - */ - public function __construct() - { - // this makes an educated guess as to what the handler is since it should already be set. - $this->saveHandlerName = ini_get('session.save_handler'); - } - - /** - * Returns true if this handler wraps an internal PHP session save handler using \SessionHandler. - * - * @return bool False - */ - public function isWrapper() - { - return false; - } -} diff --git a/src/Symfony/Component/HttpFoundation/Session/Storage/Proxy/SessionHandlerProxy.php b/src/Symfony/Component/HttpFoundation/Session/Storage/Proxy/SessionHandlerProxy.php deleted file mode 100644 index d6adef82dbf65..0000000000000 --- a/src/Symfony/Component/HttpFoundation/Session/Storage/Proxy/SessionHandlerProxy.php +++ /dev/null @@ -1,92 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Session\Storage\Proxy; - -@trigger_error('The '.__NAMESPACE__.'\SessionHandlerProxy class is deprecated since version 3.4 and will be removed in 4.0. Use your session handler implementation directly.', E_USER_DEPRECATED); - -/** - * @deprecated since version 3.4, to be removed in 4.0. Use your session handler implementation directly. - * - * @author Drak - */ -class SessionHandlerProxy extends AbstractProxy implements \SessionHandlerInterface -{ - /** - * @var \SessionHandlerInterface - */ - protected $handler; - - public function __construct(\SessionHandlerInterface $handler) - { - $this->handler = $handler; - $this->wrapper = ($handler instanceof \SessionHandler); - $this->saveHandlerName = $this->wrapper ? ini_get('session.save_handler') : 'user'; - } - - /** - * @return \SessionHandlerInterface - */ - public function getHandler() - { - return $this->handler; - } - - // \SessionHandlerInterface - - /** - * {@inheritdoc} - */ - public function open($savePath, $sessionName) - { - return (bool) $this->handler->open($savePath, $sessionName); - } - - /** - * {@inheritdoc} - */ - public function close() - { - return (bool) $this->handler->close(); - } - - /** - * {@inheritdoc} - */ - public function read($sessionId) - { - return (string) $this->handler->read($sessionId); - } - - /** - * {@inheritdoc} - */ - public function write($sessionId, $data) - { - return (bool) $this->handler->write($sessionId, $data); - } - - /** - * {@inheritdoc} - */ - public function destroy($sessionId) - { - return (bool) $this->handler->destroy($sessionId); - } - - /** - * {@inheritdoc} - */ - public function gc($maxlifetime) - { - return (bool) $this->handler->gc($maxlifetime); - } -} diff --git a/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/NativeFileSessionHandlerTest.php b/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/NativeFileSessionHandlerTest.php index a6264e51d2a72..95e725f4bc8a6 100644 --- a/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/NativeFileSessionHandlerTest.php +++ b/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/NativeFileSessionHandlerTest.php @@ -29,7 +29,6 @@ public function testConstruct() { $storage = new NativeSessionStorage(array('name' => 'TESTING'), new NativeFileSessionHandler(sys_get_temp_dir())); - $this->assertEquals('files', $storage->getSaveHandler()->getSaveHandlerName()); $this->assertEquals('user', ini_get('session.save_handler')); $this->assertEquals(sys_get_temp_dir(), ini_get('session.save_path')); diff --git a/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/NativeSessionHandlerTest.php b/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/NativeSessionHandlerTest.php deleted file mode 100644 index fe4cc72d23b56..0000000000000 --- a/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/NativeSessionHandlerTest.php +++ /dev/null @@ -1,35 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Tests\Session\Storage\Handler; - -use PHPUnit\Framework\TestCase; -use Symfony\Component\HttpFoundation\Session\Storage\Handler\NativeSessionHandler; - -/** - * Test class for NativeSessionHandler. - * - * @author Drak - * - * @runTestsInSeparateProcesses - * @preserveGlobalState disabled - * @group legacy - */ -class NativeSessionHandlerTest extends TestCase -{ - public function testConstruct() - { - $handler = new NativeSessionHandler(); - - $this->assertTrue($handler instanceof \SessionHandler); - $this->assertTrue($handler instanceof NativeSessionHandler); - } -} diff --git a/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/NativeSessionStorageTest.php b/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/NativeSessionStorageTest.php index 818c63a9d2ae2..067fc392e8cd8 100644 --- a/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/NativeSessionStorageTest.php +++ b/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/NativeSessionStorageTest.php @@ -14,10 +14,8 @@ use PHPUnit\Framework\TestCase; use Symfony\Component\HttpFoundation\Session\Attribute\AttributeBag; use Symfony\Component\HttpFoundation\Session\Flash\FlashBag; -use Symfony\Component\HttpFoundation\Session\Storage\Handler\NativeSessionHandler; use Symfony\Component\HttpFoundation\Session\Storage\Handler\NullSessionHandler; use Symfony\Component\HttpFoundation\Session\Storage\NativeSessionStorage; -use Symfony\Component\HttpFoundation\Session\Storage\Proxy\SessionHandlerProxy; /** * Test class for NativeSessionStorage. @@ -100,6 +98,7 @@ public function testGetId() $storage->start(); $id = $storage->getId(); + $this->assertEquals(session_id(), $id); $this->assertInternalType('string', $id); $this->assertNotSame('', $id); @@ -107,6 +106,44 @@ public function testGetId() $this->assertSame($id, $storage->getId(), 'ID stays after saving session'); } + public function testId() + { + $storage = $this->getStorage(); + + $this->assertEquals(session_id(), $storage->getId()); + $storage->setId('foo'); + $this->assertEquals('foo', $storage->getId()); + $this->assertEquals(session_id(), $storage->getId()); + } + + /** + * @expectedException \LogicException + */ + public function testIdException() + { + session_start(); + $this->getStorage()->setId('foo'); + } + + public function testName() + { + $storage = $this->getStorage(); + + $this->assertEquals(session_name(), $storage->getName()); + $storage->setName('foo'); + $this->assertEquals('foo', $storage->getName()); + $this->assertEquals(session_name(), $storage->getName()); + } + + /** + * @expectedException \LogicException + */ + public function testNameException() + { + session_start(); + $this->getStorage()->setName('foo'); + } + public function testRegenerate() { $storage = $this->getStorage(); @@ -185,9 +222,9 @@ public function testCookieOptions() } /** - * @expectedException \InvalidArgumentException + * @expectedException \TypeError */ - public function testSetSaveHandlerException() + public function testSetSaveHandlerError() { $storage = $this->getStorage(); $storage->setSaveHandler(new \stdClass()); @@ -198,17 +235,13 @@ public function testSetSaveHandler() $this->iniSet('session.save_handler', 'files'); $storage = $this->getStorage(); $storage->setSaveHandler(); - $this->assertInstanceOf('Symfony\Component\HttpFoundation\Session\Storage\Proxy\SessionHandlerProxy', $storage->getSaveHandler()); + $this->assertInstanceOf(\SessionHandler::class, $storage->getSaveHandler()); $storage->setSaveHandler(null); - $this->assertInstanceOf('Symfony\Component\HttpFoundation\Session\Storage\Proxy\SessionHandlerProxy', $storage->getSaveHandler()); - $storage->setSaveHandler(new SessionHandlerProxy(new NativeSessionHandler())); - $this->assertInstanceOf('Symfony\Component\HttpFoundation\Session\Storage\Proxy\SessionHandlerProxy', $storage->getSaveHandler()); - $storage->setSaveHandler(new NativeSessionHandler()); - $this->assertInstanceOf('Symfony\Component\HttpFoundation\Session\Storage\Proxy\SessionHandlerProxy', $storage->getSaveHandler()); - $storage->setSaveHandler(new SessionHandlerProxy(new NullSessionHandler())); - $this->assertInstanceOf('Symfony\Component\HttpFoundation\Session\Storage\Proxy\SessionHandlerProxy', $storage->getSaveHandler()); + $this->assertInstanceOf(\SessionHandler::class, $storage->getSaveHandler()); + $storage->setSaveHandler(new \SessionHandler()); + $this->assertInstanceOf(\SessionHandler::class, $storage->getSaveHandler()); $storage->setSaveHandler(new NullSessionHandler()); - $this->assertInstanceOf('Symfony\Component\HttpFoundation\Session\Storage\Proxy\SessionHandlerProxy', $storage->getSaveHandler()); + $this->assertInstanceOf(\SessionHandlerInterface::class, $storage->getSaveHandler()); } /** @@ -218,12 +251,12 @@ public function testStarted() { $storage = $this->getStorage(); - $this->assertFalse($storage->getSaveHandler()->isActive()); + $this->assertNotSame(\PHP_SESSION_ACTIVE, session_status()); $this->assertFalse($storage->isStarted()); session_start(); $this->assertTrue(isset($_SESSION)); - $this->assertTrue($storage->getSaveHandler()->isActive()); + $this->assertSame(\PHP_SESSION_ACTIVE, session_status()); // PHP session might have started, but the storage driver has not, so false is correct here $this->assertFalse($storage->isStarted()); diff --git a/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/PhpBridgeSessionStorageTest.php b/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/PhpBridgeSessionStorageTest.php index b8b98386c3367..945d4dd0f6ea0 100644 --- a/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/PhpBridgeSessionStorageTest.php +++ b/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/PhpBridgeSessionStorageTest.php @@ -64,13 +64,12 @@ public function testPhpSession() { $storage = $this->getStorage(); - $this->assertFalse($storage->getSaveHandler()->isActive()); + $this->assertNotSame(\PHP_SESSION_ACTIVE, session_status()); $this->assertFalse($storage->isStarted()); session_start(); $this->assertTrue(isset($_SESSION)); - // in PHP 5.4 we can reliably detect a session started - $this->assertTrue($storage->getSaveHandler()->isActive()); + $this->assertSame(\PHP_SESSION_ACTIVE, session_status()); // PHP session might have started, but the storage driver has not, so false is correct here $this->assertFalse($storage->isStarted()); diff --git a/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Proxy/AbstractProxyTest.php b/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Proxy/AbstractProxyTest.php deleted file mode 100644 index f2be722c8f522..0000000000000 --- a/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Proxy/AbstractProxyTest.php +++ /dev/null @@ -1,115 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Tests\Session\Storage\Proxy; - -use PHPUnit\Framework\TestCase; -use Symfony\Component\HttpFoundation\Session\Storage\Proxy\AbstractProxy; -use Symfony\Component\HttpFoundation\Session\Storage\Proxy\SessionHandlerProxy; - -/** - * Test class for AbstractProxy. - * - * @group legacy - * - * @author Drak - */ -class AbstractProxyTest extends TestCase -{ - /** - * @var AbstractProxy - */ - protected $proxy; - - protected function setUp() - { - $this->proxy = $this->getMockForAbstractClass(AbstractProxy::class); - } - - protected function tearDown() - { - $this->proxy = null; - } - - public function testGetSaveHandlerName() - { - $this->assertNull($this->proxy->getSaveHandlerName()); - } - - public function testIsSessionHandlerInterface() - { - $this->assertFalse($this->proxy->isSessionHandlerInterface()); - $sh = new SessionHandlerProxy(new \SessionHandler()); - $this->assertTrue($sh->isSessionHandlerInterface()); - } - - public function testIsWrapper() - { - $this->assertFalse($this->proxy->isWrapper()); - } - - /** - * @runInSeparateProcess - * @preserveGlobalState disabled - */ - public function testIsActive() - { - $this->assertFalse($this->proxy->isActive()); - session_start(); - $this->assertTrue($this->proxy->isActive()); - } - - /** - * @runInSeparateProcess - * @preserveGlobalState disabled - */ - public function testName() - { - $this->assertEquals(session_name(), $this->proxy->getName()); - $this->proxy->setName('foo'); - $this->assertEquals('foo', $this->proxy->getName()); - $this->assertEquals(session_name(), $this->proxy->getName()); - } - - /** - * @runInSeparateProcess - * @preserveGlobalState disabled - * @expectedException \LogicException - */ - public function testNameException() - { - session_start(); - $this->proxy->setName('foo'); - } - - /** - * @runInSeparateProcess - * @preserveGlobalState disabled - */ - public function testId() - { - $this->assertEquals(session_id(), $this->proxy->getId()); - $this->proxy->setId('foo'); - $this->assertEquals('foo', $this->proxy->getId()); - $this->assertEquals(session_id(), $this->proxy->getId()); - } - - /** - * @runInSeparateProcess - * @preserveGlobalState disabled - * @expectedException \LogicException - */ - public function testIdException() - { - session_start(); - $this->proxy->setId('foo'); - } -} diff --git a/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Proxy/NativeProxyTest.php b/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Proxy/NativeProxyTest.php deleted file mode 100644 index ed4fee6bfec0f..0000000000000 --- a/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Proxy/NativeProxyTest.php +++ /dev/null @@ -1,38 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Tests\Session\Storage\Proxy; - -use PHPUnit\Framework\TestCase; -use Symfony\Component\HttpFoundation\Session\Storage\Proxy\NativeProxy; - -/** - * Test class for NativeProxy. - * - * @group legacy - * - * @author Drak - */ -class NativeProxyTest extends TestCase -{ - public function testIsWrapper() - { - $proxy = new NativeProxy(); - $this->assertFalse($proxy->isWrapper()); - } - - public function testGetSaveHandlerName() - { - $name = ini_get('session.save_handler'); - $proxy = new NativeProxy(); - $this->assertEquals($name, $proxy->getSaveHandlerName()); - } -} diff --git a/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Proxy/SessionHandlerProxyTest.php b/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Proxy/SessionHandlerProxyTest.php deleted file mode 100644 index fdd1dae254198..0000000000000 --- a/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Proxy/SessionHandlerProxyTest.php +++ /dev/null @@ -1,125 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Tests\Session\Storage\Proxy; - -use PHPUnit\Framework\TestCase; -use Symfony\Component\HttpFoundation\Session\Storage\Proxy\SessionHandlerProxy; - -/** - * Tests for SessionHandlerProxy class. - * - * @author Drak - * - * @runTestsInSeparateProcesses - * @preserveGlobalState disabled - * @group legacy - */ -class SessionHandlerProxyTest extends TestCase -{ - /** - * @var \PHPUnit_Framework_MockObject_Matcher - */ - private $mock; - - /** - * @var SessionHandlerProxy - */ - private $proxy; - - protected function setUp() - { - $this->mock = $this->getMockBuilder('SessionHandlerInterface')->getMock(); - $this->proxy = new SessionHandlerProxy($this->mock); - } - - protected function tearDown() - { - $this->mock = null; - $this->proxy = null; - } - - public function testOpenTrue() - { - $this->mock->expects($this->once()) - ->method('open') - ->will($this->returnValue(true)); - - $this->assertFalse($this->proxy->isActive()); - $this->proxy->open('name', 'id'); - $this->assertFalse($this->proxy->isActive()); - } - - public function testOpenFalse() - { - $this->mock->expects($this->once()) - ->method('open') - ->will($this->returnValue(false)); - - $this->assertFalse($this->proxy->isActive()); - $this->proxy->open('name', 'id'); - $this->assertFalse($this->proxy->isActive()); - } - - public function testClose() - { - $this->mock->expects($this->once()) - ->method('close') - ->will($this->returnValue(true)); - - $this->assertFalse($this->proxy->isActive()); - $this->proxy->close(); - $this->assertFalse($this->proxy->isActive()); - } - - public function testCloseFalse() - { - $this->mock->expects($this->once()) - ->method('close') - ->will($this->returnValue(false)); - - $this->assertFalse($this->proxy->isActive()); - $this->proxy->close(); - $this->assertFalse($this->proxy->isActive()); - } - - public function testRead() - { - $this->mock->expects($this->once()) - ->method('read'); - - $this->proxy->read('id'); - } - - public function testWrite() - { - $this->mock->expects($this->once()) - ->method('write'); - - $this->proxy->write('id', 'data'); - } - - public function testDestroy() - { - $this->mock->expects($this->once()) - ->method('destroy'); - - $this->proxy->destroy('id'); - } - - public function testGc() - { - $this->mock->expects($this->once()) - ->method('gc'); - - $this->proxy->gc(86400); - } -} From aa30d0424326bfe395ba1c87bf494bb22ea75f3a Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Wed, 11 Jan 2017 15:09:04 +0100 Subject: [PATCH 0917/1099] [Serializer] throw more specific exceptions --- .../Serializer/Encoder/JsonDecode.php | 6 +++--- .../Serializer/Encoder/JsonEncode.php | 4 ++-- .../Serializer/Encoder/XmlEncoder.php | 14 +++++++------- .../Exception/NotEncodableValueException.php | 19 +++++++++++++++++++ .../NotNormalizableValueException.php | 19 +++++++++++++++++++ .../Normalizer/AbstractObjectNormalizer.php | 8 ++++---- .../Normalizer/ArrayDenormalizer.php | 6 ++++-- .../Normalizer/DataUriNormalizer.php | 9 ++++++--- .../Normalizer/DateTimeNormalizer.php | 8 ++++---- .../Component/Serializer/Serializer.php | 15 +++++++++------ 10 files changed, 77 insertions(+), 31 deletions(-) create mode 100644 src/Symfony/Component/Serializer/Exception/NotEncodableValueException.php create mode 100644 src/Symfony/Component/Serializer/Exception/NotNormalizableValueException.php diff --git a/src/Symfony/Component/Serializer/Encoder/JsonDecode.php b/src/Symfony/Component/Serializer/Encoder/JsonDecode.php index e9ca7ce570e59..079f066cf5cb3 100644 --- a/src/Symfony/Component/Serializer/Encoder/JsonDecode.php +++ b/src/Symfony/Component/Serializer/Encoder/JsonDecode.php @@ -11,7 +11,7 @@ namespace Symfony\Component\Serializer\Encoder; -use Symfony\Component\Serializer\Exception\UnexpectedValueException; +use Symfony\Component\Serializer\Exception\NotEncodableValueException; /** * Decodes JSON data. @@ -73,7 +73,7 @@ public function __construct($associative = false, $depth = 512) * * @return mixed * - * @throws UnexpectedValueException + * @throws NotEncodableValueException * * @see http://php.net/json_decode json_decode */ @@ -88,7 +88,7 @@ public function decode($data, $format, array $context = array()) $decodedData = json_decode($data, $associative, $recursionDepth, $options); if (JSON_ERROR_NONE !== $this->lastError = json_last_error()) { - throw new UnexpectedValueException(json_last_error_msg()); + throw new NotEncodableValueException(json_last_error_msg()); } return $decodedData; diff --git a/src/Symfony/Component/Serializer/Encoder/JsonEncode.php b/src/Symfony/Component/Serializer/Encoder/JsonEncode.php index 14cd2c949a991..5ed9ae7a255b7 100644 --- a/src/Symfony/Component/Serializer/Encoder/JsonEncode.php +++ b/src/Symfony/Component/Serializer/Encoder/JsonEncode.php @@ -11,7 +11,7 @@ namespace Symfony\Component\Serializer\Encoder; -use Symfony\Component\Serializer\Exception\UnexpectedValueException; +use Symfony\Component\Serializer\Exception\NotEncodableValueException; /** * Encodes JSON data. @@ -40,7 +40,7 @@ public function encode($data, $format, array $context = array()) $encodedJson = json_encode($data, $context['json_encode_options']); if (JSON_ERROR_NONE !== $this->lastError = json_last_error()) { - throw new UnexpectedValueException(json_last_error_msg()); + throw new NotEncodableValueException(json_last_error_msg()); } return $encodedJson; diff --git a/src/Symfony/Component/Serializer/Encoder/XmlEncoder.php b/src/Symfony/Component/Serializer/Encoder/XmlEncoder.php index d2ca3ee9bdb7a..9a7aa31596906 100644 --- a/src/Symfony/Component/Serializer/Encoder/XmlEncoder.php +++ b/src/Symfony/Component/Serializer/Encoder/XmlEncoder.php @@ -11,7 +11,7 @@ namespace Symfony\Component\Serializer\Encoder; -use Symfony\Component\Serializer\Exception\UnexpectedValueException; +use Symfony\Component\Serializer\Exception\NotEncodableValueException; /** * Encodes XML data. @@ -78,7 +78,7 @@ public function encode($data, $format, array $context = array()) public function decode($data, $format, array $context = array()) { if ('' === trim($data)) { - throw new UnexpectedValueException('Invalid XML data, it can not be empty.'); + throw new NotEncodableValueException('Invalid XML data, it can not be empty.'); } $internalErrors = libxml_use_internal_errors(true); @@ -94,13 +94,13 @@ public function decode($data, $format, array $context = array()) if ($error = libxml_get_last_error()) { libxml_clear_errors(); - throw new UnexpectedValueException($error->message); + throw new NotEncodableValueException($error->message); } $rootNode = null; foreach ($dom->childNodes as $child) { if (XML_DOCUMENT_TYPE_NODE === $child->nodeType) { - throw new UnexpectedValueException('Document types are not allowed.'); + throw new NotEncodableValueException('Document types are not allowed.'); } if (!$rootNode && XML_PI_NODE !== $child->nodeType) { $rootNode = $child; @@ -380,7 +380,7 @@ private function parseXmlValue(\DOMNode $node, array $context = array()) * * @return bool * - * @throws UnexpectedValueException + * @throws NotEncodableValueException */ private function buildXml(\DOMNode $parentNode, $data, $xmlRootNodeName = null) { @@ -437,7 +437,7 @@ private function buildXml(\DOMNode $parentNode, $data, $xmlRootNodeName = null) return $this->appendNode($parentNode, $data, 'data'); } - throw new UnexpectedValueException(sprintf('An unexpected value could not be serialized: %s', var_export($data, true))); + throw new NotEncodableValueException(sprintf('An unexpected value could not be serialized: %s', var_export($data, true))); } /** @@ -485,7 +485,7 @@ private function needsCdataWrapping($val) * * @return bool * - * @throws UnexpectedValueException + * @throws NotEncodableValueException */ private function selectNodeType(\DOMNode $node, $val) { diff --git a/src/Symfony/Component/Serializer/Exception/NotEncodableValueException.php b/src/Symfony/Component/Serializer/Exception/NotEncodableValueException.php new file mode 100644 index 0000000000000..e1709fb1ef221 --- /dev/null +++ b/src/Symfony/Component/Serializer/Exception/NotEncodableValueException.php @@ -0,0 +1,19 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Serializer\Exception; + +/** + * @author Christian Flothmann + */ +class NotEncodableValueException extends UnexpectedValueException +{ +} diff --git a/src/Symfony/Component/Serializer/Exception/NotNormalizableValueException.php b/src/Symfony/Component/Serializer/Exception/NotNormalizableValueException.php new file mode 100644 index 0000000000000..58adf72cab147 --- /dev/null +++ b/src/Symfony/Component/Serializer/Exception/NotNormalizableValueException.php @@ -0,0 +1,19 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Serializer\Exception; + +/** + * @author Christian Flothmann + */ +class NotNormalizableValueException extends UnexpectedValueException +{ +} diff --git a/src/Symfony/Component/Serializer/Normalizer/AbstractObjectNormalizer.php b/src/Symfony/Component/Serializer/Normalizer/AbstractObjectNormalizer.php index 93e85c6fe67de..93e5f9bc5e126 100644 --- a/src/Symfony/Component/Serializer/Normalizer/AbstractObjectNormalizer.php +++ b/src/Symfony/Component/Serializer/Normalizer/AbstractObjectNormalizer.php @@ -15,7 +15,7 @@ use Symfony\Component\Serializer\Encoder\JsonEncoder; use Symfony\Component\Serializer\Exception\ExtraAttributesException; use Symfony\Component\Serializer\Exception\LogicException; -use Symfony\Component\Serializer\Exception\UnexpectedValueException; +use Symfony\Component\Serializer\Exception\NotNormalizableValueException; use Symfony\Component\PropertyInfo\PropertyTypeExtractorInterface; use Symfony\Component\PropertyInfo\Type; use Symfony\Component\Serializer\Mapping\AttributeMetadataInterface; @@ -200,7 +200,7 @@ public function denormalize($data, $class, $format = null, array $context = arra try { $this->setAttributeValue($object, $attribute, $value, $format, $context); } catch (InvalidArgumentException $e) { - throw new UnexpectedValueException($e->getMessage(), $e->getCode(), $e); + throw new NotNormalizableValueException($e->getMessage(), $e->getCode(), $e); } } @@ -233,7 +233,7 @@ abstract protected function setAttributeValue($object, $attribute, $value, $form * * @return mixed * - * @throws UnexpectedValueException + * @throws NotNormalizableValueException * @throws LogicException */ private function validateAndDenormalize($currentClass, $attribute, $data, $format, array $context) @@ -292,7 +292,7 @@ private function validateAndDenormalize($currentClass, $attribute, $data, $forma return $data; } - throw new UnexpectedValueException(sprintf('The type of the "%s" attribute for class "%s" must be one of "%s" ("%s" given).', $attribute, $currentClass, implode('", "', array_keys($expectedTypes)), gettype($data))); + throw new NotNormalizableValueException(sprintf('The type of the "%s" attribute for class "%s" must be one of "%s" ("%s" given).', $attribute, $currentClass, implode('", "', array_keys($expectedTypes)), gettype($data))); } /** diff --git a/src/Symfony/Component/Serializer/Normalizer/ArrayDenormalizer.php b/src/Symfony/Component/Serializer/Normalizer/ArrayDenormalizer.php index 14b23d01a073f..60ba68be25146 100644 --- a/src/Symfony/Component/Serializer/Normalizer/ArrayDenormalizer.php +++ b/src/Symfony/Component/Serializer/Normalizer/ArrayDenormalizer.php @@ -13,7 +13,7 @@ use Symfony\Component\Serializer\Exception\BadMethodCallException; use Symfony\Component\Serializer\Exception\InvalidArgumentException; -use Symfony\Component\Serializer\Exception\UnexpectedValueException; +use Symfony\Component\Serializer\Exception\NotNormalizableValueException; use Symfony\Component\Serializer\SerializerAwareInterface; use Symfony\Component\Serializer\SerializerInterface; @@ -33,6 +33,8 @@ class ArrayDenormalizer implements DenormalizerInterface, SerializerAwareInterfa /** * {@inheritdoc} + * + * @throws NotNormalizableValueException */ public function denormalize($data, $class, $format = null, array $context = array()) { @@ -52,7 +54,7 @@ public function denormalize($data, $class, $format = null, array $context = arra $builtinType = isset($context['key_type']) ? $context['key_type']->getBuiltinType() : null; foreach ($data as $key => $value) { if (null !== $builtinType && !call_user_func('is_'.$builtinType, $key)) { - throw new UnexpectedValueException(sprintf('The type of the key "%s" must be "%s" ("%s" given).', $key, $builtinType, gettype($key))); + throw new NotNormalizableValueException(sprintf('The type of the key "%s" must be "%s" ("%s" given).', $key, $builtinType, gettype($key))); } $data[$key] = $serializer->denormalize($value, $class, $format, $context); diff --git a/src/Symfony/Component/Serializer/Normalizer/DataUriNormalizer.php b/src/Symfony/Component/Serializer/Normalizer/DataUriNormalizer.php index 66a9ed6bd8d55..995bdf1441776 100644 --- a/src/Symfony/Component/Serializer/Normalizer/DataUriNormalizer.php +++ b/src/Symfony/Component/Serializer/Normalizer/DataUriNormalizer.php @@ -15,7 +15,7 @@ use Symfony\Component\HttpFoundation\File\MimeType\MimeTypeGuesser; use Symfony\Component\HttpFoundation\File\MimeType\MimeTypeGuesserInterface; use Symfony\Component\Serializer\Exception\InvalidArgumentException; -use Symfony\Component\Serializer\Exception\UnexpectedValueException; +use Symfony\Component\Serializer\Exception\NotNormalizableValueException; /** * Normalizes an {@see \SplFileInfo} object to a data URI. @@ -85,11 +85,14 @@ public function supportsNormalization($data, $format = null) * Regex adapted from Brian Grinstead code. * * @see https://gist.github.com/bgrins/6194623 + * + * @throws InvalidArgumentException + * @throws NotNormalizableValueException */ public function denormalize($data, $class, $format = null, array $context = array()) { if (!preg_match('/^data:([a-z0-9][a-z0-9\!\#\$\&\-\^\_\+\.]{0,126}\/[a-z0-9][a-z0-9\!\#\$\&\-\^\_\+\.]{0,126}(;[a-z0-9\-]+\=[a-z0-9\-]+)?)?(;base64)?,[a-z0-9\!\$\&\\\'\,\(\)\*\+\,\;\=\-\.\_\~\:\@\/\?\%\s]*\s*$/i', $data)) { - throw new UnexpectedValueException('The provided "data:" URI is not valid.'); + throw new NotNormalizableValueException('The provided "data:" URI is not valid.'); } try { @@ -102,7 +105,7 @@ public function denormalize($data, $class, $format = null, array $context = arra return new \SplFileObject($data); } } catch (\RuntimeException $exception) { - throw new UnexpectedValueException($exception->getMessage(), $exception->getCode(), $exception); + throw new NotNormalizableValueException($exception->getMessage(), $exception->getCode(), $exception); } throw new InvalidArgumentException(sprintf('The class parameter "%s" is not supported. It must be one of "SplFileInfo", "SplFileObject" or "Symfony\Component\HttpFoundation\File\File".', $class)); diff --git a/src/Symfony/Component/Serializer/Normalizer/DateTimeNormalizer.php b/src/Symfony/Component/Serializer/Normalizer/DateTimeNormalizer.php index 26fd9c6201afd..fcc593b96a93f 100644 --- a/src/Symfony/Component/Serializer/Normalizer/DateTimeNormalizer.php +++ b/src/Symfony/Component/Serializer/Normalizer/DateTimeNormalizer.php @@ -12,7 +12,7 @@ namespace Symfony\Component\Serializer\Normalizer; use Symfony\Component\Serializer\Exception\InvalidArgumentException; -use Symfony\Component\Serializer\Exception\UnexpectedValueException; +use Symfony\Component\Serializer\Exception\NotNormalizableValueException; /** * Normalizes an object implementing the {@see \DateTimeInterface} to a date string. @@ -79,7 +79,7 @@ public function supportsNormalization($data, $format = null) /** * {@inheritdoc} * - * @throws UnexpectedValueException + * @throws NotNormalizableValueException */ public function denormalize($data, $class, $format = null, array $context = array()) { @@ -100,7 +100,7 @@ public function denormalize($data, $class, $format = null, array $context = arra $dateTimeErrors = \DateTime::class === $class ? \DateTime::getLastErrors() : \DateTimeImmutable::getLastErrors(); - throw new UnexpectedValueException(sprintf( + throw new NotNormalizableValueException(sprintf( 'Parsing datetime string "%s" using format "%s" resulted in %d errors:'."\n".'%s', $data, $dateTimeFormat, @@ -112,7 +112,7 @@ public function denormalize($data, $class, $format = null, array $context = arra try { return \DateTime::class === $class ? new \DateTime($data, $timezone) : new \DateTimeImmutable($data, $timezone); } catch (\Exception $e) { - throw new UnexpectedValueException($e->getMessage(), $e->getCode(), $e); + throw new NotNormalizableValueException($e->getMessage(), $e->getCode(), $e); } } diff --git a/src/Symfony/Component/Serializer/Serializer.php b/src/Symfony/Component/Serializer/Serializer.php index 4c5cec1653ced..9bcd44b4330ea 100644 --- a/src/Symfony/Component/Serializer/Serializer.php +++ b/src/Symfony/Component/Serializer/Serializer.php @@ -15,12 +15,13 @@ use Symfony\Component\Serializer\Encoder\ChainEncoder; use Symfony\Component\Serializer\Encoder\EncoderInterface; use Symfony\Component\Serializer\Encoder\DecoderInterface; +use Symfony\Component\Serializer\Exception\NotEncodableValueException; +use Symfony\Component\Serializer\Exception\NotNormalizableValueException; use Symfony\Component\Serializer\Normalizer\DenormalizerAwareInterface; use Symfony\Component\Serializer\Normalizer\NormalizerAwareInterface; use Symfony\Component\Serializer\Normalizer\NormalizerInterface; use Symfony\Component\Serializer\Normalizer\DenormalizerInterface; use Symfony\Component\Serializer\Exception\LogicException; -use Symfony\Component\Serializer\Exception\UnexpectedValueException; /** * Serializer serializes and deserializes data. @@ -108,7 +109,7 @@ public function __construct(array $normalizers = array(), array $encoders = arra final public function serialize($data, $format, array $context = array()) { if (!$this->supportsEncoding($format)) { - throw new UnexpectedValueException(sprintf('Serialization for the format %s is not supported', $format)); + throw new NotEncodableValueException(sprintf('Serialization for the format %s is not supported', $format)); } if ($this->encoder->needsNormalization($format)) { @@ -124,7 +125,7 @@ final public function serialize($data, $format, array $context = array()) final public function deserialize($data, $type, $format, array $context = array()) { if (!$this->supportsDecoding($format)) { - throw new UnexpectedValueException(sprintf('Deserialization for the format %s is not supported', $format)); + throw new NotEncodableValueException(sprintf('Deserialization for the format %s is not supported', $format)); } $data = $this->decode($data, $format, $context); @@ -160,14 +161,16 @@ public function normalize($data, $format = null, array $context = array()) throw new LogicException('You must register at least one normalizer to be able to normalize objects.'); } - throw new UnexpectedValueException(sprintf('Could not normalize object of type %s, no supporting normalizer found.', get_class($data))); + throw new NotNormalizableValueException(sprintf('Could not normalize object of type %s, no supporting normalizer found.', get_class($data))); } - throw new UnexpectedValueException(sprintf('An unexpected value could not be normalized: %s', var_export($data, true))); + throw new NotNormalizableValueException(sprintf('An unexpected value could not be normalized: %s', var_export($data, true))); } /** * {@inheritdoc} + * + * @throws NotNormalizableValueException */ public function denormalize($data, $type, $format = null, array $context = array()) { @@ -179,7 +182,7 @@ public function denormalize($data, $type, $format = null, array $context = array return $normalizer->denormalize($data, $type, $format, $context); } - throw new UnexpectedValueException(sprintf('Could not denormalize object of type %s, no supporting normalizer found.', $type)); + throw new NotNormalizableValueException(sprintf('Could not denormalize object of type %s, no supporting normalizer found.', $type)); } /** From 7c4aa0bccb468fd1de0743469c4b866208edd452 Mon Sep 17 00:00:00 2001 From: Zan Baldwin Date: Tue, 26 Sep 2017 14:54:54 +0100 Subject: [PATCH 0918/1099] Saltless Encoder Interface A new interface for all encoders that do not require a user-generated salt. --- .../Command/UserPasswordEncoderCommand.php | 10 ++++----- .../UserPasswordEncoderCommandTest.php | 12 +++++----- .../Core/Encoder/BCryptPasswordEncoder.php | 2 +- .../Encoder/SelfSaltingEncoderInterface.php | 22 +++++++++++++++++++ 4 files changed, 33 insertions(+), 13 deletions(-) create mode 100644 src/Symfony/Component/Security/Core/Encoder/SelfSaltingEncoderInterface.php diff --git a/src/Symfony/Bundle/SecurityBundle/Command/UserPasswordEncoderCommand.php b/src/Symfony/Bundle/SecurityBundle/Command/UserPasswordEncoderCommand.php index c93cb4987f481..0df89403a82a0 100644 --- a/src/Symfony/Bundle/SecurityBundle/Command/UserPasswordEncoderCommand.php +++ b/src/Symfony/Bundle/SecurityBundle/Command/UserPasswordEncoderCommand.php @@ -19,8 +19,8 @@ use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Question\Question; use Symfony\Component\Console\Style\SymfonyStyle; -use Symfony\Component\Security\Core\Encoder\BCryptPasswordEncoder; use Symfony\Component\Security\Core\Encoder\EncoderFactoryInterface; +use Symfony\Component\Security\Core\Encoder\SelfSaltingEncoderInterface; use Symfony\Component\Security\Core\User\User; /** @@ -117,9 +117,9 @@ protected function execute(InputInterface $input, OutputInterface $output) $encoderFactory = $this->encoderFactory ?: $this->getContainer()->get('security.encoder_factory'); $encoder = $encoderFactory->getEncoder($userClass); - $bcryptWithoutEmptySalt = !$emptySalt && $encoder instanceof BCryptPasswordEncoder; + $saltlessWithoutEmptySalt = !$emptySalt && $encoder instanceof SelfSaltingEncoderInterface; - if ($bcryptWithoutEmptySalt) { + if ($saltlessWithoutEmptySalt) { $emptySalt = true; } @@ -161,8 +161,8 @@ protected function execute(InputInterface $input, OutputInterface $output) if (!$emptySalt) { $errorIo->note(sprintf('Make sure that your salt storage field fits the salt length: %s chars', strlen($salt))); - } elseif ($bcryptWithoutEmptySalt) { - $errorIo->note('Bcrypt encoder used: the encoder generated its own built-in salt.'); + } elseif ($saltlessWithoutEmptySalt) { + $errorIo->note('Self-salting encoder used: the encoder generated its own built-in salt.'); } $errorIo->success('Password encoding succeeded'); diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/UserPasswordEncoderCommandTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/UserPasswordEncoderCommandTest.php index 0710f94b5b094..afd3da09ce0d2 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/UserPasswordEncoderCommandTest.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/UserPasswordEncoderCommandTest.php @@ -120,13 +120,11 @@ public function testEncodePasswordEmptySaltOutput() public function testEncodePasswordBcryptOutput() { - $this->passwordEncoderCommandTester->execute( - array( - 'command' => 'security:encode-password', - 'password' => 'p@ssw0rd', - 'user-class' => 'Custom\Class\Bcrypt\User', - ) - ); + $this->passwordEncoderCommandTester->execute(array( + 'command' => 'security:encode-password', + 'password' => 'p@ssw0rd', + 'user-class' => 'Custom\Class\Bcrypt\User', + ), array('interactive' => false)); $this->assertNotContains(' Generated salt ', $this->passwordEncoderCommandTester->getDisplay()); } diff --git a/src/Symfony/Component/Security/Core/Encoder/BCryptPasswordEncoder.php b/src/Symfony/Component/Security/Core/Encoder/BCryptPasswordEncoder.php index 8278ef34fa625..8c09660a35315 100644 --- a/src/Symfony/Component/Security/Core/Encoder/BCryptPasswordEncoder.php +++ b/src/Symfony/Component/Security/Core/Encoder/BCryptPasswordEncoder.php @@ -17,7 +17,7 @@ * @author Elnur Abdurrakhimov * @author Terje Bråten */ -class BCryptPasswordEncoder extends BasePasswordEncoder +class BCryptPasswordEncoder extends BasePasswordEncoder implements SelfSaltingEncoderInterface { const MAX_PASSWORD_LENGTH = 72; diff --git a/src/Symfony/Component/Security/Core/Encoder/SelfSaltingEncoderInterface.php b/src/Symfony/Component/Security/Core/Encoder/SelfSaltingEncoderInterface.php new file mode 100644 index 0000000000000..37855b60cff83 --- /dev/null +++ b/src/Symfony/Component/Security/Core/Encoder/SelfSaltingEncoderInterface.php @@ -0,0 +1,22 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Security\Core\Encoder; + +/** + * SelfSaltingEncoderInterface is a marker interface for encoders that do not + * require a user-generated salt. + * + * @author Zan Baldwin + */ +interface SelfSaltingEncoderInterface +{ +} From d173494e487ac07bb2dcbdc70eeb0ce288461ef9 Mon Sep 17 00:00:00 2001 From: Oliver Hoff Date: Tue, 19 Sep 2017 11:55:20 +0200 Subject: [PATCH 0919/1099] CsvEncoder handling variable structures and custom header order --- src/Symfony/Component/Serializer/CHANGELOG.md | 2 + .../Serializer/Encoder/CsvEncoder.php | 72 +++++++++++++++---- .../Tests/Encoder/CsvEncoderTest.php | 40 +++++++++-- 3 files changed, 96 insertions(+), 18 deletions(-) diff --git a/src/Symfony/Component/Serializer/CHANGELOG.md b/src/Symfony/Component/Serializer/CHANGELOG.md index ef59f22499264..9a6e20d52f96d 100644 --- a/src/Symfony/Component/Serializer/CHANGELOG.md +++ b/src/Symfony/Component/Serializer/CHANGELOG.md @@ -7,6 +7,8 @@ CHANGELOG * added `AbstractObjectNormalizer::DISABLE_TYPE_ENFORCEMENT` context option to disable throwing an `UnexpectedValueException` on a type mismatch * added support for serializing `DateInterval` objects + * improved `CsvEncoder` to handle variable nested structures + * CSV headers can be passed to the `CsvEncoder` via the `csv_headers` serialization context variable 3.3.0 ----- diff --git a/src/Symfony/Component/Serializer/Encoder/CsvEncoder.php b/src/Symfony/Component/Serializer/Encoder/CsvEncoder.php index cdbe0eb44e659..b4e501d7efab7 100644 --- a/src/Symfony/Component/Serializer/Encoder/CsvEncoder.php +++ b/src/Symfony/Component/Serializer/Encoder/CsvEncoder.php @@ -17,6 +17,7 @@ * Encodes CSV data. * * @author Kévin Dunglas + * @author Oliver Hoff */ class CsvEncoder implements EncoderInterface, DecoderInterface { @@ -25,6 +26,7 @@ class CsvEncoder implements EncoderInterface, DecoderInterface const ENCLOSURE_KEY = 'csv_enclosure'; const ESCAPE_CHAR_KEY = 'csv_escape_char'; const KEY_SEPARATOR_KEY = 'csv_key_separator'; + const HEADERS_KEY = 'csv_headers'; private $delimiter; private $enclosure; @@ -69,21 +71,22 @@ public function encode($data, $format, array $context = array()) } } - list($delimiter, $enclosure, $escapeChar, $keySeparator) = $this->getCsvOptions($context); + list($delimiter, $enclosure, $escapeChar, $keySeparator, $headers) = $this->getCsvOptions($context); - $headers = null; - foreach ($data as $value) { - $result = array(); - $this->flatten($value, $result, $keySeparator); + foreach ($data as &$value) { + $flattened = array(); + $this->flatten($value, $flattened, $keySeparator); + $value = $flattened; + } + unset($value); - if (null === $headers) { - $headers = array_keys($result); - fputcsv($handle, $headers, $delimiter, $enclosure, $escapeChar); - } elseif (array_keys($result) !== $headers) { - throw new InvalidArgumentException('To use the CSV encoder, each line in the data array must have the same structure. You may want to use a custom normalizer class to normalize the data format before passing it to the CSV encoder.'); - } + $headers = array_merge(array_values($headers), array_diff($this->extractHeaders($data), $headers)); + + fputcsv($handle, $headers, $delimiter, $enclosure, $escapeChar); - fputcsv($handle, $result, $delimiter, $enclosure, $escapeChar); + $headers = array_fill_keys($headers, ''); + foreach ($data as $row) { + fputcsv($handle, array_replace($headers, $row), $delimiter, $enclosure, $escapeChar); } rewind($handle); @@ -194,7 +197,50 @@ private function getCsvOptions(array $context) $enclosure = isset($context[self::ENCLOSURE_KEY]) ? $context[self::ENCLOSURE_KEY] : $this->enclosure; $escapeChar = isset($context[self::ESCAPE_CHAR_KEY]) ? $context[self::ESCAPE_CHAR_KEY] : $this->escapeChar; $keySeparator = isset($context[self::KEY_SEPARATOR_KEY]) ? $context[self::KEY_SEPARATOR_KEY] : $this->keySeparator; + $headers = isset($context[self::HEADERS_KEY]) ? $context[self::HEADERS_KEY] : array(); + + if (!is_array($headers)) { + throw new InvalidArgumentException(sprintf('The "%s" context variable must be an array or null, given "%s".', self::HEADERS_KEY, gettype($headers))); + } + + return array($delimiter, $enclosure, $escapeChar, $keySeparator, $headers); + } + + /** + * @param array $data + * + * @return string[] + */ + private function extractHeaders(array $data) + { + $headers = array(); + $flippedHeaders = array(); + + foreach ($data as $row) { + $previousHeader = null; + + foreach ($row as $header => $_) { + if (isset($flippedHeaders[$header])) { + $previousHeader = $header; + continue; + } + + if (null === $previousHeader) { + $n = count($headers); + } else { + $n = $flippedHeaders[$previousHeader] + 1; + + for ($j = count($headers); $j > $n; --$j) { + ++$flippedHeaders[$headers[$j] = $headers[$j - 1]]; + } + } + + $headers[$n] = $header; + $flippedHeaders[$header] = $n; + $previousHeader = $header; + } + } - return array($delimiter, $enclosure, $escapeChar, $keySeparator); + return $headers; } } diff --git a/src/Symfony/Component/Serializer/Tests/Encoder/CsvEncoderTest.php b/src/Symfony/Component/Serializer/Tests/Encoder/CsvEncoderTest.php index 61cbc03ee6d26..a5e5c256f34ad 100644 --- a/src/Symfony/Component/Serializer/Tests/Encoder/CsvEncoderTest.php +++ b/src/Symfony/Component/Serializer/Tests/Encoder/CsvEncoderTest.php @@ -135,12 +135,42 @@ public function testEncodeEmptyArray() $this->assertEquals("\n\n", $this->encoder->encode(array(array()), 'csv')); } - /** - * @expectedException \Symfony\Component\Serializer\Exception\InvalidArgumentException - */ - public function testEncodeNonFlattenableStructure() + public function testEncodeVariableStructure() + { + $value = array( + array('a' => array('foo', 'bar')), + array('a' => array(), 'b' => 'baz'), + array('a' => array('bar', 'foo'), 'c' => 'pong'), + ); + $csv = <<assertEquals($csv, $this->encoder->encode($value, 'csv')); + } + + public function testEncodeCustomHeaders() { - $this->encoder->encode(array(array('a' => array('foo', 'bar')), array('a' => array())), 'csv'); + $context = array( + CsvEncoder::HEADERS_KEY => array( + 'b', + 'c', + ), + ); + $value = array( + array('a' => 'foo', 'b' => 'bar'), + ); + $csv = <<assertEquals($csv, $this->encoder->encode($value, 'csv', $context)); } public function testSupportsDecoding() From 860575a88240a1eca46fc9a660212816827d32df Mon Sep 17 00:00:00 2001 From: Roland Franssen Date: Sat, 16 Sep 2017 21:37:07 +0200 Subject: [PATCH 0920/1099] [WebProfilerBundle] Render file links for twig templates --- .../Twig/DataCollector/TwigDataCollector.php | 21 ++++++++++++++++++- .../TwigBundle/Resources/config/twig.xml | 1 + .../Resources/views/Collector/twig.html.twig | 4 +++- .../Resources/views/Profiler/open.css.twig | 4 ++++ 4 files changed, 28 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Bridge/Twig/DataCollector/TwigDataCollector.php b/src/Symfony/Bridge/Twig/DataCollector/TwigDataCollector.php index f28c92422ae48..d5efaa805362c 100644 --- a/src/Symfony/Bridge/Twig/DataCollector/TwigDataCollector.php +++ b/src/Symfony/Bridge/Twig/DataCollector/TwigDataCollector.php @@ -15,6 +15,7 @@ use Symfony\Component\HttpKernel\DataCollector\LateDataCollectorInterface; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; +use Twig\Environment; use Twig\Markup; use Twig\Profiler\Dumper\HtmlDumper; use Twig\Profiler\Profile; @@ -27,11 +28,13 @@ class TwigDataCollector extends DataCollector implements LateDataCollectorInterface { private $profile; + private $twig; private $computed; - public function __construct(Profile $profile) + public function __construct(Profile $profile, Environment $twig) { $this->profile = $profile; + $this->twig = $twig; } /** @@ -47,6 +50,17 @@ public function collect(Request $request, Response $response, \Exception $except public function lateCollect() { $this->data['profile'] = serialize($this->profile); + $this->data['template_paths'] = array(); + + $templateFinder = function (Profile $profile) use (&$templateFinder) { + if ($profile->isTemplate() && $template = $this->twig->load($profile->getName())->getSourceContext()->getPath()) { + $this->data['template_paths'][$profile->getName()] = $template; + } + foreach ($profile as $p) { + $templateFinder($p); + } + }; + $templateFinder($this->profile); } public function getTime() @@ -59,6 +73,11 @@ public function getTemplateCount() return $this->getComputedData('template_count'); } + public function getTemplatePaths() + { + return $this->data['template_paths']; + } + public function getTemplates() { return $this->getComputedData('templates'); diff --git a/src/Symfony/Bundle/TwigBundle/Resources/config/twig.xml b/src/Symfony/Bundle/TwigBundle/Resources/config/twig.xml index 8c6a944603333..ff564b412148a 100644 --- a/src/Symfony/Bundle/TwigBundle/Resources/config/twig.xml +++ b/src/Symfony/Bundle/TwigBundle/Resources/config/twig.xml @@ -68,6 +68,7 @@ + diff --git a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/twig.html.twig b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/twig.html.twig index c3c8a5d5f6764..dbf3825ee60f6 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/twig.html.twig +++ b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/twig.html.twig @@ -85,7 +85,9 @@ {% for template, count in collector.templates %} - {{ template }} + {%- set file = collector.templatePaths[template]|default(false) -%} + {%- set link = file ? file|file_link(1) : false -%} + {% if link %}{{ template }}{% else %}{{ template }}{% endif %} {{ count }} {% endfor %} diff --git a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/open.css.twig b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/open.css.twig index 7a0941c955a6d..d0f5cda02dccc 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/open.css.twig +++ b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/open.css.twig @@ -58,6 +58,10 @@ a.doc:hover { margin-top: 41px; } +.source li code { + color: #555; +} + .source li.selected { background: rgba(255, 255, 153, 0.5); } From b4b00c9c6f7fb10e02eaa6faf34291261c5e5e59 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9my=20Deruss=C3=A9?= Date: Sun, 29 Jan 2017 20:47:50 +0100 Subject: [PATCH 0921/1099] [Lock] Include lock component in framework bundle --- .../DependencyInjection/Configuration.php | 46 +++++++ .../FrameworkExtension.php | 88 ++++++++++++ .../FrameworkBundle/Resources/config/lock.xml | 38 ++++++ .../Resources/config/schema/symfony-1.0.xsd | 16 +++ .../DependencyInjection/ConfigurationTest.php | 9 ++ .../DependencyInjection/Fixtures/xml/lock.xml | 11 ++ .../Fixtures/xml/lock_named.xml | 22 +++ .../DependencyInjection/Fixtures/yml/lock.yml | 2 + .../Fixtures/yml/lock_named.yml | 9 ++ .../Bundle/FrameworkBundle/composer.json | 1 + .../Console/Command/LockableTrait.php | 2 +- .../Tests/Command/LockableTraitTest.php | 2 +- .../Component/Lock/Store/FlockStore.php | 7 +- .../Component/Lock/Store/MemcachedStore.php | 128 ++++++++++++++++++ .../Component/Lock/Store/RedisStore.php | 90 ++++++++++++ .../Component/Lock/Store/StoreFactory.php | 54 ++++++++ .../Lock/Tests/Store/FlockStoreTest.php | 2 +- .../Lock/Tests/Store/MemcachedStoreTest.php | 96 +++++++++++++ 18 files changed, 618 insertions(+), 5 deletions(-) create mode 100644 src/Symfony/Bundle/FrameworkBundle/Resources/config/lock.xml create mode 100644 src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/lock.xml create mode 100644 src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/lock_named.xml create mode 100644 src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/lock.yml create mode 100644 src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/lock_named.yml create mode 100644 src/Symfony/Component/Lock/Store/StoreFactory.php diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php index fab5ac344600e..bc7026bd61275 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php @@ -18,6 +18,8 @@ use Symfony\Component\Config\Definition\Builder\TreeBuilder; use Symfony\Component\Config\Definition\ConfigurationInterface; use Symfony\Component\Form\Form; +use Symfony\Component\Lock\Lock; +use Symfony\Component\Lock\Store\SemaphoreStore; use Symfony\Component\Serializer\Serializer; use Symfony\Component\Translation\Translator; use Symfony\Component\Validator\Validation; @@ -129,6 +131,7 @@ public function getConfigTreeBuilder() $this->addCacheSection($rootNode); $this->addPhpErrorsSection($rootNode); $this->addWebLinkSection($rootNode); + $this->addLockSection($rootNode); return $treeBuilder; } @@ -875,6 +878,49 @@ private function addPhpErrorsSection(ArrayNodeDefinition $rootNode) ; } + private function addLockSection(ArrayNodeDefinition $rootNode) + { + $rootNode + ->children() + ->arrayNode('lock') + ->info('Lock configuration') + ->{!class_exists(FullStack::class) && class_exists(Lock::class) ? 'canBeDisabled' : 'canBeEnabled'}() + ->beforeNormalization() + ->ifString()->then(function ($v) { return array('enabled' => true, 'resources' => $v); }) + ->end() + ->beforeNormalization() + ->ifTrue(function ($v) { return is_array($v) && !isset($v['resources']); }) + ->then(function ($v) { + $e = $v['enabled']; + unset($v['enabled']); + + return array('enabled' => $e, 'resources' => $v); + }) + ->end() + ->addDefaultsIfNotSet() + ->fixXmlConfig('resource') + ->children() + ->arrayNode('resources') + ->requiresAtLeastOneElement() + ->defaultValue(array('default' => array(class_exists(SemaphoreStore::class) && SemaphoreStore::isSupported() ? 'semaphore' : 'flock'))) + ->beforeNormalization() + ->ifString()->then(function ($v) { return array('default' => $v); }) + ->end() + ->beforeNormalization() + ->ifTrue(function ($v) { return is_array($v) && array_keys($v) === range(0, count($v) - 1); }) + ->then(function ($v) { return array('default' => $v); }) + ->end() + ->prototype('array') + ->beforeNormalization()->ifString()->then(function ($v) { return array($v); })->end() + ->prototype('scalar')->end() + ->end() + ->end() + ->end() + ->end() + ->end() + ; + } + private function addWebLinkSection(ArrayNodeDefinition $rootNode) { $rootNode diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php index ebb594fac1590..4c7b4dfe67716 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php @@ -38,6 +38,7 @@ use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\DependencyInjection\EnvVarProcessorInterface; +use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; use Symfony\Component\DependencyInjection\Exception\LogicException; use Symfony\Component\DependencyInjection\Loader\XmlFileLoader; use Symfony\Component\DependencyInjection\Reference; @@ -54,6 +55,11 @@ use Symfony\Component\HttpKernel\Controller\ArgumentValueResolverInterface; use Symfony\Component\HttpKernel\DataCollector\DataCollectorInterface; use Symfony\Component\HttpKernel\DependencyInjection\Extension; +use Symfony\Component\Lock\Factory; +use Symfony\Component\Lock\Lock; +use Symfony\Component\Lock\LockInterface; +use Symfony\Component\Lock\Store\StoreFactory; +use Symfony\Component\Lock\StoreInterface; use Symfony\Component\PropertyAccess\PropertyAccessor; use Symfony\Component\PropertyInfo\PropertyAccessExtractorInterface; use Symfony\Component\PropertyInfo\PropertyDescriptionExtractorInterface; @@ -298,6 +304,10 @@ public function load(array $configs, ContainerBuilder $container) $this->registerPropertyInfoConfiguration($config['property_info'], $container, $loader); } + if ($this->isConfigEnabled($container, $config['lock'])) { + $this->registerLockConfiguration($config['lock'], $container, $loader); + } + if ($this->isConfigEnabled($container, $config['web_link'])) { if (!class_exists(HttpHeaderSerializer::class)) { throw new LogicException('WebLink support cannot be enabled as the WebLink component is not installed.'); @@ -1672,6 +1682,84 @@ private function registerPropertyInfoConfiguration(array $config, ContainerBuild } } + private function registerLockConfiguration(array $config, ContainerBuilder $container, XmlFileLoader $loader) + { + $loader->load('lock.xml'); + + foreach ($config['resources'] as $resourceName => $resourceStores) { + if (0 === count($resourceStores)) { + continue; + } + + // Generate stores + $storeDefinitions = array(); + foreach ($resourceStores as $storeDsn) { + $storeDsn = $container->resolveEnvPlaceholders($storeDsn, null, $usedEnvs); + switch (true) { + case 'flock' === $storeDsn: + $storeDefinition = new Reference('lock.store.flock'); + break; + case 'semaphore' === $storeDsn: + $storeDefinition = new Reference('lock.store.semaphore'); + break; + case $usedEnvs || preg_match('#^[a-z]++://#', $storeDsn): + if (!$container->hasDefinition($connectionDefinitionId = $container->hash($storeDsn))) { + $connectionDefinition = new Definition(\stdClass::class); + $connectionDefinition->setPublic(false); + $connectionDefinition->setFactory(array(StoreFactory::class, 'createConnection')); + $connectionDefinition->setArguments(array($storeDsn)); + $container->setDefinition($connectionDefinitionId, $connectionDefinition); + } + + $storeDefinition = new Definition(StoreInterface::class); + $storeDefinition->setPublic(false); + $storeDefinition->setFactory(array(StoreFactory::class, 'createStore')); + $storeDefinition->setArguments(array(new Reference($connectionDefinitionId))); + + $container->setDefinition($storeDefinitionId = 'lock.'.$resourceName.'.store.'.$container->hash($storeDsn), $storeDefinition); + + $storeDefinition = new Reference($storeDefinitionId); + break; + default: + throw new InvalidArgumentException(sprintf('Lock store DSN "%s" is not valid in resource "%s"', $storeDsn, $resourceName)); + } + + $storeDefinitions[] = $storeDefinition; + } + + // Wrap array of stores with CombinedStore + if (count($storeDefinitions) > 1) { + $combinedDefinition = new ChildDefinition('lock.store.combined.abstract'); + $combinedDefinition->replaceArgument(0, $storeDefinitions); + $container->setDefinition('lock.'.$resourceName.'.store', $combinedDefinition); + } else { + $container->setAlias('lock.'.$resourceName.'.store', new Alias((string) $storeDefinitions[0], false)); + } + + // Generate factories for each resource + $factoryDefinition = new ChildDefinition('lock.factory.abstract'); + $factoryDefinition->replaceArgument(0, new Reference('lock.'.$resourceName.'.store')); + $container->setDefinition('lock.'.$resourceName.'.factory', $factoryDefinition); + + // Generate services for lock instances + $lockDefinition = new Definition(Lock::class); + $lockDefinition->setPublic(false); + $lockDefinition->setFactory(array(new Reference('lock.'.$resourceName.'.factory'), 'createLock')); + $lockDefinition->setArguments(array($resourceName)); + $container->setDefinition('lock.'.$resourceName, $lockDefinition); + + // provide alias for default resource + if ('default' === $resourceName) { + $container->setAlias('lock.store', new Alias('lock.'.$resourceName.'.store', false)); + $container->setAlias('lock.factory', new Alias('lock.'.$resourceName.'.factory', false)); + $container->setAlias('lock', new Alias('lock.'.$resourceName, false)); + $container->setAlias(StoreInterface::class, new Alias('lock.store', false)); + $container->setAlias(Factory::class, new Alias('lock.factory', false)); + $container->setAlias(LockInterface::class, new Alias('lock', false)); + } + } + } + private function registerCacheConfiguration(array $config, ContainerBuilder $container) { $version = substr(str_replace('/', '-', base64_encode(hash('sha256', uniqid(mt_rand(), true), true))), 0, 22); diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/lock.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/lock.xml new file mode 100644 index 0000000000000..e4c2231c1c155 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/lock.xml @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 f63f93723029d..181dd9334a80b 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 @@ -29,6 +29,7 @@ + @@ -296,4 +297,19 @@ + + + + + + + + + + + + + + + diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/ConfigurationTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/ConfigurationTest.php index e4e6f0f2a7bea..e6e83d40b538d 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/ConfigurationTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/ConfigurationTest.php @@ -16,6 +16,7 @@ use Symfony\Bundle\FullStack; use Symfony\Component\Config\Definition\Exception\InvalidConfigurationException; use Symfony\Component\Config\Definition\Processor; +use Symfony\Component\Lock\Store\SemaphoreStore; class ConfigurationTest extends TestCase { @@ -343,6 +344,14 @@ protected static function getBundleDefaultConfig() 'web_link' => array( 'enabled' => !class_exists(FullStack::class), ), + 'lock' => array( + 'enabled' => !class_exists(FullStack::class), + 'resources' => array( + 'default' => array( + class_exists(SemaphoreStore::class) && SemaphoreStore::isSupported() ? 'semaphore' : 'flock', + ), + ), + ), ); } } diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/lock.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/lock.xml new file mode 100644 index 0000000000000..fc2bf0657a615 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/lock.xml @@ -0,0 +1,11 @@ + + + + + + + diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/lock_named.xml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/lock_named.xml new file mode 100644 index 0000000000000..d36c482de62ea --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/xml/lock_named.xml @@ -0,0 +1,22 @@ + + + + + + redis://paas.com + + + + + semaphore + flock + semaphore + flock + %env(REDIS_URL)% + + + diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/lock.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/lock.yml new file mode 100644 index 0000000000000..70f578a143a56 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/lock.yml @@ -0,0 +1,2 @@ +framework: + lock: ~ diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/lock_named.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/lock_named.yml new file mode 100644 index 0000000000000..6d0cb5ca638bd --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Fixtures/yml/lock_named.yml @@ -0,0 +1,9 @@ +parameters: + env(REDIS_DSN): redis://paas.com + +framework: + lock: + foo: semaphore + bar: flock + baz: [semaphore, flock] + qux: "%env(REDIS_DSN)%" diff --git a/src/Symfony/Bundle/FrameworkBundle/composer.json b/src/Symfony/Bundle/FrameworkBundle/composer.json index 9b16b9417950c..18065e6782306 100644 --- a/src/Symfony/Bundle/FrameworkBundle/composer.json +++ b/src/Symfony/Bundle/FrameworkBundle/composer.json @@ -54,6 +54,7 @@ "symfony/workflow": "~3.3|~4.0", "symfony/yaml": "~3.2|~4.0", "symfony/property-info": "~3.3|~4.0", + "symfony/lock": "~3.4|~4.0", "symfony/web-link": "~3.3|~4.0", "doctrine/annotations": "~1.0", "phpdocumentor/reflection-docblock": "^3.0|^4.0", diff --git a/src/Symfony/Component/Console/Command/LockableTrait.php b/src/Symfony/Component/Console/Command/LockableTrait.php index b521f3b7708b9..308ebf28c045a 100644 --- a/src/Symfony/Component/Console/Command/LockableTrait.php +++ b/src/Symfony/Component/Console/Command/LockableTrait.php @@ -46,7 +46,7 @@ private function lock($name = null, $blocking = false) if (SemaphoreStore::isSupported($blocking)) { $store = new SemaphoreStore(); } else { - $store = new FlockStore(sys_get_temp_dir()); + $store = new FlockStore(); } $this->lock = (new Factory($store))->createLock($name ?: $this->getName()); diff --git a/src/Symfony/Component/Console/Tests/Command/LockableTraitTest.php b/src/Symfony/Component/Console/Tests/Command/LockableTraitTest.php index 401ff823a7761..a622d1b4895f5 100644 --- a/src/Symfony/Component/Console/Tests/Command/LockableTraitTest.php +++ b/src/Symfony/Component/Console/Tests/Command/LockableTraitTest.php @@ -44,7 +44,7 @@ public function testLockReturnsFalseIfAlreadyLockedByAnotherCommand() if (SemaphoreStore::isSupported(false)) { $store = new SemaphoreStore(); } else { - $store = new FlockStore(sys_get_temp_dir()); + $store = new FlockStore(); } $lock = (new Factory($store))->createLock($command->getName()); diff --git a/src/Symfony/Component/Lock/Store/FlockStore.php b/src/Symfony/Component/Lock/Store/FlockStore.php index cd0a276de4a38..5babc7f610bce 100644 --- a/src/Symfony/Component/Lock/Store/FlockStore.php +++ b/src/Symfony/Component/Lock/Store/FlockStore.php @@ -32,12 +32,15 @@ class FlockStore implements StoreInterface private $lockPath; /** - * @param string $lockPath the directory to store the lock + * @param string|null $lockPath the directory to store the lock, defaults to the system's temporary directory * * @throws LockStorageException If the lock directory could not be created or is not writable */ - public function __construct($lockPath) + public function __construct($lockPath = null) { + if (null === $lockPath) { + $lockPath = sys_get_temp_dir(); + } if (!is_dir($lockPath) || !is_writable($lockPath)) { throw new InvalidArgumentException(sprintf('The directory "%s" is not writable.', $lockPath)); } diff --git a/src/Symfony/Component/Lock/Store/MemcachedStore.php b/src/Symfony/Component/Lock/Store/MemcachedStore.php index 8e9db10cd036f..4a2ffa3e02042 100644 --- a/src/Symfony/Component/Lock/Store/MemcachedStore.php +++ b/src/Symfony/Component/Lock/Store/MemcachedStore.php @@ -24,6 +24,12 @@ */ class MemcachedStore implements StoreInterface { + private static $defaultClientOptions = array( + 'persistent_id' => null, + 'username' => null, + 'password' => null, + ); + private $memcached; private $initialTtl; /** @var bool */ @@ -52,6 +58,128 @@ public function __construct(\Memcached $memcached, $initialTtl = 300) $this->initialTtl = $initialTtl; } + /** + * Creates a Memcached instance. + * + * By default, the binary protocol, block, and libketama compatible options are enabled. + * + * Example DSN: + * - 'memcached://user:pass@localhost?weight=33' + * - array(array('localhost', 11211, 33)) + * + * @param string $dsn A server or A DSN + * @param array $options An array of options + * + * @return \Memcached + * + * @throws \ErrorEception When invalid options or server are provided + */ + public static function createConnection($server, array $options = array()) + { + if (!static::isSupported()) { + throw new InvalidArgumentException('Memcached extension is required'); + } + set_error_handler(function ($type, $msg, $file, $line) { throw new \ErrorException($msg, 0, $type, $file, $line); }); + try { + $options += static::$defaultClientOptions; + $client = new \Memcached($options['persistent_id']); + $username = $options['username']; + $password = $options['password']; + + // parse any DSN in $server + if (is_string($server)) { + if (0 !== strpos($server, 'memcached://')) { + throw new InvalidArgumentException(sprintf('Invalid Memcached DSN: %s does not start with "memcached://"', $server)); + } + $params = preg_replace_callback('#^memcached://(?:([^@]*+)@)?#', function ($m) use (&$username, &$password) { + if (!empty($m[1])) { + list($username, $password) = explode(':', $m[1], 2) + array(1 => null); + } + + return 'file://'; + }, $server); + if (false === $params = parse_url($params)) { + throw new InvalidArgumentException(sprintf('Invalid Memcached DSN: %s', $server)); + } + if (!isset($params['host']) && !isset($params['path'])) { + throw new InvalidArgumentException(sprintf('Invalid Memcached DSN: %s', $server)); + } + if (isset($params['path']) && preg_match('#/(\d+)$#', $params['path'], $m)) { + $params['weight'] = $m[1]; + $params['path'] = substr($params['path'], 0, -strlen($m[0])); + } + $params += array( + 'host' => isset($params['host']) ? $params['host'] : $params['path'], + 'port' => isset($params['host']) ? 11211 : null, + 'weight' => 0, + ); + if (isset($params['query'])) { + parse_str($params['query'], $query); + $params += $query; + $options = $query + $options; + } + + $server = array($params['host'], $params['port'], $params['weight']); + } + + // set client's options + unset($options['persistent_id'], $options['username'], $options['password'], $options['weight']); + $options = array_change_key_case($options, CASE_UPPER); + $client->setOption(\Memcached::OPT_BINARY_PROTOCOL, true); + $client->setOption(\Memcached::OPT_NO_BLOCK, false); + if (!array_key_exists('LIBKETAMA_COMPATIBLE', $options) && !array_key_exists(\Memcached::OPT_LIBKETAMA_COMPATIBLE, $options)) { + $client->setOption(\Memcached::OPT_LIBKETAMA_COMPATIBLE, true); + } + foreach ($options as $name => $value) { + if (is_int($name)) { + continue; + } + if ('HASH' === $name || 'SERIALIZER' === $name || 'DISTRIBUTION' === $name) { + $value = constant('Memcached::'.$name.'_'.strtoupper($value)); + } + $opt = constant('Memcached::OPT_'.$name); + + unset($options[$name]); + $options[$opt] = $value; + } + $client->setOptions($options); + + // set client's servers, taking care of persistent connections + if (!$client->isPristine()) { + $oldServers = array(); + foreach ($client->getServerList() as $server) { + $oldServers[] = array($server['host'], $server['port']); + } + + $newServers = array(); + if (1 < count($server)) { + $server = array_values($server); + unset($server[2]); + $server[1] = (int) $server[1]; + } + $newServers[] = $server; + + if ($oldServers !== $newServers) { + // before resetting, ensure $servers is valid + $client->addServers(array($server)); + $client->resetServerList(); + } + } + $client->addServers(array($server)); + + if (null !== $username || null !== $password) { + if (!method_exists($client, 'setSaslAuthData')) { + trigger_error('Missing SASL support: the memcached extension must be compiled with --enable-memcached-sasl.'); + } + $client->setSaslAuthData($username, $password); + } + + return $client; + } finally { + restore_error_handler(); + } + } + /** * {@inheritdoc} */ diff --git a/src/Symfony/Component/Lock/Store/RedisStore.php b/src/Symfony/Component/Lock/Store/RedisStore.php index 88b15938997c9..66a067dfb0f9d 100644 --- a/src/Symfony/Component/Lock/Store/RedisStore.php +++ b/src/Symfony/Component/Lock/Store/RedisStore.php @@ -24,6 +24,14 @@ */ class RedisStore implements StoreInterface { + private static $defaultConnectionOptions = array( + 'class' => null, + 'persistent' => 0, + 'persistent_id' => null, + 'timeout' => 30, + 'read_timeout' => 0, + 'retry_interval' => 0, + ); private $redis; private $initialTtl; @@ -45,6 +53,88 @@ public function __construct($redisClient, $initialTtl = 300.0) $this->initialTtl = $initialTtl; } + /** + * Creates a Redis connection using a DSN configuration. + * + * Example DSN: + * - redis://localhost + * - redis://example.com:1234 + * - redis://secret@example.com/13 + * - redis:///var/run/redis.sock + * - redis://secret@/var/run/redis.sock/13 + * + * @param string $dsn + * @param array $options See self::$defaultConnectionOptions + * + * @throws InvalidArgumentException When the DSN is invalid + * + * @return \Redis|\Predis\Client According to the "class" option + */ + public static function createConnection($dsn, array $options = array()) + { + if (0 !== strpos($dsn, 'redis://')) { + throw new InvalidArgumentException(sprintf('Invalid Redis DSN: %s does not start with "redis://"', $dsn)); + } + $params = preg_replace_callback('#^redis://(?:(?:[^:@]*+:)?([^@]*+)@)?#', function ($m) use (&$auth) { + if (isset($m[1])) { + $auth = $m[1]; + } + + return 'file://'; + }, $dsn); + if (false === $params = parse_url($params)) { + throw new InvalidArgumentException(sprintf('Invalid Redis DSN: %s', $dsn)); + } + if (!isset($params['host']) && !isset($params['path'])) { + throw new InvalidArgumentException(sprintf('Invalid Redis DSN: %s', $dsn)); + } + if (isset($params['path']) && preg_match('#/(\d+)$#', $params['path'], $m)) { + $params['dbindex'] = $m[1]; + $params['path'] = substr($params['path'], 0, -strlen($m[0])); + } + $params += array( + 'host' => isset($params['host']) ? $params['host'] : $params['path'], + 'port' => isset($params['host']) ? 6379 : null, + 'dbindex' => 0, + ); + if (isset($params['query'])) { + parse_str($params['query'], $query); + $params += $query; + } + $params += $options + self::$defaultConnectionOptions; + $class = null === $params['class'] ? (extension_loaded('redis') ? \Redis::class : \Predis\Client::class) : $params['class']; + + if (is_a($class, \Redis::class, true)) { + $connect = $params['persistent'] || $params['persistent_id'] ? 'pconnect' : 'connect'; + $redis = new $class(); + @$redis->{$connect}($params['host'], $params['port'], $params['timeout'], $params['persistent_id'], $params['retry_interval']); + + if (@!$redis->isConnected()) { + $e = ($e = error_get_last()) && preg_match('/^Redis::p?connect\(\): (.*)/', $e['message'], $e) ? sprintf(' (%s)', $e[1]) : ''; + throw new InvalidArgumentException(sprintf('Redis connection failed%s: %s', $e, $dsn)); + } + + if ((null !== $auth && !$redis->auth($auth)) + || ($params['dbindex'] && !$redis->select($params['dbindex'])) + || ($params['read_timeout'] && !$redis->setOption(\Redis::OPT_READ_TIMEOUT, $params['read_timeout'])) + ) { + $e = preg_replace('/^ERR /', '', $redis->getLastError()); + throw new InvalidArgumentException(sprintf('Redis connection failed (%s): %s', $e, $dsn)); + } + } elseif (is_a($class, \Predis\Client::class, true)) { + $params['scheme'] = isset($params['host']) ? 'tcp' : 'unix'; + $params['database'] = $params['dbindex'] ?: null; + $params['password'] = $auth; + $redis = new $class((new Factory())->create($params)); + } elseif (class_exists($class, false)) { + throw new InvalidArgumentException(sprintf('"%s" is not a subclass of "Redis" or "Predis\Client"', $class)); + } else { + throw new InvalidArgumentException(sprintf('Class "%s" does not exist', $class)); + } + + return $redis; + } + /** * {@inheritdoc} */ diff --git a/src/Symfony/Component/Lock/Store/StoreFactory.php b/src/Symfony/Component/Lock/Store/StoreFactory.php new file mode 100644 index 0000000000000..9a23cf6472dea --- /dev/null +++ b/src/Symfony/Component/Lock/Store/StoreFactory.php @@ -0,0 +1,54 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Lock\Store; + +use Symfony\Component\Lock\Exception\InvalidArgumentException; + +/** + * StoreFactory create stores and connections. + * + * @author Jérémy Derussé + */ +class StoreFactory +{ + public static function createConnection($dsn, array $options = array()) + { + if (!is_string($dsn)) { + throw new InvalidArgumentException(sprintf('The %s() method expects argument #1 to be string, %s given.', __METHOD__, gettype($dsn))); + } + if (0 === strpos($dsn, 'redis://')) { + return RedisStore::createConnection($dsn, $options); + } + if (0 === strpos($dsn, 'memcached://')) { + return MemcachedStore::createConnection($dsn, $options); + } + + throw new InvalidArgumentException(sprintf('Unsupported DSN: %s.', $dsn)); + } + + /** + * @param \Redis|\RedisArray|\RedisCluster|\Predis\Client|\Memcached $connection + * + * @return RedisStore|MemcachedStore + */ + public static function createStore($connection) + { + if ($connection instanceof \Redis || $connection instanceof \RedisArray || $connection instanceof \RedisCluster || $connection instanceof \Predis\Client) { + return new RedisStore($connection); + } + if ($connection instanceof \Memcached) { + return new MemcachedStore($connection); + } + + throw new InvalidArgumentException(sprintf('Unsupported Connection: %s.', get_class($connection))); + } +} diff --git a/src/Symfony/Component/Lock/Tests/Store/FlockStoreTest.php b/src/Symfony/Component/Lock/Tests/Store/FlockStoreTest.php index 53d2ae78dc78a..ef3650c3124b5 100644 --- a/src/Symfony/Component/Lock/Tests/Store/FlockStoreTest.php +++ b/src/Symfony/Component/Lock/Tests/Store/FlockStoreTest.php @@ -26,7 +26,7 @@ class FlockStoreTest extends AbstractStoreTest */ protected function getStore() { - return new FlockStore(sys_get_temp_dir()); + return new FlockStore(); } /** diff --git a/src/Symfony/Component/Lock/Tests/Store/MemcachedStoreTest.php b/src/Symfony/Component/Lock/Tests/Store/MemcachedStoreTest.php index eb030fba0f9de..cfe03b25e2c34 100644 --- a/src/Symfony/Component/Lock/Tests/Store/MemcachedStoreTest.php +++ b/src/Symfony/Component/Lock/Tests/Store/MemcachedStoreTest.php @@ -54,4 +54,100 @@ public function testAbortAfterExpiration() { $this->markTestSkipped('Memcached expects a TTL greater than 1 sec. Simulating a slow network is too hard'); } + + public function testDefaultOptions() + { + $this->assertTrue(MemcachedStore::isSupported()); + + $client = MemcachedStore::createConnection('memcached://127.0.0.1'); + + $this->assertTrue($client->getOption(\Memcached::OPT_COMPRESSION)); + $this->assertSame(1, $client->getOption(\Memcached::OPT_BINARY_PROTOCOL)); + $this->assertSame(1, $client->getOption(\Memcached::OPT_LIBKETAMA_COMPATIBLE)); + } + + /** + * @dataProvider provideServersSetting + */ + public function testServersSetting($dsn, $host, $port) + { + $client1 = MemcachedStore::createConnection($dsn); + $client3 = MemcachedStore::createConnection(array($host, $port)); + $expect = array( + 'host' => $host, + 'port' => $port, + ); + + $f = function ($s) { return array('host' => $s['host'], 'port' => $s['port']); }; + $this->assertSame(array($expect), array_map($f, $client1->getServerList())); + $this->assertSame(array($expect), array_map($f, $client3->getServerList())); + } + + public function provideServersSetting() + { + yield array( + 'memcached://127.0.0.1/50', + '127.0.0.1', + 11211, + ); + yield array( + 'memcached://localhost:11222?weight=25', + 'localhost', + 11222, + ); + if (ini_get('memcached.use_sasl')) { + yield array( + 'memcached://user:password@127.0.0.1?weight=50', + '127.0.0.1', + 11211, + ); + } + yield array( + 'memcached:///var/run/memcached.sock?weight=25', + '/var/run/memcached.sock', + 0, + ); + yield array( + 'memcached:///var/local/run/memcached.socket?weight=25', + '/var/local/run/memcached.socket', + 0, + ); + if (ini_get('memcached.use_sasl')) { + yield array( + 'memcached://user:password@/var/local/run/memcached.socket?weight=25', + '/var/local/run/memcached.socket', + 0, + ); + } + } + + /** + * @dataProvider provideDsnWithOptions + */ + public function testDsnWithOptions($dsn, array $options, array $expectedOptions) + { + $client = MemcachedStore::createConnection($dsn, $options); + + foreach ($expectedOptions as $option => $expect) { + $this->assertSame($expect, $client->getOption($option)); + } + } + + public function provideDsnWithOptions() + { + if (!class_exists('\Memcached')) { + self::markTestSkipped('Extension memcached required.'); + } + + yield array( + 'memcached://localhost:11222?retry_timeout=10', + array(\Memcached::OPT_RETRY_TIMEOUT => 8), + array(\Memcached::OPT_RETRY_TIMEOUT => 10), + ); + yield array( + 'memcached://localhost:11222?socket_recv_size=1&socket_send_size=2', + array(\Memcached::OPT_RETRY_TIMEOUT => 8), + array(\Memcached::OPT_SOCKET_RECV_SIZE => 1, \Memcached::OPT_SOCKET_SEND_SIZE => 2, \Memcached::OPT_RETRY_TIMEOUT => 8), + ); + } } From 5ab50103ae4edc0db2c6bb2f8aaf6833ba9b7984 Mon Sep 17 00:00:00 2001 From: Pierre du Plessis Date: Fri, 10 Mar 2017 14:08:44 +0200 Subject: [PATCH 0922/1099] Remove Validator\TypeTestCase and add validator logic to base TypeTestCase --- .../Test/Traits/ValidatorExtensionTrait.php | 40 +++++++++++++++++ .../Component/Form/Test/TypeTestCase.php | 19 ++++++++ .../Type/BaseValidatorExtensionTest.php | 1 + .../Type/FormTypeValidatorExtensionTest.php | 3 ++ .../Type/SubmitTypeValidatorExtensionTest.php | 4 ++ .../Extension/Validator/Type/TypeTestCase.php | 44 ------------------- .../Type/UploadValidatorExtensionTest.php | 1 + 7 files changed, 68 insertions(+), 44 deletions(-) create mode 100644 src/Symfony/Component/Form/Test/Traits/ValidatorExtensionTrait.php delete mode 100644 src/Symfony/Component/Form/Tests/Extension/Validator/Type/TypeTestCase.php diff --git a/src/Symfony/Component/Form/Test/Traits/ValidatorExtensionTrait.php b/src/Symfony/Component/Form/Test/Traits/ValidatorExtensionTrait.php new file mode 100644 index 0000000000000..0724f697ba77a --- /dev/null +++ b/src/Symfony/Component/Form/Test/Traits/ValidatorExtensionTrait.php @@ -0,0 +1,40 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Test\Traits; + +use Symfony\Component\Form\Extension\Validator\ValidatorExtension; +use Symfony\Component\Form\Test\TypeTestCase; +use Symfony\Component\Validator\Mapping\ClassMetadata; +use Symfony\Component\Validator\Validator\ValidatorInterface; + +trait ValidatorExtensionTrait +{ + protected $validator; + + protected function getValidatorExtension() + { + if (!interface_exists(ValidatorInterface::class)) { + throw new \Exception('In order to use the "ValidatorExtensionTrait", the symfony/validator component must be installed'); + } + + if (!$this instanceof TypeTestCase) { + throw new \Exception(sprintf('The trait "ValidatorExtensionTrait" can only be added to a class that extends %s', TypeTestCase::class)); + } + + $this->validator = $this->getMockBuilder(ValidatorInterface::class)->getMock(); + $metadata = $this->getMockBuilder(ClassMetadata::class)->disableOriginalConstructor()->getMock(); + $this->validator->expects($this->any())->method('getMetadataFor')->will($this->returnValue($metadata)); + $this->validator->expects($this->any())->method('validate')->will($this->returnValue(array())); + + return new ValidatorExtension($this->validator); + } +} diff --git a/src/Symfony/Component/Form/Test/TypeTestCase.php b/src/Symfony/Component/Form/Test/TypeTestCase.php index ff3f78292f5f0..346dc61648896 100644 --- a/src/Symfony/Component/Form/Test/TypeTestCase.php +++ b/src/Symfony/Component/Form/Test/TypeTestCase.php @@ -13,6 +13,7 @@ use Symfony\Component\Form\FormBuilder; use Symfony\Component\EventDispatcher\EventDispatcher; +use Symfony\Component\Form\Test\Traits\ValidatorExtensionTrait; abstract class TypeTestCase extends FormIntegrationTestCase { @@ -34,6 +35,24 @@ protected function setUp() $this->builder = new FormBuilder(null, null, $this->dispatcher, $this->factory); } + protected function tearDown() + { + if (in_array(ValidatorExtensionTrait::class, class_uses($this))) { + $this->validator = null; + } + } + + protected function getExtensions() + { + $extensions = array(); + + if (in_array(ValidatorExtensionTrait::class, class_uses($this))) { + $extensions[] = $this->getValidatorExtension(); + } + + return $extensions; + } + public static function assertDateTimeEquals(\DateTime $expected, \DateTime $actual) { self::assertEquals($expected->format('c'), $actual->format('c')); diff --git a/src/Symfony/Component/Form/Tests/Extension/Validator/Type/BaseValidatorExtensionTest.php b/src/Symfony/Component/Form/Tests/Extension/Validator/Type/BaseValidatorExtensionTest.php index f12b915b9a378..e83aaaa3491dc 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Validator/Type/BaseValidatorExtensionTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Validator/Type/BaseValidatorExtensionTest.php @@ -12,6 +12,7 @@ namespace Symfony\Component\Form\Tests\Extension\Validator\Type; use Symfony\Component\Form\Test\FormInterface; +use Symfony\Component\Form\Test\TypeTestCase; use Symfony\Component\Validator\Constraints\GroupSequence; /** diff --git a/src/Symfony/Component/Form/Tests/Extension/Validator/Type/FormTypeValidatorExtensionTest.php b/src/Symfony/Component/Form/Tests/Extension/Validator/Type/FormTypeValidatorExtensionTest.php index 2bf10bb36bce2..0dca9c476b56d 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Validator/Type/FormTypeValidatorExtensionTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Validator/Type/FormTypeValidatorExtensionTest.php @@ -12,11 +12,14 @@ namespace Symfony\Component\Form\Tests\Extension\Validator\Type; use Symfony\Component\Form\Extension\Validator\Type\FormTypeValidatorExtension; +use Symfony\Component\Form\Test\Traits\ValidatorExtensionTrait; use Symfony\Component\Validator\Constraints\Valid; use Symfony\Component\Validator\ConstraintViolationList; class FormTypeValidatorExtensionTest extends BaseValidatorExtensionTest { + use ValidatorExtensionTrait; + public function testSubmitValidatesData() { $builder = $this->factory->createBuilder( diff --git a/src/Symfony/Component/Form/Tests/Extension/Validator/Type/SubmitTypeValidatorExtensionTest.php b/src/Symfony/Component/Form/Tests/Extension/Validator/Type/SubmitTypeValidatorExtensionTest.php index 48fc8de51d9c8..015b9582b5764 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Validator/Type/SubmitTypeValidatorExtensionTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Validator/Type/SubmitTypeValidatorExtensionTest.php @@ -11,8 +11,12 @@ namespace Symfony\Component\Form\Tests\Extension\Validator\Type; +use Symfony\Component\Form\Test\Traits\ValidatorExtensionTrait; + class SubmitTypeValidatorExtensionTest extends BaseValidatorExtensionTest { + use ValidatorExtensionTrait; + protected function createForm(array $options = array()) { return $this->factory->create('Symfony\Component\Form\Extension\Core\Type\SubmitType', null, $options); diff --git a/src/Symfony/Component/Form/Tests/Extension/Validator/Type/TypeTestCase.php b/src/Symfony/Component/Form/Tests/Extension/Validator/Type/TypeTestCase.php deleted file mode 100644 index cb6000aa8fb81..0000000000000 --- a/src/Symfony/Component/Form/Tests/Extension/Validator/Type/TypeTestCase.php +++ /dev/null @@ -1,44 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Form\Tests\Extension\Validator\Type; - -use Symfony\Component\Form\Test\TypeTestCase as BaseTypeTestCase; -use Symfony\Component\Form\Extension\Validator\ValidatorExtension; - -abstract class TypeTestCase extends BaseTypeTestCase -{ - protected $validator; - - protected function setUp() - { - $this->validator = $this->getMockBuilder('Symfony\Component\Validator\Validator\ValidatorInterface')->getMock(); - $metadata = $this->getMockBuilder('Symfony\Component\Validator\Mapping\ClassMetadata')->disableOriginalConstructor()->getMock(); - $this->validator->expects($this->once())->method('getMetadataFor')->will($this->returnValue($metadata)); - $this->validator->expects($this->any())->method('validate')->will($this->returnValue(array())); - - parent::setUp(); - } - - protected function tearDown() - { - $this->validator = null; - - parent::tearDown(); - } - - protected function getExtensions() - { - return array_merge(parent::getExtensions(), array( - new ValidatorExtension($this->validator), - )); - } -} diff --git a/src/Symfony/Component/Form/Tests/Extension/Validator/Type/UploadValidatorExtensionTest.php b/src/Symfony/Component/Form/Tests/Extension/Validator/Type/UploadValidatorExtensionTest.php index 8c0984f7e4e13..17792b67454f2 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Validator/Type/UploadValidatorExtensionTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Validator/Type/UploadValidatorExtensionTest.php @@ -12,6 +12,7 @@ namespace Symfony\Component\Form\Tests\Extension\Validator\Type; use Symfony\Component\Form\Extension\Validator\Type\UploadValidatorExtension; +use Symfony\Component\Form\Test\TypeTestCase; use Symfony\Component\OptionsResolver\OptionsResolver; use Symfony\Component\OptionsResolver\Options; From ec9242d1ee906ed288e0cd31c1ac1557647519cb Mon Sep 17 00:00:00 2001 From: Christopher Davis Date: Wed, 22 Feb 2017 10:41:23 -0500 Subject: [PATCH 0923/1099] [Serializer] Add Support for in CustomNormalizer --- .../Normalizer/AbstractNormalizer.php | 9 ++-- .../Normalizer/CustomNormalizer.php | 7 +-- .../Normalizer/ObjectToPopulateTrait.php | 41 ++++++++++++++++ .../Tests/Normalizer/CustomNormalizerTest.php | 12 +++++ .../Normalizer/ObjectToPopulateTraitTest.php | 47 +++++++++++++++++++ 5 files changed, 107 insertions(+), 9 deletions(-) create mode 100644 src/Symfony/Component/Serializer/Normalizer/ObjectToPopulateTrait.php create mode 100644 src/Symfony/Component/Serializer/Tests/Normalizer/ObjectToPopulateTraitTest.php diff --git a/src/Symfony/Component/Serializer/Normalizer/AbstractNormalizer.php b/src/Symfony/Component/Serializer/Normalizer/AbstractNormalizer.php index 726654cbf6b87..7a79949185740 100644 --- a/src/Symfony/Component/Serializer/Normalizer/AbstractNormalizer.php +++ b/src/Symfony/Component/Serializer/Normalizer/AbstractNormalizer.php @@ -27,6 +27,8 @@ */ abstract class AbstractNormalizer extends SerializerAwareNormalizer implements NormalizerInterface, DenormalizerInterface, SerializerAwareInterface { + use ObjectToPopulateTrait; + const CIRCULAR_REFERENCE_LIMIT = 'circular_reference_limit'; const OBJECT_TO_POPULATE = 'object_to_populate'; const GROUPS = 'groups'; @@ -317,12 +319,7 @@ protected function instantiateObject(array &$data, $class, array &$context, \Ref $format = null; } - if ( - isset($context[static::OBJECT_TO_POPULATE]) && - is_object($context[static::OBJECT_TO_POPULATE]) && - $context[static::OBJECT_TO_POPULATE] instanceof $class - ) { - $object = $context[static::OBJECT_TO_POPULATE]; + if (null !== $object = $this->extractObjectToPopulate($class, $context, static::OBJECT_TO_POPULATE)) { unset($context[static::OBJECT_TO_POPULATE]); return $object; diff --git a/src/Symfony/Component/Serializer/Normalizer/CustomNormalizer.php b/src/Symfony/Component/Serializer/Normalizer/CustomNormalizer.php index fd8bbca274211..b56b10f2dcf70 100644 --- a/src/Symfony/Component/Serializer/Normalizer/CustomNormalizer.php +++ b/src/Symfony/Component/Serializer/Normalizer/CustomNormalizer.php @@ -19,10 +19,11 @@ */ class CustomNormalizer implements NormalizerInterface, DenormalizerInterface, SerializerAwareInterface { - private $cache = array(); - + use ObjectToPopulateTrait; use SerializerAwareTrait; + private $cache = array(); + /** * {@inheritdoc} */ @@ -36,7 +37,7 @@ public function normalize($object, $format = null, array $context = array()) */ public function denormalize($data, $class, $format = null, array $context = array()) { - $object = new $class(); + $object = $this->extractObjectToPopulate($class, $context) ?: new $class(); $object->denormalize($this->serializer, $data, $format, $context); return $object; diff --git a/src/Symfony/Component/Serializer/Normalizer/ObjectToPopulateTrait.php b/src/Symfony/Component/Serializer/Normalizer/ObjectToPopulateTrait.php new file mode 100644 index 0000000000000..f21100f014c6a --- /dev/null +++ b/src/Symfony/Component/Serializer/Normalizer/ObjectToPopulateTrait.php @@ -0,0 +1,41 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Serializer\Normalizer; + +trait ObjectToPopulateTrait +{ + /** + * Extract the `object_to_populate` field from the context if it exists + * and is an instance of the provided $class. + * + * @param string $class The class the object should be + * @param $context The denormalization context + * @param string $key They in which to look for the object to populate. + * Keeps backwards compatibility with `AbstractNormalizer`. + * + * @return object|null an object if things check out, null otherwise + */ + protected function extractObjectToPopulate($class, array $context, $key = null) + { + $key = $key ?: 'object_to_populate'; + + if ( + isset($context[$key]) && + is_object($context[$key]) && + $context[$key] instanceof $class + ) { + return $context[$key]; + } + + return null; + } +} diff --git a/src/Symfony/Component/Serializer/Tests/Normalizer/CustomNormalizerTest.php b/src/Symfony/Component/Serializer/Tests/Normalizer/CustomNormalizerTest.php index a3c3c1a0e62ec..e5d0d445707eb 100644 --- a/src/Symfony/Component/Serializer/Tests/Normalizer/CustomNormalizerTest.php +++ b/src/Symfony/Component/Serializer/Tests/Normalizer/CustomNormalizerTest.php @@ -56,6 +56,18 @@ public function testDeserialize() $this->assertNull($obj->xmlFoo); } + public function testDenormalizeWithObjectToPopulateUsesProvidedObject() + { + $expected = new ScalarDummy(); + $obj = $this->normalizer->denormalize('foo', ScalarDummy::class, 'json', array( + 'object_to_populate' => $expected, + )); + + $this->assertSame($expected, $obj); + $this->assertEquals('foo', $obj->foo); + $this->assertNull($obj->xmlFoo); + } + public function testSupportsNormalization() { $this->assertTrue($this->normalizer->supportsNormalization(new ScalarDummy())); diff --git a/src/Symfony/Component/Serializer/Tests/Normalizer/ObjectToPopulateTraitTest.php b/src/Symfony/Component/Serializer/Tests/Normalizer/ObjectToPopulateTraitTest.php new file mode 100644 index 0000000000000..def71e5def5d7 --- /dev/null +++ b/src/Symfony/Component/Serializer/Tests/Normalizer/ObjectToPopulateTraitTest.php @@ -0,0 +1,47 @@ +extractObjectToPopulate(ProxyDummy::class, array()); + + $this->assertNull($object); + } + + public function testExtractObjectToPopulateReturnsNullWhenNonObjectIsProvided() + { + $object = $this->extractObjectToPopulate(ProxyDummy::class, array( + 'object_to_populate' => 'not an object', + )); + + $this->assertNull($object); + } + + public function testExtractObjectToPopulateReturnsNullWhenTheClassIsNotAnInstanceOfTheProvidedClass() + { + $object = $this->extractObjectToPopulate(ProxyDummy::class, array( + 'object_to_populate' => new \stdClass(), + )); + + $this->assertNull($object); + } + + public function testExtractObjectToPopulateReturnsObjectWhenEverythingChecksOut() + { + $expected = new ProxyDummy(); + $object = $this->extractObjectToPopulate(ProxyDummy::class, array( + 'object_to_populate' => $expected, + )); + + $this->assertSame($expected, $object); + } +} From f7eb7972ff7eb9e844b771c061e0f9fe8cc56fa4 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Wed, 27 Sep 2017 10:32:40 -0700 Subject: [PATCH 0924/1099] fixed CS --- .../Serializer/Normalizer/ObjectToPopulateTrait.php | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/Symfony/Component/Serializer/Normalizer/ObjectToPopulateTrait.php b/src/Symfony/Component/Serializer/Normalizer/ObjectToPopulateTrait.php index f21100f014c6a..ac647889168bd 100644 --- a/src/Symfony/Component/Serializer/Normalizer/ObjectToPopulateTrait.php +++ b/src/Symfony/Component/Serializer/Normalizer/ObjectToPopulateTrait.php @@ -28,11 +28,7 @@ protected function extractObjectToPopulate($class, array $context, $key = null) { $key = $key ?: 'object_to_populate'; - if ( - isset($context[$key]) && - is_object($context[$key]) && - $context[$key] instanceof $class - ) { + if (isset($context[$key]) && is_object($context[$key]) && $context[$key] instanceof $class) { return $context[$key]; } From d43c1f7b6040732d6cd66b62b3bee9e70c43b088 Mon Sep 17 00:00:00 2001 From: Maxime Steinhausser Date: Wed, 27 Sep 2017 21:54:46 +0200 Subject: [PATCH 0925/1099] [SecurityBundle] Add missing AclSchemaListener deprecation --- .../Bundle/SecurityBundle/EventListener/AclSchemaListener.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Symfony/Bundle/SecurityBundle/EventListener/AclSchemaListener.php b/src/Symfony/Bundle/SecurityBundle/EventListener/AclSchemaListener.php index 8faa9ac366fd6..33d37fe2edb64 100644 --- a/src/Symfony/Bundle/SecurityBundle/EventListener/AclSchemaListener.php +++ b/src/Symfony/Bundle/SecurityBundle/EventListener/AclSchemaListener.php @@ -11,6 +11,8 @@ namespace Symfony\Bundle\SecurityBundle\EventListener; +@trigger_error(sprintf('Class "%s" is deprecated since version 3.4 and will be removed in 4.0. Use Symfony\Bundle\AclBundle\EventListener\SetAclCommand instead.', AclSchemaListener::class), E_USER_DEPRECATED); + use Symfony\Component\Security\Acl\Dbal\Schema; use Doctrine\ORM\Tools\Event\GenerateSchemaEventArgs; @@ -18,6 +20,8 @@ * Merges ACL schema into the given schema. * * @author Johannes M. Schmitt + * + * @deprecated since 3.4, to be removed in 4.0 */ class AclSchemaListener { From c8c3d42c7c5b52880a0ab7ad8df6b6f8aaa0396c Mon Sep 17 00:00:00 2001 From: Maxime Steinhausser Date: Wed, 27 Sep 2017 21:45:22 +0200 Subject: [PATCH 0926/1099] [SecurityBundle] Remove remaining ACL stuff from SecurityBundle --- .../DependencyInjection/MainConfiguration.php | 10 +--- .../EventListener/AclSchemaListener.php | 36 -------------- .../Resources/config/security_acl.xml | 35 ------------- .../Resources/config/security_acl_dbal.xml | 49 ------------------- .../Fixtures/php/custom_acl_provider.php | 9 ---- .../Fixtures/xml/custom_acl_provider.xml | 16 ------ .../Fixtures/yml/custom_acl_provider.yml | 6 --- .../Functional/Bundle/AclBundle/AclBundle.php | 21 -------- .../Bundle/AclBundle/Entity/Car.php | 22 --------- .../Tests/Functional/app/Acl/bundles.php | 17 ------- .../Tests/Functional/app/Acl/config.yml | 28 ----------- .../Tests/Functional/app/Acl/doctrine.yml | 5 -- .../Tests/Functional/app/AppKernel.php | 6 --- .../Bundle/SecurityBundle/composer.json | 4 -- 14 files changed, 1 insertion(+), 263 deletions(-) delete mode 100644 src/Symfony/Bundle/SecurityBundle/EventListener/AclSchemaListener.php delete mode 100644 src/Symfony/Bundle/SecurityBundle/Resources/config/security_acl.xml delete mode 100644 src/Symfony/Bundle/SecurityBundle/Resources/config/security_acl_dbal.xml delete mode 100644 src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/custom_acl_provider.php delete mode 100644 src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/custom_acl_provider.xml delete mode 100644 src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/custom_acl_provider.yml delete mode 100644 src/Symfony/Bundle/SecurityBundle/Tests/Functional/Bundle/AclBundle/AclBundle.php delete mode 100644 src/Symfony/Bundle/SecurityBundle/Tests/Functional/Bundle/AclBundle/Entity/Car.php delete mode 100644 src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/Acl/bundles.php delete mode 100644 src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/Acl/config.yml delete mode 100644 src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/Acl/doctrine.yml diff --git a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/MainConfiguration.php b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/MainConfiguration.php index 078817b3be97e..5288de97b1bdb 100644 --- a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/MainConfiguration.php +++ b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/MainConfiguration.php @@ -19,15 +19,7 @@ use Symfony\Component\Security\Http\Session\SessionAuthenticationStrategy; /** - * This class contains the configuration information. - * - * This information is for the following tags: - * - * * security.config - * * security.acl - * - * This information is solely responsible for how the different configuration - * sections are normalized, and merged. + * SecurityExtension configuration structure. * * @author Johannes M. Schmitt */ diff --git a/src/Symfony/Bundle/SecurityBundle/EventListener/AclSchemaListener.php b/src/Symfony/Bundle/SecurityBundle/EventListener/AclSchemaListener.php deleted file mode 100644 index 8faa9ac366fd6..0000000000000 --- a/src/Symfony/Bundle/SecurityBundle/EventListener/AclSchemaListener.php +++ /dev/null @@ -1,36 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\SecurityBundle\EventListener; - -use Symfony\Component\Security\Acl\Dbal\Schema; -use Doctrine\ORM\Tools\Event\GenerateSchemaEventArgs; - -/** - * Merges ACL schema into the given schema. - * - * @author Johannes M. Schmitt - */ -class AclSchemaListener -{ - private $schema; - - public function __construct(Schema $schema) - { - $this->schema = $schema; - } - - public function postGenerateSchema(GenerateSchemaEventArgs $args) - { - $schema = $args->getSchema(); - $this->schema->addToSchema($schema); - } -} diff --git a/src/Symfony/Bundle/SecurityBundle/Resources/config/security_acl.xml b/src/Symfony/Bundle/SecurityBundle/Resources/config/security_acl.xml deleted file mode 100644 index 68418dadff1c9..0000000000000 --- a/src/Symfony/Bundle/SecurityBundle/Resources/config/security_acl.xml +++ /dev/null @@ -1,35 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/Symfony/Bundle/SecurityBundle/Resources/config/security_acl_dbal.xml b/src/Symfony/Bundle/SecurityBundle/Resources/config/security_acl_dbal.xml deleted file mode 100644 index c1ed332654fe0..0000000000000 --- a/src/Symfony/Bundle/SecurityBundle/Resources/config/security_acl_dbal.xml +++ /dev/null @@ -1,49 +0,0 @@ - - - - - - - - - - - - - - %security.acl.dbal.class_table_name% - %security.acl.dbal.entry_table_name% - %security.acl.dbal.oid_table_name% - %security.acl.dbal.oid_ancestors_table_name% - %security.acl.dbal.sid_table_name% - - - - - - - %security.acl.dbal.class_table_name% - %security.acl.dbal.entry_table_name% - %security.acl.dbal.oid_table_name% - %security.acl.dbal.oid_ancestors_table_name% - %security.acl.dbal.sid_table_name% - - - - - - - - - - - - - - - - - - diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/custom_acl_provider.php b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/custom_acl_provider.php deleted file mode 100644 index 351dc6c09e1a6..0000000000000 --- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/custom_acl_provider.php +++ /dev/null @@ -1,9 +0,0 @@ -load('container1.php', $container); - -$container->loadFromExtension('security', array( - 'acl' => array( - 'provider' => 'foo', - ), -)); diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/custom_acl_provider.xml b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/custom_acl_provider.xml deleted file mode 100644 index 6addc81668253..0000000000000 --- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/custom_acl_provider.xml +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - - - - - - diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/custom_acl_provider.yml b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/custom_acl_provider.yml deleted file mode 100644 index 633eed00e3418..0000000000000 --- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/custom_acl_provider.yml +++ /dev/null @@ -1,6 +0,0 @@ -imports: - - { resource: container1.yml } - -security: - acl: - provider: foo diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/Bundle/AclBundle/AclBundle.php b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/Bundle/AclBundle/AclBundle.php deleted file mode 100644 index 1208003bcc2c4..0000000000000 --- a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/Bundle/AclBundle/AclBundle.php +++ /dev/null @@ -1,21 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\SecurityBundle\Tests\Functional\Bundle\AclBundle; - -use Symfony\Component\HttpKernel\Bundle\Bundle; - -/** - * @author Kévin Dunglas - */ -class AclBundle extends Bundle -{ -} diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/Bundle/AclBundle/Entity/Car.php b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/Bundle/AclBundle/Entity/Car.php deleted file mode 100644 index c85a589578ec5..0000000000000 --- a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/Bundle/AclBundle/Entity/Car.php +++ /dev/null @@ -1,22 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bundle\SecurityBundle\Tests\Functional\Bundle\AclBundle\Entity; - -/** - * Car. - * - * @author Kévin Dunglas - */ -class Car -{ - public $id; -} diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/Acl/bundles.php b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/Acl/bundles.php deleted file mode 100644 index 51337913d5370..0000000000000 --- a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/Acl/bundles.php +++ /dev/null @@ -1,17 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -return array( - new Doctrine\Bundle\DoctrineBundle\DoctrineBundle(), - new Symfony\Bundle\SecurityBundle\SecurityBundle(), - new Symfony\Bundle\FrameworkBundle\FrameworkBundle(), - new Symfony\Bundle\SecurityBundle\Tests\Functional\Bundle\AclBundle\AclBundle(), -); diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/Acl/config.yml b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/Acl/config.yml deleted file mode 100644 index 45f8e24d4f81e..0000000000000 --- a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/Acl/config.yml +++ /dev/null @@ -1,28 +0,0 @@ -imports: - - { resource: ./../config/framework.yml } - -services: - _defaults: { public: true } - test.security.acl.provider: '@security.acl.provider' - -doctrine: - dbal: - driver: pdo_sqlite - memory: true - charset: UTF8 - -security: - firewalls: - test: - pattern: ^/ - security: false - acl: - connection: default - encoders: - Symfony\Component\Security\Core\User\User: plaintext - providers: - in_memory: - memory: - users: - kevin: { password: test, roles: [ROLE_USER] } - anne: { password: test, roles: [ROLE_ADMIN]} diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/Acl/doctrine.yml b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/Acl/doctrine.yml deleted file mode 100644 index 7a12388398f76..0000000000000 --- a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/Acl/doctrine.yml +++ /dev/null @@ -1,5 +0,0 @@ -# to be removed once https://github.com/doctrine/DoctrineBundle/pull/684 is merged -services: - Doctrine\Bundle\DoctrineBundle\Command\: - resource: "@DoctrineBundle/Command/*" - tags: [console.command] diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/AppKernel.php b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/AppKernel.php index 82c8ad4aa6c60..1aab514f45450 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/AppKernel.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/AppKernel.php @@ -11,7 +11,6 @@ namespace Symfony\Bundle\SecurityBundle\Tests\Functional\app; -use Doctrine\ORM\Version; use Symfony\Component\Config\Loader\LoaderInterface; use Symfony\Component\Filesystem\Filesystem; use Symfony\Component\HttpKernel\Kernel; @@ -83,11 +82,6 @@ public function getLogDir() public function registerContainerConfiguration(LoaderInterface $loader) { $loader->load($this->rootConfig); - - // to be removed once https://github.com/doctrine/DoctrineBundle/pull/684 is merged - if ('Acl' === $this->testCase && class_exists(Version::class)) { - $loader->load(__DIR__.'/Acl/doctrine.yml'); - } } public function serialize() diff --git a/src/Symfony/Bundle/SecurityBundle/composer.json b/src/Symfony/Bundle/SecurityBundle/composer.json index c5d6f7f103f53..d31285e66a0ee 100644 --- a/src/Symfony/Bundle/SecurityBundle/composer.json +++ b/src/Symfony/Bundle/SecurityBundle/composer.json @@ -32,7 +32,6 @@ "symfony/form": "~3.4|~4.0", "symfony/framework-bundle": "~3.4|~4.0", "symfony/http-foundation": "~3.4|~4.0", - "symfony/security-acl": "~2.8|~3.0", "symfony/translation": "~3.4|~4.0", "symfony/twig-bundle": "~3.4|~4.0", "symfony/twig-bridge": "~3.4|~4.0", @@ -50,9 +49,6 @@ "symfony/framework-bundle": "<3.4", "symfony/console": "<3.4" }, - "suggest": { - "symfony/security-acl": "For using the ACL functionality of this bundle" - }, "autoload": { "psr-4": { "Symfony\\Bundle\\SecurityBundle\\": "" }, "exclude-from-classmap": [ From 5b4308e9e1d870d0e2a7d4b931299b1e20669b7d Mon Sep 17 00:00:00 2001 From: Maxime Steinhausser Date: Wed, 27 Sep 2017 23:22:30 +0200 Subject: [PATCH 0927/1099] [Routing] Enhance Route(Collection) docblocks --- src/Symfony/Component/Routing/Route.php | 28 +++++++++---------- .../Component/Routing/RouteCollection.php | 6 ++-- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/src/Symfony/Component/Routing/Route.php b/src/Symfony/Component/Routing/Route.php index fee2002c9d9bb..d6f3906a0f939 100644 --- a/src/Symfony/Component/Routing/Route.php +++ b/src/Symfony/Component/Routing/Route.php @@ -30,12 +30,12 @@ class Route implements \Serializable private $host = ''; /** - * @var array + * @var string[] */ private $schemes = array(); /** - * @var array + * @var string[] */ private $methods = array(); @@ -71,14 +71,14 @@ class Route implements \Serializable * * * compiler_class: A class name able to compile this route instance (RouteCompiler by default) * - * @param string $path The path pattern to match - * @param array $defaults An array of default parameter values - * @param array $requirements An array of requirements for parameters (regexes) - * @param array $options An array of options - * @param string $host The host pattern to match - * @param string|array $schemes A required URI scheme or an array of restricted schemes - * @param string|array $methods A required HTTP method or an array of restricted methods - * @param string $condition A condition that should evaluate to true for the route to match + * @param string $path The path pattern to match + * @param array $defaults An array of default parameter values + * @param array $requirements An array of requirements for parameters (regexes) + * @param array $options An array of options + * @param string $host The host pattern to match + * @param string|string[] $schemes A required URI scheme or an array of restricted schemes + * @param string|string[] $methods A required HTTP method or an array of restricted methods + * @param string $condition A condition that should evaluate to true for the route to match */ public function __construct($path, array $defaults = array(), array $requirements = array(), array $options = array(), $host = '', $schemes = array(), $methods = array(), $condition = '') { @@ -230,7 +230,7 @@ public function setHost($pattern) * Returns the lowercased schemes this route is restricted to. * So an empty array means that any scheme is allowed. * - * @return array The schemes + * @return string[] The schemes */ public function getSchemes() { @@ -243,7 +243,7 @@ public function getSchemes() * * This method implements a fluent interface. * - * @param string|array $schemes The scheme or an array of schemes + * @param string|string[] $schemes The scheme or an array of schemes * * @return $this */ @@ -279,7 +279,7 @@ public function hasScheme($scheme) * Returns the uppercased HTTP methods this route is restricted to. * So an empty array means that any method is allowed. * - * @return array The methods + * @return string[] The methods */ public function getMethods() { @@ -292,7 +292,7 @@ public function getMethods() * * This method implements a fluent interface. * - * @param string|array $methods The method or an array of methods + * @param string|string[] $methods The method or an array of methods * * @return $this */ diff --git a/src/Symfony/Component/Routing/RouteCollection.php b/src/Symfony/Component/Routing/RouteCollection.php index 2ccb90f3b0966..f8b18084be126 100644 --- a/src/Symfony/Component/Routing/RouteCollection.php +++ b/src/Symfony/Component/Routing/RouteCollection.php @@ -104,7 +104,7 @@ public function get($name) /** * Removes a route or an array of routes by name from the collection. * - * @param string|array $name The route name or an array of route names + * @param string|string[] $name The route name or an array of route names */ public function remove($name) { @@ -234,7 +234,7 @@ public function addOptions(array $options) /** * Sets the schemes (e.g. 'https') all child routes are restricted to. * - * @param string|array $schemes The scheme or an array of schemes + * @param string|string[] $schemes The scheme or an array of schemes */ public function setSchemes($schemes) { @@ -246,7 +246,7 @@ public function setSchemes($schemes) /** * Sets the HTTP methods (e.g. 'POST') all child routes are restricted to. * - * @param string|array $methods The method or an array of methods + * @param string|string[] $methods The method or an array of methods */ public function setMethods($methods) { From eebe39e600c68971ec78255b16b65995d2bb49dc Mon Sep 17 00:00:00 2001 From: Robin Chalas Date: Wed, 27 Sep 2017 23:42:53 +0200 Subject: [PATCH 0928/1099] Fix AclSchemaListener deprecation --- .../Bundle/SecurityBundle/EventListener/AclSchemaListener.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Bundle/SecurityBundle/EventListener/AclSchemaListener.php b/src/Symfony/Bundle/SecurityBundle/EventListener/AclSchemaListener.php index 33d37fe2edb64..6441fbba6275e 100644 --- a/src/Symfony/Bundle/SecurityBundle/EventListener/AclSchemaListener.php +++ b/src/Symfony/Bundle/SecurityBundle/EventListener/AclSchemaListener.php @@ -11,7 +11,7 @@ namespace Symfony\Bundle\SecurityBundle\EventListener; -@trigger_error(sprintf('Class "%s" is deprecated since version 3.4 and will be removed in 4.0. Use Symfony\Bundle\AclBundle\EventListener\SetAclCommand instead.', AclSchemaListener::class), E_USER_DEPRECATED); +@trigger_error(sprintf('Class "%s" is deprecated since version 3.4 and will be removed in 4.0. Use Symfony\Bundle\AclBundle\EventListener\AclSchemaListener instead.', AclSchemaListener::class), E_USER_DEPRECATED); use Symfony\Component\Security\Acl\Dbal\Schema; use Doctrine\ORM\Tools\Event\GenerateSchemaEventArgs; From 7d749bfb7743991ddc35b93cce1876bfe441ada5 Mon Sep 17 00:00:00 2001 From: Maxime Steinhausser Date: Wed, 27 Sep 2017 19:08:26 +0200 Subject: [PATCH 0929/1099] [Routing] Enhance PHP DSL traits docblocks --- .../Routing/Loader/Configurator/Traits/AddTrait.php | 2 +- .../Routing/Loader/Configurator/Traits/RouteTrait.php | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Symfony/Component/Routing/Loader/Configurator/Traits/AddTrait.php b/src/Symfony/Component/Routing/Loader/Configurator/Traits/AddTrait.php index abaf868c9c698..7171fd241f6d0 100644 --- a/src/Symfony/Component/Routing/Loader/Configurator/Traits/AddTrait.php +++ b/src/Symfony/Component/Routing/Loader/Configurator/Traits/AddTrait.php @@ -28,7 +28,7 @@ trait AddTrait * Adds a route. * * @param string $name - * @param string $value + * @param string $path * * @return RouteConfigurator */ diff --git a/src/Symfony/Component/Routing/Loader/Configurator/Traits/RouteTrait.php b/src/Symfony/Component/Routing/Loader/Configurator/Traits/RouteTrait.php index 8eb3276500d89..a40cd16a5b2e5 100644 --- a/src/Symfony/Component/Routing/Loader/Configurator/Traits/RouteTrait.php +++ b/src/Symfony/Component/Routing/Loader/Configurator/Traits/RouteTrait.php @@ -95,7 +95,7 @@ final public function host($pattern) * Sets the schemes (e.g. 'https') this route is restricted to. * So an empty array means that any scheme is allowed. * - * @param array $schemes + * @param string[] $schemes * * @return $this */ @@ -110,7 +110,7 @@ final public function schemes(array $schemes) * Sets the HTTP methods (e.g. 'POST') this route is restricted to. * So an empty array means that any method is allowed. * - * @param array $methods + * @param string[] $methods * * @return $this */ @@ -124,7 +124,7 @@ final public function methods(array $methods) /** * Adds the "_controller" entry to defaults. * - * @param callable $controller a callable or parseable pseudo-callable + * @param callable|string $controller a callable or parseable pseudo-callable * * @return $this */ From fbe71480005c34d7f7768baca9b6fe7cd8597752 Mon Sep 17 00:00:00 2001 From: darnel Date: Thu, 28 Sep 2017 08:55:08 +0200 Subject: [PATCH 0930/1099] Fix translation for "This field was not expected" Update validators.cs.xlf - Fix czech translation for "This field was not expected" --- .../Validator/Resources/translations/validators.cs.xlf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.cs.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.cs.xlf index ba6853be90dfe..67957d845d2f6 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.cs.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.cs.xlf @@ -36,7 +36,7 @@ This field was not expected. - Toto pole nebyla očekávána. + Toto pole nebylo očekáváno. This field is missing. From 0a7e5b0d0962fce41797ec536abfe4b73acfdfe3 Mon Sep 17 00:00:00 2001 From: Maxime Steinhausser Date: Wed, 27 Sep 2017 19:31:27 +0200 Subject: [PATCH 0931/1099] [DI] Fix missing use + minor tweaks --- .../Configurator/AbstractConfigurator.php | 31 +++++-------------- .../AbstractServiceConfigurator.php | 5 ++- .../Configurator/ReferenceConfigurator.php | 9 ++++-- .../Configurator/Traits/AbstractTrait.php | 2 -- .../Traits/AutoconfigureTrait.php | 1 + .../Configurator/Traits/DeprecateTrait.php | 1 - .../Loader/Configurator/Traits/TagTrait.php | 1 - .../services_autoconfigure_with_parent.php | 9 ++++++ .../Tests/Loader/PhpFileLoaderTest.php | 13 ++++++++ 9 files changed, 39 insertions(+), 33 deletions(-) create mode 100644 src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/services_autoconfigure_with_parent.php diff --git a/src/Symfony/Component/DependencyInjection/Loader/Configurator/AbstractConfigurator.php b/src/Symfony/Component/DependencyInjection/Loader/Configurator/AbstractConfigurator.php index 2c4538e20144a..73ca320e31247 100644 --- a/src/Symfony/Component/DependencyInjection/Loader/Configurator/AbstractConfigurator.php +++ b/src/Symfony/Component/DependencyInjection/Loader/Configurator/AbstractConfigurator.php @@ -22,6 +22,9 @@ abstract class AbstractConfigurator { const FACTORY = 'unknown'; + /** @internal */ + protected $definition; + public function __call($method, $args) { if (method_exists($this, 'set'.$method)) { @@ -37,7 +40,7 @@ public function __call($method, $args) * @param mixed $value * @param bool $allowServices whether Definition and Reference are allowed; by default, only scalars and arrays are * - * @return mixed the value, optionaly cast to a Definition/Reference + * @return mixed the value, optionally cast to a Definition/Reference */ public static function processValue($value, $allowServices = false) { @@ -50,32 +53,14 @@ public static function processValue($value, $allowServices = false) } if ($value instanceof ReferenceConfigurator) { - static $refCast; - - if (!$refCast) { - $refCast = \Closure::bind(function ($value) { - return new Reference($value->id, $value->invalidBehavior); - }, null, $value); - } - - // cast ReferenceConfigurator to Reference - return $refCast($value); + return new Reference($value->id, $value->invalidBehavior); } if ($value instanceof InlineServiceConfigurator) { - static $defCast; - - if (!$defCast) { - $defCast = \Closure::bind(function ($value) { - $def = $value->definition; - $value->definition = null; - - return $def; - }, null, $value); - } + $def = $value->definition; + $value->definition = null; - // cast InlineServiceConfigurator to Definition - return $defCast($value); + return $def; } if ($value instanceof self) { diff --git a/src/Symfony/Component/DependencyInjection/Loader/Configurator/AbstractServiceConfigurator.php b/src/Symfony/Component/DependencyInjection/Loader/Configurator/AbstractServiceConfigurator.php index 72ca7320b9f69..40b6c2f389723 100644 --- a/src/Symfony/Component/DependencyInjection/Loader/Configurator/AbstractServiceConfigurator.php +++ b/src/Symfony/Component/DependencyInjection/Loader/Configurator/AbstractServiceConfigurator.php @@ -17,9 +17,8 @@ abstract class AbstractServiceConfigurator extends AbstractConfigurator { protected $parent; - protected $definition; protected $id; - protected $defaultTags = array(); + private $defaultTags = array(); public function __construct(ServicesConfigurator $parent, Definition $definition, $id = null, array $defaultTags = array()) { @@ -59,7 +58,7 @@ final public function set($id, $class = null) * Creates an alias. * * @param string $id - * @param string $ref + * @param string $referencedId * * @return AliasConfigurator */ diff --git a/src/Symfony/Component/DependencyInjection/Loader/Configurator/ReferenceConfigurator.php b/src/Symfony/Component/DependencyInjection/Loader/Configurator/ReferenceConfigurator.php index 93fdf3960e0dd..1585c0872a694 100644 --- a/src/Symfony/Component/DependencyInjection/Loader/Configurator/ReferenceConfigurator.php +++ b/src/Symfony/Component/DependencyInjection/Loader/Configurator/ReferenceConfigurator.php @@ -16,10 +16,13 @@ /** * @author Nicolas Grekas */ -class ReferenceConfigurator +class ReferenceConfigurator extends AbstractConfigurator { - private $id; - private $invalidBehavior = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE; + /** @internal */ + protected $id; + + /** @internal */ + protected $invalidBehavior = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE; public function __construct($id) { diff --git a/src/Symfony/Component/DependencyInjection/Loader/Configurator/Traits/AbstractTrait.php b/src/Symfony/Component/DependencyInjection/Loader/Configurator/Traits/AbstractTrait.php index 47e0dee287e0e..f69a7a5be109d 100644 --- a/src/Symfony/Component/DependencyInjection/Loader/Configurator/Traits/AbstractTrait.php +++ b/src/Symfony/Component/DependencyInjection/Loader/Configurator/Traits/AbstractTrait.php @@ -11,8 +11,6 @@ namespace Symfony\Component\DependencyInjection\Loader\Configurator\Traits; -use Symfony\Component\DependencyInjection\Definition; - /** * @method $this abstract(bool $abstract = true) */ diff --git a/src/Symfony/Component/DependencyInjection/Loader/Configurator/Traits/AutoconfigureTrait.php b/src/Symfony/Component/DependencyInjection/Loader/Configurator/Traits/AutoconfigureTrait.php index e3dccc9656951..42a692353e9dc 100644 --- a/src/Symfony/Component/DependencyInjection/Loader/Configurator/Traits/AutoconfigureTrait.php +++ b/src/Symfony/Component/DependencyInjection/Loader/Configurator/Traits/AutoconfigureTrait.php @@ -11,6 +11,7 @@ namespace Symfony\Component\DependencyInjection\Loader\Configurator\Traits; +use Symfony\Component\DependencyInjection\ChildDefinition; use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; trait AutoconfigureTrait diff --git a/src/Symfony/Component/DependencyInjection/Loader/Configurator/Traits/DeprecateTrait.php b/src/Symfony/Component/DependencyInjection/Loader/Configurator/Traits/DeprecateTrait.php index 331be473e216c..b14a6557eee96 100644 --- a/src/Symfony/Component/DependencyInjection/Loader/Configurator/Traits/DeprecateTrait.php +++ b/src/Symfony/Component/DependencyInjection/Loader/Configurator/Traits/DeprecateTrait.php @@ -11,7 +11,6 @@ namespace Symfony\Component\DependencyInjection\Loader\Configurator\Traits; -use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; trait DeprecateTrait diff --git a/src/Symfony/Component/DependencyInjection/Loader/Configurator/Traits/TagTrait.php b/src/Symfony/Component/DependencyInjection/Loader/Configurator/Traits/TagTrait.php index 4094acdbfce91..aeb8b047d428e 100644 --- a/src/Symfony/Component/DependencyInjection/Loader/Configurator/Traits/TagTrait.php +++ b/src/Symfony/Component/DependencyInjection/Loader/Configurator/Traits/TagTrait.php @@ -11,7 +11,6 @@ namespace Symfony\Component\DependencyInjection\Loader\Configurator\Traits; -use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; trait TagTrait diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/services_autoconfigure_with_parent.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/services_autoconfigure_with_parent.php new file mode 100644 index 0000000000000..f8ffb1dee992c --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/services_autoconfigure_with_parent.php @@ -0,0 +1,9 @@ +services() + ->set('parent_service', \stdClass::class) + ->set('child_service')->parent('parent_service')->autoconfigure(true); +}; diff --git a/src/Symfony/Component/DependencyInjection/Tests/Loader/PhpFileLoaderTest.php b/src/Symfony/Component/DependencyInjection/Tests/Loader/PhpFileLoaderTest.php index 02f84311e689c..a8f10d9ef0461 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Loader/PhpFileLoaderTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Loader/PhpFileLoaderTest.php @@ -76,4 +76,17 @@ public function provideConfig() yield array('php7'); } } + + /** + * @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException + * @expectedExceptionMessage The service "child_service" cannot have a "parent" and also have "autoconfigure". Try disabling autoconfiguration for the service. + */ + public function testAutoConfigureAndChildDefinitionNotAllowed() + { + $fixtures = realpath(__DIR__.'/../Fixtures'); + $container = new ContainerBuilder(); + $loader = new PhpFileLoader($container, new FileLocator()); + $loader->load($fixtures.'/config/services_autoconfigure_with_parent.php'); + $container->compile(); + } } From f618e43234f3ce483db04479fde9f7cbd88dafb0 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Thu, 28 Sep 2017 12:45:51 +0200 Subject: [PATCH 0932/1099] include file and line no in deprecation message --- src/Symfony/Component/Yaml/Inline.php | 43 +++++++++++++------ src/Symfony/Component/Yaml/Parser.php | 27 +++++++++--- .../Component/Yaml/Tests/ParserTest.php | 14 +++--- 3 files changed, 56 insertions(+), 28 deletions(-) diff --git a/src/Symfony/Component/Yaml/Inline.php b/src/Symfony/Component/Yaml/Inline.php index b1653137fc135..9f868f2744a44 100644 --- a/src/Symfony/Component/Yaml/Inline.php +++ b/src/Symfony/Component/Yaml/Inline.php @@ -348,7 +348,7 @@ public static function parseScalar($scalar, $flags = 0, $delimiters = null, &$i } if ($output && '%' === $output[0]) { - @trigger_error(sprintf('Not quoting the scalar "%s" starting with the "%%" indicator character is deprecated since Symfony 3.1 and will throw a ParseException in 4.0.', $output), E_USER_DEPRECATED); + @trigger_error(self::getDeprecationMessage(sprintf('Not quoting the scalar "%s" starting with the "%%" indicator character is deprecated since Symfony 3.1 and will throw a ParseException in 4.0.', $output)), E_USER_DEPRECATED); } if ($evaluate) { @@ -500,19 +500,19 @@ private static function parseMapping($mapping, $flags, &$i = 0, $references = ar } if (':' === $key) { - @trigger_error('Omitting the key of a mapping is deprecated and will throw a ParseException in 4.0.', E_USER_DEPRECATED); + @trigger_error(self::getDeprecationMessage('Omitting the key of a mapping is deprecated and will throw a ParseException in 4.0.'), E_USER_DEPRECATED); } if (!$isKeyQuoted) { $evaluatedKey = self::evaluateScalar($key, $flags, $references); if ('' !== $key && $evaluatedKey !== $key && !is_string($evaluatedKey) && !is_int($evaluatedKey)) { - @trigger_error('Implicit casting of incompatible mapping keys to strings is deprecated since version 3.3 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0. Quote your evaluable mapping keys instead.', E_USER_DEPRECATED); + @trigger_error(self::getDeprecationMessage('Implicit casting of incompatible mapping keys to strings is deprecated since version 3.3 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0. Quote your evaluable mapping keys instead.'), E_USER_DEPRECATED); } } if (':' !== $key && !$isKeyQuoted && (!isset($mapping[$i + 1]) || !in_array($mapping[$i + 1], array(' ', ',', '[', ']', '{', '}'), true))) { - @trigger_error('Using a colon after an unquoted mapping key that is not followed by an indication character (i.e. " ", ",", "[", "]", "{", "}") is deprecated since version 3.2 and will throw a ParseException in 4.0.', E_USER_DEPRECATED); + @trigger_error(self::getDeprecationMessage('Using a colon after an unquoted mapping key that is not followed by an indication character (i.e. " ", ",", "[", "]", "{", "}") is deprecated since version 3.2 and will throw a ParseException in 4.0.'), E_USER_DEPRECATED); } while ($i < $len) { @@ -532,7 +532,7 @@ private static function parseMapping($mapping, $flags, &$i = 0, $references = ar // Parser cannot abort this mapping earlier, since lines // are processed sequentially. if (isset($output[$key])) { - @trigger_error(sprintf('Duplicate key "%s" detected whilst parsing YAML. Silent handling of duplicate mapping keys in YAML is deprecated since version 3.2 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0.', $key), E_USER_DEPRECATED); + @trigger_error(self::getDeprecationMessage(sprintf('Duplicate key "%s" detected whilst parsing YAML. Silent handling of duplicate mapping keys in YAML is deprecated since version 3.2 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0.', $key)), E_USER_DEPRECATED); $duplicate = true; } break; @@ -543,7 +543,7 @@ private static function parseMapping($mapping, $flags, &$i = 0, $references = ar // Parser cannot abort this mapping earlier, since lines // are processed sequentially. if (isset($output[$key])) { - @trigger_error(sprintf('Duplicate key "%s" detected whilst parsing YAML. Silent handling of duplicate mapping keys in YAML is deprecated since version 3.2 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0.', $key), E_USER_DEPRECATED); + @trigger_error(self::getDeprecationMessage(sprintf('Duplicate key "%s" detected whilst parsing YAML. Silent handling of duplicate mapping keys in YAML is deprecated since version 3.2 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0.', $key)), E_USER_DEPRECATED); $duplicate = true; } break; @@ -553,7 +553,7 @@ private static function parseMapping($mapping, $flags, &$i = 0, $references = ar // Parser cannot abort this mapping earlier, since lines // are processed sequentially. if (isset($output[$key])) { - @trigger_error(sprintf('Duplicate key "%s" detected whilst parsing YAML. Silent handling of duplicate mapping keys in YAML is deprecated since version 3.2 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0.', $key), E_USER_DEPRECATED); + @trigger_error(self::getDeprecationMessage(sprintf('Duplicate key "%s" detected whilst parsing YAML. Silent handling of duplicate mapping keys in YAML is deprecated since version 3.2 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0.', $key)), E_USER_DEPRECATED); $duplicate = true; } --$i; @@ -622,18 +622,18 @@ private static function evaluateScalar($scalar, $flags, $references = array()) case '!' === $scalar[0]: switch (true) { case 0 === strpos($scalar, '!str'): - @trigger_error('Support for the !str tag is deprecated since version 3.4. Use the !!str tag instead.', E_USER_DEPRECATED); + @trigger_error(self::getDeprecationMessage('Support for the !str tag is deprecated since version 3.4. Use the !!str tag instead.'), E_USER_DEPRECATED); return (string) substr($scalar, 5); case 0 === strpos($scalar, '!!str '): return (string) substr($scalar, 6); case 0 === strpos($scalar, '! '): - @trigger_error('Using the non-specific tag "!" is deprecated since version 3.4 as its behavior will change in 4.0. It will force non-evaluating your values in 4.0. Use plain integers or !!float instead.', E_USER_DEPRECATED); + @trigger_error(self::getDeprecationMessage('Using the non-specific tag "!" is deprecated since version 3.4 as its behavior will change in 4.0. It will force non-evaluating your values in 4.0. Use plain integers or !!float instead.'), E_USER_DEPRECATED); return (int) self::parseScalar(substr($scalar, 2), $flags); case 0 === strpos($scalar, '!php/object:'): if (self::$objectSupport) { - @trigger_error('The !php/object: tag to indicate dumped PHP objects is deprecated since version 3.4 and will be removed in 4.0. Use the !php/object (without the colon) tag instead.', E_USER_DEPRECATED); + @trigger_error(self::getDeprecationMessage('The !php/object: tag to indicate dumped PHP objects is deprecated since version 3.4 and will be removed in 4.0. Use the !php/object (without the colon) tag instead.'), E_USER_DEPRECATED); return unserialize(substr($scalar, 12)); } @@ -645,7 +645,7 @@ private static function evaluateScalar($scalar, $flags, $references = array()) return; case 0 === strpos($scalar, '!!php/object:'): if (self::$objectSupport) { - @trigger_error('The !!php/object: tag to indicate dumped PHP objects is deprecated since version 3.1 and will be removed in 4.0. Use the !php/object (without the colon) tag instead.', E_USER_DEPRECATED); + @trigger_error(self::getDeprecationMessage('The !!php/object: tag to indicate dumped PHP objects is deprecated since version 3.1 and will be removed in 4.0. Use the !php/object (without the colon) tag instead.'), E_USER_DEPRECATED); return unserialize(substr($scalar, 13)); } @@ -667,7 +667,7 @@ private static function evaluateScalar($scalar, $flags, $references = array()) return; case 0 === strpos($scalar, '!php/const:'): if (self::$constantSupport) { - @trigger_error('The !php/const: tag to indicate dumped PHP constants is deprecated since version 3.4 and will be removed in 4.0. Use the !php/const (without the colon) tag instead.', E_USER_DEPRECATED); + @trigger_error(self::getDeprecationMessage('The !php/const: tag to indicate dumped PHP constants is deprecated since version 3.4 and will be removed in 4.0. Use the !php/const (without the colon) tag instead.'), E_USER_DEPRECATED); if (defined($const = substr($scalar, 11))) { return constant($const); @@ -698,7 +698,7 @@ private static function evaluateScalar($scalar, $flags, $references = array()) case 0 === strpos($scalar, '!!binary '): return self::evaluateBinaryScalar(substr($scalar, 9)); default: - @trigger_error(sprintf('Using the unquoted scalar value "%s" is deprecated since version 3.3 and will be considered as a tagged value in 4.0. You must quote it.', $scalar), E_USER_DEPRECATED); + @trigger_error(self::getDeprecationMessage(sprintf('Using the unquoted scalar value "%s" is deprecated since version 3.3 and will be considered as a tagged value in 4.0. You must quote it.', $scalar)), E_USER_DEPRECATED); } // Optimize for returning strings. @@ -732,7 +732,7 @@ private static function evaluateScalar($scalar, $flags, $references = array()) case Parser::preg_match('/^(-|\+)?[0-9][0-9,]*(\.[0-9_]+)?$/', $scalar): case Parser::preg_match('/^(-|\+)?[0-9][0-9_]*(\.[0-9_]+)?$/', $scalar): if (false !== strpos($scalar, ',')) { - @trigger_error('Using the comma as a group separator for floats is deprecated since version 3.2 and will be removed in 4.0.', E_USER_DEPRECATED); + @trigger_error(self::getDeprecationMessage('Using the comma as a group separator for floats is deprecated since version 3.2 and will be removed in 4.0.'), E_USER_DEPRECATED); } return (float) str_replace(array(',', '_'), '', $scalar); @@ -854,4 +854,19 @@ private static function getHexRegex() { return '~^0x[0-9a-f_]++$~i'; } + + private static function getDeprecationMessage($message) + { + $message = rtrim($message, '.'); + + if (null !== self::$parsedFilename) { + $message .= ' in '.self::$parsedFilename; + } + + if (-1 !== self::$parsedLineNumber) { + $message .= ' on line '.self::$parsedLineNumber; + } + + return $message.'.'; + } } diff --git a/src/Symfony/Component/Yaml/Parser.php b/src/Symfony/Component/Yaml/Parser.php index be1c13cddbf98..af4cb3fbe4280 100644 --- a/src/Symfony/Component/Yaml/Parser.php +++ b/src/Symfony/Component/Yaml/Parser.php @@ -214,7 +214,7 @@ private function doParse($value, $flags) } if (isset($values['value'][1]) && '?' === $values['value'][0] && ' ' === $values['value'][1]) { - @trigger_error('Starting an unquoted string with a question mark followed by a space is deprecated since version 3.3 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0.', E_USER_DEPRECATED); + @trigger_error($this->getDeprecationMessage('Starting an unquoted string with a question mark followed by a space is deprecated since version 3.3 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0.'), E_USER_DEPRECATED); } // array @@ -272,7 +272,7 @@ private function doParse($value, $flags) if (!is_string($key) && !is_int($key)) { $keyType = is_numeric($key) ? 'numeric key' : 'non-string key'; - @trigger_error(sprintf('Implicit casting of %s to string is deprecated since version 3.3 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0. Quote your evaluable mapping keys instead.', $keyType), E_USER_DEPRECATED); + @trigger_error($this->getDeprecationMessage(sprintf('Implicit casting of %s to string is deprecated since version 3.3 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0. Quote your evaluable mapping keys instead.', $keyType)), E_USER_DEPRECATED); } // Convert float keys to strings, to avoid being converted to integers by PHP @@ -346,7 +346,7 @@ private function doParse($value, $flags) $data[$key] = null; } } else { - @trigger_error(sprintf('Duplicate key "%s" detected whilst parsing YAML. Silent handling of duplicate mapping keys in YAML is deprecated since version 3.2 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0.', $key), E_USER_DEPRECATED); + @trigger_error($this->getDeprecationMessage(sprintf('Duplicate key "%s" detected whilst parsing YAML. Silent handling of duplicate mapping keys in YAML is deprecated since version 3.2 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0.', $key)), E_USER_DEPRECATED); } } else { // remember the parsed line number here in case we need it to provide some contexts in error messages below @@ -361,7 +361,7 @@ private function doParse($value, $flags) $data[$key] = $value; } } else { - @trigger_error(sprintf('Duplicate key "%s" detected whilst parsing YAML. Silent handling of duplicate mapping keys in YAML is deprecated since version 3.2 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0.', $key), E_USER_DEPRECATED); + @trigger_error($this->getDeprecationMessage(sprintf('Duplicate key "%s" detected whilst parsing YAML. Silent handling of duplicate mapping keys in YAML is deprecated since version 3.2 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0.', $key)), E_USER_DEPRECATED); } } } else { @@ -371,7 +371,7 @@ private function doParse($value, $flags) if ($allowOverwrite || !isset($data[$key])) { $data[$key] = $value; } else { - @trigger_error(sprintf('Duplicate key "%s" detected whilst parsing YAML. Silent handling of duplicate mapping keys in YAML is deprecated since version 3.2 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0.', $key), E_USER_DEPRECATED); + @trigger_error($this->getDeprecationMessage(sprintf('Duplicate key "%s" detected whilst parsing YAML. Silent handling of duplicate mapping keys in YAML is deprecated since version 3.2 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0.', $key)), E_USER_DEPRECATED); } } if ($isRef) { @@ -384,7 +384,7 @@ private function doParse($value, $flags) } if (isset($this->currentLine[1]) && '?' === $this->currentLine[0] && ' ' === $this->currentLine[1]) { - @trigger_error('Starting an unquoted string with a question mark followed by a space is deprecated since version 3.3 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0.', E_USER_DEPRECATED); + @trigger_error($this->getDeprecationMessage('Starting an unquoted string with a question mark followed by a space is deprecated since version 3.3 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0.'), E_USER_DEPRECATED); } // 1-liner optionally followed by newline(s) @@ -699,7 +699,7 @@ private function parseValue($value, $flags, $context) if ('!!binary' === $matches['tag']) { return Inline::evaluateBinaryScalar($data); } elseif ('!' !== $matches['tag']) { - @trigger_error(sprintf('Using the custom tag "%s" for the value "%s" is deprecated since version 3.3. It will be replaced by an instance of %s in 4.0.', $matches['tag'], $data, TaggedValue::class), E_USER_DEPRECATED); + @trigger_error($this->getDeprecationMessage(sprintf('Using the custom tag "%s" for the value "%s" is deprecated since version 3.3. It will be replaced by an instance of %s in 4.0.', $matches['tag'], $data, TaggedValue::class)), E_USER_DEPRECATED); } } @@ -1083,4 +1083,17 @@ private function getLineTag($value, $flags, $nextLineCheck = true) throw new ParseException(sprintf('Tags support is not enabled. You must use the flag `Yaml::PARSE_CUSTOM_TAGS` to use "%s".', $matches['tag']), $this->getRealCurrentLineNb() + 1, $value, $this->filename); } + + private function getDeprecationMessage($message) + { + $message = rtrim($message, '.'); + + if (null !== $this->filename) { + $message .= ' in '.$this->filename; + } + + $message .= ' on line '.($this->getRealCurrentLineNb() + 1); + + return $message.'.'; + } } diff --git a/src/Symfony/Component/Yaml/Tests/ParserTest.php b/src/Symfony/Component/Yaml/Tests/ParserTest.php index 553b762384c29..8dd8f43a23761 100644 --- a/src/Symfony/Component/Yaml/Tests/ParserTest.php +++ b/src/Symfony/Component/Yaml/Tests/ParserTest.php @@ -1096,7 +1096,7 @@ public function testYamlDirective() /** * @group legacy - * @expectedDeprecation Implicit casting of numeric key to string is deprecated since version 3.3 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0. Quote your evaluable mapping keys instead. + * @expectedDeprecation Implicit casting of numeric key to string is deprecated since version 3.3 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0. Quote your evaluable mapping keys instead on line 2. */ public function testFloatKeys() { @@ -1118,7 +1118,7 @@ public function testFloatKeys() /** * @group legacy - * @expectedDeprecation Implicit casting of non-string key to string is deprecated since version 3.3 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0. Quote your evaluable mapping keys instead. + * @expectedDeprecation Implicit casting of non-string key to string is deprecated since version 3.3 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0. Quote your evaluable mapping keys instead on line 1. */ public function testBooleanKeys() { @@ -1707,7 +1707,7 @@ public function testExceptionWhenUsingUnsuportedBuiltInTags() /** * @group legacy - * @expectedDeprecation Starting an unquoted string with a question mark followed by a space is deprecated since version 3.3 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0. + * @expectedDeprecation Starting an unquoted string with a question mark followed by a space is deprecated since version 3.3 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0 on line 1. */ public function testComplexMappingThrowsParseException() { @@ -1722,7 +1722,7 @@ public function testComplexMappingThrowsParseException() /** * @group legacy - * @expectedDeprecation Starting an unquoted string with a question mark followed by a space is deprecated since version 3.3 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0. + * @expectedDeprecation Starting an unquoted string with a question mark followed by a space is deprecated since version 3.3 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0 on line 2. */ public function testComplexMappingNestedInMappingThrowsParseException() { @@ -1738,7 +1738,7 @@ public function testComplexMappingNestedInMappingThrowsParseException() /** * @group legacy - * @expectedDeprecation Starting an unquoted string with a question mark followed by a space is deprecated since version 3.3 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0. + * @expectedDeprecation Starting an unquoted string with a question mark followed by a space is deprecated since version 3.3 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0 on line 1. */ public function testComplexMappingNestedInSequenceThrowsParseException() { @@ -1771,7 +1771,7 @@ private function loadTestsFromFixtureFiles($testsFile) $parser = new Parser(); $tests = array(); - $files = $parser->parse(file_get_contents(__DIR__.'/Fixtures/'.$testsFile)); + $files = $parser->parseFile(__DIR__.'/Fixtures/'.$testsFile); foreach ($files as $file) { $yamls = file_get_contents(__DIR__.'/Fixtures/'.$file.'.yml'); @@ -1852,7 +1852,7 @@ public function testPhpConstantTagMappingKey() /** * @group legacy - * @expectedDeprecation The !php/const: tag to indicate dumped PHP constants is deprecated since version 3.4 and will be removed in 4.0. Use the !php/const (without the colon) tag instead. + * @expectedDeprecation The !php/const: tag to indicate dumped PHP constants is deprecated since version 3.4 and will be removed in 4.0. Use the !php/const (without the colon) tag instead on line 1. * @expectedDeprecation The !php/const: tag to indicate dumped PHP constants is deprecated since version 3.4 and will be removed in 4.0. Use the !php/const (without the colon) tag instead. * @expectedDeprecation The !php/const: tag to indicate dumped PHP constants is deprecated since version 3.4 and will be removed in 4.0. Use the !php/const (without the colon) tag instead. */ From f0876e59272bfc0e11e20218b80be7b7560ea7d7 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Thu, 28 Sep 2017 13:24:51 +0200 Subject: [PATCH 0933/1099] register an identity translator as fallback The Form component can be used without the Translation component. However, to be able to use the default form themes provided by the TwigBridge you need to have the `trans` filter to be available. This change ensure that there will always be a `trans` filter which as a fallback will just return the message key if no translator is present. --- .../Bridge/Twig/Extension/TranslationExtension.php | 10 +++++++++- .../DependencyInjection/Compiler/ExtensionPass.php | 7 ------- .../Bundle/TwigBundle/Resources/config/twig.xml | 3 ++- 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/src/Symfony/Bridge/Twig/Extension/TranslationExtension.php b/src/Symfony/Bridge/Twig/Extension/TranslationExtension.php index 5155169a8173d..a748e1ed72e7b 100644 --- a/src/Symfony/Bridge/Twig/Extension/TranslationExtension.php +++ b/src/Symfony/Bridge/Twig/Extension/TranslationExtension.php @@ -32,7 +32,7 @@ class TranslationExtension extends AbstractExtension private $translator; private $translationNodeVisitor; - public function __construct(TranslatorInterface $translator, NodeVisitorInterface $translationNodeVisitor = null) + public function __construct(TranslatorInterface $translator = null, NodeVisitorInterface $translationNodeVisitor = null) { if (!$translationNodeVisitor) { $translationNodeVisitor = new TranslationNodeVisitor(); @@ -94,11 +94,19 @@ public function getTranslationNodeVisitor() public function trans($message, array $arguments = array(), $domain = null, $locale = null) { + if (null === $this->translator) { + return $message; + } + return $this->translator->trans($message, $arguments, $domain, $locale); } public function transchoice($message, $count, array $arguments = array(), $domain = null, $locale = null) { + if (null === $this->translator) { + return $message; + } + return $this->translator->transChoice($message, $count, array_merge(array('%count%' => $count), $arguments), $domain, $locale); } diff --git a/src/Symfony/Bundle/TwigBundle/DependencyInjection/Compiler/ExtensionPass.php b/src/Symfony/Bundle/TwigBundle/DependencyInjection/Compiler/ExtensionPass.php index 31d1b758eff56..667acfc350fbc 100644 --- a/src/Symfony/Bundle/TwigBundle/DependencyInjection/Compiler/ExtensionPass.php +++ b/src/Symfony/Bundle/TwigBundle/DependencyInjection/Compiler/ExtensionPass.php @@ -35,9 +35,6 @@ public function process(ContainerBuilder $container) if (!interface_exists('Symfony\Component\Routing\Generator\UrlGeneratorInterface')) { $container->removeDefinition('twig.extension.routing'); } - if (!interface_exists('Symfony\Component\Translation\TranslatorInterface')) { - $container->removeDefinition('twig.extension.trans'); - } if (!class_exists('Symfony\Component\Yaml\Yaml')) { $container->removeDefinition('twig.extension.yaml'); @@ -49,10 +46,6 @@ public function process(ContainerBuilder $container) $container->getDefinition('twig.loader.native_filesystem')->addMethodCall('addPath', array(dirname(dirname($reflClass->getFileName())).'/Resources/views/Form')); } - if ($container->has('translator')) { - $container->getDefinition('twig.extension.trans')->addTag('twig.extension'); - } - if ($container->has('router')) { $container->getDefinition('twig.extension.routing')->addTag('twig.extension'); } diff --git a/src/Symfony/Bundle/TwigBundle/Resources/config/twig.xml b/src/Symfony/Bundle/TwigBundle/Resources/config/twig.xml index ff564b412148a..50e439b39ec64 100644 --- a/src/Symfony/Bundle/TwigBundle/Resources/config/twig.xml +++ b/src/Symfony/Bundle/TwigBundle/Resources/config/twig.xml @@ -72,7 +72,8 @@ - + + From 4dd0e5317100848d6867170f6c41b186dc99f21c Mon Sep 17 00:00:00 2001 From: Matthias Pigulla Date: Sun, 17 Sep 2017 21:33:12 +0200 Subject: [PATCH 0934/1099] HttpCache does not consider ESI resources in HEAD requests --- .../HttpKernel/HttpCache/HttpCache.php | 14 +- .../Tests/HttpCache/HttpCacheTest.php | 123 +++++++++++++++++- 2 files changed, 124 insertions(+), 13 deletions(-) diff --git a/src/Symfony/Component/HttpKernel/HttpCache/HttpCache.php b/src/Symfony/Component/HttpKernel/HttpCache/HttpCache.php index 941d4c6fa033d..d0f2155143b7f 100644 --- a/src/Symfony/Component/HttpKernel/HttpCache/HttpCache.php +++ b/src/Symfony/Component/HttpKernel/HttpCache/HttpCache.php @@ -633,14 +633,6 @@ protected function store(Request $request, Response $response) */ private function restoreResponseBody(Request $request, Response $response) { - if ($request->isMethod('HEAD') || 304 === $response->getStatusCode()) { - $response->setContent(null); - $response->headers->remove('X-Body-Eval'); - $response->headers->remove('X-Body-File'); - - return; - } - if ($response->headers->has('X-Body-Eval')) { ob_start(); @@ -656,7 +648,11 @@ private function restoreResponseBody(Request $request, Response $response) $response->headers->set('Content-Length', strlen($response->getContent())); } } elseif ($response->headers->has('X-Body-File')) { - $response->setContent(file_get_contents($response->headers->get('X-Body-File'))); + // Response does not include possibly dynamic content (ESI, SSI), so we need + // not handle the content for HEAD requests + if (!$request->isMethod('HEAD')) { + $response->setContent(file_get_contents($response->headers->get('X-Body-File'))); + } } else { return; } diff --git a/src/Symfony/Component/HttpKernel/Tests/HttpCache/HttpCacheTest.php b/src/Symfony/Component/HttpKernel/Tests/HttpCache/HttpCacheTest.php index d75bd00efb6fc..32977cf387c24 100644 --- a/src/Symfony/Component/HttpKernel/Tests/HttpCache/HttpCacheTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/HttpCache/HttpCacheTest.php @@ -1133,7 +1133,7 @@ public function testEsiCacheSendsTheLowestTtl() array( 'status' => 200, 'body' => 'Hello World!', - 'headers' => array('Cache-Control' => 's-maxage=300'), + 'headers' => array('Cache-Control' => 's-maxage=200'), ), array( 'status' => 200, @@ -1147,8 +1147,33 @@ public function testEsiCacheSendsTheLowestTtl() $this->request('GET', '/', array(), array(), true); $this->assertEquals('Hello World! My name is Bobby.', $this->response->getContent()); - // check for 100 or 99 as the test can be executed after a second change - $this->assertTrue(in_array($this->response->getTtl(), array(99, 100))); + $this->assertEquals(100, $this->response->getTtl()); + } + + public function testEsiCacheSendsTheLowestTtlForHeadRequests() + { + $responses = array( + array( + 'status' => 200, + 'body' => 'I am a long-lived master response, but I embed a short-lived resource: ', + 'headers' => array( + 'Cache-Control' => 's-maxage=300', + 'Surrogate-Control' => 'content="ESI/1.0"', + ), + ), + array( + 'status' => 200, + 'body' => 'I am a short-lived resource', + 'headers' => array('Cache-Control' => 's-maxage=100'), + ), + ); + + $this->setNextResponses($responses); + + $this->request('HEAD', '/', array(), array(), true); + + $this->assertEmpty($this->response->getContent()); + $this->assertEquals(100, $this->response->getTtl()); } public function testEsiCacheForceValidation() @@ -1184,6 +1209,37 @@ public function testEsiCacheForceValidation() $this->assertTrue($this->response->headers->hasCacheControlDirective('no-cache')); } + public function testEsiCacheForceValidationForHeadRequests() + { + $responses = array( + array( + 'status' => 200, + 'body' => 'I am the master response and use expiration caching, but I embed another resource: ', + 'headers' => array( + 'Cache-Control' => 's-maxage=300', + 'Surrogate-Control' => 'content="ESI/1.0"', + ), + ), + array( + 'status' => 200, + 'body' => 'I am the embedded resource and use validation caching', + 'headers' => array('ETag' => 'foobar'), + ), + ); + + $this->setNextResponses($responses); + + $this->request('HEAD', '/', array(), array(), true); + + // The response has been assembled from expiration and validation based resources + // This can neither be cached nor revalidated, so it should be private/no cache + $this->assertEmpty($this->response->getContent()); + $this->assertNull($this->response->getTtl()); + $this->assertTrue($this->response->mustRevalidate()); + $this->assertTrue($this->response->headers->hasCacheControlDirective('private')); + $this->assertTrue($this->response->headers->hasCacheControlDirective('no-cache')); + } + public function testEsiRecalculateContentLengthHeader() { $responses = array( @@ -1192,7 +1248,6 @@ public function testEsiRecalculateContentLengthHeader() 'body' => '', 'headers' => array( 'Content-Length' => 26, - 'Cache-Control' => 's-maxage=300', 'Surrogate-Control' => 'content="ESI/1.0"', ), ), @@ -1210,6 +1265,37 @@ public function testEsiRecalculateContentLengthHeader() $this->assertEquals(12, $this->response->headers->get('Content-Length')); } + public function testEsiRecalculateContentLengthHeaderForHeadRequest() + { + $responses = array( + array( + 'status' => 200, + 'body' => '', + 'headers' => array( + 'Content-Length' => 26, + 'Surrogate-Control' => 'content="ESI/1.0"', + ), + ), + array( + 'status' => 200, + 'body' => 'Hello World!', + 'headers' => array(), + ), + ); + + $this->setNextResponses($responses); + + $this->request('HEAD', '/', array(), array(), true); + + // https://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.13 + // "The Content-Length entity-header field indicates the size of the entity-body, + // in decimal number of OCTETs, sent to the recipient or, in the case of the HEAD + // method, the size of the entity-body that would have been sent had the request + // been a GET." + $this->assertEmpty($this->response->getContent()); + $this->assertEquals(12, $this->response->headers->get('Content-Length')); + } + public function testClientIpIsAlwaysLocalhostForForwardedRequests() { $this->setNextResponse(); @@ -1301,6 +1387,35 @@ public function testEsiCacheRemoveValidationHeadersIfEmbeddedResponses() $this->assertNull($this->response->getLastModified()); } + public function testEsiCacheRemoveValidationHeadersIfEmbeddedResponsesAndHeadRequest() + { + $time = \DateTime::createFromFormat('U', time()); + + $responses = array( + array( + 'status' => 200, + 'body' => '', + 'headers' => array( + 'Surrogate-Control' => 'content="ESI/1.0"', + 'ETag' => 'hey', + 'Last-Modified' => $time->format(DATE_RFC2822), + ), + ), + array( + 'status' => 200, + 'body' => 'Hey!', + 'headers' => array(), + ), + ); + + $this->setNextResponses($responses); + + $this->request('HEAD', '/', array(), array(), true); + $this->assertEmpty($this->response->getContent()); + $this->assertNull($this->response->getETag()); + $this->assertNull($this->response->getLastModified()); + } + public function testDoesNotCacheOptionsRequest() { $this->setNextResponse(200, array('Cache-Control' => 'public, s-maxage=60'), 'get'); From 534eaed7aeaf52fbdcbcb8f666243de2c5aa352b Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Wed, 13 Sep 2017 19:40:55 +0200 Subject: [PATCH 0935/1099] parse merge keys with PARSE_OBJECT_FOR_MAP flag --- src/Symfony/Component/Yaml/Parser.php | 18 +++++++-- .../Component/Yaml/Tests/ParserTest.php | 37 +++++++++++++++++++ 2 files changed, 52 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Component/Yaml/Parser.php b/src/Symfony/Component/Yaml/Parser.php index 81b5e0f7f69f9..54a5704daf339 100644 --- a/src/Symfony/Component/Yaml/Parser.php +++ b/src/Symfony/Component/Yaml/Parser.php @@ -249,7 +249,7 @@ private function doParse($value, $flags) if ('<<' === $key) { $mergeNode = true; $allowOverwrite = true; - if (isset($values['value']) && 0 === strpos($values['value'], '*')) { + if (isset($values['value'][0]) && '*' === $values['value'][0]) { $refName = substr(rtrim($values['value']), 1); if (!array_key_exists($refName, $this->refs)) { throw new ParseException(sprintf('Reference "%s" does not exist.', $refName), $this->getRealCurrentLineNb() + 1, $this->currentLine); @@ -257,6 +257,10 @@ private function doParse($value, $flags) $refValue = $this->refs[$refName]; + if (Yaml::PARSE_OBJECT_FOR_MAP & $flags && $refValue instanceof \stdClass) { + $refValue = (array) $refValue; + } + if (!is_array($refValue)) { throw new ParseException('YAML merge keys used with a scalar value instead of an array.', $this->getRealCurrentLineNb() + 1, $this->currentLine); } @@ -270,6 +274,10 @@ private function doParse($value, $flags) } $parsed = $this->parseBlock($this->getRealCurrentLineNb() + 1, $value, $flags); + if (Yaml::PARSE_OBJECT_FOR_MAP & $flags && $parsed instanceof \stdClass) { + $parsed = (array) $parsed; + } + if (!is_array($parsed)) { throw new ParseException('YAML merge keys used with a scalar value instead of an array.', $this->getRealCurrentLineNb() + 1, $this->currentLine); } @@ -279,6 +287,10 @@ private function doParse($value, $flags) // and each of these nodes is merged in turn according to its order in the sequence. Keys in mapping nodes earlier // in the sequence override keys specified in later mapping nodes. foreach ($parsed as $parsedItem) { + if (Yaml::PARSE_OBJECT_FOR_MAP & $flags && $parsedItem instanceof \stdClass) { + $parsedItem = (array) $parsedItem; + } + if (!is_array($parsedItem)) { throw new ParseException('Merge items must be arrays.', $this->getRealCurrentLineNb() + 1, $parsedItem); } @@ -902,7 +914,7 @@ private function cleanup($value) // remove leading comments $trimmedValue = preg_replace('#^(\#.*?\n)+#s', '', $value, -1, $count); - if (1 == $count) { + if (1 === $count) { // items have been removed, update the offset $this->offset += substr_count($value, "\n") - substr_count($trimmedValue, "\n"); $value = $trimmedValue; @@ -910,7 +922,7 @@ private function cleanup($value) // remove start of the document marker (---) $trimmedValue = preg_replace('#^\-\-\-.*?\n#s', '', $value, -1, $count); - if (1 == $count) { + if (1 === $count) { // items have been removed, update the offset $this->offset += substr_count($value, "\n") - substr_count($trimmedValue, "\n"); $value = $trimmedValue; diff --git a/src/Symfony/Component/Yaml/Tests/ParserTest.php b/src/Symfony/Component/Yaml/Tests/ParserTest.php index 620eff32d967c..ddf3213054802 100644 --- a/src/Symfony/Component/Yaml/Tests/ParserTest.php +++ b/src/Symfony/Component/Yaml/Tests/ParserTest.php @@ -1865,6 +1865,43 @@ public function testPhpConstantTagMappingKeyWithKeysCastToStrings() $this->assertSame($expected, $this->parser->parse($yaml, Yaml::PARSE_CONSTANT | Yaml::PARSE_KEYS_AS_STRINGS)); } + + public function testMergeKeysWhenMappingsAreParsedAsObjects() + { + $yaml = << (object) array( + 'bar' => 1, + ), + 'bar' => (object) array( + 'baz' => 2, + 'bar' => 1, + ), + 'baz' => (object) array( + 'baz_foo' => 3, + 'baz_bar' => 4, + ), + 'foobar' => (object) array( + 'bar' => null, + 'baz' => 2, + ), + ); + + $this->assertEquals($expected, $this->parser->parse($yaml, Yaml::PARSE_OBJECT_FOR_MAP)); + } } class B From 979e58f37051ffa0f1d22915c90e52c9d8d7bfe5 Mon Sep 17 00:00:00 2001 From: Roland Franssen Date: Tue, 28 Mar 2017 12:05:21 +0200 Subject: [PATCH 0936/1099] [DI] Reference tagged services in config --- .../Argument/TaggedIteratorArgument.php | 37 +++++++++++++++++ .../DependencyInjection/CHANGELOG.md | 1 + .../Compiler/PassConfig.php | 1 + .../ResolveTaggedIteratorArgumentPass.php | 38 ++++++++++++++++++ .../DependencyInjection/Dumper/XmlDumper.php | 4 ++ .../DependencyInjection/Dumper/YamlDumper.php | 4 ++ .../Configurator/ContainerConfigurator.php | 13 ++++++ .../Loader/XmlFileLoader.php | 7 ++++ .../Loader/YamlFileLoader.php | 8 ++++ .../schema/dic/services/services-1.0.xsd | 3 ++ .../ResolveTaggedIteratorArgumentPassTest.php | 40 +++++++++++++++++++ .../Tests/Fixtures/config/basic.php | 2 - .../Tests/Fixtures/config/child.php | 2 - .../Tests/Fixtures/config/defaults.php | 2 - .../Tests/Fixtures/config/instanceof.php | 2 - .../Tests/Fixtures/config/php7.php | 2 - .../Tests/Fixtures/config/prototype.php | 2 - .../Tests/Fixtures/config/services9.php | 8 +++- .../Tests/Fixtures/containers/container9.php | 11 +++++ .../Tests/Fixtures/graphviz/services9.dot | 2 + .../Tests/Fixtures/php/services9.php | 25 ++++++++++++ .../Tests/Fixtures/php/services9_as_files.txt | 24 +++++++++++ .../Tests/Fixtures/php/services9_compiled.php | 26 ++++++++++++ .../Tests/Fixtures/xml/services9.xml | 6 +++ .../Tests/Fixtures/yaml/services9.yml | 10 +++++ src/Symfony/Component/Yaml/Inline.php | 4 +- src/Symfony/Component/Yaml/Parser.php | 2 + 27 files changed, 271 insertions(+), 15 deletions(-) create mode 100644 src/Symfony/Component/DependencyInjection/Argument/TaggedIteratorArgument.php create mode 100644 src/Symfony/Component/DependencyInjection/Compiler/ResolveTaggedIteratorArgumentPass.php create mode 100644 src/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveTaggedIteratorArgumentPassTest.php diff --git a/src/Symfony/Component/DependencyInjection/Argument/TaggedIteratorArgument.php b/src/Symfony/Component/DependencyInjection/Argument/TaggedIteratorArgument.php new file mode 100644 index 0000000000000..19e0d2b97152c --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Argument/TaggedIteratorArgument.php @@ -0,0 +1,37 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Argument; + +/** + * Represents a collection of services found by tag name to lazily iterate over. + * + * @author Roland Franssen + */ +class TaggedIteratorArgument extends IteratorArgument +{ + private $tag; + + /** + * @param string $tag + */ + public function __construct($tag) + { + parent::__construct(array()); + + $this->tag = (string) $tag; + } + + public function getTag() + { + return $this->tag; + } +} diff --git a/src/Symfony/Component/DependencyInjection/CHANGELOG.md b/src/Symfony/Component/DependencyInjection/CHANGELOG.md index cea65b20b7504..013da9ad4ec3f 100644 --- a/src/Symfony/Component/DependencyInjection/CHANGELOG.md +++ b/src/Symfony/Component/DependencyInjection/CHANGELOG.md @@ -13,6 +13,7 @@ CHANGELOG * deprecated support for top-level anonymous services in XML * deprecated case insensitivity of parameter names * deprecated the `ResolveDefinitionTemplatesPass` class in favor of `ResolveChildDefinitionsPass` + * added `TaggedIteratorArgument` with YAML (`!tagged foo`) and XML (``) support 3.3.0 ----- diff --git a/src/Symfony/Component/DependencyInjection/Compiler/PassConfig.php b/src/Symfony/Component/DependencyInjection/Compiler/PassConfig.php index 2cb261dfbc565..6c0448ecb4e81 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/PassConfig.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/PassConfig.php @@ -61,6 +61,7 @@ public function __construct() new AutowireRequiredMethodsPass(), new ResolveBindingsPass(), new AutowirePass(false), + new ResolveTaggedIteratorArgumentPass(), new ResolveServiceSubscribersPass(), new ResolveReferencesToAliasesPass(), new ResolveInvalidReferencesPass(), diff --git a/src/Symfony/Component/DependencyInjection/Compiler/ResolveTaggedIteratorArgumentPass.php b/src/Symfony/Component/DependencyInjection/Compiler/ResolveTaggedIteratorArgumentPass.php new file mode 100644 index 0000000000000..009cee9bf5c1d --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Compiler/ResolveTaggedIteratorArgumentPass.php @@ -0,0 +1,38 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Compiler; + +use Symfony\Component\DependencyInjection\Argument\TaggedIteratorArgument; + +/** + * Resolves all TaggedIteratorArgument arguments. + * + * @author Roland Franssen + */ +class ResolveTaggedIteratorArgumentPass extends AbstractRecursivePass +{ + use PriorityTaggedServiceTrait; + + /** + * {@inheritdoc} + */ + protected function processValue($value, $isRoot = false) + { + if (!$value instanceof TaggedIteratorArgument) { + return parent::processValue($value, $isRoot); + } + + $value->setValues($this->findAndSortTaggedServices($value->getTag(), $this->container)); + + return $value; + } +} diff --git a/src/Symfony/Component/DependencyInjection/Dumper/XmlDumper.php b/src/Symfony/Component/DependencyInjection/Dumper/XmlDumper.php index fb307a76e8ca7..cfd7c38413c84 100644 --- a/src/Symfony/Component/DependencyInjection/Dumper/XmlDumper.php +++ b/src/Symfony/Component/DependencyInjection/Dumper/XmlDumper.php @@ -13,6 +13,7 @@ use Symfony\Component\DependencyInjection\Argument\IteratorArgument; use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument; +use Symfony\Component\DependencyInjection\Argument\TaggedIteratorArgument; use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\DependencyInjection\Parameter; use Symfony\Component\DependencyInjection\Reference; @@ -298,6 +299,9 @@ private function convertParameters(array $parameters, $type, \DOMElement $parent if (is_array($value)) { $element->setAttribute('type', 'collection'); $this->convertParameters($value, $type, $element, 'key'); + } elseif ($value instanceof TaggedIteratorArgument) { + $element->setAttribute('type', 'tagged'); + $element->setAttribute('tag', $value->getTag()); } elseif ($value instanceof IteratorArgument) { $element->setAttribute('type', 'iterator'); $this->convertParameters($value->getValues(), $type, $element, 'key'); diff --git a/src/Symfony/Component/DependencyInjection/Dumper/YamlDumper.php b/src/Symfony/Component/DependencyInjection/Dumper/YamlDumper.php index 916a2317b3893..dc44cba17e9b7 100644 --- a/src/Symfony/Component/DependencyInjection/Dumper/YamlDumper.php +++ b/src/Symfony/Component/DependencyInjection/Dumper/YamlDumper.php @@ -19,6 +19,7 @@ use Symfony\Component\DependencyInjection\Argument\ArgumentInterface; use Symfony\Component\DependencyInjection\Argument\IteratorArgument; use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument; +use Symfony\Component\DependencyInjection\Argument\TaggedIteratorArgument; use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\DependencyInjection\Parameter; @@ -263,6 +264,9 @@ private function dumpValue($value) $value = $value->getValues()[0]; } if ($value instanceof ArgumentInterface) { + if ($value instanceof TaggedIteratorArgument) { + return new TaggedValue('tagged', $value->getTag()); + } if ($value instanceof IteratorArgument) { $tag = 'iterator'; } else { diff --git a/src/Symfony/Component/DependencyInjection/Loader/Configurator/ContainerConfigurator.php b/src/Symfony/Component/DependencyInjection/Loader/Configurator/ContainerConfigurator.php index 132529087ab1d..b44f1e43105a5 100644 --- a/src/Symfony/Component/DependencyInjection/Loader/Configurator/ContainerConfigurator.php +++ b/src/Symfony/Component/DependencyInjection/Loader/Configurator/ContainerConfigurator.php @@ -12,6 +12,7 @@ namespace Symfony\Component\DependencyInjection\Loader\Configurator; use Symfony\Component\DependencyInjection\Argument\IteratorArgument; +use Symfony\Component\DependencyInjection\Argument\TaggedIteratorArgument; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; @@ -115,6 +116,18 @@ function iterator(array $values) return new IteratorArgument(AbstractConfigurator::processValue($values, true)); } +/** + * Creates a lazy iterator by tag name. + * + * @param string $tag + * + * @return TaggedIteratorArgument + */ +function tagged($tag) +{ + return new TaggedIteratorArgument($tag); +} + /** * Creates an expression. * diff --git a/src/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php b/src/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php index f152d462676e2..e5a43e391d20d 100644 --- a/src/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php +++ b/src/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php @@ -12,6 +12,7 @@ namespace Symfony\Component\DependencyInjection\Loader; use Symfony\Component\Config\Util\XmlUtils; +use Symfony\Component\DependencyInjection\Argument\TaggedIteratorArgument; use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\DependencyInjection\Alias; use Symfony\Component\DependencyInjection\Argument\BoundArgument; @@ -518,6 +519,12 @@ private function getArgumentsAsPhp(\DOMElement $node, $name, $file, $lowercase = throw new InvalidArgumentException(sprintf('Tag "<%s>" with type="iterator" only accepts collections of type="service" references in "%s".', $name, $file)); } break; + case 'tagged': + if (!$arg->getAttribute('tag')) { + throw new InvalidArgumentException(sprintf('Tag "<%s>" with type="tagged" has no or empty "tag" attribute in "%s".', $name, $file)); + } + $arguments[$key] = new TaggedIteratorArgument($arg->getAttribute('tag')); + break; case 'string': $arguments[$key] = $arg->nodeValue; break; diff --git a/src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php b/src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php index d9fd24c3d71a6..4088a3152931b 100644 --- a/src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php +++ b/src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php @@ -15,6 +15,7 @@ use Symfony\Component\DependencyInjection\Argument\ArgumentInterface; use Symfony\Component\DependencyInjection\Argument\BoundArgument; use Symfony\Component\DependencyInjection\Argument\IteratorArgument; +use Symfony\Component\DependencyInjection\Argument\TaggedIteratorArgument; use Symfony\Component\DependencyInjection\ChildDefinition; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\ContainerInterface; @@ -726,6 +727,13 @@ private function resolveServices($value, $file, $isParameter = false) throw new InvalidArgumentException(sprintf('"!iterator" tag only accepts arrays of "@service" references in "%s".', $file)); } } + if ('tagged' === $value->getTag()) { + if (!is_string($argument) || !$argument) { + throw new InvalidArgumentException(sprintf('"!tagged" tag only accepts non empty string in "%s".', $file)); + } + + return new TaggedIteratorArgument($argument); + } if ('service' === $value->getTag()) { if ($isParameter) { throw new InvalidArgumentException(sprintf('Using an anonymous service in a parameter is not allowed in "%s".', $file)); diff --git a/src/Symfony/Component/DependencyInjection/Loader/schema/dic/services/services-1.0.xsd b/src/Symfony/Component/DependencyInjection/Loader/schema/dic/services/services-1.0.xsd index 0be8658e3d547..3a55a7df676c7 100644 --- a/src/Symfony/Component/DependencyInjection/Loader/schema/dic/services/services-1.0.xsd +++ b/src/Symfony/Component/DependencyInjection/Loader/schema/dic/services/services-1.0.xsd @@ -208,6 +208,7 @@ + @@ -233,6 +234,7 @@ + @@ -258,6 +260,7 @@ + diff --git a/src/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveTaggedIteratorArgumentPassTest.php b/src/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveTaggedIteratorArgumentPassTest.php new file mode 100644 index 0000000000000..a219f860078b7 --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveTaggedIteratorArgumentPassTest.php @@ -0,0 +1,40 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Tests\Compiler; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\DependencyInjection\Argument\TaggedIteratorArgument; +use Symfony\Component\DependencyInjection\Compiler\ResolveTaggedIteratorArgumentPass; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Reference; + +/** + * @author Roland Franssen + */ +class ResolveTaggedIteratorArgumentPassTest extends TestCase +{ + public function testProcess() + { + $container = new ContainerBuilder(); + $container->register('a', 'stdClass')->addTag('foo'); + $container->register('b', 'stdClass')->addTag('foo', array('priority' => 20)); + $container->register('c', 'stdClass')->addTag('foo', array('priority' => 10)); + $container->register('d', 'stdClass')->setProperty('foos', new TaggedIteratorArgument('foo')); + + (new ResolveTaggedIteratorArgumentPass())->process($container); + + $properties = $container->getDefinition('d')->getProperties(); + $expected = new TaggedIteratorArgument('foo'); + $expected->setValues(array(new Reference('b'), new Reference('c'), new Reference('a'))); + $this->assertEquals($expected, $properties['foos']); + } +} diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/basic.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/basic.php index bab4e1ec83f04..b98e894c37253 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/basic.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/basic.php @@ -5,9 +5,7 @@ use App\BarService; return function (ContainerConfigurator $c) { - $s = $c->services(); $s->set(BarService::class) ->args(array(inline('FooClass'))); - }; diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/child.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/child.php index 30178217b6924..6fd84485e7a3a 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/child.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/child.php @@ -5,7 +5,6 @@ use App\BarService; return function (ContainerConfigurator $c) { - $c->services() ->set('bar', 'Class1') ->set(BarService::class) @@ -20,5 +19,4 @@ ->parent('bar') ->parent(BarService::class) ; - }; diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/defaults.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/defaults.php index 7fa93d2a91d73..de3b99d745a56 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/defaults.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/defaults.php @@ -5,7 +5,6 @@ use Symfony\Component\DependencyInjection\Tests\Fixtures\Prototype\Foo; return function (ContainerConfigurator $c) { - $c->import('basic.php'); $s = $c->services()->defaults() @@ -19,5 +18,4 @@ $s->set(Foo::class)->args(array(ref('bar')))->public(); $s->set('bar', Foo::class)->call('setFoo')->autoconfigure(false); - }; diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/instanceof.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/instanceof.php index 13d0213bf11e5..062e8c00ab250 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/instanceof.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/instanceof.php @@ -6,7 +6,6 @@ use Symfony\Component\DependencyInjection\Tests\Fixtures\Prototype; return function (ContainerConfigurator $c) { - $s = $c->services(); $s->instanceof(Prototype\Foo::class) ->property('p', 0) @@ -20,5 +19,4 @@ $s->load(Prototype::class.'\\', '../Prototype')->exclude('../Prototype/*/*'); $s->set('foo', FooService::class); - }; diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/php7.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/php7.php index 22a98c2c571d5..7711624e6f0f6 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/php7.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/php7.php @@ -5,7 +5,6 @@ use Symfony\Component\DependencyInjection\Tests\Fixtures\Prototype\Foo; return function (ContainerConfigurator $c) { - $c->parameters() ('foo', 'Foo') ('bar', 'Bar') @@ -17,5 +16,4 @@ ('bar', Foo::class) ->call('setFoo') ; - }; diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/prototype.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/prototype.php index 77bc132dcb78a..21cab6c6af753 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/prototype.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/prototype.php @@ -5,7 +5,6 @@ use Symfony\Component\DependencyInjection\Tests\Fixtures\Prototype; return function (ContainerConfigurator $c) { - $di = $c->services()->defaults() ->tag('baz'); $di->load(Prototype::class.'\\', '../Prototype') @@ -20,5 +19,4 @@ ->parent('foo'); $di->set('foo')->lazy()->abstract(); $di->get(Prototype\Foo::class)->lazy(false); - }; diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/services9.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/services9.php index 85543b6ebbcc7..3f4d5f15ea71a 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/services9.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/services9.php @@ -9,7 +9,6 @@ require_once __DIR__.'/../includes/foo.php'; return function (ContainerConfigurator $c) { - $p = $c->parameters(); $p->set('baz_class', 'BazClass'); $p->set('foo_class', FooClass::class) @@ -119,4 +118,11 @@ $s->set('lazy_context_ignore_invalid_ref', 'LazyContext') ->args(array(iterator(array(ref('foo.baz'), ref('invalid')->ignoreOnInvalid())), iterator(array()))); + $s->set('tagged_iterator_foo', 'Bar') + ->private() + ->tag('foo'); + + $s->set('tagged_iterator', 'Bar') + ->public() + ->args(array(tagged('foo'))); }; diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container9.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container9.php index 91a9af43d9a1f..452dab6d806b6 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container9.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container9.php @@ -4,6 +4,7 @@ require_once __DIR__.'/../includes/foo.php'; use Symfony\Component\DependencyInjection\Argument\IteratorArgument; +use Symfony\Component\DependencyInjection\Argument\TaggedIteratorArgument; use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Reference; @@ -161,5 +162,15 @@ ->setArguments(array(new IteratorArgument(array(new Reference('foo.baz'), new Reference('invalid', ContainerInterface::IGNORE_ON_INVALID_REFERENCE))), new IteratorArgument(array()))) ->setPublic(true) ; +$container + ->register('tagged_iterator_foo', 'Bar') + ->addTag('foo') + ->setPublic(false) +; +$container + ->register('tagged_iterator', 'Bar') + ->addArgument(new TaggedIteratorArgument('foo')) + ->setPublic(true) +; return $container; diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/graphviz/services9.dot b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/graphviz/services9.dot index df9a1cae7ce73..6a34c5735c777 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/graphviz/services9.dot +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/graphviz/services9.dot @@ -29,6 +29,8 @@ digraph sc { node_factory_service_simple [label="factory_service_simple\nBar\n", shape=record, fillcolor="#eeeeee", style="filled"]; node_lazy_context [label="lazy_context\nLazyContext\n", shape=record, fillcolor="#eeeeee", style="filled"]; node_lazy_context_ignore_invalid_ref [label="lazy_context_ignore_invalid_ref\nLazyContext\n", shape=record, fillcolor="#eeeeee", style="filled"]; + node_tagged_iterator_foo [label="tagged_iterator_foo\nBar\n", shape=record, fillcolor="#eeeeee", style="filled"]; + node_tagged_iterator [label="tagged_iterator\nBar\n", shape=record, fillcolor="#eeeeee", style="filled"]; node_foo2 [label="foo2\n\n", shape=record, fillcolor="#ff9999", style="filled"]; node_foo3 [label="foo3\n\n", shape=record, fillcolor="#ff9999", style="filled"]; node_foobaz [label="foobaz\n\n", shape=record, fillcolor="#ff9999", style="filled"]; diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9.php index ec7c57a8dfb41..3075285dcf3a2 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9.php @@ -56,6 +56,8 @@ public function __construct() 'new_factory' => 'getNewFactoryService', 'new_factory_service' => 'getNewFactoryServiceService', 'service_from_static_method' => 'getServiceFromStaticMethodService', + 'tagged_iterator' => 'getTaggedIteratorService', + 'tagged_iterator_foo' => 'getTaggedIteratorFooService', ); $this->privates = array( 'configurator_service' => true, @@ -63,6 +65,7 @@ public function __construct() 'factory_simple' => true, 'inlined' => true, 'new_factory' => true, + 'tagged_iterator_foo' => true, ); $this->aliases = array( 'Psr\\Container\\ContainerInterface' => 'service_container', @@ -337,6 +340,18 @@ protected function getServiceFromStaticMethodService() return $this->services['service_from_static_method'] = \Bar\FooClass::getInstance(); } + /** + * Gets the public 'tagged_iterator' shared service. + * + * @return \Bar + */ + protected function getTaggedIteratorService() + { + return $this->services['tagged_iterator'] = new \Bar(new RewindableGenerator(function () { + return new \EmptyIterator(); + }, 0)); + } + /** * Gets the private 'configurator_service' shared service. * @@ -404,6 +419,16 @@ protected function getNewFactoryService() return $instance; } + /** + * Gets the private 'tagged_iterator_foo' shared service. + * + * @return \Bar + */ + protected function getTaggedIteratorFooService() + { + return $this->services['tagged_iterator_foo'] = new \Bar(); + } + /** * Gets the default parameters. * diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_as_files.txt b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_as_files.txt index 059f0912815ca..d6c0fc11eddff 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_as_files.txt +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_as_files.txt @@ -235,6 +235,27 @@ use Symfony\Component\DependencyInjection\Argument\RewindableGenerator; return $this->services['service_from_static_method'] = \Bar\FooClass::getInstance(); + [Container%s/getTaggedIteratorService.php] => services['tagged_iterator'] = new \Bar(new RewindableGenerator(function () { + yield 0 => ${($_ = isset($this->services['foo']) ? $this->services['foo'] : $this->load(__DIR__.'/getFooService.php')) && false ?: '_'}; + yield 1 => ${($_ = isset($this->services['tagged_iterator_foo']) ? $this->services['tagged_iterator_foo'] : $this->services['tagged_iterator_foo'] = new \Bar()) && false ?: '_'}; +}, 2)); + + [Container%s/getTaggedIteratorFooService.php] => services['tagged_iterator_foo'] = new \Bar(); + [Container%s/Container.php] => __DIR__.'/getMethodCall1Service.php', 'new_factory_service' => __DIR__.'/getNewFactoryServiceService.php', 'service_from_static_method' => __DIR__.'/getServiceFromStaticMethodService.php', + 'tagged_iterator' => __DIR__.'/getTaggedIteratorService.php', + 'tagged_iterator_foo' => __DIR__.'/getTaggedIteratorFooService.php', ); $this->privates = array( 'factory_simple' => true, + 'tagged_iterator_foo' => true, ); $this->aliases = array( 'alias_for_alias' => 'foo', diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_compiled.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_compiled.php index 103bb0de34d88..46e76a4d7f375 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_compiled.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_compiled.php @@ -49,9 +49,12 @@ public function __construct() 'method_call1' => 'getMethodCall1Service', 'new_factory_service' => 'getNewFactoryServiceService', 'service_from_static_method' => 'getServiceFromStaticMethodService', + 'tagged_iterator' => 'getTaggedIteratorService', + 'tagged_iterator_foo' => 'getTaggedIteratorFooService', ); $this->privates = array( 'factory_simple' => true, + 'tagged_iterator_foo' => true, ); $this->aliases = array( 'alias_for_alias' => 'foo', @@ -339,6 +342,19 @@ protected function getServiceFromStaticMethodService() return $this->services['service_from_static_method'] = \Bar\FooClass::getInstance(); } + /** + * Gets the public 'tagged_iterator' shared service. + * + * @return \Bar + */ + protected function getTaggedIteratorService() + { + return $this->services['tagged_iterator'] = new \Bar(new RewindableGenerator(function () { + yield 0 => ${($_ = isset($this->services['foo']) ? $this->services['foo'] : $this->getFooService()) && false ?: '_'}; + yield 1 => ${($_ = isset($this->services['tagged_iterator_foo']) ? $this->services['tagged_iterator_foo'] : $this->services['tagged_iterator_foo'] = new \Bar()) && false ?: '_'}; + }, 2)); + } + /** * Gets the private 'factory_simple' shared service. * @@ -353,6 +369,16 @@ protected function getFactorySimpleService() return $this->services['factory_simple'] = new \SimpleFactoryClass('foo'); } + /** + * Gets the private 'tagged_iterator_foo' shared service. + * + * @return \Bar + */ + protected function getTaggedIteratorFooService() + { + return $this->services['tagged_iterator_foo'] = new \Bar(); + } + /** * {@inheritdoc} */ diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services9.xml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services9.xml index 06f314f5eff73..d12c00319aca1 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services9.xml +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services9.xml @@ -133,6 +133,12 @@ + + + + + + diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services9.yml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services9.yml index b6b76da513106..cf713d189e57e 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services9.yml +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services9.yml @@ -145,6 +145,16 @@ services: alias_for_alias: alias: 'foo' public: true + tagged_iterator_foo: + class: Bar + tags: + - { name: foo } + public: false + tagged_iterator: + class: Bar + arguments: + - !tagged foo + public: true Psr\Container\ContainerInterface: alias: service_container public: false diff --git a/src/Symfony/Component/Yaml/Inline.php b/src/Symfony/Component/Yaml/Inline.php index b1653137fc135..7b355eca77bd1 100644 --- a/src/Symfony/Component/Yaml/Inline.php +++ b/src/Symfony/Component/Yaml/Inline.php @@ -774,8 +774,8 @@ private static function parseTag($value, &$i, $flags) $nextOffset += strspn($value, ' ', $nextOffset); // Is followed by a scalar - if (!isset($value[$nextOffset]) || !in_array($value[$nextOffset], array('[', '{'), true)) { - // Manage scalars in {@link self::evaluateScalar()} + if ((!isset($value[$nextOffset]) || !in_array($value[$nextOffset], array('[', '{'), true)) && 'tagged' !== $tag) { + // Manage non-whitelisted scalars in {@link self::evaluateScalar()} return; } diff --git a/src/Symfony/Component/Yaml/Parser.php b/src/Symfony/Component/Yaml/Parser.php index be1c13cddbf98..3789a83151705 100644 --- a/src/Symfony/Component/Yaml/Parser.php +++ b/src/Symfony/Component/Yaml/Parser.php @@ -698,6 +698,8 @@ private function parseValue($value, $flags, $context) if ('' !== $matches['tag']) { if ('!!binary' === $matches['tag']) { return Inline::evaluateBinaryScalar($data); + } elseif ('tagged' === $matches['tag']) { + return new TaggedValue(substr($matches['tag'], 1), $data); } elseif ('!' !== $matches['tag']) { @trigger_error(sprintf('Using the custom tag "%s" for the value "%s" is deprecated since version 3.3. It will be replaced by an instance of %s in 4.0.', $matches['tag'], $data, TaggedValue::class), E_USER_DEPRECATED); } From 1c8b65000ec75ef6504f20f961a620250aa4c475 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Thu, 28 Sep 2017 16:19:20 +0200 Subject: [PATCH 0937/1099] fix merge --- src/Symfony/Component/Yaml/Inline.php | 15 --------------- src/Symfony/Component/Yaml/Parser.php | 13 ------------- 2 files changed, 28 deletions(-) diff --git a/src/Symfony/Component/Yaml/Inline.php b/src/Symfony/Component/Yaml/Inline.php index 91b4ff206a7d6..128f2c97c5359 100644 --- a/src/Symfony/Component/Yaml/Inline.php +++ b/src/Symfony/Component/Yaml/Inline.php @@ -746,19 +746,4 @@ private static function getHexRegex(): string { return '~^0x[0-9a-f_]++$~i'; } - - private static function getDeprecationMessage($message) - { - $message = rtrim($message, '.'); - - if (null !== self::$parsedFilename) { - $message .= ' in '.self::$parsedFilename; - } - - if (-1 !== self::$parsedLineNumber) { - $message .= ' on line '.self::$parsedLineNumber; - } - - return $message.'.'; - } } diff --git a/src/Symfony/Component/Yaml/Parser.php b/src/Symfony/Component/Yaml/Parser.php index f579d8e58abb4..2e26e59abe890 100644 --- a/src/Symfony/Component/Yaml/Parser.php +++ b/src/Symfony/Component/Yaml/Parser.php @@ -1031,17 +1031,4 @@ private function getLineTag(string $value, int $flags, bool $nextLineCheck = tru throw new ParseException(sprintf('Tags support is not enabled. You must use the flag `Yaml::PARSE_CUSTOM_TAGS` to use "%s".', $matches['tag']), $this->getRealCurrentLineNb() + 1, $value, $this->filename); } - - private function getDeprecationMessage($message) - { - $message = rtrim($message, '.'); - - if (null !== $this->filename) { - $message .= ' in '.$this->filename; - } - - $message .= ' on line '.($this->getRealCurrentLineNb() + 1); - - return $message.'.'; - } } From cf0355203376ed9fe4a0e41446a003602dc02e66 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Wed, 13 Sep 2017 20:06:14 +0200 Subject: [PATCH 0938/1099] include file and line number in deprecation --- .../Loader/YamlFileLoader.php | 8 ++++++++ .../Routing/Loader/YamlFileLoader.php | 8 ++++++++ .../Mapping/Loader/YamlFileLoader.php | 12 ++++++++++- .../Translation/Loader/YamlFileLoader.php | 8 ++++++++ .../Mapping/Loader/YamlFileLoader.php | 8 ++++++++ src/Symfony/Component/Yaml/Inline.php | 20 +++++++++---------- src/Symfony/Component/Yaml/Parser.php | 14 ++++++------- .../Component/Yaml/Tests/InlineTest.php | 8 ++++---- .../Component/Yaml/Tests/ParserTest.php | 16 +++++++-------- 9 files changed, 72 insertions(+), 30 deletions(-) diff --git a/src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php b/src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php index 8e751be1027c2..4d14075dfea0e 100644 --- a/src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php +++ b/src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php @@ -605,10 +605,18 @@ protected function loadFile($file) $this->yamlParser = new YamlParser(); } + $prevErrorHandler = set_error_handler(function ($level, $message, $script, $line) use ($file, &$prevErrorHandler) { + $message = E_USER_DEPRECATED === $level ? preg_replace('/ on line \d+/', ' in "'.$file.'"$0', $message) : $message; + + return $prevErrorHandler ? $prevErrorHandler($level, $message, $script, $line) : false; + }); + try { $configuration = $this->yamlParser->parse(file_get_contents($file), Yaml::PARSE_CONSTANT | Yaml::PARSE_CUSTOM_TAGS | Yaml::PARSE_KEYS_AS_STRINGS); } catch (ParseException $e) { throw new InvalidArgumentException(sprintf('The file "%s" does not contain valid YAML.', $file), 0, $e); + } finally { + restore_error_handler(); } return $this->validate($configuration, $file); diff --git a/src/Symfony/Component/Routing/Loader/YamlFileLoader.php b/src/Symfony/Component/Routing/Loader/YamlFileLoader.php index 7ae5e84d109aa..72935fa5589f4 100644 --- a/src/Symfony/Component/Routing/Loader/YamlFileLoader.php +++ b/src/Symfony/Component/Routing/Loader/YamlFileLoader.php @@ -58,10 +58,18 @@ public function load($file, $type = null) $this->yamlParser = new YamlParser(); } + $prevErrorHandler = set_error_handler(function ($level, $message, $script, $line) use ($file, &$prevErrorHandler) { + $message = E_USER_DEPRECATED === $level ? preg_replace('/ on line \d+/', ' in "'.$file.'"$0', $message) : $message; + + return $prevErrorHandler ? $prevErrorHandler($level, $message, $script, $line) : false; + }); + try { $parsedConfig = $this->yamlParser->parse(file_get_contents($path), Yaml::PARSE_KEYS_AS_STRINGS); } catch (ParseException $e) { throw new \InvalidArgumentException(sprintf('The file "%s" does not contain valid YAML.', $path), 0, $e); + } finally { + restore_error_handler(); } $collection = new RouteCollection(); diff --git a/src/Symfony/Component/Serializer/Mapping/Loader/YamlFileLoader.php b/src/Symfony/Component/Serializer/Mapping/Loader/YamlFileLoader.php index 20a1d48aade65..0f833a5dedace 100644 --- a/src/Symfony/Component/Serializer/Mapping/Loader/YamlFileLoader.php +++ b/src/Symfony/Component/Serializer/Mapping/Loader/YamlFileLoader.php @@ -114,7 +114,17 @@ private function getClassesFromYaml() $this->yamlParser = new Parser(); } - $classes = $this->yamlParser->parse(file_get_contents($this->file), Yaml::PARSE_KEYS_AS_STRINGS); + $prevErrorHandler = set_error_handler(function ($level, $message, $script, $line) use (&$prevErrorHandler) { + $message = E_USER_DEPRECATED === $level ? preg_replace('/ on line \d+/', ' in "'.$this->file.'"$0', $message) : $message; + + return $prevErrorHandler ? $prevErrorHandler($level, $message, $script, $line) : false; + }); + + try { + $classes = $this->yamlParser->parse(file_get_contents($this->file), Yaml::PARSE_KEYS_AS_STRINGS); + } finally { + restore_error_handler(); + } if (empty($classes)) { return array(); diff --git a/src/Symfony/Component/Translation/Loader/YamlFileLoader.php b/src/Symfony/Component/Translation/Loader/YamlFileLoader.php index 5897767b6bf03..da6ceca2862b1 100644 --- a/src/Symfony/Component/Translation/Loader/YamlFileLoader.php +++ b/src/Symfony/Component/Translation/Loader/YamlFileLoader.php @@ -39,10 +39,18 @@ protected function loadResource($resource) $this->yamlParser = new YamlParser(); } + $prevErrorHandler = set_error_handler(function ($level, $message, $script, $line) use ($resource, &$prevErrorHandler) { + $message = E_USER_DEPRECATED === $level ? preg_replace('/ on line \d+/', ' in "'.$resource.'"$0', $message) : $message; + + return $prevErrorHandler ? $prevErrorHandler($level, $message, $script, $line) : false; + }); + try { $messages = $this->yamlParser->parse(file_get_contents($resource), Yaml::PARSE_KEYS_AS_STRINGS); } catch (ParseException $e) { throw new InvalidResourceException(sprintf('Error parsing YAML, invalid file "%s"', $resource), 0, $e); + } finally { + restore_error_handler(); } return $messages; diff --git a/src/Symfony/Component/Validator/Mapping/Loader/YamlFileLoader.php b/src/Symfony/Component/Validator/Mapping/Loader/YamlFileLoader.php index f2e664750a485..632fb4f78070e 100644 --- a/src/Symfony/Component/Validator/Mapping/Loader/YamlFileLoader.php +++ b/src/Symfony/Component/Validator/Mapping/Loader/YamlFileLoader.php @@ -115,10 +115,18 @@ protected function parseNodes(array $nodes) */ private function parseFile($path) { + $prevErrorHandler = set_error_handler(function ($level, $message, $script, $line) use ($path, &$prevErrorHandler) { + $message = E_USER_DEPRECATED === $level ? preg_replace('/ on line \d+/', ' in "'.$path.'"$0', $message) : $message; + + return $prevErrorHandler ? $prevErrorHandler($level, $message, $script, $line) : false; + }); + try { $classes = $this->yamlParser->parse(file_get_contents($path), Yaml::PARSE_KEYS_AS_STRINGS); } catch (ParseException $e) { throw new \InvalidArgumentException(sprintf('The file "%s" does not contain valid YAML.', $path), 0, $e); + } finally { + restore_error_handler(); } // empty file diff --git a/src/Symfony/Component/Yaml/Inline.php b/src/Symfony/Component/Yaml/Inline.php index c5e7f97a588aa..d747960fddacc 100644 --- a/src/Symfony/Component/Yaml/Inline.php +++ b/src/Symfony/Component/Yaml/Inline.php @@ -335,7 +335,7 @@ public static function parseScalar($scalar, $flags = 0, $delimiters = null, &$i } if ($output && '%' === $output[0]) { - @trigger_error(sprintf('Not quoting the scalar "%s" starting with the "%%" indicator character is deprecated since Symfony 3.1 and will throw a ParseException in 4.0.', $output), E_USER_DEPRECATED); + @trigger_error(sprintf('Not quoting the scalar "%s" starting with the "%%" indicator character is deprecated since Symfony 3.1 and will throw a ParseException in 4.0 on line %d.', $output, self::$parsedLineNumber + 1), E_USER_DEPRECATED); } if ($evaluate) { @@ -487,19 +487,19 @@ private static function parseMapping($mapping, $flags, &$i = 0, $references = ar } if (':' === $key) { - @trigger_error('Omitting the key of a mapping is deprecated and will throw a ParseException in 4.0.', E_USER_DEPRECATED); + @trigger_error(sprintf('Omitting the key of a mapping is deprecated and will throw a ParseException in 4.0 on line %d.', self::$parsedLineNumber + 1), E_USER_DEPRECATED); } if (!(Yaml::PARSE_KEYS_AS_STRINGS & $flags)) { $evaluatedKey = self::evaluateScalar($key, $flags, $references); if ('' !== $key && $evaluatedKey !== $key && !is_string($evaluatedKey) && !is_int($evaluatedKey)) { - @trigger_error('Implicit casting of incompatible mapping keys to strings is deprecated since version 3.3 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0. Quote your evaluable mapping keys instead.', E_USER_DEPRECATED); + @trigger_error(sprintf('Implicit casting of incompatible mapping keys to strings is deprecated since version 3.3 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0. Quote your evaluable mapping keys instead on line %d.', self::$parsedLineNumber + 1), E_USER_DEPRECATED); } } if (':' !== $key && !$isKeyQuoted && (!isset($mapping[$i + 1]) || !in_array($mapping[$i + 1], array(' ', ',', '[', ']', '{', '}'), true))) { - @trigger_error('Using a colon after an unquoted mapping key that is not followed by an indication character (i.e. " ", ",", "[", "]", "{", "}") is deprecated since version 3.2 and will throw a ParseException in 4.0.', E_USER_DEPRECATED); + @trigger_error(sprintf('Using a colon after an unquoted mapping key that is not followed by an indication character (i.e. " ", ",", "[", "]", "{", "}") is deprecated since version 3.2 and will throw a ParseException in 4.0 on line %d.', self::$parsedLineNumber + 1), E_USER_DEPRECATED); } while ($i < $len) { @@ -519,7 +519,7 @@ private static function parseMapping($mapping, $flags, &$i = 0, $references = ar // Parser cannot abort this mapping earlier, since lines // are processed sequentially. if (isset($output[$key])) { - @trigger_error(sprintf('Duplicate key "%s" detected whilst parsing YAML. Silent handling of duplicate mapping keys in YAML is deprecated since version 3.2 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0.', $key), E_USER_DEPRECATED); + @trigger_error(sprintf('Duplicate key "%s" detected whilst parsing YAML. Silent handling of duplicate mapping keys in YAML is deprecated since version 3.2 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0 on line %d.', $key, self::$parsedLineNumber + 1), E_USER_DEPRECATED); $duplicate = true; } break; @@ -530,7 +530,7 @@ private static function parseMapping($mapping, $flags, &$i = 0, $references = ar // Parser cannot abort this mapping earlier, since lines // are processed sequentially. if (isset($output[$key])) { - @trigger_error(sprintf('Duplicate key "%s" detected whilst parsing YAML. Silent handling of duplicate mapping keys in YAML is deprecated since version 3.2 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0.', $key), E_USER_DEPRECATED); + @trigger_error(sprintf('Duplicate key "%s" detected whilst parsing YAML. Silent handling of duplicate mapping keys in YAML is deprecated since version 3.2 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0 on line %d.', $key, self::$parsedLineNumber + 1), E_USER_DEPRECATED); $duplicate = true; } break; @@ -540,7 +540,7 @@ private static function parseMapping($mapping, $flags, &$i = 0, $references = ar // Parser cannot abort this mapping earlier, since lines // are processed sequentially. if (isset($output[$key])) { - @trigger_error(sprintf('Duplicate key "%s" detected whilst parsing YAML. Silent handling of duplicate mapping keys in YAML is deprecated since version 3.2 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0.', $key), E_USER_DEPRECATED); + @trigger_error(sprintf('Duplicate key "%s" detected whilst parsing YAML. Silent handling of duplicate mapping keys in YAML is deprecated since version 3.2 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0 on line %d.', $key, self::$parsedLineNumber + 1), E_USER_DEPRECATED); $duplicate = true; } --$i; @@ -624,7 +624,7 @@ private static function evaluateScalar($scalar, $flags, $references = array()) return; case 0 === strpos($scalar, '!!php/object:'): if (self::$objectSupport) { - @trigger_error('The !!php/object tag to indicate dumped PHP objects is deprecated since version 3.1 and will be removed in 4.0. Use the !php/object tag instead.', E_USER_DEPRECATED); + @trigger_error(sprintf('The !!php/object tag to indicate dumped PHP objects is deprecated since version 3.1 and will be removed in 4.0. Use the !php/object tag instead on line %d.', self::$parsedLineNumber + 1), E_USER_DEPRECATED); return unserialize(substr($scalar, 13)); } @@ -652,7 +652,7 @@ private static function evaluateScalar($scalar, $flags, $references = array()) case 0 === strpos($scalar, '!!binary '): return self::evaluateBinaryScalar(substr($scalar, 9)); default: - @trigger_error(sprintf('Using the unquoted scalar value "%s" is deprecated since version 3.3 and will be considered as a tagged value in 4.0. You must quote it.', $scalar), E_USER_DEPRECATED); + @trigger_error(sprintf('Using the unquoted scalar value "%s" is deprecated since version 3.3 and will be considered as a tagged value in 4.0. You must quote it on line %d.', $scalar, self::$parsedLineNumber + 1), E_USER_DEPRECATED); } // Optimize for returning strings. @@ -686,7 +686,7 @@ private static function evaluateScalar($scalar, $flags, $references = array()) case Parser::preg_match('/^(-|\+)?[0-9][0-9,]*(\.[0-9_]+)?$/', $scalar): case Parser::preg_match('/^(-|\+)?[0-9][0-9_]*(\.[0-9_]+)?$/', $scalar): if (false !== strpos($scalar, ',')) { - @trigger_error('Using the comma as a group separator for floats is deprecated since version 3.2 and will be removed in 4.0.', E_USER_DEPRECATED); + @trigger_error(sprintf('Using the comma as a group separator for floats is deprecated since version 3.2 and will be removed in 4.0 on line %d.', self::$parsedLineNumber + 1), E_USER_DEPRECATED); } return (float) str_replace(array(',', '_'), '', $scalar); diff --git a/src/Symfony/Component/Yaml/Parser.php b/src/Symfony/Component/Yaml/Parser.php index 81b5e0f7f69f9..3215850341693 100644 --- a/src/Symfony/Component/Yaml/Parser.php +++ b/src/Symfony/Component/Yaml/Parser.php @@ -178,7 +178,7 @@ private function doParse($value, $flags) } if (isset($values['value'][1]) && '?' === $values['value'][0] && ' ' === $values['value'][1]) { - @trigger_error('Starting an unquoted string with a question mark followed by a space is deprecated since version 3.3 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0.', E_USER_DEPRECATED); + @trigger_error(sprintf('Starting an unquoted string with a question mark followed by a space is deprecated since version 3.3 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0 on line %d.', $this->getRealCurrentLineNb() + 1), E_USER_DEPRECATED); } // array @@ -238,7 +238,7 @@ private function doParse($value, $flags) if (!(Yaml::PARSE_KEYS_AS_STRINGS & $flags) && !is_string($key) && !is_int($key)) { $keyType = is_numeric($key) ? 'numeric key' : 'non-string key'; - @trigger_error(sprintf('Implicit casting of %s to string is deprecated since version 3.3 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0. Quote your evaluable mapping keys instead.', $keyType), E_USER_DEPRECATED); + @trigger_error(sprintf('Implicit casting of %s to string is deprecated since version 3.3 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0. Quote your evaluable mapping keys instead on line %d.', $keyType, $this->getRealCurrentLineNb() + 1), E_USER_DEPRECATED); } // Convert float keys to strings, to avoid being converted to integers by PHP @@ -312,7 +312,7 @@ private function doParse($value, $flags) $data[$key] = null; } } else { - @trigger_error(sprintf('Duplicate key "%s" detected whilst parsing YAML. Silent handling of duplicate mapping keys in YAML is deprecated since version 3.2 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0.', $key), E_USER_DEPRECATED); + @trigger_error(sprintf('Duplicate key "%s" detected whilst parsing YAML. Silent handling of duplicate mapping keys in YAML is deprecated since version 3.2 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0 on line %d.', $key, $this->getRealCurrentLineNb() + 1), E_USER_DEPRECATED); } } else { // remember the parsed line number here in case we need it to provide some contexts in error messages below @@ -327,7 +327,7 @@ private function doParse($value, $flags) $data[$key] = $value; } } else { - @trigger_error(sprintf('Duplicate key "%s" detected whilst parsing YAML. Silent handling of duplicate mapping keys in YAML is deprecated since version 3.2 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0.', $key), E_USER_DEPRECATED); + @trigger_error(sprintf('Duplicate key "%s" detected whilst parsing YAML. Silent handling of duplicate mapping keys in YAML is deprecated since version 3.2 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0 on line %d.', $key, $realCurrentLineNbKey + 1), E_USER_DEPRECATED); } } } else { @@ -337,7 +337,7 @@ private function doParse($value, $flags) if ($allowOverwrite || !isset($data[$key])) { $data[$key] = $value; } else { - @trigger_error(sprintf('Duplicate key "%s" detected whilst parsing YAML. Silent handling of duplicate mapping keys in YAML is deprecated since version 3.2 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0.', $key), E_USER_DEPRECATED); + @trigger_error(sprintf('Duplicate key "%s" detected whilst parsing YAML. Silent handling of duplicate mapping keys in YAML is deprecated since version 3.2 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0 on line %d.', $key, $this->getRealCurrentLineNb() + 1), E_USER_DEPRECATED); } } if ($isRef) { @@ -350,7 +350,7 @@ private function doParse($value, $flags) } if (isset($this->currentLine[1]) && '?' === $this->currentLine[0] && ' ' === $this->currentLine[1]) { - @trigger_error('Starting an unquoted string with a question mark followed by a space is deprecated since version 3.3 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0.', E_USER_DEPRECATED); + @trigger_error(sprintf('Starting an unquoted string with a question mark followed by a space is deprecated since version 3.3 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0 on line %d.', $this->getRealCurrentLineNb() + 1), E_USER_DEPRECATED); } // 1-liner optionally followed by newline(s) @@ -663,7 +663,7 @@ private function parseValue($value, $flags, $context) if ('!!binary' === $matches['tag']) { return Inline::evaluateBinaryScalar($data); } elseif ('!' !== $matches['tag']) { - @trigger_error(sprintf('Using the custom tag "%s" for the value "%s" is deprecated since version 3.3. It will be replaced by an instance of %s in 4.0.', $matches['tag'], $data, TaggedValue::class), E_USER_DEPRECATED); + @trigger_error(sprintf('Using the custom tag "%s" for the value "%s" is deprecated since version 3.3. It will be replaced by an instance of %s in 4.0 on line %d.', $matches['tag'], $data, TaggedValue::class, $this->getRealCurrentLineNb() + 1), E_USER_DEPRECATED); } } diff --git a/src/Symfony/Component/Yaml/Tests/InlineTest.php b/src/Symfony/Component/Yaml/Tests/InlineTest.php index 665c2ecc29f33..a23bd6dc4c115 100644 --- a/src/Symfony/Component/Yaml/Tests/InlineTest.php +++ b/src/Symfony/Component/Yaml/Tests/InlineTest.php @@ -168,7 +168,7 @@ public function testParseInvalidMappingKeyShouldThrowException() /** * @group legacy - * @expectedDeprecation Using a colon after an unquoted mapping key that is not followed by an indication character (i.e. " ", ",", "[", "]", "{", "}") is deprecated since version 3.2 and will throw a ParseException in 4.0. + * @expectedDeprecation Using a colon after an unquoted mapping key that is not followed by an indication character (i.e. " ", ",", "[", "]", "{", "}") is deprecated since version 3.2 and will throw a ParseException in 4.0 on line 1. * throws \Symfony\Component\Yaml\Exception\ParseException in 4.0 */ public function testParseMappingKeyWithColonNotFollowedBySpace() @@ -304,7 +304,7 @@ public function getScalarIndicators() /** * @group legacy - * @expectedDeprecation Not quoting the scalar "%bar " starting with the "%" indicator character is deprecated since Symfony 3.1 and will throw a ParseException in 4.0. + * @expectedDeprecation Not quoting the scalar "%bar " starting with the "%" indicator character is deprecated since Symfony 3.1 and will throw a ParseException in 4.0 on line 1. * throws \Symfony\Component\Yaml\Exception\ParseException in 4.0 */ public function testParseUnquotedScalarStartingWithPercentCharacter() @@ -700,7 +700,7 @@ public function testVeryLongQuotedStrings() /** * @group legacy - * @expectedDeprecation Omitting the key of a mapping is deprecated and will throw a ParseException in 4.0. + * @expectedDeprecation Omitting the key of a mapping is deprecated and will throw a ParseException in 4.0 on line 1. */ public function testOmittedMappingKeyIsParsedAsColon() { @@ -730,7 +730,7 @@ public function testTheEmptyStringIsAValidMappingKey() /** * @group legacy - * @expectedDeprecation Implicit casting of incompatible mapping keys to strings is deprecated since version 3.3 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0. Quote your evaluable mapping keys instead. + * @expectedDeprecation Implicit casting of incompatible mapping keys to strings is deprecated since version 3.3 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0. Quote your evaluable mapping keys instead on line 1. * @dataProvider getNotPhpCompatibleMappingKeyData */ public function testImplicitStringCastingOfMappingKeysIsDeprecated($yaml, $expected) diff --git a/src/Symfony/Component/Yaml/Tests/ParserTest.php b/src/Symfony/Component/Yaml/Tests/ParserTest.php index 620eff32d967c..92f00664eb07e 100644 --- a/src/Symfony/Component/Yaml/Tests/ParserTest.php +++ b/src/Symfony/Component/Yaml/Tests/ParserTest.php @@ -61,7 +61,7 @@ public function testSpecifications($expected, $yaml, $comment, $deprecated) restore_error_handler(); $this->assertCount(1, $deprecations); - $this->assertContains('Using the comma as a group separator for floats is deprecated since version 3.2 and will be removed in 4.0.', $deprecations[0]); + $this->assertContains('Using the comma as a group separator for floats is deprecated since version 3.2 and will be removed in 4.0 on line 1.', $deprecations[0]); } } @@ -853,7 +853,7 @@ public function testMappingDuplicateKeyFlow() /** * @group legacy * @dataProvider getParseExceptionOnDuplicateData - * @expectedDeprecation Duplicate key "%s" detected whilst parsing YAML. Silent handling of duplicate mapping keys in YAML is deprecated %s. + * @expectedDeprecation Duplicate key "%s" detected whilst parsing YAML. Silent handling of duplicate mapping keys in YAML is deprecated %s and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0 on line %d. * throws \Symfony\Component\Yaml\Exception\ParseException in 4.0 */ public function testParseExceptionOnDuplicate($input, $duplicateKey, $lineNumber) @@ -1081,7 +1081,7 @@ public function testYamlDirective() /** * @group legacy - * @expectedDeprecation Implicit casting of numeric key to string is deprecated since version 3.3 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0. Quote your evaluable mapping keys instead. + * @expectedDeprecation Implicit casting of numeric key to string is deprecated since version 3.3 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0. Quote your evaluable mapping keys instead on line 2. */ public function testFloatKeys() { @@ -1103,7 +1103,7 @@ public function testFloatKeys() /** * @group legacy - * @expectedDeprecation Implicit casting of non-string key to string is deprecated since version 3.3 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0. Quote your evaluable mapping keys instead. + * @expectedDeprecation Implicit casting of non-string key to string is deprecated since version 3.3 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0. Quote your evaluable mapping keys instead on line 1. */ public function testBooleanKeys() { @@ -1682,7 +1682,7 @@ public function testCustomTagsDisabled() /** * @group legacy - * @expectedDeprecation Using the unquoted scalar value "!iterator foo" is deprecated since version 3.3 and will be considered as a tagged value in 4.0. You must quote it. + * @expectedDeprecation Using the unquoted scalar value "!iterator foo" is deprecated since version 3.3 and will be considered as a tagged value in 4.0. You must quote it on line 1. */ public function testUnsupportedTagWithScalar() { @@ -1700,7 +1700,7 @@ public function testExceptionWhenUsingUnsuportedBuiltInTags() /** * @group legacy - * @expectedDeprecation Starting an unquoted string with a question mark followed by a space is deprecated since version 3.3 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0. + * @expectedDeprecation Starting an unquoted string with a question mark followed by a space is deprecated since version 3.3 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0 on line 1. */ public function testComplexMappingThrowsParseException() { @@ -1715,7 +1715,7 @@ public function testComplexMappingThrowsParseException() /** * @group legacy - * @expectedDeprecation Starting an unquoted string with a question mark followed by a space is deprecated since version 3.3 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0. + * @expectedDeprecation Starting an unquoted string with a question mark followed by a space is deprecated since version 3.3 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0 on line 2. */ public function testComplexMappingNestedInMappingThrowsParseException() { @@ -1731,7 +1731,7 @@ public function testComplexMappingNestedInMappingThrowsParseException() /** * @group legacy - * @expectedDeprecation Starting an unquoted string with a question mark followed by a space is deprecated since version 3.3 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0. + * @expectedDeprecation Starting an unquoted string with a question mark followed by a space is deprecated since version 3.3 and will throw \Symfony\Component\Yaml\Exception\ParseException in 4.0 on line 1. */ public function testComplexMappingNestedInSequenceThrowsParseException() { From 0851189daaaba5d2e8267ef5534daf721a16974e Mon Sep 17 00:00:00 2001 From: Ryan Weaver Date: Tue, 26 Sep 2017 15:22:45 -0400 Subject: [PATCH 0939/1099] Adding a shortcuts for the main security functionality --- .../Bundle/SecurityBundle/CHANGELOG.md | 2 + .../Resources/config/security.xml | 13 +++ .../Tests/Functional/SecurityTest.php | 34 +++++++ .../Functional/app/SecurityHelper/bundles.php | 20 ++++ .../Functional/app/SecurityHelper/config.yml | 18 ++++ src/Symfony/Component/Security/CHANGELOG.md | 1 + .../Component/Security/Core/Security.php | 54 ++++++++++- .../Security/Core/Tests/SecurityTest.php | 97 +++++++++++++++++++ .../Component/Security/Core/composer.json | 2 + src/Symfony/Component/Security/composer.json | 2 + 10 files changed, 240 insertions(+), 3 deletions(-) create mode 100644 src/Symfony/Bundle/SecurityBundle/Tests/Functional/SecurityTest.php create mode 100644 src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/SecurityHelper/bundles.php create mode 100644 src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/SecurityHelper/config.yml create mode 100644 src/Symfony/Component/Security/Core/Tests/SecurityTest.php diff --git a/src/Symfony/Bundle/SecurityBundle/CHANGELOG.md b/src/Symfony/Bundle/SecurityBundle/CHANGELOG.md index b759b693cd273..269eefd43e910 100644 --- a/src/Symfony/Bundle/SecurityBundle/CHANGELOG.md +++ b/src/Symfony/Bundle/SecurityBundle/CHANGELOG.md @@ -4,6 +4,8 @@ CHANGELOG 3.4.0 ----- + * Added new `security.helper` service that is an instance of `Symfony\Component\Security\Core\Security` + and provides shortcuts for common security tasks. * Tagging voters with the `security.voter` tag without implementing the `VoterInterface` on the class is now deprecated and will be removed in 4.0. * [BC BREAK] `FirewallContext::getListeners()` now returns `\Traversable|array` diff --git a/src/Symfony/Bundle/SecurityBundle/Resources/config/security.xml b/src/Symfony/Bundle/SecurityBundle/Resources/config/security.xml index 049d67f5a05b1..0225df0ee47ae 100644 --- a/src/Symfony/Bundle/SecurityBundle/Resources/config/security.xml +++ b/src/Symfony/Bundle/SecurityBundle/Resources/config/security.xml @@ -26,6 +26,19 @@ + + + + + + + + + + + + + diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/SecurityTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/SecurityTest.php new file mode 100644 index 0000000000000..bcf8a0d620c93 --- /dev/null +++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/SecurityTest.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\Bundle\SecurityBundle\Tests\Functional; + +use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken; +use Symfony\Component\Security\Core\User\User; + +class SecurityTest extends WebTestCase +{ + public function testServiceIsFunctional() + { + $kernel = self::createKernel(array('test_case' => 'SecurityHelper', 'root_config' => 'config.yml')); + $kernel->boot(); + $container = $kernel->getContainer(); + + // put a token into the storage so the final calls can function + $user = new User('foo', 'pass'); + $token = new UsernamePasswordToken($user, '', 'provider', array('ROLE_USER')); + $container->get('security.token_storage')->setToken($token); + + $security = $container->get('functional_test.security.helper'); + $this->assertTrue($security->isGranted('ROLE_USER')); + $this->assertSame($token, $security->getToken()); + } +} diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/SecurityHelper/bundles.php b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/SecurityHelper/bundles.php new file mode 100644 index 0000000000000..2a8e7a2ff88d2 --- /dev/null +++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/SecurityHelper/bundles.php @@ -0,0 +1,20 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +use Symfony\Bundle\TwigBundle\TwigBundle; +use Symfony\Bundle\SecurityBundle\SecurityBundle; +use Symfony\Bundle\FrameworkBundle\FrameworkBundle; + +return array( + new FrameworkBundle(), + new SecurityBundle(), + new TwigBundle(), +); diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/SecurityHelper/config.yml b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/SecurityHelper/config.yml new file mode 100644 index 0000000000000..d7b8ac97d9775 --- /dev/null +++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/SecurityHelper/config.yml @@ -0,0 +1,18 @@ +imports: + - { resource: ./../config/default.yml } + +services: + # alias the service so we can access it in the tests + functional_test.security.helper: + alias: security.helper + public: true + +security: + providers: + in_memory: + memory: + users: [] + + firewalls: + default: + anonymous: ~ diff --git a/src/Symfony/Component/Security/CHANGELOG.md b/src/Symfony/Component/Security/CHANGELOG.md index 5ac97ca8b20bb..e0ac7afe2f50c 100644 --- a/src/Symfony/Component/Security/CHANGELOG.md +++ b/src/Symfony/Component/Security/CHANGELOG.md @@ -4,6 +4,7 @@ CHANGELOG 3.4.0 ----- + * Added `getUser`, `getToken` and `isGranted` methods to `Security`. * added a `setToken()` method to the `SwitchUserEvent` class to allow to replace the created token while switching users when custom token generation is required by application. * Using voters that do not implement the `VoterInterface`is now deprecated in diff --git a/src/Symfony/Component/Security/Core/Security.php b/src/Symfony/Component/Security/Core/Security.php index 84cc77dcf7f32..5f25b41ccade5 100644 --- a/src/Symfony/Component/Security/Core/Security.php +++ b/src/Symfony/Component/Security/Core/Security.php @@ -11,10 +11,12 @@ namespace Symfony\Component\Security\Core; +use Psr\Container\ContainerInterface; +use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; +use Symfony\Component\Security\Core\User\UserInterface; + /** - * This class holds security information. - * - * @author Johannes M. Schmitt + * Helper class for commonly-needed security tasks. */ final class Security { @@ -22,4 +24,50 @@ final class Security const AUTHENTICATION_ERROR = '_security.last_error'; const LAST_USERNAME = '_security.last_username'; const MAX_USERNAME_LENGTH = 4096; + + private $container; + + public function __construct(ContainerInterface $container) + { + $this->container = $container; + } + + /** + * @return UserInterface|null + */ + public function getUser() + { + if (!$token = $this->getToken()) { + return null; + } + + $user = $token->getUser(); + if (!is_object($user)) { + return null; + } + + return $user; + } + + /** + * Checks if the attributes are granted against the current authentication token and optionally supplied subject. + * + * @param mixed $attributes + * @param mixed $subject + * + * @return bool + */ + public function isGranted($attributes, $subject = null) + { + return $this->container->get('security.authorization_checker') + ->isGranted($attributes, $subject); + } + + /** + * @return TokenInterface|null + */ + public function getToken() + { + return $this->container->get('security.token_storage')->getToken(); + } } diff --git a/src/Symfony/Component/Security/Core/Tests/SecurityTest.php b/src/Symfony/Component/Security/Core/Tests/SecurityTest.php new file mode 100644 index 0000000000000..b2ba5d0d5fa1d --- /dev/null +++ b/src/Symfony/Component/Security/Core/Tests/SecurityTest.php @@ -0,0 +1,97 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Security\Core\Tests; + +use PHPUnit\Framework\TestCase; +use Psr\Container\ContainerInterface; +use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface; +use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; +use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken; +use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface; +use Symfony\Component\Security\Core\Security; +use Symfony\Component\Security\Core\User\User; + +class SecurityTest extends TestCase +{ + public function testGetToken() + { + $token = new UsernamePasswordToken('foo', 'bar', 'provider'); + $tokenStorage = $this->getMockBuilder(TokenStorageInterface::class)->getMock(); + + $tokenStorage->expects($this->once()) + ->method('getToken') + ->will($this->returnValue($token)); + + $container = $this->createContainer('security.token_storage', $tokenStorage); + + $security = new Security($container); + $this->assertSame($token, $security->getToken()); + } + + /** + * @dataProvider getUserTests + */ + public function testGetUser($userInToken, $expectedUser) + { + $token = $this->getMockBuilder(TokenInterface::class)->getMock(); + $token->expects($this->any()) + ->method('getUser') + ->will($this->returnValue($userInToken)); + $tokenStorage = $this->getMockBuilder(TokenStorageInterface::class)->getMock(); + + $tokenStorage->expects($this->once()) + ->method('getToken') + ->will($this->returnValue($token)); + + $container = $this->createContainer('security.token_storage', $tokenStorage); + + $security = new Security($container); + $this->assertSame($expectedUser, $security->getUser()); + } + + public function getUserTests() + { + yield array(null, null); + + yield array('string_username', null); + + $user = new User('nice_user', 'foo'); + yield array($user, $user); + } + + public function testIsGranted() + { + $authorizationChecker = $this->getMockBuilder(AuthorizationCheckerInterface::class)->getMock(); + + $authorizationChecker->expects($this->once()) + ->method('isGranted') + ->with('SOME_ATTRIBUTE', 'SOME_SUBJECT') + ->will($this->returnValue(true)); + + $container = $this->createContainer('security.authorization_checker', $authorizationChecker); + + $security = new Security($container); + $this->assertTrue($security->isGranted('SOME_ATTRIBUTE', 'SOME_SUBJECT')); + } + + private function createContainer($serviceId, $serviceObject) + { + $container = $this->getMockBuilder(ContainerInterface::class)->getMock(); + + $container->expects($this->atLeastOnce()) + ->method('get') + ->with($serviceId) + ->will($this->returnValue($serviceObject)); + + return $container; + } +} diff --git a/src/Symfony/Component/Security/Core/composer.json b/src/Symfony/Component/Security/Core/composer.json index 2bba025ae4b53..b70ef54004ff6 100644 --- a/src/Symfony/Component/Security/Core/composer.json +++ b/src/Symfony/Component/Security/Core/composer.json @@ -20,6 +20,7 @@ "symfony/polyfill-php56": "~1.0" }, "require-dev": { + "psr/container": "^1.0", "symfony/event-dispatcher": "~2.8|~3.0|~4.0", "symfony/expression-language": "~2.8|~3.0|~4.0", "symfony/http-foundation": "~2.8|~3.0|~4.0", @@ -28,6 +29,7 @@ "psr/log": "~1.0" }, "suggest": { + "psr/container": "To instantiate the Security class", "symfony/event-dispatcher": "", "symfony/http-foundation": "", "symfony/validator": "For using the user password constraint", diff --git a/src/Symfony/Component/Security/composer.json b/src/Symfony/Component/Security/composer.json index e53bf6d53783f..bc72e8469bf0e 100644 --- a/src/Symfony/Component/Security/composer.json +++ b/src/Symfony/Component/Security/composer.json @@ -32,6 +32,7 @@ "symfony/security-http": "self.version" }, "require-dev": { + "psr/container": "^1.0", "symfony/finder": "~2.8|~3.0|~4.0", "symfony/polyfill-intl-icu": "~1.0", "symfony/routing": "~2.8|~3.0|~4.0", @@ -41,6 +42,7 @@ "psr/log": "~1.0" }, "suggest": { + "psr/container": "To instantiate the Security class", "symfony/form": "", "symfony/validator": "For using the user password constraint", "symfony/routing": "For using the HttpUtils class to create sub-requests, redirect the user, and match URLs", From 08deb372f1a2fe2355445ba8e01f0b6aa98d7d9d Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Thu, 28 Sep 2017 19:06:05 +0200 Subject: [PATCH 0940/1099] [DependencyInjection] fix tests --- .../Tests/Fixtures/php/services9_as_files.txt | 7 +++---- .../Tests/Fixtures/php/services9_compiled.php | 15 ++------------- 2 files changed, 5 insertions(+), 17 deletions(-) diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_as_files.txt b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_as_files.txt index 75562d178a286..22135fa6a91c9 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_as_files.txt +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_as_files.txt @@ -274,8 +274,8 @@ use Symfony\Component\DependencyInjection\Argument\RewindableGenerator; // Returns the public 'tagged_iterator' shared service. return $this->services['tagged_iterator'] = new \Bar(new RewindableGenerator(function () { - yield 0 => ${($_ = isset($this->services['foo']) ? $this->services['foo'] : $this->load(__DIR__.'/getFooService.php')) && false ?: '_'}; - yield 1 => ${($_ = isset($this->services['tagged_iterator_foo']) ? $this->services['tagged_iterator_foo'] : $this->services['tagged_iterator_foo'] = new \Bar()) && false ?: '_'}; + yield 0 => ($this->services['foo'] ?? $this->load(__DIR__.'/getFooService.php')); + yield 1 => ($this->privates['tagged_iterator_foo'] ?? $this->privates['tagged_iterator_foo'] = new \Bar()); }, 2)); [Container%s/getTaggedIteratorFooService.php] => services['tagged_iterator_foo'] = new \Bar(); +return $this->privates['tagged_iterator_foo'] = new \Bar(); [Container%s/Container.php] => __DIR__.'/getNewFactoryServiceService.php', 'service_from_static_method' => __DIR__.'/getServiceFromStaticMethodService.php', 'tagged_iterator' => __DIR__.'/getTaggedIteratorService.php', - 'tagged_iterator_foo' => __DIR__.'/getTaggedIteratorFooService.php', ); $this->aliases = array( 'alias_for_alias' => 'foo', diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_compiled.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_compiled.php index fce5f72271916..ed8861e137a04 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_compiled.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_compiled.php @@ -53,7 +53,6 @@ public function __construct() 'new_factory_service' => 'getNewFactoryServiceService', 'service_from_static_method' => 'getServiceFromStaticMethodService', 'tagged_iterator' => 'getTaggedIteratorService', - 'tagged_iterator_foo' => 'getTaggedIteratorFooService', ); $this->aliases = array( 'alias_for_alias' => 'foo', @@ -382,8 +381,8 @@ protected function getServiceFromStaticMethodService() protected function getTaggedIteratorService() { return $this->services['tagged_iterator'] = new \Bar(new RewindableGenerator(function () { - yield 0 => ${($_ = isset($this->services['foo']) ? $this->services['foo'] : $this->getFooService()) && false ?: '_'}; - yield 1 => ${($_ = isset($this->services['tagged_iterator_foo']) ? $this->services['tagged_iterator_foo'] : $this->services['tagged_iterator_foo'] = new \Bar()) && false ?: '_'}; + yield 0 => ($this->services['foo'] ?? $this->getFooService()); + yield 1 => ($this->privates['tagged_iterator_foo'] ?? $this->privates['tagged_iterator_foo'] = new \Bar()); }, 2)); } @@ -401,16 +400,6 @@ protected function getFactorySimpleService() return $this->privates['factory_simple'] = new \SimpleFactoryClass('foo'); } - /** - * Gets the private 'tagged_iterator_foo' shared service. - * - * @return \Bar - */ - protected function getTaggedIteratorFooService() - { - return $this->services['tagged_iterator_foo'] = new \Bar(); - } - /** * {@inheritdoc} */ From 95358ac98f9a871d7e81a9498c462d30cbdc086d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9my=20Deruss=C3=A9?= Date: Thu, 28 Sep 2017 19:35:07 +0200 Subject: [PATCH 0941/1099] Share connection factories between cache and lock --- .../FrameworkExtension.php | 3 +- .../Component/Lock/Store/MemcachedStore.php | 122 ------------------ .../Component/Lock/Store/RedisStore.php | 82 ------------ .../Component/Lock/Store/StoreFactory.php | 15 --- .../Lock/Tests/Store/MemcachedStoreTest.php | 96 -------------- 5 files changed, 2 insertions(+), 316 deletions(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php index 4c7b4dfe67716..dafecf9d581d6 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php @@ -23,6 +23,7 @@ use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Bundle\FrameworkBundle\Controller\Controller; use Symfony\Bundle\FrameworkBundle\Routing\AnnotatedRouteControllerLoader; +use Symfony\Component\Cache\Adapter\AbstractAdapter; use Symfony\Component\Cache\Adapter\AdapterInterface; use Symfony\Component\Cache\Adapter\ArrayAdapter; use Symfony\Component\Cache\ResettableInterface; @@ -1706,7 +1707,7 @@ private function registerLockConfiguration(array $config, ContainerBuilder $cont if (!$container->hasDefinition($connectionDefinitionId = $container->hash($storeDsn))) { $connectionDefinition = new Definition(\stdClass::class); $connectionDefinition->setPublic(false); - $connectionDefinition->setFactory(array(StoreFactory::class, 'createConnection')); + $connectionDefinition->setFactory(array(AbstractAdapter::class, 'createConnection')); $connectionDefinition->setArguments(array($storeDsn)); $container->setDefinition($connectionDefinitionId, $connectionDefinition); } diff --git a/src/Symfony/Component/Lock/Store/MemcachedStore.php b/src/Symfony/Component/Lock/Store/MemcachedStore.php index 4a2ffa3e02042..beaad69962084 100644 --- a/src/Symfony/Component/Lock/Store/MemcachedStore.php +++ b/src/Symfony/Component/Lock/Store/MemcachedStore.php @@ -58,128 +58,6 @@ public function __construct(\Memcached $memcached, $initialTtl = 300) $this->initialTtl = $initialTtl; } - /** - * Creates a Memcached instance. - * - * By default, the binary protocol, block, and libketama compatible options are enabled. - * - * Example DSN: - * - 'memcached://user:pass@localhost?weight=33' - * - array(array('localhost', 11211, 33)) - * - * @param string $dsn A server or A DSN - * @param array $options An array of options - * - * @return \Memcached - * - * @throws \ErrorEception When invalid options or server are provided - */ - public static function createConnection($server, array $options = array()) - { - if (!static::isSupported()) { - throw new InvalidArgumentException('Memcached extension is required'); - } - set_error_handler(function ($type, $msg, $file, $line) { throw new \ErrorException($msg, 0, $type, $file, $line); }); - try { - $options += static::$defaultClientOptions; - $client = new \Memcached($options['persistent_id']); - $username = $options['username']; - $password = $options['password']; - - // parse any DSN in $server - if (is_string($server)) { - if (0 !== strpos($server, 'memcached://')) { - throw new InvalidArgumentException(sprintf('Invalid Memcached DSN: %s does not start with "memcached://"', $server)); - } - $params = preg_replace_callback('#^memcached://(?:([^@]*+)@)?#', function ($m) use (&$username, &$password) { - if (!empty($m[1])) { - list($username, $password) = explode(':', $m[1], 2) + array(1 => null); - } - - return 'file://'; - }, $server); - if (false === $params = parse_url($params)) { - throw new InvalidArgumentException(sprintf('Invalid Memcached DSN: %s', $server)); - } - if (!isset($params['host']) && !isset($params['path'])) { - throw new InvalidArgumentException(sprintf('Invalid Memcached DSN: %s', $server)); - } - if (isset($params['path']) && preg_match('#/(\d+)$#', $params['path'], $m)) { - $params['weight'] = $m[1]; - $params['path'] = substr($params['path'], 0, -strlen($m[0])); - } - $params += array( - 'host' => isset($params['host']) ? $params['host'] : $params['path'], - 'port' => isset($params['host']) ? 11211 : null, - 'weight' => 0, - ); - if (isset($params['query'])) { - parse_str($params['query'], $query); - $params += $query; - $options = $query + $options; - } - - $server = array($params['host'], $params['port'], $params['weight']); - } - - // set client's options - unset($options['persistent_id'], $options['username'], $options['password'], $options['weight']); - $options = array_change_key_case($options, CASE_UPPER); - $client->setOption(\Memcached::OPT_BINARY_PROTOCOL, true); - $client->setOption(\Memcached::OPT_NO_BLOCK, false); - if (!array_key_exists('LIBKETAMA_COMPATIBLE', $options) && !array_key_exists(\Memcached::OPT_LIBKETAMA_COMPATIBLE, $options)) { - $client->setOption(\Memcached::OPT_LIBKETAMA_COMPATIBLE, true); - } - foreach ($options as $name => $value) { - if (is_int($name)) { - continue; - } - if ('HASH' === $name || 'SERIALIZER' === $name || 'DISTRIBUTION' === $name) { - $value = constant('Memcached::'.$name.'_'.strtoupper($value)); - } - $opt = constant('Memcached::OPT_'.$name); - - unset($options[$name]); - $options[$opt] = $value; - } - $client->setOptions($options); - - // set client's servers, taking care of persistent connections - if (!$client->isPristine()) { - $oldServers = array(); - foreach ($client->getServerList() as $server) { - $oldServers[] = array($server['host'], $server['port']); - } - - $newServers = array(); - if (1 < count($server)) { - $server = array_values($server); - unset($server[2]); - $server[1] = (int) $server[1]; - } - $newServers[] = $server; - - if ($oldServers !== $newServers) { - // before resetting, ensure $servers is valid - $client->addServers(array($server)); - $client->resetServerList(); - } - } - $client->addServers(array($server)); - - if (null !== $username || null !== $password) { - if (!method_exists($client, 'setSaslAuthData')) { - trigger_error('Missing SASL support: the memcached extension must be compiled with --enable-memcached-sasl.'); - } - $client->setSaslAuthData($username, $password); - } - - return $client; - } finally { - restore_error_handler(); - } - } - /** * {@inheritdoc} */ diff --git a/src/Symfony/Component/Lock/Store/RedisStore.php b/src/Symfony/Component/Lock/Store/RedisStore.php index 66a067dfb0f9d..9f17e49b78668 100644 --- a/src/Symfony/Component/Lock/Store/RedisStore.php +++ b/src/Symfony/Component/Lock/Store/RedisStore.php @@ -53,88 +53,6 @@ public function __construct($redisClient, $initialTtl = 300.0) $this->initialTtl = $initialTtl; } - /** - * Creates a Redis connection using a DSN configuration. - * - * Example DSN: - * - redis://localhost - * - redis://example.com:1234 - * - redis://secret@example.com/13 - * - redis:///var/run/redis.sock - * - redis://secret@/var/run/redis.sock/13 - * - * @param string $dsn - * @param array $options See self::$defaultConnectionOptions - * - * @throws InvalidArgumentException When the DSN is invalid - * - * @return \Redis|\Predis\Client According to the "class" option - */ - public static function createConnection($dsn, array $options = array()) - { - if (0 !== strpos($dsn, 'redis://')) { - throw new InvalidArgumentException(sprintf('Invalid Redis DSN: %s does not start with "redis://"', $dsn)); - } - $params = preg_replace_callback('#^redis://(?:(?:[^:@]*+:)?([^@]*+)@)?#', function ($m) use (&$auth) { - if (isset($m[1])) { - $auth = $m[1]; - } - - return 'file://'; - }, $dsn); - if (false === $params = parse_url($params)) { - throw new InvalidArgumentException(sprintf('Invalid Redis DSN: %s', $dsn)); - } - if (!isset($params['host']) && !isset($params['path'])) { - throw new InvalidArgumentException(sprintf('Invalid Redis DSN: %s', $dsn)); - } - if (isset($params['path']) && preg_match('#/(\d+)$#', $params['path'], $m)) { - $params['dbindex'] = $m[1]; - $params['path'] = substr($params['path'], 0, -strlen($m[0])); - } - $params += array( - 'host' => isset($params['host']) ? $params['host'] : $params['path'], - 'port' => isset($params['host']) ? 6379 : null, - 'dbindex' => 0, - ); - if (isset($params['query'])) { - parse_str($params['query'], $query); - $params += $query; - } - $params += $options + self::$defaultConnectionOptions; - $class = null === $params['class'] ? (extension_loaded('redis') ? \Redis::class : \Predis\Client::class) : $params['class']; - - if (is_a($class, \Redis::class, true)) { - $connect = $params['persistent'] || $params['persistent_id'] ? 'pconnect' : 'connect'; - $redis = new $class(); - @$redis->{$connect}($params['host'], $params['port'], $params['timeout'], $params['persistent_id'], $params['retry_interval']); - - if (@!$redis->isConnected()) { - $e = ($e = error_get_last()) && preg_match('/^Redis::p?connect\(\): (.*)/', $e['message'], $e) ? sprintf(' (%s)', $e[1]) : ''; - throw new InvalidArgumentException(sprintf('Redis connection failed%s: %s', $e, $dsn)); - } - - if ((null !== $auth && !$redis->auth($auth)) - || ($params['dbindex'] && !$redis->select($params['dbindex'])) - || ($params['read_timeout'] && !$redis->setOption(\Redis::OPT_READ_TIMEOUT, $params['read_timeout'])) - ) { - $e = preg_replace('/^ERR /', '', $redis->getLastError()); - throw new InvalidArgumentException(sprintf('Redis connection failed (%s): %s', $e, $dsn)); - } - } elseif (is_a($class, \Predis\Client::class, true)) { - $params['scheme'] = isset($params['host']) ? 'tcp' : 'unix'; - $params['database'] = $params['dbindex'] ?: null; - $params['password'] = $auth; - $redis = new $class((new Factory())->create($params)); - } elseif (class_exists($class, false)) { - throw new InvalidArgumentException(sprintf('"%s" is not a subclass of "Redis" or "Predis\Client"', $class)); - } else { - throw new InvalidArgumentException(sprintf('Class "%s" does not exist', $class)); - } - - return $redis; - } - /** * {@inheritdoc} */ diff --git a/src/Symfony/Component/Lock/Store/StoreFactory.php b/src/Symfony/Component/Lock/Store/StoreFactory.php index 9a23cf6472dea..eccaeaf97473c 100644 --- a/src/Symfony/Component/Lock/Store/StoreFactory.php +++ b/src/Symfony/Component/Lock/Store/StoreFactory.php @@ -20,21 +20,6 @@ */ class StoreFactory { - public static function createConnection($dsn, array $options = array()) - { - if (!is_string($dsn)) { - throw new InvalidArgumentException(sprintf('The %s() method expects argument #1 to be string, %s given.', __METHOD__, gettype($dsn))); - } - if (0 === strpos($dsn, 'redis://')) { - return RedisStore::createConnection($dsn, $options); - } - if (0 === strpos($dsn, 'memcached://')) { - return MemcachedStore::createConnection($dsn, $options); - } - - throw new InvalidArgumentException(sprintf('Unsupported DSN: %s.', $dsn)); - } - /** * @param \Redis|\RedisArray|\RedisCluster|\Predis\Client|\Memcached $connection * diff --git a/src/Symfony/Component/Lock/Tests/Store/MemcachedStoreTest.php b/src/Symfony/Component/Lock/Tests/Store/MemcachedStoreTest.php index cfe03b25e2c34..eb030fba0f9de 100644 --- a/src/Symfony/Component/Lock/Tests/Store/MemcachedStoreTest.php +++ b/src/Symfony/Component/Lock/Tests/Store/MemcachedStoreTest.php @@ -54,100 +54,4 @@ public function testAbortAfterExpiration() { $this->markTestSkipped('Memcached expects a TTL greater than 1 sec. Simulating a slow network is too hard'); } - - public function testDefaultOptions() - { - $this->assertTrue(MemcachedStore::isSupported()); - - $client = MemcachedStore::createConnection('memcached://127.0.0.1'); - - $this->assertTrue($client->getOption(\Memcached::OPT_COMPRESSION)); - $this->assertSame(1, $client->getOption(\Memcached::OPT_BINARY_PROTOCOL)); - $this->assertSame(1, $client->getOption(\Memcached::OPT_LIBKETAMA_COMPATIBLE)); - } - - /** - * @dataProvider provideServersSetting - */ - public function testServersSetting($dsn, $host, $port) - { - $client1 = MemcachedStore::createConnection($dsn); - $client3 = MemcachedStore::createConnection(array($host, $port)); - $expect = array( - 'host' => $host, - 'port' => $port, - ); - - $f = function ($s) { return array('host' => $s['host'], 'port' => $s['port']); }; - $this->assertSame(array($expect), array_map($f, $client1->getServerList())); - $this->assertSame(array($expect), array_map($f, $client3->getServerList())); - } - - public function provideServersSetting() - { - yield array( - 'memcached://127.0.0.1/50', - '127.0.0.1', - 11211, - ); - yield array( - 'memcached://localhost:11222?weight=25', - 'localhost', - 11222, - ); - if (ini_get('memcached.use_sasl')) { - yield array( - 'memcached://user:password@127.0.0.1?weight=50', - '127.0.0.1', - 11211, - ); - } - yield array( - 'memcached:///var/run/memcached.sock?weight=25', - '/var/run/memcached.sock', - 0, - ); - yield array( - 'memcached:///var/local/run/memcached.socket?weight=25', - '/var/local/run/memcached.socket', - 0, - ); - if (ini_get('memcached.use_sasl')) { - yield array( - 'memcached://user:password@/var/local/run/memcached.socket?weight=25', - '/var/local/run/memcached.socket', - 0, - ); - } - } - - /** - * @dataProvider provideDsnWithOptions - */ - public function testDsnWithOptions($dsn, array $options, array $expectedOptions) - { - $client = MemcachedStore::createConnection($dsn, $options); - - foreach ($expectedOptions as $option => $expect) { - $this->assertSame($expect, $client->getOption($option)); - } - } - - public function provideDsnWithOptions() - { - if (!class_exists('\Memcached')) { - self::markTestSkipped('Extension memcached required.'); - } - - yield array( - 'memcached://localhost:11222?retry_timeout=10', - array(\Memcached::OPT_RETRY_TIMEOUT => 8), - array(\Memcached::OPT_RETRY_TIMEOUT => 10), - ); - yield array( - 'memcached://localhost:11222?socket_recv_size=1&socket_send_size=2', - array(\Memcached::OPT_RETRY_TIMEOUT => 8), - array(\Memcached::OPT_SOCKET_RECV_SIZE => 1, \Memcached::OPT_SOCKET_SEND_SIZE => 2, \Memcached::OPT_RETRY_TIMEOUT => 8), - ); - } } From 0f0a6e85e36432b8c5d6745e785ddee34f3ad343 Mon Sep 17 00:00:00 2001 From: Tobias Schultze Date: Thu, 28 Sep 2017 20:22:10 +0200 Subject: [PATCH 0942/1099] PdoSessionHandler: fix advisory lock for pgsql when session.sid_bits_per_character > 4 --- .../Storage/Handler/PdoSessionHandler.php | 33 +++++++++++++++---- 1 file changed, 27 insertions(+), 6 deletions(-) diff --git a/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/PdoSessionHandler.php b/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/PdoSessionHandler.php index 8909a5f401fdc..483e73a119a04 100644 --- a/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/PdoSessionHandler.php +++ b/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/PdoSessionHandler.php @@ -580,11 +580,11 @@ private function doAdvisoryLock($sessionId) return $releaseStmt; case 'pgsql': // Obtaining an exclusive session level advisory lock requires an integer key. - // So we convert the HEX representation of the session id to an integer. - // Since integers are signed, we have to skip one hex char to fit in the range. - if (4 === PHP_INT_SIZE) { - $sessionInt1 = hexdec(substr($sessionId, 0, 7)); - $sessionInt2 = hexdec(substr($sessionId, 7, 7)); + // When session.sid_bits_per_character > 4, the session id can contain non-hex-characters. + // So we cannot just use hexdec(). + if (4 === \PHP_INT_SIZE) { + $sessionInt1 = $this->convertStringToInt($sessionId); + $sessionInt2 = $this->convertStringToInt(substr($sessionId, 4, 4)); $stmt = $this->pdo->prepare('SELECT pg_advisory_lock(:key1, :key2)'); $stmt->bindValue(':key1', $sessionInt1, \PDO::PARAM_INT); @@ -595,7 +595,7 @@ private function doAdvisoryLock($sessionId) $releaseStmt->bindValue(':key1', $sessionInt1, \PDO::PARAM_INT); $releaseStmt->bindValue(':key2', $sessionInt2, \PDO::PARAM_INT); } else { - $sessionBigInt = hexdec(substr($sessionId, 0, 15)); + $sessionBigInt = $this->convertStringToInt($sessionId); $stmt = $this->pdo->prepare('SELECT pg_advisory_lock(:key)'); $stmt->bindValue(':key', $sessionBigInt, \PDO::PARAM_INT); @@ -613,6 +613,27 @@ private function doAdvisoryLock($sessionId) } } + /** + * Encodes the first 4 (when PHP_INT_SIZE == 4) or 8 characters of the string as an integer. + * + * Keep in mind, PHP integers are signed. + * + * @param string $string + * + * @return int + */ + private function convertStringToInt($string) + { + if (4 === \PHP_INT_SIZE) { + return (ord($string[3]) << 24) + (ord($string[2]) << 16) + (ord($string[1]) << 8) + ord($string[0]); + } + + $int1 = (ord($string[7]) << 24) + (ord($string[6]) << 16) + (ord($string[5]) << 8) + ord($string[4]); + $int2 = (ord($string[3]) << 24) + (ord($string[2]) << 16) + (ord($string[1]) << 8) + ord($string[0]); + + return $int2 + ($int1 << 32); + } + /** * Return a locking or nonlocking SQL query to read session information. * From 0a658c6eef6b74e64193b6d89bd6cde7a90f78fe Mon Sep 17 00:00:00 2001 From: Yonel Ceruto Date: Tue, 19 Sep 2017 13:13:19 -0400 Subject: [PATCH 0943/1099] Add exclusive Twig namespace for bundles path --- src/Symfony/Bundle/TwigBundle/CHANGELOG.md | 1 + .../TwigBundle/DependencyInjection/TwigExtension.php | 7 +++++++ .../Tests/DependencyInjection/TwigExtensionTest.php | 1 + 3 files changed, 9 insertions(+) diff --git a/src/Symfony/Bundle/TwigBundle/CHANGELOG.md b/src/Symfony/Bundle/TwigBundle/CHANGELOG.md index 8ba6647306e04..bdf357181f060 100644 --- a/src/Symfony/Bundle/TwigBundle/CHANGELOG.md +++ b/src/Symfony/Bundle/TwigBundle/CHANGELOG.md @@ -4,6 +4,7 @@ CHANGELOG 3.4.0 ----- + * added exclusive Twig namespace only for root bundles * deprecated `Symfony\Bundle\TwigBundle\Command\DebugCommand`, use `Symfony\Bridge\Twig\Command\DebugCommand` instead * deprecated relying on the `ContainerAwareInterface` implementation for `Symfony\Bundle\TwigBundle\Command\LintCommand` * added option to configure default path templates (via `default_path`) diff --git a/src/Symfony/Bundle/TwigBundle/DependencyInjection/TwigExtension.php b/src/Symfony/Bundle/TwigBundle/DependencyInjection/TwigExtension.php index d4450f531c322..4123ad7c66378 100644 --- a/src/Symfony/Bundle/TwigBundle/DependencyInjection/TwigExtension.php +++ b/src/Symfony/Bundle/TwigBundle/DependencyInjection/TwigExtension.php @@ -130,6 +130,13 @@ public function load(array $configs, ContainerBuilder $container) foreach ($bundle['paths'] as $path) { $twigFilesystemLoaderDefinition->addMethodCall('addPath', array($path, $namespace)); } + + // add exclusive namespace for root bundles only + // to override a bundle template that also extends itself + if (count($bundle['paths']) > 0 && 0 === count($bundle['parents'])) { + // the last path must be the bundle views directory + $twigFilesystemLoaderDefinition->addMethodCall('addPath', array(end($bundle['paths']), '!'.$namespace)); + } } if (file_exists($dir = $container->getParameter('kernel.root_dir').'/Resources/views')) { diff --git a/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/TwigExtensionTest.php b/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/TwigExtensionTest.php index 9d47948d67b77..2faaaa38fcb13 100644 --- a/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/TwigExtensionTest.php +++ b/src/Symfony/Bundle/TwigBundle/Tests/DependencyInjection/TwigExtensionTest.php @@ -198,6 +198,7 @@ public function testTwigLoaderPaths($format) array(__DIR__.'/Fixtures/Resources/TwigBundle/views', 'Twig'), array(__DIR__.'/Fixtures/templates/bundles/TwigBundle', 'Twig'), array(realpath(__DIR__.'/../..').'/Resources/views', 'Twig'), + array(realpath(__DIR__.'/../..').'/Resources/views', '!Twig'), array(__DIR__.'/Fixtures/Bundle/ChildChildChildChildTwigBundle/Resources/views', 'ChildTwig'), array(__DIR__.'/Fixtures/Bundle/ChildChildChildTwigBundle/Resources/views', 'ChildTwig'), array(__DIR__.'/Fixtures/Bundle/ChildChildTwigBundle/Resources/views', 'ChildTwig'), From fa62e5068e81c65cd2676675da4caeec438a33cc Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Thu, 28 Sep 2017 16:57:16 +0200 Subject: [PATCH 0944/1099] [HttpKernel] Deprecate some compiler passes in favor of tagged iterator args --- UPGRADE-3.4.md | 14 +++- UPGRADE-4.0.md | 14 +++- .../Bundle/FrameworkBundle/CHANGELOG.md | 6 +- .../Compiler/AddCacheClearerPass.php | 26 ++++++- .../Compiler/AddCacheWarmerPass.php | 29 ++++++- .../Compiler/ConfigCachePass.php | 4 +- .../FrameworkBundle/FrameworkBundle.php | 6 -- .../Resources/config/services.xml | 6 +- .../DependencyInjection/ConfigCachePass.php | 4 + .../ConfigCachePassTest.php | 3 + src/Symfony/Component/HttpKernel/CHANGELOG.md | 4 + .../CacheClearer/ChainCacheClearer.php | 8 +- .../CacheWarmer/CacheWarmerAggregate.php | 17 +++- .../AddCacheClearerPass.php | 50 ------------ .../AddCacheWarmerPass.php | 53 ------------- .../CacheClearer/ChainCacheClearerTest.php | 3 + .../CacheWarmer/CacheWarmerAggregateTest.php | 6 ++ .../AddCacheClearerPassTest.php | 53 ------------- .../AddCacheWarmerPassTest.php | 77 ------------------- 19 files changed, 119 insertions(+), 264 deletions(-) delete mode 100644 src/Symfony/Component/HttpKernel/DependencyInjection/AddCacheClearerPass.php delete mode 100644 src/Symfony/Component/HttpKernel/DependencyInjection/AddCacheWarmerPass.php delete mode 100644 src/Symfony/Component/HttpKernel/Tests/DependencyInjection/AddCacheClearerPassTest.php delete mode 100644 src/Symfony/Component/HttpKernel/Tests/DependencyInjection/AddCacheWarmerPassTest.php diff --git a/UPGRADE-3.4.md b/UPGRADE-3.4.md index f6d137842b400..ffc6458fecd5d 100644 --- a/UPGRADE-3.4.md +++ b/UPGRADE-3.4.md @@ -136,12 +136,10 @@ FrameworkBundle instead (e.g. `--prefix=""`) * The `Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\AddCacheClearerPass` - class has been deprecated and will be removed in 4.0. Use the - `Symfony\Component\HttpKernel\DependencyInjection\AddCacheClearerPass` class instead. + class has been deprecated and will be removed in 4.0. Use tagged iterator arguments instead. * The `Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\AddCacheWarmerPass` - class has been deprecated and will be removed in 4.0. Use the - `Symfony\Component\HttpKernel\DependencyInjection\AddCacheWarmerPass` class instead. + class has been deprecated and will be removed in 4.0. Use tagged iterator arguments instead. * The `Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\TranslationDumperPass` class has been deprecated and will be removed in 4.0. Use the @@ -260,6 +258,14 @@ HttpKernel * The `Symfony\Component\HttpKernel\Config\EnvParametersResource` class has been deprecated and will be removed in 4.0. + * The `ChainCacheClearer::add()` method has been deprecated and will be removed in 4.0, + inject the list of clearers as a constructor argument instead. + + * The `CacheWarmerAggregate::add()` and `setWarmers()` methods have been deprecated and will be removed in 4.0, + inject the list of clearers as a constructor argument instead. + + * The `CacheWarmerAggregate` and `ChainCacheClearer` classes have been made final. + Process ------- diff --git a/UPGRADE-4.0.md b/UPGRADE-4.0.md index 8174f1a4d266d..1f122c002dccf 100644 --- a/UPGRADE-4.0.md +++ b/UPGRADE-4.0.md @@ -384,7 +384,7 @@ FrameworkBundle class instead. * The `Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\ConfigCachePass` class has been removed. - Use `Symfony\Component\Config\DependencyInjection\ConfigCachePass` class instead. + Use tagged iterator arguments instead. * The `Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\PropertyInfoPass` class has been removed. Use the `Symfony\Component\PropertyInfo\DependencyInjection\PropertyInfoPass` @@ -439,10 +439,10 @@ FrameworkBundle been removed. * The `Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\AddCacheClearerPass` class has been removed. - Use the `Symfony\Component\HttpKernel\DependencyInjection\AddCacheClearerPass` class instead. + Use tagged iterator arguments instead. * The `Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\AddCacheWarmerPass` class has been removed. - Use the `Symfony\Component\HttpKernel\DependencyInjection\AddCacheWarmerPass` class instead. + Use tagged iterator arguments instead. * The `Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\TranslationDumperPass` class has been removed. Use the @@ -603,6 +603,14 @@ HttpKernel * The `Symfony\Component\HttpKernel\Config\EnvParametersResource` class has been removed. + * The `ChainCacheClearer::add()` method has been removed, + inject the list of clearers as a constructor argument instead. + + * The `CacheWarmerAggregate::add()` and `setWarmers()` methods have been removed, + inject the list of clearers as a constructor argument instead. + + * The `CacheWarmerAggregate` and `ChainCacheClearer` classes have been made final. + Ldap ---- diff --git a/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md b/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md index 0c7581e7c0b7d..4ff27e13a43a5 100644 --- a/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md +++ b/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md @@ -12,8 +12,8 @@ CHANGELOG require symfony/stopwatch` in your `dev` environment. * Deprecated using the `KERNEL_DIR` environment variable with `KernelTestCase::getKernelClass()`. * Deprecated the `KernelTestCase::getPhpUnitXmlDir()` and `KernelTestCase::getPhpUnitCliConfigArgument()` methods. - * Deprecated `AddCacheClearerPass`, use `Symfony\Component\HttpKernel\DependencyInjection\AddCacheClearerPass` instead. - * Deprecated `AddCacheWarmerPass`, use `Symfony\Component\HttpKernel\DependencyInjection\AddCacheWarmerPass` instead. + * Deprecated `AddCacheClearerPass`, use tagged iterator arguments instead. + * Deprecated `AddCacheWarmerPass`, use tagged iterator arguments instead. * Deprecated `TranslationDumperPass`, use `Symfony\Component\Translation\DependencyInjection\TranslationDumperPass` instead * Deprecated `TranslationExtractorPass`, use @@ -82,7 +82,7 @@ CHANGELOG * Deprecated `SessionListener` * Deprecated `TestSessionListener` * Deprecated `Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\ConfigCachePass`. - Use `Symfony\Component\Console\DependencyInjection\ConfigCachePass` instead. + Use tagged iterator arguments instead. * Deprecated `PropertyInfoPass`, use `Symfony\Component\PropertyInfo\DependencyInjection\PropertyInfoPass` instead * Deprecated `ControllerArgumentValueResolverPass`. Use `Symfony\Component\HttpKernel\DependencyInjection\ControllerArgumentValueResolverPass` instead diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/AddCacheClearerPass.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/AddCacheClearerPass.php index c58fd6843d3eb..f650826be04c9 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/AddCacheClearerPass.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/AddCacheClearerPass.php @@ -11,17 +11,35 @@ namespace Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler; -@trigger_error(sprintf('The %s class is deprecated since version 3.4 and will be removed in 4.0. Use Symfony\Component\HttpKernel\DependencyInjection\AddCacheClearerPass instead.', AddCacheClearerPass::class), E_USER_DEPRECATED); +@trigger_error(sprintf('The %s class is deprecated since version 3.4 and will be removed in 4.0. Use tagged iterator arguments instead.', AddCacheClearerPass::class), E_USER_DEPRECATED); -use Symfony\Component\HttpKernel\DependencyInjection\AddCacheClearerPass as BaseAddCacheClearerPass; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; +use Symfony\Component\DependencyInjection\Reference; /** * Registers the cache clearers. * - * @deprecated since version 3.4, to be removed in 4.0. Use {@link BaseAddCacheClearerPass instead}. + * @deprecated since version 3.4, to be removed in 4.0. Use tagged iterator arguments. * * @author Dustin Dobervich */ -class AddCacheClearerPass extends BaseAddCacheClearerPass +class AddCacheClearerPass implements CompilerPassInterface { + /** + * {@inheritdoc} + */ + public function process(ContainerBuilder $container) + { + if (!$container->hasDefinition('cache_clearer')) { + return; + } + + $clearers = array(); + foreach ($container->findTaggedServiceIds('kernel.cache_clearer', true) as $id => $attributes) { + $clearers[] = new Reference($id); + } + + $container->getDefinition('cache_clearer')->replaceArgument(0, $clearers); + } } diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/AddCacheWarmerPass.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/AddCacheWarmerPass.php index 4b427684a9ed3..7a1b2e98bba19 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/AddCacheWarmerPass.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/AddCacheWarmerPass.php @@ -11,17 +11,38 @@ namespace Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler; -@trigger_error(sprintf('The %s class is deprecated since version 3.4 and will be removed in 4.0. Use Symfony\Component\HttpKernel\DependencyInjection\AddCacheWarmerPass instead.', AddCacheWarmerPass::class), E_USER_DEPRECATED); +@trigger_error(sprintf('The %s class is deprecated since version 3.4 and will be removed in 4.0. Use tagged iterator arguments instead.', AddCacheWarmerPass::class), E_USER_DEPRECATED); -use Symfony\Component\HttpKernel\DependencyInjection\AddCacheWarmerPass as BaseAddCacheWarmerPass; +use Symfony\Component\DependencyInjection\Compiler\PriorityTaggedServiceTrait; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; /** * Registers the cache warmers. * - * @deprecated since version 3.4, to be removed in 4.0. Use {@link BaseAddCacheWarmerPass instead}. + * @deprecated since version 3.4, to be removed in 4.0. Use tagged iterator arguments instead. * * @author Fabien Potencier */ -class AddCacheWarmerPass extends BaseAddCacheWarmerPass +class AddCacheWarmerPass implements CompilerPassInterface { + use PriorityTaggedServiceTrait; + + /** + * {@inheritdoc} + */ + public function process(ContainerBuilder $container) + { + if (!$container->hasDefinition('cache_warmer')) { + return; + } + + $warmers = $this->findAndSortTaggedServices('kernel.cache_warmer', $container); + + if (empty($warmers)) { + return; + } + + $container->getDefinition('cache_warmer')->replaceArgument(0, $warmers); + } } diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/ConfigCachePass.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/ConfigCachePass.php index 7fcea3b0e555d..eae4311a345ad 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/ConfigCachePass.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/ConfigCachePass.php @@ -13,12 +13,12 @@ use Symfony\Component\Config\DependencyInjection\ConfigCachePass as BaseConfigCachePass; -@trigger_error(sprintf('The %s class is deprecated since version 3.3 and will be removed in 4.0. Use Symfony\Component\Config\DependencyInjection\ConfigCachePass instead.', ConfigCachePass::class), E_USER_DEPRECATED); +@trigger_error(sprintf('The %s class is deprecated since version 3.3 and will be removed in 4.0. Use tagged iterator arguments instead.', ConfigCachePass::class), E_USER_DEPRECATED); /** * Adds services tagged config_cache.resource_checker to the config_cache_factory service, ordering them by priority. * - * @deprecated since version 3.3, to be removed in 4.0. Use {@link BaseConfigCachePass} instead. + * @deprecated since version 3.3, to be removed in 4.0. Use tagged iterator arguments instead. * * @author Matthias Pigulla * @author Benjamin Klotz diff --git a/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php b/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php index c6936d35be83d..62df8c5ed9bbd 100644 --- a/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php +++ b/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php @@ -25,11 +25,8 @@ use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\ContainerBuilderDebugDumpPass; use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\UnusedTagsPass; use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\WorkflowGuardListenerPass; -use Symfony\Component\Config\DependencyInjection\ConfigCachePass; use Symfony\Component\Console\Application; use Symfony\Component\Console\DependencyInjection\AddConsoleCommandPass; -use Symfony\Component\HttpKernel\DependencyInjection\AddCacheClearerPass; -use Symfony\Component\HttpKernel\DependencyInjection\AddCacheWarmerPass; use Symfony\Component\HttpKernel\DependencyInjection\ControllerArgumentValueResolverPass; use Symfony\Component\HttpKernel\DependencyInjection\RegisterControllerArgumentLocatorsPass; use Symfony\Component\HttpKernel\DependencyInjection\RemoveEmptyControllerArgumentLocatorsPass; @@ -102,8 +99,6 @@ public function build(ContainerBuilder $container) $container->addCompilerPass(new TranslatorPass('translator.default', 'translation.loader')); } $container->addCompilerPass(new LoggingTranslatorPass()); - $container->addCompilerPass(new AddCacheWarmerPass()); - $container->addCompilerPass(new AddCacheClearerPass()); $container->addCompilerPass(new AddExpressionLanguageProvidersPass()); $this->addCompilerPassIfExists($container, TranslationExtractorPass::class); $this->addCompilerPassIfExists($container, TranslationDumperPass::class); @@ -124,7 +119,6 @@ public function build(ContainerBuilder $container) $container->addCompilerPass(new AddDebugLogProcessorPass(), PassConfig::TYPE_BEFORE_OPTIMIZATION, -32); $container->addCompilerPass(new UnusedTagsPass(), PassConfig::TYPE_AFTER_REMOVING); $container->addCompilerPass(new ContainerBuilderDebugDumpPass(), PassConfig::TYPE_BEFORE_REMOVING, -255); - $this->addCompilerPassIfExists($container, ConfigCachePass::class); $container->addCompilerPass(new CacheCollectorPass(), PassConfig::TYPE_BEFORE_REMOVING); } } diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/services.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/services.xml index 0bae93663bf5c..31ca2075e4a98 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/services.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/services.xml @@ -24,7 +24,7 @@ - + @@ -40,7 +40,7 @@ - + @@ -63,7 +63,7 @@ - + diff --git a/src/Symfony/Component/Config/DependencyInjection/ConfigCachePass.php b/src/Symfony/Component/Config/DependencyInjection/ConfigCachePass.php index 02cae0d2b2b65..665cd39e8dd09 100644 --- a/src/Symfony/Component/Config/DependencyInjection/ConfigCachePass.php +++ b/src/Symfony/Component/Config/DependencyInjection/ConfigCachePass.php @@ -11,6 +11,8 @@ namespace Symfony\Component\Config\DependencyInjection; +@trigger_error(sprintf('The %s class is deprecated since version 3.4 and will be removed in 4.0. Use tagged iterator arguments instead.', ConfigCachePass::class), E_USER_DEPRECATED); + use Symfony\Component\DependencyInjection\Argument\IteratorArgument; use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; use Symfony\Component\DependencyInjection\Compiler\PriorityTaggedServiceTrait; @@ -21,6 +23,8 @@ * * @author Matthias Pigulla * @author Benjamin Klotz + * + * @deprecated since version 3.4, to be removed in 4.0. Use tagged iterator arguments instead. */ class ConfigCachePass implements CompilerPassInterface { diff --git a/src/Symfony/Component/Config/Tests/DependencyInjection/ConfigCachePassTest.php b/src/Symfony/Component/Config/Tests/DependencyInjection/ConfigCachePassTest.php index 7452755f50884..4f9c12f8c4ff0 100644 --- a/src/Symfony/Component/Config/Tests/DependencyInjection/ConfigCachePassTest.php +++ b/src/Symfony/Component/Config/Tests/DependencyInjection/ConfigCachePassTest.php @@ -17,6 +17,9 @@ use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\Config\DependencyInjection\ConfigCachePass; +/** + * @group legacy + */ class ConfigCachePassTest extends TestCase { public function testThatCheckersAreProcessedInPriorityOrder() diff --git a/src/Symfony/Component/HttpKernel/CHANGELOG.md b/src/Symfony/Component/HttpKernel/CHANGELOG.md index 66e3b38e25ce6..0c4ee8fa016ea 100644 --- a/src/Symfony/Component/HttpKernel/CHANGELOG.md +++ b/src/Symfony/Component/HttpKernel/CHANGELOG.md @@ -12,6 +12,10 @@ CHANGELOG * added `AddCacheWarmerPass` * deprecated `EnvParametersResource` * added `Symfony\Component\HttpKernel\Client::catchExceptions()` + * deprecated the `ChainCacheClearer::add()` method + * deprecated the `CacheaWarmerAggregate::add()` and `setWarmers()` methods + * made `CacheWarmerAggregate` and `ChainCacheClearer` classes final + 3.3.0 ----- diff --git a/src/Symfony/Component/HttpKernel/CacheClearer/ChainCacheClearer.php b/src/Symfony/Component/HttpKernel/CacheClearer/ChainCacheClearer.php index c749c7c0a4e47..f85d6d14356d3 100644 --- a/src/Symfony/Component/HttpKernel/CacheClearer/ChainCacheClearer.php +++ b/src/Symfony/Component/HttpKernel/CacheClearer/ChainCacheClearer.php @@ -15,6 +15,8 @@ * ChainCacheClearer. * * @author Dustin Dobervich + * + * @final since version 3.4 */ class ChainCacheClearer implements CacheClearerInterface { @@ -28,7 +30,7 @@ class ChainCacheClearer implements CacheClearerInterface * * @param array $clearers The initial clearers */ - public function __construct(array $clearers = array()) + public function __construct($clearers = array()) { $this->clearers = $clearers; } @@ -47,9 +49,13 @@ public function clear($cacheDir) * Adds a cache clearer to the aggregate. * * @param CacheClearerInterface $clearer + * + * @deprecated since version 3.4, to be removed in 4.0, inject the list of clearers as a constructor argument instead. */ public function add(CacheClearerInterface $clearer) { + @trigger_error(sprintf('The "%s()" method is deprecated since version 3.4 and will be removed in 4.0, inject the list of clearers as a constructor argument instead.', __METHOD__), E_USER_DEPRECATED); + $this->clearers[] = $clearer; } } diff --git a/src/Symfony/Component/HttpKernel/CacheWarmer/CacheWarmerAggregate.php b/src/Symfony/Component/HttpKernel/CacheWarmer/CacheWarmerAggregate.php index e5f4e4fa4a231..c53b4e4bf0ab1 100644 --- a/src/Symfony/Component/HttpKernel/CacheWarmer/CacheWarmerAggregate.php +++ b/src/Symfony/Component/HttpKernel/CacheWarmer/CacheWarmerAggregate.php @@ -15,17 +15,21 @@ * Aggregates several cache warmers into a single one. * * @author Fabien Potencier + * + * @final since version 3.4 */ class CacheWarmerAggregate implements CacheWarmerInterface { protected $warmers = array(); protected $optionalsEnabled = false; + private $triggerDeprecation = false; - public function __construct(array $warmers = array()) + public function __construct($warmers = array()) { foreach ($warmers as $warmer) { $this->add($warmer); } + $this->triggerDeprecation = true; } public function enableOptionalWarmers() @@ -53,6 +57,8 @@ public function warmUp($cacheDir) * Checks whether this warmer is optional or not. * * @return bool always false + * + * @deprecated since version 3.4, to be removed in 4.0, inject the list of clearers as a constructor argument instead. */ public function isOptional() { @@ -61,14 +67,23 @@ public function isOptional() public function setWarmers(array $warmers) { + @trigger_error(sprintf('The "%s()" method is deprecated since version 3.4 and will be removed in 4.0, inject the list of clearers as a constructor argument instead.', __METHOD__), E_USER_DEPRECATED); + $this->warmers = array(); foreach ($warmers as $warmer) { $this->add($warmer); } } + /** + * @deprecated since version 3.4, to be removed in 4.0, inject the list of clearers as a constructor argument instead. + */ public function add(CacheWarmerInterface $warmer) { + if ($this->triggerDeprecation) { + @trigger_error(sprintf('The "%s()" method is deprecated since version 3.4 and will be removed in 4.0, inject the list of clearers as a constructor argument instead.', __METHOD__), E_USER_DEPRECATED); + } + $this->warmers[] = $warmer; } } diff --git a/src/Symfony/Component/HttpKernel/DependencyInjection/AddCacheClearerPass.php b/src/Symfony/Component/HttpKernel/DependencyInjection/AddCacheClearerPass.php deleted file mode 100644 index 2689440bd7253..0000000000000 --- a/src/Symfony/Component/HttpKernel/DependencyInjection/AddCacheClearerPass.php +++ /dev/null @@ -1,50 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\DependencyInjection; - -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; -use Symfony\Component\DependencyInjection\Reference; - -/** - * Registers the cache clearers. - * - * @author Dustin Dobervich - */ -class AddCacheClearerPass implements CompilerPassInterface -{ - private $cacheClearerId; - private $cacheClearerTag; - - public function __construct($cacheClearerId = 'cache_clearer', $cacheClearerTag = 'kernel.cache_clearer') - { - $this->cacheClearerId = $cacheClearerId; - $this->cacheClearerTag = $cacheClearerTag; - } - - /** - * {@inheritdoc} - */ - public function process(ContainerBuilder $container) - { - if (!$container->hasDefinition($this->cacheClearerId)) { - return; - } - - $clearers = array(); - foreach ($container->findTaggedServiceIds($this->cacheClearerTag, true) as $id => $attributes) { - $clearers[] = new Reference($id); - } - - $container->getDefinition($this->cacheClearerId)->replaceArgument(0, $clearers); - } -} diff --git a/src/Symfony/Component/HttpKernel/DependencyInjection/AddCacheWarmerPass.php b/src/Symfony/Component/HttpKernel/DependencyInjection/AddCacheWarmerPass.php deleted file mode 100644 index 6d13e1cbcb536..0000000000000 --- a/src/Symfony/Component/HttpKernel/DependencyInjection/AddCacheWarmerPass.php +++ /dev/null @@ -1,53 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\DependencyInjection; - -use Symfony\Component\DependencyInjection\Compiler\PriorityTaggedServiceTrait; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; - -/** - * Registers the cache warmers. - * - * @author Fabien Potencier - */ -class AddCacheWarmerPass implements CompilerPassInterface -{ - use PriorityTaggedServiceTrait; - - private $cacheWarmerId; - private $cacheWarmerTag; - - public function __construct($cacheWarmerId = 'cache_warmer', $cacheWarmerTag = 'kernel.cache_warmer') - { - $this->cacheWarmerId = $cacheWarmerId; - $this->cacheWarmerTag = $cacheWarmerTag; - } - - /** - * {@inheritdoc} - */ - public function process(ContainerBuilder $container) - { - if (!$container->hasDefinition($this->cacheWarmerId)) { - return; - } - - $warmers = $this->findAndSortTaggedServices($this->cacheWarmerTag, $container); - - if (empty($warmers)) { - return; - } - - $container->getDefinition($this->cacheWarmerId)->replaceArgument(0, $warmers); - } -} diff --git a/src/Symfony/Component/HttpKernel/Tests/CacheClearer/ChainCacheClearerTest.php b/src/Symfony/Component/HttpKernel/Tests/CacheClearer/ChainCacheClearerTest.php index 1bc853349f230..ec2ecff948c81 100644 --- a/src/Symfony/Component/HttpKernel/Tests/CacheClearer/ChainCacheClearerTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/CacheClearer/ChainCacheClearerTest.php @@ -39,6 +39,9 @@ public function testInjectClearersInConstructor() $chainClearer->clear(self::$cacheDir); } + /** + * @group legacy + */ public function testInjectClearerUsingAdd() { $clearer = $this->getMockClearer(); diff --git a/src/Symfony/Component/HttpKernel/Tests/CacheWarmer/CacheWarmerAggregateTest.php b/src/Symfony/Component/HttpKernel/Tests/CacheWarmer/CacheWarmerAggregateTest.php index d07ade303f107..ba159124c93e9 100644 --- a/src/Symfony/Component/HttpKernel/Tests/CacheWarmer/CacheWarmerAggregateTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/CacheWarmer/CacheWarmerAggregateTest.php @@ -38,6 +38,9 @@ public function testInjectWarmersUsingConstructor() $aggregate->warmUp(self::$cacheDir); } + /** + * @group legacy + */ public function testInjectWarmersUsingAdd() { $warmer = $this->getCacheWarmerMock(); @@ -49,6 +52,9 @@ public function testInjectWarmersUsingAdd() $aggregate->warmUp(self::$cacheDir); } + /** + * @group legacy + */ public function testInjectWarmersUsingSetWarmers() { $warmer = $this->getCacheWarmerMock(); diff --git a/src/Symfony/Component/HttpKernel/Tests/DependencyInjection/AddCacheClearerPassTest.php b/src/Symfony/Component/HttpKernel/Tests/DependencyInjection/AddCacheClearerPassTest.php deleted file mode 100644 index 3bdb84ad10667..0000000000000 --- a/src/Symfony/Component/HttpKernel/Tests/DependencyInjection/AddCacheClearerPassTest.php +++ /dev/null @@ -1,53 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\Tests\DependencyInjection; - -use PHPUnit\Framework\TestCase; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Reference; -use Symfony\Component\HttpKernel\DependencyInjection\AddCacheClearerPass; - -class AddCacheClearerPassTest extends TestCase -{ - public function testThatCacheClearer() - { - $container = new ContainerBuilder(); - - $definition = $container->register('cache_clearer')->addArgument(null); - $container->register('my_cache_clearer_service1')->addTag('kernel.cache_clearer'); - - $addCacheWarmerPass = new AddCacheClearerPass(); - $addCacheWarmerPass->process($container); - - $expected = array( - new Reference('my_cache_clearer_service1'), - ); - $this->assertEquals($expected, $definition->getArgument(0)); - } - - public function testThatCompilerPassIsIgnoredIfThereIsNoCacheClearerDefinition() - { - $definition = $this->getMockBuilder('Symfony\Component\DependencyInjection\Definition')->getMock(); - $container = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerBuilder')->setMethods(array('hasDefinition', 'findTaggedServiceIds', 'getDefinition'))->getMock(); - - $container->expects($this->never())->method('findTaggedServiceIds'); - $container->expects($this->never())->method('getDefinition'); - $container->expects($this->atLeastOnce()) - ->method('hasDefinition') - ->with('cache_clearer') - ->will($this->returnValue(false)); - $definition->expects($this->never())->method('replaceArgument'); - - $addCacheWarmerPass = new AddCacheClearerPass(); - $addCacheWarmerPass->process($container); - } -} diff --git a/src/Symfony/Component/HttpKernel/Tests/DependencyInjection/AddCacheWarmerPassTest.php b/src/Symfony/Component/HttpKernel/Tests/DependencyInjection/AddCacheWarmerPassTest.php deleted file mode 100644 index 3f7bc6e65ebef..0000000000000 --- a/src/Symfony/Component/HttpKernel/Tests/DependencyInjection/AddCacheWarmerPassTest.php +++ /dev/null @@ -1,77 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\Tests\DependencyInjection; - -use PHPUnit\Framework\TestCase; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Reference; -use Symfony\Component\HttpKernel\DependencyInjection\AddCacheWarmerPass; - -class AddCacheWarmerPassTest extends TestCase -{ - public function testThatCacheWarmersAreProcessedInPriorityOrder() - { - $container = new ContainerBuilder(); - - $definition = $container->register('cache_warmer')->addArgument(null); - $container->register('my_cache_warmer_service1')->addTag('kernel.cache_warmer', array('priority' => 100)); - $container->register('my_cache_warmer_service2')->addTag('kernel.cache_warmer', array('priority' => 200)); - $container->register('my_cache_warmer_service3')->addTag('kernel.cache_warmer'); - - $addCacheWarmerPass = new AddCacheWarmerPass(); - $addCacheWarmerPass->process($container); - - $expected = array( - new Reference('my_cache_warmer_service2'), - new Reference('my_cache_warmer_service1'), - new Reference('my_cache_warmer_service3'), - ); - $this->assertEquals($expected, $definition->getArgument(0)); - } - - public function testThatCompilerPassIsIgnoredIfThereIsNoCacheWarmerDefinition() - { - $definition = $this->getMockBuilder('Symfony\Component\DependencyInjection\Definition')->getMock(); - $container = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerBuilder')->setMethods(array('hasDefinition', 'findTaggedServiceIds', 'getDefinition'))->getMock(); - - $container->expects($this->never())->method('findTaggedServiceIds'); - $container->expects($this->never())->method('getDefinition'); - $container->expects($this->atLeastOnce()) - ->method('hasDefinition') - ->with('cache_warmer') - ->will($this->returnValue(false)); - $definition->expects($this->never())->method('replaceArgument'); - - $addCacheWarmerPass = new AddCacheWarmerPass(); - $addCacheWarmerPass->process($container); - } - - public function testThatCacheWarmersMightBeNotDefined() - { - $definition = $this->getMockBuilder('Symfony\Component\DependencyInjection\Definition')->getMock(); - $container = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerBuilder')->setMethods(array('hasDefinition', 'findTaggedServiceIds', 'getDefinition'))->getMock(); - - $container->expects($this->atLeastOnce()) - ->method('findTaggedServiceIds') - ->will($this->returnValue(array())); - $container->expects($this->never())->method('getDefinition'); - $container->expects($this->atLeastOnce()) - ->method('hasDefinition') - ->with('cache_warmer') - ->will($this->returnValue(true)); - - $definition->expects($this->never())->method('replaceArgument'); - - $addCacheWarmerPass = new AddCacheWarmerPass(); - $addCacheWarmerPass->process($container); - } -} From 9137d57ecd43f1d42e6e09b06ed090614e5f6c8c Mon Sep 17 00:00:00 2001 From: Roland Franssen Date: Sat, 24 Dec 2016 11:15:47 +0000 Subject: [PATCH 0945/1099] [Asset] Provide default context --- src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md | 2 ++ .../FrameworkBundle/Resources/config/assets.xml | 7 +++++++ src/Symfony/Component/Asset/CHANGELOG.md | 6 ++++++ .../Asset/Context/RequestStackContext.php | 15 ++++++++++++--- .../Tests/Context/RequestStackContextTest.php | 9 +++++++++ 5 files changed, 36 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md b/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md index dafd4c46bb0fc..8bcbe06ae6664 100644 --- a/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md +++ b/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md @@ -53,6 +53,8 @@ CHANGELOG `EventDispatcherDebugCommand`, `RouterDebugCommand`, `RouterMatchCommand`, `TranslationDebugCommand`, `TranslationUpdateCommand`, `XliffLintCommand` and `YamlLintCommand` classes have been marked as final + * Added `asset.request_context.base_path` and `asset.request_context.secure` parameters + to provide a default request context in case the stack is empty (similar to `router.request_context.*` parameters) 3.3.0 ----- diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/assets.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/assets.xml index e714e2834c5fc..cb0f11c926f82 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/assets.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/assets.xml @@ -4,6 +4,11 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd"> + + + false + + @@ -19,6 +24,8 @@ + %asset.request_context.base_path% + %asset.request_context.secure% diff --git a/src/Symfony/Component/Asset/CHANGELOG.md b/src/Symfony/Component/Asset/CHANGELOG.md index 72030a9d65b16..bb4c02f333187 100644 --- a/src/Symfony/Component/Asset/CHANGELOG.md +++ b/src/Symfony/Component/Asset/CHANGELOG.md @@ -1,6 +1,12 @@ CHANGELOG ========= +3.4.0 +----- + + * added optional arguments `$basePath` and `$secure` in `RequestStackContext::__construct()` + to provide a default request context in case the stack is empty + 3.3.0 ----- * Added `JsonManifestVersionStrategy` as a way to read final, diff --git a/src/Symfony/Component/Asset/Context/RequestStackContext.php b/src/Symfony/Component/Asset/Context/RequestStackContext.php index ba7113851d863..c18f833264832 100644 --- a/src/Symfony/Component/Asset/Context/RequestStackContext.php +++ b/src/Symfony/Component/Asset/Context/RequestStackContext.php @@ -21,10 +21,19 @@ class RequestStackContext implements ContextInterface { private $requestStack; + private $basePath; + private $secure; - public function __construct(RequestStack $requestStack) + /** + * @param RequestStack $requestStack + * @param string $basePath + * @param bool $secure + */ + public function __construct(RequestStack $requestStack, $basePath = '', $secure = false) { $this->requestStack = $requestStack; + $this->basePath = $basePath; + $this->secure = $secure; } /** @@ -33,7 +42,7 @@ public function __construct(RequestStack $requestStack) public function getBasePath() { if (!$request = $this->requestStack->getMasterRequest()) { - return ''; + return $this->basePath; } return $request->getBasePath(); @@ -45,7 +54,7 @@ public function getBasePath() public function isSecure() { if (!$request = $this->requestStack->getMasterRequest()) { - return false; + return $this->secure; } return $request->isSecure(); diff --git a/src/Symfony/Component/Asset/Tests/Context/RequestStackContextTest.php b/src/Symfony/Component/Asset/Tests/Context/RequestStackContextTest.php index 7269d0e6bc983..7f24534eba202 100644 --- a/src/Symfony/Component/Asset/Tests/Context/RequestStackContextTest.php +++ b/src/Symfony/Component/Asset/Tests/Context/RequestStackContextTest.php @@ -61,4 +61,13 @@ public function testIsSecureTrue() $this->assertTrue($requestStackContext->isSecure()); } + + public function testDefaultContext() + { + $requestStack = $this->getMockBuilder('Symfony\Component\HttpFoundation\RequestStack')->getMock(); + $requestStackContext = new RequestStackContext($requestStack, 'default-path', true); + + $this->assertSame('default-path', $requestStackContext->getBasePath()); + $this->assertTrue($requestStackContext->isSecure()); + } } From eca2f8e58773582a238441a318373c93f90d76ca Mon Sep 17 00:00:00 2001 From: Tobias Nyholm Date: Thu, 14 Sep 2017 09:57:19 +0200 Subject: [PATCH 0946/1099] Moved PhpExtractor and PhpStringTokenParser to Translation component --- UPGRADE-3.4.md | 14 +- UPGRADE-4.0.md | 14 +- .../Bundle/FrameworkBundle/CHANGELOG.md | 4 + .../Tests/Translation/PhpExtractorTest.php | 3 + .../Translation/PhpExtractor.php | 247 +---------------- .../Translation/PhpStringTokenParser.php | 131 +-------- .../Component/Translation/CHANGELOG.md | 2 + .../Translation/Extractor/PhpExtractor.php | 258 ++++++++++++++++++ .../Extractor/PhpStringTokenParser.php | 142 ++++++++++ .../Tests/Extractor/PhpExtractorTest.php | 95 +++++++ .../fixtures/extractor/resource.format.engine | 0 .../this.is.a.template.format.engine | 0 .../fixtures/extractor/translation.html.php | 49 ++++ 13 files changed, 585 insertions(+), 374 deletions(-) create mode 100644 src/Symfony/Component/Translation/Extractor/PhpExtractor.php create mode 100644 src/Symfony/Component/Translation/Extractor/PhpStringTokenParser.php create mode 100644 src/Symfony/Component/Translation/Tests/Extractor/PhpExtractorTest.php create mode 100644 src/Symfony/Component/Translation/Tests/fixtures/extractor/resource.format.engine create mode 100644 src/Symfony/Component/Translation/Tests/fixtures/extractor/this.is.a.template.format.engine create mode 100644 src/Symfony/Component/Translation/Tests/fixtures/extractor/translation.html.php diff --git a/UPGRADE-3.4.md b/UPGRADE-3.4.md index ffc6458fecd5d..6561c15a0b46f 100644 --- a/UPGRADE-3.4.md +++ b/UPGRADE-3.4.md @@ -204,6 +204,14 @@ FrameworkBundle `TranslationDebugCommand`, `TranslationUpdateCommand`, `XliffLintCommand` and `YamlLintCommand` classes have been marked as final + * The `Symfony\Bundle\FrameworkBundle\Translation\PhpExtractor` + class has been deprecated and will be removed in 4.0. Use the + `Symfony\Component\Translation\Extractor\PhpExtractor` class instead. + + * The `Symfony\Bundle\FrameworkBundle\Translation\PhpStringTokenParser` + class has been deprecated and will be removed in 4.0. Use the + `Symfony\Component\Translation\Extractor\PhpStringTokenParser` class instead. + HttpFoundation -------------- @@ -280,8 +288,8 @@ Profiler Security -------- - * Deprecated the HTTP digest authentication: `NonceExpiredException`, - `DigestAuthenticationListener` and `DigestAuthenticationEntryPoint` will be + * Deprecated the HTTP digest authentication: `NonceExpiredException`, + `DigestAuthenticationListener` and `DigestAuthenticationEntryPoint` will be removed in 4.0. Use another authentication system like `http_basic` instead. SecurityBundle @@ -305,7 +313,7 @@ SecurityBundle * Added `logout_on_user_change` to the firewall options. This config item will trigger a logout when the user has changed. Should be set to true to avoid deprecations in the configuration. - + * Deprecated the HTTP digest authentication: `HttpDigestFactory` will be removed in 4.0. Use another authentication system like `http_basic` instead. diff --git a/UPGRADE-4.0.md b/UPGRADE-4.0.md index 1f122c002dccf..688a309466b5d 100644 --- a/UPGRADE-4.0.md +++ b/UPGRADE-4.0.md @@ -494,6 +494,14 @@ FrameworkBundle `Symfony\Component\Translation\TranslatorInterface` as first argument. + * The `Symfony\Bundle\FrameworkBundle\Translation\PhpExtractor` + class has been deprecated and will be removed in 4.0. Use the + `Symfony\Component\Translation\Extractor\PhpExtractor` class instead. + + * The `Symfony\Bundle\FrameworkBundle\Translation\PhpStringTokenParser` + class has been deprecated and will be removed in 4.0. Use the + `Symfony\Component\Translation\Extractor\PhpStringTokenParser` class instead. + HttpFoundation -------------- @@ -525,9 +533,9 @@ HttpFoundation * The ability to check only for cacheable HTTP methods using `Request::isMethodSafe()` is not supported anymore, use `Request::isMethodCacheable()` instead. - * The `Symfony\Component\HttpFoundation\Session\Storage\Handler\NativeSessionHandler`, + * The `Symfony\Component\HttpFoundation\Session\Storage\Handler\NativeSessionHandler`, `Symfony\Component\HttpFoundation\Session\Storage\Proxy\AbstractProxy`, - `Symfony\Component\HttpFoundation\Session\Storage\Proxy\NativeProxy` and + `Symfony\Component\HttpFoundation\Session\Storage\Proxy\NativeProxy` and `Symfony\Component\HttpFoundation\Session\Storage\Proxy\SessionHandlerProxy` classes have been removed. * `NativeSessionStorage::setSaveHandler()` now requires an instance of `\SessionHandlerInterface` as argument. @@ -682,7 +690,7 @@ SecurityBundle * The firewall option `logout_on_user_change` is now always true, which will trigger a logout if the user changes between requests. - + * Removed the HTTP digest authentication system. The `HttpDigestFactory` class has been removed. Use another authentication system like `http_basic` instead. diff --git a/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md b/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md index 2af300950c43b..1e87a15660466 100644 --- a/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md +++ b/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md @@ -105,6 +105,10 @@ CHANGELOG `Symfony\Component\Workflow\DependencyInjection\ValidateWorkflowsPass` instead * Deprecated `ConstraintValidatorFactory`, use `Symfony\Component\Validator\ContainerConstraintValidatorFactory` instead. + * Deprecated `PhpStringTokenParser`, use + `Symfony\Component\Translation\Extractor\PhpStringTokenParser` instead. + * Deprecated `PhpExtractor`, use + `Symfony\Component\Translation\Extractor\PhpExtractor` instead. 3.2.0 ----- diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Translation/PhpExtractorTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Translation/PhpExtractorTest.php index e8c56ee4d5e52..ca45f43329a2f 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Translation/PhpExtractorTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Translation/PhpExtractorTest.php @@ -15,6 +15,9 @@ use Symfony\Bundle\FrameworkBundle\Translation\PhpExtractor; use Symfony\Component\Translation\MessageCatalogue; +/** + * @group legacy + */ class PhpExtractorTest extends TestCase { /** diff --git a/src/Symfony/Bundle/FrameworkBundle/Translation/PhpExtractor.php b/src/Symfony/Bundle/FrameworkBundle/Translation/PhpExtractor.php index 70658f67232d3..f8530875ae199 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Translation/PhpExtractor.php +++ b/src/Symfony/Bundle/FrameworkBundle/Translation/PhpExtractor.php @@ -11,250 +11,13 @@ namespace Symfony\Bundle\FrameworkBundle\Translation; -use Symfony\Component\Finder\Finder; -use Symfony\Component\Translation\Extractor\AbstractFileExtractor; -use Symfony\Component\Translation\MessageCatalogue; -use Symfony\Component\Translation\Extractor\ExtractorInterface; +use Symfony\Component\Translation\Extractor\PhpExtractor as NewPhpExtractor; + +@trigger_error(sprintf('The class "%s" is deprecated since version 3.4 and will be removed in 4.0. Use "%s" instead. ', PhpExtractor::class, NewPhpExtractor::class), E_USER_DEPRECATED); /** - * PhpExtractor extracts translation messages from a PHP template. - * - * @author Michel Salib + * @deprecated since version 3.4 and will be removed in 4.0. Use Symfony\Component\Translation\Extractor\PhpExtractor instead */ -class PhpExtractor extends AbstractFileExtractor implements ExtractorInterface +class PhpExtractor extends NewPhpExtractor { - const MESSAGE_TOKEN = 300; - const METHOD_ARGUMENTS_TOKEN = 1000; - const DOMAIN_TOKEN = 1001; - - /** - * Prefix for new found message. - * - * @var string - */ - private $prefix = ''; - - /** - * The sequence that captures translation messages. - * - * @var array - */ - protected $sequences = array( - array( - '->', - 'trans', - '(', - self::MESSAGE_TOKEN, - ',', - self::METHOD_ARGUMENTS_TOKEN, - ',', - self::DOMAIN_TOKEN, - ), - array( - '->', - 'transChoice', - '(', - self::MESSAGE_TOKEN, - ',', - self::METHOD_ARGUMENTS_TOKEN, - ',', - self::METHOD_ARGUMENTS_TOKEN, - ',', - self::DOMAIN_TOKEN, - ), - array( - '->', - 'trans', - '(', - self::MESSAGE_TOKEN, - ), - array( - '->', - 'transChoice', - '(', - self::MESSAGE_TOKEN, - ), - ); - - /** - * {@inheritdoc} - */ - public function extract($resource, MessageCatalogue $catalog) - { - $files = $this->extractFiles($resource); - foreach ($files as $file) { - $this->parseTokens(token_get_all(file_get_contents($file)), $catalog); - - if (\PHP_VERSION_ID >= 70000) { - // PHP 7 memory manager will not release after token_get_all(), see https://bugs.php.net/70098 - gc_mem_caches(); - } - } - } - - /** - * {@inheritdoc} - */ - public function setPrefix($prefix) - { - $this->prefix = $prefix; - } - - /** - * Normalizes a token. - * - * @param mixed $token - * - * @return string - */ - protected function normalizeToken($token) - { - if (isset($token[1]) && 'b"' !== $token) { - return $token[1]; - } - - return $token; - } - - /** - * Seeks to a non-whitespace token. - */ - private function seekToNextRelevantToken(\Iterator $tokenIterator) - { - for (; $tokenIterator->valid(); $tokenIterator->next()) { - $t = $tokenIterator->current(); - if (T_WHITESPACE !== $t[0]) { - break; - } - } - } - - private function skipMethodArgument(\Iterator $tokenIterator) - { - $openBraces = 0; - - for (; $tokenIterator->valid(); $tokenIterator->next()) { - $t = $tokenIterator->current(); - - if ('[' === $t[0] || '(' === $t[0]) { - ++$openBraces; - } - - if (']' === $t[0] || ')' === $t[0]) { - --$openBraces; - } - - if ((0 === $openBraces && ',' === $t[0]) || (-1 === $openBraces && ')' === $t[0])) { - break; - } - } - } - - /** - * Extracts the message from the iterator while the tokens - * match allowed message tokens. - */ - private function getValue(\Iterator $tokenIterator) - { - $message = ''; - $docToken = ''; - - for (; $tokenIterator->valid(); $tokenIterator->next()) { - $t = $tokenIterator->current(); - if (!isset($t[1])) { - break; - } - - switch ($t[0]) { - case T_START_HEREDOC: - $docToken = $t[1]; - break; - case T_ENCAPSED_AND_WHITESPACE: - case T_CONSTANT_ENCAPSED_STRING: - $message .= $t[1]; - break; - case T_END_HEREDOC: - return PhpStringTokenParser::parseDocString($docToken, $message); - default: - break 2; - } - } - - if ($message) { - $message = PhpStringTokenParser::parse($message); - } - - return $message; - } - - /** - * Extracts trans message from PHP tokens. - * - * @param array $tokens - * @param MessageCatalogue $catalog - */ - protected function parseTokens($tokens, MessageCatalogue $catalog) - { - $tokenIterator = new \ArrayIterator($tokens); - - for ($key = 0; $key < $tokenIterator->count(); ++$key) { - foreach ($this->sequences as $sequence) { - $message = ''; - $domain = 'messages'; - $tokenIterator->seek($key); - - foreach ($sequence as $sequenceKey => $item) { - $this->seekToNextRelevantToken($tokenIterator); - - if ($this->normalizeToken($tokenIterator->current()) === $item) { - $tokenIterator->next(); - continue; - } elseif (self::MESSAGE_TOKEN === $item) { - $message = $this->getValue($tokenIterator); - - if (count($sequence) === ($sequenceKey + 1)) { - break; - } - } elseif (self::METHOD_ARGUMENTS_TOKEN === $item) { - $this->skipMethodArgument($tokenIterator); - } elseif (self::DOMAIN_TOKEN === $item) { - $domain = $this->getValue($tokenIterator); - - break; - } else { - break; - } - } - - if ($message) { - $catalog->set($message, $this->prefix.$message, $domain); - break; - } - } - } - } - - /** - * @param string $file - * - * @return bool - * - * @throws \InvalidArgumentException - */ - protected function canBeExtracted($file) - { - return $this->isFile($file) && 'php' === pathinfo($file, PATHINFO_EXTENSION); - } - - /** - * @param string|array $directory - * - * @return array - */ - protected function extractFromDirectory($directory) - { - $finder = new Finder(); - - return $finder->files()->name('*.php')->in($directory); - } } diff --git a/src/Symfony/Bundle/FrameworkBundle/Translation/PhpStringTokenParser.php b/src/Symfony/Bundle/FrameworkBundle/Translation/PhpStringTokenParser.php index e950ac478f84c..7b472cb4350ed 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Translation/PhpStringTokenParser.php +++ b/src/Symfony/Bundle/FrameworkBundle/Translation/PhpStringTokenParser.php @@ -11,132 +11,11 @@ namespace Symfony\Bundle\FrameworkBundle\Translation; -/* - * The following is derived from code at http://github.com/nikic/PHP-Parser - * - * Copyright (c) 2011 by Nikita Popov - * - * Some rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * - * * The names of the contributors may not be used to endorse or - * promote products derived from this software without specific - * prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ +@trigger_error(sprintf('The class "%s" is deprecated since version 3.4 and will be removed in 4.0. Use "%s" instead. ', PhpStringTokenParser::class, \Symfony\Component\Translation\Extractor\PhpStringTokenParser::class), E_USER_DEPRECATED); -class PhpStringTokenParser +/** + * @deprecated since version 3.4 and will be removed in 4.0. Use Symfony\Component\Translation\Extractor\PhpStringTokenParser instead + */ +class PhpStringTokenParser extends \Symfony\Component\Translation\Extractor\PhpStringTokenParser { - protected static $replacements = array( - '\\' => '\\', - '$' => '$', - 'n' => "\n", - 'r' => "\r", - 't' => "\t", - 'f' => "\f", - 'v' => "\v", - 'e' => "\x1B", - ); - - /** - * Parses a string token. - * - * @param string $str String token content - * - * @return string The parsed string - */ - public static function parse($str) - { - $bLength = 0; - if ('b' === $str[0]) { - $bLength = 1; - } - - if ('\'' === $str[$bLength]) { - return str_replace( - array('\\\\', '\\\''), - array('\\', '\''), - substr($str, $bLength + 1, -1) - ); - } else { - return self::parseEscapeSequences(substr($str, $bLength + 1, -1), '"'); - } - } - - /** - * Parses escape sequences in strings (all string types apart from single quoted). - * - * @param string $str String without quotes - * @param null|string $quote Quote type - * - * @return string String with escape sequences parsed - */ - public static function parseEscapeSequences($str, $quote) - { - if (null !== $quote) { - $str = str_replace('\\'.$quote, $quote, $str); - } - - return preg_replace_callback( - '~\\\\([\\\\$nrtfve]|[xX][0-9a-fA-F]{1,2}|[0-7]{1,3})~', - array(__CLASS__, 'parseCallback'), - $str - ); - } - - private static function parseCallback($matches) - { - $str = $matches[1]; - - if (isset(self::$replacements[$str])) { - return self::$replacements[$str]; - } elseif ('x' === $str[0] || 'X' === $str[0]) { - return chr(hexdec($str)); - } else { - return chr(octdec($str)); - } - } - - /** - * Parses a constant doc string. - * - * @param string $startToken Doc string start token content (<< + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Extractor; + +use Symfony\Component\Finder\Finder; +use Symfony\Component\Translation\MessageCatalogue; + +/** + * PhpExtractor extracts translation messages from a PHP template. + * + * @author Michel Salib + */ +class PhpExtractor extends AbstractFileExtractor implements ExtractorInterface +{ + const MESSAGE_TOKEN = 300; + const METHOD_ARGUMENTS_TOKEN = 1000; + const DOMAIN_TOKEN = 1001; + + /** + * Prefix for new found message. + * + * @var string + */ + private $prefix = ''; + + /** + * The sequence that captures translation messages. + * + * @var array + */ + protected $sequences = array( + array( + '->', + 'trans', + '(', + self::MESSAGE_TOKEN, + ',', + self::METHOD_ARGUMENTS_TOKEN, + ',', + self::DOMAIN_TOKEN, + ), + array( + '->', + 'transChoice', + '(', + self::MESSAGE_TOKEN, + ',', + self::METHOD_ARGUMENTS_TOKEN, + ',', + self::METHOD_ARGUMENTS_TOKEN, + ',', + self::DOMAIN_TOKEN, + ), + array( + '->', + 'trans', + '(', + self::MESSAGE_TOKEN, + ), + array( + '->', + 'transChoice', + '(', + self::MESSAGE_TOKEN, + ), + ); + + /** + * {@inheritdoc} + */ + public function extract($resource, MessageCatalogue $catalog) + { + $files = $this->extractFiles($resource); + foreach ($files as $file) { + $this->parseTokens(token_get_all(file_get_contents($file)), $catalog); + + if (\PHP_VERSION_ID >= 70000) { + // PHP 7 memory manager will not release after token_get_all(), see https://bugs.php.net/70098 + gc_mem_caches(); + } + } + } + + /** + * {@inheritdoc} + */ + public function setPrefix($prefix) + { + $this->prefix = $prefix; + } + + /** + * Normalizes a token. + * + * @param mixed $token + * + * @return string + */ + protected function normalizeToken($token) + { + if (isset($token[1]) && 'b"' !== $token) { + return $token[1]; + } + + return $token; + } + + /** + * Seeks to a non-whitespace token. + */ + private function seekToNextRelevantToken(\Iterator $tokenIterator) + { + for (; $tokenIterator->valid(); $tokenIterator->next()) { + $t = $tokenIterator->current(); + if (T_WHITESPACE !== $t[0]) { + break; + } + } + } + + private function skipMethodArgument(\Iterator $tokenIterator) + { + $openBraces = 0; + + for (; $tokenIterator->valid(); $tokenIterator->next()) { + $t = $tokenIterator->current(); + + if ('[' === $t[0] || '(' === $t[0]) { + ++$openBraces; + } + + if (']' === $t[0] || ')' === $t[0]) { + --$openBraces; + } + + if ((0 === $openBraces && ',' === $t[0]) || (-1 === $openBraces && ')' === $t[0])) { + break; + } + } + } + + /** + * Extracts the message from the iterator while the tokens + * match allowed message tokens. + */ + private function getValue(\Iterator $tokenIterator) + { + $message = ''; + $docToken = ''; + + for (; $tokenIterator->valid(); $tokenIterator->next()) { + $t = $tokenIterator->current(); + if (!isset($t[1])) { + break; + } + + switch ($t[0]) { + case T_START_HEREDOC: + $docToken = $t[1]; + break; + case T_ENCAPSED_AND_WHITESPACE: + case T_CONSTANT_ENCAPSED_STRING: + $message .= $t[1]; + break; + case T_END_HEREDOC: + return PhpStringTokenParser::parseDocString($docToken, $message); + default: + break 2; + } + } + + if ($message) { + $message = PhpStringTokenParser::parse($message); + } + + return $message; + } + + /** + * Extracts trans message from PHP tokens. + * + * @param array $tokens + * @param MessageCatalogue $catalog + */ + protected function parseTokens($tokens, MessageCatalogue $catalog) + { + $tokenIterator = new \ArrayIterator($tokens); + + for ($key = 0; $key < $tokenIterator->count(); ++$key) { + foreach ($this->sequences as $sequence) { + $message = ''; + $domain = 'messages'; + $tokenIterator->seek($key); + + foreach ($sequence as $sequenceKey => $item) { + $this->seekToNextRelevantToken($tokenIterator); + + if ($this->normalizeToken($tokenIterator->current()) === $item) { + $tokenIterator->next(); + continue; + } elseif (self::MESSAGE_TOKEN === $item) { + $message = $this->getValue($tokenIterator); + + if (count($sequence) === ($sequenceKey + 1)) { + break; + } + } elseif (self::METHOD_ARGUMENTS_TOKEN === $item) { + $this->skipMethodArgument($tokenIterator); + } elseif (self::DOMAIN_TOKEN === $item) { + $domain = $this->getValue($tokenIterator); + + break; + } else { + break; + } + } + + if ($message) { + $catalog->set($message, $this->prefix.$message, $domain); + break; + } + } + } + } + + /** + * @param string $file + * + * @return bool + * + * @throws \InvalidArgumentException + */ + protected function canBeExtracted($file) + { + return $this->isFile($file) && 'php' === pathinfo($file, PATHINFO_EXTENSION); + } + + /** + * @param string|array $directory + * + * @return array + */ + protected function extractFromDirectory($directory) + { + $finder = new Finder(); + + return $finder->files()->name('*.php')->in($directory); + } +} diff --git a/src/Symfony/Component/Translation/Extractor/PhpStringTokenParser.php b/src/Symfony/Component/Translation/Extractor/PhpStringTokenParser.php new file mode 100644 index 0000000000000..bab4ce0c97e26 --- /dev/null +++ b/src/Symfony/Component/Translation/Extractor/PhpStringTokenParser.php @@ -0,0 +1,142 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Extractor; + +/* + * The following is derived from code at http://github.com/nikic/PHP-Parser + * + * Copyright (c) 2011 by Nikita Popov + * + * Some rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * * The names of the contributors may not be used to endorse or + * promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +class PhpStringTokenParser +{ + protected static $replacements = array( + '\\' => '\\', + '$' => '$', + 'n' => "\n", + 'r' => "\r", + 't' => "\t", + 'f' => "\f", + 'v' => "\v", + 'e' => "\x1B", + ); + + /** + * Parses a string token. + * + * @param string $str String token content + * + * @return string The parsed string + */ + public static function parse($str) + { + $bLength = 0; + if ('b' === $str[0]) { + $bLength = 1; + } + + if ('\'' === $str[$bLength]) { + return str_replace( + array('\\\\', '\\\''), + array('\\', '\''), + substr($str, $bLength + 1, -1) + ); + } else { + return self::parseEscapeSequences(substr($str, $bLength + 1, -1), '"'); + } + } + + /** + * Parses escape sequences in strings (all string types apart from single quoted). + * + * @param string $str String without quotes + * @param null|string $quote Quote type + * + * @return string String with escape sequences parsed + */ + public static function parseEscapeSequences($str, $quote) + { + if (null !== $quote) { + $str = str_replace('\\'.$quote, $quote, $str); + } + + return preg_replace_callback( + '~\\\\([\\\\$nrtfve]|[xX][0-9a-fA-F]{1,2}|[0-7]{1,3})~', + array(__CLASS__, 'parseCallback'), + $str + ); + } + + private static function parseCallback($matches) + { + $str = $matches[1]; + + if (isset(self::$replacements[$str])) { + return self::$replacements[$str]; + } elseif ('x' === $str[0] || 'X' === $str[0]) { + return chr(hexdec($str)); + } else { + return chr(octdec($str)); + } + } + + /** + * Parses a constant doc string. + * + * @param string $startToken Doc string start token content (<< + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Translation\Tests\Extractor; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\Translation\Extractor\PhpExtractor; +use Symfony\Component\Translation\MessageCatalogue; + +class PhpExtractorTest extends TestCase +{ + /** + * @dataProvider resourcesProvider + * + * @param array|string $resource + */ + public function testExtraction($resource) + { + // Arrange + $extractor = new PhpExtractor(); + $extractor->setPrefix('prefix'); + $catalogue = new MessageCatalogue('en'); + + // Act + $extractor->extract($resource, $catalogue); + + $expectedHeredoc = << array( + 'single-quoted key' => 'prefixsingle-quoted key', + 'double-quoted key' => 'prefixdouble-quoted key', + 'heredoc key' => 'prefixheredoc key', + 'nowdoc key' => 'prefixnowdoc key', + "double-quoted key with whitespace and escaped \$\n\" sequences" => "prefixdouble-quoted key with whitespace and escaped \$\n\" sequences", + 'single-quoted key with whitespace and nonescaped \$\n\' sequences' => 'prefixsingle-quoted key with whitespace and nonescaped \$\n\' sequences', + 'single-quoted key with "quote mark at the end"' => 'prefixsingle-quoted key with "quote mark at the end"', + $expectedHeredoc => 'prefix'.$expectedHeredoc, + $expectedNowdoc => 'prefix'.$expectedNowdoc, + '{0} There is no apples|{1} There is one apple|]1,Inf[ There are %count% apples' => 'prefix{0} There is no apples|{1} There is one apple|]1,Inf[ There are %count% apples', + ), + 'not_messages' => array( + 'other-domain-test-no-params-short-array' => 'prefixother-domain-test-no-params-short-array', + 'other-domain-test-no-params-long-array' => 'prefixother-domain-test-no-params-long-array', + 'other-domain-test-params-short-array' => 'prefixother-domain-test-params-short-array', + 'other-domain-test-params-long-array' => 'prefixother-domain-test-params-long-array', + 'other-domain-test-trans-choice-short-array-%count%' => 'prefixother-domain-test-trans-choice-short-array-%count%', + 'other-domain-test-trans-choice-long-array-%count%' => 'prefixother-domain-test-trans-choice-long-array-%count%', + 'typecast' => 'prefixtypecast', + 'msg1' => 'prefixmsg1', + 'msg2' => 'prefixmsg2', + ), + ); + $actualCatalogue = $catalogue->all(); + + $this->assertEquals($expectedCatalogue, $actualCatalogue); + } + + public function resourcesProvider() + { + $directory = __DIR__.'/../fixtures/extractor/'; + $splFiles = array(); + foreach (new \DirectoryIterator($directory) as $fileInfo) { + if ($fileInfo->isDot()) { + continue; + } + if ('translation.html.php' === $fileInfo->getBasename()) { + $phpFile = $fileInfo->getPathname(); + } + $splFiles[] = $fileInfo->getFileInfo(); + } + + return array( + array($directory), + array($phpFile), + array(glob($directory.'*')), + array($splFiles), + array(new \ArrayObject(glob($directory.'*'))), + array(new \ArrayObject($splFiles)), + ); + } +} diff --git a/src/Symfony/Component/Translation/Tests/fixtures/extractor/resource.format.engine b/src/Symfony/Component/Translation/Tests/fixtures/extractor/resource.format.engine new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/src/Symfony/Component/Translation/Tests/fixtures/extractor/this.is.a.template.format.engine b/src/Symfony/Component/Translation/Tests/fixtures/extractor/this.is.a.template.format.engine new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/src/Symfony/Component/Translation/Tests/fixtures/extractor/translation.html.php b/src/Symfony/Component/Translation/Tests/fixtures/extractor/translation.html.php new file mode 100644 index 0000000000000..1ce8ea94fd339 --- /dev/null +++ b/src/Symfony/Component/Translation/Tests/fixtures/extractor/translation.html.php @@ -0,0 +1,49 @@ +This template is used for translation message extraction tests +trans('single-quoted key'); ?> +trans('double-quoted key'); ?> +trans(<<<'EOF' +heredoc key +EOF +); ?> +trans(<<<'EOF' +nowdoc key +EOF +); ?> +trans( + "double-quoted key with whitespace and escaped \$\n\" sequences" +); ?> +trans( + 'single-quoted key with whitespace and nonescaped \$\n\' sequences' +); ?> +trans(<< +trans(<<<'EOF' +nowdoc key with whitespace and nonescaped \$\n sequences +EOF +); ?> + +trans('single-quoted key with "quote mark at the end"'); ?> + +transChoice( + '{0} There is no apples|{1} There is one apple|]1,Inf[ There are %count% apples', + 10, + array('%count%' => 10) +); ?> + +trans('other-domain-test-no-params-short-array', array(), 'not_messages'); ?> + +trans('other-domain-test-no-params-long-array', array(), 'not_messages'); ?> + +trans('other-domain-test-params-short-array', array('foo' => 'bar'), 'not_messages'); ?> + +trans('other-domain-test-params-long-array', array('foo' => 'bar'), 'not_messages'); ?> + +transChoice('other-domain-test-trans-choice-short-array-%count%', 10, array('%count%' => 10), 'not_messages'); ?> + +transChoice('other-domain-test-trans-choice-long-array-%count%', 10, array('%count%' => 10), 'not_messages'); ?> + +trans('typecast', array('a' => (int) '123'), 'not_messages'); ?> +transChoice('msg1', 10 + 1, array(), 'not_messages'); ?> +transChoice('msg2', ceil(4.5), array(), 'not_messages'); ?> From 9fac290b411e33c78ee88680d39db9d1515e6de5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9goire=20Pineau?= Date: Fri, 29 Sep 2017 11:11:46 +0200 Subject: [PATCH 0947/1099] [PhpUnitBridge] Make CoverageListenerTest more robust when xdebug is not available --- src/Symfony/Bridge/PhpUnit/Tests/CoverageListenerTest.php | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Bridge/PhpUnit/Tests/CoverageListenerTest.php b/src/Symfony/Bridge/PhpUnit/Tests/CoverageListenerTest.php index 216b860a4bc2c..0d548aa91204e 100644 --- a/src/Symfony/Bridge/PhpUnit/Tests/CoverageListenerTest.php +++ b/src/Symfony/Bridge/PhpUnit/Tests/CoverageListenerTest.php @@ -8,7 +8,7 @@ class CoverageListenerTest extends TestCase { public function test() { - if ("\n" !== PHP_EOL) { + if ('\\' === \DIRECTORY_SEPARATOR) { $this->markTestSkipped('This test cannot be run on Windows.'); } @@ -16,6 +16,11 @@ public function test() $this->markTestSkipped('This test cannot be run on HHVM.'); } + exec('php --ri xdebug -d zend_extension=xdebug.so 2> /dev/null', $output, $returnCode); + if (0 !== $returnCode) { + $this->markTestSkipped('Xdebug is required to run this test.'); + } + $dir = __DIR__.'/../Tests/Fixtures/coverage'; $php = PHP_BINARY; $phpunit = $_SERVER['argv'][0]; From f18a47bef7d3306b6668b4e66e0cec3dcb3decd9 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Fri, 29 Sep 2017 11:41:38 +0200 Subject: [PATCH 0948/1099] doc fixes --- src/Symfony/Component/Config/CHANGELOG.md | 1 + src/Symfony/Component/HttpKernel/CHANGELOG.md | 2 -- .../HttpKernel/CacheWarmer/CacheWarmerAggregate.php | 5 +++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Symfony/Component/Config/CHANGELOG.md b/src/Symfony/Component/Config/CHANGELOG.md index f8a2028e558db..7813ac53ede47 100644 --- a/src/Symfony/Component/Config/CHANGELOG.md +++ b/src/Symfony/Component/Config/CHANGELOG.md @@ -6,6 +6,7 @@ CHANGELOG * added `setDeprecated()` method to indicate a deprecated node * added `XmlUtils::parse()` method to parse an XML string + * deprecated `ConfigCachePass` 3.3.0 ----- diff --git a/src/Symfony/Component/HttpKernel/CHANGELOG.md b/src/Symfony/Component/HttpKernel/CHANGELOG.md index 0c4ee8fa016ea..d646f7f6aea77 100644 --- a/src/Symfony/Component/HttpKernel/CHANGELOG.md +++ b/src/Symfony/Component/HttpKernel/CHANGELOG.md @@ -8,8 +8,6 @@ CHANGELOG * deprecated bundle inheritance * added `RebootableInterface` and implemented it in `Kernel` * deprecated commands auto registration - * added `AddCacheClearerPass` - * added `AddCacheWarmerPass` * deprecated `EnvParametersResource` * added `Symfony\Component\HttpKernel\Client::catchExceptions()` * deprecated the `ChainCacheClearer::add()` method diff --git a/src/Symfony/Component/HttpKernel/CacheWarmer/CacheWarmerAggregate.php b/src/Symfony/Component/HttpKernel/CacheWarmer/CacheWarmerAggregate.php index c53b4e4bf0ab1..7b7b96bcc8f58 100644 --- a/src/Symfony/Component/HttpKernel/CacheWarmer/CacheWarmerAggregate.php +++ b/src/Symfony/Component/HttpKernel/CacheWarmer/CacheWarmerAggregate.php @@ -57,14 +57,15 @@ public function warmUp($cacheDir) * Checks whether this warmer is optional or not. * * @return bool always false - * - * @deprecated since version 3.4, to be removed in 4.0, inject the list of clearers as a constructor argument instead. */ public function isOptional() { return false; } + /** + * @deprecated since version 3.4, to be removed in 4.0, inject the list of clearers as a constructor argument instead. + */ public function setWarmers(array $warmers) { @trigger_error(sprintf('The "%s()" method is deprecated since version 3.4 and will be removed in 4.0, inject the list of clearers as a constructor argument instead.', __METHOD__), E_USER_DEPRECATED); From 1c0701ab8572c216817666b52ccbe28d9747b731 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20M=C3=B6nch?= Date: Fri, 29 Sep 2017 12:03:48 +0200 Subject: [PATCH 0949/1099] [DI] Fix typehint --- .../Loader/Configurator/ParametersConfigurator.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/DependencyInjection/Loader/Configurator/ParametersConfigurator.php b/src/Symfony/Component/DependencyInjection/Loader/Configurator/ParametersConfigurator.php index 0d81869e8bb50..9585b1a4b5c34 100644 --- a/src/Symfony/Component/DependencyInjection/Loader/Configurator/ParametersConfigurator.php +++ b/src/Symfony/Component/DependencyInjection/Loader/Configurator/ParametersConfigurator.php @@ -31,7 +31,7 @@ public function __construct(ContainerBuilder $container) * Creates a parameter. * * @param string $name - * @param string $value + * @param mixed $value * * @return $this */ @@ -46,7 +46,7 @@ final public function set($name, $value) * Creates a parameter. * * @param string $name - * @param string $value + * @param mixed $value * * @return $this */ From 73eda66b99a668f891781ebf49a88ad23e237a36 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Fri, 29 Sep 2017 12:22:06 +0200 Subject: [PATCH 0950/1099] [DowCrawler] Default to UTF-8 when possible --- src/Symfony/Component/DomCrawler/Crawler.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Component/DomCrawler/Crawler.php b/src/Symfony/Component/DomCrawler/Crawler.php index 1ad80e933ee84..5d201dff1eef6 100644 --- a/src/Symfony/Component/DomCrawler/Crawler.php +++ b/src/Symfony/Component/DomCrawler/Crawler.php @@ -127,8 +127,8 @@ public function add($node) /** * Adds HTML/XML content. * - * If the charset is not set via the content type, it is assumed - * to be ISO-8859-1, which is the default charset defined by the + * If the charset is not set via the content type, it is assumed to be UTF-8, + * or ISO-8859-1 as a fallback, which is the default charset defined by the * HTTP 1.1 specification. * * @param string $content A string to parse as HTML/XML @@ -161,7 +161,7 @@ public function addContent($content, $type = null) } if (null === $charset) { - $charset = 'ISO-8859-1'; + $charset = preg_match('//u', $content) ? 'UTF-8' : 'ISO-8859-1'; } if ('x' === $xmlMatches[1]) { From 3392f9f32d8c16348cf4a501e54859d84e4e3a07 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Fri, 29 Sep 2017 12:59:58 +0200 Subject: [PATCH 0951/1099] Fix conflicts between Bridge/PhpUnit and Debug fixtures --- src/Symfony/Bridge/PhpUnit/Tests/CoverageListenerTest.php | 4 ++-- .../Tests/Fixtures/coverage/src/{Bar.php => BarCov.php} | 4 ++-- .../Tests/Fixtures/coverage/src/{Foo.php => FooCov.php} | 2 +- .../PhpUnit/Tests/Fixtures/coverage/tests/BarTest.php | 6 +++--- .../PhpUnit/Tests/Fixtures/coverage/tests/bootstrap.php | 4 ++-- 5 files changed, 10 insertions(+), 10 deletions(-) rename src/Symfony/Bridge/PhpUnit/Tests/Fixtures/coverage/src/{Bar.php => BarCov.php} (87%) rename src/Symfony/Bridge/PhpUnit/Tests/Fixtures/coverage/src/{Foo.php => FooCov.php} (96%) diff --git a/src/Symfony/Bridge/PhpUnit/Tests/CoverageListenerTest.php b/src/Symfony/Bridge/PhpUnit/Tests/CoverageListenerTest.php index 0d548aa91204e..64984ee0b962c 100644 --- a/src/Symfony/Bridge/PhpUnit/Tests/CoverageListenerTest.php +++ b/src/Symfony/Bridge/PhpUnit/Tests/CoverageListenerTest.php @@ -27,11 +27,11 @@ public function test() exec("$php -d zend_extension=xdebug.so $phpunit -c $dir/phpunit-without-listener.xml.dist $dir/tests/ --coverage-text", $output); $output = implode("\n", $output); - $this->assertContains('Foo', $output); + $this->assertContains('FooCov', $output); exec("$php -d zend_extension=xdebug.so $phpunit -c $dir/phpunit-with-listener.xml.dist $dir/tests/ --coverage-text", $output); $output = implode("\n", $output); - $this->assertNotContains('Foo', $output); + $this->assertNotContains('FooCov', $output); $this->assertContains("SutNotFoundTest::test\nCould not find the tested class.", $output); $this->assertNotContains("CoversTest::test\nCould not find the tested class.", $output); $this->assertNotContains("CoversDefaultClassTest::test\nCould not find the tested class.", $output); diff --git a/src/Symfony/Bridge/PhpUnit/Tests/Fixtures/coverage/src/Bar.php b/src/Symfony/Bridge/PhpUnit/Tests/Fixtures/coverage/src/BarCov.php similarity index 87% rename from src/Symfony/Bridge/PhpUnit/Tests/Fixtures/coverage/src/Bar.php rename to src/Symfony/Bridge/PhpUnit/Tests/Fixtures/coverage/src/BarCov.php index b50305a402634..c399e8def2b70 100644 --- a/src/Symfony/Bridge/PhpUnit/Tests/Fixtures/coverage/src/Bar.php +++ b/src/Symfony/Bridge/PhpUnit/Tests/Fixtures/coverage/src/BarCov.php @@ -11,11 +11,11 @@ namespace PhpUnitCoverageTest; -class Bar +class BarCov { private $foo; - public function __construct(Foo $foo) + public function __construct(FooCov $foo) { $this->foo = $foo; } diff --git a/src/Symfony/Bridge/PhpUnit/Tests/Fixtures/coverage/src/Foo.php b/src/Symfony/Bridge/PhpUnit/Tests/Fixtures/coverage/src/FooCov.php similarity index 96% rename from src/Symfony/Bridge/PhpUnit/Tests/Fixtures/coverage/src/Foo.php rename to src/Symfony/Bridge/PhpUnit/Tests/Fixtures/coverage/src/FooCov.php index f811ae70b10a0..7a7b1163452b8 100644 --- a/src/Symfony/Bridge/PhpUnit/Tests/Fixtures/coverage/src/Foo.php +++ b/src/Symfony/Bridge/PhpUnit/Tests/Fixtures/coverage/src/FooCov.php @@ -11,7 +11,7 @@ namespace PhpUnitCoverageTest; -class Foo +class FooCov { public function fooZ() { diff --git a/src/Symfony/Bridge/PhpUnit/Tests/Fixtures/coverage/tests/BarTest.php b/src/Symfony/Bridge/PhpUnit/Tests/Fixtures/coverage/tests/BarTest.php index b49fc706a9cfa..def55c5e975b5 100644 --- a/src/Symfony/Bridge/PhpUnit/Tests/Fixtures/coverage/tests/BarTest.php +++ b/src/Symfony/Bridge/PhpUnit/Tests/Fixtures/coverage/tests/BarTest.php @@ -17,12 +17,12 @@ class BarTest extends TestCase { public function testBar() { - if (!class_exists('PhpUnitCoverageTest\Foo')) { + if (!class_exists('PhpUnitCoverageTest\FooCov')) { $this->markTestSkipped('This test is not part of the main Symfony test suite. It\'s here to test the CoverageListener.'); } - $foo = new \PhpUnitCoverageTest\Foo(); - $bar = new \PhpUnitCoverageTest\Bar($foo); + $foo = new \PhpUnitCoverageTest\FooCov(); + $bar = new \PhpUnitCoverageTest\BarCov($foo); $this->assertSame('bar', $bar->barZ()); } diff --git a/src/Symfony/Bridge/PhpUnit/Tests/Fixtures/coverage/tests/bootstrap.php b/src/Symfony/Bridge/PhpUnit/Tests/Fixtures/coverage/tests/bootstrap.php index 9647a8658d212..925f4831ac89d 100644 --- a/src/Symfony/Bridge/PhpUnit/Tests/Fixtures/coverage/tests/bootstrap.php +++ b/src/Symfony/Bridge/PhpUnit/Tests/Fixtures/coverage/tests/bootstrap.php @@ -9,8 +9,8 @@ * file that was distributed with this source code. */ -require __DIR__.'/../src/Bar.php'; -require __DIR__.'/../src/Foo.php'; +require __DIR__.'/../src/BarCov.php'; +require __DIR__.'/../src/FooCov.php'; require __DIR__.'/../../../../Legacy/CoverageListenerTrait.php'; if (class_exists('PHPUnit_Runner_Version') && version_compare(\PHPUnit_Runner_Version::id(), '6.0.0', '<')) { From 15a2e5b091112e7d6601bd2bf045859355aaff66 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Fri, 29 Sep 2017 13:12:40 +0200 Subject: [PATCH 0952/1099] fix test --- .../Fixtures/coverage/tests/{BarTest.php => BarCovTest.php} | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) rename src/Symfony/Bridge/PhpUnit/Tests/Fixtures/coverage/tests/{BarTest.php => BarCovTest.php} (91%) diff --git a/src/Symfony/Bridge/PhpUnit/Tests/Fixtures/coverage/tests/BarTest.php b/src/Symfony/Bridge/PhpUnit/Tests/Fixtures/coverage/tests/BarCovTest.php similarity index 91% rename from src/Symfony/Bridge/PhpUnit/Tests/Fixtures/coverage/tests/BarTest.php rename to src/Symfony/Bridge/PhpUnit/Tests/Fixtures/coverage/tests/BarCovTest.php index def55c5e975b5..dc7f2cefd01c3 100644 --- a/src/Symfony/Bridge/PhpUnit/Tests/Fixtures/coverage/tests/BarTest.php +++ b/src/Symfony/Bridge/PhpUnit/Tests/Fixtures/coverage/tests/BarCovTest.php @@ -13,9 +13,9 @@ use PHPUnit\Framework\TestCase; -class BarTest extends TestCase +class BarCovTest extends TestCase { - public function testBar() + public function testBarCov() { if (!class_exists('PhpUnitCoverageTest\FooCov')) { $this->markTestSkipped('This test is not part of the main Symfony test suite. It\'s here to test the CoverageListener.'); From 3d19fd98378d4f12e7dcd478faaeb49a89c23193 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Fri, 29 Sep 2017 13:28:23 +0200 Subject: [PATCH 0953/1099] [FrameworkBundle] Use PhpExtractor from Translation --- .../Bundle/FrameworkBundle/Resources/config/translation.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/translation.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/translation.xml index b1f478ac90bac..fddd2abf759eb 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/translation.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/translation.xml @@ -121,7 +121,7 @@ - + From 260d2f02d8c40d6ce2c37e5f28ba5bd31740e8a0 Mon Sep 17 00:00:00 2001 From: Maxime Steinhausser Date: Fri, 29 Sep 2017 13:52:17 +0200 Subject: [PATCH 0954/1099] [DI] EnvVarProcessorInterface: fix missing use --- .../Component/DependencyInjection/EnvVarProcessorInterface.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Symfony/Component/DependencyInjection/EnvVarProcessorInterface.php b/src/Symfony/Component/DependencyInjection/EnvVarProcessorInterface.php index fce9f5cd7a998..654fe55e982fc 100644 --- a/src/Symfony/Component/DependencyInjection/EnvVarProcessorInterface.php +++ b/src/Symfony/Component/DependencyInjection/EnvVarProcessorInterface.php @@ -11,6 +11,8 @@ namespace Symfony\Component\DependencyInjection; +use Symfony\Component\DependencyInjection\Exception\RuntimeException; + /** * The EnvVarProcessorInterface is implemented by objects that manage environment-like variables. * From be093dd79a2de4d67360ca0d0d576773e6cf91ac Mon Sep 17 00:00:00 2001 From: Zan Baldwin Date: Tue, 26 Sep 2017 13:56:45 +0100 Subject: [PATCH 0955/1099] Argon2i Password Encoder Add the Argon2i hashing algorithm provided by libsodium as a core encoder in the Security component, and enable it in the SecurityBundle. Credit to @chalasr for help with unit tests. --- .../Bundle/SecurityBundle/CHANGELOG.md | 1 + .../DependencyInjection/SecurityExtension.php | 13 +++ .../CompleteConfigurationTest.php | 13 +++ .../Fixtures/php/argon2i_encoder.php | 19 ++++ .../Fixtures/xml/argon2i_encoder.xml | 18 +++ .../Fixtures/yml/argon2i_encoder.yml | 13 +++ .../UserPasswordEncoderCommandTest.php | 51 +++++++++ .../Functional/app/PasswordEncode/argon2i.yml | 7 ++ src/Symfony/Component/Security/CHANGELOG.md | 1 + .../Core/Encoder/Argon2iPasswordEncoder.php | 104 ++++++++++++++++++ .../Security/Core/Encoder/EncoderFactory.php | 6 + .../Encoder/Argon2iPasswordEncoderTest.php | 62 +++++++++++ 12 files changed, 308 insertions(+) create mode 100644 src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/argon2i_encoder.php create mode 100644 src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/argon2i_encoder.xml create mode 100644 src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/argon2i_encoder.yml create mode 100644 src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/PasswordEncode/argon2i.yml create mode 100644 src/Symfony/Component/Security/Core/Encoder/Argon2iPasswordEncoder.php create mode 100644 src/Symfony/Component/Security/Core/Tests/Encoder/Argon2iPasswordEncoderTest.php diff --git a/src/Symfony/Bundle/SecurityBundle/CHANGELOG.md b/src/Symfony/Bundle/SecurityBundle/CHANGELOG.md index b759b693cd273..dd27ace596055 100644 --- a/src/Symfony/Bundle/SecurityBundle/CHANGELOG.md +++ b/src/Symfony/Bundle/SecurityBundle/CHANGELOG.md @@ -14,6 +14,7 @@ CHANGELOG * deprecated HTTP digest authentication * deprecated command `acl:set` along with `SetAclCommand` class * deprecated command `init:acl` along with `InitAclCommand` class + * Added support for the new Argon2i password encoder 3.3.0 ----- diff --git a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php index b19f6b1b8d58c..45ab00ac47871 100644 --- a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php +++ b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php @@ -29,6 +29,7 @@ use Symfony\Component\Config\FileLocator; use Symfony\Component\Security\Core\Authorization\ExpressionLanguage; use Symfony\Component\Security\Core\Authorization\Voter\VoterInterface; +use Symfony\Component\Security\Core\Encoder\Argon2iPasswordEncoder; /** * SecurityExtension. @@ -607,6 +608,18 @@ private function createEncoder($config, ContainerBuilder $container) ); } + // Argon2i encoder + if ('argon2i' === $config['algorithm']) { + if (!Argon2iPasswordEncoder::isSupported()) { + throw new InvalidConfigurationException('Argon2i algorithm is not supported. Please install the libsodium extension or upgrade to PHP 7.2+.'); + } + + return array( + 'class' => 'Symfony\Component\Security\Core\Encoder\Argon2iPasswordEncoder', + 'arguments' => array(), + ); + } + // run-time configured encoder return $config; } diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/CompleteConfigurationTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/CompleteConfigurationTest.php index 5a2c731b2ac7d..cb581048448fd 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/CompleteConfigurationTest.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/CompleteConfigurationTest.php @@ -19,6 +19,7 @@ use Symfony\Bundle\SecurityBundle\DependencyInjection\SecurityExtension; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\Security\Core\Authorization\AccessDecisionManager; +use Symfony\Component\Security\Core\Encoder\Argon2iPasswordEncoder; abstract class CompleteConfigurationTest extends TestCase { @@ -451,6 +452,18 @@ public function testEncoders() )), $container->getDefinition('security.encoder_factory.generic')->getArguments()); } + public function testArgon2iEncoder() + { + if (!Argon2iPasswordEncoder::isSupported()) { + $this->markTestSkipped('Argon2i algorithm is not supported.'); + } + + $this->assertSame(array(array('JMS\FooBundle\Entity\User7' => array( + 'class' => 'Symfony\Component\Security\Core\Encoder\Argon2iPasswordEncoder', + 'arguments' => array(), + ))), $this->getContainer('argon2i_encoder')->getDefinition('security.encoder_factory.generic')->getArguments()); + } + /** * @group legacy * @expectedDeprecation The "security.acl" configuration key is deprecated since version 3.4 and will be removed in 4.0. Install symfony/acl-bundle and use the "acl" key instead. diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/argon2i_encoder.php b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/argon2i_encoder.php new file mode 100644 index 0000000000000..23ff1799c8300 --- /dev/null +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/argon2i_encoder.php @@ -0,0 +1,19 @@ +loadFromExtension('security', array( + 'encoders' => array( + 'JMS\FooBundle\Entity\User7' => array( + 'algorithm' => 'argon2i', + ), + ), + 'providers' => array( + 'default' => array('id' => 'foo'), + ), + 'firewalls' => array( + 'main' => array( + 'form_login' => false, + 'http_basic' => null, + 'logout_on_user_change' => true, + ), + ), +)); diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/argon2i_encoder.xml b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/argon2i_encoder.xml new file mode 100644 index 0000000000000..dda4d8ec888c8 --- /dev/null +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/argon2i_encoder.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/argon2i_encoder.yml b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/argon2i_encoder.yml new file mode 100644 index 0000000000000..a51e766005456 --- /dev/null +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/argon2i_encoder.yml @@ -0,0 +1,13 @@ +security: + encoders: + JMS\FooBundle\Entity\User6: + algorithm: argon2i + + providers: + default: { id: foo } + + firewalls: + main: + form_login: false + http_basic: ~ + logout_on_user_change: true diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/UserPasswordEncoderCommandTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/UserPasswordEncoderCommandTest.php index afd3da09ce0d2..ab9275aeed24d 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/UserPasswordEncoderCommandTest.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/UserPasswordEncoderCommandTest.php @@ -15,6 +15,7 @@ use Symfony\Bundle\SecurityBundle\Command\UserPasswordEncoderCommand; use Symfony\Component\Console\Application as ConsoleApplication; use Symfony\Component\Console\Tester\CommandTester; +use Symfony\Component\Security\Core\Encoder\Argon2iPasswordEncoder; use Symfony\Component\Security\Core\Encoder\BCryptPasswordEncoder; use Symfony\Component\Security\Core\Encoder\EncoderFactoryInterface; use Symfony\Component\Security\Core\Encoder\Pbkdf2PasswordEncoder; @@ -69,6 +70,27 @@ public function testEncodePasswordBcrypt() $this->assertTrue($encoder->isPasswordValid($hash, 'password', null)); } + public function testEncodePasswordArgon2i() + { + if (!Argon2iPasswordEncoder::isSupported()) { + $this->markTestSkipped('Argon2i algorithm not available.'); + } + $this->setupArgon2i(); + $this->passwordEncoderCommandTester->execute(array( + 'command' => 'security:encode-password', + 'password' => 'password', + 'user-class' => 'Custom\Class\Argon2i\User', + ), array('interactive' => false)); + + $output = $this->passwordEncoderCommandTester->getDisplay(); + $this->assertContains('Password encoding succeeded', $output); + + $encoder = new Argon2iPasswordEncoder(); + preg_match('# Encoded password\s+(\$argon2i\$[\w\d,=\$+\/]+={0,2})\s+#', $output, $matches); + $hash = $matches[1]; + $this->assertTrue($encoder->isPasswordValid($hash, 'password', null)); + } + public function testEncodePasswordPbkdf2() { $this->passwordEncoderCommandTester->execute(array( @@ -129,6 +151,22 @@ public function testEncodePasswordBcryptOutput() $this->assertNotContains(' Generated salt ', $this->passwordEncoderCommandTester->getDisplay()); } + public function testEncodePasswordArgon2iOutput() + { + if (!Argon2iPasswordEncoder::isSupported()) { + $this->markTestSkipped('Argon2i algorithm not available.'); + } + + $this->setupArgon2i(); + $this->passwordEncoderCommandTester->execute(array( + 'command' => 'security:encode-password', + 'password' => 'p@ssw0rd', + 'user-class' => 'Custom\Class\Argon2i\User', + ), array('interactive' => false)); + + $this->assertNotContains(' Generated salt ', $this->passwordEncoderCommandTester->getDisplay()); + } + public function testEncodePasswordNoConfigForGivenUserClass() { if (method_exists($this, 'expectException')) { @@ -230,4 +268,17 @@ protected function tearDown() { $this->passwordEncoderCommandTester = null; } + + private function setupArgon2i() + { + putenv('COLUMNS='.(119 + strlen(PHP_EOL))); + $kernel = $this->createKernel(array('test_case' => 'PasswordEncode', 'root_config' => 'argon2i')); + $kernel->boot(); + + $application = new Application($kernel); + + $passwordEncoderCommand = $application->get('security:encode-password'); + + $this->passwordEncoderCommandTester = new CommandTester($passwordEncoderCommand); + } } diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/PasswordEncode/argon2i.yml b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/PasswordEncode/argon2i.yml new file mode 100644 index 0000000000000..2ca4f3461a6e9 --- /dev/null +++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/PasswordEncode/argon2i.yml @@ -0,0 +1,7 @@ +imports: + - { resource: config.yml } + +security: + encoders: + Custom\Class\Argon2i\User: + algorithm: argon2i diff --git a/src/Symfony/Component/Security/CHANGELOG.md b/src/Symfony/Component/Security/CHANGELOG.md index 5ac97ca8b20bb..176393c173ec6 100644 --- a/src/Symfony/Component/Security/CHANGELOG.md +++ b/src/Symfony/Component/Security/CHANGELOG.md @@ -13,6 +13,7 @@ CHANGELOG the user will always be logged out when the user has changed between requests. * deprecated HTTP digest authentication + * Added a new password encoder for the Argon2i hashing algorithm 3.3.0 ----- diff --git a/src/Symfony/Component/Security/Core/Encoder/Argon2iPasswordEncoder.php b/src/Symfony/Component/Security/Core/Encoder/Argon2iPasswordEncoder.php new file mode 100644 index 0000000000000..c88bce0081941 --- /dev/null +++ b/src/Symfony/Component/Security/Core/Encoder/Argon2iPasswordEncoder.php @@ -0,0 +1,104 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Security\Core\Encoder; + +use Symfony\Component\Security\Core\Exception\BadCredentialsException; + +/** + * Argon2iPasswordEncoder uses the Argon2i hashing algorithm. + * + * @author Zan Baldwin + */ +class Argon2iPasswordEncoder extends BasePasswordEncoder implements SelfSaltingEncoderInterface +{ + public static function isSupported() + { + return (\PHP_VERSION_ID >= 70200 && \defined('PASSWORD_ARGON2I')) + || \function_exists('sodium_crypto_pwhash_str') + || \extension_loaded('libsodium'); + } + + /** + * {@inheritdoc} + */ + public function encodePassword($raw, $salt) + { + if ($this->isPasswordTooLong($raw)) { + throw new BadCredentialsException('Invalid password.'); + } + + if (\PHP_VERSION_ID >= 70200 && \defined('PASSWORD_ARGON2I')) { + return $this->encodePasswordNative($raw); + } + if (\function_exists('sodium_crypto_pwhash_str')) { + return $this->encodePasswordSodiumFunction($raw); + } + if (\extension_loaded('libsodium')) { + return $this->encodePasswordSodiumExtension($raw); + } + + throw new \LogicException('Argon2i algorithm is not supported. Please install the libsodium extension or upgrade to PHP 7.2+.'); + } + + /** + * {@inheritdoc} + */ + public function isPasswordValid($encoded, $raw, $salt) + { + if (\PHP_VERSION_ID >= 70200 && \defined('PASSWORD_ARGON2I')) { + return !$this->isPasswordTooLong($raw) && password_verify($raw, $encoded); + } + if (\function_exists('sodium_crypto_pwhash_str_verify')) { + $valid = !$this->isPasswordTooLong($raw) && \sodium_crypto_pwhash_str_verify($encoded, $raw); + \sodium_memzero($raw); + + return $valid; + } + if (\extension_loaded('libsodium')) { + $valid = !$this->isPasswordTooLong($raw) && \Sodium\crypto_pwhash_str_verify($encoded, $raw); + \Sodium\memzero($raw); + + return $valid; + } + + throw new \LogicException('Argon2i algorithm is not supported. Please install the libsodium extension or upgrade to PHP 7.2+.'); + } + + private function encodePasswordNative($raw) + { + 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_memzero($raw); + + return $hash; + } + + private function encodePasswordSodiumExtension($raw) + { + $hash = \Sodium\crypto_pwhash_str( + $raw, + \Sodium\CRYPTO_PWHASH_OPSLIMIT_INTERACTIVE, + \Sodium\CRYPTO_PWHASH_MEMLIMIT_INTERACTIVE + ); + \Sodium\memzero($raw); + + return $hash; + } +} diff --git a/src/Symfony/Component/Security/Core/Encoder/EncoderFactory.php b/src/Symfony/Component/Security/Core/Encoder/EncoderFactory.php index 7794b2f4dbcc1..8e1dbc852e746 100644 --- a/src/Symfony/Component/Security/Core/Encoder/EncoderFactory.php +++ b/src/Symfony/Component/Security/Core/Encoder/EncoderFactory.php @@ -109,6 +109,12 @@ private function getEncoderConfigFromAlgorithm($config) 'class' => BCryptPasswordEncoder::class, 'arguments' => array($config['cost']), ); + + case 'argon2i': + return array( + 'class' => Argon2iPasswordEncoder::class, + 'arguments' => array(), + ); } return array( diff --git a/src/Symfony/Component/Security/Core/Tests/Encoder/Argon2iPasswordEncoderTest.php b/src/Symfony/Component/Security/Core/Tests/Encoder/Argon2iPasswordEncoderTest.php new file mode 100644 index 0000000000000..70f2142ec39df --- /dev/null +++ b/src/Symfony/Component/Security/Core/Tests/Encoder/Argon2iPasswordEncoderTest.php @@ -0,0 +1,62 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Security\Core\Tests\Encoder; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\Security\Core\Encoder\Argon2iPasswordEncoder; + +/** + * @author Zan Baldwin + */ +class Argon2iPasswordEncoderTest extends TestCase +{ + const PASSWORD = 'password'; + + protected function setUp() + { + if (!Argon2iPasswordEncoder::isSupported()) { + $this->markTestSkipped('Argon2i algorithm is not supported.'); + } + } + + public function testValidation() + { + $encoder = new Argon2iPasswordEncoder(); + $result = $encoder->encodePassword(self::PASSWORD, null); + $this->assertTrue($encoder->isPasswordValid($result, self::PASSWORD, null)); + $this->assertFalse($encoder->isPasswordValid($result, 'anotherPassword', null)); + } + + /** + * @expectedException \Symfony\Component\Security\Core\Exception\BadCredentialsException + */ + public function testEncodePasswordLength() + { + $encoder = new Argon2iPasswordEncoder(); + $encoder->encodePassword(str_repeat('a', 4097), 'salt'); + } + + public function testCheckPasswordLength() + { + $encoder = new Argon2iPasswordEncoder(); + $result = $encoder->encodePassword(str_repeat('a', 4096), null); + $this->assertFalse($encoder->isPasswordValid($result, str_repeat('a', 4097), null)); + $this->assertTrue($encoder->isPasswordValid($result, str_repeat('a', 4096), null)); + } + + public function testUserProvidedSaltIsNotUsed() + { + $encoder = new Argon2iPasswordEncoder(); + $result = $encoder->encodePassword(self::PASSWORD, 'salt'); + $this->assertTrue($encoder->isPasswordValid($result, self::PASSWORD, 'anotherSalt')); + } +} From 9a06513ec741e6d7975b09300904e79b477bf9dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Sat, 23 Sep 2017 14:20:05 +0100 Subject: [PATCH 0956/1099] [HttpKernel][FrameworkBundle] Add a minimalist default PSR-3 logger --- composer.json | 1 + .../Bundle/FrameworkBundle/CHANGELOG.md | 1 + .../FrameworkBundle/FrameworkBundle.php | 2 + .../Console/Logger/ConsoleLogger.php | 2 + src/Symfony/Component/HttpKernel/CHANGELOG.md | 1 + .../DependencyInjection/LoggerPass.php | 45 ++++ .../Component/HttpKernel/Log/Logger.php | 98 ++++++++ .../DependencyInjection/LoggerPassTest.php | 68 ++++++ .../HttpKernel/Tests/Log/LoggerTest.php | 212 ++++++++++++++++++ .../Component/HttpKernel/composer.json | 3 + 10 files changed, 433 insertions(+) create mode 100644 src/Symfony/Component/HttpKernel/DependencyInjection/LoggerPass.php create mode 100644 src/Symfony/Component/HttpKernel/Log/Logger.php create mode 100644 src/Symfony/Component/HttpKernel/Tests/DependencyInjection/LoggerPassTest.php create mode 100644 src/Symfony/Component/HttpKernel/Tests/Log/LoggerTest.php diff --git a/composer.json b/composer.json index 00039be77db9b..7b55e30efd330 100644 --- a/composer.json +++ b/composer.json @@ -109,6 +109,7 @@ "provide": { "psr/cache-implementation": "1.0", "psr/container-implementation": "1.0", + "psr/log-implementation": "1.0", "psr/simple-cache-implementation": "1.0" }, "autoload": { diff --git a/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md b/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md index 0c7581e7c0b7d..b76987b6c1291 100644 --- a/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md +++ b/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md @@ -4,6 +4,7 @@ CHANGELOG 3.4.0 ----- + * Always register a minimalist logger that writes in `stderr` * Deprecated `profiler.matcher` option * Added support for `EventSubscriberInterface` on `MicroKernelTrait` * Removed `doctrine/cache` from the list of required dependencies in `composer.json` diff --git a/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php b/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php index c6936d35be83d..85569070f3c1e 100644 --- a/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php +++ b/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php @@ -31,6 +31,7 @@ use Symfony\Component\HttpKernel\DependencyInjection\AddCacheClearerPass; use Symfony\Component\HttpKernel\DependencyInjection\AddCacheWarmerPass; use Symfony\Component\HttpKernel\DependencyInjection\ControllerArgumentValueResolverPass; +use Symfony\Component\HttpKernel\DependencyInjection\LoggerPass; use Symfony\Component\HttpKernel\DependencyInjection\RegisterControllerArgumentLocatorsPass; use Symfony\Component\HttpKernel\DependencyInjection\RemoveEmptyControllerArgumentLocatorsPass; use Symfony\Component\HttpKernel\DependencyInjection\ResettableServicePass; @@ -85,6 +86,7 @@ public function build(ContainerBuilder $container) { parent::build($container); + $container->addCompilerPass(new LoggerPass(), PassConfig::TYPE_BEFORE_OPTIMIZATION, -32); $container->addCompilerPass(new RegisterControllerArgumentLocatorsPass()); $container->addCompilerPass(new RemoveEmptyControllerArgumentLocatorsPass(), PassConfig::TYPE_BEFORE_REMOVING); $container->addCompilerPass(new RoutingResolverPass()); diff --git a/src/Symfony/Component/Console/Logger/ConsoleLogger.php b/src/Symfony/Component/Console/Logger/ConsoleLogger.php index 27c9b6b278e17..d7bcdfad003f5 100644 --- a/src/Symfony/Component/Console/Logger/ConsoleLogger.php +++ b/src/Symfony/Component/Console/Logger/ConsoleLogger.php @@ -101,6 +101,8 @@ public function log($level, $message, array $context = array()) /** * Returns true when any messages have been logged at error levels. + * + * @return bool */ public function hasErrored() { diff --git a/src/Symfony/Component/HttpKernel/CHANGELOG.md b/src/Symfony/Component/HttpKernel/CHANGELOG.md index 66e3b38e25ce6..76a2f39735fd5 100644 --- a/src/Symfony/Component/HttpKernel/CHANGELOG.md +++ b/src/Symfony/Component/HttpKernel/CHANGELOG.md @@ -4,6 +4,7 @@ CHANGELOG 3.4.0 ----- + * added a minimalist PSR-3 `Logger` class that writes in `stderr` * made kernels implementing `CompilerPassInterface` able to process the container * deprecated bundle inheritance * added `RebootableInterface` and implemented it in `Kernel` diff --git a/src/Symfony/Component/HttpKernel/DependencyInjection/LoggerPass.php b/src/Symfony/Component/HttpKernel/DependencyInjection/LoggerPass.php new file mode 100644 index 0000000000000..2cffb99b321ec --- /dev/null +++ b/src/Symfony/Component/HttpKernel/DependencyInjection/LoggerPass.php @@ -0,0 +1,45 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\DependencyInjection; + +use Psr\Log\LoggerInterface; +use Psr\Log\LogLevel; +use Symfony\Component\HttpKernel\Log\Logger; +use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; +use Symfony\Component\DependencyInjection\ContainerBuilder; + +/** + * Registers the default logger if necessary. + * + * @author Kévin Dunglas + */ +class LoggerPass implements CompilerPassInterface +{ + /** + * {@inheritdoc} + */ + public function process(ContainerBuilder $container) + { + $alias = $container->setAlias(LoggerInterface::class, 'logger'); + $alias->setPublic(false); + + if ($container->has('logger')) { + return; + } + + $loggerDefinition = $container->register('logger', Logger::class); + $loggerDefinition->setPublic(false); + if ($container->getParameter('kernel.debug')) { + $loggerDefinition->addArgument(LogLevel::DEBUG); + } + } +} diff --git a/src/Symfony/Component/HttpKernel/Log/Logger.php b/src/Symfony/Component/HttpKernel/Log/Logger.php new file mode 100644 index 0000000000000..cf20ca258a322 --- /dev/null +++ b/src/Symfony/Component/HttpKernel/Log/Logger.php @@ -0,0 +1,98 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Log; + +use Psr\Log\AbstractLogger; +use Psr\Log\InvalidArgumentException; +use Psr\Log\LogLevel; + +/** + * Minimalist PSR-3 logger designed to write in stderr or any other stream. + * + * @author Kévin Dunglas + */ +class Logger extends AbstractLogger +{ + private static $levels = array( + LogLevel::DEBUG => 0, + LogLevel::INFO => 1, + LogLevel::NOTICE => 2, + LogLevel::WARNING => 3, + LogLevel::ERROR => 4, + LogLevel::CRITICAL => 5, + LogLevel::ALERT => 6, + LogLevel::EMERGENCY => 7, + ); + + private $minLevelIndex; + private $formatter; + private $handle; + + public function __construct($minLevel = LogLevel::WARNING, $output = 'php://stderr', callable $formatter = null) + { + if (!isset(self::$levels[$minLevel])) { + throw new InvalidArgumentException(sprintf('The log level "%s" does not exist.', $minLevel)); + } + + $this->minLevelIndex = self::$levels[$minLevel]; + $this->formatter = $formatter ?: array($this, 'format'); + if (false === $this->handle = @fopen($output, 'a')) { + throw new InvalidArgumentException(sprintf('Unable to open "%s".', $output)); + } + } + + /** + * {@inheritdoc} + */ + public function log($level, $message, array $context = array()) + { + if (!isset(self::$levels[$level])) { + throw new InvalidArgumentException(sprintf('The log level "%s" does not exist.', $level)); + } + + if (self::$levels[$level] < $this->minLevelIndex) { + return; + } + + $formatter = $this->formatter; + fwrite($this->handle, $formatter($level, $message, $context)); + } + + /** + * @param string $level + * @param string $message + * @param array $context + * + * @return string + */ + private function format($level, $message, array $context) + { + if (false !== strpos($message, '{')) { + $replacements = array(); + foreach ($context as $key => $val) { + if (null === $val || is_scalar($val) || (\is_object($val) && method_exists($val, '__toString'))) { + $replacements["{{$key}}"] = $val; + } elseif ($val instanceof \DateTimeInterface) { + $replacements["{{$key}}"] = $val->format(\DateTime::RFC3339); + } elseif (\is_object($val)) { + $replacements["{{$key}}"] = '[object '.\get_class($val).']'; + } else { + $replacements["{{$key}}"] = '['.\gettype($val).']'; + } + } + + $message = strtr($message, $replacements); + } + + return sprintf('%s [%s] %s', date(\DateTime::RFC3339), $level, $message).\PHP_EOL; + } +} diff --git a/src/Symfony/Component/HttpKernel/Tests/DependencyInjection/LoggerPassTest.php b/src/Symfony/Component/HttpKernel/Tests/DependencyInjection/LoggerPassTest.php new file mode 100644 index 0000000000000..d018929b2a830 --- /dev/null +++ b/src/Symfony/Component/HttpKernel/Tests/DependencyInjection/LoggerPassTest.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\Component\HttpKernel\Tests\DependencyInjection; + +use PHPUnit\Framework\TestCase; +use Psr\Log\LoggerInterface; +use Psr\Log\LogLevel; +use Symfony\Component\HttpKernel\DependencyInjection\LoggerPass; +use Symfony\Component\HttpKernel\Log\Logger; +use Symfony\Component\DependencyInjection\ContainerBuilder; + +/** + * @author Kévin Dunglas + */ +class LoggerPassTest extends TestCase +{ + public function testAlwaysSetAutowiringAlias() + { + $container = new ContainerBuilder(); + $container->register('logger', 'Foo'); + + (new LoggerPass())->process($container); + + $this->assertFalse($container->getAlias(LoggerInterface::class)->isPublic()); + } + + public function testDoNotOverrideExistingLogger() + { + $container = new ContainerBuilder(); + $container->register('logger', 'Foo'); + + (new LoggerPass())->process($container); + + $this->assertSame('Foo', $container->getDefinition('logger')->getClass()); + } + + public function testRegisterLogger() + { + $container = new ContainerBuilder(); + $container->setParameter('kernel.debug', false); + + (new LoggerPass())->process($container); + + $definition = $container->getDefinition('logger'); + $this->assertSame(Logger::class, $definition->getClass()); + $this->assertFalse($definition->isPublic()); + } + + public function testSetMinLevelWhenDebugging() + { + $container = new ContainerBuilder(); + $container->setParameter('kernel.debug', true); + + (new LoggerPass())->process($container); + + $definition = $container->getDefinition('logger'); + $this->assertSame(LogLevel::DEBUG, $definition->getArgument(0)); + } +} diff --git a/src/Symfony/Component/HttpKernel/Tests/Log/LoggerTest.php b/src/Symfony/Component/HttpKernel/Tests/Log/LoggerTest.php new file mode 100644 index 0000000000000..ecf67af78c115 --- /dev/null +++ b/src/Symfony/Component/HttpKernel/Tests/Log/LoggerTest.php @@ -0,0 +1,212 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Tests\Log; + +use PHPUnit\Framework\TestCase; +use Psr\Log\LoggerInterface; +use Psr\Log\LogLevel; +use Symfony\Component\HttpKernel\Log\Logger; + +/** + * @author Kévin Dunglas + * @author Jordi Boggiano + */ +class LoggerTest extends TestCase +{ + /** + * @var LoggerInterface + */ + private $logger; + + /** + * @var string + */ + private $tmpFile; + + protected function setUp() + { + $this->tmpFile = sys_get_temp_dir().DIRECTORY_SEPARATOR.'log'; + $this->logger = new Logger(LogLevel::DEBUG, $this->tmpFile); + } + + protected function tearDown() + { + if (!@unlink($this->tmpFile)) { + file_put_contents($this->tmpFile, ''); + } + } + + public static function assertLogsMatch(array $expected, array $given) + { + foreach ($given as $k => $line) { + self::assertThat(1 === preg_match('/[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}[\+-][0-9]{2}:[0-9]{2} '.preg_quote($expected[$k]).'/', $line), self::isTrue(), "\"$line\" do not match expected pattern \"$expected[$k]\""); + } + } + + /** + * Return the log messages in order. + * + * @return string[] + */ + public function getLogs() + { + return file($this->tmpFile, FILE_IGNORE_NEW_LINES); + } + + public function testImplements() + { + $this->assertInstanceOf(LoggerInterface::class, $this->logger); + } + + /** + * @dataProvider provideLevelsAndMessages + */ + public function testLogsAtAllLevels($level, $message) + { + $this->logger->{$level}($message, array('user' => 'Bob')); + $this->logger->log($level, $message, array('user' => 'Bob')); + + $expected = array( + "[$level] message of level $level with context: Bob", + "[$level] message of level $level with context: Bob", + ); + $this->assertLogsMatch($expected, $this->getLogs()); + } + + public function provideLevelsAndMessages() + { + return array( + LogLevel::EMERGENCY => array(LogLevel::EMERGENCY, 'message of level emergency with context: {user}'), + LogLevel::ALERT => array(LogLevel::ALERT, 'message of level alert with context: {user}'), + LogLevel::CRITICAL => array(LogLevel::CRITICAL, 'message of level critical with context: {user}'), + LogLevel::ERROR => array(LogLevel::ERROR, 'message of level error with context: {user}'), + LogLevel::WARNING => array(LogLevel::WARNING, 'message of level warning with context: {user}'), + LogLevel::NOTICE => array(LogLevel::NOTICE, 'message of level notice with context: {user}'), + LogLevel::INFO => array(LogLevel::INFO, 'message of level info with context: {user}'), + LogLevel::DEBUG => array(LogLevel::DEBUG, 'message of level debug with context: {user}'), + ); + } + + public function testLogLevelDisabled() + { + $this->logger = new Logger(LogLevel::INFO, $this->tmpFile); + + $this->logger->debug('test', array('user' => 'Bob')); + $this->logger->log(LogLevel::DEBUG, 'test', array('user' => 'Bob')); + + // Will always be true, but asserts than an exception isn't thrown + $this->assertSame(array(), $this->getLogs()); + } + + /** + * @expectedException \Psr\Log\InvalidArgumentException + */ + public function testThrowsOnInvalidLevel() + { + $this->logger->log('invalid level', 'Foo'); + } + + /** + * @expectedException \Psr\Log\InvalidArgumentException + */ + public function testThrowsOnInvalidMinLevel() + { + new Logger('invalid'); + } + + /** + * @expectedException \Psr\Log\InvalidArgumentException + */ + public function testInvalidOutput() + { + new Logger(LogLevel::DEBUG, '/'); + } + + public function testContextReplacement() + { + $logger = $this->logger; + $logger->info('{Message {nothing} {user} {foo.bar} a}', array('user' => 'Bob', 'foo.bar' => 'Bar')); + + $expected = array('[info] {Message {nothing} Bob Bar a}'); + $this->assertLogsMatch($expected, $this->getLogs()); + } + + public function testObjectCastToString() + { + if (method_exists($this, 'createPartialMock')) { + $dummy = $this->createPartialMock(DummyTest::class, array('__toString')); + } else { + $dummy = $this->getMock(DummyTest::class, array('__toString')); + } + $dummy->expects($this->atLeastOnce()) + ->method('__toString') + ->will($this->returnValue('DUMMY')); + + $this->logger->warning($dummy); + + $expected = array('[warning] DUMMY'); + $this->assertLogsMatch($expected, $this->getLogs()); + } + + public function testContextCanContainAnything() + { + $context = array( + 'bool' => true, + 'null' => null, + 'string' => 'Foo', + 'int' => 0, + 'float' => 0.5, + 'nested' => array('with object' => new DummyTest()), + 'object' => new \DateTime(), + 'resource' => fopen('php://memory', 'r'), + ); + + $this->logger->warning('Crazy context data', $context); + + $expected = array('[warning] Crazy context data'); + $this->assertLogsMatch($expected, $this->getLogs()); + } + + public function testContextExceptionKeyCanBeExceptionOrOtherValues() + { + $logger = $this->logger; + $logger->warning('Random message', array('exception' => 'oops')); + $logger->critical('Uncaught Exception!', array('exception' => new \LogicException('Fail'))); + + $expected = array( + '[warning] Random message', + '[critical] Uncaught Exception!', + ); + $this->assertLogsMatch($expected, $this->getLogs()); + } + + public function testFormatter() + { + $this->logger = new Logger(LogLevel::DEBUG, $this->tmpFile, function ($level, $message, $context) { + return json_encode(array('level' => $level, 'message' => $message, 'context' => $context)).\PHP_EOL; + }); + + $this->logger->error('An error', array('foo' => 'bar')); + $this->logger->warning('A warning', array('baz' => 'bar')); + $this->assertSame(array( + '{"level":"error","message":"An error","context":{"foo":"bar"}}', + '{"level":"warning","message":"A warning","context":{"baz":"bar"}}', + ), $this->getLogs()); + } +} + +class DummyTest +{ + public function __toString() + { + } +} diff --git a/src/Symfony/Component/HttpKernel/composer.json b/src/Symfony/Component/HttpKernel/composer.json index 3c051bb5f7b33..a372edb588601 100644 --- a/src/Symfony/Component/HttpKernel/composer.json +++ b/src/Symfony/Component/HttpKernel/composer.json @@ -40,6 +40,9 @@ "symfony/var-dumper": "~3.3|~4.0", "psr/cache": "~1.0" }, + "provide": { + "psr/log-implementation": "1.0" + }, "conflict": { "symfony/config": "<2.8", "symfony/dependency-injection": "<3.4", From 722872f4c48e9c76de9fe7156c886fcabd9a3b68 Mon Sep 17 00:00:00 2001 From: Amrouche Hamza Date: Fri, 29 Sep 2017 20:45:30 +0200 Subject: [PATCH 0957/1099] [PHPUnitBridge] don't remove when set to empty string --- src/Symfony/Bridge/PhpUnit/bin/simple-phpunit | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Bridge/PhpUnit/bin/simple-phpunit b/src/Symfony/Bridge/PhpUnit/bin/simple-phpunit index a2747f3be2a09..ae4c818aa327f 100755 --- a/src/Symfony/Bridge/PhpUnit/bin/simple-phpunit +++ b/src/Symfony/Bridge/PhpUnit/bin/simple-phpunit @@ -60,7 +60,8 @@ if (!file_exists("$PHPUNIT_DIR/phpunit-$PHPUNIT_VERSION/phpunit") || md5_file(__ $zip->extractTo(getcwd()); $zip->close(); chdir("phpunit-$PHPUNIT_VERSION"); - passthru("$COMPOSER remove --no-update ".(getenv('SYMFONY_PHPUNIT_REMOVE') ?: 'phpspec/prophecy symfony/yaml')); + $SYMFONY_PHPUNIT_REMOVE = getenv('SYMFONY_PHPUNIT_REMOVE'); + passthru("$COMPOSER remove --no-update ".('' === $SYMFONY_PHPUNIT_REMOVE ?: 'phpspec/prophecy symfony/yaml')); if (5.1 <= $PHPUNIT_VERSION && $PHPUNIT_VERSION < 5.4) { passthru("$COMPOSER require --no-update phpunit/phpunit-mock-objects \"~3.1.0\""); } From ec2aaace236dddcf568a3313ecc3b035443959d3 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Fri, 29 Sep 2017 12:25:35 -0700 Subject: [PATCH 0958/1099] improved error message --- .../WebProfilerBundle/Resources/views/Collector/time.html.twig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/time.html.twig b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/time.html.twig index 28e3a3c8385af..4f20078e6a139 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/time.html.twig +++ b/src/Symfony/Bundle/WebProfilerBundle/Resources/views/Collector/time.html.twig @@ -91,7 +91,7 @@ {% if collector.events is empty %}
-

No timing events have been recorded. Are you sure that debugging is enabled in the kernel?

+

No timing events have been recorded. Check that symfony/stopwatch is installed and debugging enabled in the kernel.

{% else %} {{ block('panelContent') }} From c6c09e4f2844d4aaa37a1530e9ccba3daf748b6a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A1chym=20Tou=C5=A1ek?= Date: Fri, 29 Sep 2017 22:09:03 +0200 Subject: [PATCH 0959/1099] [Form] Fix FormInterface::submit() annotation --- src/Symfony/Component/Form/FormInterface.php | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/Symfony/Component/Form/FormInterface.php b/src/Symfony/Component/Form/FormInterface.php index 780c00f40af48..e28d1a102d81f 100644 --- a/src/Symfony/Component/Form/FormInterface.php +++ b/src/Symfony/Component/Form/FormInterface.php @@ -269,10 +269,9 @@ public function handleRequest($request = null); /** * Submits data to the form, transforms and validates it. * - * @param null|string|array $submittedData The submitted data - * @param bool $clearMissing whether to set fields to NULL - * when they are missing in the - * submitted data + * @param mixed $submittedData The submitted data + * @param bool $clearMissing whether to set fields to NULL when they + * are missing in the submitted data * * @return $this * From e7a5803e2ed6ade6d39d83f0b768aa2d67783eea Mon Sep 17 00:00:00 2001 From: Robin Chalas Date: Thu, 28 Sep 2017 13:56:55 +0200 Subject: [PATCH 0960/1099] [Security] Add user impersonation support for stateless authentication --- UPGRADE-3.4.md | 3 +++ UPGRADE-4.0.md | 2 ++ .../Bundle/SecurityBundle/CHANGELOG.md | 1 + .../DependencyInjection/MainConfiguration.php | 1 + .../DependencyInjection/SecurityExtension.php | 10 +++++-- .../Resources/config/security_listeners.xml | 1 + .../CompleteConfigurationTest.php | 2 ++ .../Fixtures/php/container1.php | 2 +- .../Fixtures/php/container1_with_acl.php | 2 +- .../Fixtures/php/container1_with_digest.php | 2 +- .../Fixtures/php/no_custom_user_checker.php | 2 +- .../Fixtures/xml/container1.xml | 2 +- .../Fixtures/xml/container1_with_acl.xml | 2 +- .../Fixtures/xml/container1_with_digest.xml | 2 +- .../Fixtures/xml/no_custom_user_checker.xml | 2 +- .../Fixtures/yml/container1.yml | 3 ++- .../Fixtures/yml/container1_with_acl.yml | 3 ++- .../Fixtures/yml/container1_with_digest.yml | 3 ++- .../Fixtures/yml/no_custom_user_checker.yml | 3 ++- .../SecurityExtensionTest.php | 26 +++++++++++++++++++ .../Tests/Functional/SwitchUserTest.php | 13 ++++++++++ .../app/JsonLogin/switchuser_stateless.yml | 13 ++++++++++ .../Http/Firewall/SwitchUserListener.php | 15 ++++++----- .../Tests/Firewall/SwitchUserListenerTest.php | 25 ++++++++++++++++++ 24 files changed, 120 insertions(+), 20 deletions(-) create mode 100644 src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/JsonLogin/switchuser_stateless.yml diff --git a/UPGRADE-3.4.md b/UPGRADE-3.4.md index 6561c15a0b46f..09e0a8a002027 100644 --- a/UPGRADE-3.4.md +++ b/UPGRADE-3.4.md @@ -316,6 +316,9 @@ SecurityBundle * Deprecated the HTTP digest authentication: `HttpDigestFactory` will be removed in 4.0. Use another authentication system like `http_basic` instead. + + * Deprecated setting the `switch_user.stateless` option to false when the firewall is `stateless`. + Setting it to false will have no effect in 4.0. Translation ----------- diff --git a/UPGRADE-4.0.md b/UPGRADE-4.0.md index 688a309466b5d..9631609958628 100644 --- a/UPGRADE-4.0.md +++ b/UPGRADE-4.0.md @@ -693,6 +693,8 @@ SecurityBundle * Removed the HTTP digest authentication system. The `HttpDigestFactory` class has been removed. Use another authentication system like `http_basic` instead. + + * The `switch_user.stateless` option is now always true if the firewall is stateless. Serializer ---------- diff --git a/src/Symfony/Bundle/SecurityBundle/CHANGELOG.md b/src/Symfony/Bundle/SecurityBundle/CHANGELOG.md index 4d5a1b8f86eab..12c8fa8a0c504 100644 --- a/src/Symfony/Bundle/SecurityBundle/CHANGELOG.md +++ b/src/Symfony/Bundle/SecurityBundle/CHANGELOG.md @@ -17,6 +17,7 @@ CHANGELOG * deprecated command `acl:set` along with `SetAclCommand` class * deprecated command `init:acl` along with `InitAclCommand` class * Added support for the new Argon2i password encoder + * added `stateless` option to the `switch_user` listener 3.3.0 ----- diff --git a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/MainConfiguration.php b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/MainConfiguration.php index 533b52cd4b1c6..e3c3fcef12141 100644 --- a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/MainConfiguration.php +++ b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/MainConfiguration.php @@ -304,6 +304,7 @@ private function addFirewallsSection(ArrayNodeDefinition $rootNode, array $facto ->scalarNode('provider')->end() ->scalarNode('parameter')->defaultValue('_switch_user')->end() ->scalarNode('role')->defaultValue('ROLE_ALLOWED_TO_SWITCH')->end() + ->booleanNode('stateless')->defaultValue(false)->end() ->end() ->end() ; diff --git a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php index 45ab00ac47871..f0e9abf0a7a15 100644 --- a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php +++ b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php @@ -456,7 +456,7 @@ private function createFirewall(ContainerBuilder $container, $id, $firewall, &$a // Switch user listener if (isset($firewall['switch_user'])) { $listenerKeys[] = 'switch_user'; - $listeners[] = new Reference($this->createSwitchUserListener($container, $id, $firewall['switch_user'], $defaultProvider)); + $listeners[] = new Reference($this->createSwitchUserListener($container, $id, $firewall['switch_user'], $defaultProvider, $firewall['stateless'])); } // Access listener @@ -699,10 +699,15 @@ private function createExceptionListener($container, $config, $id, $defaultEntry return $exceptionListenerId; } - private function createSwitchUserListener($container, $id, $config, $defaultProvider) + private function createSwitchUserListener($container, $id, $config, $defaultProvider, $stateless) { $userProvider = isset($config['provider']) ? $this->getUserProviderId($config['provider']) : $defaultProvider; + // in 4.0, ignore the `switch_user.stateless` key if $stateless is `true` + if ($stateless && false === $config['stateless']) { + @trigger_error(sprintf('Firewall "%s" is configured as "stateless" but the "switch_user.stateless" key is set to false. Both should have the same value, the firewall\'s "stateless" value will be used as default value for the "switch_user.stateless" key in 4.0.', $id), E_USER_DEPRECATED); + } + $switchUserListenerId = 'security.authentication.switchuser_listener.'.$id; $listener = $container->setDefinition($switchUserListenerId, new ChildDefinition('security.authentication.switchuser_listener')); $listener->replaceArgument(1, new Reference($userProvider)); @@ -710,6 +715,7 @@ private function createSwitchUserListener($container, $id, $config, $defaultProv $listener->replaceArgument(3, $id); $listener->replaceArgument(6, $config['parameter']); $listener->replaceArgument(7, $config['role']); + $listener->replaceArgument(9, $config['stateless']); return $switchUserListenerId; } diff --git a/src/Symfony/Bundle/SecurityBundle/Resources/config/security_listeners.xml b/src/Symfony/Bundle/SecurityBundle/Resources/config/security_listeners.xml index ab9a587ad7d18..73c3eed722083 100644 --- a/src/Symfony/Bundle/SecurityBundle/Resources/config/security_listeners.xml +++ b/src/Symfony/Bundle/SecurityBundle/Resources/config/security_listeners.xml @@ -241,6 +241,7 @@ _switch_user ROLE_ALLOWED_TO_SWITCH + false
diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/CompleteConfigurationTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/CompleteConfigurationTest.php index cb581048448fd..ad87bcb112904 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/CompleteConfigurationTest.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/CompleteConfigurationTest.php @@ -130,6 +130,7 @@ public function testFirewalls() array( 'parameter' => '_switch_user', 'role' => 'ROLE_ALLOWED_TO_SWITCH', + 'stateless' => true, ), ), array( @@ -256,6 +257,7 @@ public function testFirewallsWithDigest() array( 'parameter' => '_switch_user', 'role' => 'ROLE_ALLOWED_TO_SWITCH', + 'stateless' => true, ), ), array( diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/container1.php b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/container1.php index a80f880f80850..1395aa5db4920 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/container1.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/container1.php @@ -65,7 +65,7 @@ 'http_basic' => true, 'form_login' => true, 'anonymous' => true, - 'switch_user' => true, + 'switch_user' => array('stateless' => true), 'x509' => true, 'remote_user' => true, 'logout' => true, diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/container1_with_acl.php b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/container1_with_acl.php index fc9b07c4f18b2..f6c156101454b 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/container1_with_acl.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/container1_with_acl.php @@ -67,7 +67,7 @@ 'http_digest' => array('secret' => 'TheSecret'), 'form_login' => true, 'anonymous' => true, - 'switch_user' => true, + 'switch_user' => array('stateless' => true), 'x509' => true, 'remote_user' => true, 'logout' => true, diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/container1_with_digest.php b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/container1_with_digest.php index 581407fcc05a5..d35a5743b69e2 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/container1_with_digest.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/container1_with_digest.php @@ -67,7 +67,7 @@ 'http_digest' => array('secret' => 'TheSecret'), 'form_login' => true, 'anonymous' => true, - 'switch_user' => true, + 'switch_user' => array('stateless' => true), 'x509' => true, 'remote_user' => true, 'logout' => true, diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/no_custom_user_checker.php b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/no_custom_user_checker.php index 3889752f8f928..2724be3e28040 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/no_custom_user_checker.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/no_custom_user_checker.php @@ -17,7 +17,7 @@ 'http_basic' => true, 'form_login' => true, 'anonymous' => true, - 'switch_user' => true, + 'switch_user' => array('stateless' => true), 'x509' => true, 'remote_user' => true, 'logout' => true, diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/container1.xml b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/container1.xml index 01a5940d8c699..ac85132ffe00b 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/container1.xml +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/container1.xml @@ -49,7 +49,7 @@ - + diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/container1_with_acl.xml b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/container1_with_acl.xml index 6d43fcdc4ff80..30b24f8d8ef19 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/container1_with_acl.xml +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/container1_with_acl.xml @@ -51,7 +51,7 @@ - + diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/container1_with_digest.xml b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/container1_with_digest.xml index e5049f2033e51..b0af7529ca70a 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/container1_with_digest.xml +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/container1_with_digest.xml @@ -52,7 +52,7 @@ - + diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/no_custom_user_checker.xml b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/no_custom_user_checker.xml index b97d39adb5a78..996c8a7de20b5 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/no_custom_user_checker.xml +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/no_custom_user_checker.xml @@ -17,7 +17,7 @@ - + diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/container1.yml b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/container1.yml index d9489abca1358..48a572ba7166b 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/container1.yml +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/container1.yml @@ -47,7 +47,8 @@ security: http_basic: true form_login: true anonymous: true - switch_user: true + switch_user: + stateless: true x509: true remote_user: true logout: true diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/container1_with_acl.yml b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/container1_with_acl.yml index e8ed61ef031b9..9a3d902bb5268 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/container1_with_acl.yml +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/container1_with_acl.yml @@ -50,7 +50,8 @@ security: secret: TheSecret form_login: true anonymous: true - switch_user: true + switch_user: + stateless: true x509: true remote_user: true logout: true diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/container1_with_digest.yml b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/container1_with_digest.yml index a2b57201bfbd2..77a4f9b0a353d 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/container1_with_digest.yml +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/container1_with_digest.yml @@ -50,7 +50,8 @@ security: secret: TheSecret form_login: true anonymous: true - switch_user: true + switch_user: + stateless: true x509: true remote_user: true logout: true diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/no_custom_user_checker.yml b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/no_custom_user_checker.yml index 6a196597c51e7..05ee906237db8 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/no_custom_user_checker.yml +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/no_custom_user_checker.yml @@ -12,7 +12,8 @@ security: http_basic: true form_login: true anonymous: true - switch_user: true + switch_user: + stateless: true x509: true remote_user: true logout: true diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/SecurityExtensionTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/SecurityExtensionTest.php index 1055e4afd40f6..9ad7bfb3f8b04 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/SecurityExtensionTest.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/SecurityExtensionTest.php @@ -148,6 +148,32 @@ public function testDeprecationForUserLogout() $container->compile(); } + /** + * @group legacy + * @expectedDeprecation Firewall "some_firewall" is configured as "stateless" but the "switch_user.stateless" key is set to false. Both should have the same value, the firewall's "stateless" value will be used as default value for the "switch_user.stateless" key in 4.0. + */ + public function testSwitchUserNotStatelessOnStatelessFirewall() + { + $container = $this->getRawContainer(); + + $container->loadFromExtension('security', array( + 'providers' => array( + 'default' => array('id' => 'foo'), + ), + + 'firewalls' => array( + 'some_firewall' => array( + 'stateless' => true, + 'http_basic' => null, + 'switch_user' => array('stateless' => false), + 'logout_on_user_change' => true, + ), + ), + )); + + $container->compile(); + } + protected function getRawContainer() { $container = new ContainerBuilder(); diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/SwitchUserTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/SwitchUserTest.php index 697829b1cb75a..d89c24f1233fb 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/SwitchUserTest.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/SwitchUserTest.php @@ -11,6 +11,7 @@ namespace Symfony\Bundle\SecurityBundle\Tests\Functional; +use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\Security\Http\Firewall\SwitchUserListener; class SwitchUserTest extends WebTestCase @@ -50,6 +51,18 @@ public function testSwitchedUserExit() $this->assertEquals('user_can_switch', $client->getProfile()->getCollector('security')->getUser()); } + public function testSwitchUserStateless() + { + $client = $this->createClient(array('test_case' => 'JsonLogin', 'root_config' => 'switchuser_stateless.yml')); + $client->request('POST', '/chk', array('_switch_user' => 'dunglas'), array(), array('CONTENT_TYPE' => 'application/json'), '{"user": {"login": "user_can_switch", "password": "test"}}'); + $response = $client->getResponse(); + + $this->assertInstanceOf(JsonResponse::class, $response); + $this->assertSame(200, $response->getStatusCode()); + $this->assertSame(array('message' => 'Welcome @dunglas!'), json_decode($response->getContent(), true)); + $this->assertSame('dunglas', $client->getProfile()->getCollector('security')->getUser()); + } + public function getTestParameters() { return array( diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/JsonLogin/switchuser_stateless.yml b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/JsonLogin/switchuser_stateless.yml new file mode 100644 index 0000000000000..29789a4caa25f --- /dev/null +++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/JsonLogin/switchuser_stateless.yml @@ -0,0 +1,13 @@ +imports: + - { resource: ./config.yml } + +security: + providers: + in_memory: + memory: + users: + user_can_switch: { password: test, roles: [ROLE_USER, ROLE_ALLOWED_TO_SWITCH] } + firewalls: + main: + switch_user: + stateless: true diff --git a/src/Symfony/Component/Security/Http/Firewall/SwitchUserListener.php b/src/Symfony/Component/Security/Http/Firewall/SwitchUserListener.php index 2fc06140cfd37..d659ffc258db4 100644 --- a/src/Symfony/Component/Security/Http/Firewall/SwitchUserListener.php +++ b/src/Symfony/Component/Security/Http/Firewall/SwitchUserListener.php @@ -49,8 +49,9 @@ class SwitchUserListener implements ListenerInterface private $role; private $logger; private $dispatcher; + private $stateless; - public function __construct(TokenStorageInterface $tokenStorage, UserProviderInterface $provider, UserCheckerInterface $userChecker, $providerKey, AccessDecisionManagerInterface $accessDecisionManager, LoggerInterface $logger = null, $usernameParameter = '_switch_user', $role = 'ROLE_ALLOWED_TO_SWITCH', EventDispatcherInterface $dispatcher = null) + public function __construct(TokenStorageInterface $tokenStorage, UserProviderInterface $provider, UserCheckerInterface $userChecker, $providerKey, AccessDecisionManagerInterface $accessDecisionManager, LoggerInterface $logger = null, $usernameParameter = '_switch_user', $role = 'ROLE_ALLOWED_TO_SWITCH', EventDispatcherInterface $dispatcher = null, $stateless = false) { if (empty($providerKey)) { throw new \InvalidArgumentException('$providerKey must not be empty.'); @@ -65,6 +66,7 @@ public function __construct(TokenStorageInterface $tokenStorage, UserProviderInt $this->role = $role; $this->logger = $logger; $this->dispatcher = $dispatcher; + $this->stateless = $stateless; } /** @@ -92,12 +94,13 @@ public function handle(GetResponseEvent $event) } } - $request->query->remove($this->usernameParameter); - $request->server->set('QUERY_STRING', http_build_query($request->query->all())); + if (!$this->stateless) { + $request->query->remove($this->usernameParameter); + $request->server->set('QUERY_STRING', http_build_query($request->query->all())); + $response = new RedirectResponse($request->getUri(), 302); - $response = new RedirectResponse($request->getUri(), 302); - - $event->setResponse($response); + $event->setResponse($response); + } } /** diff --git a/src/Symfony/Component/Security/Http/Tests/Firewall/SwitchUserListenerTest.php b/src/Symfony/Component/Security/Http/Tests/Firewall/SwitchUserListenerTest.php index c97eda759330b..0e61ee208ee2c 100644 --- a/src/Symfony/Component/Security/Http/Tests/Firewall/SwitchUserListenerTest.php +++ b/src/Symfony/Component/Security/Http/Tests/Firewall/SwitchUserListenerTest.php @@ -266,4 +266,29 @@ public function testSwitchUserWithReplacedToken() $this->assertSame($replacedToken, $this->tokenStorage->getToken()); } + + public function testSwitchUserStateless() + { + $token = new UsernamePasswordToken('username', '', 'key', array('ROLE_FOO')); + $user = new User('username', 'password', array()); + + $this->tokenStorage->setToken($token); + $this->request->query->set('_switch_user', 'kuba'); + + $this->accessDecisionManager->expects($this->once()) + ->method('decide')->with($token, array('ROLE_ALLOWED_TO_SWITCH')) + ->will($this->returnValue(true)); + + $this->userProvider->expects($this->once()) + ->method('loadUserByUsername')->with('kuba') + ->will($this->returnValue($user)); + $this->userChecker->expects($this->once()) + ->method('checkPostAuth')->with($user); + + $listener = new SwitchUserListener($this->tokenStorage, $this->userProvider, $this->userChecker, 'provider123', $this->accessDecisionManager, null, '_switch_user', 'ROLE_ALLOWED_TO_SWITCH', null, true); + $listener->handle($this->event); + + $this->assertInstanceOf('Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken', $this->tokenStorage->getToken()); + $this->assertFalse($this->event->hasResponse()); + } } From 2d1e3347a64b249f75b2b9820f87f60f87200b2c Mon Sep 17 00:00:00 2001 From: Maxime Steinhausser Date: Fri, 29 Sep 2017 20:40:54 +0200 Subject: [PATCH 0961/1099] [SecurityBundle] Deprecate auto picking the first provider when no provider is explicitly configured on a firewall --- UPGRADE-3.4.md | 4 +++ UPGRADE-4.0.md | 4 +++ .../Bundle/SecurityBundle/CHANGELOG.md | 1 + .../DependencyInjection/SecurityExtension.php | 4 +++ .../Fixtures/php/container1.php | 5 +++- .../Fixtures/php/container1_with_acl.php | 5 +++- .../Fixtures/php/container1_with_digest.php | 5 +++- .../Fixtures/xml/container1.xml | 8 +++--- .../Fixtures/xml/container1_with_acl.xml | 8 +++--- .../Fixtures/xml/container1_with_digest.xml | 8 +++--- .../Fixtures/yml/container1.yml | 3 +++ .../Fixtures/yml/container1_with_acl.yml | 3 +++ .../Fixtures/yml/container1_with_digest.yml | 3 +++ .../SecurityExtensionTest.php | 25 +++++++++++++++++++ 14 files changed, 71 insertions(+), 15 deletions(-) diff --git a/UPGRADE-3.4.md b/UPGRADE-3.4.md index 6561c15a0b46f..3bfbde4b32d5c 100644 --- a/UPGRADE-3.4.md +++ b/UPGRADE-3.4.md @@ -316,6 +316,10 @@ SecurityBundle * Deprecated the HTTP digest authentication: `HttpDigestFactory` will be removed in 4.0. Use another authentication system like `http_basic` instead. + + * Not configuring explicitly the provider on a firewall is ambiguous when there is more than one registered provider. + Using the first configured provider is deprecated since 3.4 and will throw an exception on 4.0. + Explicitly configure the provider to use on your firewalls. Translation ----------- diff --git a/UPGRADE-4.0.md b/UPGRADE-4.0.md index 688a309466b5d..c3ba0ed84c9d4 100644 --- a/UPGRADE-4.0.md +++ b/UPGRADE-4.0.md @@ -693,6 +693,10 @@ SecurityBundle * Removed the HTTP digest authentication system. The `HttpDigestFactory` class has been removed. Use another authentication system like `http_basic` instead. + + * Not configuring explicitly the provider on a firewall is ambiguous when there is more than one registered provider. + The first configured provider is not used anymore and an exception is thrown instead. + Explicitly configure the provider to use on your firewalls. Serializer ---------- diff --git a/src/Symfony/Bundle/SecurityBundle/CHANGELOG.md b/src/Symfony/Bundle/SecurityBundle/CHANGELOG.md index 4d5a1b8f86eab..9b02ebac34eee 100644 --- a/src/Symfony/Bundle/SecurityBundle/CHANGELOG.md +++ b/src/Symfony/Bundle/SecurityBundle/CHANGELOG.md @@ -17,6 +17,7 @@ CHANGELOG * deprecated command `acl:set` along with `SetAclCommand` class * deprecated command `init:acl` along with `InitAclCommand` class * Added support for the new Argon2i password encoder + * deprecated auto picking the first registered provider when no configured provider on a firewall and ambiguous 3.3.0 ----- diff --git a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php index 45ab00ac47871..231d5dae7223d 100644 --- a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php +++ b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php @@ -359,6 +359,10 @@ private function createFirewall(ContainerBuilder $container, $id, $firewall, &$a $defaultProvider = $providerIds[$normalizedName]; } else { $defaultProvider = reset($providerIds); + + if (count($providerIds) > 1) { + @trigger_error(sprintf('Firewall "%s" has no "provider" set but multiple providers exist. Using the first configured provider (%s) is deprecated since 3.4 and will throw an exception in 4.0, set the "provider" key on the firewall instead.', $id, key($providerIds)), E_USER_DEPRECATED); + } } $config->replaceArgument(5, $defaultProvider); diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/container1.php b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/container1.php index a80f880f80850..433c9ed2ecb22 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/container1.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/container1.php @@ -60,8 +60,9 @@ ), 'firewalls' => array( - 'simple' => array('pattern' => '/login', 'security' => false), + 'simple' => array('provider' => 'default', 'pattern' => '/login', 'security' => false), 'secure' => array('stateless' => true, + 'provider' => 'default', 'http_basic' => true, 'form_login' => true, 'anonymous' => true, @@ -74,6 +75,7 @@ 'logout_on_user_change' => true, ), 'host' => array( + 'provider' => 'default', 'pattern' => '/test', 'host' => 'foo\\.example\\.org', 'methods' => array('GET', 'POST'), @@ -82,6 +84,7 @@ 'logout_on_user_change' => true, ), 'with_user_checker' => array( + 'provider' => 'default', 'user_checker' => 'app.user_checker', 'anonymous' => true, 'http_basic' => true, diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/container1_with_acl.php b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/container1_with_acl.php index fc9b07c4f18b2..4dd85111cfb22 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/container1_with_acl.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/container1_with_acl.php @@ -61,8 +61,9 @@ ), 'firewalls' => array( - 'simple' => array('pattern' => '/login', 'security' => false), + 'simple' => array('provider' => 'default', 'pattern' => '/login', 'security' => false), 'secure' => array('stateless' => true, + 'provider' => 'default', 'http_basic' => true, 'http_digest' => array('secret' => 'TheSecret'), 'form_login' => true, @@ -75,6 +76,7 @@ 'user_checker' => null, ), 'host' => array( + 'provider' => 'default', 'pattern' => '/test', 'host' => 'foo\\.example\\.org', 'methods' => array('GET', 'POST'), @@ -82,6 +84,7 @@ 'http_basic' => true, ), 'with_user_checker' => array( + 'provider' => 'default', 'user_checker' => 'app.user_checker', 'anonymous' => true, 'http_basic' => true, diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/container1_with_digest.php b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/container1_with_digest.php index 581407fcc05a5..df57aee64bac7 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/container1_with_digest.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/container1_with_digest.php @@ -61,8 +61,9 @@ ), 'firewalls' => array( - 'simple' => array('pattern' => '/login', 'security' => false), + 'simple' => array('provider' => 'default', 'pattern' => '/login', 'security' => false), 'secure' => array('stateless' => true, + 'provider' => 'default', 'http_basic' => true, 'http_digest' => array('secret' => 'TheSecret'), 'form_login' => true, @@ -76,6 +77,7 @@ 'logout_on_user_change' => true, ), 'host' => array( + 'provider' => 'default', 'pattern' => '/test', 'host' => 'foo\\.example\\.org', 'methods' => array('GET', 'POST'), @@ -84,6 +86,7 @@ 'logout_on_user_change' => true, ), 'with_user_checker' => array( + 'provider' => 'default', 'user_checker' => 'app.user_checker', 'anonymous' => true, 'http_basic' => true, diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/container1.xml b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/container1.xml index 01a5940d8c699..56052deb4a1a1 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/container1.xml +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/container1.xml @@ -43,9 +43,9 @@ - + - + @@ -57,12 +57,12 @@ - + - + app.user_checker diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/container1_with_acl.xml b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/container1_with_acl.xml index 6d43fcdc4ff80..fbe21f0bb1742 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/container1_with_acl.xml +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/container1_with_acl.xml @@ -44,9 +44,9 @@ - + - + @@ -59,12 +59,12 @@ - + - + app.user_checker diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/container1_with_digest.xml b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/container1_with_digest.xml index e5049f2033e51..790a90714a4e1 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/container1_with_digest.xml +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/container1_with_digest.xml @@ -45,9 +45,9 @@ - + - + @@ -60,12 +60,12 @@ - + - + app.user_checker diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/container1.yml b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/container1.yml index d9489abca1358..292154660b6dc 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/container1.yml +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/container1.yml @@ -43,6 +43,7 @@ security: firewalls: simple: { pattern: /login, security: false } secure: + provider: default stateless: true http_basic: true form_login: true @@ -56,6 +57,7 @@ security: user_checker: ~ host: + provider: default pattern: /test host: foo\.example\.org methods: [GET,POST] @@ -64,6 +66,7 @@ security: logout_on_user_change: true with_user_checker: + provider: default anonymous: ~ http_basic: ~ user_checker: app.user_checker diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/container1_with_acl.yml b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/container1_with_acl.yml index e8ed61ef031b9..176494e8ba93f 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/container1_with_acl.yml +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/container1_with_acl.yml @@ -44,6 +44,7 @@ security: firewalls: simple: { pattern: /login, security: false } secure: + provider: default stateless: true http_basic: true http_digest: @@ -59,6 +60,7 @@ security: user_checker: ~ host: + provider: default pattern: /test host: foo\.example\.org methods: [GET,POST] @@ -66,6 +68,7 @@ security: http_basic: true with_user_checker: + provider: default anonymous: ~ http_basic: ~ user_checker: app.user_checker diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/container1_with_digest.yml b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/container1_with_digest.yml index a2b57201bfbd2..1e984256f33d1 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/container1_with_digest.yml +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/container1_with_digest.yml @@ -44,6 +44,7 @@ security: firewalls: simple: { pattern: /login, security: false } secure: + provider: default stateless: true http_basic: true http_digest: @@ -59,6 +60,7 @@ security: user_checker: ~ host: + provider: default pattern: /test host: foo\.example\.org methods: [GET,POST] @@ -67,6 +69,7 @@ security: logout_on_user_change: true with_user_checker: + provider: default anonymous: ~ http_basic: ~ user_checker: app.user_checker diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/SecurityExtensionTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/SecurityExtensionTest.php index 1055e4afd40f6..3dd1f817ae618 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/SecurityExtensionTest.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/SecurityExtensionTest.php @@ -148,6 +148,31 @@ public function testDeprecationForUserLogout() $container->compile(); } + /** + * @group legacy + * @expectedDeprecation Firewall "default" has no "provider" set but multiple providers exist. Using the first configured provider (first) is deprecated since 3.4 and will throw an exception in 4.0, set the "provider" key on the firewall instead. + */ + public function testDeprecationForAmbiguousProvider() + { + $container = $this->getRawContainer(); + + $container->loadFromExtension('security', array( + 'providers' => array( + 'first' => array('id' => 'foo'), + 'second' => array('id' => 'bar'), + ), + + 'firewalls' => array( + 'default' => array( + 'http_basic' => null, + 'logout_on_user_change' => true, + ), + ), + )); + + $container->compile(); + } + protected function getRawContainer() { $container = new ContainerBuilder(); From c109dcd5ae0a9c2979bf5ad2957b029f79960b51 Mon Sep 17 00:00:00 2001 From: Maxime Steinhausser Date: Sat, 30 Sep 2017 14:58:47 +0200 Subject: [PATCH 0962/1099] [FrameworkBundle] Register a NullLogger from test kernels --- .../Command/CacheClearCommand/Fixture/TestAppKernel.php | 7 +++++++ .../FrameworkBundle/Tests/Functional/app/AppKernel.php | 7 +++++++ .../FrameworkBundle/Tests/Kernel/ConcreteMicroKernel.php | 2 ++ 3 files changed, 16 insertions(+) diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/CacheClearCommand/Fixture/TestAppKernel.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/CacheClearCommand/Fixture/TestAppKernel.php index 8a61d96d36c6e..18ea12ee30e2a 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/CacheClearCommand/Fixture/TestAppKernel.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/CacheClearCommand/Fixture/TestAppKernel.php @@ -11,8 +11,10 @@ namespace Symfony\Bundle\FrameworkBundle\Tests\Command\CacheClearCommand\Fixture; +use Psr\Log\NullLogger; use Symfony\Bundle\FrameworkBundle\FrameworkBundle; use Symfony\Component\Config\Loader\LoaderInterface; +use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\HttpKernel\Kernel; class TestAppKernel extends Kernel @@ -33,4 +35,9 @@ public function registerContainerConfiguration(LoaderInterface $loader) { $loader->load(__DIR__.DIRECTORY_SEPARATOR.'config.yml'); } + + protected function build(ContainerBuilder $container) + { + $container->register('logger', NullLogger::class); + } } diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/AppKernel.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/AppKernel.php index 58fb963855e2f..e239bb5331696 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/AppKernel.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/AppKernel.php @@ -11,7 +11,9 @@ namespace Symfony\Bundle\FrameworkBundle\Tests\Functional\app; +use Psr\Log\NullLogger; use Symfony\Component\Config\Loader\LoaderInterface; +use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\Filesystem\Filesystem; use Symfony\Component\HttpKernel\Kernel; @@ -72,6 +74,11 @@ public function registerContainerConfiguration(LoaderInterface $loader) $loader->load($this->rootConfig); } + protected function build(ContainerBuilder $container) + { + $container->register('logger', NullLogger::class); + } + public function serialize() { return serialize(array($this->varDir, $this->testCase, $this->rootConfig, $this->getEnvironment(), $this->isDebug())); diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Kernel/ConcreteMicroKernel.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Kernel/ConcreteMicroKernel.php index f476945f3da0c..1994778095d13 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Kernel/ConcreteMicroKernel.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Kernel/ConcreteMicroKernel.php @@ -11,6 +11,7 @@ namespace Symfony\Bundle\FrameworkBundle\Tests\Kernel; +use Psr\Log\NullLogger; use Symfony\Bundle\FrameworkBundle\Kernel\MicroKernelTrait; use Symfony\Bundle\FrameworkBundle\FrameworkBundle; use Symfony\Component\Config\Loader\LoaderInterface; @@ -77,6 +78,7 @@ protected function configureRoutes(RouteCollectionBuilder $routes) protected function configureContainer(ContainerBuilder $c, LoaderInterface $loader) { + $c->register('logger', NullLogger::class); $c->loadFromExtension('framework', array( 'secret' => '$ecret', )); From 2080582a75769db4b9e32b241ec0da90c05af6a6 Mon Sep 17 00:00:00 2001 From: Antoine Bellion Date: Fri, 29 Sep 2017 13:45:44 +0200 Subject: [PATCH 0963/1099] [HttpFoundation] Return instance in StreamedResponse --- .../HttpFoundation/StreamedResponse.php | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/HttpFoundation/StreamedResponse.php b/src/Symfony/Component/HttpFoundation/StreamedResponse.php index 928531309ad0a..cd86be1363cd4 100644 --- a/src/Symfony/Component/HttpFoundation/StreamedResponse.php +++ b/src/Symfony/Component/HttpFoundation/StreamedResponse.php @@ -66,16 +66,22 @@ public static function create($callback = null, $status = 200, $headers = array( * Sets the PHP callback associated with this Response. * * @param callable $callback A valid PHP callback + * + * @return $this */ public function setCallback(callable $callback) { $this->callback = $callback; + + return $this; } /** * {@inheritdoc} * * This method only sends the headers once. + * + * @return $this */ public function sendHeaders() { @@ -85,13 +91,15 @@ public function sendHeaders() $this->headersSent = true; - parent::sendHeaders(); + return parent::sendHeaders(); } /** * {@inheritdoc} * * This method only sends the content once. + * + * @return $this */ public function sendContent() { @@ -106,18 +114,24 @@ public function sendContent() } call_user_func($this->callback); + + return $this; } /** * {@inheritdoc} * * @throws \LogicException when the content is not null + * + * @return $this */ public function setContent($content) { if (null !== $content) { throw new \LogicException('The content cannot be set on a StreamedResponse instance.'); } + + return $this; } /** From 5ee9043d8b81dfaf84beb5e9b79fc5bc0a001b2b Mon Sep 17 00:00:00 2001 From: Oskar Stark Date: Thu, 28 Sep 2017 08:42:58 +0200 Subject: [PATCH 0964/1099] removed useless PHPDoc --- .../Bridge/Doctrine/CacheWarmer/ProxyCacheWarmer.php | 2 -- .../Bridge/Doctrine/DataFixtures/ContainerAwareLoader.php | 2 -- .../CompilerPass/RegisterMappingsPass.php | 2 -- .../Bridge/Doctrine/HttpFoundation/DbalSessionHandler.php | 2 -- src/Symfony/Bridge/Doctrine/Logger/DbalLogger.php | 4 ---- src/Symfony/Bridge/Monolog/Handler/ConsoleHandler.php | 2 -- .../ProxyManager/LazyProxy/PhpDumper/ProxyDumper.php | 2 -- .../Swiftmailer/DataCollector/MessageDataCollector.php | 4 ---- src/Symfony/Bridge/Twig/Extension/CodeExtension.php | 2 -- src/Symfony/Bridge/Twig/Extension/HttpKernelExtension.php | 2 -- .../NodeVisitor/TranslationDefaultDomainNodeVisitor.php | 5 ----- .../FrameworkBundle/CacheWarmer/RouterCacheWarmer.php | 2 -- .../Bundle/FrameworkBundle/CacheWarmer/TemplateFinder.php | 2 -- .../CacheWarmer/TemplatePathsCacheWarmer.php | 2 -- .../Bundle/FrameworkBundle/Console/Application.php | 4 ---- .../FrameworkBundle/Console/Helper/DescriptorHelper.php | 3 --- .../FrameworkBundle/Controller/ControllerNameParser.php | 4 +--- .../FrameworkBundle/Controller/ControllerResolver.php | 4 ---- .../Bundle/FrameworkBundle/HttpCache/HttpCache.php | 2 -- .../Bundle/FrameworkBundle/Routing/DelegatingLoader.php | 2 -- src/Symfony/Bundle/FrameworkBundle/Routing/Router.php | 2 -- .../FrameworkBundle/Templating/Asset/PathPackage.php | 2 -- .../Bundle/FrameworkBundle/Templating/Debugger.php | 2 -- .../FrameworkBundle/Templating/DelegatingEngine.php | 2 -- .../FrameworkBundle/Templating/Helper/ActionsHelper.php | 2 -- .../FrameworkBundle/Templating/Helper/CodeHelper.php | 4 ---- .../FrameworkBundle/Templating/Helper/RequestHelper.php | 2 -- .../FrameworkBundle/Templating/Helper/RouterHelper.php | 2 -- .../FrameworkBundle/Templating/Helper/SessionHelper.php | 2 -- .../Templating/Helper/TranslatorHelper.php | 4 ---- .../Templating/Loader/FilesystemLoader.php | 2 -- .../FrameworkBundle/Templating/Loader/TemplateLocator.php | 2 -- .../Bundle/FrameworkBundle/Templating/PhpEngine.php | 2 -- .../FrameworkBundle/Templating/TemplateNameParser.php | 2 -- .../Bundle/FrameworkBundle/Templating/TimedPhpEngine.php | 2 -- .../Bundle/FrameworkBundle/Translation/Translator.php | 2 -- .../Validator/ConstraintValidatorFactory.php | 2 -- .../DataCollector/SecurityDataCollector.php | 4 ---- .../DependencyInjection/MainConfiguration.php | 2 -- .../SecurityBundle/Templating/Helper/LogoutUrlHelper.php | 2 -- .../TwigBundle/CacheWarmer/TemplateCacheCacheWarmer.php | 2 -- src/Symfony/Bundle/TwigBundle/Loader/FilesystemLoader.php | 2 -- .../WebProfilerBundle/Controller/ProfilerController.php | 4 ---- src/Symfony/Component/BrowserKit/Client.php | 2 -- src/Symfony/Component/BrowserKit/Request.php | 4 ---- src/Symfony/Component/BrowserKit/Response.php | 4 ---- src/Symfony/Component/ClassLoader/ApcClassLoader.php | 2 -- .../Component/ClassLoader/ApcUniversalClassLoader.php | 2 -- src/Symfony/Component/ClassLoader/DebugClassLoader.php | 2 -- src/Symfony/Component/ClassLoader/MapClassLoader.php | 2 -- src/Symfony/Component/ClassLoader/WinCacheClassLoader.php | 2 -- src/Symfony/Component/ClassLoader/XcacheClassLoader.php | 2 -- src/Symfony/Component/Config/Definition/BaseNode.php | 2 -- .../Component/Config/Definition/Builder/ExprBuilder.php | 2 -- .../Component/Config/Definition/Builder/MergeBuilder.php | 2 -- .../Component/Config/Definition/Builder/NodeBuilder.php | 3 --- .../Config/Definition/Builder/NodeDefinition.php | 2 -- .../Config/Definition/Builder/NormalizationBuilder.php | 2 -- .../Config/Definition/Builder/ValidationBuilder.php | 2 -- src/Symfony/Component/Config/FileLocator.php | 2 -- src/Symfony/Component/Config/Loader/DelegatingLoader.php | 2 -- src/Symfony/Component/Config/Loader/FileLoader.php | 2 -- src/Symfony/Component/Config/Loader/LoaderResolver.php | 2 -- .../Component/Config/Resource/DirectoryResource.php | 2 -- src/Symfony/Component/Config/Resource/FileResource.php | 2 -- src/Symfony/Component/Console/Application.php | 2 -- src/Symfony/Component/Console/Command/Command.php | 2 -- .../Console/Descriptor/ApplicationDescription.php | 2 -- .../Console/Formatter/OutputFormatterStyleStack.php | 2 -- src/Symfony/Component/Console/Helper/DescriptorHelper.php | 3 --- src/Symfony/Component/Console/Helper/HelperSet.php | 2 -- src/Symfony/Component/Console/Helper/ProgressBar.php | 2 -- src/Symfony/Component/Console/Input/ArgvInput.php | 2 -- src/Symfony/Component/Console/Input/ArrayInput.php | 2 -- src/Symfony/Component/Console/Input/Input.php | 2 -- src/Symfony/Component/Console/Input/InputArgument.php | 2 -- src/Symfony/Component/Console/Input/InputDefinition.php | 2 -- src/Symfony/Component/Console/Input/InputOption.php | 2 -- src/Symfony/Component/Console/Input/StringInput.php | 2 -- src/Symfony/Component/Console/Output/ConsoleOutput.php | 2 -- src/Symfony/Component/Console/Output/Output.php | 2 -- src/Symfony/Component/Console/Output/StreamOutput.php | 2 -- src/Symfony/Component/Console/Question/ChoiceQuestion.php | 2 -- .../Component/Console/Question/ConfirmationQuestion.php | 2 -- src/Symfony/Component/Console/Question/Question.php | 2 -- src/Symfony/Component/Console/Shell.php | 2 -- .../Component/Console/Tester/ApplicationTester.php | 2 -- src/Symfony/Component/Console/Tester/CommandTester.php | 2 -- src/Symfony/Component/CssSelector/Node/Specificity.php | 2 -- src/Symfony/Component/CssSelector/Parser/Parser.php | 2 -- .../Component/CssSelector/Parser/Tokenizer/Tokenizer.php | 3 --- .../CssSelector/Parser/Tokenizer/TokenizerPatterns.php | 3 --- .../CssSelector/XPath/Extension/HtmlExtension.php | 2 -- .../CssSelector/XPath/Extension/NodeExtension.php | 2 -- src/Symfony/Component/Debug/DebugClassLoader.php | 2 -- .../Component/DependencyInjection/Dumper/PhpDumper.php | 8 -------- .../Tests/Fixtures/php/services1-1.php | 5 ----- .../DependencyInjection/Tests/Fixtures/php/services1.php | 5 ----- .../DependencyInjection/Tests/Fixtures/php/services10.php | 5 ----- .../DependencyInjection/Tests/Fixtures/php/services12.php | 5 ----- .../DependencyInjection/Tests/Fixtures/php/services13.php | 5 ----- .../DependencyInjection/Tests/Fixtures/php/services19.php | 5 ----- .../DependencyInjection/Tests/Fixtures/php/services20.php | 5 ----- .../DependencyInjection/Tests/Fixtures/php/services8.php | 5 ----- .../DependencyInjection/Tests/Fixtures/php/services9.php | 5 ----- .../Tests/Fixtures/php/services9_compiled.php | 5 ----- src/Symfony/Component/DomCrawler/Crawler.php | 2 -- src/Symfony/Component/DomCrawler/Field/FormField.php | 2 -- src/Symfony/Component/DomCrawler/Form.php | 2 -- src/Symfony/Component/DomCrawler/Link.php | 2 -- .../EventDispatcher/ContainerAwareEventDispatcher.php | 2 -- .../EventDispatcher/Debug/TraceableEventDispatcher.php | 2 -- .../DependencyInjection/RegisterListenersPass.php | 2 -- src/Symfony/Component/ExpressionLanguage/Expression.php | 2 -- .../Component/ExpressionLanguage/ExpressionFunction.php | 2 -- src/Symfony/Component/ExpressionLanguage/Node/Node.php | 2 -- .../Component/ExpressionLanguage/ParsedExpression.php | 2 -- .../ExpressionLanguage/SerializedParsedExpression.php | 2 -- src/Symfony/Component/ExpressionLanguage/Token.php | 2 -- src/Symfony/Component/ExpressionLanguage/TokenStream.php | 2 -- .../Component/Finder/Adapter/AbstractFindAdapter.php | 3 --- .../Component/Finder/Comparator/DateComparator.php | 2 -- .../Component/Finder/Comparator/NumberComparator.php | 2 -- src/Symfony/Component/Finder/Finder.php | 3 --- .../Component/Finder/Iterator/CustomFilterIterator.php | 2 -- .../Component/Finder/Iterator/DateRangeFilterIterator.php | 2 -- .../Finder/Iterator/DepthRangeFilterIterator.php | 2 -- .../Finder/Iterator/ExcludeDirectoryFilterIterator.php | 2 -- .../Component/Finder/Iterator/FileTypeFilterIterator.php | 2 -- .../Finder/Iterator/MultiplePcreFilterIterator.php | 2 -- .../Finder/Iterator/RecursiveDirectoryIterator.php | 2 -- .../Component/Finder/Iterator/SizeRangeFilterIterator.php | 2 -- .../Component/Finder/Iterator/SortableIterator.php | 2 -- src/Symfony/Component/Finder/Shell/Command.php | 2 -- src/Symfony/Component/Finder/SplFileInfo.php | 2 -- src/Symfony/Component/Form/CallbackTransformer.php | 2 -- .../Core/DataTransformer/BaseDateTimeTransformer.php | 2 -- .../DataTransformer/ChoiceToBooleanArrayTransformer.php | 2 -- .../Core/DataTransformer/ChoiceToValueTransformer.php | 2 -- .../Core/DataTransformer/ChoicesToValuesTransformer.php | 2 -- .../Core/DataTransformer/DateTimeToArrayTransformer.php | 2 -- .../DateTimeToLocalizedStringTransformer.php | 2 -- .../PercentToLocalizedStringTransformer.php | 2 -- .../Core/EventListener/FixCheckboxInputListener.php | 2 -- .../Core/EventListener/FixRadioInputListener.php | 2 -- .../Core/EventListener/FixUrlProtocolListener.php | 2 -- .../Component/Form/Extension/Csrf/CsrfExtension.php | 2 -- src/Symfony/Component/Form/FormError.php | 2 -- src/Symfony/Component/Form/FormRegistry.php | 2 -- src/Symfony/Component/Form/FormRenderer.php | 2 -- src/Symfony/Component/Form/FormTypeGuesserChain.php | 2 -- src/Symfony/Component/Form/Guess/Guess.php | 2 -- src/Symfony/Component/Form/Guess/TypeGuess.php | 2 -- src/Symfony/Component/Form/Guess/ValueGuess.php | 2 -- src/Symfony/Component/HttpFoundation/AcceptHeader.php | 2 -- src/Symfony/Component/HttpFoundation/AcceptHeaderItem.php | 2 -- .../Component/HttpFoundation/BinaryFileResponse.php | 2 -- src/Symfony/Component/HttpFoundation/Cookie.php | 2 -- .../File/Exception/AccessDeniedException.php | 2 -- .../File/Exception/FileNotFoundException.php | 2 -- .../File/MimeType/FileBinaryMimeTypeGuesser.php | 2 -- .../File/MimeType/FileinfoMimeTypeGuesser.php | 2 -- src/Symfony/Component/HttpFoundation/FileBag.php | 2 -- src/Symfony/Component/HttpFoundation/HeaderBag.php | 2 -- src/Symfony/Component/HttpFoundation/JsonResponse.php | 2 -- src/Symfony/Component/HttpFoundation/ParameterBag.php | 2 -- src/Symfony/Component/HttpFoundation/Request.php | 2 -- src/Symfony/Component/HttpFoundation/Response.php | 2 -- .../Component/HttpFoundation/ResponseHeaderBag.php | 2 -- .../HttpFoundation/Session/Attribute/AttributeBag.php | 2 -- .../Session/Attribute/NamespacedAttributeBag.php | 2 -- .../HttpFoundation/Session/Flash/AutoExpireFlashBag.php | 2 -- .../Component/HttpFoundation/Session/Flash/FlashBag.php | 2 -- src/Symfony/Component/HttpFoundation/Session/Session.php | 4 ---- .../Session/Storage/Handler/LegacyPdoSessionHandler.php | 2 -- .../Session/Storage/Handler/MemcacheSessionHandler.php | 4 ---- .../Session/Storage/Handler/MemcachedSessionHandler.php | 4 ---- .../Session/Storage/Handler/MongoDbSessionHandler.php | 4 ---- .../Session/Storage/Handler/NativeFileSessionHandler.php | 4 ---- .../Session/Storage/Handler/PdoSessionHandler.php | 2 -- .../HttpFoundation/Session/Storage/MetadataBag.php | 2 -- .../Session/Storage/MockArraySessionStorage.php | 2 -- .../Session/Storage/MockFileSessionStorage.php | 2 -- .../Session/Storage/NativeSessionStorage.php | 2 -- .../Session/Storage/PhpBridgeSessionStorage.php | 2 -- .../HttpFoundation/Session/Storage/Proxy/NativeProxy.php | 5 ----- .../Session/Storage/Proxy/SessionHandlerProxy.php | 4 ---- src/Symfony/Component/HttpFoundation/StreamedResponse.php | 2 -- src/Symfony/Component/HttpKernel/Client.php | 2 -- .../Component/HttpKernel/Config/EnvParametersResource.php | 2 -- src/Symfony/Component/HttpKernel/Config/FileLocator.php | 2 -- .../HttpKernel/Controller/ControllerReference.php | 2 -- .../HttpKernel/Controller/ControllerResolver.php | 4 ---- .../HttpKernel/Controller/TraceableControllerResolver.php | 4 ---- .../HttpKernel/DataCollector/ConfigDataCollector.php | 4 ---- .../DependencyInjection/ContainerAwareHttpKernel.php | 2 -- .../HttpKernel/EventListener/FragmentListener.php | 2 -- .../HttpKernel/EventListener/ProfilerListener.php | 2 -- .../Component/HttpKernel/EventListener/RouterListener.php | 2 -- .../HttpKernel/EventListener/SurrogateListener.php | 2 -- .../HttpKernel/Exception/AccessDeniedHttpException.php | 4 ---- .../HttpKernel/Exception/BadRequestHttpException.php | 4 ---- .../HttpKernel/Exception/ConflictHttpException.php | 4 ---- .../Component/HttpKernel/Exception/GoneHttpException.php | 4 ---- .../HttpKernel/Exception/LengthRequiredHttpException.php | 4 ---- .../Exception/MethodNotAllowedHttpException.php | 4 ---- .../HttpKernel/Exception/NotAcceptableHttpException.php | 4 ---- .../HttpKernel/Exception/NotFoundHttpException.php | 4 ---- .../Exception/PreconditionFailedHttpException.php | 4 ---- .../Exception/PreconditionRequiredHttpException.php | 4 ---- .../Exception/ServiceUnavailableHttpException.php | 4 ---- .../HttpKernel/Exception/TooManyRequestsHttpException.php | 4 ---- .../HttpKernel/Exception/UnauthorizedHttpException.php | 4 ---- .../Exception/UnprocessableEntityHttpException.php | 4 ---- .../Exception/UnsupportedMediaTypeHttpException.php | 4 ---- .../Fragment/AbstractSurrogateFragmentRenderer.php | 2 -- .../Component/HttpKernel/Fragment/FragmentHandler.php | 2 -- .../HttpKernel/Fragment/HIncludeFragmentRenderer.php | 2 -- .../HttpKernel/Fragment/InlineFragmentRenderer.php | 2 -- src/Symfony/Component/HttpKernel/HttpCache/Esi.php | 2 -- src/Symfony/Component/HttpKernel/HttpCache/HttpCache.php | 2 -- src/Symfony/Component/HttpKernel/HttpCache/Ssi.php | 2 -- src/Symfony/Component/HttpKernel/HttpCache/Store.php | 2 -- src/Symfony/Component/HttpKernel/HttpKernel.php | 2 -- src/Symfony/Component/HttpKernel/Kernel.php | 2 -- .../HttpKernel/Profiler/BaseMemcacheProfilerStorage.php | 2 -- .../HttpKernel/Profiler/MongoDbProfilerStorage.php | 2 -- .../Component/HttpKernel/Profiler/PdoProfilerStorage.php | 2 -- src/Symfony/Component/HttpKernel/Profiler/Profile.php | 2 -- src/Symfony/Component/HttpKernel/Profiler/Profiler.php | 2 -- .../HttpKernel/Profiler/RedisProfilerStorage.php | 2 -- src/Symfony/Component/HttpKernel/UriSigner.php | 2 -- src/Symfony/Component/Intl/Collator/Collator.php | 2 -- .../Intl/DateFormatter/DateFormat/FullTransformer.php | 2 -- .../Intl/DateFormatter/DateFormat/MonthTransformer.php | 3 --- .../Component/Intl/DateFormatter/IntlDateFormatter.php | 2 -- .../Exception/MethodArgumentNotImplementedException.php | 2 -- .../MethodArgumentValueNotImplementedException.php | 2 -- .../Intl/Exception/MethodNotImplementedException.php | 2 -- .../Component/Intl/Exception/NotImplementedException.php | 2 -- .../Component/Intl/NumberFormatter/NumberFormatter.php | 2 -- src/Symfony/Component/Process/PhpProcess.php | 2 -- src/Symfony/Component/Process/Process.php | 2 -- src/Symfony/Component/Process/ProcessBuilder.php | 4 ---- .../Component/PropertyAccess/PropertyPathIterator.php | 2 -- src/Symfony/Component/Routing/Annotation/Route.php | 2 -- src/Symfony/Component/Routing/CompiledRoute.php | 2 -- .../Routing/Generator/Dumper/GeneratorDumper.php | 2 -- .../Routing/Generator/Dumper/PhpGeneratorDumper.php | 5 ----- src/Symfony/Component/Routing/Generator/UrlGenerator.php | 2 -- .../Component/Routing/Loader/AnnotationClassLoader.php | 2 -- .../Component/Routing/Loader/AnnotationFileLoader.php | 2 -- .../Component/Routing/Matcher/Dumper/DumperRoute.php | 2 -- .../Component/Routing/Matcher/Dumper/MatcherDumper.php | 2 -- .../Component/Routing/Matcher/Dumper/PhpMatcherDumper.php | 5 ----- src/Symfony/Component/Routing/Matcher/UrlMatcher.php | 2 -- src/Symfony/Component/Routing/RequestContext.php | 2 -- src/Symfony/Component/Routing/Route.php | 2 -- src/Symfony/Component/Routing/Router.php | 2 -- .../Routing/Tests/Fixtures/dumper/url_matcher1.php | 5 ----- .../Routing/Tests/Fixtures/dumper/url_matcher2.php | 5 ----- .../Routing/Tests/Fixtures/dumper/url_matcher3.php | 5 ----- src/Symfony/Component/Security/Acl/Dbal/AclProvider.php | 2 -- src/Symfony/Component/Security/Acl/Dbal/Schema.php | 2 -- src/Symfony/Component/Security/Acl/Domain/Acl.php | 2 -- .../Component/Security/Acl/Domain/AclCollectionCache.php | 2 -- .../Component/Security/Acl/Domain/DoctrineAclCache.php | 2 -- src/Symfony/Component/Security/Acl/Domain/Entry.php | 2 -- src/Symfony/Component/Security/Acl/Domain/FieldEntry.php | 2 -- .../Component/Security/Acl/Domain/ObjectIdentity.php | 2 -- .../Security/Acl/Domain/RoleSecurityIdentity.php | 2 -- .../Acl/Domain/SecurityIdentityRetrievalStrategy.php | 2 -- .../Security/Acl/Domain/UserSecurityIdentity.php | 2 -- .../Security/Acl/Permission/AbstractMaskBuilder.php | 2 -- .../Core/Authentication/AuthenticationProviderManager.php | 2 -- .../Core/Authentication/AuthenticationTrustResolver.php | 2 -- .../Provider/AnonymousAuthenticationProvider.php | 2 -- .../Authentication/Provider/DaoAuthenticationProvider.php | 2 -- .../Provider/PreAuthenticatedAuthenticationProvider.php | 2 -- .../Provider/RememberMeAuthenticationProvider.php | 2 -- .../Provider/UserAuthenticationProvider.php | 2 -- .../Core/Authentication/RememberMe/PersistentToken.php | 2 -- .../Security/Core/Authentication/Token/AbstractToken.php | 2 -- .../Security/Core/Authentication/Token/AnonymousToken.php | 2 -- .../Core/Authentication/Token/PreAuthenticatedToken.php | 2 -- .../Core/Authentication/Token/RememberMeToken.php | 2 -- .../Core/Authentication/Token/UsernamePasswordToken.php | 2 -- .../Security/Core/Authorization/AccessDecisionManager.php | 2 -- .../Security/Core/Authorization/AuthorizationChecker.php | 2 -- .../Core/Authorization/Voter/AuthenticatedVoter.php | 2 -- .../Security/Core/Authorization/Voter/ExpressionVoter.php | 2 -- .../Security/Core/Authorization/Voter/RoleVoter.php | 2 -- .../Security/Core/Encoder/BCryptPasswordEncoder.php | 2 -- .../Core/Encoder/MessageDigestPasswordEncoder.php | 2 -- .../Security/Core/Encoder/Pbkdf2PasswordEncoder.php | 2 -- .../Security/Core/Encoder/PlaintextPasswordEncoder.php | 2 -- src/Symfony/Component/Security/Core/Role/Role.php | 2 -- .../Component/Security/Core/Role/RoleHierarchy.php | 2 -- .../Component/Security/Core/Role/SwitchUserRole.php | 2 -- .../Component/Security/Core/User/InMemoryUserProvider.php | 2 -- src/Symfony/Component/Security/Csrf/CsrfToken.php | 2 -- src/Symfony/Component/Security/Http/AccessMap.php | 2 -- .../Authentication/CustomAuthenticationFailureHandler.php | 2 -- .../Authentication/CustomAuthenticationSuccessHandler.php | 2 -- .../DefaultAuthenticationFailureHandler.php | 2 -- .../DefaultAuthenticationSuccessHandler.php | 2 -- .../Http/Authentication/SimpleAuthenticationHandler.php | 2 -- .../Http/EntryPoint/FormAuthenticationEntryPoint.php | 2 -- .../Security/Http/Event/InteractiveLoginEvent.php | 4 ---- src/Symfony/Component/Security/Http/Firewall.php | 2 -- .../Http/Firewall/AbstractAuthenticationListener.php | 2 -- .../Component/Security/Http/Firewall/LogoutListener.php | 2 -- .../Security/Http/Firewall/RememberMeListener.php | 2 -- .../Http/Firewall/SimpleFormAuthenticationListener.php | 2 -- .../Http/Firewall/SimplePreAuthenticationListener.php | 2 -- src/Symfony/Component/Security/Http/HttpUtils.php | 2 -- .../Security/Http/Logout/CookieClearingLogoutHandler.php | 2 -- .../Http/RememberMe/AbstractRememberMeServices.php | 2 -- .../RememberMe/PersistentTokenBasedRememberMeServices.php | 2 -- .../Component/Serializer/Mapping/Loader/FileLoader.php | 2 -- src/Symfony/Component/Stopwatch/Section.php | 2 -- src/Symfony/Component/Stopwatch/StopwatchEvent.php | 2 -- src/Symfony/Component/Stopwatch/StopwatchPeriod.php | 2 -- src/Symfony/Component/Templating/Asset/Package.php | 2 -- src/Symfony/Component/Templating/Asset/PathPackage.php | 2 -- src/Symfony/Component/Templating/Asset/UrlPackage.php | 2 -- src/Symfony/Component/Templating/DelegatingEngine.php | 2 -- src/Symfony/Component/Templating/Helper/AssetsHelper.php | 2 -- .../Component/Templating/Helper/CoreAssetsHelper.php | 2 -- src/Symfony/Component/Templating/Loader/CacheLoader.php | 2 -- src/Symfony/Component/Templating/Loader/ChainLoader.php | 2 -- .../Component/Templating/Loader/FilesystemLoader.php | 2 -- src/Symfony/Component/Templating/PhpEngine.php | 2 -- src/Symfony/Component/Templating/Storage/Storage.php | 2 -- src/Symfony/Component/Translation/IdentityTranslator.php | 2 -- src/Symfony/Component/Translation/MessageCatalogue.php | 4 ---- src/Symfony/Component/Translation/Translator.php | 4 ---- .../Component/Validator/Mapping/GetterMetadata.php | 2 -- .../Component/Validator/Mapping/MemberMetadata.php | 2 -- .../Component/Validator/Mapping/PropertyMetadata.php | 2 -- src/Symfony/Component/Yaml/Exception/ParseException.php | 2 -- src/Symfony/Component/Yaml/Parser.php | 2 -- 342 files changed, 1 insertion(+), 826 deletions(-) diff --git a/src/Symfony/Bridge/Doctrine/CacheWarmer/ProxyCacheWarmer.php b/src/Symfony/Bridge/Doctrine/CacheWarmer/ProxyCacheWarmer.php index b1e4f6a9d93b1..9725fdcc088f9 100644 --- a/src/Symfony/Bridge/Doctrine/CacheWarmer/ProxyCacheWarmer.php +++ b/src/Symfony/Bridge/Doctrine/CacheWarmer/ProxyCacheWarmer.php @@ -27,8 +27,6 @@ class ProxyCacheWarmer implements CacheWarmerInterface private $registry; /** - * Constructor. - * * @param ManagerRegistry $registry A ManagerRegistry instance */ public function __construct(ManagerRegistry $registry) diff --git a/src/Symfony/Bridge/Doctrine/DataFixtures/ContainerAwareLoader.php b/src/Symfony/Bridge/Doctrine/DataFixtures/ContainerAwareLoader.php index 0b1052719f559..93cd2c11f9a4d 100644 --- a/src/Symfony/Bridge/Doctrine/DataFixtures/ContainerAwareLoader.php +++ b/src/Symfony/Bridge/Doctrine/DataFixtures/ContainerAwareLoader.php @@ -31,8 +31,6 @@ class ContainerAwareLoader extends Loader private $container; /** - * Constructor. - * * @param ContainerInterface $container A ContainerInterface instance */ public function __construct(ContainerInterface $container) diff --git a/src/Symfony/Bridge/Doctrine/DependencyInjection/CompilerPass/RegisterMappingsPass.php b/src/Symfony/Bridge/Doctrine/DependencyInjection/CompilerPass/RegisterMappingsPass.php index e37e4f66c29aa..d6ab657d515b3 100644 --- a/src/Symfony/Bridge/Doctrine/DependencyInjection/CompilerPass/RegisterMappingsPass.php +++ b/src/Symfony/Bridge/Doctrine/DependencyInjection/CompilerPass/RegisterMappingsPass.php @@ -97,8 +97,6 @@ abstract class RegisterMappingsPass implements CompilerPassInterface private $aliasMap; /** - * Constructor. - * * The $managerParameters is an ordered list of container parameters that could provide the * name of the manager to register these namespaces and alias on. The first non-empty name * is used, the others skipped. diff --git a/src/Symfony/Bridge/Doctrine/HttpFoundation/DbalSessionHandler.php b/src/Symfony/Bridge/Doctrine/HttpFoundation/DbalSessionHandler.php index d819ff0a6c51e..6ae9c469bb166 100644 --- a/src/Symfony/Bridge/Doctrine/HttpFoundation/DbalSessionHandler.php +++ b/src/Symfony/Bridge/Doctrine/HttpFoundation/DbalSessionHandler.php @@ -54,8 +54,6 @@ class DbalSessionHandler implements \SessionHandlerInterface private $timeCol = 'sess_time'; /** - * Constructor. - * * @param Connection $con A connection * @param string $tableName Table name */ diff --git a/src/Symfony/Bridge/Doctrine/Logger/DbalLogger.php b/src/Symfony/Bridge/Doctrine/Logger/DbalLogger.php index acd8cc0fcd510..9fab65a12c039 100644 --- a/src/Symfony/Bridge/Doctrine/Logger/DbalLogger.php +++ b/src/Symfony/Bridge/Doctrine/Logger/DbalLogger.php @@ -16,8 +16,6 @@ use Doctrine\DBAL\Logging\SQLLogger; /** - * DbalLogger. - * * @author Fabien Potencier */ class DbalLogger implements SQLLogger @@ -29,8 +27,6 @@ class DbalLogger implements SQLLogger protected $stopwatch; /** - * Constructor. - * * @param LoggerInterface $logger A LoggerInterface instance * @param Stopwatch $stopwatch A Stopwatch instance */ diff --git a/src/Symfony/Bridge/Monolog/Handler/ConsoleHandler.php b/src/Symfony/Bridge/Monolog/Handler/ConsoleHandler.php index 0b9ada21b2c50..2b3bafa8b7794 100644 --- a/src/Symfony/Bridge/Monolog/Handler/ConsoleHandler.php +++ b/src/Symfony/Bridge/Monolog/Handler/ConsoleHandler.php @@ -56,8 +56,6 @@ class ConsoleHandler extends AbstractProcessingHandler implements EventSubscribe ); /** - * Constructor. - * * @param OutputInterface|null $output The console output to use (the handler remains disabled when passing null * until the output is set, e.g. by using console events) * @param bool $bubble Whether the messages that are handled can bubble up the stack diff --git a/src/Symfony/Bridge/ProxyManager/LazyProxy/PhpDumper/ProxyDumper.php b/src/Symfony/Bridge/ProxyManager/LazyProxy/PhpDumper/ProxyDumper.php index 40791358500a0..45509058c051e 100644 --- a/src/Symfony/Bridge/ProxyManager/LazyProxy/PhpDumper/ProxyDumper.php +++ b/src/Symfony/Bridge/ProxyManager/LazyProxy/PhpDumper/ProxyDumper.php @@ -41,8 +41,6 @@ class ProxyDumper implements DumperInterface private $classGenerator; /** - * Constructor. - * * @param string $salt */ public function __construct($salt = '') diff --git a/src/Symfony/Bridge/Swiftmailer/DataCollector/MessageDataCollector.php b/src/Symfony/Bridge/Swiftmailer/DataCollector/MessageDataCollector.php index a7d7f541baa3d..aaf114311cab7 100644 --- a/src/Symfony/Bridge/Swiftmailer/DataCollector/MessageDataCollector.php +++ b/src/Symfony/Bridge/Swiftmailer/DataCollector/MessageDataCollector.php @@ -19,8 +19,6 @@ use Symfony\Component\DependencyInjection\ContainerInterface; /** - * MessageDataCollector. - * * @author Fabien Potencier * @author Clément JOBEILI * @@ -33,8 +31,6 @@ class MessageDataCollector extends DataCollector private $isSpool; /** - * Constructor. - * * We don't inject the message logger and mailer here * to avoid the creation of these objects when no emails are sent. * diff --git a/src/Symfony/Bridge/Twig/Extension/CodeExtension.php b/src/Symfony/Bridge/Twig/Extension/CodeExtension.php index eca1e52d77a70..84e150e3ef1c9 100644 --- a/src/Symfony/Bridge/Twig/Extension/CodeExtension.php +++ b/src/Symfony/Bridge/Twig/Extension/CodeExtension.php @@ -26,8 +26,6 @@ class CodeExtension extends AbstractExtension private $charset; /** - * Constructor. - * * @param string $fileLinkFormat The format for links to source files * @param string $rootDir The project root directory * @param string $charset The charset diff --git a/src/Symfony/Bridge/Twig/Extension/HttpKernelExtension.php b/src/Symfony/Bridge/Twig/Extension/HttpKernelExtension.php index 07e913059754c..bbf6fea639815 100644 --- a/src/Symfony/Bridge/Twig/Extension/HttpKernelExtension.php +++ b/src/Symfony/Bridge/Twig/Extension/HttpKernelExtension.php @@ -26,8 +26,6 @@ class HttpKernelExtension extends AbstractExtension private $handler; /** - * Constructor. - * * @param FragmentHandler $handler A FragmentHandler instance */ public function __construct(FragmentHandler $handler) diff --git a/src/Symfony/Bridge/Twig/NodeVisitor/TranslationDefaultDomainNodeVisitor.php b/src/Symfony/Bridge/Twig/NodeVisitor/TranslationDefaultDomainNodeVisitor.php index b3c89d18eb2bd..c04ce13a1881b 100644 --- a/src/Symfony/Bridge/Twig/NodeVisitor/TranslationDefaultDomainNodeVisitor.php +++ b/src/Symfony/Bridge/Twig/NodeVisitor/TranslationDefaultDomainNodeVisitor.php @@ -26,8 +26,6 @@ use Twig\NodeVisitor\AbstractNodeVisitor; /** - * TranslationDefaultDomainNodeVisitor. - * * @author Fabien Potencier */ class TranslationDefaultDomainNodeVisitor extends AbstractNodeVisitor @@ -37,9 +35,6 @@ class TranslationDefaultDomainNodeVisitor extends AbstractNodeVisitor */ private $scope; - /** - * Constructor. - */ public function __construct() { $this->scope = new Scope(); diff --git a/src/Symfony/Bundle/FrameworkBundle/CacheWarmer/RouterCacheWarmer.php b/src/Symfony/Bundle/FrameworkBundle/CacheWarmer/RouterCacheWarmer.php index 256bebebe80b7..3515cfc7f3225 100644 --- a/src/Symfony/Bundle/FrameworkBundle/CacheWarmer/RouterCacheWarmer.php +++ b/src/Symfony/Bundle/FrameworkBundle/CacheWarmer/RouterCacheWarmer.php @@ -25,8 +25,6 @@ class RouterCacheWarmer implements CacheWarmerInterface protected $router; /** - * Constructor. - * * @param RouterInterface $router A Router instance */ public function __construct(RouterInterface $router) diff --git a/src/Symfony/Bundle/FrameworkBundle/CacheWarmer/TemplateFinder.php b/src/Symfony/Bundle/FrameworkBundle/CacheWarmer/TemplateFinder.php index 2b756a2997abc..d68fa7ce77674 100644 --- a/src/Symfony/Bundle/FrameworkBundle/CacheWarmer/TemplateFinder.php +++ b/src/Symfony/Bundle/FrameworkBundle/CacheWarmer/TemplateFinder.php @@ -29,8 +29,6 @@ class TemplateFinder implements TemplateFinderInterface private $templates; /** - * Constructor. - * * @param KernelInterface $kernel A KernelInterface instance * @param TemplateNameParserInterface $parser A TemplateNameParserInterface instance * @param string $rootDir The directory where global templates can be stored diff --git a/src/Symfony/Bundle/FrameworkBundle/CacheWarmer/TemplatePathsCacheWarmer.php b/src/Symfony/Bundle/FrameworkBundle/CacheWarmer/TemplatePathsCacheWarmer.php index 829218bb2c828..2cb19d9df20b0 100644 --- a/src/Symfony/Bundle/FrameworkBundle/CacheWarmer/TemplatePathsCacheWarmer.php +++ b/src/Symfony/Bundle/FrameworkBundle/CacheWarmer/TemplatePathsCacheWarmer.php @@ -25,8 +25,6 @@ class TemplatePathsCacheWarmer extends CacheWarmer protected $locator; /** - * Constructor. - * * @param TemplateFinderInterface $finder A template finder * @param TemplateLocator $locator The template locator */ diff --git a/src/Symfony/Bundle/FrameworkBundle/Console/Application.php b/src/Symfony/Bundle/FrameworkBundle/Console/Application.php index 3ccb97fe39231..54cce9a45954c 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Console/Application.php +++ b/src/Symfony/Bundle/FrameworkBundle/Console/Application.php @@ -22,8 +22,6 @@ use Symfony\Component\HttpKernel\Bundle\Bundle; /** - * Application. - * * @author Fabien Potencier */ class Application extends BaseApplication @@ -32,8 +30,6 @@ class Application extends BaseApplication private $commandsRegistered = false; /** - * Constructor. - * * @param KernelInterface $kernel A KernelInterface instance */ public function __construct(KernelInterface $kernel) diff --git a/src/Symfony/Bundle/FrameworkBundle/Console/Helper/DescriptorHelper.php b/src/Symfony/Bundle/FrameworkBundle/Console/Helper/DescriptorHelper.php index 2599f0090e5d3..475c22ca31e80 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Console/Helper/DescriptorHelper.php +++ b/src/Symfony/Bundle/FrameworkBundle/Console/Helper/DescriptorHelper.php @@ -24,9 +24,6 @@ */ class DescriptorHelper extends BaseDescriptorHelper { - /** - * Constructor. - */ public function __construct() { $this diff --git a/src/Symfony/Bundle/FrameworkBundle/Controller/ControllerNameParser.php b/src/Symfony/Bundle/FrameworkBundle/Controller/ControllerNameParser.php index 989dc8cd23d7c..8d6203a06fb68 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Controller/ControllerNameParser.php +++ b/src/Symfony/Bundle/FrameworkBundle/Controller/ControllerNameParser.php @@ -25,8 +25,6 @@ class ControllerNameParser protected $kernel; /** - * Constructor. - * * @param KernelInterface $kernel A KernelInterface instance */ public function __construct(KernelInterface $kernel) @@ -141,7 +139,7 @@ private function findAlternative($nonExistentBundleName) } $lev = levenshtein($nonExistentBundleName, $bundleName); - if ($lev <= strlen($nonExistentBundleName) / 3 && ($alternative === null || $lev < $shortest)) { + if ($lev <= strlen($nonExistentBundleName) / 3 && (null === $alternative || $lev < $shortest)) { $alternative = $bundleName; $shortest = $lev; } diff --git a/src/Symfony/Bundle/FrameworkBundle/Controller/ControllerResolver.php b/src/Symfony/Bundle/FrameworkBundle/Controller/ControllerResolver.php index 31593b9b80506..00f4f1ed148c3 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Controller/ControllerResolver.php +++ b/src/Symfony/Bundle/FrameworkBundle/Controller/ControllerResolver.php @@ -17,8 +17,6 @@ use Symfony\Component\DependencyInjection\ContainerAwareInterface; /** - * ControllerResolver. - * * @author Fabien Potencier */ class ControllerResolver extends BaseControllerResolver @@ -27,8 +25,6 @@ class ControllerResolver extends BaseControllerResolver protected $parser; /** - * Constructor. - * * @param ContainerInterface $container A ContainerInterface instance * @param ControllerNameParser $parser A ControllerNameParser instance * @param LoggerInterface $logger A LoggerInterface instance diff --git a/src/Symfony/Bundle/FrameworkBundle/HttpCache/HttpCache.php b/src/Symfony/Bundle/FrameworkBundle/HttpCache/HttpCache.php index 05dbfb3bd0cfb..d50598bb1db00 100644 --- a/src/Symfony/Bundle/FrameworkBundle/HttpCache/HttpCache.php +++ b/src/Symfony/Bundle/FrameworkBundle/HttpCache/HttpCache.php @@ -29,8 +29,6 @@ abstract class HttpCache extends BaseHttpCache protected $kernel; /** - * Constructor. - * * @param HttpKernelInterface $kernel An HttpKernelInterface instance * @param string $cacheDir The cache directory (default used if null) */ diff --git a/src/Symfony/Bundle/FrameworkBundle/Routing/DelegatingLoader.php b/src/Symfony/Bundle/FrameworkBundle/Routing/DelegatingLoader.php index 29f3072a897cd..b54ac4e8373b7 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Routing/DelegatingLoader.php +++ b/src/Symfony/Bundle/FrameworkBundle/Routing/DelegatingLoader.php @@ -32,8 +32,6 @@ class DelegatingLoader extends BaseDelegatingLoader private $loading = false; /** - * Constructor. - * * @param ControllerNameParser $parser A ControllerNameParser instance * @param LoggerInterface $logger A LoggerInterface instance * @param LoaderResolverInterface $resolver A LoaderResolverInterface instance diff --git a/src/Symfony/Bundle/FrameworkBundle/Routing/Router.php b/src/Symfony/Bundle/FrameworkBundle/Routing/Router.php index 4ef5f0a4bd1c4..ec37ca3067cbf 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Routing/Router.php +++ b/src/Symfony/Bundle/FrameworkBundle/Routing/Router.php @@ -29,8 +29,6 @@ class Router extends BaseRouter implements WarmableInterface private $container; /** - * Constructor. - * * @param ContainerInterface $container A ContainerInterface instance * @param mixed $resource The main resource to load * @param array $options An array of options diff --git a/src/Symfony/Bundle/FrameworkBundle/Templating/Asset/PathPackage.php b/src/Symfony/Bundle/FrameworkBundle/Templating/Asset/PathPackage.php index 1eb801c4546c8..27f6af8d6634e 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Templating/Asset/PathPackage.php +++ b/src/Symfony/Bundle/FrameworkBundle/Templating/Asset/PathPackage.php @@ -26,8 +26,6 @@ class PathPackage extends BasePathPackage { /** - * Constructor. - * * @param Request $request The current request * @param string $version The version * @param string $format The version format diff --git a/src/Symfony/Bundle/FrameworkBundle/Templating/Debugger.php b/src/Symfony/Bundle/FrameworkBundle/Templating/Debugger.php index 55471027449b9..7dcdec2b4bc79 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Templating/Debugger.php +++ b/src/Symfony/Bundle/FrameworkBundle/Templating/Debugger.php @@ -29,8 +29,6 @@ class Debugger implements DebuggerInterface protected $logger; /** - * Constructor. - * * @param LoggerInterface $logger A LoggerInterface instance */ public function __construct(LoggerInterface $logger = null) diff --git a/src/Symfony/Bundle/FrameworkBundle/Templating/DelegatingEngine.php b/src/Symfony/Bundle/FrameworkBundle/Templating/DelegatingEngine.php index c204ffa2f03b2..a6a0b508fbda2 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Templating/DelegatingEngine.php +++ b/src/Symfony/Bundle/FrameworkBundle/Templating/DelegatingEngine.php @@ -25,8 +25,6 @@ class DelegatingEngine extends BaseDelegatingEngine implements EngineInterface protected $container; /** - * Constructor. - * * @param ContainerInterface $container The DI container * @param array $engineIds An array of engine Ids */ diff --git a/src/Symfony/Bundle/FrameworkBundle/Templating/Helper/ActionsHelper.php b/src/Symfony/Bundle/FrameworkBundle/Templating/Helper/ActionsHelper.php index 8f0d54eada32c..8e1e242f01ac4 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Templating/Helper/ActionsHelper.php +++ b/src/Symfony/Bundle/FrameworkBundle/Templating/Helper/ActionsHelper.php @@ -25,8 +25,6 @@ class ActionsHelper extends Helper private $handler; /** - * Constructor. - * * @param FragmentHandler $handler A FragmentHandler instance */ public function __construct(FragmentHandler $handler) diff --git a/src/Symfony/Bundle/FrameworkBundle/Templating/Helper/CodeHelper.php b/src/Symfony/Bundle/FrameworkBundle/Templating/Helper/CodeHelper.php index 06071e51b276c..aac7ec85cc2f7 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Templating/Helper/CodeHelper.php +++ b/src/Symfony/Bundle/FrameworkBundle/Templating/Helper/CodeHelper.php @@ -14,8 +14,6 @@ use Symfony\Component\Templating\Helper\Helper; /** - * CodeHelper. - * * @author Fabien Potencier */ class CodeHelper extends Helper @@ -25,8 +23,6 @@ class CodeHelper extends Helper protected $charset; /** - * Constructor. - * * @param string $fileLinkFormat The format for links to source files * @param string $rootDir The project root directory * @param string $charset The charset diff --git a/src/Symfony/Bundle/FrameworkBundle/Templating/Helper/RequestHelper.php b/src/Symfony/Bundle/FrameworkBundle/Templating/Helper/RequestHelper.php index ec28f12ba63f6..1d0a32243cd5c 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Templating/Helper/RequestHelper.php +++ b/src/Symfony/Bundle/FrameworkBundle/Templating/Helper/RequestHelper.php @@ -26,8 +26,6 @@ class RequestHelper extends Helper protected $requestStack; /** - * Constructor. - * * @param Request|RequestStack $requestStack A RequestStack instance or a Request instance * * @deprecated since version 2.5, passing a Request instance is deprecated and support for it will be removed in 3.0. diff --git a/src/Symfony/Bundle/FrameworkBundle/Templating/Helper/RouterHelper.php b/src/Symfony/Bundle/FrameworkBundle/Templating/Helper/RouterHelper.php index d54caaf395509..e9d5d03c71859 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Templating/Helper/RouterHelper.php +++ b/src/Symfony/Bundle/FrameworkBundle/Templating/Helper/RouterHelper.php @@ -24,8 +24,6 @@ class RouterHelper extends Helper protected $generator; /** - * Constructor. - * * @param UrlGeneratorInterface $router A Router instance */ public function __construct(UrlGeneratorInterface $router) diff --git a/src/Symfony/Bundle/FrameworkBundle/Templating/Helper/SessionHelper.php b/src/Symfony/Bundle/FrameworkBundle/Templating/Helper/SessionHelper.php index 5d15fa3464b07..1149943b4ee0d 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Templating/Helper/SessionHelper.php +++ b/src/Symfony/Bundle/FrameworkBundle/Templating/Helper/SessionHelper.php @@ -26,8 +26,6 @@ class SessionHelper extends Helper protected $requestStack; /** - * Constructor. - * * @param Request|RequestStack $requestStack A RequestStack instance or a Request instance * * @deprecated since version 2.5, passing a Request instance is deprecated and support for it will be removed in 3.0. diff --git a/src/Symfony/Bundle/FrameworkBundle/Templating/Helper/TranslatorHelper.php b/src/Symfony/Bundle/FrameworkBundle/Templating/Helper/TranslatorHelper.php index 2c2641a885b13..9893c5e35c9c5 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Templating/Helper/TranslatorHelper.php +++ b/src/Symfony/Bundle/FrameworkBundle/Templating/Helper/TranslatorHelper.php @@ -15,8 +15,6 @@ use Symfony\Component\Translation\TranslatorInterface; /** - * TranslatorHelper. - * * @author Fabien Potencier */ class TranslatorHelper extends Helper @@ -24,8 +22,6 @@ class TranslatorHelper extends Helper protected $translator; /** - * Constructor. - * * @param TranslatorInterface $translator A TranslatorInterface instance */ public function __construct(TranslatorInterface $translator) diff --git a/src/Symfony/Bundle/FrameworkBundle/Templating/Loader/FilesystemLoader.php b/src/Symfony/Bundle/FrameworkBundle/Templating/Loader/FilesystemLoader.php index 4f6cffc103b8c..402778bd76857 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Templating/Loader/FilesystemLoader.php +++ b/src/Symfony/Bundle/FrameworkBundle/Templating/Loader/FilesystemLoader.php @@ -26,8 +26,6 @@ class FilesystemLoader implements LoaderInterface protected $locator; /** - * Constructor. - * * @param FileLocatorInterface $locator A FileLocatorInterface instance */ public function __construct(FileLocatorInterface $locator) diff --git a/src/Symfony/Bundle/FrameworkBundle/Templating/Loader/TemplateLocator.php b/src/Symfony/Bundle/FrameworkBundle/Templating/Loader/TemplateLocator.php index 369e95a1f08aa..c74322d6814fd 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Templating/Loader/TemplateLocator.php +++ b/src/Symfony/Bundle/FrameworkBundle/Templating/Loader/TemplateLocator.php @@ -27,8 +27,6 @@ class TemplateLocator implements FileLocatorInterface private $cacheHits = array(); /** - * Constructor. - * * @param FileLocatorInterface $locator A FileLocatorInterface instance * @param string $cacheDir The cache path */ diff --git a/src/Symfony/Bundle/FrameworkBundle/Templating/PhpEngine.php b/src/Symfony/Bundle/FrameworkBundle/Templating/PhpEngine.php index 41382f769c65f..0725e010e979c 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Templating/PhpEngine.php +++ b/src/Symfony/Bundle/FrameworkBundle/Templating/PhpEngine.php @@ -27,8 +27,6 @@ class PhpEngine extends BasePhpEngine implements EngineInterface protected $container; /** - * Constructor. - * * @param TemplateNameParserInterface $parser A TemplateNameParserInterface instance * @param ContainerInterface $container The DI container * @param LoaderInterface $loader A loader instance diff --git a/src/Symfony/Bundle/FrameworkBundle/Templating/TemplateNameParser.php b/src/Symfony/Bundle/FrameworkBundle/Templating/TemplateNameParser.php index c50541fa27ee3..3ae8fccd202c9 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Templating/TemplateNameParser.php +++ b/src/Symfony/Bundle/FrameworkBundle/Templating/TemplateNameParser.php @@ -28,8 +28,6 @@ class TemplateNameParser extends BaseTemplateNameParser protected $cache = array(); /** - * Constructor. - * * @param KernelInterface $kernel A KernelInterface instance */ public function __construct(KernelInterface $kernel) diff --git a/src/Symfony/Bundle/FrameworkBundle/Templating/TimedPhpEngine.php b/src/Symfony/Bundle/FrameworkBundle/Templating/TimedPhpEngine.php index 3295cc73a726f..ccfbcf7408f4f 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Templating/TimedPhpEngine.php +++ b/src/Symfony/Bundle/FrameworkBundle/Templating/TimedPhpEngine.php @@ -26,8 +26,6 @@ class TimedPhpEngine extends PhpEngine protected $stopwatch; /** - * Constructor. - * * @param TemplateNameParserInterface $parser A TemplateNameParserInterface instance * @param ContainerInterface $container A ContainerInterface instance * @param LoaderInterface $loader A LoaderInterface instance diff --git a/src/Symfony/Bundle/FrameworkBundle/Translation/Translator.php b/src/Symfony/Bundle/FrameworkBundle/Translation/Translator.php index 9fdfb645d372a..3b68fda38cb93 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Translation/Translator.php +++ b/src/Symfony/Bundle/FrameworkBundle/Translation/Translator.php @@ -46,8 +46,6 @@ class Translator extends BaseTranslator implements WarmableInterface private $resources = array(); /** - * Constructor. - * * Available options: * * * cache_dir: The cache directory (or null to disable caching) diff --git a/src/Symfony/Bundle/FrameworkBundle/Validator/ConstraintValidatorFactory.php b/src/Symfony/Bundle/FrameworkBundle/Validator/ConstraintValidatorFactory.php index 4e36678212baa..ce4efcbb1bea7 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Validator/ConstraintValidatorFactory.php +++ b/src/Symfony/Bundle/FrameworkBundle/Validator/ConstraintValidatorFactory.php @@ -44,8 +44,6 @@ class ConstraintValidatorFactory implements ConstraintValidatorFactoryInterface protected $validators; /** - * Constructor. - * * @param ContainerInterface $container The service container * @param array $validators An array of validators */ diff --git a/src/Symfony/Bundle/SecurityBundle/DataCollector/SecurityDataCollector.php b/src/Symfony/Bundle/SecurityBundle/DataCollector/SecurityDataCollector.php index c9f2599526a70..285d5993a27c5 100644 --- a/src/Symfony/Bundle/SecurityBundle/DataCollector/SecurityDataCollector.php +++ b/src/Symfony/Bundle/SecurityBundle/DataCollector/SecurityDataCollector.php @@ -19,8 +19,6 @@ use Symfony\Component\Security\Core\Role\RoleInterface; /** - * SecurityDataCollector. - * * @author Fabien Potencier */ class SecurityDataCollector extends DataCollector @@ -29,8 +27,6 @@ class SecurityDataCollector extends DataCollector private $roleHierarchy; /** - * Constructor. - * * @param TokenStorageInterface|null $tokenStorage * @param RoleHierarchyInterface|null $roleHierarchy */ diff --git a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/MainConfiguration.php b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/MainConfiguration.php index df6380224cd20..8b6d2e7d2970b 100644 --- a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/MainConfiguration.php +++ b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/MainConfiguration.php @@ -37,8 +37,6 @@ class MainConfiguration implements ConfigurationInterface private $userProviderFactories; /** - * Constructor. - * * @param array $factories * @param array $userProviderFactories */ diff --git a/src/Symfony/Bundle/SecurityBundle/Templating/Helper/LogoutUrlHelper.php b/src/Symfony/Bundle/SecurityBundle/Templating/Helper/LogoutUrlHelper.php index 6819c37609875..b998d4d80a056 100644 --- a/src/Symfony/Bundle/SecurityBundle/Templating/Helper/LogoutUrlHelper.php +++ b/src/Symfony/Bundle/SecurityBundle/Templating/Helper/LogoutUrlHelper.php @@ -27,8 +27,6 @@ class LogoutUrlHelper extends Helper private $generator; /** - * Constructor. - * * @param ContainerInterface|LogoutUrlGenerator $generator A ContainerInterface or LogoutUrlGenerator instance * @param UrlGeneratorInterface|null $router The router service * @param TokenStorageInterface|null $tokenStorage The token storage service diff --git a/src/Symfony/Bundle/TwigBundle/CacheWarmer/TemplateCacheCacheWarmer.php b/src/Symfony/Bundle/TwigBundle/CacheWarmer/TemplateCacheCacheWarmer.php index e5be1d5234d53..328c7318f5ef7 100644 --- a/src/Symfony/Bundle/TwigBundle/CacheWarmer/TemplateCacheCacheWarmer.php +++ b/src/Symfony/Bundle/TwigBundle/CacheWarmer/TemplateCacheCacheWarmer.php @@ -30,8 +30,6 @@ class TemplateCacheCacheWarmer implements CacheWarmerInterface protected $finder; /** - * Constructor. - * * @param ContainerInterface $container The dependency injection container * @param TemplateFinderInterface|null $finder The template paths cache warmer */ diff --git a/src/Symfony/Bundle/TwigBundle/Loader/FilesystemLoader.php b/src/Symfony/Bundle/TwigBundle/Loader/FilesystemLoader.php index b92764d371bf4..a1e5bbc609233 100644 --- a/src/Symfony/Bundle/TwigBundle/Loader/FilesystemLoader.php +++ b/src/Symfony/Bundle/TwigBundle/Loader/FilesystemLoader.php @@ -29,8 +29,6 @@ class FilesystemLoader extends BaseFilesystemLoader protected $parser; /** - * Constructor. - * * @param FileLocatorInterface $locator A FileLocatorInterface instance * @param TemplateNameParserInterface $parser A TemplateNameParserInterface instance */ diff --git a/src/Symfony/Bundle/WebProfilerBundle/Controller/ProfilerController.php b/src/Symfony/Bundle/WebProfilerBundle/Controller/ProfilerController.php index 355edde5c866b..ef6624195e17a 100644 --- a/src/Symfony/Bundle/WebProfilerBundle/Controller/ProfilerController.php +++ b/src/Symfony/Bundle/WebProfilerBundle/Controller/ProfilerController.php @@ -22,8 +22,6 @@ use Twig\Environment; /** - * ProfilerController. - * * @author Fabien Potencier */ class ProfilerController @@ -36,8 +34,6 @@ class ProfilerController private $toolbarPosition; /** - * Constructor. - * * @param UrlGeneratorInterface $generator The URL Generator * @param Profiler $profiler The profiler * @param Environment $twig The twig environment diff --git a/src/Symfony/Component/BrowserKit/Client.php b/src/Symfony/Component/BrowserKit/Client.php index b5b2dab50d4cc..ecd6d65ee688b 100644 --- a/src/Symfony/Component/BrowserKit/Client.php +++ b/src/Symfony/Component/BrowserKit/Client.php @@ -45,8 +45,6 @@ abstract class Client private $isMainRequest = true; /** - * Constructor. - * * @param array $server The server parameters (equivalent of $_SERVER) * @param History $history A History instance to store the browser history * @param CookieJar $cookieJar A CookieJar instance to store the cookies diff --git a/src/Symfony/Component/BrowserKit/Request.php b/src/Symfony/Component/BrowserKit/Request.php index 2e2819b4ca465..d78868e539022 100644 --- a/src/Symfony/Component/BrowserKit/Request.php +++ b/src/Symfony/Component/BrowserKit/Request.php @@ -12,8 +12,6 @@ namespace Symfony\Component\BrowserKit; /** - * Request object. - * * @author Fabien Potencier */ class Request @@ -27,8 +25,6 @@ class Request protected $content; /** - * Constructor. - * * @param string $uri The request URI * @param string $method The HTTP method request * @param array $parameters The request parameters diff --git a/src/Symfony/Component/BrowserKit/Response.php b/src/Symfony/Component/BrowserKit/Response.php index 984442fbe3691..ba4e416bf8048 100644 --- a/src/Symfony/Component/BrowserKit/Response.php +++ b/src/Symfony/Component/BrowserKit/Response.php @@ -12,8 +12,6 @@ namespace Symfony\Component\BrowserKit; /** - * Response object. - * * @author Fabien Potencier */ class Response @@ -23,8 +21,6 @@ class Response protected $headers; /** - * Constructor. - * * The headers array is a set of key/value pairs. If a header is present multiple times * then the value is an array of all the values. * diff --git a/src/Symfony/Component/ClassLoader/ApcClassLoader.php b/src/Symfony/Component/ClassLoader/ApcClassLoader.php index 46ee4a8566b1f..3a1c4ee45c554 100644 --- a/src/Symfony/Component/ClassLoader/ApcClassLoader.php +++ b/src/Symfony/Component/ClassLoader/ApcClassLoader.php @@ -57,8 +57,6 @@ class ApcClassLoader protected $decorated; /** - * Constructor. - * * @param string $prefix The APC namespace prefix to use * @param object $decorated A class loader object that implements the findFile() method * diff --git a/src/Symfony/Component/ClassLoader/ApcUniversalClassLoader.php b/src/Symfony/Component/ClassLoader/ApcUniversalClassLoader.php index 0ab45678f9af1..fa897b004cc5b 100644 --- a/src/Symfony/Component/ClassLoader/ApcUniversalClassLoader.php +++ b/src/Symfony/Component/ClassLoader/ApcUniversalClassLoader.php @@ -68,8 +68,6 @@ class ApcUniversalClassLoader extends UniversalClassLoader private $prefix; /** - * Constructor. - * * @param string $prefix A prefix to create a namespace in APC * * @throws \RuntimeException diff --git a/src/Symfony/Component/ClassLoader/DebugClassLoader.php b/src/Symfony/Component/ClassLoader/DebugClassLoader.php index 783cf676f7060..ec046927364f2 100644 --- a/src/Symfony/Component/ClassLoader/DebugClassLoader.php +++ b/src/Symfony/Component/ClassLoader/DebugClassLoader.php @@ -31,8 +31,6 @@ class DebugClassLoader private $classFinder; /** - * Constructor. - * * @param object $classFinder */ public function __construct($classFinder) diff --git a/src/Symfony/Component/ClassLoader/MapClassLoader.php b/src/Symfony/Component/ClassLoader/MapClassLoader.php index 1d8bcc2a026b2..289f7efb53456 100644 --- a/src/Symfony/Component/ClassLoader/MapClassLoader.php +++ b/src/Symfony/Component/ClassLoader/MapClassLoader.php @@ -21,8 +21,6 @@ class MapClassLoader private $map = array(); /** - * Constructor. - * * @param array $map A map where keys are classes and values the absolute file path */ public function __construct(array $map) diff --git a/src/Symfony/Component/ClassLoader/WinCacheClassLoader.php b/src/Symfony/Component/ClassLoader/WinCacheClassLoader.php index 3e077450f1ebc..d5381b446b73b 100644 --- a/src/Symfony/Component/ClassLoader/WinCacheClassLoader.php +++ b/src/Symfony/Component/ClassLoader/WinCacheClassLoader.php @@ -58,8 +58,6 @@ class WinCacheClassLoader protected $decorated; /** - * Constructor. - * * @param string $prefix The WinCache namespace prefix to use * @param object $decorated A class loader object that implements the findFile() method * diff --git a/src/Symfony/Component/ClassLoader/XcacheClassLoader.php b/src/Symfony/Component/ClassLoader/XcacheClassLoader.php index aa4dc9d052b9f..1dcfbaea6ec35 100644 --- a/src/Symfony/Component/ClassLoader/XcacheClassLoader.php +++ b/src/Symfony/Component/ClassLoader/XcacheClassLoader.php @@ -58,8 +58,6 @@ class XcacheClassLoader private $decorated; /** - * Constructor. - * * @param string $prefix The XCache namespace prefix to use * @param object $decorated A class loader object that implements the findFile() method * diff --git a/src/Symfony/Component/Config/Definition/BaseNode.php b/src/Symfony/Component/Config/Definition/BaseNode.php index dbf36335b69e3..71c18cae3421e 100644 --- a/src/Symfony/Component/Config/Definition/BaseNode.php +++ b/src/Symfony/Component/Config/Definition/BaseNode.php @@ -33,8 +33,6 @@ abstract class BaseNode implements NodeInterface protected $attributes = array(); /** - * Constructor. - * * @param string $name The name of the node * @param NodeInterface $parent The parent of this node * diff --git a/src/Symfony/Component/Config/Definition/Builder/ExprBuilder.php b/src/Symfony/Component/Config/Definition/Builder/ExprBuilder.php index 10112a813df7a..3b55958309164 100644 --- a/src/Symfony/Component/Config/Definition/Builder/ExprBuilder.php +++ b/src/Symfony/Component/Config/Definition/Builder/ExprBuilder.php @@ -26,8 +26,6 @@ class ExprBuilder public $thenPart; /** - * Constructor. - * * @param NodeDefinition $node The related node */ public function __construct(NodeDefinition $node) diff --git a/src/Symfony/Component/Config/Definition/Builder/MergeBuilder.php b/src/Symfony/Component/Config/Definition/Builder/MergeBuilder.php index 1d24953df5742..09327a6db6768 100644 --- a/src/Symfony/Component/Config/Definition/Builder/MergeBuilder.php +++ b/src/Symfony/Component/Config/Definition/Builder/MergeBuilder.php @@ -23,8 +23,6 @@ class MergeBuilder public $allowOverwrite = true; /** - * Constructor. - * * @param NodeDefinition $node The related node */ public function __construct(NodeDefinition $node) diff --git a/src/Symfony/Component/Config/Definition/Builder/NodeBuilder.php b/src/Symfony/Component/Config/Definition/Builder/NodeBuilder.php index e780777a1e837..d795f8ff84865 100644 --- a/src/Symfony/Component/Config/Definition/Builder/NodeBuilder.php +++ b/src/Symfony/Component/Config/Definition/Builder/NodeBuilder.php @@ -21,9 +21,6 @@ class NodeBuilder implements NodeParentInterface protected $parent; protected $nodeMapping; - /** - * Constructor. - */ public function __construct() { $this->nodeMapping = array( diff --git a/src/Symfony/Component/Config/Definition/Builder/NodeDefinition.php b/src/Symfony/Component/Config/Definition/Builder/NodeDefinition.php index 1b712a3150bc3..9dcba444ac479 100644 --- a/src/Symfony/Component/Config/Definition/Builder/NodeDefinition.php +++ b/src/Symfony/Component/Config/Definition/Builder/NodeDefinition.php @@ -40,8 +40,6 @@ abstract class NodeDefinition implements NodeParentInterface protected $attributes = array(); /** - * Constructor. - * * @param string $name The name of the node * @param NodeParentInterface|null $parent The parent */ diff --git a/src/Symfony/Component/Config/Definition/Builder/NormalizationBuilder.php b/src/Symfony/Component/Config/Definition/Builder/NormalizationBuilder.php index ae642a2d49a2c..8ff1d8a045103 100644 --- a/src/Symfony/Component/Config/Definition/Builder/NormalizationBuilder.php +++ b/src/Symfony/Component/Config/Definition/Builder/NormalizationBuilder.php @@ -23,8 +23,6 @@ class NormalizationBuilder public $remappings = array(); /** - * Constructor. - * * @param NodeDefinition $node The related node */ public function __construct(NodeDefinition $node) diff --git a/src/Symfony/Component/Config/Definition/Builder/ValidationBuilder.php b/src/Symfony/Component/Config/Definition/Builder/ValidationBuilder.php index 12aa59a4fd61c..0acd7343910e3 100644 --- a/src/Symfony/Component/Config/Definition/Builder/ValidationBuilder.php +++ b/src/Symfony/Component/Config/Definition/Builder/ValidationBuilder.php @@ -22,8 +22,6 @@ class ValidationBuilder public $rules = array(); /** - * Constructor. - * * @param NodeDefinition $node The related node */ public function __construct(NodeDefinition $node) diff --git a/src/Symfony/Component/Config/FileLocator.php b/src/Symfony/Component/Config/FileLocator.php index 4816724c8190e..70d9857de3811 100644 --- a/src/Symfony/Component/Config/FileLocator.php +++ b/src/Symfony/Component/Config/FileLocator.php @@ -21,8 +21,6 @@ class FileLocator implements FileLocatorInterface protected $paths; /** - * Constructor. - * * @param string|array $paths A path or an array of paths where to look for resources */ public function __construct($paths = array()) diff --git a/src/Symfony/Component/Config/Loader/DelegatingLoader.php b/src/Symfony/Component/Config/Loader/DelegatingLoader.php index 3097878bf0bf2..24a00be201c01 100644 --- a/src/Symfony/Component/Config/Loader/DelegatingLoader.php +++ b/src/Symfony/Component/Config/Loader/DelegatingLoader.php @@ -24,8 +24,6 @@ class DelegatingLoader extends Loader { /** - * Constructor. - * * @param LoaderResolverInterface $resolver A LoaderResolverInterface instance */ public function __construct(LoaderResolverInterface $resolver) diff --git a/src/Symfony/Component/Config/Loader/FileLoader.php b/src/Symfony/Component/Config/Loader/FileLoader.php index 2b19b52584bdd..fd6947c75a057 100644 --- a/src/Symfony/Component/Config/Loader/FileLoader.php +++ b/src/Symfony/Component/Config/Loader/FileLoader.php @@ -35,8 +35,6 @@ abstract class FileLoader extends Loader private $currentDir; /** - * Constructor. - * * @param FileLocatorInterface $locator A FileLocatorInterface instance */ public function __construct(FileLocatorInterface $locator) diff --git a/src/Symfony/Component/Config/Loader/LoaderResolver.php b/src/Symfony/Component/Config/Loader/LoaderResolver.php index dc6846df8d617..288feb865bd1b 100644 --- a/src/Symfony/Component/Config/Loader/LoaderResolver.php +++ b/src/Symfony/Component/Config/Loader/LoaderResolver.php @@ -27,8 +27,6 @@ class LoaderResolver implements LoaderResolverInterface private $loaders = array(); /** - * Constructor. - * * @param LoaderInterface[] $loaders An array of loaders */ public function __construct(array $loaders = array()) diff --git a/src/Symfony/Component/Config/Resource/DirectoryResource.php b/src/Symfony/Component/Config/Resource/DirectoryResource.php index bde84b1b5bd5c..8ddb4989353af 100644 --- a/src/Symfony/Component/Config/Resource/DirectoryResource.php +++ b/src/Symfony/Component/Config/Resource/DirectoryResource.php @@ -22,8 +22,6 @@ class DirectoryResource implements ResourceInterface, \Serializable private $pattern; /** - * Constructor. - * * @param string $resource The file path to the resource * @param string|null $pattern A pattern to restrict monitored files */ diff --git a/src/Symfony/Component/Config/Resource/FileResource.php b/src/Symfony/Component/Config/Resource/FileResource.php index 0723ddf0e1f20..410ad1804f575 100644 --- a/src/Symfony/Component/Config/Resource/FileResource.php +++ b/src/Symfony/Component/Config/Resource/FileResource.php @@ -26,8 +26,6 @@ class FileResource implements ResourceInterface, \Serializable private $resource; /** - * Constructor. - * * @param string $resource The file path to the resource */ public function __construct($resource) diff --git a/src/Symfony/Component/Console/Application.php b/src/Symfony/Component/Console/Application.php index 873b09e808729..82299ffba15a6 100644 --- a/src/Symfony/Component/Console/Application.php +++ b/src/Symfony/Component/Console/Application.php @@ -75,8 +75,6 @@ class Application private $initialized; /** - * Constructor. - * * @param string $name The name of the application * @param string $version The version of the application */ diff --git a/src/Symfony/Component/Console/Command/Command.php b/src/Symfony/Component/Console/Command/Command.php index 6b91e548e64e1..ceddc75da765d 100644 --- a/src/Symfony/Component/Console/Command/Command.php +++ b/src/Symfony/Component/Console/Command/Command.php @@ -45,8 +45,6 @@ class Command private $helperSet; /** - * Constructor. - * * @param string|null $name The name of the command; passing null means it must be set in configure() * * @throws \LogicException When the command name is empty diff --git a/src/Symfony/Component/Console/Descriptor/ApplicationDescription.php b/src/Symfony/Component/Console/Descriptor/ApplicationDescription.php index 0e871931d81d2..90018a14f37b9 100644 --- a/src/Symfony/Component/Console/Descriptor/ApplicationDescription.php +++ b/src/Symfony/Component/Console/Descriptor/ApplicationDescription.php @@ -49,8 +49,6 @@ class ApplicationDescription private $aliases; /** - * Constructor. - * * @param Application $application * @param string|null $namespace */ diff --git a/src/Symfony/Component/Console/Formatter/OutputFormatterStyleStack.php b/src/Symfony/Component/Console/Formatter/OutputFormatterStyleStack.php index e335b0ab64bc0..c21a569622400 100644 --- a/src/Symfony/Component/Console/Formatter/OutputFormatterStyleStack.php +++ b/src/Symfony/Component/Console/Formatter/OutputFormatterStyleStack.php @@ -27,8 +27,6 @@ class OutputFormatterStyleStack private $emptyStyle; /** - * Constructor. - * * @param OutputFormatterStyleInterface|null $emptyStyle */ public function __construct(OutputFormatterStyleInterface $emptyStyle = null) diff --git a/src/Symfony/Component/Console/Helper/DescriptorHelper.php b/src/Symfony/Component/Console/Helper/DescriptorHelper.php index 6090bbfd006b5..17fffe509a942 100644 --- a/src/Symfony/Component/Console/Helper/DescriptorHelper.php +++ b/src/Symfony/Component/Console/Helper/DescriptorHelper.php @@ -30,9 +30,6 @@ class DescriptorHelper extends Helper */ private $descriptors = array(); - /** - * Constructor. - */ public function __construct() { $this diff --git a/src/Symfony/Component/Console/Helper/HelperSet.php b/src/Symfony/Component/Console/Helper/HelperSet.php index fb04341378181..3bf15525a9c61 100644 --- a/src/Symfony/Component/Console/Helper/HelperSet.php +++ b/src/Symfony/Component/Console/Helper/HelperSet.php @@ -27,8 +27,6 @@ class HelperSet implements \IteratorAggregate private $command; /** - * Constructor. - * * @param Helper[] $helpers An array of helper */ public function __construct(array $helpers = array()) diff --git a/src/Symfony/Component/Console/Helper/ProgressBar.php b/src/Symfony/Component/Console/Helper/ProgressBar.php index 62c38528f960e..c6aa1a920bd0f 100644 --- a/src/Symfony/Component/Console/Helper/ProgressBar.php +++ b/src/Symfony/Component/Console/Helper/ProgressBar.php @@ -49,8 +49,6 @@ class ProgressBar private static $formats; /** - * Constructor. - * * @param OutputInterface $output An OutputInterface instance * @param int $max Maximum steps (0 if unknown) */ diff --git a/src/Symfony/Component/Console/Input/ArgvInput.php b/src/Symfony/Component/Console/Input/ArgvInput.php index 119be49170853..a8e22fdaefe4e 100644 --- a/src/Symfony/Component/Console/Input/ArgvInput.php +++ b/src/Symfony/Component/Console/Input/ArgvInput.php @@ -42,8 +42,6 @@ class ArgvInput extends Input private $parsed; /** - * Constructor. - * * @param array|null $argv An array of parameters from the CLI (in the argv format) * @param InputDefinition|null $definition A InputDefinition instance */ diff --git a/src/Symfony/Component/Console/Input/ArrayInput.php b/src/Symfony/Component/Console/Input/ArrayInput.php index e9d4f8e842a9f..31ce14a3ec4e7 100644 --- a/src/Symfony/Component/Console/Input/ArrayInput.php +++ b/src/Symfony/Component/Console/Input/ArrayInput.php @@ -25,8 +25,6 @@ class ArrayInput extends Input private $parameters; /** - * Constructor. - * * @param array $parameters An array of parameters * @param InputDefinition|null $definition A InputDefinition instance */ diff --git a/src/Symfony/Component/Console/Input/Input.php b/src/Symfony/Component/Console/Input/Input.php index 2251b16cb95fa..c9073b9e2438d 100644 --- a/src/Symfony/Component/Console/Input/Input.php +++ b/src/Symfony/Component/Console/Input/Input.php @@ -33,8 +33,6 @@ abstract class Input implements InputInterface protected $interactive = true; /** - * Constructor. - * * @param InputDefinition|null $definition A InputDefinition instance */ public function __construct(InputDefinition $definition = null) diff --git a/src/Symfony/Component/Console/Input/InputArgument.php b/src/Symfony/Component/Console/Input/InputArgument.php index 69edecbc26660..29b80010cf8de 100644 --- a/src/Symfony/Component/Console/Input/InputArgument.php +++ b/src/Symfony/Component/Console/Input/InputArgument.php @@ -28,8 +28,6 @@ class InputArgument private $description; /** - * Constructor. - * * @param string $name The argument name * @param int $mode The argument mode: self::REQUIRED or self::OPTIONAL * @param string $description A description text diff --git a/src/Symfony/Component/Console/Input/InputDefinition.php b/src/Symfony/Component/Console/Input/InputDefinition.php index f7eafbd84f282..2fb5e492ebbe0 100644 --- a/src/Symfony/Component/Console/Input/InputDefinition.php +++ b/src/Symfony/Component/Console/Input/InputDefinition.php @@ -37,8 +37,6 @@ class InputDefinition private $shortcuts; /** - * Constructor. - * * @param array $definition An array of InputArgument and InputOption instance */ public function __construct(array $definition = array()) diff --git a/src/Symfony/Component/Console/Input/InputOption.php b/src/Symfony/Component/Console/Input/InputOption.php index 26773ca599a39..6f7d68a9bad13 100644 --- a/src/Symfony/Component/Console/Input/InputOption.php +++ b/src/Symfony/Component/Console/Input/InputOption.php @@ -30,8 +30,6 @@ class InputOption private $description; /** - * Constructor. - * * @param string $name The option name * @param string|array $shortcut The shortcuts, can be null, a string of shortcuts delimited by | or an array of shortcuts * @param int $mode The option mode: One of the VALUE_* constants diff --git a/src/Symfony/Component/Console/Input/StringInput.php b/src/Symfony/Component/Console/Input/StringInput.php index c518d5c910b9a..4e4c4a28b6095 100644 --- a/src/Symfony/Component/Console/Input/StringInput.php +++ b/src/Symfony/Component/Console/Input/StringInput.php @@ -26,8 +26,6 @@ class StringInput extends ArgvInput const REGEX_QUOTED_STRING = '(?:"([^"\\\\]*(?:\\\\.[^"\\\\]*)*)"|\'([^\'\\\\]*(?:\\\\.[^\'\\\\]*)*)\')'; /** - * Constructor. - * * @param string $input An array of parameters from the CLI (in the argv format) * @param InputDefinition $definition A InputDefinition instance * diff --git a/src/Symfony/Component/Console/Output/ConsoleOutput.php b/src/Symfony/Component/Console/Output/ConsoleOutput.php index f666c793e2265..80bea654da6f0 100644 --- a/src/Symfony/Component/Console/Output/ConsoleOutput.php +++ b/src/Symfony/Component/Console/Output/ConsoleOutput.php @@ -34,8 +34,6 @@ class ConsoleOutput extends StreamOutput implements ConsoleOutputInterface private $stderr; /** - * Constructor. - * * @param int $verbosity The verbosity level (one of the VERBOSITY constants in OutputInterface) * @param bool|null $decorated Whether to decorate messages (null for auto-guessing) * @param OutputFormatterInterface|null $formatter Output formatter instance (null to use default OutputFormatter) diff --git a/src/Symfony/Component/Console/Output/Output.php b/src/Symfony/Component/Console/Output/Output.php index 32bfc8cc3b58f..e7e165e5db7a3 100644 --- a/src/Symfony/Component/Console/Output/Output.php +++ b/src/Symfony/Component/Console/Output/Output.php @@ -33,8 +33,6 @@ abstract class Output implements OutputInterface private $formatter; /** - * Constructor. - * * @param int $verbosity The verbosity level (one of the VERBOSITY constants in OutputInterface) * @param bool $decorated Whether to decorate messages * @param OutputFormatterInterface|null $formatter Output formatter instance (null to use default OutputFormatter) diff --git a/src/Symfony/Component/Console/Output/StreamOutput.php b/src/Symfony/Component/Console/Output/StreamOutput.php index a043459440f2f..e547c3a6c0b9f 100644 --- a/src/Symfony/Component/Console/Output/StreamOutput.php +++ b/src/Symfony/Component/Console/Output/StreamOutput.php @@ -31,8 +31,6 @@ class StreamOutput extends Output private $stream; /** - * Constructor. - * * @param resource $stream A stream resource * @param int $verbosity The verbosity level (one of the VERBOSITY constants in OutputInterface) * @param bool|null $decorated Whether to decorate messages (null for auto-guessing) diff --git a/src/Symfony/Component/Console/Question/ChoiceQuestion.php b/src/Symfony/Component/Console/Question/ChoiceQuestion.php index be2504b6dde6d..7417f67968284 100644 --- a/src/Symfony/Component/Console/Question/ChoiceQuestion.php +++ b/src/Symfony/Component/Console/Question/ChoiceQuestion.php @@ -24,8 +24,6 @@ class ChoiceQuestion extends Question private $errorMessage = 'Value "%s" is invalid'; /** - * Constructor. - * * @param string $question The question to ask to the user * @param array $choices The list of available choices * @param mixed $default The default answer to return diff --git a/src/Symfony/Component/Console/Question/ConfirmationQuestion.php b/src/Symfony/Component/Console/Question/ConfirmationQuestion.php index 29d98879f0c56..40f54b4e9b8d8 100644 --- a/src/Symfony/Component/Console/Question/ConfirmationQuestion.php +++ b/src/Symfony/Component/Console/Question/ConfirmationQuestion.php @@ -21,8 +21,6 @@ class ConfirmationQuestion extends Question private $trueAnswerRegex; /** - * Constructor. - * * @param string $question The question to ask to the user * @param bool $default The default answer to return, true or false * @param string $trueAnswerRegex A regex to match the "yes" answer diff --git a/src/Symfony/Component/Console/Question/Question.php b/src/Symfony/Component/Console/Question/Question.php index 373501d691f8c..34b476928087d 100644 --- a/src/Symfony/Component/Console/Question/Question.php +++ b/src/Symfony/Component/Console/Question/Question.php @@ -28,8 +28,6 @@ class Question private $normalizer; /** - * Constructor. - * * @param string $question The question to ask to the user * @param mixed $default The default answer to return if the user enters nothing */ diff --git a/src/Symfony/Component/Console/Shell.php b/src/Symfony/Component/Console/Shell.php index a140a5e4fee83..c4967236d6da2 100644 --- a/src/Symfony/Component/Console/Shell.php +++ b/src/Symfony/Component/Console/Shell.php @@ -34,8 +34,6 @@ class Shell private $processIsolation = false; /** - * Constructor. - * * If there is no readline support for the current PHP executable * a \RuntimeException exception is thrown. * diff --git a/src/Symfony/Component/Console/Tester/ApplicationTester.php b/src/Symfony/Component/Console/Tester/ApplicationTester.php index 90efbab2182a8..a8f8dd9702893 100644 --- a/src/Symfony/Component/Console/Tester/ApplicationTester.php +++ b/src/Symfony/Component/Console/Tester/ApplicationTester.php @@ -35,8 +35,6 @@ class ApplicationTester private $statusCode; /** - * Constructor. - * * @param Application $application An Application instance to test */ public function __construct(Application $application) diff --git a/src/Symfony/Component/Console/Tester/CommandTester.php b/src/Symfony/Component/Console/Tester/CommandTester.php index 609f46a654da9..3619281cbb273 100644 --- a/src/Symfony/Component/Console/Tester/CommandTester.php +++ b/src/Symfony/Component/Console/Tester/CommandTester.php @@ -30,8 +30,6 @@ class CommandTester private $statusCode; /** - * Constructor. - * * @param Command $command A Command instance to test */ public function __construct(Command $command) diff --git a/src/Symfony/Component/CssSelector/Node/Specificity.php b/src/Symfony/Component/CssSelector/Node/Specificity.php index 6ee406d1328d1..6adadfb6ff0d0 100644 --- a/src/Symfony/Component/CssSelector/Node/Specificity.php +++ b/src/Symfony/Component/CssSelector/Node/Specificity.php @@ -43,8 +43,6 @@ class Specificity private $c; /** - * Constructor. - * * @param int $a * @param int $b * @param int $c diff --git a/src/Symfony/Component/CssSelector/Parser/Parser.php b/src/Symfony/Component/CssSelector/Parser/Parser.php index 8b86bce3b77d6..722a32f22f371 100644 --- a/src/Symfony/Component/CssSelector/Parser/Parser.php +++ b/src/Symfony/Component/CssSelector/Parser/Parser.php @@ -31,8 +31,6 @@ class Parser implements ParserInterface private $tokenizer; /** - * Constructor. - * * @param null|Tokenizer $tokenizer */ public function __construct(Tokenizer $tokenizer = null) diff --git a/src/Symfony/Component/CssSelector/Parser/Tokenizer/Tokenizer.php b/src/Symfony/Component/CssSelector/Parser/Tokenizer/Tokenizer.php index 79fa7b77d06fa..d549f9338abc7 100644 --- a/src/Symfony/Component/CssSelector/Parser/Tokenizer/Tokenizer.php +++ b/src/Symfony/Component/CssSelector/Parser/Tokenizer/Tokenizer.php @@ -31,9 +31,6 @@ class Tokenizer */ private $handlers; - /** - * Constructor. - */ public function __construct() { $patterns = new TokenizerPatterns(); diff --git a/src/Symfony/Component/CssSelector/Parser/Tokenizer/TokenizerPatterns.php b/src/Symfony/Component/CssSelector/Parser/Tokenizer/TokenizerPatterns.php index 326f0208219a6..2d0f26ac84f54 100644 --- a/src/Symfony/Component/CssSelector/Parser/Tokenizer/TokenizerPatterns.php +++ b/src/Symfony/Component/CssSelector/Parser/Tokenizer/TokenizerPatterns.php @@ -81,9 +81,6 @@ class TokenizerPatterns */ private $quotedStringPattern; - /** - * Constructor. - */ public function __construct() { $this->unicodeEscapePattern = '\\\\([0-9a-f]{1,6})(?:\r\n|[ \n\r\t\f])?'; diff --git a/src/Symfony/Component/CssSelector/XPath/Extension/HtmlExtension.php b/src/Symfony/Component/CssSelector/XPath/Extension/HtmlExtension.php index 0da74d47273fb..1ed05bd6b89d9 100644 --- a/src/Symfony/Component/CssSelector/XPath/Extension/HtmlExtension.php +++ b/src/Symfony/Component/CssSelector/XPath/Extension/HtmlExtension.php @@ -27,8 +27,6 @@ class HtmlExtension extends AbstractExtension { /** - * Constructor. - * * @param Translator $translator */ public function __construct(Translator $translator) diff --git a/src/Symfony/Component/CssSelector/XPath/Extension/NodeExtension.php b/src/Symfony/Component/CssSelector/XPath/Extension/NodeExtension.php index c47130aa17c1a..49c77823cf598 100644 --- a/src/Symfony/Component/CssSelector/XPath/Extension/NodeExtension.php +++ b/src/Symfony/Component/CssSelector/XPath/Extension/NodeExtension.php @@ -35,8 +35,6 @@ class NodeExtension extends AbstractExtension private $flags; /** - * Constructor. - * * @param int $flags */ public function __construct($flags = 0) diff --git a/src/Symfony/Component/Debug/DebugClassLoader.php b/src/Symfony/Component/Debug/DebugClassLoader.php index 2094a85c4cd6a..160e945ccbbe0 100644 --- a/src/Symfony/Component/Debug/DebugClassLoader.php +++ b/src/Symfony/Component/Debug/DebugClassLoader.php @@ -34,8 +34,6 @@ class DebugClassLoader private static $darwinCache = array('/' => array('/', array())); /** - * Constructor. - * * @param callable|object $classLoader Passing an object is @deprecated since version 2.5 and support for it will be removed in 3.0 */ public function __construct($classLoader) diff --git a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php index 4d576df1bd6c8..e5ea4a546de8d 100644 --- a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php +++ b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php @@ -813,8 +813,6 @@ private function startClass($class, $baseClass, $namespace) $bagClass /*{$this->docStar} - * $class. - * * This class has been auto-generated * by the Symfony Dependency Injection Component. */ @@ -838,9 +836,6 @@ private function addConstructor() $code = <<docStar} - * Constructor. - */ public function __construct() {{$targetDirs} parent::__construct($arguments); @@ -875,9 +870,6 @@ private function addFrozenConstructor() $code = <<docStar} - * Constructor. - */ public function __construct() {{$targetDirs} EOF; diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services1-1.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services1-1.php index 0fede650233e5..c6616e0563795 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services1-1.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services1-1.php @@ -11,8 +11,6 @@ use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag; /** - * Container. - * * This class has been auto-generated * by the Symfony Dependency Injection Component. */ @@ -21,9 +19,6 @@ class Container extends AbstractContainer private $parameters; private $targetDirs = array(); - /** - * Constructor. - */ public function __construct() { parent::__construct(); diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services1.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services1.php index 5497a7587ab54..abe9bc0e32e9e 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services1.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services1.php @@ -9,8 +9,6 @@ use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag; /** - * ProjectServiceContainer. - * * This class has been auto-generated * by the Symfony Dependency Injection Component. */ @@ -19,9 +17,6 @@ class ProjectServiceContainer extends Container private $parameters; private $targetDirs = array(); - /** - * Constructor. - */ public function __construct() { parent::__construct(); diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services10.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services10.php index 923c437bb06a1..a674eae8b49d3 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services10.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services10.php @@ -9,8 +9,6 @@ use Symfony\Component\DependencyInjection\ParameterBag\FrozenParameterBag; /** - * ProjectServiceContainer. - * * This class has been auto-generated * by the Symfony Dependency Injection Component. */ @@ -19,9 +17,6 @@ class ProjectServiceContainer extends Container private $parameters; private $targetDirs = array(); - /** - * Constructor. - */ public function __construct() { $this->parameters = $this->getDefaultParameters(); diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services12.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services12.php index 2119719828d67..10e7f19d23f0e 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services12.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services12.php @@ -9,8 +9,6 @@ use Symfony\Component\DependencyInjection\ParameterBag\FrozenParameterBag; /** - * ProjectServiceContainer. - * * This class has been auto-generated * by the Symfony Dependency Injection Component. */ @@ -19,9 +17,6 @@ class ProjectServiceContainer extends Container private $parameters; private $targetDirs = array(); - /** - * Constructor. - */ public function __construct() { $dir = __DIR__; diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services13.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services13.php index eaf9c4bef0edc..1a01fc73f237a 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services13.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services13.php @@ -9,8 +9,6 @@ use Symfony\Component\DependencyInjection\ParameterBag\FrozenParameterBag; /** - * ProjectServiceContainer. - * * This class has been auto-generated * by the Symfony Dependency Injection Component. */ @@ -19,9 +17,6 @@ class ProjectServiceContainer extends Container private $parameters; private $targetDirs = array(); - /** - * Constructor. - */ public function __construct() { $this->services = diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services19.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services19.php index a3fde04b78a4b..b9aae84a006bc 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services19.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services19.php @@ -9,8 +9,6 @@ use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag; /** - * ProjectServiceContainer. - * * This class has been auto-generated * by the Symfony Dependency Injection Component. */ @@ -19,9 +17,6 @@ class ProjectServiceContainer extends Container private $parameters; private $targetDirs = array(); - /** - * Constructor. - */ public function __construct() { parent::__construct(); diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services20.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services20.php index ba9a8902e4d06..7acf32be00293 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services20.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services20.php @@ -9,8 +9,6 @@ use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag; /** - * ProjectServiceContainer. - * * This class has been auto-generated * by the Symfony Dependency Injection Component. */ @@ -19,9 +17,6 @@ class ProjectServiceContainer extends Container private $parameters; private $targetDirs = array(); - /** - * Constructor. - */ public function __construct() { parent::__construct(); diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services8.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services8.php index c2c52fe3351c7..d599751374a2e 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services8.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services8.php @@ -9,8 +9,6 @@ use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag; /** - * ProjectServiceContainer. - * * This class has been auto-generated * by the Symfony Dependency Injection Component. */ @@ -19,9 +17,6 @@ class ProjectServiceContainer extends Container private $parameters; private $targetDirs = array(); - /** - * Constructor. - */ public function __construct() { parent::__construct(new ParameterBag($this->getDefaultParameters())); diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9.php index 1d352601431a6..caefdc09e35d6 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9.php @@ -9,8 +9,6 @@ use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag; /** - * ProjectServiceContainer. - * * This class has been auto-generated * by the Symfony Dependency Injection Component. */ @@ -19,9 +17,6 @@ class ProjectServiceContainer extends Container private $parameters; private $targetDirs = array(); - /** - * Constructor. - */ public function __construct() { parent::__construct(new ParameterBag($this->getDefaultParameters())); diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_compiled.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_compiled.php index 22d447e303aa9..0f831b96abfe3 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_compiled.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_compiled.php @@ -9,8 +9,6 @@ use Symfony\Component\DependencyInjection\ParameterBag\FrozenParameterBag; /** - * ProjectServiceContainer. - * * This class has been auto-generated * by the Symfony Dependency Injection Component. */ @@ -19,9 +17,6 @@ class ProjectServiceContainer extends Container private $parameters; private $targetDirs = array(); - /** - * Constructor. - */ public function __construct() { $this->parameters = $this->getDefaultParameters(); diff --git a/src/Symfony/Component/DomCrawler/Crawler.php b/src/Symfony/Component/DomCrawler/Crawler.php index ed9b0b02398f5..782d5f1d9b1b3 100644 --- a/src/Symfony/Component/DomCrawler/Crawler.php +++ b/src/Symfony/Component/DomCrawler/Crawler.php @@ -41,8 +41,6 @@ class Crawler extends \SplObjectStorage private $baseHref; /** - * Constructor. - * * @param mixed $node A Node to use as the base for the crawling * @param string $currentUri The current URI * @param string $baseHref The base href value diff --git a/src/Symfony/Component/DomCrawler/Field/FormField.php b/src/Symfony/Component/DomCrawler/Field/FormField.php index a6b33ded2d2f3..496d45d05ac45 100644 --- a/src/Symfony/Component/DomCrawler/Field/FormField.php +++ b/src/Symfony/Component/DomCrawler/Field/FormField.php @@ -44,8 +44,6 @@ abstract class FormField protected $disabled; /** - * Constructor. - * * @param \DOMElement $node The node associated with this field */ public function __construct(\DOMElement $node) diff --git a/src/Symfony/Component/DomCrawler/Form.php b/src/Symfony/Component/DomCrawler/Form.php index bad1b34935d04..7f64f7576b36d 100644 --- a/src/Symfony/Component/DomCrawler/Form.php +++ b/src/Symfony/Component/DomCrawler/Form.php @@ -37,8 +37,6 @@ class Form extends Link implements \ArrayAccess private $baseHref; /** - * Constructor. - * * @param \DOMElement $node A \DOMElement instance * @param string $currentUri The URI of the page where the form is embedded * @param string $method The method to use for the link (if null, it defaults to the method defined by the form) diff --git a/src/Symfony/Component/DomCrawler/Link.php b/src/Symfony/Component/DomCrawler/Link.php index ede0991e6f36c..b68f246b0efd5 100644 --- a/src/Symfony/Component/DomCrawler/Link.php +++ b/src/Symfony/Component/DomCrawler/Link.php @@ -34,8 +34,6 @@ class Link protected $currentUri; /** - * Constructor. - * * @param \DOMElement $node A \DOMElement instance * @param string $currentUri The URI of the page where the link is embedded (or the base href) * @param string $method The method to use for the link (get by default) diff --git a/src/Symfony/Component/EventDispatcher/ContainerAwareEventDispatcher.php b/src/Symfony/Component/EventDispatcher/ContainerAwareEventDispatcher.php index dc2816f16906b..601754e460160 100644 --- a/src/Symfony/Component/EventDispatcher/ContainerAwareEventDispatcher.php +++ b/src/Symfony/Component/EventDispatcher/ContainerAwareEventDispatcher.php @@ -45,8 +45,6 @@ class ContainerAwareEventDispatcher extends EventDispatcher private $listeners = array(); /** - * Constructor. - * * @param ContainerInterface $container A ContainerInterface instance */ public function __construct(ContainerInterface $container) diff --git a/src/Symfony/Component/EventDispatcher/Debug/TraceableEventDispatcher.php b/src/Symfony/Component/EventDispatcher/Debug/TraceableEventDispatcher.php index 12e2b1c67b310..775b75a4f633e 100644 --- a/src/Symfony/Component/EventDispatcher/Debug/TraceableEventDispatcher.php +++ b/src/Symfony/Component/EventDispatcher/Debug/TraceableEventDispatcher.php @@ -34,8 +34,6 @@ class TraceableEventDispatcher implements TraceableEventDispatcherInterface private $wrappedListeners; /** - * Constructor. - * * @param EventDispatcherInterface $dispatcher An EventDispatcherInterface instance * @param Stopwatch $stopwatch A Stopwatch instance * @param LoggerInterface $logger A LoggerInterface instance diff --git a/src/Symfony/Component/EventDispatcher/DependencyInjection/RegisterListenersPass.php b/src/Symfony/Component/EventDispatcher/DependencyInjection/RegisterListenersPass.php index 326bfd184f497..c51942c2cd2d2 100644 --- a/src/Symfony/Component/EventDispatcher/DependencyInjection/RegisterListenersPass.php +++ b/src/Symfony/Component/EventDispatcher/DependencyInjection/RegisterListenersPass.php @@ -35,8 +35,6 @@ class RegisterListenersPass implements CompilerPassInterface protected $subscriberTag; /** - * Constructor. - * * @param string $dispatcherService Service name of the event dispatcher in processed container * @param string $listenerTag Tag name used for listener * @param string $subscriberTag Tag name used for subscribers diff --git a/src/Symfony/Component/ExpressionLanguage/Expression.php b/src/Symfony/Component/ExpressionLanguage/Expression.php index f5a3820309231..ac656cce033bf 100644 --- a/src/Symfony/Component/ExpressionLanguage/Expression.php +++ b/src/Symfony/Component/ExpressionLanguage/Expression.php @@ -21,8 +21,6 @@ class Expression protected $expression; /** - * Constructor. - * * @param string $expression An expression */ public function __construct($expression) diff --git a/src/Symfony/Component/ExpressionLanguage/ExpressionFunction.php b/src/Symfony/Component/ExpressionLanguage/ExpressionFunction.php index 7222261cd5386..dfb18d1ba3229 100644 --- a/src/Symfony/Component/ExpressionLanguage/ExpressionFunction.php +++ b/src/Symfony/Component/ExpressionLanguage/ExpressionFunction.php @@ -35,8 +35,6 @@ class ExpressionFunction private $evaluator; /** - * Constructor. - * * @param string $name The function name * @param callable $compiler A callable able to compile the function * @param callable $evaluator A callable able to evaluate the function diff --git a/src/Symfony/Component/ExpressionLanguage/Node/Node.php b/src/Symfony/Component/ExpressionLanguage/Node/Node.php index da49d6b4b29cc..b5fb2fe7df972 100644 --- a/src/Symfony/Component/ExpressionLanguage/Node/Node.php +++ b/src/Symfony/Component/ExpressionLanguage/Node/Node.php @@ -24,8 +24,6 @@ class Node public $attributes = array(); /** - * Constructor. - * * @param array $nodes An array of nodes * @param array $attributes An array of attributes */ diff --git a/src/Symfony/Component/ExpressionLanguage/ParsedExpression.php b/src/Symfony/Component/ExpressionLanguage/ParsedExpression.php index 61bf5807c49e7..a5603fc3ca96d 100644 --- a/src/Symfony/Component/ExpressionLanguage/ParsedExpression.php +++ b/src/Symfony/Component/ExpressionLanguage/ParsedExpression.php @@ -23,8 +23,6 @@ class ParsedExpression extends Expression private $nodes; /** - * Constructor. - * * @param string $expression An expression * @param Node $nodes A Node representing the expression */ diff --git a/src/Symfony/Component/ExpressionLanguage/SerializedParsedExpression.php b/src/Symfony/Component/ExpressionLanguage/SerializedParsedExpression.php index ced25dbc99b1c..dd763f75b524d 100644 --- a/src/Symfony/Component/ExpressionLanguage/SerializedParsedExpression.php +++ b/src/Symfony/Component/ExpressionLanguage/SerializedParsedExpression.php @@ -21,8 +21,6 @@ class SerializedParsedExpression extends ParsedExpression private $nodes; /** - * Constructor. - * * @param string $expression An expression * @param string $nodes The serialized nodes for the expression */ diff --git a/src/Symfony/Component/ExpressionLanguage/Token.php b/src/Symfony/Component/ExpressionLanguage/Token.php index 329273a84be64..b231bc25e73f2 100644 --- a/src/Symfony/Component/ExpressionLanguage/Token.php +++ b/src/Symfony/Component/ExpressionLanguage/Token.php @@ -30,8 +30,6 @@ class Token const PUNCTUATION_TYPE = 'punctuation'; /** - * Constructor. - * * @param string $type The type of the token (self::*_TYPE) * @param string $value The token value * @param int $cursor The cursor position in the source diff --git a/src/Symfony/Component/ExpressionLanguage/TokenStream.php b/src/Symfony/Component/ExpressionLanguage/TokenStream.php index 3c22fc1d46ed3..aa238f46a662b 100644 --- a/src/Symfony/Component/ExpressionLanguage/TokenStream.php +++ b/src/Symfony/Component/ExpressionLanguage/TokenStream.php @@ -25,8 +25,6 @@ class TokenStream private $expression; /** - * Constructor. - * * @param array $tokens An array of tokens * @param string $expression */ diff --git a/src/Symfony/Component/Finder/Adapter/AbstractFindAdapter.php b/src/Symfony/Component/Finder/Adapter/AbstractFindAdapter.php index da4004d6b525c..ca407b9ceab7b 100644 --- a/src/Symfony/Component/Finder/Adapter/AbstractFindAdapter.php +++ b/src/Symfony/Component/Finder/Adapter/AbstractFindAdapter.php @@ -31,9 +31,6 @@ abstract class AbstractFindAdapter extends AbstractAdapter */ protected $shell; - /** - * Constructor. - */ public function __construct() { $this->shell = new Shell(); diff --git a/src/Symfony/Component/Finder/Comparator/DateComparator.php b/src/Symfony/Component/Finder/Comparator/DateComparator.php index 8b7746badbe99..3de43ef4b8ddb 100644 --- a/src/Symfony/Component/Finder/Comparator/DateComparator.php +++ b/src/Symfony/Component/Finder/Comparator/DateComparator.php @@ -19,8 +19,6 @@ class DateComparator extends Comparator { /** - * Constructor. - * * @param string $test A comparison string * * @throws \InvalidArgumentException If the test is not understood diff --git a/src/Symfony/Component/Finder/Comparator/NumberComparator.php b/src/Symfony/Component/Finder/Comparator/NumberComparator.php index 16f91285a6d8c..f62c0e5740f69 100644 --- a/src/Symfony/Component/Finder/Comparator/NumberComparator.php +++ b/src/Symfony/Component/Finder/Comparator/NumberComparator.php @@ -35,8 +35,6 @@ class NumberComparator extends Comparator { /** - * Constructor. - * * @param string|int $test A comparison string or an integer * * @throws \InvalidArgumentException If the test is not understood diff --git a/src/Symfony/Component/Finder/Finder.php b/src/Symfony/Component/Finder/Finder.php index edbdcd6402074..c479f166ca3f0 100644 --- a/src/Symfony/Component/Finder/Finder.php +++ b/src/Symfony/Component/Finder/Finder.php @@ -67,9 +67,6 @@ class Finder implements \IteratorAggregate, \Countable private static $vcsPatterns = array('.svn', '_svn', 'CVS', '_darcs', '.arch-params', '.monotone', '.bzr', '.git', '.hg'); - /** - * Constructor. - */ public function __construct() { $this->ignore = static::IGNORE_VCS_FILES | static::IGNORE_DOT_FILES; diff --git a/src/Symfony/Component/Finder/Iterator/CustomFilterIterator.php b/src/Symfony/Component/Finder/Iterator/CustomFilterIterator.php index b43b88d98df79..399b6a9719c01 100644 --- a/src/Symfony/Component/Finder/Iterator/CustomFilterIterator.php +++ b/src/Symfony/Component/Finder/Iterator/CustomFilterIterator.php @@ -24,8 +24,6 @@ class CustomFilterIterator extends FilterIterator private $filters = array(); /** - * Constructor. - * * @param \Iterator $iterator The Iterator to filter * @param callable[] $filters An array of PHP callbacks * diff --git a/src/Symfony/Component/Finder/Iterator/DateRangeFilterIterator.php b/src/Symfony/Component/Finder/Iterator/DateRangeFilterIterator.php index 0f2d48f39ef99..b01e5e3f5d885 100644 --- a/src/Symfony/Component/Finder/Iterator/DateRangeFilterIterator.php +++ b/src/Symfony/Component/Finder/Iterator/DateRangeFilterIterator.php @@ -23,8 +23,6 @@ class DateRangeFilterIterator extends FilterIterator private $comparators = array(); /** - * Constructor. - * * @param \Iterator $iterator The Iterator to filter * @param DateComparator[] $comparators An array of DateComparator instances */ diff --git a/src/Symfony/Component/Finder/Iterator/DepthRangeFilterIterator.php b/src/Symfony/Component/Finder/Iterator/DepthRangeFilterIterator.php index f78c71ed415cc..ce9d3aa73a13e 100644 --- a/src/Symfony/Component/Finder/Iterator/DepthRangeFilterIterator.php +++ b/src/Symfony/Component/Finder/Iterator/DepthRangeFilterIterator.php @@ -21,8 +21,6 @@ class DepthRangeFilterIterator extends FilterIterator private $minDepth = 0; /** - * Constructor. - * * @param \RecursiveIteratorIterator $iterator The Iterator to filter * @param int $minDepth The min depth * @param int $maxDepth The max depth diff --git a/src/Symfony/Component/Finder/Iterator/ExcludeDirectoryFilterIterator.php b/src/Symfony/Component/Finder/Iterator/ExcludeDirectoryFilterIterator.php index 3f5a5dfeb133c..c57128c278492 100644 --- a/src/Symfony/Component/Finder/Iterator/ExcludeDirectoryFilterIterator.php +++ b/src/Symfony/Component/Finder/Iterator/ExcludeDirectoryFilterIterator.php @@ -24,8 +24,6 @@ class ExcludeDirectoryFilterIterator extends FilterIterator implements \Recursiv private $excludedPattern; /** - * Constructor. - * * @param \Iterator $iterator The Iterator to filter * @param array $directories An array of directories to exclude */ diff --git a/src/Symfony/Component/Finder/Iterator/FileTypeFilterIterator.php b/src/Symfony/Component/Finder/Iterator/FileTypeFilterIterator.php index f50fd82c345f4..e9811d4a03ee6 100644 --- a/src/Symfony/Component/Finder/Iterator/FileTypeFilterIterator.php +++ b/src/Symfony/Component/Finder/Iterator/FileTypeFilterIterator.php @@ -24,8 +24,6 @@ class FileTypeFilterIterator extends FilterIterator private $mode; /** - * Constructor. - * * @param \Iterator $iterator The Iterator to filter * @param int $mode The mode (self::ONLY_FILES or self::ONLY_DIRECTORIES) */ diff --git a/src/Symfony/Component/Finder/Iterator/MultiplePcreFilterIterator.php b/src/Symfony/Component/Finder/Iterator/MultiplePcreFilterIterator.php index 068a7efbae96e..b816591e48c51 100644 --- a/src/Symfony/Component/Finder/Iterator/MultiplePcreFilterIterator.php +++ b/src/Symfony/Component/Finder/Iterator/MultiplePcreFilterIterator.php @@ -24,8 +24,6 @@ abstract class MultiplePcreFilterIterator extends FilterIterator protected $noMatchRegexps = array(); /** - * Constructor. - * * @param \Iterator $iterator The Iterator to filter * @param array $matchPatterns An array of patterns that need to match * @param array $noMatchPatterns An array of patterns that need to not match diff --git a/src/Symfony/Component/Finder/Iterator/RecursiveDirectoryIterator.php b/src/Symfony/Component/Finder/Iterator/RecursiveDirectoryIterator.php index c87096fc87e23..8b94965ef1566 100644 --- a/src/Symfony/Component/Finder/Iterator/RecursiveDirectoryIterator.php +++ b/src/Symfony/Component/Finder/Iterator/RecursiveDirectoryIterator.php @@ -37,8 +37,6 @@ class RecursiveDirectoryIterator extends \RecursiveDirectoryIterator private $directorySeparator = '/'; /** - * Constructor. - * * @param string $path * @param int $flags * @param bool $ignoreUnreadableDirs diff --git a/src/Symfony/Component/Finder/Iterator/SizeRangeFilterIterator.php b/src/Symfony/Component/Finder/Iterator/SizeRangeFilterIterator.php index 3d3140a6ae45a..bd1a7fb700481 100644 --- a/src/Symfony/Component/Finder/Iterator/SizeRangeFilterIterator.php +++ b/src/Symfony/Component/Finder/Iterator/SizeRangeFilterIterator.php @@ -23,8 +23,6 @@ class SizeRangeFilterIterator extends FilterIterator private $comparators = array(); /** - * Constructor. - * * @param \Iterator $iterator The Iterator to filter * @param NumberComparator[] $comparators An array of NumberComparator instances */ diff --git a/src/Symfony/Component/Finder/Iterator/SortableIterator.php b/src/Symfony/Component/Finder/Iterator/SortableIterator.php index f1134c00b9489..c2f54b937652f 100644 --- a/src/Symfony/Component/Finder/Iterator/SortableIterator.php +++ b/src/Symfony/Component/Finder/Iterator/SortableIterator.php @@ -28,8 +28,6 @@ class SortableIterator implements \IteratorAggregate private $sort; /** - * Constructor. - * * @param \Traversable $iterator The Iterator to filter * @param int|callable $sort The sort type (SORT_BY_NAME, SORT_BY_TYPE, or a PHP callback) * diff --git a/src/Symfony/Component/Finder/Shell/Command.php b/src/Symfony/Component/Finder/Shell/Command.php index 1e0747210c7a1..29158d8cac350 100644 --- a/src/Symfony/Component/Finder/Shell/Command.php +++ b/src/Symfony/Component/Finder/Shell/Command.php @@ -37,8 +37,6 @@ class Command private $errorHandler; /** - * Constructor. - * * @param Command|null $parent Parent command */ public function __construct(Command $parent = null) diff --git a/src/Symfony/Component/Finder/SplFileInfo.php b/src/Symfony/Component/Finder/SplFileInfo.php index 31a3f86a674d5..19f95e26be69a 100644 --- a/src/Symfony/Component/Finder/SplFileInfo.php +++ b/src/Symfony/Component/Finder/SplFileInfo.php @@ -22,8 +22,6 @@ class SplFileInfo extends \SplFileInfo private $relativePathname; /** - * Constructor. - * * @param string $file The file name * @param string $relativePath The relative path * @param string $relativePathname The relative path name diff --git a/src/Symfony/Component/Form/CallbackTransformer.php b/src/Symfony/Component/Form/CallbackTransformer.php index 7857ad5f598fe..6f61370d5e037 100644 --- a/src/Symfony/Component/Form/CallbackTransformer.php +++ b/src/Symfony/Component/Form/CallbackTransformer.php @@ -31,8 +31,6 @@ class CallbackTransformer implements DataTransformerInterface private $reverseTransform; /** - * Constructor. - * * @param callable $transform The forward transform callback * @param callable $reverseTransform The reverse transform callback * diff --git a/src/Symfony/Component/Form/Extension/Core/DataTransformer/BaseDateTimeTransformer.php b/src/Symfony/Component/Form/Extension/Core/DataTransformer/BaseDateTimeTransformer.php index 309d46074e00f..44fa3d8119878 100644 --- a/src/Symfony/Component/Form/Extension/Core/DataTransformer/BaseDateTimeTransformer.php +++ b/src/Symfony/Component/Form/Extension/Core/DataTransformer/BaseDateTimeTransformer.php @@ -30,8 +30,6 @@ abstract class BaseDateTimeTransformer implements DataTransformerInterface protected $outputTimezone; /** - * Constructor. - * * @param string $inputTimezone The name of the input timezone * @param string $outputTimezone The name of the output timezone * diff --git a/src/Symfony/Component/Form/Extension/Core/DataTransformer/ChoiceToBooleanArrayTransformer.php b/src/Symfony/Component/Form/Extension/Core/DataTransformer/ChoiceToBooleanArrayTransformer.php index 50ee4b693e485..b2744c5e82be4 100644 --- a/src/Symfony/Component/Form/Extension/Core/DataTransformer/ChoiceToBooleanArrayTransformer.php +++ b/src/Symfony/Component/Form/Extension/Core/DataTransformer/ChoiceToBooleanArrayTransformer.php @@ -30,8 +30,6 @@ class ChoiceToBooleanArrayTransformer implements DataTransformerInterface private $placeholderPresent; /** - * Constructor. - * * @param ChoiceListInterface $choiceList * @param bool $placeholderPresent */ diff --git a/src/Symfony/Component/Form/Extension/Core/DataTransformer/ChoiceToValueTransformer.php b/src/Symfony/Component/Form/Extension/Core/DataTransformer/ChoiceToValueTransformer.php index c7a6655b4e65a..369a12343facd 100644 --- a/src/Symfony/Component/Form/Extension/Core/DataTransformer/ChoiceToValueTransformer.php +++ b/src/Symfony/Component/Form/Extension/Core/DataTransformer/ChoiceToValueTransformer.php @@ -23,8 +23,6 @@ class ChoiceToValueTransformer implements DataTransformerInterface private $choiceList; /** - * Constructor. - * * @param ChoiceListInterface $choiceList */ public function __construct(ChoiceListInterface $choiceList) diff --git a/src/Symfony/Component/Form/Extension/Core/DataTransformer/ChoicesToValuesTransformer.php b/src/Symfony/Component/Form/Extension/Core/DataTransformer/ChoicesToValuesTransformer.php index 0a1f2f028863a..9e6dcef12ff1f 100644 --- a/src/Symfony/Component/Form/Extension/Core/DataTransformer/ChoicesToValuesTransformer.php +++ b/src/Symfony/Component/Form/Extension/Core/DataTransformer/ChoicesToValuesTransformer.php @@ -23,8 +23,6 @@ class ChoicesToValuesTransformer implements DataTransformerInterface private $choiceList; /** - * Constructor. - * * @param ChoiceListInterface $choiceList */ public function __construct(ChoiceListInterface $choiceList) diff --git a/src/Symfony/Component/Form/Extension/Core/DataTransformer/DateTimeToArrayTransformer.php b/src/Symfony/Component/Form/Extension/Core/DataTransformer/DateTimeToArrayTransformer.php index 24479fb0163dd..af8bb836da4df 100644 --- a/src/Symfony/Component/Form/Extension/Core/DataTransformer/DateTimeToArrayTransformer.php +++ b/src/Symfony/Component/Form/Extension/Core/DataTransformer/DateTimeToArrayTransformer.php @@ -27,8 +27,6 @@ class DateTimeToArrayTransformer extends BaseDateTimeTransformer private $fields; /** - * Constructor. - * * @param string $inputTimezone The input timezone * @param string $outputTimezone The output timezone * @param array $fields The date fields diff --git a/src/Symfony/Component/Form/Extension/Core/DataTransformer/DateTimeToLocalizedStringTransformer.php b/src/Symfony/Component/Form/Extension/Core/DataTransformer/DateTimeToLocalizedStringTransformer.php index e1db36bda663d..185846044fe04 100644 --- a/src/Symfony/Component/Form/Extension/Core/DataTransformer/DateTimeToLocalizedStringTransformer.php +++ b/src/Symfony/Component/Form/Extension/Core/DataTransformer/DateTimeToLocalizedStringTransformer.php @@ -28,8 +28,6 @@ class DateTimeToLocalizedStringTransformer extends BaseDateTimeTransformer private $calendar; /** - * Constructor. - * * @see BaseDateTimeTransformer::formats for available format options * * @param string $inputTimezone The name of the input timezone diff --git a/src/Symfony/Component/Form/Extension/Core/DataTransformer/PercentToLocalizedStringTransformer.php b/src/Symfony/Component/Form/Extension/Core/DataTransformer/PercentToLocalizedStringTransformer.php index 7fc191a054ff4..af4606c2383a3 100644 --- a/src/Symfony/Component/Form/Extension/Core/DataTransformer/PercentToLocalizedStringTransformer.php +++ b/src/Symfony/Component/Form/Extension/Core/DataTransformer/PercentToLocalizedStringTransformer.php @@ -36,8 +36,6 @@ class PercentToLocalizedStringTransformer implements DataTransformerInterface private $scale; /** - * Constructor. - * * @see self::$types for a list of supported types * * @param int $scale The scale diff --git a/src/Symfony/Component/Form/Extension/Core/EventListener/FixCheckboxInputListener.php b/src/Symfony/Component/Form/Extension/Core/EventListener/FixCheckboxInputListener.php index 68aacd4c56b9e..87d03e05e154a 100644 --- a/src/Symfony/Component/Form/Extension/Core/EventListener/FixCheckboxInputListener.php +++ b/src/Symfony/Component/Form/Extension/Core/EventListener/FixCheckboxInputListener.php @@ -33,8 +33,6 @@ class FixCheckboxInputListener implements EventSubscriberInterface private $choiceList; /** - * Constructor. - * * @param ChoiceListInterface $choiceList */ public function __construct(ChoiceListInterface $choiceList) diff --git a/src/Symfony/Component/Form/Extension/Core/EventListener/FixRadioInputListener.php b/src/Symfony/Component/Form/Extension/Core/EventListener/FixRadioInputListener.php index 9855b374df643..b2e0f852b46d9 100644 --- a/src/Symfony/Component/Form/Extension/Core/EventListener/FixRadioInputListener.php +++ b/src/Symfony/Component/Form/Extension/Core/EventListener/FixRadioInputListener.php @@ -34,8 +34,6 @@ class FixRadioInputListener implements EventSubscriberInterface private $placeholderPresent; /** - * Constructor. - * * @param ChoiceListInterface $choiceList * @param bool $placeholderPresent */ diff --git a/src/Symfony/Component/Form/Extension/Core/EventListener/FixUrlProtocolListener.php b/src/Symfony/Component/Form/Extension/Core/EventListener/FixUrlProtocolListener.php index e9a51cc988b7e..f132d8709d111 100644 --- a/src/Symfony/Component/Form/Extension/Core/EventListener/FixUrlProtocolListener.php +++ b/src/Symfony/Component/Form/Extension/Core/EventListener/FixUrlProtocolListener.php @@ -25,8 +25,6 @@ class FixUrlProtocolListener implements EventSubscriberInterface private $defaultProtocol; /** - * Constructor. - * * @param string|null $defaultProtocol The URL scheme to add when there is none or null to not modify the data */ public function __construct($defaultProtocol = 'http') diff --git a/src/Symfony/Component/Form/Extension/Csrf/CsrfExtension.php b/src/Symfony/Component/Form/Extension/Csrf/CsrfExtension.php index 0bc8ca7db19d0..b5396669f6d27 100644 --- a/src/Symfony/Component/Form/Extension/Csrf/CsrfExtension.php +++ b/src/Symfony/Component/Form/Extension/Csrf/CsrfExtension.php @@ -41,8 +41,6 @@ class CsrfExtension extends AbstractExtension private $translationDomain; /** - * Constructor. - * * @param CsrfTokenManagerInterface $tokenManager The CSRF token manager * @param TranslatorInterface $translator The translator for translating error messages * @param null|string $translationDomain The translation domain for translating diff --git a/src/Symfony/Component/Form/FormError.php b/src/Symfony/Component/Form/FormError.php index 6b3938868ddde..c35a26f5a3fce 100644 --- a/src/Symfony/Component/Form/FormError.php +++ b/src/Symfony/Component/Form/FormError.php @@ -61,8 +61,6 @@ class FormError implements \Serializable private $origin; /** - * Constructor. - * * Any array key in $messageParameters will be used as a placeholder in * $messageTemplate. * diff --git a/src/Symfony/Component/Form/FormRegistry.php b/src/Symfony/Component/Form/FormRegistry.php index 5f0b795e92234..70b0c78e6cfa5 100644 --- a/src/Symfony/Component/Form/FormRegistry.php +++ b/src/Symfony/Component/Form/FormRegistry.php @@ -45,8 +45,6 @@ class FormRegistry implements FormRegistryInterface private $resolvedTypeFactory; /** - * Constructor. - * * @param FormExtensionInterface[] $extensions An array of FormExtensionInterface * @param ResolvedFormTypeFactoryInterface $resolvedTypeFactory The factory for resolved form types * diff --git a/src/Symfony/Component/Form/FormRenderer.php b/src/Symfony/Component/Form/FormRenderer.php index 9d1c075bb5fa7..b731b740dff34 100644 --- a/src/Symfony/Component/Form/FormRenderer.php +++ b/src/Symfony/Component/Form/FormRenderer.php @@ -53,8 +53,6 @@ class FormRenderer implements FormRendererInterface private $variableStack = array(); /** - * Constructor. - * * @param FormRendererEngineInterface $engine * @param CsrfTokenManagerInterface|null $csrfTokenManager * diff --git a/src/Symfony/Component/Form/FormTypeGuesserChain.php b/src/Symfony/Component/Form/FormTypeGuesserChain.php index 7c4f65b43579f..25f07ff2af58e 100644 --- a/src/Symfony/Component/Form/FormTypeGuesserChain.php +++ b/src/Symfony/Component/Form/FormTypeGuesserChain.php @@ -19,8 +19,6 @@ class FormTypeGuesserChain implements FormTypeGuesserInterface private $guessers = array(); /** - * Constructor. - * * @param FormTypeGuesserInterface[] $guessers Guessers as instances of FormTypeGuesserInterface * * @throws UnexpectedTypeException if any guesser does not implement FormTypeGuesserInterface diff --git a/src/Symfony/Component/Form/Guess/Guess.php b/src/Symfony/Component/Form/Guess/Guess.php index 36614ffdb9f93..2576b59437859 100644 --- a/src/Symfony/Component/Form/Guess/Guess.php +++ b/src/Symfony/Component/Form/Guess/Guess.php @@ -88,8 +88,6 @@ public static function getBestGuess(array $guesses) } /** - * Constructor. - * * @param int $confidence The confidence * * @throws InvalidArgumentException if the given value of confidence is unknown diff --git a/src/Symfony/Component/Form/Guess/TypeGuess.php b/src/Symfony/Component/Form/Guess/TypeGuess.php index 87cc60a0f1ef5..a190d5bc03e12 100644 --- a/src/Symfony/Component/Form/Guess/TypeGuess.php +++ b/src/Symfony/Component/Form/Guess/TypeGuess.php @@ -34,8 +34,6 @@ class TypeGuess extends Guess private $options; /** - * Constructor. - * * @param string $type The guessed field type * @param array $options The options for creating instances of the * guessed class diff --git a/src/Symfony/Component/Form/Guess/ValueGuess.php b/src/Symfony/Component/Form/Guess/ValueGuess.php index 9a46207eefe42..251e9cd428375 100644 --- a/src/Symfony/Component/Form/Guess/ValueGuess.php +++ b/src/Symfony/Component/Form/Guess/ValueGuess.php @@ -21,8 +21,6 @@ class ValueGuess extends Guess private $value; /** - * Constructor. - * * @param string|int|bool|null $value The guessed value * @param int $confidence The confidence that the guessed class name * is correct diff --git a/src/Symfony/Component/HttpFoundation/AcceptHeader.php b/src/Symfony/Component/HttpFoundation/AcceptHeader.php index 2aa91dc44cb47..99be6768f9b72 100644 --- a/src/Symfony/Component/HttpFoundation/AcceptHeader.php +++ b/src/Symfony/Component/HttpFoundation/AcceptHeader.php @@ -32,8 +32,6 @@ class AcceptHeader private $sorted = true; /** - * Constructor. - * * @param AcceptHeaderItem[] $items */ public function __construct(array $items) diff --git a/src/Symfony/Component/HttpFoundation/AcceptHeaderItem.php b/src/Symfony/Component/HttpFoundation/AcceptHeaderItem.php index fb54b4935a9f3..2758f5c40bcfa 100644 --- a/src/Symfony/Component/HttpFoundation/AcceptHeaderItem.php +++ b/src/Symfony/Component/HttpFoundation/AcceptHeaderItem.php @@ -39,8 +39,6 @@ class AcceptHeaderItem private $attributes = array(); /** - * Constructor. - * * @param string $value * @param array $attributes */ diff --git a/src/Symfony/Component/HttpFoundation/BinaryFileResponse.php b/src/Symfony/Component/HttpFoundation/BinaryFileResponse.php index 177b708e8f054..71823c0f374b3 100644 --- a/src/Symfony/Component/HttpFoundation/BinaryFileResponse.php +++ b/src/Symfony/Component/HttpFoundation/BinaryFileResponse.php @@ -36,8 +36,6 @@ class BinaryFileResponse extends Response protected $deleteFileAfterSend = false; /** - * Constructor. - * * @param \SplFileInfo|string $file The file to stream * @param int $status The response status code * @param array $headers An array of response headers diff --git a/src/Symfony/Component/HttpFoundation/Cookie.php b/src/Symfony/Component/HttpFoundation/Cookie.php index fb1e7dfd74ea4..93bb099cd5d24 100644 --- a/src/Symfony/Component/HttpFoundation/Cookie.php +++ b/src/Symfony/Component/HttpFoundation/Cookie.php @@ -27,8 +27,6 @@ class Cookie protected $httpOnly; /** - * Constructor. - * * @param string $name The name of the cookie * @param string $value The value of the cookie * @param int|string|\DateTime|\DateTimeInterface $expire The time the cookie expires diff --git a/src/Symfony/Component/HttpFoundation/File/Exception/AccessDeniedException.php b/src/Symfony/Component/HttpFoundation/File/Exception/AccessDeniedException.php index 41f7a462506b7..3b8e41d4a2cf9 100644 --- a/src/Symfony/Component/HttpFoundation/File/Exception/AccessDeniedException.php +++ b/src/Symfony/Component/HttpFoundation/File/Exception/AccessDeniedException.php @@ -19,8 +19,6 @@ class AccessDeniedException extends FileException { /** - * Constructor. - * * @param string $path The path to the accessed file */ public function __construct($path) diff --git a/src/Symfony/Component/HttpFoundation/File/Exception/FileNotFoundException.php b/src/Symfony/Component/HttpFoundation/File/Exception/FileNotFoundException.php index ac90d4035b8ce..bfcc37ec66ea0 100644 --- a/src/Symfony/Component/HttpFoundation/File/Exception/FileNotFoundException.php +++ b/src/Symfony/Component/HttpFoundation/File/Exception/FileNotFoundException.php @@ -19,8 +19,6 @@ class FileNotFoundException extends FileException { /** - * Constructor. - * * @param string $path The path to the file that was not found */ public function __construct($path) diff --git a/src/Symfony/Component/HttpFoundation/File/MimeType/FileBinaryMimeTypeGuesser.php b/src/Symfony/Component/HttpFoundation/File/MimeType/FileBinaryMimeTypeGuesser.php index f917a06d6ccbf..c2ac6768c3013 100644 --- a/src/Symfony/Component/HttpFoundation/File/MimeType/FileBinaryMimeTypeGuesser.php +++ b/src/Symfony/Component/HttpFoundation/File/MimeType/FileBinaryMimeTypeGuesser.php @@ -24,8 +24,6 @@ class FileBinaryMimeTypeGuesser implements MimeTypeGuesserInterface private $cmd; /** - * Constructor. - * * The $cmd pattern must contain a "%s" string that will be replaced * with the file name to guess. * diff --git a/src/Symfony/Component/HttpFoundation/File/MimeType/FileinfoMimeTypeGuesser.php b/src/Symfony/Component/HttpFoundation/File/MimeType/FileinfoMimeTypeGuesser.php index 6fee94798c9cd..9b42835e43044 100644 --- a/src/Symfony/Component/HttpFoundation/File/MimeType/FileinfoMimeTypeGuesser.php +++ b/src/Symfony/Component/HttpFoundation/File/MimeType/FileinfoMimeTypeGuesser.php @@ -24,8 +24,6 @@ class FileinfoMimeTypeGuesser implements MimeTypeGuesserInterface private $magicFile; /** - * Constructor. - * * @param string $magicFile A magic file to use with the finfo instance * * @see http://www.php.net/manual/en/function.finfo-open.php diff --git a/src/Symfony/Component/HttpFoundation/FileBag.php b/src/Symfony/Component/HttpFoundation/FileBag.php index e17a9057b7157..0aaf49aa6eaab 100644 --- a/src/Symfony/Component/HttpFoundation/FileBag.php +++ b/src/Symfony/Component/HttpFoundation/FileBag.php @@ -24,8 +24,6 @@ class FileBag extends ParameterBag private static $fileKeys = array('error', 'name', 'size', 'tmp_name', 'type'); /** - * Constructor. - * * @param array $parameters An array of HTTP files */ public function __construct(array $parameters = array()) diff --git a/src/Symfony/Component/HttpFoundation/HeaderBag.php b/src/Symfony/Component/HttpFoundation/HeaderBag.php index 29bac5e513414..a824ed8649268 100644 --- a/src/Symfony/Component/HttpFoundation/HeaderBag.php +++ b/src/Symfony/Component/HttpFoundation/HeaderBag.php @@ -22,8 +22,6 @@ class HeaderBag implements \IteratorAggregate, \Countable protected $cacheControl = array(); /** - * Constructor. - * * @param array $headers An array of HTTP headers */ public function __construct(array $headers = array()) diff --git a/src/Symfony/Component/HttpFoundation/JsonResponse.php b/src/Symfony/Component/HttpFoundation/JsonResponse.php index c6e0ba6541061..099749084140d 100644 --- a/src/Symfony/Component/HttpFoundation/JsonResponse.php +++ b/src/Symfony/Component/HttpFoundation/JsonResponse.php @@ -32,8 +32,6 @@ class JsonResponse extends Response protected $encodingOptions = 15; /** - * Constructor. - * * @param mixed $data The response data * @param int $status The response status code * @param array $headers An array of response headers diff --git a/src/Symfony/Component/HttpFoundation/ParameterBag.php b/src/Symfony/Component/HttpFoundation/ParameterBag.php index 3436ee9337486..77b05a9000e4c 100644 --- a/src/Symfony/Component/HttpFoundation/ParameterBag.php +++ b/src/Symfony/Component/HttpFoundation/ParameterBag.php @@ -26,8 +26,6 @@ class ParameterBag implements \IteratorAggregate, \Countable protected $parameters; /** - * Constructor. - * * @param array $parameters An array of parameters */ public function __construct(array $parameters = array()) diff --git a/src/Symfony/Component/HttpFoundation/Request.php b/src/Symfony/Component/HttpFoundation/Request.php index 0c11adab6a92e..8f372d432c40d 100644 --- a/src/Symfony/Component/HttpFoundation/Request.php +++ b/src/Symfony/Component/HttpFoundation/Request.php @@ -207,8 +207,6 @@ class Request protected static $requestFactory; /** - * Constructor. - * * @param array $query The GET parameters * @param array $request The POST parameters * @param array $attributes The request attributes (parameters parsed from the PATH_INFO, ...) diff --git a/src/Symfony/Component/HttpFoundation/Response.php b/src/Symfony/Component/HttpFoundation/Response.php index f9512d6706ef9..5e801116083d4 100644 --- a/src/Symfony/Component/HttpFoundation/Response.php +++ b/src/Symfony/Component/HttpFoundation/Response.php @@ -188,8 +188,6 @@ class Response ); /** - * Constructor. - * * @param mixed $content The response content, see setContent() * @param int $status The response status code * @param array $headers An array of response headers diff --git a/src/Symfony/Component/HttpFoundation/ResponseHeaderBag.php b/src/Symfony/Component/HttpFoundation/ResponseHeaderBag.php index 3223691eb6fe4..32e7187853496 100644 --- a/src/Symfony/Component/HttpFoundation/ResponseHeaderBag.php +++ b/src/Symfony/Component/HttpFoundation/ResponseHeaderBag.php @@ -40,8 +40,6 @@ class ResponseHeaderBag extends HeaderBag protected $headerNames = array(); /** - * Constructor. - * * @param array $headers An array of HTTP headers */ public function __construct(array $headers = array()) diff --git a/src/Symfony/Component/HttpFoundation/Session/Attribute/AttributeBag.php b/src/Symfony/Component/HttpFoundation/Session/Attribute/AttributeBag.php index af292e37a4fe4..57c297197b862 100644 --- a/src/Symfony/Component/HttpFoundation/Session/Attribute/AttributeBag.php +++ b/src/Symfony/Component/HttpFoundation/Session/Attribute/AttributeBag.php @@ -29,8 +29,6 @@ class AttributeBag implements AttributeBagInterface, \IteratorAggregate, \Counta protected $attributes = array(); /** - * Constructor. - * * @param string $storageKey The key used to store attributes in the session */ public function __construct($storageKey = '_sf2_attributes') diff --git a/src/Symfony/Component/HttpFoundation/Session/Attribute/NamespacedAttributeBag.php b/src/Symfony/Component/HttpFoundation/Session/Attribute/NamespacedAttributeBag.php index d797a6f23886e..7afc6de7c6c06 100644 --- a/src/Symfony/Component/HttpFoundation/Session/Attribute/NamespacedAttributeBag.php +++ b/src/Symfony/Component/HttpFoundation/Session/Attribute/NamespacedAttributeBag.php @@ -27,8 +27,6 @@ class NamespacedAttributeBag extends AttributeBag private $namespaceCharacter; /** - * Constructor. - * * @param string $storageKey Session storage key * @param string $namespaceCharacter Namespace character to use in keys */ diff --git a/src/Symfony/Component/HttpFoundation/Session/Flash/AutoExpireFlashBag.php b/src/Symfony/Component/HttpFoundation/Session/Flash/AutoExpireFlashBag.php index ddd603fdd1efb..8110aee0cffc1 100644 --- a/src/Symfony/Component/HttpFoundation/Session/Flash/AutoExpireFlashBag.php +++ b/src/Symfony/Component/HttpFoundation/Session/Flash/AutoExpireFlashBag.php @@ -35,8 +35,6 @@ class AutoExpireFlashBag implements FlashBagInterface private $storageKey; /** - * Constructor. - * * @param string $storageKey The key used to store flashes in the session */ public function __construct($storageKey = '_sf2_flashes') diff --git a/src/Symfony/Component/HttpFoundation/Session/Flash/FlashBag.php b/src/Symfony/Component/HttpFoundation/Session/Flash/FlashBag.php index 1516de7fe92ef..a4159cd82254e 100644 --- a/src/Symfony/Component/HttpFoundation/Session/Flash/FlashBag.php +++ b/src/Symfony/Component/HttpFoundation/Session/Flash/FlashBag.php @@ -37,8 +37,6 @@ class FlashBag implements FlashBagInterface, \IteratorAggregate private $storageKey; /** - * Constructor. - * * @param string $storageKey The key used to store flashes in the session */ public function __construct($storageKey = '_sf2_flashes') diff --git a/src/Symfony/Component/HttpFoundation/Session/Session.php b/src/Symfony/Component/HttpFoundation/Session/Session.php index cdd97375b9054..5a765654c1dd9 100644 --- a/src/Symfony/Component/HttpFoundation/Session/Session.php +++ b/src/Symfony/Component/HttpFoundation/Session/Session.php @@ -19,8 +19,6 @@ use Symfony\Component\HttpFoundation\Session\Storage\NativeSessionStorage; /** - * Session. - * * @author Fabien Potencier * @author Drak */ @@ -44,8 +42,6 @@ class Session implements SessionInterface, \IteratorAggregate, \Countable private $attributeName; /** - * Constructor. - * * @param SessionStorageInterface $storage A SessionStorageInterface instance * @param AttributeBagInterface $attributes An AttributeBagInterface instance, (defaults null for default AttributeBag) * @param FlashBagInterface $flashes A FlashBagInterface instance (defaults null for default FlashBag) diff --git a/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/LegacyPdoSessionHandler.php b/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/LegacyPdoSessionHandler.php index 111541d92d521..900fb9f5f23e1 100644 --- a/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/LegacyPdoSessionHandler.php +++ b/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/LegacyPdoSessionHandler.php @@ -57,8 +57,6 @@ class LegacyPdoSessionHandler implements \SessionHandlerInterface private $timeCol; /** - * Constructor. - * * List of available options: * * db_table: The name of the table [required] * * db_id_col: The column where to store the session id [default: sess_id] diff --git a/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/MemcacheSessionHandler.php b/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/MemcacheSessionHandler.php index 4e490a05d4ce0..d31aa7667e657 100644 --- a/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/MemcacheSessionHandler.php +++ b/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/MemcacheSessionHandler.php @@ -12,8 +12,6 @@ namespace Symfony\Component\HttpFoundation\Session\Storage\Handler; /** - * MemcacheSessionHandler. - * * @author Drak */ class MemcacheSessionHandler implements \SessionHandlerInterface @@ -34,8 +32,6 @@ class MemcacheSessionHandler implements \SessionHandlerInterface private $prefix; /** - * Constructor. - * * List of available options: * * prefix: The prefix to use for the memcache keys in order to avoid collision * * expiretime: The time to live in seconds diff --git a/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/MemcachedSessionHandler.php b/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/MemcachedSessionHandler.php index 67a49ad6f5e2a..68901294ebefe 100644 --- a/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/MemcachedSessionHandler.php +++ b/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/MemcachedSessionHandler.php @@ -12,8 +12,6 @@ namespace Symfony\Component\HttpFoundation\Session\Storage\Handler; /** - * MemcachedSessionHandler. - * * Memcached based session storage handler based on the Memcached class * provided by the PHP memcached extension. * @@ -39,8 +37,6 @@ class MemcachedSessionHandler implements \SessionHandlerInterface private $prefix; /** - * Constructor. - * * List of available options: * * prefix: The prefix to use for the memcached keys in order to avoid collision * * expiretime: The time to live in seconds diff --git a/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/MongoDbSessionHandler.php b/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/MongoDbSessionHandler.php index 8408f000cdbf8..80ecc1cc3c788 100644 --- a/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/MongoDbSessionHandler.php +++ b/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/MongoDbSessionHandler.php @@ -12,8 +12,6 @@ namespace Symfony\Component\HttpFoundation\Session\Storage\Handler; /** - * MongoDB session handler. - * * @author Markus Bachmann */ class MongoDbSessionHandler implements \SessionHandlerInterface @@ -34,8 +32,6 @@ class MongoDbSessionHandler implements \SessionHandlerInterface private $options; /** - * Constructor. - * * List of available options: * * database: The name of the database [required] * * collection: The name of the collection [required] diff --git a/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/NativeFileSessionHandler.php b/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/NativeFileSessionHandler.php index 1be0a39837333..d6ad93749f048 100644 --- a/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/NativeFileSessionHandler.php +++ b/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/NativeFileSessionHandler.php @@ -12,8 +12,6 @@ namespace Symfony\Component\HttpFoundation\Session\Storage\Handler; /** - * NativeFileSessionHandler. - * * Native session handler using PHP's built in file storage. * * @author Drak @@ -21,8 +19,6 @@ class NativeFileSessionHandler extends NativeSessionHandler { /** - * Constructor. - * * @param string $savePath Path of directory to save session files * Default null will leave setting as defined by PHP. * '/path', 'N;/path', or 'N;octal-mode;/path diff --git a/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/PdoSessionHandler.php b/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/PdoSessionHandler.php index 8909a5f401fdc..66d12aaef835f 100644 --- a/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/PdoSessionHandler.php +++ b/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/PdoSessionHandler.php @@ -148,8 +148,6 @@ class PdoSessionHandler implements \SessionHandlerInterface private $gcCalled = false; /** - * Constructor. - * * You can either pass an existing database connection as PDO instance or * pass a DSN string that will be used to lazy-connect to the database * when the session is actually used. Furthermore it's possible to pass null diff --git a/src/Symfony/Component/HttpFoundation/Session/Storage/MetadataBag.php b/src/Symfony/Component/HttpFoundation/Session/Storage/MetadataBag.php index 322dd560f8087..6f59af486981e 100644 --- a/src/Symfony/Component/HttpFoundation/Session/Storage/MetadataBag.php +++ b/src/Symfony/Component/HttpFoundation/Session/Storage/MetadataBag.php @@ -54,8 +54,6 @@ class MetadataBag implements SessionBagInterface private $updateThreshold; /** - * Constructor. - * * @param string $storageKey The key used to store bag in the session * @param int $updateThreshold The time to wait between two UPDATED updates */ diff --git a/src/Symfony/Component/HttpFoundation/Session/Storage/MockArraySessionStorage.php b/src/Symfony/Component/HttpFoundation/Session/Storage/MockArraySessionStorage.php index 348fd23018a03..0349a43367d76 100644 --- a/src/Symfony/Component/HttpFoundation/Session/Storage/MockArraySessionStorage.php +++ b/src/Symfony/Component/HttpFoundation/Session/Storage/MockArraySessionStorage.php @@ -63,8 +63,6 @@ class MockArraySessionStorage implements SessionStorageInterface protected $bags = array(); /** - * Constructor. - * * @param string $name Session name * @param MetadataBag $metaBag MetadataBag instance */ diff --git a/src/Symfony/Component/HttpFoundation/Session/Storage/MockFileSessionStorage.php b/src/Symfony/Component/HttpFoundation/Session/Storage/MockFileSessionStorage.php index 71f9e555121fa..8c1bf73caefb3 100644 --- a/src/Symfony/Component/HttpFoundation/Session/Storage/MockFileSessionStorage.php +++ b/src/Symfony/Component/HttpFoundation/Session/Storage/MockFileSessionStorage.php @@ -30,8 +30,6 @@ class MockFileSessionStorage extends MockArraySessionStorage private $savePath; /** - * Constructor. - * * @param string $savePath Path of directory to save session files * @param string $name Session name * @param MetadataBag $metaBag MetadataBag instance diff --git a/src/Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.php b/src/Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.php index 812f5f2e4fcc0..5888323bd7c30 100644 --- a/src/Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.php +++ b/src/Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.php @@ -52,8 +52,6 @@ class NativeSessionStorage implements SessionStorageInterface protected $metadataBag; /** - * Constructor. - * * Depending on how you want the storage driver to behave you probably * want to override this constructor entirely. * diff --git a/src/Symfony/Component/HttpFoundation/Session/Storage/PhpBridgeSessionStorage.php b/src/Symfony/Component/HttpFoundation/Session/Storage/PhpBridgeSessionStorage.php index ced706f72c85b..3a2391e762e4e 100644 --- a/src/Symfony/Component/HttpFoundation/Session/Storage/PhpBridgeSessionStorage.php +++ b/src/Symfony/Component/HttpFoundation/Session/Storage/PhpBridgeSessionStorage.php @@ -22,8 +22,6 @@ class PhpBridgeSessionStorage extends NativeSessionStorage { /** - * Constructor. - * * @param AbstractProxy|NativeSessionHandler|\SessionHandlerInterface|null $handler * @param MetadataBag $metaBag MetadataBag */ diff --git a/src/Symfony/Component/HttpFoundation/Session/Storage/Proxy/NativeProxy.php b/src/Symfony/Component/HttpFoundation/Session/Storage/Proxy/NativeProxy.php index 0db34aa28d385..21ed1ada04b4f 100644 --- a/src/Symfony/Component/HttpFoundation/Session/Storage/Proxy/NativeProxy.php +++ b/src/Symfony/Component/HttpFoundation/Session/Storage/Proxy/NativeProxy.php @@ -12,17 +12,12 @@ namespace Symfony\Component\HttpFoundation\Session\Storage\Proxy; /** - * NativeProxy. - * * This proxy is built-in session handlers in PHP 5.3.x * * @author Drak */ class NativeProxy extends AbstractProxy { - /** - * Constructor. - */ public function __construct() { // this makes an educated guess as to what the handler is since it should already be set. diff --git a/src/Symfony/Component/HttpFoundation/Session/Storage/Proxy/SessionHandlerProxy.php b/src/Symfony/Component/HttpFoundation/Session/Storage/Proxy/SessionHandlerProxy.php index 81643c74b4001..8f91f06048718 100644 --- a/src/Symfony/Component/HttpFoundation/Session/Storage/Proxy/SessionHandlerProxy.php +++ b/src/Symfony/Component/HttpFoundation/Session/Storage/Proxy/SessionHandlerProxy.php @@ -12,8 +12,6 @@ namespace Symfony\Component\HttpFoundation\Session\Storage\Proxy; /** - * SessionHandler proxy. - * * @author Drak */ class SessionHandlerProxy extends AbstractProxy implements \SessionHandlerInterface @@ -24,8 +22,6 @@ class SessionHandlerProxy extends AbstractProxy implements \SessionHandlerInterf protected $handler; /** - * Constructor. - * * @param \SessionHandlerInterface $handler */ public function __construct(\SessionHandlerInterface $handler) diff --git a/src/Symfony/Component/HttpFoundation/StreamedResponse.php b/src/Symfony/Component/HttpFoundation/StreamedResponse.php index 8be624436c1ba..d6b7b9e53aba2 100644 --- a/src/Symfony/Component/HttpFoundation/StreamedResponse.php +++ b/src/Symfony/Component/HttpFoundation/StreamedResponse.php @@ -31,8 +31,6 @@ class StreamedResponse extends Response private $headersSent; /** - * Constructor. - * * @param callable|null $callback A valid PHP callback or null to set it later * @param int $status The response status code * @param array $headers An array of response headers diff --git a/src/Symfony/Component/HttpKernel/Client.php b/src/Symfony/Component/HttpKernel/Client.php index b1814ad1f3e6b..d89fb85dbb10b 100644 --- a/src/Symfony/Component/HttpKernel/Client.php +++ b/src/Symfony/Component/HttpKernel/Client.php @@ -34,8 +34,6 @@ class Client extends BaseClient protected $kernel; /** - * Constructor. - * * @param HttpKernelInterface $kernel An HttpKernel instance * @param array $server The server parameters (equivalent of $_SERVER) * @param History $history A History instance to store the browser history diff --git a/src/Symfony/Component/HttpKernel/Config/EnvParametersResource.php b/src/Symfony/Component/HttpKernel/Config/EnvParametersResource.php index 5f54450137a71..bf1e58344304e 100644 --- a/src/Symfony/Component/HttpKernel/Config/EnvParametersResource.php +++ b/src/Symfony/Component/HttpKernel/Config/EnvParametersResource.php @@ -31,8 +31,6 @@ class EnvParametersResource implements ResourceInterface, \Serializable private $variables; /** - * Constructor. - * * @param string $prefix */ public function __construct($prefix) diff --git a/src/Symfony/Component/HttpKernel/Config/FileLocator.php b/src/Symfony/Component/HttpKernel/Config/FileLocator.php index 169c9ad6e502a..fb1f913bdff5d 100644 --- a/src/Symfony/Component/HttpKernel/Config/FileLocator.php +++ b/src/Symfony/Component/HttpKernel/Config/FileLocator.php @@ -25,8 +25,6 @@ class FileLocator extends BaseFileLocator private $path; /** - * Constructor. - * * @param KernelInterface $kernel A KernelInterface instance * @param null|string $path The path the global resource directory * @param array $paths An array of paths where to look for resources diff --git a/src/Symfony/Component/HttpKernel/Controller/ControllerReference.php b/src/Symfony/Component/HttpKernel/Controller/ControllerReference.php index 3d1592e83aee1..fae4e7fa449bc 100644 --- a/src/Symfony/Component/HttpKernel/Controller/ControllerReference.php +++ b/src/Symfony/Component/HttpKernel/Controller/ControllerReference.php @@ -31,8 +31,6 @@ class ControllerReference public $query = array(); /** - * Constructor. - * * @param string $controller The controller name * @param array $attributes An array of parameters to add to the Request attributes * @param array $query An array of parameters to add to the Request query string diff --git a/src/Symfony/Component/HttpKernel/Controller/ControllerResolver.php b/src/Symfony/Component/HttpKernel/Controller/ControllerResolver.php index a1cff53535dc1..5d288a4a110e6 100644 --- a/src/Symfony/Component/HttpKernel/Controller/ControllerResolver.php +++ b/src/Symfony/Component/HttpKernel/Controller/ControllerResolver.php @@ -15,8 +15,6 @@ use Symfony\Component\HttpFoundation\Request; /** - * ControllerResolver. - * * This implementation uses the '_controller' request attribute to determine * the controller to execute and uses the request attributes to determine * the controller method arguments. @@ -44,8 +42,6 @@ class ControllerResolver implements ControllerResolverInterface private $supportsScalarTypes; /** - * Constructor. - * * @param LoggerInterface $logger A LoggerInterface instance */ public function __construct(LoggerInterface $logger = null) diff --git a/src/Symfony/Component/HttpKernel/Controller/TraceableControllerResolver.php b/src/Symfony/Component/HttpKernel/Controller/TraceableControllerResolver.php index f8de31cf078c1..2d3d03b231a6f 100644 --- a/src/Symfony/Component/HttpKernel/Controller/TraceableControllerResolver.php +++ b/src/Symfony/Component/HttpKernel/Controller/TraceableControllerResolver.php @@ -15,8 +15,6 @@ use Symfony\Component\HttpFoundation\Request; /** - * TraceableControllerResolver. - * * @author Fabien Potencier */ class TraceableControllerResolver implements ControllerResolverInterface @@ -25,8 +23,6 @@ class TraceableControllerResolver implements ControllerResolverInterface private $stopwatch; /** - * Constructor. - * * @param ControllerResolverInterface $resolver A ControllerResolverInterface instance * @param Stopwatch $stopwatch A Stopwatch instance */ diff --git a/src/Symfony/Component/HttpKernel/DataCollector/ConfigDataCollector.php b/src/Symfony/Component/HttpKernel/DataCollector/ConfigDataCollector.php index 395fee3929993..d17e32687a0ab 100644 --- a/src/Symfony/Component/HttpKernel/DataCollector/ConfigDataCollector.php +++ b/src/Symfony/Component/HttpKernel/DataCollector/ConfigDataCollector.php @@ -17,8 +17,6 @@ use Symfony\Component\HttpFoundation\Response; /** - * ConfigDataCollector. - * * @author Fabien Potencier */ class ConfigDataCollector extends DataCollector @@ -32,8 +30,6 @@ class ConfigDataCollector extends DataCollector private $cacheVersionInfo = true; /** - * Constructor. - * * @param string $name The name of the application using the web profiler * @param string $version The version of the application using the web profiler */ diff --git a/src/Symfony/Component/HttpKernel/DependencyInjection/ContainerAwareHttpKernel.php b/src/Symfony/Component/HttpKernel/DependencyInjection/ContainerAwareHttpKernel.php index 4b3e218b85c58..189052b5f1c7e 100644 --- a/src/Symfony/Component/HttpKernel/DependencyInjection/ContainerAwareHttpKernel.php +++ b/src/Symfony/Component/HttpKernel/DependencyInjection/ContainerAwareHttpKernel.php @@ -33,8 +33,6 @@ class ContainerAwareHttpKernel extends HttpKernel protected $container; /** - * Constructor. - * * @param EventDispatcherInterface $dispatcher An EventDispatcherInterface instance * @param ContainerInterface $container A ContainerInterface instance * @param ControllerResolverInterface $controllerResolver A ControllerResolverInterface instance diff --git a/src/Symfony/Component/HttpKernel/EventListener/FragmentListener.php b/src/Symfony/Component/HttpKernel/EventListener/FragmentListener.php index ad6349286dde7..5c72bae54ed72 100644 --- a/src/Symfony/Component/HttpKernel/EventListener/FragmentListener.php +++ b/src/Symfony/Component/HttpKernel/EventListener/FragmentListener.php @@ -35,8 +35,6 @@ class FragmentListener implements EventSubscriberInterface private $fragmentPath; /** - * Constructor. - * * @param UriSigner $signer A UriSigner instance * @param string $fragmentPath The path that triggers this listener */ diff --git a/src/Symfony/Component/HttpKernel/EventListener/ProfilerListener.php b/src/Symfony/Component/HttpKernel/EventListener/ProfilerListener.php index 06a5bbf08bbfb..d4c515e293932 100644 --- a/src/Symfony/Component/HttpKernel/EventListener/ProfilerListener.php +++ b/src/Symfony/Component/HttpKernel/EventListener/ProfilerListener.php @@ -39,8 +39,6 @@ class ProfilerListener implements EventSubscriberInterface protected $parents; /** - * Constructor. - * * @param Profiler $profiler A Profiler instance * @param RequestMatcherInterface|null $matcher A RequestMatcher instance * @param bool $onlyException true if the profiler only collects data when an exception occurs, false otherwise diff --git a/src/Symfony/Component/HttpKernel/EventListener/RouterListener.php b/src/Symfony/Component/HttpKernel/EventListener/RouterListener.php index 297aab6fa12b2..758a76ed6540d 100644 --- a/src/Symfony/Component/HttpKernel/EventListener/RouterListener.php +++ b/src/Symfony/Component/HttpKernel/EventListener/RouterListener.php @@ -46,8 +46,6 @@ class RouterListener implements EventSubscriberInterface private $requestStack; /** - * Constructor. - * * RequestStack will become required in 3.0. * * @param UrlMatcherInterface|RequestMatcherInterface $matcher The Url or Request matcher diff --git a/src/Symfony/Component/HttpKernel/EventListener/SurrogateListener.php b/src/Symfony/Component/HttpKernel/EventListener/SurrogateListener.php index dc815a216f6c0..b68019a62794b 100644 --- a/src/Symfony/Component/HttpKernel/EventListener/SurrogateListener.php +++ b/src/Symfony/Component/HttpKernel/EventListener/SurrogateListener.php @@ -26,8 +26,6 @@ class SurrogateListener implements EventSubscriberInterface private $surrogate; /** - * Constructor. - * * @param SurrogateInterface $surrogate An SurrogateInterface instance */ public function __construct(SurrogateInterface $surrogate = null) diff --git a/src/Symfony/Component/HttpKernel/Exception/AccessDeniedHttpException.php b/src/Symfony/Component/HttpKernel/Exception/AccessDeniedHttpException.php index 79d8639a5f7d3..39418842666b2 100644 --- a/src/Symfony/Component/HttpKernel/Exception/AccessDeniedHttpException.php +++ b/src/Symfony/Component/HttpKernel/Exception/AccessDeniedHttpException.php @@ -12,16 +12,12 @@ namespace Symfony\Component\HttpKernel\Exception; /** - * AccessDeniedHttpException. - * * @author Fabien Potencier * @author Christophe Coevoet */ class AccessDeniedHttpException extends HttpException { /** - * Constructor. - * * @param string $message The internal exception message * @param \Exception $previous The previous exception * @param int $code The internal exception code diff --git a/src/Symfony/Component/HttpKernel/Exception/BadRequestHttpException.php b/src/Symfony/Component/HttpKernel/Exception/BadRequestHttpException.php index 5f68172a8d44e..c28d83739c7a5 100644 --- a/src/Symfony/Component/HttpKernel/Exception/BadRequestHttpException.php +++ b/src/Symfony/Component/HttpKernel/Exception/BadRequestHttpException.php @@ -12,15 +12,11 @@ namespace Symfony\Component\HttpKernel\Exception; /** - * BadRequestHttpException. - * * @author Ben Ramsey */ class BadRequestHttpException extends HttpException { /** - * Constructor. - * * @param string $message The internal exception message * @param \Exception $previous The previous exception * @param int $code The internal exception code diff --git a/src/Symfony/Component/HttpKernel/Exception/ConflictHttpException.php b/src/Symfony/Component/HttpKernel/Exception/ConflictHttpException.php index 34d738ed12030..79f24f2e56dc0 100644 --- a/src/Symfony/Component/HttpKernel/Exception/ConflictHttpException.php +++ b/src/Symfony/Component/HttpKernel/Exception/ConflictHttpException.php @@ -12,15 +12,11 @@ namespace Symfony\Component\HttpKernel\Exception; /** - * ConflictHttpException. - * * @author Ben Ramsey */ class ConflictHttpException extends HttpException { /** - * Constructor. - * * @param string $message The internal exception message * @param \Exception $previous The previous exception * @param int $code The internal exception code diff --git a/src/Symfony/Component/HttpKernel/Exception/GoneHttpException.php b/src/Symfony/Component/HttpKernel/Exception/GoneHttpException.php index 16ea223fae558..84e6915df70f7 100644 --- a/src/Symfony/Component/HttpKernel/Exception/GoneHttpException.php +++ b/src/Symfony/Component/HttpKernel/Exception/GoneHttpException.php @@ -12,15 +12,11 @@ namespace Symfony\Component\HttpKernel\Exception; /** - * GoneHttpException. - * * @author Ben Ramsey */ class GoneHttpException extends HttpException { /** - * Constructor. - * * @param string $message The internal exception message * @param \Exception $previous The previous exception * @param int $code The internal exception code diff --git a/src/Symfony/Component/HttpKernel/Exception/LengthRequiredHttpException.php b/src/Symfony/Component/HttpKernel/Exception/LengthRequiredHttpException.php index 0c4b9431f4b9f..645efe87d7c23 100644 --- a/src/Symfony/Component/HttpKernel/Exception/LengthRequiredHttpException.php +++ b/src/Symfony/Component/HttpKernel/Exception/LengthRequiredHttpException.php @@ -12,15 +12,11 @@ namespace Symfony\Component\HttpKernel\Exception; /** - * LengthRequiredHttpException. - * * @author Ben Ramsey */ class LengthRequiredHttpException extends HttpException { /** - * Constructor. - * * @param string $message The internal exception message * @param \Exception $previous The previous exception * @param int $code The internal exception code diff --git a/src/Symfony/Component/HttpKernel/Exception/MethodNotAllowedHttpException.php b/src/Symfony/Component/HttpKernel/Exception/MethodNotAllowedHttpException.php index 78dd26bf0fd8f..e308a5fee2767 100644 --- a/src/Symfony/Component/HttpKernel/Exception/MethodNotAllowedHttpException.php +++ b/src/Symfony/Component/HttpKernel/Exception/MethodNotAllowedHttpException.php @@ -12,15 +12,11 @@ namespace Symfony\Component\HttpKernel\Exception; /** - * MethodNotAllowedHttpException. - * * @author Kris Wallsmith */ class MethodNotAllowedHttpException extends HttpException { /** - * Constructor. - * * @param array $allow An array of allowed methods * @param string $message The internal exception message * @param \Exception $previous The previous exception diff --git a/src/Symfony/Component/HttpKernel/Exception/NotAcceptableHttpException.php b/src/Symfony/Component/HttpKernel/Exception/NotAcceptableHttpException.php index cc6be4ba45a7d..097a13fd9bc05 100644 --- a/src/Symfony/Component/HttpKernel/Exception/NotAcceptableHttpException.php +++ b/src/Symfony/Component/HttpKernel/Exception/NotAcceptableHttpException.php @@ -12,15 +12,11 @@ namespace Symfony\Component\HttpKernel\Exception; /** - * NotAcceptableHttpException. - * * @author Ben Ramsey */ class NotAcceptableHttpException extends HttpException { /** - * Constructor. - * * @param string $message The internal exception message * @param \Exception $previous The previous exception * @param int $code The internal exception code diff --git a/src/Symfony/Component/HttpKernel/Exception/NotFoundHttpException.php b/src/Symfony/Component/HttpKernel/Exception/NotFoundHttpException.php index 4639e379b90fc..878173cc7b9ac 100644 --- a/src/Symfony/Component/HttpKernel/Exception/NotFoundHttpException.php +++ b/src/Symfony/Component/HttpKernel/Exception/NotFoundHttpException.php @@ -12,15 +12,11 @@ namespace Symfony\Component\HttpKernel\Exception; /** - * NotFoundHttpException. - * * @author Fabien Potencier */ class NotFoundHttpException extends HttpException { /** - * Constructor. - * * @param string $message The internal exception message * @param \Exception $previous The previous exception * @param int $code The internal exception code diff --git a/src/Symfony/Component/HttpKernel/Exception/PreconditionFailedHttpException.php b/src/Symfony/Component/HttpKernel/Exception/PreconditionFailedHttpException.php index 9df0e7b49aa9b..9f13a624cc0fb 100644 --- a/src/Symfony/Component/HttpKernel/Exception/PreconditionFailedHttpException.php +++ b/src/Symfony/Component/HttpKernel/Exception/PreconditionFailedHttpException.php @@ -12,15 +12,11 @@ namespace Symfony\Component\HttpKernel\Exception; /** - * PreconditionFailedHttpException. - * * @author Ben Ramsey */ class PreconditionFailedHttpException extends HttpException { /** - * Constructor. - * * @param string $message The internal exception message * @param \Exception $previous The previous exception * @param int $code The internal exception code diff --git a/src/Symfony/Component/HttpKernel/Exception/PreconditionRequiredHttpException.php b/src/Symfony/Component/HttpKernel/Exception/PreconditionRequiredHttpException.php index 08ebca2241e00..9d0a36d7d34d6 100644 --- a/src/Symfony/Component/HttpKernel/Exception/PreconditionRequiredHttpException.php +++ b/src/Symfony/Component/HttpKernel/Exception/PreconditionRequiredHttpException.php @@ -12,8 +12,6 @@ namespace Symfony\Component\HttpKernel\Exception; /** - * PreconditionRequiredHttpException. - * * @author Ben Ramsey * * @see http://tools.ietf.org/html/rfc6585 @@ -21,8 +19,6 @@ class PreconditionRequiredHttpException extends HttpException { /** - * Constructor. - * * @param string $message The internal exception message * @param \Exception $previous The previous exception * @param int $code The internal exception code diff --git a/src/Symfony/Component/HttpKernel/Exception/ServiceUnavailableHttpException.php b/src/Symfony/Component/HttpKernel/Exception/ServiceUnavailableHttpException.php index 32b9e2d261218..b2767c3fd5bcc 100644 --- a/src/Symfony/Component/HttpKernel/Exception/ServiceUnavailableHttpException.php +++ b/src/Symfony/Component/HttpKernel/Exception/ServiceUnavailableHttpException.php @@ -12,15 +12,11 @@ namespace Symfony\Component\HttpKernel\Exception; /** - * ServiceUnavailableHttpException. - * * @author Ben Ramsey */ class ServiceUnavailableHttpException extends HttpException { /** - * Constructor. - * * @param int|string $retryAfter The number of seconds or HTTP-date after which the request may be retried * @param string $message The internal exception message * @param \Exception $previous The previous exception diff --git a/src/Symfony/Component/HttpKernel/Exception/TooManyRequestsHttpException.php b/src/Symfony/Component/HttpKernel/Exception/TooManyRequestsHttpException.php index ab86e0920bc69..7d8a803323b7c 100644 --- a/src/Symfony/Component/HttpKernel/Exception/TooManyRequestsHttpException.php +++ b/src/Symfony/Component/HttpKernel/Exception/TooManyRequestsHttpException.php @@ -12,8 +12,6 @@ namespace Symfony\Component\HttpKernel\Exception; /** - * TooManyRequestsHttpException. - * * @author Ben Ramsey * * @see http://tools.ietf.org/html/rfc6585 @@ -21,8 +19,6 @@ class TooManyRequestsHttpException extends HttpException { /** - * Constructor. - * * @param int|string $retryAfter The number of seconds or HTTP-date after which the request may be retried * @param string $message The internal exception message * @param \Exception $previous The previous exception diff --git a/src/Symfony/Component/HttpKernel/Exception/UnauthorizedHttpException.php b/src/Symfony/Component/HttpKernel/Exception/UnauthorizedHttpException.php index 0dfe42db97280..05ac875c552e2 100644 --- a/src/Symfony/Component/HttpKernel/Exception/UnauthorizedHttpException.php +++ b/src/Symfony/Component/HttpKernel/Exception/UnauthorizedHttpException.php @@ -12,15 +12,11 @@ namespace Symfony\Component\HttpKernel\Exception; /** - * UnauthorizedHttpException. - * * @author Ben Ramsey */ class UnauthorizedHttpException extends HttpException { /** - * Constructor. - * * @param string $challenge WWW-Authenticate challenge string * @param string $message The internal exception message * @param \Exception $previous The previous exception diff --git a/src/Symfony/Component/HttpKernel/Exception/UnprocessableEntityHttpException.php b/src/Symfony/Component/HttpKernel/Exception/UnprocessableEntityHttpException.php index eb13f563f6cbb..01b8b8465a1a3 100644 --- a/src/Symfony/Component/HttpKernel/Exception/UnprocessableEntityHttpException.php +++ b/src/Symfony/Component/HttpKernel/Exception/UnprocessableEntityHttpException.php @@ -12,15 +12,11 @@ namespace Symfony\Component\HttpKernel\Exception; /** - * UnprocessableEntityHttpException. - * * @author Steve Hutchins */ class UnprocessableEntityHttpException extends HttpException { /** - * Constructor. - * * @param string $message The internal exception message * @param \Exception $previous The previous exception * @param int $code The internal exception code diff --git a/src/Symfony/Component/HttpKernel/Exception/UnsupportedMediaTypeHttpException.php b/src/Symfony/Component/HttpKernel/Exception/UnsupportedMediaTypeHttpException.php index a9d8fa086f13c..6913504e832dc 100644 --- a/src/Symfony/Component/HttpKernel/Exception/UnsupportedMediaTypeHttpException.php +++ b/src/Symfony/Component/HttpKernel/Exception/UnsupportedMediaTypeHttpException.php @@ -12,15 +12,11 @@ namespace Symfony\Component\HttpKernel\Exception; /** - * UnsupportedMediaTypeHttpException. - * * @author Ben Ramsey */ class UnsupportedMediaTypeHttpException extends HttpException { /** - * Constructor. - * * @param string $message The internal exception message * @param \Exception $previous The previous exception * @param int $code The internal exception code diff --git a/src/Symfony/Component/HttpKernel/Fragment/AbstractSurrogateFragmentRenderer.php b/src/Symfony/Component/HttpKernel/Fragment/AbstractSurrogateFragmentRenderer.php index 1968001a86b98..07eda6f1c1c06 100644 --- a/src/Symfony/Component/HttpKernel/Fragment/AbstractSurrogateFragmentRenderer.php +++ b/src/Symfony/Component/HttpKernel/Fragment/AbstractSurrogateFragmentRenderer.php @@ -29,8 +29,6 @@ abstract class AbstractSurrogateFragmentRenderer extends RoutableFragmentRendere private $signer; /** - * Constructor. - * * The "fallback" strategy when surrogate is not available should always be an * instance of InlineFragmentRenderer. * diff --git a/src/Symfony/Component/HttpKernel/Fragment/FragmentHandler.php b/src/Symfony/Component/HttpKernel/Fragment/FragmentHandler.php index 774870a273a35..108ebd5388e6b 100644 --- a/src/Symfony/Component/HttpKernel/Fragment/FragmentHandler.php +++ b/src/Symfony/Component/HttpKernel/Fragment/FragmentHandler.php @@ -40,8 +40,6 @@ class FragmentHandler private $requestStack; /** - * Constructor. - * * RequestStack will become required in 3.0. * * @param FragmentRendererInterface[] $renderers An array of FragmentRendererInterface instances diff --git a/src/Symfony/Component/HttpKernel/Fragment/HIncludeFragmentRenderer.php b/src/Symfony/Component/HttpKernel/Fragment/HIncludeFragmentRenderer.php index e7d4aedb16404..3252f061e5fc7 100644 --- a/src/Symfony/Component/HttpKernel/Fragment/HIncludeFragmentRenderer.php +++ b/src/Symfony/Component/HttpKernel/Fragment/HIncludeFragmentRenderer.php @@ -33,8 +33,6 @@ class HIncludeFragmentRenderer extends RoutableFragmentRenderer private $charset; /** - * Constructor. - * * @param EngineInterface|Environment $templating An EngineInterface or a Twig instance * @param UriSigner $signer A UriSigner instance * @param string $globalDefaultTemplate The global default content (it can be a template name or the content) diff --git a/src/Symfony/Component/HttpKernel/Fragment/InlineFragmentRenderer.php b/src/Symfony/Component/HttpKernel/Fragment/InlineFragmentRenderer.php index a61b239c158b9..8170ceeb91943 100644 --- a/src/Symfony/Component/HttpKernel/Fragment/InlineFragmentRenderer.php +++ b/src/Symfony/Component/HttpKernel/Fragment/InlineFragmentRenderer.php @@ -30,8 +30,6 @@ class InlineFragmentRenderer extends RoutableFragmentRenderer private $dispatcher; /** - * Constructor. - * * @param HttpKernelInterface $kernel A HttpKernelInterface instance * @param EventDispatcherInterface $dispatcher A EventDispatcherInterface instance */ diff --git a/src/Symfony/Component/HttpKernel/HttpCache/Esi.php b/src/Symfony/Component/HttpKernel/HttpCache/Esi.php index 457793953d1f1..9b17b4fc54039 100644 --- a/src/Symfony/Component/HttpKernel/HttpCache/Esi.php +++ b/src/Symfony/Component/HttpKernel/HttpCache/Esi.php @@ -35,8 +35,6 @@ class Esi implements SurrogateInterface ); /** - * Constructor. - * * @param array $contentTypes An array of content-type that should be parsed for ESI information * (default: text/html, text/xml, application/xhtml+xml, and application/xml) */ diff --git a/src/Symfony/Component/HttpKernel/HttpCache/HttpCache.php b/src/Symfony/Component/HttpKernel/HttpCache/HttpCache.php index 941d4c6fa033d..a2a1d11ea3d59 100644 --- a/src/Symfony/Component/HttpKernel/HttpCache/HttpCache.php +++ b/src/Symfony/Component/HttpKernel/HttpCache/HttpCache.php @@ -36,8 +36,6 @@ class HttpCache implements HttpKernelInterface, TerminableInterface private $traces = array(); /** - * Constructor. - * * The available options are: * * * debug: If true, the traces are added as a HTTP header to ease debugging diff --git a/src/Symfony/Component/HttpKernel/HttpCache/Ssi.php b/src/Symfony/Component/HttpKernel/HttpCache/Ssi.php index 5f7ee10a5bf60..e7a70c19a23e1 100644 --- a/src/Symfony/Component/HttpKernel/HttpCache/Ssi.php +++ b/src/Symfony/Component/HttpKernel/HttpCache/Ssi.php @@ -29,8 +29,6 @@ class Ssi implements SurrogateInterface ); /** - * Constructor. - * * @param array $contentTypes An array of content-type that should be parsed for SSI information * (default: text/html, text/xml, application/xhtml+xml, and application/xml) */ diff --git a/src/Symfony/Component/HttpKernel/HttpCache/Store.php b/src/Symfony/Component/HttpKernel/HttpCache/Store.php index c4d961e68f043..b656e28d99442 100644 --- a/src/Symfony/Component/HttpKernel/HttpCache/Store.php +++ b/src/Symfony/Component/HttpKernel/HttpCache/Store.php @@ -29,8 +29,6 @@ class Store implements StoreInterface private $locks; /** - * Constructor. - * * @param string $root The path to the cache directory * * @throws \RuntimeException diff --git a/src/Symfony/Component/HttpKernel/HttpKernel.php b/src/Symfony/Component/HttpKernel/HttpKernel.php index 4e628a1409beb..cb32e597bd34b 100644 --- a/src/Symfony/Component/HttpKernel/HttpKernel.php +++ b/src/Symfony/Component/HttpKernel/HttpKernel.php @@ -40,8 +40,6 @@ class HttpKernel implements HttpKernelInterface, TerminableInterface protected $requestStack; /** - * Constructor. - * * @param EventDispatcherInterface $dispatcher An EventDispatcherInterface instance * @param ControllerResolverInterface $resolver A ControllerResolverInterface instance * @param RequestStack $requestStack A stack for master/sub requests diff --git a/src/Symfony/Component/HttpKernel/Kernel.php b/src/Symfony/Component/HttpKernel/Kernel.php index 401a3626d84b4..83d384dfc49b7 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -69,8 +69,6 @@ abstract class Kernel implements KernelInterface, TerminableInterface const END_OF_LIFE = '05/2019'; /** - * Constructor. - * * @param string $environment The environment * @param bool $debug Whether to enable debugging or not */ diff --git a/src/Symfony/Component/HttpKernel/Profiler/BaseMemcacheProfilerStorage.php b/src/Symfony/Component/HttpKernel/Profiler/BaseMemcacheProfilerStorage.php index c6395bd67a2d0..d0f815955eda6 100644 --- a/src/Symfony/Component/HttpKernel/Profiler/BaseMemcacheProfilerStorage.php +++ b/src/Symfony/Component/HttpKernel/Profiler/BaseMemcacheProfilerStorage.php @@ -24,8 +24,6 @@ abstract class BaseMemcacheProfilerStorage implements ProfilerStorageInterface protected $lifetime; /** - * Constructor. - * * @param string $dsn A data source name * @param string $username * @param string $password diff --git a/src/Symfony/Component/HttpKernel/Profiler/MongoDbProfilerStorage.php b/src/Symfony/Component/HttpKernel/Profiler/MongoDbProfilerStorage.php index f35a7f74199b3..3a4fa7b79a403 100644 --- a/src/Symfony/Component/HttpKernel/Profiler/MongoDbProfilerStorage.php +++ b/src/Symfony/Component/HttpKernel/Profiler/MongoDbProfilerStorage.php @@ -18,8 +18,6 @@ class MongoDbProfilerStorage implements ProfilerStorageInterface private $mongo; /** - * Constructor. - * * @param string $dsn A data source name * @param string $username Not used * @param string $password Not used diff --git a/src/Symfony/Component/HttpKernel/Profiler/PdoProfilerStorage.php b/src/Symfony/Component/HttpKernel/Profiler/PdoProfilerStorage.php index dc273dd97a43a..55dcb30ded984 100644 --- a/src/Symfony/Component/HttpKernel/Profiler/PdoProfilerStorage.php +++ b/src/Symfony/Component/HttpKernel/Profiler/PdoProfilerStorage.php @@ -26,8 +26,6 @@ abstract class PdoProfilerStorage implements ProfilerStorageInterface protected $db; /** - * Constructor. - * * @param string $dsn A data source name * @param string $username The username for the database * @param string $password The password for the database diff --git a/src/Symfony/Component/HttpKernel/Profiler/Profile.php b/src/Symfony/Component/HttpKernel/Profiler/Profile.php index 9e0c9fb7dabdd..ad42652d5d8a3 100644 --- a/src/Symfony/Component/HttpKernel/Profiler/Profile.php +++ b/src/Symfony/Component/HttpKernel/Profiler/Profile.php @@ -44,8 +44,6 @@ class Profile private $children = array(); /** - * Constructor. - * * @param string $token The token */ public function __construct($token) diff --git a/src/Symfony/Component/HttpKernel/Profiler/Profiler.php b/src/Symfony/Component/HttpKernel/Profiler/Profiler.php index 9bfc54e1a19cf..2ff0beaf62019 100644 --- a/src/Symfony/Component/HttpKernel/Profiler/Profiler.php +++ b/src/Symfony/Component/HttpKernel/Profiler/Profiler.php @@ -46,8 +46,6 @@ class Profiler private $enabled = true; /** - * Constructor. - * * @param ProfilerStorageInterface $storage A ProfilerStorageInterface instance * @param LoggerInterface $logger A LoggerInterface instance */ diff --git a/src/Symfony/Component/HttpKernel/Profiler/RedisProfilerStorage.php b/src/Symfony/Component/HttpKernel/Profiler/RedisProfilerStorage.php index b0e14ea456291..0471e87341b60 100644 --- a/src/Symfony/Component/HttpKernel/Profiler/RedisProfilerStorage.php +++ b/src/Symfony/Component/HttpKernel/Profiler/RedisProfilerStorage.php @@ -35,8 +35,6 @@ class RedisProfilerStorage implements ProfilerStorageInterface private $redis; /** - * Constructor. - * * @param string $dsn A data source name * @param string $username Not used * @param string $password Not used diff --git a/src/Symfony/Component/HttpKernel/UriSigner.php b/src/Symfony/Component/HttpKernel/UriSigner.php index fa84899064e88..a64bf2c4460b5 100644 --- a/src/Symfony/Component/HttpKernel/UriSigner.php +++ b/src/Symfony/Component/HttpKernel/UriSigner.php @@ -21,8 +21,6 @@ class UriSigner private $secret; /** - * Constructor. - * * @param string $secret A secret */ public function __construct($secret) diff --git a/src/Symfony/Component/Intl/Collator/Collator.php b/src/Symfony/Component/Intl/Collator/Collator.php index 6d79bf30ecc31..2e281951e3e2b 100644 --- a/src/Symfony/Component/Intl/Collator/Collator.php +++ b/src/Symfony/Component/Intl/Collator/Collator.php @@ -68,8 +68,6 @@ class Collator const SORT_STRING = 1; /** - * Constructor. - * * @param string $locale The locale code. The only currently supported locale is "en" (or null using the default locale, i.e. "en") * * @throws MethodArgumentValueNotImplementedException When $locale different than "en" or null is passed diff --git a/src/Symfony/Component/Intl/DateFormatter/DateFormat/FullTransformer.php b/src/Symfony/Component/Intl/DateFormatter/DateFormat/FullTransformer.php index 958ba95c7cd69..35373bb6c3a4e 100644 --- a/src/Symfony/Component/Intl/DateFormatter/DateFormat/FullTransformer.php +++ b/src/Symfony/Component/Intl/DateFormatter/DateFormat/FullTransformer.php @@ -35,8 +35,6 @@ class FullTransformer private $timezone; /** - * Constructor. - * * @param string $pattern The pattern to be used to format and/or parse values * @param string $timezone The timezone to perform the date/time calculations */ diff --git a/src/Symfony/Component/Intl/DateFormatter/DateFormat/MonthTransformer.php b/src/Symfony/Component/Intl/DateFormatter/DateFormat/MonthTransformer.php index 4b02c85b24e30..3cb7fd162ead8 100644 --- a/src/Symfony/Component/Intl/DateFormatter/DateFormat/MonthTransformer.php +++ b/src/Symfony/Component/Intl/DateFormatter/DateFormat/MonthTransformer.php @@ -57,9 +57,6 @@ class MonthTransformer extends Transformer */ protected static $flippedShortMonths = array(); - /** - * Constructor. - */ public function __construct() { if (0 === count(self::$shortMonths)) { diff --git a/src/Symfony/Component/Intl/DateFormatter/IntlDateFormatter.php b/src/Symfony/Component/Intl/DateFormatter/IntlDateFormatter.php index 438b4d73e943b..a59becfddfba4 100644 --- a/src/Symfony/Component/Intl/DateFormatter/IntlDateFormatter.php +++ b/src/Symfony/Component/Intl/DateFormatter/IntlDateFormatter.php @@ -127,8 +127,6 @@ class IntlDateFormatter private $timeZoneId; /** - * Constructor. - * * @param string $locale The locale code. The only currently supported locale is "en" (or null using the default locale, i.e. "en") * @param int $datetype Type of date formatting, one of the format type constants * @param int $timetype Type of time formatting, one of the format type constants diff --git a/src/Symfony/Component/Intl/Exception/MethodArgumentNotImplementedException.php b/src/Symfony/Component/Intl/Exception/MethodArgumentNotImplementedException.php index 3a86da888088e..f3ed0fa928594 100644 --- a/src/Symfony/Component/Intl/Exception/MethodArgumentNotImplementedException.php +++ b/src/Symfony/Component/Intl/Exception/MethodArgumentNotImplementedException.php @@ -17,8 +17,6 @@ class MethodArgumentNotImplementedException extends NotImplementedException { /** - * Constructor. - * * @param string $methodName The method name that raised the exception * @param string $argName The argument name that is not implemented */ diff --git a/src/Symfony/Component/Intl/Exception/MethodArgumentValueNotImplementedException.php b/src/Symfony/Component/Intl/Exception/MethodArgumentValueNotImplementedException.php index 3193483dfe88a..53b62576843fd 100644 --- a/src/Symfony/Component/Intl/Exception/MethodArgumentValueNotImplementedException.php +++ b/src/Symfony/Component/Intl/Exception/MethodArgumentValueNotImplementedException.php @@ -17,8 +17,6 @@ class MethodArgumentValueNotImplementedException extends NotImplementedException { /** - * Constructor. - * * @param string $methodName The method name that raised the exception * @param string $argName The argument name * @param string $argValue The argument value that is not implemented diff --git a/src/Symfony/Component/Intl/Exception/MethodNotImplementedException.php b/src/Symfony/Component/Intl/Exception/MethodNotImplementedException.php index 97b7986bdee92..544e0e40a4821 100644 --- a/src/Symfony/Component/Intl/Exception/MethodNotImplementedException.php +++ b/src/Symfony/Component/Intl/Exception/MethodNotImplementedException.php @@ -17,8 +17,6 @@ class MethodNotImplementedException extends NotImplementedException { /** - * Constructor. - * * @param string $methodName The name of the method */ public function __construct($methodName) diff --git a/src/Symfony/Component/Intl/Exception/NotImplementedException.php b/src/Symfony/Component/Intl/Exception/NotImplementedException.php index cf919fecad22e..47ac32b3201e9 100644 --- a/src/Symfony/Component/Intl/Exception/NotImplementedException.php +++ b/src/Symfony/Component/Intl/Exception/NotImplementedException.php @@ -21,8 +21,6 @@ class NotImplementedException extends RuntimeException const INTL_INSTALL_MESSAGE = 'Please install the "intl" extension for full localization capabilities.'; /** - * Constructor. - * * @param string $message The exception message. A note to install the intl extension is appended to this string */ public function __construct($message) diff --git a/src/Symfony/Component/Intl/NumberFormatter/NumberFormatter.php b/src/Symfony/Component/Intl/NumberFormatter/NumberFormatter.php index ce03e9f5d6642..d3c7d5b476e77 100644 --- a/src/Symfony/Component/Intl/NumberFormatter/NumberFormatter.php +++ b/src/Symfony/Component/Intl/NumberFormatter/NumberFormatter.php @@ -255,8 +255,6 @@ class NumberFormatter ); /** - * Constructor. - * * @param string $locale The locale code. The only currently supported locale is "en" (or null using the default locale, i.e. "en") * @param int $style Style of the formatting, one of the format style constants * The only supported styles are NumberFormatter::DECIMAL diff --git a/src/Symfony/Component/Process/PhpProcess.php b/src/Symfony/Component/Process/PhpProcess.php index 42ecb66f2bd4d..3ecde89749cc2 100644 --- a/src/Symfony/Component/Process/PhpProcess.php +++ b/src/Symfony/Component/Process/PhpProcess.php @@ -25,8 +25,6 @@ class PhpProcess extends Process { /** - * Constructor. - * * @param string $script The PHP script to run (as a string) * @param string|null $cwd The working directory or null to use the working dir of the current PHP process * @param array|null $env The environment variables or null to use the same environment as the current PHP process diff --git a/src/Symfony/Component/Process/Process.php b/src/Symfony/Component/Process/Process.php index 96a93343f1d5d..af0bb2bcb2ecd 100644 --- a/src/Symfony/Component/Process/Process.php +++ b/src/Symfony/Component/Process/Process.php @@ -127,8 +127,6 @@ class Process ); /** - * Constructor. - * * @param string $commandline The command line to run * @param string|null $cwd The working directory or null to use the working dir of the current PHP process * @param array|null $env The environment variables or null to use the same environment as the current PHP process diff --git a/src/Symfony/Component/Process/ProcessBuilder.php b/src/Symfony/Component/Process/ProcessBuilder.php index 54877a8282813..3d90f1a5d6d71 100644 --- a/src/Symfony/Component/Process/ProcessBuilder.php +++ b/src/Symfony/Component/Process/ProcessBuilder.php @@ -15,8 +15,6 @@ use Symfony\Component\Process\Exception\LogicException; /** - * Process builder. - * * @author Kris Wallsmith */ class ProcessBuilder @@ -32,8 +30,6 @@ class ProcessBuilder private $outputDisabled = false; /** - * Constructor. - * * @param string[] $arguments An array of arguments */ public function __construct(array $arguments = array()) diff --git a/src/Symfony/Component/PropertyAccess/PropertyPathIterator.php b/src/Symfony/Component/PropertyAccess/PropertyPathIterator.php index b49e77e271835..7ea0fa2455488 100644 --- a/src/Symfony/Component/PropertyAccess/PropertyPathIterator.php +++ b/src/Symfony/Component/PropertyAccess/PropertyPathIterator.php @@ -27,8 +27,6 @@ class PropertyPathIterator extends \ArrayIterator implements PropertyPathIterato protected $path; /** - * Constructor. - * * @param PropertyPathInterface $path The property path to traverse */ public function __construct(PropertyPathInterface $path) diff --git a/src/Symfony/Component/Routing/Annotation/Route.php b/src/Symfony/Component/Routing/Annotation/Route.php index 191aa68a57a18..aec320156b4e8 100644 --- a/src/Symfony/Component/Routing/Annotation/Route.php +++ b/src/Symfony/Component/Routing/Annotation/Route.php @@ -32,8 +32,6 @@ class Route private $condition; /** - * Constructor. - * * @param array $data An array of key/value parameters * * @throws \BadMethodCallException diff --git a/src/Symfony/Component/Routing/CompiledRoute.php b/src/Symfony/Component/Routing/CompiledRoute.php index 3eca9ecd8b010..c95477ae631c1 100644 --- a/src/Symfony/Component/Routing/CompiledRoute.php +++ b/src/Symfony/Component/Routing/CompiledRoute.php @@ -28,8 +28,6 @@ class CompiledRoute implements \Serializable private $hostTokens; /** - * Constructor. - * * @param string $staticPrefix The static prefix of the compiled route * @param string $regex The regular expression to use to match this route * @param array $tokens An array of tokens to use to generate URL for this route diff --git a/src/Symfony/Component/Routing/Generator/Dumper/GeneratorDumper.php b/src/Symfony/Component/Routing/Generator/Dumper/GeneratorDumper.php index 4739bd8365cea..4a7051b5ae797 100644 --- a/src/Symfony/Component/Routing/Generator/Dumper/GeneratorDumper.php +++ b/src/Symfony/Component/Routing/Generator/Dumper/GeneratorDumper.php @@ -26,8 +26,6 @@ abstract class GeneratorDumper implements GeneratorDumperInterface private $routes; /** - * Constructor. - * * @param RouteCollection $routes The RouteCollection to dump */ public function __construct(RouteCollection $routes) diff --git a/src/Symfony/Component/Routing/Generator/Dumper/PhpGeneratorDumper.php b/src/Symfony/Component/Routing/Generator/Dumper/PhpGeneratorDumper.php index 9fd35ea112559..60bdf1da3522c 100644 --- a/src/Symfony/Component/Routing/Generator/Dumper/PhpGeneratorDumper.php +++ b/src/Symfony/Component/Routing/Generator/Dumper/PhpGeneratorDumper.php @@ -46,8 +46,6 @@ public function dump(array $options = array()) use Psr\Log\LoggerInterface; /** - * {$options['class']} - * * This class has been auto-generated * by the Symfony Routing Component. */ @@ -55,9 +53,6 @@ class {$options['class']} extends {$options['base_class']} { private static \$declaredRoutes; - /** - * Constructor. - */ public function __construct(RequestContext \$context, LoggerInterface \$logger = null) { \$this->context = \$context; diff --git a/src/Symfony/Component/Routing/Generator/UrlGenerator.php b/src/Symfony/Component/Routing/Generator/UrlGenerator.php index e72b6cf974c74..11e068fec1367 100644 --- a/src/Symfony/Component/Routing/Generator/UrlGenerator.php +++ b/src/Symfony/Component/Routing/Generator/UrlGenerator.php @@ -76,8 +76,6 @@ class UrlGenerator implements UrlGeneratorInterface, ConfigurableRequirementsInt ); /** - * Constructor. - * * @param RouteCollection $routes A RouteCollection instance * @param RequestContext $context The context * @param LoggerInterface|null $logger A logger instance diff --git a/src/Symfony/Component/Routing/Loader/AnnotationClassLoader.php b/src/Symfony/Component/Routing/Loader/AnnotationClassLoader.php index 62ad9c3f9fae0..8d6e1c19ba47a 100644 --- a/src/Symfony/Component/Routing/Loader/AnnotationClassLoader.php +++ b/src/Symfony/Component/Routing/Loader/AnnotationClassLoader.php @@ -73,8 +73,6 @@ abstract class AnnotationClassLoader implements LoaderInterface protected $defaultRouteIndex = 0; /** - * Constructor. - * * @param Reader $reader */ public function __construct(Reader $reader) diff --git a/src/Symfony/Component/Routing/Loader/AnnotationFileLoader.php b/src/Symfony/Component/Routing/Loader/AnnotationFileLoader.php index d98e024640366..376ad3c585f4f 100644 --- a/src/Symfony/Component/Routing/Loader/AnnotationFileLoader.php +++ b/src/Symfony/Component/Routing/Loader/AnnotationFileLoader.php @@ -27,8 +27,6 @@ class AnnotationFileLoader extends FileLoader protected $loader; /** - * Constructor. - * * @param FileLocatorInterface $locator A FileLocator instance * @param AnnotationClassLoader $loader An AnnotationClassLoader instance * diff --git a/src/Symfony/Component/Routing/Matcher/Dumper/DumperRoute.php b/src/Symfony/Component/Routing/Matcher/Dumper/DumperRoute.php index 3ad08c2006f24..c2e2a116d12d0 100644 --- a/src/Symfony/Component/Routing/Matcher/Dumper/DumperRoute.php +++ b/src/Symfony/Component/Routing/Matcher/Dumper/DumperRoute.php @@ -33,8 +33,6 @@ class DumperRoute private $route; /** - * Constructor. - * * @param string $name The route name * @param Route $route The route */ diff --git a/src/Symfony/Component/Routing/Matcher/Dumper/MatcherDumper.php b/src/Symfony/Component/Routing/Matcher/Dumper/MatcherDumper.php index 52edc017e8473..70c23f647d91d 100644 --- a/src/Symfony/Component/Routing/Matcher/Dumper/MatcherDumper.php +++ b/src/Symfony/Component/Routing/Matcher/Dumper/MatcherDumper.php @@ -26,8 +26,6 @@ abstract class MatcherDumper implements MatcherDumperInterface private $routes; /** - * Constructor. - * * @param RouteCollection $routes The RouteCollection to dump */ public function __construct(RouteCollection $routes) diff --git a/src/Symfony/Component/Routing/Matcher/Dumper/PhpMatcherDumper.php b/src/Symfony/Component/Routing/Matcher/Dumper/PhpMatcherDumper.php index aa7df8a78b5ba..bf629b8f8675b 100644 --- a/src/Symfony/Component/Routing/Matcher/Dumper/PhpMatcherDumper.php +++ b/src/Symfony/Component/Routing/Matcher/Dumper/PhpMatcherDumper.php @@ -63,16 +63,11 @@ public function dump(array $options = array()) use Symfony\Component\Routing\RequestContext; /** - * {$options['class']}. - * * This class has been auto-generated * by the Symfony Routing Component. */ class {$options['class']} extends {$options['base_class']} { - /** - * Constructor. - */ public function __construct(RequestContext \$context) { \$this->context = \$context; diff --git a/src/Symfony/Component/Routing/Matcher/UrlMatcher.php b/src/Symfony/Component/Routing/Matcher/UrlMatcher.php index c646723b3ab08..62bb74a8d6780 100644 --- a/src/Symfony/Component/Routing/Matcher/UrlMatcher.php +++ b/src/Symfony/Component/Routing/Matcher/UrlMatcher.php @@ -55,8 +55,6 @@ class UrlMatcher implements UrlMatcherInterface, RequestMatcherInterface protected $expressionLanguageProviders = array(); /** - * Constructor. - * * @param RouteCollection $routes A RouteCollection instance * @param RequestContext $context The context */ diff --git a/src/Symfony/Component/Routing/RequestContext.php b/src/Symfony/Component/Routing/RequestContext.php index 9b15cd07d54a3..d522189cb0d51 100644 --- a/src/Symfony/Component/Routing/RequestContext.php +++ b/src/Symfony/Component/Routing/RequestContext.php @@ -38,8 +38,6 @@ class RequestContext private $parameters = array(); /** - * Constructor. - * * @param string $baseUrl The base URL * @param string $method The HTTP method * @param string $host The HTTP host name diff --git a/src/Symfony/Component/Routing/Route.php b/src/Symfony/Component/Routing/Route.php index fee2002c9d9bb..4966c16f983c8 100644 --- a/src/Symfony/Component/Routing/Route.php +++ b/src/Symfony/Component/Routing/Route.php @@ -65,8 +65,6 @@ class Route implements \Serializable private $condition = ''; /** - * Constructor. - * * Available options: * * * compiler_class: A class name able to compile this route instance (RouteCompiler by default) diff --git a/src/Symfony/Component/Routing/Router.php b/src/Symfony/Component/Routing/Router.php index a04385ead47d1..afec0f5ed5de8 100644 --- a/src/Symfony/Component/Routing/Router.php +++ b/src/Symfony/Component/Routing/Router.php @@ -84,8 +84,6 @@ class Router implements RouterInterface, RequestMatcherInterface private $expressionLanguageProviders = array(); /** - * Constructor. - * * @param LoaderInterface $loader A LoaderInterface instance * @param mixed $resource The main resource to load * @param array $options An array of options diff --git a/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher1.php b/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher1.php index 4ea0b8a1a3e7c..6fc15819b131e 100644 --- a/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher1.php +++ b/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher1.php @@ -5,16 +5,11 @@ use Symfony\Component\Routing\RequestContext; /** - * ProjectUrlMatcher. - * * This class has been auto-generated * by the Symfony Routing Component. */ class ProjectUrlMatcher extends Symfony\Component\Routing\Matcher\UrlMatcher { - /** - * Constructor. - */ public function __construct(RequestContext $context) { $this->context = $context; diff --git a/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher2.php b/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher2.php index f9d3fa2d8257b..b83d904f6e2ac 100644 --- a/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher2.php +++ b/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher2.php @@ -5,16 +5,11 @@ use Symfony\Component\Routing\RequestContext; /** - * ProjectUrlMatcher. - * * This class has been auto-generated * by the Symfony Routing Component. */ class ProjectUrlMatcher extends Symfony\Component\Routing\Tests\Fixtures\RedirectableUrlMatcher { - /** - * Constructor. - */ public function __construct(RequestContext $context) { $this->context = $context; diff --git a/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher3.php b/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher3.php index d9da7b02d4b43..774767d2ca406 100644 --- a/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher3.php +++ b/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher3.php @@ -5,16 +5,11 @@ use Symfony\Component\Routing\RequestContext; /** - * ProjectUrlMatcher. - * * This class has been auto-generated * by the Symfony Routing Component. */ class ProjectUrlMatcher extends Symfony\Component\Routing\Matcher\UrlMatcher { - /** - * Constructor. - */ public function __construct(RequestContext $context) { $this->context = $context; diff --git a/src/Symfony/Component/Security/Acl/Dbal/AclProvider.php b/src/Symfony/Component/Security/Acl/Dbal/AclProvider.php index 6709023ff0351..d60b82ce9de20 100644 --- a/src/Symfony/Component/Security/Acl/Dbal/AclProvider.php +++ b/src/Symfony/Component/Security/Acl/Dbal/AclProvider.php @@ -57,8 +57,6 @@ class AclProvider implements AclProviderInterface private $permissionGrantingStrategy; /** - * Constructor. - * * @param Connection $connection * @param PermissionGrantingStrategyInterface $permissionGrantingStrategy * @param array $options diff --git a/src/Symfony/Component/Security/Acl/Dbal/Schema.php b/src/Symfony/Component/Security/Acl/Dbal/Schema.php index 864d0091af3ef..b98423cbc84e9 100644 --- a/src/Symfony/Component/Security/Acl/Dbal/Schema.php +++ b/src/Symfony/Component/Security/Acl/Dbal/Schema.php @@ -24,8 +24,6 @@ final class Schema extends BaseSchema private $options; /** - * Constructor. - * * @param array $options the names for tables * @param Connection $connection */ diff --git a/src/Symfony/Component/Security/Acl/Domain/Acl.php b/src/Symfony/Component/Security/Acl/Domain/Acl.php index fb70738ae7f65..a759d5f04793b 100644 --- a/src/Symfony/Component/Security/Acl/Domain/Acl.php +++ b/src/Symfony/Component/Security/Acl/Domain/Acl.php @@ -48,8 +48,6 @@ class Acl implements AuditableAclInterface, NotifyPropertyChanged private $listeners = array(); /** - * Constructor. - * * @param int $id * @param ObjectIdentityInterface $objectIdentity * @param PermissionGrantingStrategyInterface $permissionGrantingStrategy diff --git a/src/Symfony/Component/Security/Acl/Domain/AclCollectionCache.php b/src/Symfony/Component/Security/Acl/Domain/AclCollectionCache.php index 5dfef08839e6e..97ec20f210187 100644 --- a/src/Symfony/Component/Security/Acl/Domain/AclCollectionCache.php +++ b/src/Symfony/Component/Security/Acl/Domain/AclCollectionCache.php @@ -28,8 +28,6 @@ class AclCollectionCache private $securityIdentityRetrievalStrategy; /** - * Constructor. - * * @param AclProviderInterface $aclProvider * @param ObjectIdentityRetrievalStrategyInterface $oidRetrievalStrategy * @param SecurityIdentityRetrievalStrategyInterface $sidRetrievalStrategy diff --git a/src/Symfony/Component/Security/Acl/Domain/DoctrineAclCache.php b/src/Symfony/Component/Security/Acl/Domain/DoctrineAclCache.php index 667a19e0a1ce2..a72622f519ee2 100644 --- a/src/Symfony/Component/Security/Acl/Domain/DoctrineAclCache.php +++ b/src/Symfony/Component/Security/Acl/Domain/DoctrineAclCache.php @@ -32,8 +32,6 @@ class DoctrineAclCache implements AclCacheInterface private $permissionGrantingStrategy; /** - * Constructor. - * * @param Cache $cache * @param PermissionGrantingStrategyInterface $permissionGrantingStrategy * @param string $prefix diff --git a/src/Symfony/Component/Security/Acl/Domain/Entry.php b/src/Symfony/Component/Security/Acl/Domain/Entry.php index 55c4b378a74b2..57795632ad178 100644 --- a/src/Symfony/Component/Security/Acl/Domain/Entry.php +++ b/src/Symfony/Component/Security/Acl/Domain/Entry.php @@ -32,8 +32,6 @@ class Entry implements AuditableEntryInterface private $granting; /** - * Constructor. - * * @param int $id * @param AclInterface $acl * @param SecurityIdentityInterface $sid diff --git a/src/Symfony/Component/Security/Acl/Domain/FieldEntry.php b/src/Symfony/Component/Security/Acl/Domain/FieldEntry.php index 86b1e5b30274b..6f4563ffcc6c4 100644 --- a/src/Symfony/Component/Security/Acl/Domain/FieldEntry.php +++ b/src/Symfony/Component/Security/Acl/Domain/FieldEntry.php @@ -25,8 +25,6 @@ class FieldEntry extends Entry implements FieldEntryInterface private $field; /** - * Constructor. - * * @param int $id * @param AclInterface $acl * @param string $field diff --git a/src/Symfony/Component/Security/Acl/Domain/ObjectIdentity.php b/src/Symfony/Component/Security/Acl/Domain/ObjectIdentity.php index d2f353e653ff9..be524489e7655 100644 --- a/src/Symfony/Component/Security/Acl/Domain/ObjectIdentity.php +++ b/src/Symfony/Component/Security/Acl/Domain/ObjectIdentity.php @@ -27,8 +27,6 @@ final class ObjectIdentity implements ObjectIdentityInterface private $type; /** - * Constructor. - * * @param string $identifier * @param string $type * diff --git a/src/Symfony/Component/Security/Acl/Domain/RoleSecurityIdentity.php b/src/Symfony/Component/Security/Acl/Domain/RoleSecurityIdentity.php index c28a1c522da0d..95d2887ead232 100644 --- a/src/Symfony/Component/Security/Acl/Domain/RoleSecurityIdentity.php +++ b/src/Symfony/Component/Security/Acl/Domain/RoleSecurityIdentity.php @@ -24,8 +24,6 @@ final class RoleSecurityIdentity implements SecurityIdentityInterface private $role; /** - * Constructor. - * * @param mixed $role a Role instance, or its string representation */ public function __construct($role) diff --git a/src/Symfony/Component/Security/Acl/Domain/SecurityIdentityRetrievalStrategy.php b/src/Symfony/Component/Security/Acl/Domain/SecurityIdentityRetrievalStrategy.php index a08f67e295515..cad892f7dc583 100644 --- a/src/Symfony/Component/Security/Acl/Domain/SecurityIdentityRetrievalStrategy.php +++ b/src/Symfony/Component/Security/Acl/Domain/SecurityIdentityRetrievalStrategy.php @@ -29,8 +29,6 @@ class SecurityIdentityRetrievalStrategy implements SecurityIdentityRetrievalStra private $authenticationTrustResolver; /** - * Constructor. - * * @param RoleHierarchyInterface $roleHierarchy * @param AuthenticationTrustResolver $authenticationTrustResolver */ diff --git a/src/Symfony/Component/Security/Acl/Domain/UserSecurityIdentity.php b/src/Symfony/Component/Security/Acl/Domain/UserSecurityIdentity.php index 5766148df0ed6..d6b3d3fcfc477 100644 --- a/src/Symfony/Component/Security/Acl/Domain/UserSecurityIdentity.php +++ b/src/Symfony/Component/Security/Acl/Domain/UserSecurityIdentity.php @@ -27,8 +27,6 @@ final class UserSecurityIdentity implements SecurityIdentityInterface private $class; /** - * Constructor. - * * @param string $username the username representation * @param string $class the user's fully qualified class name * diff --git a/src/Symfony/Component/Security/Acl/Permission/AbstractMaskBuilder.php b/src/Symfony/Component/Security/Acl/Permission/AbstractMaskBuilder.php index 93f1755be6db0..5c50eb6bf6f99 100644 --- a/src/Symfony/Component/Security/Acl/Permission/AbstractMaskBuilder.php +++ b/src/Symfony/Component/Security/Acl/Permission/AbstractMaskBuilder.php @@ -22,8 +22,6 @@ abstract class AbstractMaskBuilder implements MaskBuilderInterface protected $mask; /** - * Constructor. - * * @param int $mask optional; defaults to 0 */ public function __construct($mask = 0) diff --git a/src/Symfony/Component/Security/Core/Authentication/AuthenticationProviderManager.php b/src/Symfony/Component/Security/Core/Authentication/AuthenticationProviderManager.php index 4c0a7459d070c..6d631a62f1ae9 100644 --- a/src/Symfony/Component/Security/Core/Authentication/AuthenticationProviderManager.php +++ b/src/Symfony/Component/Security/Core/Authentication/AuthenticationProviderManager.php @@ -35,8 +35,6 @@ class AuthenticationProviderManager implements AuthenticationManagerInterface private $eventDispatcher; /** - * Constructor. - * * @param AuthenticationProviderInterface[] $providers An array of AuthenticationProviderInterface instances * @param bool $eraseCredentials Whether to erase credentials after authentication or not * diff --git a/src/Symfony/Component/Security/Core/Authentication/AuthenticationTrustResolver.php b/src/Symfony/Component/Security/Core/Authentication/AuthenticationTrustResolver.php index c66661a1a32d1..d191d6d532366 100644 --- a/src/Symfony/Component/Security/Core/Authentication/AuthenticationTrustResolver.php +++ b/src/Symfony/Component/Security/Core/Authentication/AuthenticationTrustResolver.php @@ -24,8 +24,6 @@ class AuthenticationTrustResolver implements AuthenticationTrustResolverInterfac private $rememberMeClass; /** - * Constructor. - * * @param string $anonymousClass * @param string $rememberMeClass */ diff --git a/src/Symfony/Component/Security/Core/Authentication/Provider/AnonymousAuthenticationProvider.php b/src/Symfony/Component/Security/Core/Authentication/Provider/AnonymousAuthenticationProvider.php index 7fbbf858ace91..882443a013970 100644 --- a/src/Symfony/Component/Security/Core/Authentication/Provider/AnonymousAuthenticationProvider.php +++ b/src/Symfony/Component/Security/Core/Authentication/Provider/AnonymousAuthenticationProvider.php @@ -25,8 +25,6 @@ class AnonymousAuthenticationProvider implements AuthenticationProviderInterface private $key; /** - * Constructor. - * * @param string $key The key shared with the authentication token */ public function __construct($key) diff --git a/src/Symfony/Component/Security/Core/Authentication/Provider/DaoAuthenticationProvider.php b/src/Symfony/Component/Security/Core/Authentication/Provider/DaoAuthenticationProvider.php index 90cba25d64382..b7b7f51d209fe 100644 --- a/src/Symfony/Component/Security/Core/Authentication/Provider/DaoAuthenticationProvider.php +++ b/src/Symfony/Component/Security/Core/Authentication/Provider/DaoAuthenticationProvider.php @@ -32,8 +32,6 @@ class DaoAuthenticationProvider extends UserAuthenticationProvider private $userProvider; /** - * Constructor. - * * @param UserProviderInterface $userProvider An UserProviderInterface instance * @param UserCheckerInterface $userChecker An UserCheckerInterface instance * @param string $providerKey The provider key diff --git a/src/Symfony/Component/Security/Core/Authentication/Provider/PreAuthenticatedAuthenticationProvider.php b/src/Symfony/Component/Security/Core/Authentication/Provider/PreAuthenticatedAuthenticationProvider.php index 4f732542ea94f..b871f1f5a3591 100644 --- a/src/Symfony/Component/Security/Core/Authentication/Provider/PreAuthenticatedAuthenticationProvider.php +++ b/src/Symfony/Component/Security/Core/Authentication/Provider/PreAuthenticatedAuthenticationProvider.php @@ -34,8 +34,6 @@ class PreAuthenticatedAuthenticationProvider implements AuthenticationProviderIn private $providerKey; /** - * Constructor. - * * @param UserProviderInterface $userProvider An UserProviderInterface instance * @param UserCheckerInterface $userChecker An UserCheckerInterface instance * @param string $providerKey The provider key diff --git a/src/Symfony/Component/Security/Core/Authentication/Provider/RememberMeAuthenticationProvider.php b/src/Symfony/Component/Security/Core/Authentication/Provider/RememberMeAuthenticationProvider.php index 82be1d13e9a99..d5e4172bb132d 100644 --- a/src/Symfony/Component/Security/Core/Authentication/Provider/RememberMeAuthenticationProvider.php +++ b/src/Symfony/Component/Security/Core/Authentication/Provider/RememberMeAuthenticationProvider.php @@ -23,8 +23,6 @@ class RememberMeAuthenticationProvider implements AuthenticationProviderInterfac private $providerKey; /** - * Constructor. - * * @param UserCheckerInterface $userChecker An UserCheckerInterface interface * @param string $key A key * @param string $providerKey A provider key diff --git a/src/Symfony/Component/Security/Core/Authentication/Provider/UserAuthenticationProvider.php b/src/Symfony/Component/Security/Core/Authentication/Provider/UserAuthenticationProvider.php index 26740883cfbc9..7527128cc7d3f 100644 --- a/src/Symfony/Component/Security/Core/Authentication/Provider/UserAuthenticationProvider.php +++ b/src/Symfony/Component/Security/Core/Authentication/Provider/UserAuthenticationProvider.php @@ -33,8 +33,6 @@ abstract class UserAuthenticationProvider implements AuthenticationProviderInter private $providerKey; /** - * Constructor. - * * @param UserCheckerInterface $userChecker An UserCheckerInterface interface * @param string $providerKey A provider key * @param bool $hideUserNotFoundExceptions Whether to hide user not found exception or not diff --git a/src/Symfony/Component/Security/Core/Authentication/RememberMe/PersistentToken.php b/src/Symfony/Component/Security/Core/Authentication/RememberMe/PersistentToken.php index 76873fc603cd7..c6b76c2e6b038 100644 --- a/src/Symfony/Component/Security/Core/Authentication/RememberMe/PersistentToken.php +++ b/src/Symfony/Component/Security/Core/Authentication/RememberMe/PersistentToken.php @@ -25,8 +25,6 @@ final class PersistentToken implements PersistentTokenInterface private $lastUsed; /** - * Constructor. - * * @param string $class * @param string $username * @param string $series diff --git a/src/Symfony/Component/Security/Core/Authentication/Token/AbstractToken.php b/src/Symfony/Component/Security/Core/Authentication/Token/AbstractToken.php index 0eee6d94a41c6..8a9f2477b2ea8 100644 --- a/src/Symfony/Component/Security/Core/Authentication/Token/AbstractToken.php +++ b/src/Symfony/Component/Security/Core/Authentication/Token/AbstractToken.php @@ -31,8 +31,6 @@ abstract class AbstractToken implements TokenInterface private $attributes = array(); /** - * Constructor. - * * @param (RoleInterface|string)[] $roles An array of roles * * @throws \InvalidArgumentException diff --git a/src/Symfony/Component/Security/Core/Authentication/Token/AnonymousToken.php b/src/Symfony/Component/Security/Core/Authentication/Token/AnonymousToken.php index 0d7dea08aa97c..218a172c6028c 100644 --- a/src/Symfony/Component/Security/Core/Authentication/Token/AnonymousToken.php +++ b/src/Symfony/Component/Security/Core/Authentication/Token/AnonymousToken.php @@ -23,8 +23,6 @@ class AnonymousToken extends AbstractToken private $key; /** - * Constructor. - * * @param string $key The key shared with the authentication provider * @param string|object $user The user can be a UserInterface instance, or an object implementing a __toString method or the username as a regular string * @param RoleInterface[] $roles An array of roles diff --git a/src/Symfony/Component/Security/Core/Authentication/Token/PreAuthenticatedToken.php b/src/Symfony/Component/Security/Core/Authentication/Token/PreAuthenticatedToken.php index a5460f50839ee..84fdb4b00c086 100644 --- a/src/Symfony/Component/Security/Core/Authentication/Token/PreAuthenticatedToken.php +++ b/src/Symfony/Component/Security/Core/Authentication/Token/PreAuthenticatedToken.php @@ -24,8 +24,6 @@ class PreAuthenticatedToken extends AbstractToken private $providerKey; /** - * Constructor. - * * @param string|object $user The user can be a UserInterface instance, or an object implementing a __toString method or the username as a regular string * @param mixed $credentials The user credentials * @param string $providerKey The provider key diff --git a/src/Symfony/Component/Security/Core/Authentication/Token/RememberMeToken.php b/src/Symfony/Component/Security/Core/Authentication/Token/RememberMeToken.php index 609fdad1c1fc6..c72a34b1cc768 100644 --- a/src/Symfony/Component/Security/Core/Authentication/Token/RememberMeToken.php +++ b/src/Symfony/Component/Security/Core/Authentication/Token/RememberMeToken.php @@ -24,8 +24,6 @@ class RememberMeToken extends AbstractToken private $providerKey; /** - * Constructor. - * * @param UserInterface $user * @param string $providerKey * @param string $key diff --git a/src/Symfony/Component/Security/Core/Authentication/Token/UsernamePasswordToken.php b/src/Symfony/Component/Security/Core/Authentication/Token/UsernamePasswordToken.php index 7bfc556bdbf25..9c790a98d4e50 100644 --- a/src/Symfony/Component/Security/Core/Authentication/Token/UsernamePasswordToken.php +++ b/src/Symfony/Component/Security/Core/Authentication/Token/UsernamePasswordToken.php @@ -24,8 +24,6 @@ class UsernamePasswordToken extends AbstractToken private $providerKey; /** - * Constructor. - * * @param string|object $user The username (like a nickname, email address, etc.), or a UserInterface instance or an object implementing a __toString method * @param mixed $credentials This usually is the password of the user * @param string $providerKey The provider key diff --git a/src/Symfony/Component/Security/Core/Authorization/AccessDecisionManager.php b/src/Symfony/Component/Security/Core/Authorization/AccessDecisionManager.php index c18c2cbf09f0f..dd56a04dc764e 100644 --- a/src/Symfony/Component/Security/Core/Authorization/AccessDecisionManager.php +++ b/src/Symfony/Component/Security/Core/Authorization/AccessDecisionManager.php @@ -32,8 +32,6 @@ class AccessDecisionManager implements AccessDecisionManagerInterface private $allowIfEqualGrantedDeniedDecisions; /** - * Constructor. - * * @param VoterInterface[] $voters An array of VoterInterface instances * @param string $strategy The vote strategy * @param bool $allowIfAllAbstainDecisions Whether to grant access if all voters abstained or not diff --git a/src/Symfony/Component/Security/Core/Authorization/AuthorizationChecker.php b/src/Symfony/Component/Security/Core/Authorization/AuthorizationChecker.php index 23c190cb563d0..eb502ef290769 100644 --- a/src/Symfony/Component/Security/Core/Authorization/AuthorizationChecker.php +++ b/src/Symfony/Component/Security/Core/Authorization/AuthorizationChecker.php @@ -31,8 +31,6 @@ class AuthorizationChecker implements AuthorizationCheckerInterface private $alwaysAuthenticate; /** - * Constructor. - * * @param TokenStorageInterface $tokenStorage * @param AuthenticationManagerInterface $authenticationManager An AuthenticationManager instance * @param AccessDecisionManagerInterface $accessDecisionManager An AccessDecisionManager instance diff --git a/src/Symfony/Component/Security/Core/Authorization/Voter/AuthenticatedVoter.php b/src/Symfony/Component/Security/Core/Authorization/Voter/AuthenticatedVoter.php index 5847e0d15c058..7f449bee1cef2 100644 --- a/src/Symfony/Component/Security/Core/Authorization/Voter/AuthenticatedVoter.php +++ b/src/Symfony/Component/Security/Core/Authorization/Voter/AuthenticatedVoter.php @@ -32,8 +32,6 @@ class AuthenticatedVoter implements VoterInterface private $authenticationTrustResolver; /** - * Constructor. - * * @param AuthenticationTrustResolverInterface $authenticationTrustResolver */ public function __construct(AuthenticationTrustResolverInterface $authenticationTrustResolver) diff --git a/src/Symfony/Component/Security/Core/Authorization/Voter/ExpressionVoter.php b/src/Symfony/Component/Security/Core/Authorization/Voter/ExpressionVoter.php index 98b8f50f15d03..8dd00bfb73e71 100644 --- a/src/Symfony/Component/Security/Core/Authorization/Voter/ExpressionVoter.php +++ b/src/Symfony/Component/Security/Core/Authorization/Voter/ExpressionVoter.php @@ -31,8 +31,6 @@ class ExpressionVoter implements VoterInterface private $roleHierarchy; /** - * Constructor. - * * @param ExpressionLanguage $expressionLanguage * @param AuthenticationTrustResolverInterface $trustResolver * @param RoleHierarchyInterface|null $roleHierarchy diff --git a/src/Symfony/Component/Security/Core/Authorization/Voter/RoleVoter.php b/src/Symfony/Component/Security/Core/Authorization/Voter/RoleVoter.php index 539dcda327932..f130ce39ee73a 100644 --- a/src/Symfony/Component/Security/Core/Authorization/Voter/RoleVoter.php +++ b/src/Symfony/Component/Security/Core/Authorization/Voter/RoleVoter.php @@ -24,8 +24,6 @@ class RoleVoter implements VoterInterface private $prefix; /** - * Constructor. - * * @param string $prefix The role prefix */ public function __construct($prefix = 'ROLE_') diff --git a/src/Symfony/Component/Security/Core/Encoder/BCryptPasswordEncoder.php b/src/Symfony/Component/Security/Core/Encoder/BCryptPasswordEncoder.php index f2fe0817dc154..f65d1d9d5801b 100644 --- a/src/Symfony/Component/Security/Core/Encoder/BCryptPasswordEncoder.php +++ b/src/Symfony/Component/Security/Core/Encoder/BCryptPasswordEncoder.php @@ -27,8 +27,6 @@ class BCryptPasswordEncoder extends BasePasswordEncoder private $cost; /** - * Constructor. - * * @param int $cost The algorithmic cost that should be used * * @throws \RuntimeException When no BCrypt encoder is available diff --git a/src/Symfony/Component/Security/Core/Encoder/MessageDigestPasswordEncoder.php b/src/Symfony/Component/Security/Core/Encoder/MessageDigestPasswordEncoder.php index 1706fc86a8eb7..e1e430d172888 100644 --- a/src/Symfony/Component/Security/Core/Encoder/MessageDigestPasswordEncoder.php +++ b/src/Symfony/Component/Security/Core/Encoder/MessageDigestPasswordEncoder.php @@ -25,8 +25,6 @@ class MessageDigestPasswordEncoder extends BasePasswordEncoder private $iterations; /** - * Constructor. - * * @param string $algorithm The digest algorithm to use * @param bool $encodeHashAsBase64 Whether to base64 encode the password hash * @param int $iterations The number of iterations to use to stretch the password hash diff --git a/src/Symfony/Component/Security/Core/Encoder/Pbkdf2PasswordEncoder.php b/src/Symfony/Component/Security/Core/Encoder/Pbkdf2PasswordEncoder.php index 6f24c4f1e279e..9a50829f728b9 100644 --- a/src/Symfony/Component/Security/Core/Encoder/Pbkdf2PasswordEncoder.php +++ b/src/Symfony/Component/Security/Core/Encoder/Pbkdf2PasswordEncoder.php @@ -34,8 +34,6 @@ class Pbkdf2PasswordEncoder extends BasePasswordEncoder private $length; /** - * Constructor. - * * @param string $algorithm The digest algorithm to use * @param bool $encodeHashAsBase64 Whether to base64 encode the password hash * @param int $iterations The number of iterations to use to stretch the password hash diff --git a/src/Symfony/Component/Security/Core/Encoder/PlaintextPasswordEncoder.php b/src/Symfony/Component/Security/Core/Encoder/PlaintextPasswordEncoder.php index 09059f667a35a..bda6269a52012 100644 --- a/src/Symfony/Component/Security/Core/Encoder/PlaintextPasswordEncoder.php +++ b/src/Symfony/Component/Security/Core/Encoder/PlaintextPasswordEncoder.php @@ -23,8 +23,6 @@ class PlaintextPasswordEncoder extends BasePasswordEncoder private $ignorePasswordCase; /** - * Constructor. - * * @param bool $ignorePasswordCase Compare password case-insensitive */ public function __construct($ignorePasswordCase = false) diff --git a/src/Symfony/Component/Security/Core/Role/Role.php b/src/Symfony/Component/Security/Core/Role/Role.php index 5b50981fe1a78..123a1262f1f31 100644 --- a/src/Symfony/Component/Security/Core/Role/Role.php +++ b/src/Symfony/Component/Security/Core/Role/Role.php @@ -22,8 +22,6 @@ class Role implements RoleInterface private $role; /** - * Constructor. - * * @param string $role The role name */ public function __construct($role) diff --git a/src/Symfony/Component/Security/Core/Role/RoleHierarchy.php b/src/Symfony/Component/Security/Core/Role/RoleHierarchy.php index 95e76ee279316..ff487f2523ec8 100644 --- a/src/Symfony/Component/Security/Core/Role/RoleHierarchy.php +++ b/src/Symfony/Component/Security/Core/Role/RoleHierarchy.php @@ -22,8 +22,6 @@ class RoleHierarchy implements RoleHierarchyInterface protected $map; /** - * Constructor. - * * @param array $hierarchy An array defining the hierarchy */ public function __construct(array $hierarchy) diff --git a/src/Symfony/Component/Security/Core/Role/SwitchUserRole.php b/src/Symfony/Component/Security/Core/Role/SwitchUserRole.php index c6795841beaba..f68f40750d03b 100644 --- a/src/Symfony/Component/Security/Core/Role/SwitchUserRole.php +++ b/src/Symfony/Component/Security/Core/Role/SwitchUserRole.php @@ -24,8 +24,6 @@ class SwitchUserRole extends Role private $source; /** - * Constructor. - * * @param string $role The role as a string * @param TokenInterface $source The original token */ diff --git a/src/Symfony/Component/Security/Core/User/InMemoryUserProvider.php b/src/Symfony/Component/Security/Core/User/InMemoryUserProvider.php index e09d72e564f12..9e5a9a8e5a48c 100644 --- a/src/Symfony/Component/Security/Core/User/InMemoryUserProvider.php +++ b/src/Symfony/Component/Security/Core/User/InMemoryUserProvider.php @@ -27,8 +27,6 @@ class InMemoryUserProvider implements UserProviderInterface private $users; /** - * Constructor. - * * The user array is a hash where the keys are usernames and the values are * an array of attributes: 'password', 'enabled', and 'roles'. * diff --git a/src/Symfony/Component/Security/Csrf/CsrfToken.php b/src/Symfony/Component/Security/Csrf/CsrfToken.php index 9ccaaebf2df1e..693f37be7d251 100644 --- a/src/Symfony/Component/Security/Csrf/CsrfToken.php +++ b/src/Symfony/Component/Security/Csrf/CsrfToken.php @@ -29,8 +29,6 @@ class CsrfToken private $value; /** - * Constructor. - * * @param string $id The token ID * @param string $value The actual token value */ diff --git a/src/Symfony/Component/Security/Http/AccessMap.php b/src/Symfony/Component/Security/Http/AccessMap.php index 116874a3198ba..acd4101e72a97 100644 --- a/src/Symfony/Component/Security/Http/AccessMap.php +++ b/src/Symfony/Component/Security/Http/AccessMap.php @@ -25,8 +25,6 @@ class AccessMap implements AccessMapInterface private $map = array(); /** - * Constructor. - * * @param RequestMatcherInterface $requestMatcher A RequestMatcherInterface instance * @param array $attributes An array of attributes to pass to the access decision manager (like roles) * @param string|null $channel The channel to enforce (http, https, or null) diff --git a/src/Symfony/Component/Security/Http/Authentication/CustomAuthenticationFailureHandler.php b/src/Symfony/Component/Security/Http/Authentication/CustomAuthenticationFailureHandler.php index 36d4a78d6dc8e..1440179131ab7 100644 --- a/src/Symfony/Component/Security/Http/Authentication/CustomAuthenticationFailureHandler.php +++ b/src/Symfony/Component/Security/Http/Authentication/CustomAuthenticationFailureHandler.php @@ -22,8 +22,6 @@ class CustomAuthenticationFailureHandler implements AuthenticationFailureHandler private $handler; /** - * Constructor. - * * @param AuthenticationFailureHandlerInterface $handler An AuthenticationFailureHandlerInterface instance * @param array $options Options for processing a successful authentication attempt */ diff --git a/src/Symfony/Component/Security/Http/Authentication/CustomAuthenticationSuccessHandler.php b/src/Symfony/Component/Security/Http/Authentication/CustomAuthenticationSuccessHandler.php index 2d1b26ebb9179..369e2d14c7893 100644 --- a/src/Symfony/Component/Security/Http/Authentication/CustomAuthenticationSuccessHandler.php +++ b/src/Symfony/Component/Security/Http/Authentication/CustomAuthenticationSuccessHandler.php @@ -22,8 +22,6 @@ class CustomAuthenticationSuccessHandler implements AuthenticationSuccessHandler private $handler; /** - * Constructor. - * * @param AuthenticationSuccessHandlerInterface $handler An AuthenticationSuccessHandlerInterface instance * @param array $options Options for processing a successful authentication attempt * @param string $providerKey The provider key diff --git a/src/Symfony/Component/Security/Http/Authentication/DefaultAuthenticationFailureHandler.php b/src/Symfony/Component/Security/Http/Authentication/DefaultAuthenticationFailureHandler.php index 830c00aeb0180..08b5faee39827 100644 --- a/src/Symfony/Component/Security/Http/Authentication/DefaultAuthenticationFailureHandler.php +++ b/src/Symfony/Component/Security/Http/Authentication/DefaultAuthenticationFailureHandler.php @@ -42,8 +42,6 @@ class DefaultAuthenticationFailureHandler implements AuthenticationFailureHandle ); /** - * Constructor. - * * @param HttpKernelInterface $httpKernel * @param HttpUtils $httpUtils * @param array $options Options for processing a failed authentication attempt diff --git a/src/Symfony/Component/Security/Http/Authentication/DefaultAuthenticationSuccessHandler.php b/src/Symfony/Component/Security/Http/Authentication/DefaultAuthenticationSuccessHandler.php index 7da6e35572b47..898dfbc8c8393 100644 --- a/src/Symfony/Component/Security/Http/Authentication/DefaultAuthenticationSuccessHandler.php +++ b/src/Symfony/Component/Security/Http/Authentication/DefaultAuthenticationSuccessHandler.php @@ -36,8 +36,6 @@ class DefaultAuthenticationSuccessHandler implements AuthenticationSuccessHandle ); /** - * Constructor. - * * @param HttpUtils $httpUtils * @param array $options Options for processing a successful authentication attempt */ diff --git a/src/Symfony/Component/Security/Http/Authentication/SimpleAuthenticationHandler.php b/src/Symfony/Component/Security/Http/Authentication/SimpleAuthenticationHandler.php index c5c43f2895734..669dc13489fec 100644 --- a/src/Symfony/Component/Security/Http/Authentication/SimpleAuthenticationHandler.php +++ b/src/Symfony/Component/Security/Http/Authentication/SimpleAuthenticationHandler.php @@ -35,8 +35,6 @@ class SimpleAuthenticationHandler implements AuthenticationFailureHandlerInterfa protected $logger; /** - * Constructor. - * * @param SimpleAuthenticatorInterface $authenticator SimpleAuthenticatorInterface instance * @param AuthenticationSuccessHandlerInterface $successHandler Default success handler * @param AuthenticationFailureHandlerInterface $failureHandler Default failure handler diff --git a/src/Symfony/Component/Security/Http/EntryPoint/FormAuthenticationEntryPoint.php b/src/Symfony/Component/Security/Http/EntryPoint/FormAuthenticationEntryPoint.php index c734db065e16f..35ee02f5401dc 100644 --- a/src/Symfony/Component/Security/Http/EntryPoint/FormAuthenticationEntryPoint.php +++ b/src/Symfony/Component/Security/Http/EntryPoint/FormAuthenticationEntryPoint.php @@ -29,8 +29,6 @@ class FormAuthenticationEntryPoint implements AuthenticationEntryPointInterface private $httpUtils; /** - * Constructor. - * * @param HttpKernelInterface $kernel * @param HttpUtils $httpUtils An HttpUtils instance * @param string $loginPath The path to the login form diff --git a/src/Symfony/Component/Security/Http/Event/InteractiveLoginEvent.php b/src/Symfony/Component/Security/Http/Event/InteractiveLoginEvent.php index b5ac242d41502..17c6d9e8f78e7 100644 --- a/src/Symfony/Component/Security/Http/Event/InteractiveLoginEvent.php +++ b/src/Symfony/Component/Security/Http/Event/InteractiveLoginEvent.php @@ -16,8 +16,6 @@ use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; /** - * InteractiveLoginEvent. - * * @author Fabien Potencier */ class InteractiveLoginEvent extends Event @@ -26,8 +24,6 @@ class InteractiveLoginEvent extends Event private $authenticationToken; /** - * Constructor. - * * @param Request $request A Request instance * @param TokenInterface $authenticationToken A TokenInterface instance */ diff --git a/src/Symfony/Component/Security/Http/Firewall.php b/src/Symfony/Component/Security/Http/Firewall.php index 7bad47a5bed01..12fb2b5452787 100644 --- a/src/Symfony/Component/Security/Http/Firewall.php +++ b/src/Symfony/Component/Security/Http/Firewall.php @@ -34,8 +34,6 @@ class Firewall implements EventSubscriberInterface private $exceptionListeners; /** - * Constructor. - * * @param FirewallMapInterface $map A FirewallMapInterface instance * @param EventDispatcherInterface $dispatcher An EventDispatcherInterface instance */ diff --git a/src/Symfony/Component/Security/Http/Firewall/AbstractAuthenticationListener.php b/src/Symfony/Component/Security/Http/Firewall/AbstractAuthenticationListener.php index 1eae0948a13c3..1056879e348f7 100644 --- a/src/Symfony/Component/Security/Http/Firewall/AbstractAuthenticationListener.php +++ b/src/Symfony/Component/Security/Http/Firewall/AbstractAuthenticationListener.php @@ -64,8 +64,6 @@ abstract class AbstractAuthenticationListener implements ListenerInterface private $rememberMeServices; /** - * Constructor. - * * @param TokenStorageInterface $tokenStorage A TokenStorageInterface instance * @param AuthenticationManagerInterface $authenticationManager An AuthenticationManagerInterface instance * @param SessionAuthenticationStrategyInterface $sessionStrategy diff --git a/src/Symfony/Component/Security/Http/Firewall/LogoutListener.php b/src/Symfony/Component/Security/Http/Firewall/LogoutListener.php index e04a0a601920d..5b5ccbff1009d 100644 --- a/src/Symfony/Component/Security/Http/Firewall/LogoutListener.php +++ b/src/Symfony/Component/Security/Http/Firewall/LogoutListener.php @@ -40,8 +40,6 @@ class LogoutListener implements ListenerInterface private $csrfTokenManager; /** - * Constructor. - * * @param TokenStorageInterface $tokenStorage * @param HttpUtils $httpUtils An HttpUtils instance * @param LogoutSuccessHandlerInterface $successHandler A LogoutSuccessHandlerInterface instance diff --git a/src/Symfony/Component/Security/Http/Firewall/RememberMeListener.php b/src/Symfony/Component/Security/Http/Firewall/RememberMeListener.php index bc859f9f5dce4..1802dd878738c 100644 --- a/src/Symfony/Component/Security/Http/Firewall/RememberMeListener.php +++ b/src/Symfony/Component/Security/Http/Firewall/RememberMeListener.php @@ -39,8 +39,6 @@ class RememberMeListener implements ListenerInterface private $sessionStrategy; /** - * Constructor. - * * @param TokenStorageInterface $tokenStorage * @param RememberMeServicesInterface $rememberMeServices * @param AuthenticationManagerInterface $authenticationManager diff --git a/src/Symfony/Component/Security/Http/Firewall/SimpleFormAuthenticationListener.php b/src/Symfony/Component/Security/Http/Firewall/SimpleFormAuthenticationListener.php index d97a3427138b3..cf61d83d4334c 100644 --- a/src/Symfony/Component/Security/Http/Firewall/SimpleFormAuthenticationListener.php +++ b/src/Symfony/Component/Security/Http/Firewall/SimpleFormAuthenticationListener.php @@ -39,8 +39,6 @@ class SimpleFormAuthenticationListener extends AbstractAuthenticationListener private $csrfTokenManager; /** - * Constructor. - * * @param TokenStorageInterface $tokenStorage A TokenStorageInterface instance * @param AuthenticationManagerInterface $authenticationManager An AuthenticationManagerInterface instance * @param SessionAuthenticationStrategyInterface $sessionStrategy diff --git a/src/Symfony/Component/Security/Http/Firewall/SimplePreAuthenticationListener.php b/src/Symfony/Component/Security/Http/Firewall/SimplePreAuthenticationListener.php index 7f85a1ec7bd8f..59385e17e7edd 100644 --- a/src/Symfony/Component/Security/Http/Firewall/SimplePreAuthenticationListener.php +++ b/src/Symfony/Component/Security/Http/Firewall/SimplePreAuthenticationListener.php @@ -40,8 +40,6 @@ class SimplePreAuthenticationListener implements ListenerInterface private $dispatcher; /** - * Constructor. - * * @param TokenStorageInterface $tokenStorage A TokenStorageInterface instance * @param AuthenticationManagerInterface $authenticationManager An AuthenticationManagerInterface instance * @param string $providerKey diff --git a/src/Symfony/Component/Security/Http/HttpUtils.php b/src/Symfony/Component/Security/Http/HttpUtils.php index 56add79926d3e..d30b71ae7b81d 100644 --- a/src/Symfony/Component/Security/Http/HttpUtils.php +++ b/src/Symfony/Component/Security/Http/HttpUtils.php @@ -31,8 +31,6 @@ class HttpUtils private $urlMatcher; /** - * Constructor. - * * @param UrlGeneratorInterface $urlGenerator A UrlGeneratorInterface instance * @param UrlMatcherInterface|RequestMatcherInterface $urlMatcher The URL or Request matcher * diff --git a/src/Symfony/Component/Security/Http/Logout/CookieClearingLogoutHandler.php b/src/Symfony/Component/Security/Http/Logout/CookieClearingLogoutHandler.php index 6838be57e1ee8..a78b25f0c34ec 100644 --- a/src/Symfony/Component/Security/Http/Logout/CookieClearingLogoutHandler.php +++ b/src/Symfony/Component/Security/Http/Logout/CookieClearingLogoutHandler.php @@ -25,8 +25,6 @@ class CookieClearingLogoutHandler implements LogoutHandlerInterface private $cookies; /** - * Constructor. - * * @param array $cookies An array of cookie names to unset */ public function __construct(array $cookies) diff --git a/src/Symfony/Component/Security/Http/RememberMe/AbstractRememberMeServices.php b/src/Symfony/Component/Security/Http/RememberMe/AbstractRememberMeServices.php index 4ab3465c66263..0cb4007b13901 100644 --- a/src/Symfony/Component/Security/Http/RememberMe/AbstractRememberMeServices.php +++ b/src/Symfony/Component/Security/Http/RememberMe/AbstractRememberMeServices.php @@ -43,8 +43,6 @@ abstract class AbstractRememberMeServices implements RememberMeServicesInterface private $userProviders; /** - * Constructor. - * * @param array $userProviders * @param string $key * @param string $providerKey diff --git a/src/Symfony/Component/Security/Http/RememberMe/PersistentTokenBasedRememberMeServices.php b/src/Symfony/Component/Security/Http/RememberMe/PersistentTokenBasedRememberMeServices.php index cbbbb235192d9..82aa48fc6664f 100644 --- a/src/Symfony/Component/Security/Http/RememberMe/PersistentTokenBasedRememberMeServices.php +++ b/src/Symfony/Component/Security/Http/RememberMe/PersistentTokenBasedRememberMeServices.php @@ -36,8 +36,6 @@ class PersistentTokenBasedRememberMeServices extends AbstractRememberMeServices private $secureRandom; /** - * Constructor. - * * @param array $userProviders * @param string $key * @param string $providerKey diff --git a/src/Symfony/Component/Serializer/Mapping/Loader/FileLoader.php b/src/Symfony/Component/Serializer/Mapping/Loader/FileLoader.php index 38bb59389a6dd..229111b6ff26b 100644 --- a/src/Symfony/Component/Serializer/Mapping/Loader/FileLoader.php +++ b/src/Symfony/Component/Serializer/Mapping/Loader/FileLoader.php @@ -26,8 +26,6 @@ abstract class FileLoader implements LoaderInterface protected $file; /** - * Constructor. - * * @param string $file The mapping file to load * * @throws MappingException if the mapping file does not exist or is not readable diff --git a/src/Symfony/Component/Stopwatch/Section.php b/src/Symfony/Component/Stopwatch/Section.php index e2d4dec5cb713..f44ae17856620 100644 --- a/src/Symfony/Component/Stopwatch/Section.php +++ b/src/Symfony/Component/Stopwatch/Section.php @@ -39,8 +39,6 @@ class Section private $children = array(); /** - * Constructor. - * * @param float|null $origin Set the origin of the events in this section, use null to set their origin to their start time */ public function __construct($origin = null) diff --git a/src/Symfony/Component/Stopwatch/StopwatchEvent.php b/src/Symfony/Component/Stopwatch/StopwatchEvent.php index 16a30db2aa50e..5fdd62e6e0b1f 100644 --- a/src/Symfony/Component/Stopwatch/StopwatchEvent.php +++ b/src/Symfony/Component/Stopwatch/StopwatchEvent.php @@ -39,8 +39,6 @@ class StopwatchEvent private $started = array(); /** - * Constructor. - * * @param float $origin The origin time in milliseconds * @param string|null $category The event category or null to use the default * diff --git a/src/Symfony/Component/Stopwatch/StopwatchPeriod.php b/src/Symfony/Component/Stopwatch/StopwatchPeriod.php index 9876f179aadb6..c14610304f1c6 100644 --- a/src/Symfony/Component/Stopwatch/StopwatchPeriod.php +++ b/src/Symfony/Component/Stopwatch/StopwatchPeriod.php @@ -23,8 +23,6 @@ class StopwatchPeriod private $memory; /** - * Constructor. - * * @param int $start The relative time of the start of the period (in milliseconds) * @param int $end The relative time of the end of the period (in milliseconds) */ diff --git a/src/Symfony/Component/Templating/Asset/Package.php b/src/Symfony/Component/Templating/Asset/Package.php index 1c6bcf2b04a82..beb6a90648bd9 100644 --- a/src/Symfony/Component/Templating/Asset/Package.php +++ b/src/Symfony/Component/Templating/Asset/Package.php @@ -26,8 +26,6 @@ class Package implements PackageInterface private $format; /** - * Constructor. - * * @param string $version The package version * @param string $format The format used to apply the version */ diff --git a/src/Symfony/Component/Templating/Asset/PathPackage.php b/src/Symfony/Component/Templating/Asset/PathPackage.php index 265e313cad8ce..0ec12eb940823 100644 --- a/src/Symfony/Component/Templating/Asset/PathPackage.php +++ b/src/Symfony/Component/Templating/Asset/PathPackage.php @@ -25,8 +25,6 @@ class PathPackage extends Package private $basePath; /** - * Constructor. - * * @param string $basePath The base path to be prepended to relative paths * @param string $version The package version * @param string $format The format used to apply the version diff --git a/src/Symfony/Component/Templating/Asset/UrlPackage.php b/src/Symfony/Component/Templating/Asset/UrlPackage.php index 6831d1245ecab..2c2a659a8261b 100644 --- a/src/Symfony/Component/Templating/Asset/UrlPackage.php +++ b/src/Symfony/Component/Templating/Asset/UrlPackage.php @@ -25,8 +25,6 @@ class UrlPackage extends Package private $baseUrls; /** - * Constructor. - * * @param string|array $baseUrls Base asset URLs * @param string $version The package version * @param string $format The format used to apply the version diff --git a/src/Symfony/Component/Templating/DelegatingEngine.php b/src/Symfony/Component/Templating/DelegatingEngine.php index 4006ea5d92f9a..bef82af7bd21b 100644 --- a/src/Symfony/Component/Templating/DelegatingEngine.php +++ b/src/Symfony/Component/Templating/DelegatingEngine.php @@ -24,8 +24,6 @@ class DelegatingEngine implements EngineInterface, StreamingEngineInterface protected $engines = array(); /** - * Constructor. - * * @param EngineInterface[] $engines An array of EngineInterface instances to add */ public function __construct(array $engines = array()) diff --git a/src/Symfony/Component/Templating/Helper/AssetsHelper.php b/src/Symfony/Component/Templating/Helper/AssetsHelper.php index 12c4c638846b2..f07e1c7d76a08 100644 --- a/src/Symfony/Component/Templating/Helper/AssetsHelper.php +++ b/src/Symfony/Component/Templating/Helper/AssetsHelper.php @@ -33,8 +33,6 @@ class AssetsHelper extends CoreAssetsHelper { /** - * Constructor. - * * @param string $basePath The base path * @param string|array $baseUrls Base asset URLs * @param string $version The asset version diff --git a/src/Symfony/Component/Templating/Helper/CoreAssetsHelper.php b/src/Symfony/Component/Templating/Helper/CoreAssetsHelper.php index fe677e0e0f369..689b17b401d58 100644 --- a/src/Symfony/Component/Templating/Helper/CoreAssetsHelper.php +++ b/src/Symfony/Component/Templating/Helper/CoreAssetsHelper.php @@ -35,8 +35,6 @@ class CoreAssetsHelper extends Helper implements PackageInterface protected $namedPackages = array(); /** - * Constructor. - * * @param PackageInterface $defaultPackage The default package * @param array $namedPackages Additional packages indexed by name */ diff --git a/src/Symfony/Component/Templating/Loader/CacheLoader.php b/src/Symfony/Component/Templating/Loader/CacheLoader.php index ab4808d682ac6..9ee24f1daaff8 100644 --- a/src/Symfony/Component/Templating/Loader/CacheLoader.php +++ b/src/Symfony/Component/Templating/Loader/CacheLoader.php @@ -30,8 +30,6 @@ class CacheLoader extends Loader protected $dir; /** - * Constructor. - * * @param LoaderInterface $loader A Loader instance * @param string $dir The directory where to store the cache files */ diff --git a/src/Symfony/Component/Templating/Loader/ChainLoader.php b/src/Symfony/Component/Templating/Loader/ChainLoader.php index 9a9d15792101f..ea9aac5f77174 100644 --- a/src/Symfony/Component/Templating/Loader/ChainLoader.php +++ b/src/Symfony/Component/Templating/Loader/ChainLoader.php @@ -24,8 +24,6 @@ class ChainLoader extends Loader protected $loaders = array(); /** - * Constructor. - * * @param LoaderInterface[] $loaders An array of loader instances */ public function __construct(array $loaders = array()) diff --git a/src/Symfony/Component/Templating/Loader/FilesystemLoader.php b/src/Symfony/Component/Templating/Loader/FilesystemLoader.php index 0d102a6326e6c..7cdf5b8a1916e 100644 --- a/src/Symfony/Component/Templating/Loader/FilesystemLoader.php +++ b/src/Symfony/Component/Templating/Loader/FilesystemLoader.php @@ -25,8 +25,6 @@ class FilesystemLoader extends Loader protected $templatePathPatterns; /** - * Constructor. - * * @param array $templatePathPatterns An array of path patterns to look for templates */ public function __construct($templatePathPatterns) diff --git a/src/Symfony/Component/Templating/PhpEngine.php b/src/Symfony/Component/Templating/PhpEngine.php index de243d35e09bf..0828b78fc2784 100644 --- a/src/Symfony/Component/Templating/PhpEngine.php +++ b/src/Symfony/Component/Templating/PhpEngine.php @@ -43,8 +43,6 @@ class PhpEngine implements EngineInterface, \ArrayAccess private $evalParameters; /** - * Constructor. - * * @param TemplateNameParserInterface $parser A TemplateNameParserInterface instance * @param LoaderInterface $loader A loader instance * @param HelperInterface[] $helpers An array of helper instances diff --git a/src/Symfony/Component/Templating/Storage/Storage.php b/src/Symfony/Component/Templating/Storage/Storage.php index e5ad2c48189fe..87245b3d425f3 100644 --- a/src/Symfony/Component/Templating/Storage/Storage.php +++ b/src/Symfony/Component/Templating/Storage/Storage.php @@ -21,8 +21,6 @@ abstract class Storage protected $template; /** - * Constructor. - * * @param string $template The template name */ public function __construct($template) diff --git a/src/Symfony/Component/Translation/IdentityTranslator.php b/src/Symfony/Component/Translation/IdentityTranslator.php index 46a046365b324..82b247015bfe6 100644 --- a/src/Symfony/Component/Translation/IdentityTranslator.php +++ b/src/Symfony/Component/Translation/IdentityTranslator.php @@ -22,8 +22,6 @@ class IdentityTranslator implements TranslatorInterface private $locale; /** - * Constructor. - * * @param MessageSelector|null $selector The message selector for pluralization */ public function __construct(MessageSelector $selector = null) diff --git a/src/Symfony/Component/Translation/MessageCatalogue.php b/src/Symfony/Component/Translation/MessageCatalogue.php index 73649fb6ddcaa..920bc84c1cdfb 100644 --- a/src/Symfony/Component/Translation/MessageCatalogue.php +++ b/src/Symfony/Component/Translation/MessageCatalogue.php @@ -14,8 +14,6 @@ use Symfony\Component\Config\Resource\ResourceInterface; /** - * MessageCatalogue. - * * @author Fabien Potencier */ class MessageCatalogue implements MessageCatalogueInterface, MetadataAwareInterface @@ -28,8 +26,6 @@ class MessageCatalogue implements MessageCatalogueInterface, MetadataAwareInterf private $parent; /** - * Constructor. - * * @param string $locale The locale * @param array $messages An array of messages classified by domain */ diff --git a/src/Symfony/Component/Translation/Translator.php b/src/Symfony/Component/Translation/Translator.php index 816cfd28f9f2a..4fc517ffb5f68 100644 --- a/src/Symfony/Component/Translation/Translator.php +++ b/src/Symfony/Component/Translation/Translator.php @@ -18,8 +18,6 @@ use Symfony\Component\Config\ConfigCacheFactory; /** - * Translator. - * * @author Fabien Potencier */ class Translator implements TranslatorInterface, TranslatorBagInterface @@ -70,8 +68,6 @@ class Translator implements TranslatorInterface, TranslatorBagInterface private $configCacheFactory; /** - * Constructor. - * * @param string $locale The locale * @param MessageSelector|null $selector The message selector for pluralization * @param string|null $cacheDir The directory to use for the cache diff --git a/src/Symfony/Component/Validator/Mapping/GetterMetadata.php b/src/Symfony/Component/Validator/Mapping/GetterMetadata.php index cd42c4338cbb5..5a72bd84b7442 100644 --- a/src/Symfony/Component/Validator/Mapping/GetterMetadata.php +++ b/src/Symfony/Component/Validator/Mapping/GetterMetadata.php @@ -33,8 +33,6 @@ class GetterMetadata extends MemberMetadata { /** - * Constructor. - * * @param string $class The class the getter is defined on * @param string $property The property which the getter returns * @param string|null $method The method that is called to retrieve the value being validated (null for auto-detection) diff --git a/src/Symfony/Component/Validator/Mapping/MemberMetadata.php b/src/Symfony/Component/Validator/Mapping/MemberMetadata.php index 0def248431f2d..af2060c2efe2b 100644 --- a/src/Symfony/Component/Validator/Mapping/MemberMetadata.php +++ b/src/Symfony/Component/Validator/Mapping/MemberMetadata.php @@ -62,8 +62,6 @@ abstract class MemberMetadata extends ElementMetadata implements PropertyMetadat private $reflMember = array(); /** - * Constructor. - * * @param string $class The name of the class this member is defined on * @param string $name The name of the member * @param string $property The property the member belongs to diff --git a/src/Symfony/Component/Validator/Mapping/PropertyMetadata.php b/src/Symfony/Component/Validator/Mapping/PropertyMetadata.php index d12701cb44aba..7fc19dd2f7020 100644 --- a/src/Symfony/Component/Validator/Mapping/PropertyMetadata.php +++ b/src/Symfony/Component/Validator/Mapping/PropertyMetadata.php @@ -29,8 +29,6 @@ class PropertyMetadata extends MemberMetadata { /** - * Constructor. - * * @param string $class The class this property is defined on * @param string $name The name of this property * diff --git a/src/Symfony/Component/Yaml/Exception/ParseException.php b/src/Symfony/Component/Yaml/Exception/ParseException.php index ef36cfbadd35c..60802b6d701b5 100644 --- a/src/Symfony/Component/Yaml/Exception/ParseException.php +++ b/src/Symfony/Component/Yaml/Exception/ParseException.php @@ -24,8 +24,6 @@ class ParseException extends RuntimeException private $rawMessage; /** - * Constructor. - * * @param string $message The error message * @param int $parsedLine The line where the error occurred * @param string|null $snippet The snippet of code near the problem diff --git a/src/Symfony/Component/Yaml/Parser.php b/src/Symfony/Component/Yaml/Parser.php index 90a2f34e02123..6fa05e7409422 100644 --- a/src/Symfony/Component/Yaml/Parser.php +++ b/src/Symfony/Component/Yaml/Parser.php @@ -34,8 +34,6 @@ class Parser private $locallySkippedLineNumbers = array(); /** - * Constructor. - * * @param int $offset The offset of YAML document (used for line numbers in error messages) * @param int|null $totalNumberOfLines The overall number of lines being parsed * @param int[] $skippedLineNumbers Number of comment lines that have been skipped by the parser From aeb57ab658e1a5c67cc0ac12a0b0043c15677ea0 Mon Sep 17 00:00:00 2001 From: Maxime Steinhausser Date: Fri, 29 Sep 2017 21:16:17 +0200 Subject: [PATCH 0965/1099] [SecurityBundle] Remove auto picking the first provider when no provider is explicitly configured on a firewall --- src/Symfony/Bundle/SecurityBundle/CHANGELOG.md | 1 + .../SecurityBundle/DependencyInjection/SecurityExtension.php | 4 ++++ .../Tests/DependencyInjection/SecurityExtensionTest.php | 4 ++-- 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Bundle/SecurityBundle/CHANGELOG.md b/src/Symfony/Bundle/SecurityBundle/CHANGELOG.md index 25aee704c2713..698d54011000d 100644 --- a/src/Symfony/Bundle/SecurityBundle/CHANGELOG.md +++ b/src/Symfony/Bundle/SecurityBundle/CHANGELOG.md @@ -13,6 +13,7 @@ CHANGELOG * removed command `acl:set` along with `SetAclCommand` class * removed command `init:acl` along with `InitAclCommand` class * removed `acl` configuration key and related services, use symfony/acl-bundle instead + * removed auto picking the first registered provider when no configured provider on a firewall and ambiguous 3.4.0 ----- diff --git a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php index bdc83cd14a5c6..5c2bf3278c8de 100644 --- a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php +++ b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php @@ -261,6 +261,10 @@ private function createFirewall(ContainerBuilder $container, $id, $firewall, &$a } $defaultProvider = $providerIds[$normalizedName]; } else { + if (count($providerIds) > 1) { + throw new InvalidConfigurationException(sprintf('Not configuring explicitly the provider on "%s" firewall is ambiguous as there is more than one registered provider.', $id)); + } + $defaultProvider = reset($providerIds); if (count($providerIds) > 1) { diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/SecurityExtensionTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/SecurityExtensionTest.php index f7d3e4cd5207b..18821f9aedd36 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/SecurityExtensionTest.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/SecurityExtensionTest.php @@ -175,8 +175,8 @@ public function testSwitchUserNotStatelessOnStatelessFirewall() } /** - * @group legacy - * @expectedDeprecation Firewall "default" has no "provider" set but multiple providers exist. Using the first configured provider (first) is deprecated since 3.4 and will throw an exception in 4.0, set the "provider" key on the firewall instead. + * @expectedException \Symfony\Component\Config\Definition\Exception\InvalidConfigurationException + * @expectedExceptionMessage Not configuring explicitly the provider on "default" firewall is ambiguous as there is more than one registered provider. */ public function testDeprecationForAmbiguousProvider() { From e3190755cf8df517800e405f8b1ca2db3b2038fe Mon Sep 17 00:00:00 2001 From: TeLiXj Date: Mon, 11 Sep 2017 10:56:17 +0200 Subject: [PATCH 0966/1099] Hide label button when its setted to false Added same behaviour in buttons like in other form components when label is setted to false, don't show it. It's very useful with buttons with icon and without text --- .../Bridge/Twig/Resources/views/Form/form_div_layout.html.twig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 3d8afe2cba602..3241c6256cab8 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 @@ -216,7 +216,7 @@ {%- endblock range_widget %} {%- block button_widget -%} - {%- if label is empty -%} + {%- if label is not same as(false) and label is empty -%} {%- if label_format is not empty -%} {% set label = label_format|replace({ '%name%': name, From 0067948c2c5370952b742052a7cca0c0fded4144 Mon Sep 17 00:00:00 2001 From: Robin Chalas Date: Sat, 30 Sep 2017 20:09:08 +0200 Subject: [PATCH 0967/1099] [SecurityBundle] Remove dead code --- .../SecurityBundle/DependencyInjection/SecurityExtension.php | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php index 5c2bf3278c8de..2b886d93a998a 100644 --- a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php +++ b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php @@ -266,10 +266,6 @@ private function createFirewall(ContainerBuilder $container, $id, $firewall, &$a } $defaultProvider = reset($providerIds); - - if (count($providerIds) > 1) { - @trigger_error(sprintf('Firewall "%s" has no "provider" set but multiple providers exist. Using the first configured provider (%s) is deprecated since 3.4 and will throw an exception in 4.0, set the "provider" key on the firewall instead.', $id, key($providerIds)), E_USER_DEPRECATED); - } } $config->replaceArgument(5, $defaultProvider); From b0c04f83544ce397fb3f34e4b42f5ee21274ed65 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Tue, 26 Sep 2017 11:37:36 +0200 Subject: [PATCH 0968/1099] [FrameworkBundle] Don't clear app pools on cache:clear --- UPGRADE-3.4.md | 4 ++++ src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md | 2 ++ .../DependencyInjection/Compiler/CachePoolPass.php | 2 +- .../DependencyInjection/FrameworkExtension.php | 2 +- .../Bundle/FrameworkBundle/Resources/config/cache.xml | 6 +++++- .../FrameworkBundle/Tests/Functional/CachePoolsTest.php | 6 +++--- .../Tests/Functional/app/CachePools/config.yml | 1 + .../Tests/Functional/app/CachePools/redis_config.yml | 1 + .../Tests/Functional/app/CachePools/redis_custom_config.yml | 1 + 9 files changed, 19 insertions(+), 6 deletions(-) diff --git a/UPGRADE-3.4.md b/UPGRADE-3.4.md index 6561c15a0b46f..d5ae0a934ffa2 100644 --- a/UPGRADE-3.4.md +++ b/UPGRADE-3.4.md @@ -113,6 +113,10 @@ Form FrameworkBundle --------------- + * The `cache:clear` command doesn't clear "app" PSR-6 cache pools anymore, + but still clears "system" ones. + Use the `cache:pool:clear` command to clear "app" pools instead. + * The `doctrine/cache` dependency has been removed; require it via `composer require doctrine/cache` if you are using Doctrine cache in your project. diff --git a/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md b/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md index 34af26de698ed..f49eb6dbc2dd3 100644 --- a/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md +++ b/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md @@ -4,6 +4,8 @@ CHANGELOG 3.4.0 ----- + * Made the `cache:clear` command to *not* clear "app" PSR-6 cache pools anymore, + but to still clear "system" ones; use the `cache:pool:clear` command to clear "app" pools instead * Always register a minimalist logger that writes in `stderr` * Deprecated `profiler.matcher` option * Added support for `EventSubscriberInterface` on `MicroKernelTrait` diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/CachePoolPass.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/CachePoolPass.php index dafe0b7b8fce4..004a2c544da3d 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/CachePoolPass.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/CachePoolPass.php @@ -106,7 +106,7 @@ public function process(ContainerBuilder $container) foreach ($clearers as $id => $pools) { $clearer = $container->getDefinition($id); - if ($clearer instanceof ChilDefinition) { + if ($clearer instanceof ChildDefinition) { $clearer->replaceArgument(0, $pools); } else { $clearer->setArgument(0, $pools); diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php index dafecf9d581d6..0e136bfe436f7 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php @@ -1802,7 +1802,7 @@ private function registerCacheConfiguration(array $config, ContainerBuilder $con if (!$container->getParameter('kernel.debug')) { $propertyAccessDefinition->setFactory(array(PropertyAccessor::class, 'createCache')); $propertyAccessDefinition->setArguments(array(null, null, $version, new Reference('logger', ContainerInterface::IGNORE_ON_INVALID_REFERENCE))); - $propertyAccessDefinition->addTag('cache.pool', array('clearer' => 'cache.default_clearer')); + $propertyAccessDefinition->addTag('cache.pool', array('clearer' => 'cache.system_clearer')); $propertyAccessDefinition->addTag('monolog.logger', array('channel' => 'cache')); } else { $propertyAccessDefinition->setClass(ArrayAdapter::class); diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/cache.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/cache.xml index 16b15a661768c..b4d23a576ed0f 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/cache.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/cache.xml @@ -29,7 +29,7 @@ - + 0 @@ -101,6 +101,10 @@ + + + + diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/CachePoolsTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/CachePoolsTest.php index 06ed75d64d5c1..eafc798a4838b 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/CachePoolsTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/CachePoolsTest.php @@ -11,7 +11,7 @@ namespace Symfony\Bundle\FrameworkBundle\Tests\Functional; -use Symfony\Component\Cache\Adapter\FilesystemAdapter; +use Symfony\Component\Cache\Adapter\AdapterInterface; use Symfony\Component\Cache\Adapter\RedisAdapter; use Symfony\Component\Cache\Exception\InvalidArgumentException; @@ -19,7 +19,7 @@ class CachePoolsTest extends WebTestCase { public function testCachePools() { - $this->doTestCachePools(array(), FilesystemAdapter::class); + $this->doTestCachePools(array(), AdapterInterface::class); } /** @@ -67,7 +67,7 @@ public function testRedisCustomCachePools() } } - public function doTestCachePools($options, $adapterClass) + private function doTestCachePools($options, $adapterClass) { static::bootKernel($options); $container = static::$kernel->getContainer(); diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/CachePools/config.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/CachePools/config.yml index eabf83825e05d..de1e144dad062 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/CachePools/config.yml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/CachePools/config.yml @@ -6,6 +6,7 @@ framework: pools: cache.pool1: public: true + adapter: cache.system cache.pool2: public: true adapter: cache.pool3 diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/CachePools/redis_config.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/CachePools/redis_config.yml index 02de40c5b81e5..3bf10f448f9c2 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/CachePools/redis_config.yml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/CachePools/redis_config.yml @@ -11,6 +11,7 @@ framework: pools: cache.pool1: public: true + clearer: cache.system_clearer cache.pool2: public: true clearer: ~ diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/CachePools/redis_custom_config.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/CachePools/redis_custom_config.yml index 9206638495947..d0a219753eb8e 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/CachePools/redis_custom_config.yml +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/CachePools/redis_custom_config.yml @@ -22,6 +22,7 @@ framework: pools: cache.pool1: public: true + clearer: cache.system_clearer cache.pool2: public: true clearer: ~ From 3c801951c8e92a716bd83c0491a601b7adf13039 Mon Sep 17 00:00:00 2001 From: Robin Chalas Date: Sun, 1 Oct 2017 11:18:37 +0200 Subject: [PATCH 0969/1099] [Security] Look at headers for switch user username parameter --- .../Tests/Functional/SwitchUserTest.php | 2 +- .../app/JsonLogin/switchuser_stateless.yml | 1 + .../Http/Firewall/SwitchUserListener.php | 16 ++++++++-------- 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/SwitchUserTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/SwitchUserTest.php index d89c24f1233fb..97b0a559193c4 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/SwitchUserTest.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/SwitchUserTest.php @@ -54,7 +54,7 @@ public function testSwitchedUserExit() public function testSwitchUserStateless() { $client = $this->createClient(array('test_case' => 'JsonLogin', 'root_config' => 'switchuser_stateless.yml')); - $client->request('POST', '/chk', array('_switch_user' => 'dunglas'), array(), array('CONTENT_TYPE' => 'application/json'), '{"user": {"login": "user_can_switch", "password": "test"}}'); + $client->request('POST', '/chk', array(), array(), array('HTTP_X_SWITCH_USER' => 'dunglas', 'CONTENT_TYPE' => 'application/json'), '{"user": {"login": "user_can_switch", "password": "test"}}'); $response = $client->getResponse(); $this->assertInstanceOf(JsonResponse::class, $response); diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/JsonLogin/switchuser_stateless.yml b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/JsonLogin/switchuser_stateless.yml index 29789a4caa25f..b8c832032c6f0 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/JsonLogin/switchuser_stateless.yml +++ b/src/Symfony/Bundle/SecurityBundle/Tests/Functional/app/JsonLogin/switchuser_stateless.yml @@ -10,4 +10,5 @@ security: firewalls: main: switch_user: + parameter: X-Switch-User stateless: true diff --git a/src/Symfony/Component/Security/Http/Firewall/SwitchUserListener.php b/src/Symfony/Component/Security/Http/Firewall/SwitchUserListener.php index d659ffc258db4..426727a738365 100644 --- a/src/Symfony/Component/Security/Http/Firewall/SwitchUserListener.php +++ b/src/Symfony/Component/Security/Http/Firewall/SwitchUserListener.php @@ -79,16 +79,17 @@ public function __construct(TokenStorageInterface $tokenStorage, UserProviderInt public function handle(GetResponseEvent $event) { $request = $event->getRequest(); + $username = $request->get($this->usernameParameter) ?: $request->headers->get($this->usernameParameter); - if (!$request->get($this->usernameParameter)) { + if (!$username) { return; } - if (self::EXIT_VALUE === $request->get($this->usernameParameter)) { + if (self::EXIT_VALUE === $username) { $this->tokenStorage->setToken($this->attemptExitUser($request)); } else { try { - $this->tokenStorage->setToken($this->attemptSwitchUser($request)); + $this->tokenStorage->setToken($this->attemptSwitchUser($request, $username)); } catch (AuthenticationException $e) { throw new \LogicException(sprintf('Switch User failed: "%s"', $e->getMessage())); } @@ -106,20 +107,21 @@ public function handle(GetResponseEvent $event) /** * Attempts to switch to another user. * - * @param Request $request A Request instance + * @param Request $request A Request instance + * @param string $username * * @return TokenInterface|null The new TokenInterface if successfully switched, null otherwise * * @throws \LogicException * @throws AccessDeniedException */ - private function attemptSwitchUser(Request $request) + private function attemptSwitchUser(Request $request, $username) { $token = $this->tokenStorage->getToken(); $originalToken = $this->getOriginalToken($token); if (false !== $originalToken) { - if ($token->getUsername() === $request->get($this->usernameParameter)) { + if ($token->getUsername() === $username) { return $token; } @@ -133,8 +135,6 @@ private function attemptSwitchUser(Request $request) throw $exception; } - $username = $request->get($this->usernameParameter); - if (null !== $this->logger) { $this->logger->info('Attempting to switch to user.', array('username' => $username)); } From ffc74eb959c619f79afeabc6e672083559bc92dd Mon Sep 17 00:00:00 2001 From: Tobias Schultze Date: Sun, 1 Oct 2017 17:08:32 +0200 Subject: [PATCH 0970/1099] [DoctrineBridge] Deprecate DbalSessionHandler --- .../Bridge/Doctrine/HttpFoundation/DbalSessionHandler.php | 4 ++++ .../Doctrine/HttpFoundation/DbalSessionHandlerSchema.php | 4 ++++ .../Doctrine/Tests/HttpFoundation/DbalSessionHandlerTest.php | 2 ++ 3 files changed, 10 insertions(+) diff --git a/src/Symfony/Bridge/Doctrine/HttpFoundation/DbalSessionHandler.php b/src/Symfony/Bridge/Doctrine/HttpFoundation/DbalSessionHandler.php index d819ff0a6c51e..7bbcfe0375bc6 100644 --- a/src/Symfony/Bridge/Doctrine/HttpFoundation/DbalSessionHandler.php +++ b/src/Symfony/Bridge/Doctrine/HttpFoundation/DbalSessionHandler.php @@ -11,6 +11,8 @@ namespace Symfony\Bridge\Doctrine\HttpFoundation; +@trigger_error(sprintf('The class %s is deprecated since version 3.4 and will be removed in 4.0. Use Symfony\Component\HttpFoundation\Session\Storage\Handler\PdoSessionHandler instead.', DbalSessionHandler::class), E_USER_DEPRECATED); + use Doctrine\DBAL\Connection; use Doctrine\DBAL\Driver\DriverException; use Doctrine\DBAL\Driver\ServerInfoAwareConnection; @@ -25,6 +27,8 @@ * @author Fabien Potencier * @author Johannes M. Schmitt * @author Tobias Schultze + * + * @deprecated since version 3.4, to be removed in 4.0. Use Symfony\Component\HttpFoundation\Session\Storage\Handler\PdoSessionHandler instead. */ class DbalSessionHandler implements \SessionHandlerInterface { diff --git a/src/Symfony/Bridge/Doctrine/HttpFoundation/DbalSessionHandlerSchema.php b/src/Symfony/Bridge/Doctrine/HttpFoundation/DbalSessionHandlerSchema.php index 978373da0cbd0..7af50a65074f8 100644 --- a/src/Symfony/Bridge/Doctrine/HttpFoundation/DbalSessionHandlerSchema.php +++ b/src/Symfony/Bridge/Doctrine/HttpFoundation/DbalSessionHandlerSchema.php @@ -11,12 +11,16 @@ namespace Symfony\Bridge\Doctrine\HttpFoundation; +@trigger_error(sprintf('The class %s is deprecated since version 3.4 and will be removed in 4.0. Use Symfony\Component\HttpFoundation\Session\Storage\Handler\PdoSessionHandler::createTable instead.', DbalSessionHandlerSchema::class), E_USER_DEPRECATED); + use Doctrine\DBAL\Schema\Schema; /** * DBAL Session Storage Schema. * * @author Johannes M. Schmitt + * + * @deprecated since version 3.4, to be removed in 4.0. Use Symfony\Component\HttpFoundation\Session\Storage\Handler\PdoSessionHandler::createTable instead. */ final class DbalSessionHandlerSchema extends Schema { diff --git a/src/Symfony/Bridge/Doctrine/Tests/HttpFoundation/DbalSessionHandlerTest.php b/src/Symfony/Bridge/Doctrine/Tests/HttpFoundation/DbalSessionHandlerTest.php index 1c9c82bc129e6..8d46bf9e63beb 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/HttpFoundation/DbalSessionHandlerTest.php +++ b/src/Symfony/Bridge/Doctrine/Tests/HttpFoundation/DbalSessionHandlerTest.php @@ -18,6 +18,8 @@ * Test class for DbalSessionHandler. * * @author Drak + * + * @group legacy */ class DbalSessionHandlerTest extends TestCase { From 41665b759f381ce1942ada2c67695025e73e801d Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Sun, 1 Oct 2017 10:11:23 -0700 Subject: [PATCH 0971/1099] fixed CS --- .../Extension/FormExtensionBootstrap4HorizontalLayoutTest.php | 2 +- .../Twig/Tests/Extension/FormExtensionBootstrap4LayoutTest.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionBootstrap4HorizontalLayoutTest.php b/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionBootstrap4HorizontalLayoutTest.php index 842150dc5e0fa..d7afc2cf26238 100644 --- a/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionBootstrap4HorizontalLayoutTest.php +++ b/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionBootstrap4HorizontalLayoutTest.php @@ -63,7 +63,7 @@ protected function renderForm(FormView $view, array $vars = array()) protected function renderLabel(FormView $view, $label = null, array $vars = array()) { - if ($label !== null) { + if (null !== $label) { $vars += array('label' => $label); } diff --git a/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionBootstrap4LayoutTest.php b/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionBootstrap4LayoutTest.php index 4650246cda4f7..0dfa1ebadbe39 100644 --- a/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionBootstrap4LayoutTest.php +++ b/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionBootstrap4LayoutTest.php @@ -85,7 +85,7 @@ protected function renderForm(FormView $view, array $vars = array()) protected function renderLabel(FormView $view, $label = null, array $vars = array()) { - if ($label !== null) { + if (null !== $label) { $vars += array('label' => $label); } From f96a7f81b87db7bc92822d734b8c7abd495d199d Mon Sep 17 00:00:00 2001 From: adev Date: Mon, 17 Apr 2017 20:52:26 +0200 Subject: [PATCH 0972/1099] [Form] Fixed PercentToLocalizedStringTransformer to accept both comma and dot as decimal separator, if possible --- .../PercentToLocalizedStringTransformer.php | 12 ++ ...ercentToLocalizedStringTransformerTest.php | 117 ++++++++++++++++++ 2 files changed, 129 insertions(+) diff --git a/src/Symfony/Component/Form/Extension/Core/DataTransformer/PercentToLocalizedStringTransformer.php b/src/Symfony/Component/Form/Extension/Core/DataTransformer/PercentToLocalizedStringTransformer.php index 7fc191a054ff4..6d209c9d60232 100644 --- a/src/Symfony/Component/Form/Extension/Core/DataTransformer/PercentToLocalizedStringTransformer.php +++ b/src/Symfony/Component/Form/Extension/Core/DataTransformer/PercentToLocalizedStringTransformer.php @@ -119,6 +119,18 @@ public function reverseTransform($value) } $formatter = $this->getNumberFormatter(); + $groupSep = $formatter->getSymbol(\NumberFormatter::GROUPING_SEPARATOR_SYMBOL); + $decSep = $formatter->getSymbol(\NumberFormatter::DECIMAL_SEPARATOR_SYMBOL); + $grouping = $formatter->getAttribute(\NumberFormatter::GROUPING_USED); + + if ('.' !== $decSep && (!$grouping || '.' !== $groupSep)) { + $value = str_replace('.', $decSep, $value); + } + + if (',' !== $decSep && (!$grouping || ',' !== $groupSep)) { + $value = str_replace(',', $decSep, $value); + } + // replace normal spaces so that the formatter can read them $value = $formatter->parse(str_replace(' ', "\xc2\xa0", $value)); diff --git a/src/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/PercentToLocalizedStringTransformerTest.php b/src/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/PercentToLocalizedStringTransformerTest.php index abcc72e2315f8..24cef424d1c3e 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/PercentToLocalizedStringTransformerTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/PercentToLocalizedStringTransformerTest.php @@ -119,4 +119,121 @@ public function testReverseTransformExpectsString() $transformer->reverseTransform(1); } + + public function testDecimalSeparatorMayBeDotIfGroupingSeparatorIsNotDot() + { + IntlTestHelper::requireFullIntl($this, '4.8.1.1'); + + \Locale::setDefault('fr'); + $transformer = new PercentToLocalizedStringTransformer(1, 'integer'); + + // completely valid format + $this->assertEquals(1234.5, $transformer->reverseTransform('1 234,5')); + // accept dots + $this->assertEquals(1234.5, $transformer->reverseTransform('1 234.5')); + // omit group separator + $this->assertEquals(1234.5, $transformer->reverseTransform('1234,5')); + $this->assertEquals(1234.5, $transformer->reverseTransform('1234.5')); + } + + /** + * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException + */ + public function testDecimalSeparatorMayNotBeDotIfGroupingSeparatorIsDot() + { + // Since we test against "de_AT", we need the full implementation + IntlTestHelper::requireFullIntl($this, '4.8.1.1'); + + \Locale::setDefault('de_AT'); + + $transformer = new PercentToLocalizedStringTransformer(1, 'integer'); + + $transformer->reverseTransform('1.234.5'); + } + + /** + * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException + */ + public function testDecimalSeparatorMayNotBeDotIfGroupingSeparatorIsDotWithNoGroupSep() + { + // Since we test against "de_DE", we need the full implementation + IntlTestHelper::requireFullIntl($this, '4.8.1.1'); + + \Locale::setDefault('de_DE'); + + $transformer = new PercentToLocalizedStringTransformer(1, 'integer'); + + $transformer->reverseTransform('1234.5'); + } + + public function testDecimalSeparatorMayBeDotIfGroupingSeparatorIsDotButNoGroupingUsed() + { + // Since we test against other locales, we need the full implementation + IntlTestHelper::requireFullIntl($this, false); + + \Locale::setDefault('fr'); + $transformer = new PercentToLocalizedStringTransformer(1, 'integer'); + + $this->assertEquals(1234.5, $transformer->reverseTransform('1234,5')); + $this->assertEquals(1234.5, $transformer->reverseTransform('1234.5')); + } + + public function testDecimalSeparatorMayBeCommaIfGroupingSeparatorIsNotComma() + { + // Since we test against other locales, we need the full implementation + IntlTestHelper::requireFullIntl($this, '4.8.1.1'); + + \Locale::setDefault('bg'); + $transformer = new PercentToLocalizedStringTransformer(1, 'integer'); + + // completely valid format + $this->assertEquals(1234.5, $transformer->reverseTransform('1 234.5')); + // accept commas + $this->assertEquals(1234.5, $transformer->reverseTransform('1 234,5')); + // omit group separator + $this->assertEquals(1234.5, $transformer->reverseTransform('1234.5')); + $this->assertEquals(1234.5, $transformer->reverseTransform('1234,5')); + } + + /** + * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException + */ + public function testDecimalSeparatorMayNotBeCommaIfGroupingSeparatorIsComma() + { + IntlTestHelper::requireFullIntl($this, '4.8.1.1'); + + $transformer = new PercentToLocalizedStringTransformer(1, 'integer'); + + $transformer->reverseTransform('1,234,5'); + } + + /** + * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException + */ + public function testDecimalSeparatorMayNotBeCommaIfGroupingSeparatorIsCommaWithNoGroupSep() + { + IntlTestHelper::requireFullIntl($this, '4.8.1.1'); + + $transformer = new PercentToLocalizedStringTransformer(1, 'integer'); + + $transformer->reverseTransform('1234,5'); + } + + public function testDecimalSeparatorMayBeCommaIfGroupingSeparatorIsCommaButNoGroupingUsed() + { + $formatter = new \NumberFormatter(\Locale::getDefault(), \NumberFormatter::DECIMAL); + $formatter->setAttribute(\NumberFormatter::FRACTION_DIGITS, 1); + $formatter->setAttribute(\NumberFormatter::GROUPING_USED, false); + + $transformer = $this->getMockBuilder('Symfony\Component\Form\Extension\Core\DataTransformer\PercentToLocalizedStringTransformer') + ->setMethods(array('getNumberFormatter')) + ->setConstructorArgs(array(1, 'integer')) + ->getMock(); + $transformer->expects($this->any()) + ->method('getNumberFormatter') + ->willReturn($formatter); + + $this->assertEquals(1234.5, $transformer->reverseTransform('1234,5')); + $this->assertEquals(1234.5, $transformer->reverseTransform('1234.5')); + } } From 2eedc1fd3760ca74c909df1de09e3ff6c9ea10cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9my=20Deruss=C3=A9?= Date: Thu, 23 Mar 2017 21:40:19 +0100 Subject: [PATCH 0973/1099] [Lock] Automaticaly release lock when user forget it --- src/Symfony/Component/Lock/Factory.php | 9 ++-- src/Symfony/Component/Lock/Lock.php | 31 +++++++++++--- .../Component/Lock/Store/SemaphoreStore.php | 2 +- src/Symfony/Component/Lock/Tests/LockTest.php | 42 ++++++++++++++++++- 4 files changed, 72 insertions(+), 12 deletions(-) diff --git a/src/Symfony/Component/Lock/Factory.php b/src/Symfony/Component/Lock/Factory.php index c050145f90978..e9fdde97e8b35 100644 --- a/src/Symfony/Component/Lock/Factory.php +++ b/src/Symfony/Component/Lock/Factory.php @@ -36,14 +36,15 @@ public function __construct(StoreInterface $store) /** * Creates a lock for the given resource. * - * @param string $resource The resource to lock - * @param float $ttl maximum expected lock duration + * @param string $resource The resource to lock + * @param float $ttl Maximum expected lock duration in seconds + * @param bool $autoRelease Whether to automatically release the lock or not when the lock instance is destroyed * * @return Lock */ - public function createLock($resource, $ttl = 300.0) + public function createLock($resource, $ttl = 300.0, $autoRelease = true) { - $lock = new Lock(new Key($resource), $this->store, $ttl); + $lock = new Lock(new Key($resource), $this->store, $ttl, $autoRelease); $lock->setLogger($this->logger); return $lock; diff --git a/src/Symfony/Component/Lock/Lock.php b/src/Symfony/Component/Lock/Lock.php index d8271569d8c05..e81878a43725c 100644 --- a/src/Symfony/Component/Lock/Lock.php +++ b/src/Symfony/Component/Lock/Lock.php @@ -32,21 +32,37 @@ final class Lock implements LockInterface, LoggerAwareInterface private $store; private $key; private $ttl; + private $autoRelease; + private $dirty = false; /** - * @param Key $key - * @param StoreInterface $store - * @param float|null $ttl + * @param Key $key Resource to lock + * @param StoreInterface $store Store used to handle lock persistence + * @param float|null $ttl Maximum expected lock duration in seconds + * @param bool $autoRelease Whether to automatically release the lock or not when the lock instance is destroyed */ - public function __construct(Key $key, StoreInterface $store, $ttl = null) + public function __construct(Key $key, StoreInterface $store, $ttl = null, $autoRelease = true) { $this->store = $store; $this->key = $key; $this->ttl = $ttl; + $this->autoRelease = (bool) $autoRelease; $this->logger = new NullLogger(); } + /** + * Automatically releases the underlying lock when the object is destructed. + */ + public function __destruct() + { + if (!$this->autoRelease || !$this->dirty || !$this->isAcquired()) { + return; + } + + $this->release(); + } + /** * {@inheritdoc} */ @@ -59,6 +75,7 @@ public function acquire($blocking = false) $this->store->waitAndSave($this->key); } + $this->dirty = true; $this->logger->info('Successfully acquired the "{resource}" lock.', array('resource' => $this->key)); if ($this->ttl) { @@ -71,6 +88,7 @@ public function acquire($blocking = false) return true; } catch (LockConflictedException $e) { + $this->dirty = false; $this->logger->warning('Failed to acquire the "{resource}" lock. Someone else already acquired the lock.', array('resource' => $this->key)); if ($blocking) { @@ -96,6 +114,7 @@ public function refresh() try { $this->key->resetLifetime(); $this->store->putOffExpiration($this->key, $this->ttl); + $this->dirty = true; if ($this->key->isExpired()) { throw new LockExpiredException(sprintf('Failed to put off the expiration of the "%s" lock within the specified time.', $this->key)); @@ -103,6 +122,7 @@ public function refresh() $this->logger->info('Expiration defined for "{resource}" lock for "{ttl}" seconds.', array('resource' => $this->key, 'ttl' => $this->ttl)); } catch (LockConflictedException $e) { + $this->dirty = false; $this->logger->warning('Failed to define an expiration for the "{resource}" lock, someone else acquired the lock.', array('resource' => $this->key)); throw $e; } catch (\Exception $e) { @@ -116,7 +136,7 @@ public function refresh() */ public function isAcquired() { - return $this->store->exists($this->key); + return $this->dirty = $this->store->exists($this->key); } /** @@ -125,6 +145,7 @@ public function isAcquired() public function release() { $this->store->delete($this->key); + $this->dirty = false; if ($this->store->exists($this->key)) { $this->logger->warning('Failed to release the "{resource}" lock.', array('resource' => $this->key)); diff --git a/src/Symfony/Component/Lock/Store/SemaphoreStore.php b/src/Symfony/Component/Lock/Store/SemaphoreStore.php index fe9455cccea09..a6cc9ea8b9f1d 100644 --- a/src/Symfony/Component/Lock/Store/SemaphoreStore.php +++ b/src/Symfony/Component/Lock/Store/SemaphoreStore.php @@ -116,7 +116,7 @@ public function delete(Key $key) */ public function putOffExpiration(Key $key, $ttl) { - // do nothing, the flock locks forever. + // do nothing, the semaphore locks forever. } /** diff --git a/src/Symfony/Component/Lock/Tests/LockTest.php b/src/Symfony/Component/Lock/Tests/LockTest.php index 97b376621169a..ece5cf667963a 100644 --- a/src/Symfony/Component/Lock/Tests/LockTest.php +++ b/src/Symfony/Component/Lock/Tests/LockTest.php @@ -103,10 +103,10 @@ public function testIsAquired() $lock = new Lock($key, $store, 10); $store - ->expects($this->once()) + ->expects($this->any()) ->method('exists') ->with($key) - ->willReturn(true); + ->will($this->onConsecutiveCalls(true, false)); $this->assertTrue($lock->isAcquired()); } @@ -131,6 +131,44 @@ public function testRelease() $lock->release(); } + public function testReleaseOnDestruction() + { + $key = new Key(uniqid(__METHOD__, true)); + $store = $this->getMockBuilder(StoreInterface::class)->getMock(); + $lock = new Lock($key, $store, 10); + + $store + ->method('exists') + ->willReturnOnConsecutiveCalls(array(true, false)) + ; + $store + ->expects($this->once()) + ->method('delete') + ; + + $lock->acquire(false); + unset($lock); + } + + public function testNoAutoReleaseWhenNotConfigured() + { + $key = new Key(uniqid(__METHOD__, true)); + $store = $this->getMockBuilder(StoreInterface::class)->getMock(); + $lock = new Lock($key, $store, 10, false); + + $store + ->method('exists') + ->willReturnOnConsecutiveCalls(array(true, false)) + ; + $store + ->expects($this->never()) + ->method('delete') + ; + + $lock->acquire(false); + unset($lock); + } + /** * @expectedException \Symfony\Component\Lock\Exception\LockReleasingException */ From 7ae06dc6174cd14fee5a2b7c984a2299c199b1a6 Mon Sep 17 00:00:00 2001 From: Ilya Vertakov Date: Wed, 9 Aug 2017 22:55:49 +0400 Subject: [PATCH 0974/1099] [Validator] Add unique entity violation cause --- src/Symfony/Bridge/Doctrine/CHANGELOG.md | 1 + .../Constraints/UniqueEntityValidatorTest.php | 46 +++++++++++++++++++ .../Constraints/UniqueEntityValidator.php | 1 + 3 files changed, 48 insertions(+) diff --git a/src/Symfony/Bridge/Doctrine/CHANGELOG.md b/src/Symfony/Bridge/Doctrine/CHANGELOG.md index ba74440bc6e96..0258a36a998ee 100644 --- a/src/Symfony/Bridge/Doctrine/CHANGELOG.md +++ b/src/Symfony/Bridge/Doctrine/CHANGELOG.md @@ -5,6 +5,7 @@ CHANGELOG ----- * added support for doctrine/dbal v2.6 types + * added cause of UniqueEntity constraint violation 3.1.0 ----- diff --git a/src/Symfony/Bridge/Doctrine/Tests/Validator/Constraints/UniqueEntityValidatorTest.php b/src/Symfony/Bridge/Doctrine/Tests/Validator/Constraints/UniqueEntityValidatorTest.php index 2074eacae7a99..878e19ccb5cd9 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/Validator/Constraints/UniqueEntityValidatorTest.php +++ b/src/Symfony/Bridge/Doctrine/Tests/Validator/Constraints/UniqueEntityValidatorTest.php @@ -190,6 +190,7 @@ public function testValidateUniqueness() ->atPath('property.path.name') ->setParameter('{{ value }}', '"Foo"') ->setInvalidValue($entity2) + ->setCause(array($entity1)) ->setCode(UniqueEntity::NOT_UNIQUE_ERROR) ->assertRaised(); } @@ -215,6 +216,7 @@ public function testValidateCustomErrorPath() ->atPath('property.path.bar') ->setParameter('{{ value }}', '"Foo"') ->setInvalidValue($entity2) + ->setCause(array($entity1)) ->setCode(UniqueEntity::NOT_UNIQUE_ERROR) ->assertRaised(); } @@ -268,6 +270,7 @@ public function testValidateUniquenessWithIgnoreNullDisabled() ->atPath('property.path.name') ->setParameter('{{ value }}', '"Foo"') ->setInvalidValue('Foo') + ->setCause(array($entity1)) ->setCode(UniqueEntity::NOT_UNIQUE_ERROR) ->assertRaised(); } @@ -346,6 +349,7 @@ public function testValidateUniquenessWithValidCustomErrorPath() ->atPath('property.path.name2') ->setParameter('{{ value }}', '"Bar"') ->setInvalidValue('Bar') + ->setCause(array($entity1)) ->setCode(UniqueEntity::NOT_UNIQUE_ERROR) ->assertRaised(); } @@ -481,6 +485,7 @@ public function testAssociatedEntity() ->setParameter('{{ value }}', 'object("Symfony\Bridge\Doctrine\Tests\Fixtures\SingleIntIdEntity") identified by (id => 1)') ->setInvalidValue($entity1) ->setCode(UniqueEntity::NOT_UNIQUE_ERROR) + ->setCause(array($associated, $associated2)) ->assertRaised(); } @@ -517,6 +522,7 @@ public function testValidateUniquenessNotToStringEntityWithAssociatedEntity() ->atPath('property.path.single') ->setParameter('{{ value }}', $expectedValue) ->setInvalidValue($entity1) + ->setCause(array($associated, $associated2)) ->setCode(UniqueEntity::NOT_UNIQUE_ERROR) ->assertRaised(); } @@ -575,6 +581,7 @@ public function testValidateUniquenessWithArrayValue() ->atPath('property.path.phoneNumbers') ->setParameter('{{ value }}', 'array') ->setInvalidValue(array(123)) + ->setCause(array($entity1)) ->setCode(UniqueEntity::NOT_UNIQUE_ERROR) ->assertRaised(); } @@ -652,6 +659,7 @@ public function testValidateInheritanceUniqueness() ->atPath('property.path.name') ->setInvalidValue('Foo') ->setCode('23bd9dbf-6b9b-41cd-a99e-4844bcf3077f') + ->setCause(array($entity1)) ->setParameters(array('{{ value }}' => '"Foo"')) ->assertRaised(); } @@ -703,6 +711,7 @@ public function testValidateUniquenessWithCompositeObjectNoToStringIdEntity() ->atPath('property.path.objectOne') ->setParameter('{{ value }}', $expectedValue) ->setInvalidValue($objectOne) + ->setCause(array($entity)) ->setCode(UniqueEntity::NOT_UNIQUE_ERROR) ->assertRaised(); } @@ -730,6 +739,43 @@ public function testValidateUniquenessWithCustomDoctrineTypeValue() ->atPath('property.path.name') ->setParameter('{{ value }}', $expectedValue) ->setInvalidValue($existingEntity->name) + ->setCause(array($existingEntity)) + ->setCode(UniqueEntity::NOT_UNIQUE_ERROR) + ->assertRaised(); + } + + /** + * This is a functional test as there is a large integration necessary to get the validator working. + */ + public function testValidateUniquenessCause() + { + $constraint = new UniqueEntity(array( + 'message' => 'myMessage', + 'fields' => array('name'), + 'em' => self::EM_NAME, + )); + + $entity1 = new SingleIntIdEntity(1, 'Foo'); + $entity2 = new SingleIntIdEntity(2, 'Foo'); + + $this->validator->validate($entity1, $constraint); + + $this->assertNoViolation(); + + $this->em->persist($entity1); + $this->em->flush(); + + $this->validator->validate($entity1, $constraint); + + $this->assertNoViolation(); + + $this->validator->validate($entity2, $constraint); + + $this->buildViolation('myMessage') + ->atPath('property.path.name') + ->setParameter('{{ value }}', '"Foo"') + ->setInvalidValue($entity2) + ->setCause(array($entity1)) ->setCode(UniqueEntity::NOT_UNIQUE_ERROR) ->assertRaised(); } diff --git a/src/Symfony/Bridge/Doctrine/Validator/Constraints/UniqueEntityValidator.php b/src/Symfony/Bridge/Doctrine/Validator/Constraints/UniqueEntityValidator.php index 78d82b322568b..95e8197c35fac 100644 --- a/src/Symfony/Bridge/Doctrine/Validator/Constraints/UniqueEntityValidator.php +++ b/src/Symfony/Bridge/Doctrine/Validator/Constraints/UniqueEntityValidator.php @@ -171,6 +171,7 @@ public function validate($entity, Constraint $constraint) ->setParameter('{{ value }}', $this->formatWithIdentifiers($em, $class, $invalidValue)) ->setInvalidValue($invalidValue) ->setCode(UniqueEntity::NOT_UNIQUE_ERROR) + ->setCause($result) ->addViolation(); } From aaba6b4c2bdbe2d4a92754ea4f9a43570af2ff16 Mon Sep 17 00:00:00 2001 From: stoccc Date: Fri, 25 Aug 2017 09:11:28 +0200 Subject: [PATCH 0975/1099] Tests and fix for issue in array model data in EntityType field with multiple=true --- .../Tests/Form/Type/EntityTypeTest.php | 34 +++++++++++++++++++ src/Symfony/Bridge/Doctrine/composer.json | 2 +- .../EventListener/MergeCollectionListener.php | 2 +- 3 files changed, 36 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Bridge/Doctrine/Tests/Form/Type/EntityTypeTest.php b/src/Symfony/Bridge/Doctrine/Tests/Form/Type/EntityTypeTest.php index 587ebd6b3e24d..a7d41ce8f3270 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/Form/Type/EntityTypeTest.php +++ b/src/Symfony/Bridge/Doctrine/Tests/Form/Type/EntityTypeTest.php @@ -1482,4 +1482,38 @@ public function testSubmitNullExpandedMultiple() $this->assertEquals($collection, $form->getNormData()); $this->assertSame(array(), $form->getViewData(), 'View data is always an array'); } + + public function testSetDataEmptyArraySubmitNullMultiple() + { + $emptyArray = array(); + $form = $this->factory->create(static::TESTED_TYPE, null, array( + 'em' => 'default', + 'class' => self::SINGLE_IDENT_CLASS, + 'multiple' => true, + )); + $form->setData($emptyArray); + $form->submit(null); + $this->assertInternalType('array', $form->getData()); + $this->assertEquals(array(), $form->getData()); + $this->assertEquals(array(), $form->getNormData()); + $this->assertSame(array(), $form->getViewData(), 'View data is always an array'); + } + + public function testSetDataNonEmptyArraySubmitNullMultiple() + { + $entity1 = new SingleIntIdEntity(1, 'Foo'); + $this->persist(array($entity1)); + $form = $this->factory->create(static::TESTED_TYPE, null, array( + 'em' => 'default', + 'class' => self::SINGLE_IDENT_CLASS, + 'multiple' => true, + )); + $existing = array(0 => $entity1); + $form->setData($existing); + $form->submit(null); + $this->assertInternalType('array', $form->getData()); + $this->assertEquals(array(), $form->getData()); + $this->assertEquals(array(), $form->getNormData()); + $this->assertSame(array(), $form->getViewData(), 'View data is always an array'); + } } diff --git a/src/Symfony/Bridge/Doctrine/composer.json b/src/Symfony/Bridge/Doctrine/composer.json index 22635d45ecc7b..dc8e0d528f5db 100644 --- a/src/Symfony/Bridge/Doctrine/composer.json +++ b/src/Symfony/Bridge/Doctrine/composer.json @@ -22,7 +22,7 @@ "require-dev": { "symfony/stopwatch": "~2.2", "symfony/dependency-injection": "~2.2", - "symfony/form": "~2.7.25|^2.8.18", + "symfony/form": "~2.7.34|^2.8.27", "symfony/http-kernel": "~2.2", "symfony/property-access": "~2.3", "symfony/security": "~2.2", diff --git a/src/Symfony/Component/Form/Extension/Core/EventListener/MergeCollectionListener.php b/src/Symfony/Component/Form/Extension/Core/EventListener/MergeCollectionListener.php index a65116fd5c8ce..0c16bd42ba9cd 100644 --- a/src/Symfony/Component/Form/Extension/Core/EventListener/MergeCollectionListener.php +++ b/src/Symfony/Component/Form/Extension/Core/EventListener/MergeCollectionListener.php @@ -80,7 +80,7 @@ public function onSubmit(FormEvent $event) return; } - if (!$dataToMergeInto) { + if (null === $dataToMergeInto) { // No original data was set. Set it if allowed if ($this->allowAdd) { $dataToMergeInto = $data; From 17a413876a3d04597e01772a9aee35ea56ae0cae Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Sun, 1 Oct 2017 22:19:02 +0200 Subject: [PATCH 0976/1099] Remove remaining `@experimental` annotations --- .../DependencyInjection/Security/Factory/JsonLoginFactory.php | 2 -- src/Symfony/Component/Cache/CacheItem.php | 2 -- .../Firewall/UsernamePasswordJsonAuthenticationListener.php | 2 -- 3 files changed, 6 deletions(-) diff --git a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/JsonLoginFactory.php b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/JsonLoginFactory.php index c69cab8949af6..28a7bf5743078 100644 --- a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/JsonLoginFactory.php +++ b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/JsonLoginFactory.php @@ -19,8 +19,6 @@ * JsonLoginFactory creates services for JSON login authentication. * * @author Kévin Dunglas - * - * @experimental in version 3.3 */ class JsonLoginFactory extends AbstractFactory { diff --git a/src/Symfony/Component/Cache/CacheItem.php b/src/Symfony/Component/Cache/CacheItem.php index d6f629b2abc70..93ffea495e88f 100644 --- a/src/Symfony/Component/Cache/CacheItem.php +++ b/src/Symfony/Component/Cache/CacheItem.php @@ -135,8 +135,6 @@ public function tag($tags) * Returns the list of tags bound to the value coming from the pool storage if any. * * @return array - * - * @experimental in version 3.3 */ public function getPreviousTags() { diff --git a/src/Symfony/Component/Security/Http/Firewall/UsernamePasswordJsonAuthenticationListener.php b/src/Symfony/Component/Security/Http/Firewall/UsernamePasswordJsonAuthenticationListener.php index 0c7e8bda36878..955288c23c375 100644 --- a/src/Symfony/Component/Security/Http/Firewall/UsernamePasswordJsonAuthenticationListener.php +++ b/src/Symfony/Component/Security/Http/Firewall/UsernamePasswordJsonAuthenticationListener.php @@ -39,8 +39,6 @@ * an authentication via a JSON document composed of a username and a password. * * @author Kévin Dunglas - * - * @experimental in version 3.3 */ class UsernamePasswordJsonAuthenticationListener implements ListenerInterface { From 09e512851ffb84288e55a1ac9c2d31514032e764 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Mon, 2 Oct 2017 08:54:00 +0200 Subject: [PATCH 0977/1099] Fix in simple-phpunit script --- src/Symfony/Bridge/PhpUnit/bin/simple-phpunit | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/Symfony/Bridge/PhpUnit/bin/simple-phpunit b/src/Symfony/Bridge/PhpUnit/bin/simple-phpunit index ae4c818aa327f..869e8dc0d52b5 100755 --- a/src/Symfony/Bridge/PhpUnit/bin/simple-phpunit +++ b/src/Symfony/Bridge/PhpUnit/bin/simple-phpunit @@ -38,7 +38,11 @@ $COMPOSER = file_exists($COMPOSER = $oldPwd.'/composer.phar') || ($COMPOSER = rt ? $PHP.' '.escapeshellarg($COMPOSER) : 'composer'; -if (!file_exists("$PHPUNIT_DIR/phpunit-$PHPUNIT_VERSION/phpunit") || md5_file(__FILE__)."\n".getenv('SYMFONY_PHPUNIT_REMOVE') !== @file_get_contents("$PHPUNIT_DIR/.$PHPUNIT_VERSION.md5")) { +if (false === $SYMFONY_PHPUNIT_REMOVE = getenv('SYMFONY_PHPUNIT_REMOVE')) { + $SYMFONY_PHPUNIT_REMOVE = 'phpspec/prophecy symfony/yaml'; +} + +if (!file_exists("$PHPUNIT_DIR/phpunit-$PHPUNIT_VERSION/phpunit") || md5_file(__FILE__)."\n".$SYMFONY_PHPUNIT_REMOVE !== @file_get_contents("$PHPUNIT_DIR/.$PHPUNIT_VERSION.md5")) { // Build a standalone phpunit without symfony/yaml nor prophecy by default @mkdir($PHPUNIT_DIR, 0777, true); @@ -60,8 +64,7 @@ if (!file_exists("$PHPUNIT_DIR/phpunit-$PHPUNIT_VERSION/phpunit") || md5_file(__ $zip->extractTo(getcwd()); $zip->close(); chdir("phpunit-$PHPUNIT_VERSION"); - $SYMFONY_PHPUNIT_REMOVE = getenv('SYMFONY_PHPUNIT_REMOVE'); - passthru("$COMPOSER remove --no-update ".('' === $SYMFONY_PHPUNIT_REMOVE ?: 'phpspec/prophecy symfony/yaml')); + passthru("$COMPOSER remove --no-update ".$SYMFONY_PHPUNIT_REMOVE); if (5.1 <= $PHPUNIT_VERSION && $PHPUNIT_VERSION < 5.4) { passthru("$COMPOSER require --no-update phpunit/phpunit-mock-objects \"~3.1.0\""); } @@ -83,7 +86,7 @@ Symfony\Bridge\PhpUnit\TextUI\Command::main(); EOPHP ); chdir('..'); - file_put_contents(".$PHPUNIT_VERSION.md5", md5_file(__FILE__)."\n".getenv('SYMFONY_PHPUNIT_REMOVE')); + file_put_contents(".$PHPUNIT_VERSION.md5", md5_file(__FILE__)."\n".$SYMFONY_PHPUNIT_REMOVE); chdir($oldPwd); } From 90986f450251a02067cd263427c40d0e6ea7a46e Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Mon, 2 Oct 2017 09:00:01 +0200 Subject: [PATCH 0978/1099] fix merge --- .../Tests/Fixtures/php/services9_as_files.txt | 3 --- .../Tests/Fixtures/php/services_array_params.php | 3 --- .../Tests/Fixtures/php/services_base64_env.php | 3 --- .../Tests/Fixtures/php/services_legacy_privates.php | 3 --- .../Tests/Fixtures/php/services_rot13_env.php | 3 --- .../Tests/Fixtures/php/services_uninitialized_ref.php | 3 --- 6 files changed, 18 deletions(-) diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_as_files.txt b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_as_files.txt index d6c0fc11eddff..4af0de98e4b26 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_as_files.txt +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_as_files.txt @@ -279,9 +279,6 @@ class Container%s extends Container private $parameters; private $targetDirs = array(); - /** - * Constructor. - */ public function __construct() { $dir = $this->targetDirs[0] = dirname(__DIR__); diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_array_params.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_array_params.php index d848941013388..69a1297129bd9 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_array_params.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_array_params.php @@ -21,9 +21,6 @@ class ProjectServiceContainer extends Container private $parameters; private $targetDirs = array(); - /** - * Constructor. - */ public function __construct() { $dir = __DIR__; diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_base64_env.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_base64_env.php index 4f4c7e79df38b..4b143565f153d 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_base64_env.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_base64_env.php @@ -21,9 +21,6 @@ class Symfony_DI_PhpDumper_Test_Base64Parameters extends Container private $parameters; private $targetDirs = array(); - /** - * Constructor. - */ public function __construct() { $this->parameters = $this->getDefaultParameters(); diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_legacy_privates.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_legacy_privates.php index 611b0cf4acadd..25e7943ed49b0 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_legacy_privates.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_legacy_privates.php @@ -21,9 +21,6 @@ class Symfony_DI_PhpDumper_Test_Legacy_Privates extends Container private $parameters; private $targetDirs = array(); - /** - * Constructor. - */ public function __construct() { $dir = __DIR__; diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_rot13_env.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_rot13_env.php index 2e08cdcb42f92..cc5235bba6a59 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_rot13_env.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_rot13_env.php @@ -21,9 +21,6 @@ class Symfony_DI_PhpDumper_Test_Rot13Parameters extends Container private $parameters; private $targetDirs = array(); - /** - * Constructor. - */ public function __construct() { $this->parameters = $this->getDefaultParameters(); diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_uninitialized_ref.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_uninitialized_ref.php index 4c26d58d70c28..f89b35c9eb1a0 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_uninitialized_ref.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_uninitialized_ref.php @@ -21,9 +21,6 @@ class Symfony_DI_PhpDumper_Test_Uninitialized_Reference extends Container private $parameters; private $targetDirs = array(); - /** - * Constructor. - */ public function __construct() { $this->services = array(); From ef4f532395a65c5b67855412c0fd0ccfc9b35261 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Mon, 2 Oct 2017 09:17:52 +0200 Subject: [PATCH 0979/1099] fix merge --- .../DependencyInjection/Tests/Fixtures/php/services24.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services24.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services24.php index 2f34ad9fb7fa9..f546d6736ca3b 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services24.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services24.php @@ -9,8 +9,6 @@ use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag; /** - * ProjectServiceContainer. - * * This class has been auto-generated * by the Symfony Dependency Injection Component. */ From 7fa94dc84608e0f5347547a00dd52dd4be7ef85e Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Mon, 2 Oct 2017 09:25:00 +0200 Subject: [PATCH 0980/1099] fix merge --- .../Component/Routing/Tests/Fixtures/dumper/url_matcher4.php | 2 -- .../Component/Routing/Tests/Fixtures/dumper/url_matcher5.php | 2 -- .../Component/Routing/Tests/Fixtures/dumper/url_matcher6.php | 2 -- .../Component/Routing/Tests/Fixtures/dumper/url_matcher7.php | 2 -- 4 files changed, 8 deletions(-) diff --git a/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher4.php b/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher4.php index 2dc9028325ca7..6aefd6938272c 100644 --- a/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher4.php +++ b/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher4.php @@ -5,8 +5,6 @@ use Symfony\Component\Routing\RequestContext; /** - * ProjectUrlMatcher. - * * This class has been auto-generated * by the Symfony Routing Component. */ diff --git a/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher5.php b/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher5.php index c92de2fcc5ca5..1884df1c45e27 100644 --- a/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher5.php +++ b/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher5.php @@ -5,8 +5,6 @@ use Symfony\Component\Routing\RequestContext; /** - * ProjectUrlMatcher. - * * This class has been auto-generated * by the Symfony Routing Component. */ diff --git a/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher6.php b/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher6.php index c85334cb4b769..bb9d80b55181b 100644 --- a/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher6.php +++ b/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher6.php @@ -5,8 +5,6 @@ use Symfony\Component\Routing\RequestContext; /** - * ProjectUrlMatcher. - * * This class has been auto-generated * by the Symfony Routing Component. */ diff --git a/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher7.php b/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher7.php index b701742320fd0..404d462ed5415 100644 --- a/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher7.php +++ b/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher7.php @@ -5,8 +5,6 @@ use Symfony\Component\Routing\RequestContext; /** - * ProjectUrlMatcher. - * * This class has been auto-generated * by the Symfony Routing Component. */ From f86b4c43a3dbd2c49bfc8814fcfec5e1067f4bb3 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Mon, 2 Oct 2017 09:56:07 +0200 Subject: [PATCH 0981/1099] fix tests --- ...application_renderexception_linebreaks.txt | 2 +- .../Filesystem/Tests/FilesystemTest.php | 37 ++++++++++++------- 2 files changed, 24 insertions(+), 15 deletions(-) diff --git a/src/Symfony/Component/Console/Tests/Fixtures/application_renderexception_linebreaks.txt b/src/Symfony/Component/Console/Tests/Fixtures/application_renderexception_linebreaks.txt index e9a9518b4aead..88ee0f29ff748 100644 --- a/src/Symfony/Component/Console/Tests/Fixtures/application_renderexception_linebreaks.txt +++ b/src/Symfony/Component/Console/Tests/Fixtures/application_renderexception_linebreaks.txt @@ -1,6 +1,6 @@ +In ApplicationTest.php line 761: - [InvalidArgumentException] line 1 with extra spaces line 2 diff --git a/src/Symfony/Component/Filesystem/Tests/FilesystemTest.php b/src/Symfony/Component/Filesystem/Tests/FilesystemTest.php index 1954aef93a38b..0273a81b5d7c3 100644 --- a/src/Symfony/Component/Filesystem/Tests/FilesystemTest.php +++ b/src/Symfony/Component/Filesystem/Tests/FilesystemTest.php @@ -1101,7 +1101,6 @@ public function providePathsForMakePathRelative() array('/var/lib/symfony/src/Symfony', '/var/lib/symfony/src/Symfony/Component', '../'), array('/var/lib/symfony/src/Symfony', '/var/lib/symfony/src/Symfony/Component/', '../'), array('/usr/lib/symfony/', '/var/lib/symfony/src/Symfony/Component', '../../../../../../usr/lib/symfony/'), - array('usr/lib/symfony/', 'var/lib/symfony/src/Symfony/Component', '../../../../../../usr/lib/symfony/'), array('/var/lib/symfony/src/Symfony/', '/var/lib/symfony/', 'src/Symfony/'), array('/aa/bb', '/aa/bb', './'), array('/aa/bb', '/aa/bb/', './'), @@ -1133,17 +1132,6 @@ public function providePathsForMakePathRelative() array('C:/aa/bb/../../cc', 'C:/aa/../dd/..', 'cc/'), array('C:/../aa/bb/cc', 'C:/aa/dd/..', 'bb/cc/'), array('C:/../../aa/../bb/cc', 'C:/aa/dd/..', '../bb/cc/'), - array('aa/bb', 'aa/cc', '../bb/'), - array('aa/cc', 'bb/cc', '../../aa/cc/'), - array('aa/bb', 'aa/./cc', '../bb/'), - array('aa/./bb', 'aa/cc', '../bb/'), - array('aa/./bb', 'aa/./cc', '../bb/'), - array('../../', '../../', './'), - array('../aa/bb/', 'aa/bb/', '../../../aa/bb/'), - array('../../../', '../../', '../'), - array('', '', './'), - array('', 'aa/', '../'), - array('aa/', '', 'aa/'), ); if ('\\' === DIRECTORY_SEPARATOR) { @@ -1155,11 +1143,32 @@ public function providePathsForMakePathRelative() /** * @group legacy + * @dataProvider provideLegacyPathsForMakePathRelativeWithRelativePaths * @expectedDeprecation Support for passing relative paths to Symfony\Component\Filesystem\Filesystem::makePathRelative() is deprecated since version 3.4 and will be removed in 4.0. */ - public function testMakePathRelativeWithRelativePaths() + public function testMakePathRelativeWithRelativePaths($endPath, $startPath, $expectedPath) + { + $path = $this->filesystem->makePathRelative($endPath, $startPath); + + $this->assertEquals($expectedPath, $path); + } + + public function provideLegacyPathsForMakePathRelativeWithRelativePaths() { - $this->assertSame('../../../', $this->filesystem->makePathRelative('var/lib/symfony/', 'var/lib/symfony/src/Symfony/Component')); + return array( + array('usr/lib/symfony/', 'var/lib/symfony/src/Symfony/Component', '../../../../../../usr/lib/symfony/'), + array('aa/bb', 'aa/cc', '../bb/'), + array('aa/cc', 'bb/cc', '../../aa/cc/'), + array('aa/bb', 'aa/./cc', '../bb/'), + array('aa/./bb', 'aa/cc', '../bb/'), + array('aa/./bb', 'aa/./cc', '../bb/'), + array('../../', '../../', './'), + array('../aa/bb/', 'aa/bb/', '../../../aa/bb/'), + array('../../../', '../../', '../'), + array('', '', './'), + array('', 'aa/', '../'), + array('aa/', '', 'aa/'), + ); } public function testMirrorCopiesFilesAndDirectoriesRecursively() From 817f594f48c86f2357ffb41a544d0b5838277676 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Mon, 2 Oct 2017 10:43:16 +0200 Subject: [PATCH 0982/1099] fix tests --- src/Symfony/Bridge/Doctrine/composer.json | 2 +- src/Symfony/Component/Filesystem/Tests/FilesystemTest.php | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Bridge/Doctrine/composer.json b/src/Symfony/Bridge/Doctrine/composer.json index dc8e0d528f5db..e9dda5f59ae43 100644 --- a/src/Symfony/Bridge/Doctrine/composer.json +++ b/src/Symfony/Bridge/Doctrine/composer.json @@ -22,7 +22,7 @@ "require-dev": { "symfony/stopwatch": "~2.2", "symfony/dependency-injection": "~2.2", - "symfony/form": "~2.7.34|^2.8.27", + "symfony/form": "~2.7.35|^2.8.28", "symfony/http-kernel": "~2.2", "symfony/property-access": "~2.3", "symfony/security": "~2.2", diff --git a/src/Symfony/Component/Filesystem/Tests/FilesystemTest.php b/src/Symfony/Component/Filesystem/Tests/FilesystemTest.php index fb6c135f925b3..8daee9a9cbfbc 100644 --- a/src/Symfony/Component/Filesystem/Tests/FilesystemTest.php +++ b/src/Symfony/Component/Filesystem/Tests/FilesystemTest.php @@ -374,6 +374,9 @@ public function testFilesExists() */ public function testFilesExistsFails() { + if ('\\' !== DIRECTORY_SEPARATOR) { + $this->markTestSkipped('Long file names are an issue on Windows'); + } $basePath = $this->workspace.'\\directory\\'; $maxPathLength = PHP_MAXPATHLEN - 2; From 7d85ff27bd421efc32caab0ed3cd6e48d9148de8 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Mon, 2 Oct 2017 10:49:00 +0200 Subject: [PATCH 0983/1099] fix merge --- .../Tests/Fixtures/application_renderexception_linebreaks.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/Console/Tests/Fixtures/application_renderexception_linebreaks.txt b/src/Symfony/Component/Console/Tests/Fixtures/application_renderexception_linebreaks.txt index 88ee0f29ff748..64bfe9a183c7a 100644 --- a/src/Symfony/Component/Console/Tests/Fixtures/application_renderexception_linebreaks.txt +++ b/src/Symfony/Component/Console/Tests/Fixtures/application_renderexception_linebreaks.txt @@ -1,5 +1,5 @@ -In ApplicationTest.php line 761: +In ApplicationTest.php line 760: line 1 with extra spaces line 2 From 1eee2a461c40f5de3788d7de832e9ebc05b7c7b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9goire=20Pineau?= Date: Mon, 2 Oct 2017 11:08:26 +0200 Subject: [PATCH 0984/1099] [Process] Removed dead code in the start method --- src/Symfony/Component/Process/Process.php | 27 ++++++++--------------- 1 file changed, 9 insertions(+), 18 deletions(-) diff --git a/src/Symfony/Component/Process/Process.php b/src/Symfony/Component/Process/Process.php index 6141c8b4753c6..5e1e369cffb7e 100644 --- a/src/Symfony/Component/Process/Process.php +++ b/src/Symfony/Component/Process/Process.php @@ -268,26 +268,21 @@ public function start(callable $callback = null, array $env = array()) } } - if (null === $env) { - $env = $this->env; - } elseif ($this->env) { + if ($this->env) { $env += $this->env; } $envBackup = array(); - if (null !== $env) { - foreach ($env as $k => $v) { - $envBackup[$k] = getenv($k); - putenv(false === $v || null === $v ? $k : "$k=$v"); - } - $env = null; + foreach ($env as $k => $v) { + $envBackup[$k] = getenv($k); + putenv(false === $v || null === $v ? $k : "$k=$v"); } $options = array('suppress_errors' => true); if ('\\' === DIRECTORY_SEPARATOR) { $options['bypass_shell'] = true; - $commandline = $this->prepareWindowsCommandLine($commandline, $envBackup, $env); + $commandline = $this->prepareWindowsCommandLine($commandline, $envBackup); } elseif (!$this->useFileHandles && $this->isSigchildEnabled()) { // last exit code is output on the fourth pipe and caught to work around --enable-sigchild $descriptors[3] = array('pipe', 'w'); @@ -301,7 +296,7 @@ public function start(callable $callback = null, array $env = array()) $ptsWorkaround = fopen(__FILE__, 'r'); } - $this->process = proc_open($commandline, $descriptors, $this->processPipes->pipes, $this->cwd, $env, $options); + $this->process = proc_open($commandline, $descriptors, $this->processPipes->pipes, $this->cwd, null, $options); foreach ($envBackup as $k => $v) { putenv(false === $v ? $k : "$k=$v"); @@ -1464,7 +1459,7 @@ private function doSignal($signal, $throwException) return true; } - private function prepareWindowsCommandLine($cmd, array &$envBackup, array &$env = null) + private function prepareWindowsCommandLine($cmd, array &$envBackup) { $uid = uniqid('', true); $varCount = 0; @@ -1477,7 +1472,7 @@ private function prepareWindowsCommandLine($cmd, array &$envBackup, array &$env [^"%!^]*+ )++ ) | [^"]*+ )"/x', - function ($m) use (&$envBackup, &$env, &$varCache, &$varCount, $uid) { + function ($m) use (&$envBackup, &$varCache, &$varCount, $uid) { if (!isset($m[1])) { return $m[0]; } @@ -1495,11 +1490,7 @@ function ($m) use (&$envBackup, &$env, &$varCache, &$varCount, $uid) { $value = '"'.preg_replace('/(\\\\*)"/', '$1$1\\"', $value).'"'; $var = $uid.++$varCount; - if (null === $env) { - putenv("$var=$value"); - } else { - $env[$var] = $value; - } + putenv("$var=$value"); $envBackup[$var] = false; From f9aeee5e630cee960d4da6dec193943862b14dc3 Mon Sep 17 00:00:00 2001 From: Maxime Steinhausser Date: Mon, 2 Oct 2017 13:59:28 +0200 Subject: [PATCH 0985/1099] [DI] Fix missing CHANGELOG update + typo --- src/Symfony/Component/DependencyInjection/CHANGELOG.md | 2 ++ .../Compiler/DefinitionErrorExceptionPass.php | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/DependencyInjection/CHANGELOG.md b/src/Symfony/Component/DependencyInjection/CHANGELOG.md index 013da9ad4ec3f..a004161b963d9 100644 --- a/src/Symfony/Component/DependencyInjection/CHANGELOG.md +++ b/src/Symfony/Component/DependencyInjection/CHANGELOG.md @@ -14,6 +14,8 @@ CHANGELOG * deprecated case insensitivity of parameter names * deprecated the `ResolveDefinitionTemplatesPass` class in favor of `ResolveChildDefinitionsPass` * added `TaggedIteratorArgument` with YAML (`!tagged foo`) and XML (``) support + * deprecated `AutowireExceptionPass` and `AutowirePass::getAutowiringExceptions()`, use `Definition::addError()` and the `DefinitionErrorExceptionPass` instead + 3.3.0 ----- diff --git a/src/Symfony/Component/DependencyInjection/Compiler/DefinitionErrorExceptionPass.php b/src/Symfony/Component/DependencyInjection/Compiler/DefinitionErrorExceptionPass.php index 69cd899f2a5d4..73b5d1d57d582 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/DefinitionErrorExceptionPass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/DefinitionErrorExceptionPass.php @@ -30,7 +30,7 @@ protected function processValue($value, $isRoot = false) return parent::processValue($value, $isRoot); } - // only show the first error so they user can focus on it + // only show the first error so the user can focus on it $errors = $value->getErrors(); $message = reset($errors); From 5b07ca7f2fa7e5db90161e6623f23ad960424361 Mon Sep 17 00:00:00 2001 From: apetitpa Date: Tue, 9 May 2017 15:39:49 +0200 Subject: [PATCH 0986/1099] [Form] Add tel and color types --- .../views/Form/form_div_layout.html.twig | 10 ++++++ .../views/Form/color_widget.html.php | 1 + .../Resources/views/Form/tel_widget.html.php | 1 + .../Form/Extension/Core/CoreExtension.php | 2 ++ .../Form/Extension/Core/Type/ColorType.php | 33 +++++++++++++++++++ .../Form/Extension/Core/Type/TelType.php | 33 +++++++++++++++++++ .../Tests/AbstractBootstrap3LayoutTest.php | 30 +++++++++++++++++ .../Form/Tests/AbstractLayoutTest.php | 28 ++++++++++++++++ .../Tests/Fixtures/Descriptor/defaults_1.json | 2 ++ .../Tests/Fixtures/Descriptor/defaults_1.txt | 12 +++---- src/Symfony/Component/Form/composer.json | 4 +-- 11 files changed, 148 insertions(+), 8 deletions(-) create mode 100644 src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/color_widget.html.php create mode 100644 src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/tel_widget.html.php create mode 100644 src/Symfony/Component/Form/Extension/Core/Type/ColorType.php create mode 100644 src/Symfony/Component/Form/Extension/Core/Type/TelType.php 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 2a0dd466bbc81..52525c061ccba 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 @@ -239,6 +239,16 @@ {{ block('button_widget') }} {%- endblock reset_widget -%} +{%- block tel_widget -%} + {%- set type = type|default('tel') -%} + {{ block('form_widget_simple') }} +{%- endblock tel_widget -%} + +{%- block color_widget -%} + {%- set type = type|default('color') -%} + {{ block('form_widget_simple') }} +{%- endblock color_widget -%} + {# Labels #} {%- block form_label -%} diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/color_widget.html.php b/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/color_widget.html.php new file mode 100644 index 0000000000000..10a8cdf14930e --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/color_widget.html.php @@ -0,0 +1 @@ +block($form, 'form_widget_simple', array('type' => isset($type) ? $type : 'color')); diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/tel_widget.html.php b/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/tel_widget.html.php new file mode 100644 index 0000000000000..7779538127026 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/views/Form/tel_widget.html.php @@ -0,0 +1 @@ +block($form, 'form_widget_simple', array('type' => isset($type) ? $type : 'tel')); diff --git a/src/Symfony/Component/Form/Extension/Core/CoreExtension.php b/src/Symfony/Component/Form/Extension/Core/CoreExtension.php index 156d5568801a8..857792ad9f066 100644 --- a/src/Symfony/Component/Form/Extension/Core/CoreExtension.php +++ b/src/Symfony/Component/Form/Extension/Core/CoreExtension.php @@ -77,6 +77,8 @@ protected function loadTypes() new Type\SubmitType(), new Type\ResetType(), new Type\CurrencyType(), + new Type\TelType(), + new Type\ColorType(), ); } } diff --git a/src/Symfony/Component/Form/Extension/Core/Type/ColorType.php b/src/Symfony/Component/Form/Extension/Core/Type/ColorType.php new file mode 100644 index 0000000000000..9c2734ead6f40 --- /dev/null +++ b/src/Symfony/Component/Form/Extension/Core/Type/ColorType.php @@ -0,0 +1,33 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Extension\Core\Type; + +use Symfony\Component\Form\AbstractType; + +class ColorType extends AbstractType +{ + /** + * {@inheritdoc} + */ + public function getParent() + { + return TextType::class; + } + + /** + * {@inheritdoc} + */ + public function getBlockPrefix() + { + return 'color'; + } +} diff --git a/src/Symfony/Component/Form/Extension/Core/Type/TelType.php b/src/Symfony/Component/Form/Extension/Core/Type/TelType.php new file mode 100644 index 0000000000000..de74a3ed3721d --- /dev/null +++ b/src/Symfony/Component/Form/Extension/Core/Type/TelType.php @@ -0,0 +1,33 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Extension\Core\Type; + +use Symfony\Component\Form\AbstractType; + +class TelType extends AbstractType +{ + /** + * {@inheritdoc} + */ + public function getParent() + { + return TextType::class; + } + + /** + * {@inheritdoc} + */ + public function getBlockPrefix() + { + return 'tel'; + } +} diff --git a/src/Symfony/Component/Form/Tests/AbstractBootstrap3LayoutTest.php b/src/Symfony/Component/Form/Tests/AbstractBootstrap3LayoutTest.php index 09138b1da7dcd..6415d7f4a9096 100644 --- a/src/Symfony/Component/Form/Tests/AbstractBootstrap3LayoutTest.php +++ b/src/Symfony/Component/Form/Tests/AbstractBootstrap3LayoutTest.php @@ -2468,4 +2468,34 @@ public function testButtonAttributeNameRepeatedIfTrue() // foo="foo" $this->assertSame('', $html); } + + public function testTel() + { + $tel = '0102030405'; + $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\TelType', $tel); + + $this->assertWidgetMatchesXpath($form->createView(), array('attr' => array('class' => 'my&class')), + '/input + [@type="tel"] + [@name="name"] + [@class="my&class form-control"] + [@value="0102030405"] +' + ); + } + + public function testColor() + { + $color = '#0000ff'; + $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\ColorType', $color); + + $this->assertWidgetMatchesXpath($form->createView(), array('attr' => array('class' => 'my&class')), + '/input + [@type="color"] + [@name="name"] + [@class="my&class form-control"] + [@value="#0000ff"] +' + ); + } } diff --git a/src/Symfony/Component/Form/Tests/AbstractLayoutTest.php b/src/Symfony/Component/Form/Tests/AbstractLayoutTest.php index db6c64d54e3a4..98d2d48cbe360 100644 --- a/src/Symfony/Component/Form/Tests/AbstractLayoutTest.php +++ b/src/Symfony/Component/Form/Tests/AbstractLayoutTest.php @@ -2463,4 +2463,32 @@ public function testAttributesNotTranslatedWhenTranslationDomainIsFalse() $this->assertMatchesXpath($html, '/form//input[@title="Foo"]'); $this->assertMatchesXpath($html, '/form//input[@placeholder="Bar"]'); } + + public function testTel() + { + $tel = '0102030405'; + $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\TelType', $tel); + + $this->assertWidgetMatchesXpath($form->createView(), array(), + '/input + [@type="tel"] + [@name="name"] + [@value="0102030405"] +' + ); + } + + public function testColor() + { + $color = '#0000ff'; + $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\ColorType', $color); + + $this->assertWidgetMatchesXpath($form->createView(), array(), + '/input + [@type="color"] + [@name="name"] + [@value="#0000ff"] +' + ); + } } diff --git a/src/Symfony/Component/Form/Tests/Fixtures/Descriptor/defaults_1.json b/src/Symfony/Component/Form/Tests/Fixtures/Descriptor/defaults_1.json index 565c17601ed1e..99858a2f997e8 100644 --- a/src/Symfony/Component/Form/Tests/Fixtures/Descriptor/defaults_1.json +++ b/src/Symfony/Component/Form/Tests/Fixtures/Descriptor/defaults_1.json @@ -5,6 +5,7 @@ "Symfony\\Component\\Form\\Extension\\Core\\Type\\CheckboxType", "Symfony\\Component\\Form\\Extension\\Core\\Type\\ChoiceType", "Symfony\\Component\\Form\\Extension\\Core\\Type\\CollectionType", + "Symfony\\Component\\Form\\Extension\\Core\\Type\\ColorType", "Symfony\\Component\\Form\\Extension\\Core\\Type\\CountryType", "Symfony\\Component\\Form\\Extension\\Core\\Type\\CurrencyType", "Symfony\\Component\\Form\\Extension\\Core\\Type\\DateIntervalType", @@ -27,6 +28,7 @@ "Symfony\\Component\\Form\\Extension\\Core\\Type\\ResetType", "Symfony\\Component\\Form\\Extension\\Core\\Type\\SearchType", "Symfony\\Component\\Form\\Extension\\Core\\Type\\SubmitType", + "Symfony\\Component\\Form\\Extension\\Core\\Type\\TelType", "Symfony\\Component\\Form\\Extension\\Core\\Type\\TextType", "Symfony\\Component\\Form\\Extension\\Core\\Type\\TextareaType", "Symfony\\Component\\Form\\Extension\\Core\\Type\\TimeType", diff --git a/src/Symfony/Component/Form/Tests/Fixtures/Descriptor/defaults_1.txt b/src/Symfony/Component/Form/Tests/Fixtures/Descriptor/defaults_1.txt index dd08d5f7a64c3..52a579ac43e62 100644 --- a/src/Symfony/Component/Form/Tests/Fixtures/Descriptor/defaults_1.txt +++ b/src/Symfony/Component/Form/Tests/Fixtures/Descriptor/defaults_1.txt @@ -3,12 +3,12 @@ ---------------------------------------------------------------- BirthdayType, ButtonType, CheckboxType, ChoiceType, CollectionType - CountryType, CurrencyType, DateIntervalType, DateTimeType, DateType - EmailType, FileType, FormType, HiddenType, IntegerType - LanguageType, LocaleType, MoneyType, NumberType, PasswordType - PercentType, RadioType, RangeType, RepeatedType, ResetType - SearchType, SubmitType, TextType, TextareaType, TimeType - TimezoneType, UrlType + ColorType, CountryType, CurrencyType, DateIntervalType, DateTimeType + DateType, EmailType, FileType, FormType, HiddenType + IntegerType, LanguageType, LocaleType, MoneyType, NumberType + PasswordType, PercentType, RadioType, RangeType, RepeatedType + ResetType, SearchType, SubmitType, TelType, TextType + TextareaType, TimeType, TimezoneType, UrlType Service form types ------------------ diff --git a/src/Symfony/Component/Form/composer.json b/src/Symfony/Component/Form/composer.json index 77fc3e565ffa7..4106c65890aa2 100644 --- a/src/Symfony/Component/Form/composer.json +++ b/src/Symfony/Component/Form/composer.json @@ -39,9 +39,9 @@ "phpunit/phpunit": "<4.8.35|<5.4.3,>=5.0", "symfony/dependency-injection": "<3.3", "symfony/doctrine-bridge": "<2.7", - "symfony/framework-bundle": "<2.7", + "symfony/framework-bundle": "<3.4", "symfony/http-kernel": "<3.3.5", - "symfony/twig-bridge": "<2.7" + "symfony/twig-bridge": "<3.4" }, "suggest": { "symfony/validator": "For form validation.", From 2ada55878a6dfcbd609d08c89d29b8f61ab1802b Mon Sep 17 00:00:00 2001 From: Maxime Steinhausser Date: Mon, 2 Oct 2017 13:43:47 +0200 Subject: [PATCH 0987/1099] [DI] Remove AutowireExceptionPass --- .../DependencyInjection/CHANGELOG.md | 1 + .../Compiler/AutowireExceptionPass.php | 74 --------- .../Compiler/AutowirePass.php | 17 -- .../Compiler/InlineServiceDefinitionsPass.php | 18 --- .../Compiler/AutowireExceptionPassTest.php | 145 ------------------ .../Tests/Compiler/AutowirePassTest.php | 18 --- .../InlineServiceDefinitionsPassTest.php | 27 ---- 7 files changed, 1 insertion(+), 299 deletions(-) delete mode 100644 src/Symfony/Component/DependencyInjection/Compiler/AutowireExceptionPass.php delete mode 100644 src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowireExceptionPassTest.php diff --git a/src/Symfony/Component/DependencyInjection/CHANGELOG.md b/src/Symfony/Component/DependencyInjection/CHANGELOG.md index 2c11feb0e082d..ca437e2cf6701 100644 --- a/src/Symfony/Component/DependencyInjection/CHANGELOG.md +++ b/src/Symfony/Component/DependencyInjection/CHANGELOG.md @@ -22,6 +22,7 @@ CHANGELOG * removed support for setting and accessing private services in `Container` * removed support for setting pre-defined services in `Container` * removed support for case insensitivity of parameter names + * removed `AutowireExceptionPass` and `AutowirePass::getAutowiringExceptions()`, use `Definition::addError()` and the `DefinitionErrorExceptionPass` instead 3.4.0 ----- diff --git a/src/Symfony/Component/DependencyInjection/Compiler/AutowireExceptionPass.php b/src/Symfony/Component/DependencyInjection/Compiler/AutowireExceptionPass.php deleted file mode 100644 index f01617dd633c6..0000000000000 --- a/src/Symfony/Component/DependencyInjection/Compiler/AutowireExceptionPass.php +++ /dev/null @@ -1,74 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Compiler; - -@trigger_error('The '.__NAMESPACE__.'\AutowireExceptionPass class is deprecated since version 3.4 and will be removed in 4.0. Use the DefinitionErrorExceptionPass class instead.', E_USER_DEPRECATED); - -use Symfony\Component\DependencyInjection\ContainerBuilder; - -/** - * Throws autowire exceptions from AutowirePass for definitions that still exist. - * - * @deprecated since version 3.4, will be removed in 4.0. - * - * @author Ryan Weaver - */ -class AutowireExceptionPass implements CompilerPassInterface -{ - private $autowirePass; - private $inlineServicePass; - - public function __construct(AutowirePass $autowirePass, InlineServiceDefinitionsPass $inlineServicePass) - { - $this->autowirePass = $autowirePass; - $this->inlineServicePass = $inlineServicePass; - } - - public function process(ContainerBuilder $container) - { - // the pass should only be run once - if (null === $this->autowirePass || null === $this->inlineServicePass) { - return; - } - - $inlinedIds = $this->inlineServicePass->getInlinedServiceIds(); - $exceptions = $this->autowirePass->getAutowiringExceptions(); - - // free up references - $this->autowirePass = null; - $this->inlineServicePass = null; - - foreach ($exceptions as $exception) { - if ($this->doesServiceExistInTheContainer($exception->getServiceId(), $container, $inlinedIds)) { - throw $exception; - } - } - } - - private function doesServiceExistInTheContainer($serviceId, ContainerBuilder $container, array $inlinedIds) - { - if ($container->hasDefinition($serviceId)) { - return true; - } - - // was the service inlined? Of so, does its parent service exist? - if (isset($inlinedIds[$serviceId])) { - foreach ($inlinedIds[$serviceId] as $parentId) { - if ($this->doesServiceExistInTheContainer($parentId, $container, $inlinedIds)) { - return true; - } - } - } - - return false; - } -} diff --git a/src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php b/src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php index dba3fa82ce1aa..1b099e0ac8885 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php @@ -31,7 +31,6 @@ class AutowirePass extends AbstractRecursivePass private $autowired = array(); private $lastFailure; private $throwOnAutowiringException; - private $autowiringExceptions = array(); /** * @param bool $throwOnAutowireException Errors can be retrieved via Definition::getErrors() @@ -41,26 +40,11 @@ public function __construct($throwOnAutowireException = true) $this->throwOnAutowiringException = $throwOnAutowireException; } - /** - * @deprecated since version 3.4, to be removed in 4.0. - * - * @return AutowiringFailedException[] - */ - public function getAutowiringExceptions() - { - @trigger_error('Calling AutowirePass::getAutowiringExceptions() is deprecated since Symfony 3.4 and will be removed in 4.0. Use Definition::getErrors() instead.', E_USER_DEPRECATED); - - return $this->autowiringExceptions; - } - /** * {@inheritdoc} */ public function process(ContainerBuilder $container) { - // clear out any possibly stored exceptions from before - $this->autowiringExceptions = array(); - try { parent::process($container); } finally { @@ -82,7 +66,6 @@ protected function processValue($value, $isRoot = false) throw $e; } - $this->autowiringExceptions[] = $e; $this->container->getDefinition($this->currentId)->addError($e->getMessage()); return parent::processValue($value, $isRoot); diff --git a/src/Symfony/Component/DependencyInjection/Compiler/InlineServiceDefinitionsPass.php b/src/Symfony/Component/DependencyInjection/Compiler/InlineServiceDefinitionsPass.php index 254ac3c00c6da..76f2e502170de 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/InlineServiceDefinitionsPass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/InlineServiceDefinitionsPass.php @@ -23,7 +23,6 @@ class InlineServiceDefinitionsPass extends AbstractRecursivePass implements RepeatablePassInterface { private $repeatedPass; - private $inlinedServiceIds = array(); /** * {@inheritdoc} @@ -33,22 +32,6 @@ public function setRepeatedPass(RepeatedPass $repeatedPass) $this->repeatedPass = $repeatedPass; } - /** - * Returns an array of all services inlined by this pass. - * - * The key is the inlined service id and its value is the list of services it was inlined into. - * - * @deprecated since version 3.4, to be removed in 4.0. - * - * @return array - */ - public function getInlinedServiceIds() - { - @trigger_error('Calling InlineServiceDefinitionsPass::getInlinedServiceIds() is deprecated since Symfony 3.4 and will be removed in 4.0.', E_USER_DEPRECATED); - - return $this->inlinedServiceIds; - } - /** * {@inheritdoc} */ @@ -63,7 +46,6 @@ protected function processValue($value, $isRoot = false) if ($this->isInlineableDefinition($id, $definition, $this->container->getCompiler()->getServiceReferenceGraph())) { $this->container->log($this, sprintf('Inlined service "%s" to "%s".', $id, $this->currentId)); - $this->inlinedServiceIds[$id][] = $this->currentId; if ($definition->isShared()) { return $definition; diff --git a/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowireExceptionPassTest.php b/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowireExceptionPassTest.php deleted file mode 100644 index a9c3445cefdd8..0000000000000 --- a/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowireExceptionPassTest.php +++ /dev/null @@ -1,145 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\DependencyInjection\Tests\Compiler; - -use PHPUnit\Framework\TestCase; -use Symfony\Component\DependencyInjection\Compiler\AutowireExceptionPass; -use Symfony\Component\DependencyInjection\Compiler\AutowirePass; -use Symfony\Component\DependencyInjection\Compiler\InlineServiceDefinitionsPass; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Exception\AutowiringFailedException; - -/** - * @group legacy - */ -class AutowireExceptionPassTest extends TestCase -{ - public function testThrowsException() - { - $autowirePass = $this->getMockBuilder(AutowirePass::class) - ->getMock(); - - $autowireException = new AutowiringFailedException('foo_service_id', 'An autowiring exception message'); - $autowirePass->expects($this->any()) - ->method('getAutowiringExceptions') - ->will($this->returnValue(array($autowireException))); - - $inlinePass = $this->getMockBuilder(InlineServiceDefinitionsPass::class) - ->getMock(); - $inlinePass->expects($this->any()) - ->method('getInlinedServiceIds') - ->will($this->returnValue(array())); - - $container = new ContainerBuilder(); - $container->register('foo_service_id'); - - $pass = new AutowireExceptionPass($autowirePass, $inlinePass); - - try { - $pass->process($container); - $this->fail('->process() should throw the exception if the service id exists'); - } catch (\Exception $e) { - $this->assertSame($autowireException, $e); - } - } - - public function testThrowExceptionIfServiceInlined() - { - $autowirePass = $this->getMockBuilder(AutowirePass::class) - ->getMock(); - - $autowireException = new AutowiringFailedException('a_service', 'An autowiring exception message'); - $autowirePass->expects($this->any()) - ->method('getAutowiringExceptions') - ->will($this->returnValue(array($autowireException))); - - $inlinePass = $this->getMockBuilder(InlineServiceDefinitionsPass::class) - ->getMock(); - $inlinePass->expects($this->any()) - ->method('getInlinedServiceIds') - ->will($this->returnValue(array( - // a_service inlined into b_service - 'a_service' => array('b_service'), - // b_service inlined into c_service - 'b_service' => array('c_service'), - ))); - - $container = new ContainerBuilder(); - // ONLY register c_service in the final container - $container->register('c_service', 'stdClass'); - - $pass = new AutowireExceptionPass($autowirePass, $inlinePass); - - try { - $pass->process($container); - $this->fail('->process() should throw the exception if the service id exists'); - } catch (\Exception $e) { - $this->assertSame($autowireException, $e); - } - } - - public function testDoNotThrowExceptionIfServiceInlinedButRemoved() - { - $autowirePass = $this->getMockBuilder(AutowirePass::class) - ->getMock(); - - $autowireException = new AutowiringFailedException('a_service', 'An autowiring exception message'); - $autowirePass->expects($this->any()) - ->method('getAutowiringExceptions') - ->will($this->returnValue(array($autowireException))); - - $inlinePass = $this->getMockBuilder(InlineServiceDefinitionsPass::class) - ->getMock(); - $inlinePass->expects($this->any()) - ->method('getInlinedServiceIds') - ->will($this->returnValue(array( - // a_service inlined into b_service - 'a_service' => array('b_service'), - // b_service inlined into c_service - 'b_service' => array('c_service'), - ))); - - // do NOT register c_service in the container - $container = new ContainerBuilder(); - - $pass = new AutowireExceptionPass($autowirePass, $inlinePass); - - $pass->process($container); - // mark the test as passed - $this->assertTrue(true); - } - - public function testNoExceptionIfServiceRemoved() - { - $autowirePass = $this->getMockBuilder(AutowirePass::class) - ->getMock(); - - $autowireException = new AutowiringFailedException('non_existent_service'); - $autowirePass->expects($this->any()) - ->method('getAutowiringExceptions') - ->will($this->returnValue(array($autowireException))); - - $inlinePass = $this->getMockBuilder(InlineServiceDefinitionsPass::class) - ->getMock(); - $inlinePass->expects($this->any()) - ->method('getInlinedServiceIds') - ->will($this->returnValue(array())); - - $container = new ContainerBuilder(); - - $pass = new AutowireExceptionPass($autowirePass, $inlinePass); - - $pass->process($container); - // mark the test as passed - $this->assertTrue(true); - } -} diff --git a/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowirePassTest.php b/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowirePassTest.php index b8cd5216fe9d4..c47d813220973 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowirePassTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowirePassTest.php @@ -131,24 +131,6 @@ public function testCompleteExistingDefinitionWithNotDefinedArguments() $this->assertEquals(DInterface::class, (string) $container->getDefinition('h')->getArgument(1)); } - /** - * @group legacy - */ - public function testExceptionsAreStored() - { - $container = new ContainerBuilder(); - - $container->register('c1', __NAMESPACE__.'\CollisionA'); - $container->register('c2', __NAMESPACE__.'\CollisionB'); - $container->register('c3', __NAMESPACE__.'\CollisionB'); - $aDefinition = $container->register('a', __NAMESPACE__.'\CannotBeAutowired'); - $aDefinition->setAutowired(true); - - $pass = new AutowirePass(false); - $pass->process($container); - $this->assertCount(1, $pass->getAutowiringExceptions()); - } - /** * @expectedException \Symfony\Component\DependencyInjection\Exception\AutowiringFailedException * @expectedExceptionMessage Invalid service "private_service": constructor of class "Symfony\Component\DependencyInjection\Tests\Compiler\PrivateConstructor" must be public. diff --git a/src/Symfony/Component/DependencyInjection/Tests/Compiler/InlineServiceDefinitionsPassTest.php b/src/Symfony/Component/DependencyInjection/Tests/Compiler/InlineServiceDefinitionsPassTest.php index 6154080c8bc0e..3e1cf8a8c2b10 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Compiler/InlineServiceDefinitionsPassTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Compiler/InlineServiceDefinitionsPassTest.php @@ -252,33 +252,6 @@ public function testProcessDoesNotSetLazyArgumentValuesAfterInlining() $this->assertSame('inline', (string) $values[0]); } - /** - * @group legacy - */ - public function testGetInlinedServiceIdData() - { - $container = new ContainerBuilder(); - $container - ->register('inlinable.service') - ->setPublic(false) - ; - $container - ->register('non_inlinable.service') - ->setPublic(true) - ; - - $container - ->register('other_service') - ->setArguments(array(new Reference('inlinable.service'))) - ; - - $inlinePass = new InlineServiceDefinitionsPass(); - $repeatedPass = new RepeatedPass(array(new AnalyzeServiceReferencesPass(), $inlinePass)); - $repeatedPass->process($container); - - $this->assertEquals(array('inlinable.service' => array('other_service')), $inlinePass->getInlinedServiceIds()); - } - protected function process(ContainerBuilder $container) { $repeatedPass = new RepeatedPass(array(new AnalyzeServiceReferencesPass(), new InlineServiceDefinitionsPass())); From e097ab3141413158d66db4c12a7e5596fa68a93c Mon Sep 17 00:00:00 2001 From: Yonel Ceruto Date: Mon, 2 Oct 2017 11:39:30 -0400 Subject: [PATCH 0988/1099] Show welcome message if no routing configuration could be found --- .../Resources/config/routing.xml | 2 + .../EventListener/RouterListener.php | 30 ++++++- .../HttpKernel/Resources/welcome.html.php | 84 +++++++++++++++++++ .../EventListener/RouterListenerTest.php | 23 +++++ .../Component/HttpKernel/composer.json | 2 +- src/Symfony/Component/Routing/CHANGELOG.md | 1 + .../Exception/NoConfigurationException.php | 21 +++++ .../Matcher/Dumper/PhpMatcherDumper.php | 6 ++ .../Matcher/RequestMatcherInterface.php | 2 + .../Component/Routing/Matcher/UrlMatcher.php | 6 ++ .../Routing/Matcher/UrlMatcherInterface.php | 2 + .../Tests/Fixtures/dumper/url_matcher0.php | 39 +++++++++ .../Matcher/Dumper/PhpMatcherDumperTest.php | 1 + .../Routing/Tests/Matcher/UrlMatcherTest.php | 11 +++ 14 files changed, 228 insertions(+), 2 deletions(-) create mode 100644 src/Symfony/Component/HttpKernel/Resources/welcome.html.php create mode 100644 src/Symfony/Component/Routing/Exception/NoConfigurationException.php create mode 100644 src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher0.php diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/routing.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/routing.xml index 6856512e20349..d92cb1164ac90 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/routing.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/routing.xml @@ -109,6 +109,8 @@ + %kernel.project_dir% + %kernel.debug%
diff --git a/src/Symfony/Component/HttpKernel/EventListener/RouterListener.php b/src/Symfony/Component/HttpKernel/EventListener/RouterListener.php index 16f31a2d947a7..a8f7dd7e7ed97 100644 --- a/src/Symfony/Component/HttpKernel/EventListener/RouterListener.php +++ b/src/Symfony/Component/HttpKernel/EventListener/RouterListener.php @@ -12,13 +12,16 @@ namespace Symfony\Component\HttpKernel\EventListener; use Psr\Log\LoggerInterface; +use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\Event\GetResponseEvent; use Symfony\Component\HttpKernel\Event\FinishRequestEvent; +use Symfony\Component\HttpKernel\Kernel; use Symfony\Component\HttpKernel\KernelEvents; use Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException; use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; use Symfony\Component\HttpFoundation\RequestStack; use Symfony\Component\Routing\Exception\MethodNotAllowedException; +use Symfony\Component\Routing\Exception\NoConfigurationException; use Symfony\Component\Routing\Exception\ResourceNotFoundException; use Symfony\Component\Routing\Matcher\UrlMatcherInterface; use Symfony\Component\Routing\Matcher\RequestMatcherInterface; @@ -31,6 +34,7 @@ * Initializes the context from the request and sets request attributes based on a matching route. * * @author Fabien Potencier + * @author Yonel Ceruto */ class RouterListener implements EventSubscriberInterface { @@ -38,16 +42,20 @@ class RouterListener implements EventSubscriberInterface private $context; private $logger; private $requestStack; + private $projectDir; + private $debug; /** * @param UrlMatcherInterface|RequestMatcherInterface $matcher The Url or Request matcher * @param RequestStack $requestStack A RequestStack instance * @param RequestContext|null $context The RequestContext (can be null when $matcher implements RequestContextAwareInterface) * @param LoggerInterface|null $logger The logger + * @param string $projectDir + * @param bool $debug * * @throws \InvalidArgumentException */ - public function __construct($matcher, RequestStack $requestStack, RequestContext $context = null, LoggerInterface $logger = null) + public function __construct($matcher, RequestStack $requestStack, RequestContext $context = null, LoggerInterface $logger = null, $projectDir = null, $debug = true) { if (!$matcher instanceof UrlMatcherInterface && !$matcher instanceof RequestMatcherInterface) { throw new \InvalidArgumentException('Matcher must either implement UrlMatcherInterface or RequestMatcherInterface.'); @@ -61,6 +69,8 @@ public function __construct($matcher, RequestStack $requestStack, RequestContext $this->context = $context ?: $matcher->getContext(); $this->requestStack = $requestStack; $this->logger = $logger; + $this->projectDir = $projectDir; + $this->debug = $debug; } private function setCurrentRequest(Request $request = null) @@ -114,6 +124,12 @@ public function onKernelRequest(GetResponseEvent $event) unset($parameters['_route'], $parameters['_controller']); $request->attributes->set('_route_params', $parameters); } catch (ResourceNotFoundException $e) { + if ($this->debug && $e instanceof NoConfigurationException) { + $event->setResponse($this->createWelcomeResponse()); + + return; + } + $message = sprintf('No route found for "%s %s"', $request->getMethod(), $request->getPathInfo()); if ($referer = $request->headers->get('referer')) { @@ -135,4 +151,16 @@ public static function getSubscribedEvents() KernelEvents::FINISH_REQUEST => array(array('onKernelFinishRequest', 0)), ); } + + private function createWelcomeResponse() + { + $version = Kernel::VERSION; + $baseDir = realpath($this->projectDir).DIRECTORY_SEPARATOR; + $docVersion = substr(Kernel::VERSION, 0, 3); + + ob_start(); + include __DIR__.'/../Resources/welcome.html.php'; + + return new Response(ob_get_clean(), Response::HTTP_NOT_FOUND); + } } diff --git a/src/Symfony/Component/HttpKernel/Resources/welcome.html.php b/src/Symfony/Component/HttpKernel/Resources/welcome.html.php new file mode 100644 index 0000000000000..d8c37beb56ae2 --- /dev/null +++ b/src/Symfony/Component/HttpKernel/Resources/welcome.html.php @@ -0,0 +1,84 @@ + + + + + Welcome! + + + +
+
+
+

Welcome to Symfony

+
+ +
+

+ + + Your application is now ready. You can start working on it at:
+ +

+
+ + +
+
+

+ You're seeing this message because you have debug mode enabled and you haven't configured any URLs. +

+
+
+ + diff --git a/src/Symfony/Component/HttpKernel/Tests/EventListener/RouterListenerTest.php b/src/Symfony/Component/HttpKernel/Tests/EventListener/RouterListenerTest.php index a40e57998dee2..8ef2dc29f7a25 100644 --- a/src/Symfony/Component/HttpKernel/Tests/EventListener/RouterListenerTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/EventListener/RouterListenerTest.php @@ -24,6 +24,7 @@ use Symfony\Component\HttpKernel\HttpKernelInterface; use Symfony\Component\HttpKernel\HttpKernel; use Symfony\Component\HttpKernel\Event\GetResponseEvent; +use Symfony\Component\Routing\Exception\NoConfigurationException; use Symfony\Component\Routing\RequestContext; class RouterListenerTest extends TestCase @@ -185,4 +186,26 @@ public function testWithBadRequest() $response = $kernel->handle($request); $this->assertSame(400, $response->getStatusCode()); } + + public function testNoRoutingConfigurationResponse() + { + $requestStack = new RequestStack(); + + $requestMatcher = $this->getMockBuilder('Symfony\Component\Routing\Matcher\RequestMatcherInterface')->getMock(); + $requestMatcher + ->expects($this->once()) + ->method('matchRequest') + ->willThrowException(new NoConfigurationException()) + ; + + $dispatcher = new EventDispatcher(); + $dispatcher->addSubscriber(new RouterListener($requestMatcher, $requestStack, new RequestContext())); + + $kernel = new HttpKernel($dispatcher, new ControllerResolver(), $requestStack, new ArgumentResolver()); + + $request = Request::create('http://localhost/'); + $response = $kernel->handle($request); + $this->assertSame(404, $response->getStatusCode()); + $this->assertContains('Welcome', $response->getContent()); + } } diff --git a/src/Symfony/Component/HttpKernel/composer.json b/src/Symfony/Component/HttpKernel/composer.json index a372edb588601..888cd3f23852d 100644 --- a/src/Symfony/Component/HttpKernel/composer.json +++ b/src/Symfony/Component/HttpKernel/composer.json @@ -33,7 +33,7 @@ "symfony/expression-language": "~2.8|~3.0|~4.0", "symfony/finder": "~2.8|~3.0|~4.0", "symfony/process": "~2.8|~3.0|~4.0", - "symfony/routing": "~2.8|~3.0|~4.0", + "symfony/routing": "~3.4|~4.0", "symfony/stopwatch": "~2.8|~3.0|~4.0", "symfony/templating": "~2.8|~3.0|~4.0", "symfony/translation": "~2.8|~3.0|~4.0", diff --git a/src/Symfony/Component/Routing/CHANGELOG.md b/src/Symfony/Component/Routing/CHANGELOG.md index 3785709d42425..e278f8b1e5936 100644 --- a/src/Symfony/Component/Routing/CHANGELOG.md +++ b/src/Symfony/Component/Routing/CHANGELOG.md @@ -4,6 +4,7 @@ CHANGELOG 3.4.0 ----- + * Added `NoConfigurationException`. * Added the possibility to define a prefix for all routes of a controller via @Route(name="prefix_") * Added support for prioritized routing loaders. * Add matched and default parameters to redirect responses diff --git a/src/Symfony/Component/Routing/Exception/NoConfigurationException.php b/src/Symfony/Component/Routing/Exception/NoConfigurationException.php new file mode 100644 index 0000000000000..333bc74331460 --- /dev/null +++ b/src/Symfony/Component/Routing/Exception/NoConfigurationException.php @@ -0,0 +1,21 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing\Exception; + +/** + * Exception thrown when no routes are configured. + * + * @author Yonel Ceruto + */ +class NoConfigurationException extends ResourceNotFoundException +{ +} diff --git a/src/Symfony/Component/Routing/Matcher/Dumper/PhpMatcherDumper.php b/src/Symfony/Component/Routing/Matcher/Dumper/PhpMatcherDumper.php index 589e4f75390aa..aaa352d22c069 100644 --- a/src/Symfony/Component/Routing/Matcher/Dumper/PhpMatcherDumper.php +++ b/src/Symfony/Component/Routing/Matcher/Dumper/PhpMatcherDumper.php @@ -155,6 +155,12 @@ private function compileRoutes(RouteCollection $routes, $supportsRedirections) } } + if ('' === $code) { + $code .= " if ('/' === \$pathinfo) {\n"; + $code .= " throw new Symfony\Component\Routing\Exception\NoConfigurationException();\n"; + $code .= " }\n"; + } + return $code; } diff --git a/src/Symfony/Component/Routing/Matcher/RequestMatcherInterface.php b/src/Symfony/Component/Routing/Matcher/RequestMatcherInterface.php index b5def3d468ab3..097929555d7e5 100644 --- a/src/Symfony/Component/Routing/Matcher/RequestMatcherInterface.php +++ b/src/Symfony/Component/Routing/Matcher/RequestMatcherInterface.php @@ -12,6 +12,7 @@ namespace Symfony\Component\Routing\Matcher; use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\Routing\Exception\NoConfigurationException; use Symfony\Component\Routing\Exception\ResourceNotFoundException; use Symfony\Component\Routing\Exception\MethodNotAllowedException; @@ -32,6 +33,7 @@ interface RequestMatcherInterface * * @return array An array of parameters * + * @throws NoConfigurationException If no routing configuration could be found * @throws ResourceNotFoundException If no matching resource could be found * @throws MethodNotAllowedException If a matching resource was found but the request method is not allowed */ diff --git a/src/Symfony/Component/Routing/Matcher/UrlMatcher.php b/src/Symfony/Component/Routing/Matcher/UrlMatcher.php index 12c15c68917ae..abd04c4208edf 100644 --- a/src/Symfony/Component/Routing/Matcher/UrlMatcher.php +++ b/src/Symfony/Component/Routing/Matcher/UrlMatcher.php @@ -12,6 +12,7 @@ namespace Symfony\Component\Routing\Matcher; use Symfony\Component\Routing\Exception\MethodNotAllowedException; +use Symfony\Component\Routing\Exception\NoConfigurationException; use Symfony\Component\Routing\Exception\ResourceNotFoundException; use Symfony\Component\Routing\RouteCollection; use Symfony\Component\Routing\RequestContext; @@ -91,6 +92,10 @@ public function match($pathinfo) return $ret; } + if (0 === count($this->routes) && '/' === $pathinfo) { + throw new NoConfigurationException(); + } + throw 0 < count($this->allow) ? new MethodNotAllowedException(array_unique($this->allow)) : new ResourceNotFoundException(sprintf('No routes found for "%s".', $pathinfo)); @@ -123,6 +128,7 @@ public function addExpressionLanguageProvider(ExpressionFunctionProviderInterfac * * @return array An array of parameters * + * @throws NoConfigurationException If no routing configuration could be found * @throws ResourceNotFoundException If the resource could not be found * @throws MethodNotAllowedException If the resource was found but the request method is not allowed */ diff --git a/src/Symfony/Component/Routing/Matcher/UrlMatcherInterface.php b/src/Symfony/Component/Routing/Matcher/UrlMatcherInterface.php index af38662fea930..2c7c3135bc66f 100644 --- a/src/Symfony/Component/Routing/Matcher/UrlMatcherInterface.php +++ b/src/Symfony/Component/Routing/Matcher/UrlMatcherInterface.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Routing\Matcher; +use Symfony\Component\Routing\Exception\NoConfigurationException; use Symfony\Component\Routing\RequestContextAwareInterface; use Symfony\Component\Routing\Exception\ResourceNotFoundException; use Symfony\Component\Routing\Exception\MethodNotAllowedException; @@ -32,6 +33,7 @@ interface UrlMatcherInterface extends RequestContextAwareInterface * * @return array An array of parameters * + * @throws NoConfigurationException If no routing configuration could be found * @throws ResourceNotFoundException If the resource could not be found * @throws MethodNotAllowedException If the resource was found but the request method is not allowed */ diff --git a/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher0.php b/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher0.php new file mode 100644 index 0000000000000..0fa8ea45e0a15 --- /dev/null +++ b/src/Symfony/Component/Routing/Tests/Fixtures/dumper/url_matcher0.php @@ -0,0 +1,39 @@ +context = $context; + } + + public function match($pathinfo) + { + $allow = array(); + $pathinfo = rawurldecode($pathinfo); + $trimmedPathinfo = rtrim($pathinfo, '/'); + $context = $this->context; + $request = $this->request; + $requestMethod = $canonicalMethod = $context->getMethod(); + $scheme = $context->getScheme(); + + if ('HEAD' === $requestMethod) { + $canonicalMethod = 'GET'; + } + + + if ('/' === $pathinfo) { + throw new Symfony\Component\Routing\Exception\NoConfigurationException(); + } + + throw 0 < count($allow) ? new MethodNotAllowedException(array_unique($allow)) : new ResourceNotFoundException(); + } +} diff --git a/src/Symfony/Component/Routing/Tests/Matcher/Dumper/PhpMatcherDumperTest.php b/src/Symfony/Component/Routing/Tests/Matcher/Dumper/PhpMatcherDumperTest.php index 4fb65f4a11a47..8b32e0cd3d194 100644 --- a/src/Symfony/Component/Routing/Tests/Matcher/Dumper/PhpMatcherDumperTest.php +++ b/src/Symfony/Component/Routing/Tests/Matcher/Dumper/PhpMatcherDumperTest.php @@ -374,6 +374,7 @@ public function getRouteCollections() $trailingSlashCollection->add('regex_not_trailing_slash_POST_method', new Route('/not-trailing/regex/post-method/{param}', array(), array(), array(), '', array(), array('POST'))); return array( + array(new RouteCollection(), 'url_matcher0.php', array()), array($collection, 'url_matcher1.php', array()), array($redirectCollection, 'url_matcher2.php', array('base_class' => 'Symfony\Component\Routing\Tests\Fixtures\RedirectableUrlMatcher')), array($rootprefixCollection, 'url_matcher3.php', array()), diff --git a/src/Symfony/Component/Routing/Tests/Matcher/UrlMatcherTest.php b/src/Symfony/Component/Routing/Tests/Matcher/UrlMatcherTest.php index 1eeb5d4360cde..8545c2c29d83d 100644 --- a/src/Symfony/Component/Routing/Tests/Matcher/UrlMatcherTest.php +++ b/src/Symfony/Component/Routing/Tests/Matcher/UrlMatcherTest.php @@ -427,4 +427,15 @@ public function testHostIsCaseInsensitive() $matcher = new UrlMatcher($coll, new RequestContext('', 'GET', 'en.example.com')); $this->assertEquals(array('_route' => 'foo', 'locale' => 'en'), $matcher->match('/')); } + + /** + * @expectedException \Symfony\Component\Routing\Exception\NoConfigurationException + */ + public function testNoConfiguration() + { + $coll = new RouteCollection(); + + $matcher = new UrlMatcher($coll, new RequestContext()); + $matcher->match('/'); + } } From bbc52a1d14358500b39073ba7cb46ed95fbc5810 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Tue, 3 Oct 2017 11:44:07 +0200 Subject: [PATCH 0989/1099] [FrameworkBundle] Make Controller helpers final --- .../FrameworkBundle/Controller/Controller.php | 24 ------- .../Controller/ControllerTrait.php | 66 +++++++++++++++++++ 2 files changed, 66 insertions(+), 24 deletions(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/Controller/Controller.php b/src/Symfony/Bundle/FrameworkBundle/Controller/Controller.php index 870965201e397..11161d46ebd17 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Controller/Controller.php +++ b/src/Symfony/Bundle/FrameworkBundle/Controller/Controller.php @@ -26,30 +26,6 @@ abstract class Controller implements ContainerAwareInterface use ContainerAwareTrait; use ControllerTrait; - /** - * Returns true if the service id is defined. - * - * @param string $id The service id - * - * @return bool true if the service id is defined, false otherwise - */ - protected function has($id) - { - return $this->container->has($id); - } - - /** - * Gets a container service by its id. - * - * @param string $id The service id - * - * @return object The service - */ - protected function get($id) - { - return $this->container->get($id); - } - /** * Gets a container configuration parameter by its name. * diff --git a/src/Symfony/Bundle/FrameworkBundle/Controller/ControllerTrait.php b/src/Symfony/Bundle/FrameworkBundle/Controller/ControllerTrait.php index 77a02883083b7..593c02f14522d 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Controller/ControllerTrait.php +++ b/src/Symfony/Bundle/FrameworkBundle/Controller/ControllerTrait.php @@ -39,6 +39,34 @@ */ trait ControllerTrait { + /** + * Returns true if the service id is defined. + * + * @param string $id The service id + * + * @return bool true if the service id is defined, false otherwise + * + * @final since version 3.4 + */ + protected function has($id) + { + return $this->container->has($id); + } + + /** + * Gets a container service by its id. + * + * @param string $id The service id + * + * @return object The service + * + * @final since version 3.4 + */ + protected function get($id) + { + return $this->container->get($id); + } + /** * Generates a URL from the given parameters. * @@ -49,6 +77,8 @@ trait ControllerTrait * @return string The generated URL * * @see UrlGeneratorInterface + * + * @final since version 3.4 */ protected function generateUrl($route, $parameters = array(), $referenceType = UrlGeneratorInterface::ABSOLUTE_PATH) { @@ -63,6 +93,8 @@ protected function generateUrl($route, $parameters = array(), $referenceType = U * @param array $query An array of query parameters * * @return Response A Response instance + * + * @final since version 3.4 */ protected function forward($controller, array $path = array(), array $query = array()) { @@ -81,6 +113,8 @@ protected function forward($controller, array $path = array(), array $query = ar * @param int $status The status code to use for the Response * * @return RedirectResponse + * + * @final since version 3.4 */ protected function redirect($url, $status = 302) { @@ -95,6 +129,8 @@ protected function redirect($url, $status = 302) * @param int $status The status code to use for the Response * * @return RedirectResponse + * + * @final since version 3.4 */ protected function redirectToRoute($route, array $parameters = array(), $status = 302) { @@ -110,6 +146,8 @@ protected function redirectToRoute($route, array $parameters = array(), $status * @param array $context Context to pass to serializer when using serializer component * * @return JsonResponse + * + * @final since version 3.4 */ protected function json($data, $status = 200, $headers = array(), $context = array()) { @@ -132,6 +170,8 @@ protected function json($data, $status = 200, $headers = array(), $context = arr * @param string $disposition Disposition of response ("attachment" is default, other type is "inline") * * @return BinaryFileResponse + * + * @final since version 3.4 */ protected function file($file, $fileName = null, $disposition = ResponseHeaderBag::DISPOSITION_ATTACHMENT) { @@ -148,6 +188,8 @@ protected function file($file, $fileName = null, $disposition = ResponseHeaderBa * @param string $message The message * * @throws \LogicException + * + * @final since version 3.4 */ protected function addFlash($type, $message) { @@ -167,6 +209,8 @@ protected function addFlash($type, $message) * @return bool * * @throws \LogicException + * + * @final since version 3.4 */ protected function isGranted($attributes, $subject = null) { @@ -186,6 +230,8 @@ protected function isGranted($attributes, $subject = null) * @param string $message The message passed to the exception * * @throws AccessDeniedException + * + * @final since version 3.4 */ protected function denyAccessUnlessGranted($attributes, $subject = null, $message = 'Access Denied.') { @@ -205,6 +251,8 @@ protected function denyAccessUnlessGranted($attributes, $subject = null, $messag * @param array $parameters An array of parameters to pass to the view * * @return string The rendered view + * + * @final since version 3.4 */ protected function renderView($view, array $parameters = array()) { @@ -227,6 +275,8 @@ protected function renderView($view, array $parameters = array()) * @param Response $response A response instance * * @return Response A Response instance + * + * @final since version 3.4 */ protected function render($view, array $parameters = array(), Response $response = null) { @@ -255,6 +305,8 @@ protected function render($view, array $parameters = array(), Response $response * @param StreamedResponse $response A response instance * * @return StreamedResponse A StreamedResponse instance + * + * @final since version 3.4 */ protected function stream($view, array $parameters = array(), StreamedResponse $response = null) { @@ -294,6 +346,8 @@ protected function stream($view, array $parameters = array(), StreamedResponse $ * @param \Exception|null $previous The previous exception * * @return NotFoundHttpException + * + * @final since version 3.4 */ protected function createNotFoundException($message = 'Not Found', \Exception $previous = null) { @@ -311,6 +365,8 @@ protected function createNotFoundException($message = 'Not Found', \Exception $p * @param \Exception|null $previous The previous exception * * @return AccessDeniedException + * + * @final since version 3.4 */ protected function createAccessDeniedException($message = 'Access Denied.', \Exception $previous = null) { @@ -325,6 +381,8 @@ protected function createAccessDeniedException($message = 'Access Denied.', \Exc * @param array $options Options for the form * * @return Form + * + * @final since version 3.4 */ protected function createForm($type, $data = null, array $options = array()) { @@ -338,6 +396,8 @@ protected function createForm($type, $data = null, array $options = array()) * @param array $options Options for the form * * @return FormBuilder + * + * @final since version 3.4 */ protected function createFormBuilder($data = null, array $options = array()) { @@ -350,6 +410,8 @@ protected function createFormBuilder($data = null, array $options = array()) * @return Registry * * @throws \LogicException If DoctrineBundle is not available + * + * @final since version 3.4 */ protected function getDoctrine() { @@ -368,6 +430,8 @@ protected function getDoctrine() * @throws \LogicException If SecurityBundle is not available * * @see TokenInterface::getUser() + * + * @final since version 3.4 */ protected function getUser() { @@ -394,6 +458,8 @@ protected function getUser() * @param string $token The actual token sent with the request that should be validated * * @return bool + * + * @final since version 3.4 */ protected function isCsrfTokenValid($id, $token) { From 8bbb5e788417c4dca8e88d79688b6ab2e959d4cc Mon Sep 17 00:00:00 2001 From: Yonel Ceruto Date: Thu, 14 Sep 2017 15:14:31 -0400 Subject: [PATCH 0990/1099] Add debug:form type option --- .../Component/Form/Command/DebugCommand.php | 85 ++++++++++++++++++- .../Form/Console/Descriptor/Descriptor.php | 47 +++++----- .../Console/Descriptor/JsonDescriptor.php | 31 ++++++- .../Console/Descriptor/TextDescriptor.php | 60 +++++++++++-- .../Form/Tests/Command/DebugCommandTest.php | 11 ++- .../Descriptor/AbstractDescriptorTest.php | 74 ++++++++++++++-- .../default_option_with_normalizer.json | 11 +++ .../default_option_with_normalizer.txt | 24 ++++++ .../Tests/Fixtures/Descriptor/defaults_1.json | 35 +------- .../Tests/Fixtures/Descriptor/defaults_1.txt | 24 ++---- ...erridden_option_with_default_closures.json | 6 ++ ...verridden_option_with_default_closures.txt | 29 +++++++ .../required_option_with_allowed_values.json | 11 +++ .../required_option_with_allowed_values.txt | 25 ++++++ .../Descriptor/resolved_form_type_1.txt | 16 ++-- 15 files changed, 391 insertions(+), 98 deletions(-) create mode 100644 src/Symfony/Component/Form/Tests/Fixtures/Descriptor/default_option_with_normalizer.json create mode 100644 src/Symfony/Component/Form/Tests/Fixtures/Descriptor/default_option_with_normalizer.txt create mode 100644 src/Symfony/Component/Form/Tests/Fixtures/Descriptor/overridden_option_with_default_closures.json create mode 100644 src/Symfony/Component/Form/Tests/Fixtures/Descriptor/overridden_option_with_default_closures.txt create mode 100644 src/Symfony/Component/Form/Tests/Fixtures/Descriptor/required_option_with_allowed_values.json create mode 100644 src/Symfony/Component/Form/Tests/Fixtures/Descriptor/required_option_with_allowed_values.txt diff --git a/src/Symfony/Component/Form/Command/DebugCommand.php b/src/Symfony/Component/Form/Command/DebugCommand.php index d8e1f5a0789b0..68f3bc96f100d 100644 --- a/src/Symfony/Component/Form/Command/DebugCommand.php +++ b/src/Symfony/Component/Form/Command/DebugCommand.php @@ -19,7 +19,9 @@ use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Style\SymfonyStyle; use Symfony\Component\Form\Console\Helper\DescriptorHelper; +use Symfony\Component\Form\Extension\Core\CoreExtension; use Symfony\Component\Form\FormRegistryInterface; +use Symfony\Component\Form\FormTypeInterface; /** * A console command for retrieving information about form types. @@ -55,6 +57,7 @@ protected function configure() $this ->setDefinition(array( new InputArgument('class', InputArgument::OPTIONAL, 'The form type class'), + new InputArgument('option', InputArgument::OPTIONAL, 'The form type option'), new InputOption('format', null, InputOption::VALUE_REQUIRED, 'The output format (txt or json)', 'txt'), )) ->setDescription('Displays form type information') @@ -70,6 +73,10 @@ protected function configure() The command lists all defined options that contains the given form type, as well as their parents and type extensions. + php %command.full_name% ChoiceType choice_value + +The command displays the definition of the given option name. + php %command.full_name% --format=json The command lists everything in a machine readable json format. @@ -87,14 +94,42 @@ protected function execute(InputInterface $input, OutputInterface $output) if (null === $class = $input->getArgument('class')) { $object = null; - $options['types'] = $this->types; + $options['core_types'] = $this->getCoreTypes(); + $options['service_types'] = array_values(array_diff($this->types, $options['core_types'])); $options['extensions'] = $this->extensions; $options['guessers'] = $this->guessers; + foreach ($options as $k => $list) { + sort($options[$k]); + } } else { if (!class_exists($class)) { $class = $this->getFqcnTypeClass($input, $io, $class); } - $object = $this->formRegistry->getType($class); + $resolvedType = $this->formRegistry->getType($class); + + if ($option = $input->getArgument('option')) { + $object = $resolvedType->getOptionsResolver(); + + if (!$object->isDefined($option)) { + $message = sprintf('Option "%s" is not defined in "%s".', $option, get_class($resolvedType->getInnerType())); + + if ($alternatives = $this->findAlternatives($option, $object->getDefinedOptions())) { + if (1 == count($alternatives)) { + $message .= "\n\nDid you mean this?\n "; + } else { + $message .= "\n\nDid you mean one of these?\n "; + } + $message .= implode("\n ", $alternatives); + } + + throw new InvalidArgumentException($message); + } + + $options['type'] = $resolvedType->getInnerType(); + $options['option'] = $option; + } else { + $object = $resolvedType; + } } $helper = new DescriptorHelper(); @@ -105,6 +140,7 @@ protected function execute(InputInterface $input, OutputInterface $output) private function getFqcnTypeClass(InputInterface $input, SymfonyStyle $io, $shortClassName) { $classes = array(); + sort($this->namespaces); foreach ($this->namespaces as $namespace) { if (class_exists($fqcn = $namespace.'\\'.$shortClassName)) { $classes[] = $fqcn; @@ -112,7 +148,19 @@ private function getFqcnTypeClass(InputInterface $input, SymfonyStyle $io, $shor } if (0 === $count = count($classes)) { - throw new InvalidArgumentException(sprintf("Could not find type \"%s\" into the following namespaces:\n %s", $shortClassName, implode("\n ", $this->namespaces))); + $message = sprintf("Could not find type \"%s\" into the following namespaces:\n %s", $shortClassName, implode("\n ", $this->namespaces)); + + $allTypes = array_merge($this->getCoreTypes(), $this->types); + if ($alternatives = $this->findAlternatives($shortClassName, $allTypes)) { + if (1 == count($alternatives)) { + $message .= "\n\nDid you mean this?\n "; + } else { + $message .= "\n\nDid you mean one of these?\n "; + } + $message .= implode("\n ", $alternatives); + } + + throw new InvalidArgumentException($message); } if (1 === $count) { return $classes[0]; @@ -121,6 +169,35 @@ private function getFqcnTypeClass(InputInterface $input, SymfonyStyle $io, $shor throw new InvalidArgumentException(sprintf("The type \"%s\" is ambiguous.\n\nDid you mean one of these?\n %s", $shortClassName, implode("\n ", $classes))); } - return $io->choice(sprintf("The type \"%s\" is ambiguous.\n\n Select one of the following form types to display its information:", $shortClassName), $classes, $classes[0]); + return $io->choice(sprintf("The type \"%s\" is ambiguous.\n\nSelect one of the following form types to display its information:", $shortClassName), $classes, $classes[0]); + } + + private function getCoreTypes() + { + $coreExtension = new CoreExtension(); + $loadTypesRefMethod = (new \ReflectionObject($coreExtension))->getMethod('loadTypes'); + $loadTypesRefMethod->setAccessible(true); + $coreTypes = $loadTypesRefMethod->invoke($coreExtension); + $coreTypes = array_map(function (FormTypeInterface $type) { return get_class($type); }, $coreTypes); + sort($coreTypes); + + return $coreTypes; + } + + private function findAlternatives($name, array $collection) + { + $alternatives = array(); + foreach ($collection as $item) { + $lev = levenshtein($name, $item); + if ($lev <= strlen($name) / 3 || false !== strpos($item, $name)) { + $alternatives[$item] = isset($alternatives[$item]) ? $alternatives[$item] - $lev : $lev; + } + } + + $threshold = 1e3; + $alternatives = array_filter($alternatives, function ($lev) use ($threshold) { return $lev < 2 * $threshold; }); + ksort($alternatives, SORT_NATURAL | SORT_FLAG_CASE); + + return array_keys($alternatives); } } diff --git a/src/Symfony/Component/Form/Console/Descriptor/Descriptor.php b/src/Symfony/Component/Form/Console/Descriptor/Descriptor.php index c72a19d7993f1..f149becc66469 100644 --- a/src/Symfony/Component/Form/Console/Descriptor/Descriptor.php +++ b/src/Symfony/Component/Form/Console/Descriptor/Descriptor.php @@ -14,10 +14,8 @@ use Symfony\Component\Console\Descriptor\DescriptorInterface; use Symfony\Component\Console\Input\ArrayInput; use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Style\StyleInterface; +use Symfony\Component\Console\Style\OutputStyle; use Symfony\Component\Console\Style\SymfonyStyle; -use Symfony\Component\Form\Extension\Core\CoreExtension; -use Symfony\Component\Form\FormTypeInterface; use Symfony\Component\Form\ResolvedFormTypeInterface; use Symfony\Component\Form\Util\OptionsResolverWrapper; use Symfony\Component\OptionsResolver\OptionsResolver; @@ -29,7 +27,7 @@ */ abstract class Descriptor implements DescriptorInterface { - /** @var StyleInterface */ + /** @var OutputStyle */ protected $output; protected $type; protected $ownOptions = array(); @@ -45,7 +43,7 @@ abstract class Descriptor implements DescriptorInterface */ public function describe(OutputInterface $output, $object, array $options = array()) { - $this->output = $output instanceof StyleInterface ? $output : new SymfonyStyle(new ArrayInput(array()), $output); + $this->output = $output instanceof OutputStyle ? $output : new SymfonyStyle(new ArrayInput(array()), $output); switch (true) { case null === $object: @@ -54,28 +52,19 @@ public function describe(OutputInterface $output, $object, array $options = arra case $object instanceof ResolvedFormTypeInterface: $this->describeResolvedFormType($object, $options); break; + case $object instanceof OptionsResolver: + $this->describeOption($object, $options); + break; default: throw new \InvalidArgumentException(sprintf('Object of type "%s" is not describable.', get_class($object))); } } - abstract protected function describeDefaults(array $options = array()); + abstract protected function describeDefaults(array $options); abstract protected function describeResolvedFormType(ResolvedFormTypeInterface $resolvedFormType, array $options = array()); - protected function getCoreTypes() - { - $coreExtension = new CoreExtension(); - $coreExtensionRefObject = new \ReflectionObject($coreExtension); - $loadTypesRefMethod = $coreExtensionRefObject->getMethod('loadTypes'); - $loadTypesRefMethod->setAccessible(true); - $coreTypes = $loadTypesRefMethod->invoke($coreExtension); - - $coreTypes = array_map(function (FormTypeInterface $type) { return get_class($type); }, $coreTypes); - sort($coreTypes); - - return $coreTypes; - } + abstract protected function describeOption(OptionsResolver $optionsResolver, array $options); protected function collectOptions(ResolvedFormTypeInterface $type) { @@ -113,6 +102,26 @@ protected function collectOptions(ResolvedFormTypeInterface $type) $this->extensions = array_keys($this->extensions); } + protected function getOptionDefinition(OptionsResolver $optionsResolver, $option) + { + $refObject = new \ReflectionObject($optionsResolver); + foreach (array('defaults', 'lazy', 'allowedTypes', 'allowedValues', 'normalizers') as $name) { + $property = $refObject->getProperty($name); + $property->setAccessible(true); + $value = $property->getValue($optionsResolver); + if (array_key_exists($option, $value)) { + $definition[$name] = $value[$option]; + } + } + $definition['required'] = $optionsResolver->isRequired($option); + + if (isset($definition['lazy']) && 1 === count($definition['lazy'])) { + $definition['lazy'] = $definition['lazy'][0]; + } + + return $definition; + } + private function getParentOptionsResolver(ResolvedFormTypeInterface $type) { $this->parents[$class = get_class($type->getInnerType())] = array(); diff --git a/src/Symfony/Component/Form/Console/Descriptor/JsonDescriptor.php b/src/Symfony/Component/Form/Console/Descriptor/JsonDescriptor.php index 7616d616f1441..de296e19b7906 100644 --- a/src/Symfony/Component/Form/Console/Descriptor/JsonDescriptor.php +++ b/src/Symfony/Component/Form/Console/Descriptor/JsonDescriptor.php @@ -12,6 +12,7 @@ namespace Symfony\Component\Form\Console\Descriptor; use Symfony\Component\Form\ResolvedFormTypeInterface; +use Symfony\Component\OptionsResolver\OptionsResolver; /** * @author Yonel Ceruto @@ -20,10 +21,10 @@ */ class JsonDescriptor extends Descriptor { - protected function describeDefaults(array $options = array()) + protected function describeDefaults(array $options) { - $data['builtin_form_types'] = $this->getCoreTypes(); - $data['service_form_types'] = array_values(array_diff($options['types'], $data['builtin_form_types'])); + $data['builtin_form_types'] = $options['core_types']; + $data['service_form_types'] = $options['service_types']; $data['type_extensions'] = $options['extensions']; $data['type_guessers'] = $options['guessers']; @@ -54,6 +55,30 @@ protected function describeResolvedFormType(ResolvedFormTypeInterface $resolvedF $this->writeData($data, $options); } + protected function describeOption(OptionsResolver $optionsResolver, array $options) + { + $definition = $this->getOptionDefinition($optionsResolver, $options['option']); + + $map = array( + 'required' => 'required', + 'default' => 'defaults', + 'allowed_types' => 'allowedTypes', + 'allowed_values' => 'allowedValues', + ); + foreach ($map as $label => $name) { + if (array_key_exists($name, $definition)) { + $data[$label] = $definition[$name]; + + if ('defaults' === $name) { + $data['is_lazy'] = isset($definition['lazy']); + } + } + } + $data['has_normalizer'] = isset($definition['normalizers']); + + $this->writeData($data, $options); + } + private function writeData(array $data, array $options) { $flags = isset($options['json_encoding']) ? $options['json_encoding'] : 0; diff --git a/src/Symfony/Component/Form/Console/Descriptor/TextDescriptor.php b/src/Symfony/Component/Form/Console/Descriptor/TextDescriptor.php index d5072f1e9a632..2b58d8ffb3c33 100644 --- a/src/Symfony/Component/Form/Console/Descriptor/TextDescriptor.php +++ b/src/Symfony/Component/Form/Console/Descriptor/TextDescriptor.php @@ -13,6 +13,10 @@ use Symfony\Component\Console\Helper\TableSeparator; use Symfony\Component\Form\ResolvedFormTypeInterface; +use Symfony\Component\OptionsResolver\OptionsResolver; +use Symfony\Component\VarDumper\Caster\Caster; +use Symfony\Component\VarDumper\Cloner\VarCloner; +use Symfony\Component\VarDumper\Dumper\CliDumper; /** * @author Yonel Ceruto @@ -21,18 +25,16 @@ */ class TextDescriptor extends Descriptor { - protected function describeDefaults(array $options = array()) + protected function describeDefaults(array $options) { - $coreTypes = $this->getCoreTypes(); - $this->output->section('Built-in form types (Symfony\Component\Form\Extension\Core\Type)'); - $shortClassNames = array_map(function ($fqcn) { return array_slice(explode('\\', $fqcn), -1)[0]; }, $coreTypes); + $shortClassNames = array_map(function ($fqcn) { return array_slice(explode('\\', $fqcn), -1)[0]; }, $options['core_types']); for ($i = 0; $i * 5 < count($shortClassNames); ++$i) { $this->output->writeln(' '.implode(', ', array_slice($shortClassNames, $i * 5, 5))); } $this->output->section('Service form types'); - $this->output->listing(array_diff($options['types'], $coreTypes)); + $this->output->listing($options['service_types']); $this->output->section('Type extensions'); $this->output->listing($options['extensions']); @@ -94,6 +96,34 @@ protected function describeResolvedFormType(ResolvedFormTypeInterface $resolvedF } } + protected function describeOption(OptionsResolver $optionsResolver, array $options) + { + $definition = $this->getOptionDefinition($optionsResolver, $options['option']); + + $dump = $this->getDumpFunction(); + $map = array( + 'Required' => 'required', + 'Default' => 'defaults', + 'Allowed types' => 'allowedTypes', + 'Allowed values' => 'allowedValues', + 'Normalizer' => 'normalizers', + ); + $rows = array(); + foreach ($map as $label => $name) { + $value = array_key_exists($name, $definition) ? $dump($definition[$name]) : '-'; + if ('defaults' === $name && isset($definition['lazy'])) { + $value = "Value: $value\n\nClosure(s): ".$dump($definition['lazy']); + } + + $rows[] = array("$label", $value); + $rows[] = new TableSeparator(); + } + array_pop($rows); + + $this->output->title(sprintf('%s (%s)', get_class($options['type']), $options['option'])); + $this->output->table(array(), $rows); + } + private function normalizeAndSortOptionsColumns(array $options) { foreach ($options as $group => &$opts) { @@ -125,4 +155,24 @@ private function normalizeAndSortOptionsColumns(array $options) return $options; } + + private function getDumpFunction() + { + $cloner = new VarCloner(); + $cloner->addCasters(array('Closure' => function ($c, $a) { + $prefix = Caster::PREFIX_VIRTUAL; + + return array( + $prefix.'parameters' => isset($a[$prefix.'parameters']) ? count($a[$prefix.'parameters']->value) : 0, + $prefix.'file' => $a[$prefix.'file'], + $prefix.'line' => $a[$prefix.'line'], + ); + })); + $dumper = new CliDumper(null, null, CliDumper::DUMP_LIGHT_ARRAY | CliDumper::DUMP_COMMA_SEPARATOR); + $dumper->setColors($this->output->isDecorated()); + + return function ($value) use ($dumper, $cloner) { + return rtrim($dumper->dump($cloner->cloneVar($value)->withRefHandles(false), true)); + }; + } } diff --git a/src/Symfony/Component/Form/Tests/Command/DebugCommandTest.php b/src/Symfony/Component/Form/Tests/Command/DebugCommandTest.php index d24af0a4b1bc5..f69222c345edb 100644 --- a/src/Symfony/Component/Form/Tests/Command/DebugCommandTest.php +++ b/src/Symfony/Component/Form/Tests/Command/DebugCommandTest.php @@ -39,6 +39,15 @@ public function testDebugSingleFormType() $this->assertContains('Symfony\Component\Form\Extension\Core\Type\FormType (Block prefix: "form")', $tester->getDisplay()); } + public function testDebugFormTypeOption() + { + $tester = $this->createCommandTester(); + $ret = $tester->execute(array('class' => 'FormType', 'option' => 'method'), array('decorated' => false)); + + $this->assertEquals(0, $ret, 'Returns 0 in case of success'); + $this->assertContains('Symfony\Component\Form\Extension\Core\Type\FormType (method)', $tester->getDisplay()); + } + /** * @expectedException \Symfony\Component\Console\Exception\InvalidArgumentException * @expectedExceptionMessage Could not find type "NonExistentType" @@ -90,7 +99,7 @@ public function testDebugAmbiguousFormTypeInteractive() The type "AmbiguousType" is ambiguous. - Select one of the following form types to display its information: [%A\A\AmbiguousType]: +Select one of the following form types to display its information: [%A\A\AmbiguousType]: [0] %A\A\AmbiguousType [1] %A\B\AmbiguousType %A diff --git a/src/Symfony/Component/Form/Tests/Console/Descriptor/AbstractDescriptorTest.php b/src/Symfony/Component/Form/Tests/Console/Descriptor/AbstractDescriptorTest.php index 3a5efcefeb684..8849266527d81 100644 --- a/src/Symfony/Component/Form/Tests/Console/Descriptor/AbstractDescriptorTest.php +++ b/src/Symfony/Component/Form/Tests/Console/Descriptor/AbstractDescriptorTest.php @@ -15,11 +15,15 @@ use Symfony\Component\Console\Input\ArrayInput; use Symfony\Component\Console\Output\BufferedOutput; use Symfony\Component\Console\Style\SymfonyStyle; +use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\Extension\Core\Type\ChoiceType; use Symfony\Component\Form\Extension\Core\Type\FormType; use Symfony\Component\Form\Extension\Csrf\Type\FormTypeCsrfExtension; +use Symfony\Component\Form\FormInterface; use Symfony\Component\Form\ResolvedFormType; use Symfony\Component\Form\ResolvedFormTypeInterface; +use Symfony\Component\OptionsResolver\Options; +use Symfony\Component\OptionsResolver\OptionsResolver; use Symfony\Component\Security\Csrf\CsrfTokenManager; abstract class AbstractDescriptorTest extends TestCase @@ -27,8 +31,8 @@ abstract class AbstractDescriptorTest extends TestCase /** @dataProvider getDescribeDefaultsTestData */ public function testDescribeDefaults($object, array $options, $fixtureName) { - $expectedDescription = $this->getExpectedDescription($fixtureName); $describedObject = $this->getObjectDescription($object, $options); + $expectedDescription = $this->getExpectedDescription($fixtureName); if ('json' === $this->getFormat()) { $this->assertEquals(json_encode(json_decode($expectedDescription), JSON_PRETTY_PRINT), json_encode(json_decode($describedObject), JSON_PRETTY_PRINT)); @@ -40,8 +44,8 @@ public function testDescribeDefaults($object, array $options, $fixtureName) /** @dataProvider getDescribeResolvedFormTypeTestData */ public function testDescribeResolvedFormType(ResolvedFormTypeInterface $type, array $options, $fixtureName) { - $expectedDescription = $this->getExpectedDescription($fixtureName); $describedObject = $this->getObjectDescription($type, $options); + $expectedDescription = $this->getExpectedDescription($fixtureName); if ('json' === $this->getFormat()) { $this->assertEquals(json_encode(json_decode($expectedDescription), JSON_PRETTY_PRINT), json_encode(json_decode($describedObject), JSON_PRETTY_PRINT)); @@ -50,32 +54,64 @@ public function testDescribeResolvedFormType(ResolvedFormTypeInterface $type, ar } } + /** @dataProvider getDescribeOptionTestData */ + public function testDescribeOption(OptionsResolver $optionsResolver, array $options, $fixtureName) + { + $describedObject = $this->getObjectDescription($optionsResolver, $options); + $expectedDescription = $this->getExpectedDescription($fixtureName); + + if ('json' === $this->getFormat()) { + $this->assertEquals(json_encode(json_decode($expectedDescription), JSON_PRETTY_PRINT), json_encode(json_decode($describedObject), JSON_PRETTY_PRINT)); + } else { + $this->assertStringMatchesFormat(trim($expectedDescription), trim(str_replace(PHP_EOL, "\n", $describedObject))); + } + } + public function getDescribeDefaultsTestData() { - $options['types'] = array('Symfony\Bridge\Doctrine\Form\Type\EntityType'); + $options['core_types'] = array('Symfony\Component\Form\Extension\Core\Type\FormType'); + $options['service_types'] = array('Symfony\Bridge\Doctrine\Form\Type\EntityType'); $options['extensions'] = array('Symfony\Component\Form\Extension\Csrf\Type\FormTypeCsrfExtension'); $options['guessers'] = array('Symfony\Component\Form\Extension\Validator\ValidatorTypeGuesser'); + $options['decorated'] = false; yield array(null, $options, 'defaults_1'); } public function getDescribeResolvedFormTypeTestData() { - $typeExtensions = array( - new FormTypeCsrfExtension(new CsrfTokenManager()), - ); + $typeExtensions = array(new FormTypeCsrfExtension(new CsrfTokenManager())); $parent = new ResolvedFormType(new FormType(), $typeExtensions); - yield array(new ResolvedFormType(new ChoiceType(), array(), $parent), array(), 'resolved_form_type_1'); + yield array(new ResolvedFormType(new ChoiceType(), array(), $parent), array('decorated' => false), 'resolved_form_type_1'); + } + + public function getDescribeOptionTestData() + { + $parent = new ResolvedFormType(new FormType()); + $options['decorated'] = false; + + $resolvedType = new ResolvedFormType(new ChoiceType(), array(), $parent); + $options['type'] = $resolvedType->getInnerType(); + $options['option'] = 'choice_translation_domain'; + yield array($resolvedType->getOptionsResolver(), $options, 'default_option_with_normalizer'); + + $resolvedType = new ResolvedFormType(new FooType(), array(), $parent); + $options['type'] = $resolvedType->getInnerType(); + $options['option'] = 'foo'; + yield array($resolvedType->getOptionsResolver(), $options, 'required_option_with_allowed_values'); + + $options['option'] = 'empty_data'; + yield array($resolvedType->getOptionsResolver(), $options, 'overridden_option_with_default_closures'); } abstract protected function getDescriptor(); abstract protected function getFormat(); - private function getObjectDescription($object, array $options = array()) + private function getObjectDescription($object, array $options) { - $output = new BufferedOutput(BufferedOutput::VERBOSITY_NORMAL, true); + $output = new BufferedOutput(BufferedOutput::VERBOSITY_NORMAL, $options['decorated']); $io = new SymfonyStyle(new ArrayInput(array()), $output); $this->getDescriptor()->describe($io, $object, $options); @@ -93,3 +129,23 @@ private function getFixtureFilename($name) return sprintf('%s/../../Fixtures/Descriptor/%s.%s', __DIR__, $name, $this->getFormat()); } } + +class FooType extends AbstractType +{ + public function configureOptions(OptionsResolver $resolver) + { + $resolver->setRequired('foo'); + $resolver->setDefault('empty_data', function (Options $options, $value) { + $foo = $options['foo']; + + return function (FormInterface $form) use ($foo) { + return $form->getConfig()->getCompound() ? array($foo) : $foo; + }; + }); + $resolver->setAllowedTypes('foo', 'string'); + $resolver->setAllowedValues('foo', array('bar', 'baz')); + $resolver->setNormalizer('foo', function (Options $options, $value) { + return (string) $value; + }); + } +} diff --git a/src/Symfony/Component/Form/Tests/Fixtures/Descriptor/default_option_with_normalizer.json b/src/Symfony/Component/Form/Tests/Fixtures/Descriptor/default_option_with_normalizer.json new file mode 100644 index 0000000000000..0ac903a954754 --- /dev/null +++ b/src/Symfony/Component/Form/Tests/Fixtures/Descriptor/default_option_with_normalizer.json @@ -0,0 +1,11 @@ +{ + "required": false, + "default": true, + "is_lazy": false, + "allowed_types": [ + "null", + "bool", + "string" + ], + "has_normalizer": true +} diff --git a/src/Symfony/Component/Form/Tests/Fixtures/Descriptor/default_option_with_normalizer.txt b/src/Symfony/Component/Form/Tests/Fixtures/Descriptor/default_option_with_normalizer.txt new file mode 100644 index 0000000000000..a579a90e53b58 --- /dev/null +++ b/src/Symfony/Component/Form/Tests/Fixtures/Descriptor/default_option_with_normalizer.txt @@ -0,0 +1,24 @@ + +Symfony\Component\Form\Extension\Core\Type\ChoiceType (choice_translation_domain) +================================================================================= + + ---------------- --------------------%s + Required false %s + ---------------- --------------------%s + Default true %s + ---------------- --------------------%s + Allowed types [ %s + "null", %s + "bool", %s + "string" %s + ] %s + ---------------- --------------------%s + Allowed values - %s + ---------------- --------------------%s + Normalizer Closure { %s + parameters: 2, %s + file: "%s%eExtension%eCore%eType%eChoiceType.php", + line: "%s to %s" %s + } %s + ---------------- --------------------%s + diff --git a/src/Symfony/Component/Form/Tests/Fixtures/Descriptor/defaults_1.json b/src/Symfony/Component/Form/Tests/Fixtures/Descriptor/defaults_1.json index 99858a2f997e8..7629e80431ebe 100644 --- a/src/Symfony/Component/Form/Tests/Fixtures/Descriptor/defaults_1.json +++ b/src/Symfony/Component/Form/Tests/Fixtures/Descriptor/defaults_1.json @@ -1,39 +1,6 @@ { "builtin_form_types": [ - "Symfony\\Component\\Form\\Extension\\Core\\Type\\BirthdayType", - "Symfony\\Component\\Form\\Extension\\Core\\Type\\ButtonType", - "Symfony\\Component\\Form\\Extension\\Core\\Type\\CheckboxType", - "Symfony\\Component\\Form\\Extension\\Core\\Type\\ChoiceType", - "Symfony\\Component\\Form\\Extension\\Core\\Type\\CollectionType", - "Symfony\\Component\\Form\\Extension\\Core\\Type\\ColorType", - "Symfony\\Component\\Form\\Extension\\Core\\Type\\CountryType", - "Symfony\\Component\\Form\\Extension\\Core\\Type\\CurrencyType", - "Symfony\\Component\\Form\\Extension\\Core\\Type\\DateIntervalType", - "Symfony\\Component\\Form\\Extension\\Core\\Type\\DateTimeType", - "Symfony\\Component\\Form\\Extension\\Core\\Type\\DateType", - "Symfony\\Component\\Form\\Extension\\Core\\Type\\EmailType", - "Symfony\\Component\\Form\\Extension\\Core\\Type\\FileType", - "Symfony\\Component\\Form\\Extension\\Core\\Type\\FormType", - "Symfony\\Component\\Form\\Extension\\Core\\Type\\HiddenType", - "Symfony\\Component\\Form\\Extension\\Core\\Type\\IntegerType", - "Symfony\\Component\\Form\\Extension\\Core\\Type\\LanguageType", - "Symfony\\Component\\Form\\Extension\\Core\\Type\\LocaleType", - "Symfony\\Component\\Form\\Extension\\Core\\Type\\MoneyType", - "Symfony\\Component\\Form\\Extension\\Core\\Type\\NumberType", - "Symfony\\Component\\Form\\Extension\\Core\\Type\\PasswordType", - "Symfony\\Component\\Form\\Extension\\Core\\Type\\PercentType", - "Symfony\\Component\\Form\\Extension\\Core\\Type\\RadioType", - "Symfony\\Component\\Form\\Extension\\Core\\Type\\RangeType", - "Symfony\\Component\\Form\\Extension\\Core\\Type\\RepeatedType", - "Symfony\\Component\\Form\\Extension\\Core\\Type\\ResetType", - "Symfony\\Component\\Form\\Extension\\Core\\Type\\SearchType", - "Symfony\\Component\\Form\\Extension\\Core\\Type\\SubmitType", - "Symfony\\Component\\Form\\Extension\\Core\\Type\\TelType", - "Symfony\\Component\\Form\\Extension\\Core\\Type\\TextType", - "Symfony\\Component\\Form\\Extension\\Core\\Type\\TextareaType", - "Symfony\\Component\\Form\\Extension\\Core\\Type\\TimeType", - "Symfony\\Component\\Form\\Extension\\Core\\Type\\TimezoneType", - "Symfony\\Component\\Form\\Extension\\Core\\Type\\UrlType" + "Symfony\\Component\\Form\\Extension\\Core\\Type\\FormType" ], "service_form_types": [ "Symfony\\Bridge\\Doctrine\\Form\\Type\\EntityType" diff --git a/src/Symfony/Component/Form/Tests/Fixtures/Descriptor/defaults_1.txt b/src/Symfony/Component/Form/Tests/Fixtures/Descriptor/defaults_1.txt index 52a579ac43e62..9b3338ec7bd31 100644 --- a/src/Symfony/Component/Form/Tests/Fixtures/Descriptor/defaults_1.txt +++ b/src/Symfony/Component/Form/Tests/Fixtures/Descriptor/defaults_1.txt @@ -1,27 +1,21 @@ -Built-in form types (Symfony\Component\Form\Extension\Core\Type) ----------------------------------------------------------------- +Built-in form types (Symfony\Component\Form\Extension\Core\Type) +---------------------------------------------------------------- - BirthdayType, ButtonType, CheckboxType, ChoiceType, CollectionType - ColorType, CountryType, CurrencyType, DateIntervalType, DateTimeType - DateType, EmailType, FileType, FormType, HiddenType - IntegerType, LanguageType, LocaleType, MoneyType, NumberType - PasswordType, PercentType, RadioType, RangeType, RepeatedType - ResetType, SearchType, SubmitType, TelType, TextType - TextareaType, TimeType, TimezoneType, UrlType + FormType -Service form types ------------------- +Service form types +------------------ * Symfony\Bridge\Doctrine\Form\Type\EntityType -Type extensions ---------------- +Type extensions +--------------- * Symfony\Component\Form\Extension\Csrf\Type\FormTypeCsrfExtension -Type guessers -------------- +Type guessers +------------- * Symfony\Component\Form\Extension\Validator\ValidatorTypeGuesser diff --git a/src/Symfony/Component/Form/Tests/Fixtures/Descriptor/overridden_option_with_default_closures.json b/src/Symfony/Component/Form/Tests/Fixtures/Descriptor/overridden_option_with_default_closures.json new file mode 100644 index 0000000000000..c41e377acd3db --- /dev/null +++ b/src/Symfony/Component/Form/Tests/Fixtures/Descriptor/overridden_option_with_default_closures.json @@ -0,0 +1,6 @@ +{ + "required": false, + "default": null, + "is_lazy": true, + "has_normalizer": false +} diff --git a/src/Symfony/Component/Form/Tests/Fixtures/Descriptor/overridden_option_with_default_closures.txt b/src/Symfony/Component/Form/Tests/Fixtures/Descriptor/overridden_option_with_default_closures.txt new file mode 100644 index 0000000000000..662d982979bc4 --- /dev/null +++ b/src/Symfony/Component/Form/Tests/Fixtures/Descriptor/overridden_option_with_default_closures.txt @@ -0,0 +1,29 @@ + +Symfony\Component\Form\Tests\Console\Descriptor\FooType (empty_data) +==================================================================== + + ---------------- ----------------------%s + Required false %s + ---------------- ----------------------%s + Default Value: null %s + %s + Closure(s): [ %s + Closure { %s + parameters: 1, %s + file: "%s%eExtension%eCore%eType%eFormType.php", + line: "%s to %s" %s + }, %s + Closure { %s + parameters: 2, %s + file: "%s%eTests%eConsole%eDescriptor%eAbstractDescriptorTest.php", + line: "%s to %s" %s + } %s + ] %s + ---------------- ----------------------%s + Allowed types - %s + ---------------- ----------------------%s + Allowed values - %s + ---------------- ----------------------%s + Normalizer - %s + ---------------- ----------------------%s + diff --git a/src/Symfony/Component/Form/Tests/Fixtures/Descriptor/required_option_with_allowed_values.json b/src/Symfony/Component/Form/Tests/Fixtures/Descriptor/required_option_with_allowed_values.json new file mode 100644 index 0000000000000..126933c6b0485 --- /dev/null +++ b/src/Symfony/Component/Form/Tests/Fixtures/Descriptor/required_option_with_allowed_values.json @@ -0,0 +1,11 @@ +{ + "required": true, + "allowed_types": [ + "string" + ], + "allowed_values": [ + "bar", + "baz" + ], + "has_normalizer": true +} diff --git a/src/Symfony/Component/Form/Tests/Fixtures/Descriptor/required_option_with_allowed_values.txt b/src/Symfony/Component/Form/Tests/Fixtures/Descriptor/required_option_with_allowed_values.txt new file mode 100644 index 0000000000000..049b692f1dc7f --- /dev/null +++ b/src/Symfony/Component/Form/Tests/Fixtures/Descriptor/required_option_with_allowed_values.txt @@ -0,0 +1,25 @@ + +Symfony\Component\Form\Tests\Console\Descriptor\FooType (foo) +============================================================= + + ---------------- --------------------%s + Required true %s + ---------------- --------------------%s + Default - %s + ---------------- --------------------%s + Allowed types [ %s + "string" %s + ] %s + ---------------- --------------------%s + Allowed values [ %s + "bar", %s + "baz" %s + ] %s + ---------------- --------------------%s + Normalizer Closure { %s + parameters: 2, %s + file: "%s%eTests%eConsole%eDescriptor%eAbstractDescriptorTest.php", + line: "%s to %s" %s + } %s + ---------------- --------------------%s + diff --git a/src/Symfony/Component/Form/Tests/Fixtures/Descriptor/resolved_form_type_1.txt b/src/Symfony/Component/Form/Tests/Fixtures/Descriptor/resolved_form_type_1.txt index 5f839b85ac6b0..2b34ad960d672 100644 --- a/src/Symfony/Component/Form/Tests/Fixtures/Descriptor/resolved_form_type_1.txt +++ b/src/Symfony/Component/Form/Tests/Fixtures/Descriptor/resolved_form_type_1.txt @@ -1,11 +1,11 @@ -Symfony\Component\Form\Extension\Core\Type\ChoiceType (Block prefix: "choice") -============================================================================== +Symfony\Component\Form\Extension\Core\Type\ChoiceType (Block prefix: "choice") +============================================================================== --------------------------- -------------------- ------------------------- ----------------------- -  Options   Overridden options   Parent options   Extension options  + Options Overridden options Parent options Extension options --------------------------- -------------------- ------------------------- ----------------------- - choice_attr FormType FormType FormTypeCsrfExtension + choice_attr FormType FormType FormTypeCsrfExtension choice_label -------------------- ------------------------- ----------------------- choice_loader compound action csrf_field_name choice_name data_class attr csrf_message @@ -28,13 +28,13 @@ upload_max_size_message --------------------------- -------------------- ------------------------- ----------------------- -Parent types ------------- +Parent types +------------ * Symfony\Component\Form\Extension\Core\Type\FormType -Type extensions ---------------- +Type extensions +--------------- * Symfony\Component\Form\Extension\Csrf\Type\FormTypeCsrfExtension From 0e1ce341025d14f35e9171e09f38960ff7aa757e Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Tue, 3 Oct 2017 13:02:27 +0200 Subject: [PATCH 0991/1099] [Intl] fix return type value --- src/Symfony/Component/Intl/Locale.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Symfony/Component/Intl/Locale.php b/src/Symfony/Component/Intl/Locale.php index 9eef59ea6c155..236e58e3f676f 100644 --- a/src/Symfony/Component/Intl/Locale.php +++ b/src/Symfony/Component/Intl/Locale.php @@ -105,6 +105,8 @@ public static function getFallback($locale): ?string if (strlen($locale) < 4) { return self::$defaultFallback; } + + return null; } /** From d6d187d26e0921a428c7ecc423d4f915c8f72c14 Mon Sep 17 00:00:00 2001 From: Maxime Steinhausser Date: Tue, 26 Sep 2017 18:43:11 +0200 Subject: [PATCH 0992/1099] Add & use OptionResolverIntrospector --- .../Form/Console/Descriptor/Descriptor.php | 31 +-- .../Console/Descriptor/JsonDescriptor.php | 6 +- .../Console/Descriptor/TextDescriptor.php | 6 +- .../Component/OptionsResolver/CHANGELOG.md | 5 + .../Debug/OptionsResolverIntrospector.php | 102 +++++++++ .../Exception/NoConfigurationException.php | 26 +++ .../Debug/OptionsResolverIntrospectorTest.php | 203 ++++++++++++++++++ 7 files changed, 361 insertions(+), 18 deletions(-) create mode 100644 src/Symfony/Component/OptionsResolver/Debug/OptionsResolverIntrospector.php create mode 100644 src/Symfony/Component/OptionsResolver/Exception/NoConfigurationException.php create mode 100644 src/Symfony/Component/OptionsResolver/Tests/Debug/OptionsResolverIntrospectorTest.php diff --git a/src/Symfony/Component/Form/Console/Descriptor/Descriptor.php b/src/Symfony/Component/Form/Console/Descriptor/Descriptor.php index f149becc66469..6cccd8ead235f 100644 --- a/src/Symfony/Component/Form/Console/Descriptor/Descriptor.php +++ b/src/Symfony/Component/Form/Console/Descriptor/Descriptor.php @@ -18,6 +18,8 @@ use Symfony\Component\Console\Style\SymfonyStyle; use Symfony\Component\Form\ResolvedFormTypeInterface; use Symfony\Component\Form\Util\OptionsResolverWrapper; +use Symfony\Component\OptionsResolver\Debug\OptionsResolverIntrospector; +use Symfony\Component\OptionsResolver\Exception\NoConfigurationException; use Symfony\Component\OptionsResolver\OptionsResolver; /** @@ -104,20 +106,25 @@ protected function collectOptions(ResolvedFormTypeInterface $type) protected function getOptionDefinition(OptionsResolver $optionsResolver, $option) { - $refObject = new \ReflectionObject($optionsResolver); - foreach (array('defaults', 'lazy', 'allowedTypes', 'allowedValues', 'normalizers') as $name) { - $property = $refObject->getProperty($name); - $property->setAccessible(true); - $value = $property->getValue($optionsResolver); - if (array_key_exists($option, $value)) { - $definition[$name] = $value[$option]; + $definition = array('required' => $optionsResolver->isRequired($option)); + + $introspector = new OptionsResolverIntrospector($optionsResolver); + + $map = array( + 'default' => 'getDefault', + 'lazy' => 'getLazyClosures', + 'allowedTypes' => 'getAllowedTypes', + 'allowedValues' => 'getAllowedValues', + 'normalizer' => 'getNormalizer', + ); + + foreach ($map as $key => $method) { + try { + $definition[$key] = $introspector->{$method}($option); + } catch (NoConfigurationException $e) { + // noop } } - $definition['required'] = $optionsResolver->isRequired($option); - - if (isset($definition['lazy']) && 1 === count($definition['lazy'])) { - $definition['lazy'] = $definition['lazy'][0]; - } return $definition; } diff --git a/src/Symfony/Component/Form/Console/Descriptor/JsonDescriptor.php b/src/Symfony/Component/Form/Console/Descriptor/JsonDescriptor.php index de296e19b7906..9d02aba3c12ad 100644 --- a/src/Symfony/Component/Form/Console/Descriptor/JsonDescriptor.php +++ b/src/Symfony/Component/Form/Console/Descriptor/JsonDescriptor.php @@ -61,7 +61,7 @@ protected function describeOption(OptionsResolver $optionsResolver, array $optio $map = array( 'required' => 'required', - 'default' => 'defaults', + 'default' => 'default', 'allowed_types' => 'allowedTypes', 'allowed_values' => 'allowedValues', ); @@ -69,12 +69,12 @@ protected function describeOption(OptionsResolver $optionsResolver, array $optio if (array_key_exists($name, $definition)) { $data[$label] = $definition[$name]; - if ('defaults' === $name) { + if ('default' === $name) { $data['is_lazy'] = isset($definition['lazy']); } } } - $data['has_normalizer'] = isset($definition['normalizers']); + $data['has_normalizer'] = isset($definition['normalizer']); $this->writeData($data, $options); } diff --git a/src/Symfony/Component/Form/Console/Descriptor/TextDescriptor.php b/src/Symfony/Component/Form/Console/Descriptor/TextDescriptor.php index 2b58d8ffb3c33..6e17e9b859e01 100644 --- a/src/Symfony/Component/Form/Console/Descriptor/TextDescriptor.php +++ b/src/Symfony/Component/Form/Console/Descriptor/TextDescriptor.php @@ -103,15 +103,15 @@ protected function describeOption(OptionsResolver $optionsResolver, array $optio $dump = $this->getDumpFunction(); $map = array( 'Required' => 'required', - 'Default' => 'defaults', + 'Default' => 'default', 'Allowed types' => 'allowedTypes', 'Allowed values' => 'allowedValues', - 'Normalizer' => 'normalizers', + 'Normalizer' => 'normalizer', ); $rows = array(); foreach ($map as $label => $name) { $value = array_key_exists($name, $definition) ? $dump($definition[$name]) : '-'; - if ('defaults' === $name && isset($definition['lazy'])) { + if ('default' === $name && isset($definition['lazy'])) { $value = "Value: $value\n\nClosure(s): ".$dump($definition['lazy']); } diff --git a/src/Symfony/Component/OptionsResolver/CHANGELOG.md b/src/Symfony/Component/OptionsResolver/CHANGELOG.md index 5f6d15b2c7ddc..d19116f37c280 100644 --- a/src/Symfony/Component/OptionsResolver/CHANGELOG.md +++ b/src/Symfony/Component/OptionsResolver/CHANGELOG.md @@ -1,6 +1,11 @@ CHANGELOG ========= +3.4.0 +----- + + * added `OptionsResolverIntrospector` to inspect options definitions inside an `OptionsResolver` instance + 2.6.0 ----- diff --git a/src/Symfony/Component/OptionsResolver/Debug/OptionsResolverIntrospector.php b/src/Symfony/Component/OptionsResolver/Debug/OptionsResolverIntrospector.php new file mode 100644 index 0000000000000..60317243e9c4f --- /dev/null +++ b/src/Symfony/Component/OptionsResolver/Debug/OptionsResolverIntrospector.php @@ -0,0 +1,102 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\OptionsResolver\Debug; + +use Symfony\Component\OptionsResolver\Exception\NoConfigurationException; +use Symfony\Component\OptionsResolver\Exception\UndefinedOptionsException; +use Symfony\Component\OptionsResolver\OptionsResolver; + +/** + * @author Maxime Steinhausser + * + * @final + */ +class OptionsResolverIntrospector +{ + private $get; + + public function __construct(OptionsResolver $optionsResolver) + { + $this->get = \Closure::bind(function ($property, $option, $message) { + /** @var OptionsResolver $this */ + if (!$this->isDefined($option)) { + throw new UndefinedOptionsException(sprintf('The option "%s" does not exist.', $option)); + } + + if (!array_key_exists($option, $this->{$property})) { + throw new NoConfigurationException($message); + } + + return $this->{$property}[$option]; + }, $optionsResolver, $optionsResolver); + } + + /** + * @param string $option + * + * @return mixed + * + * @throws NoConfigurationException on no configured value + */ + public function getDefault($option) + { + return call_user_func($this->get, 'defaults', $option, sprintf('No default value was set for the "%s" option.', $option)); + } + + /** + * @param string $option + * + * @return \Closure[] + * + * @throws NoConfigurationException on no configured closures + */ + public function getLazyClosures($option) + { + return call_user_func($this->get, 'lazy', $option, sprintf('No lazy closures were set for the "%s" option.', $option)); + } + + /** + * @param string $option + * + * @return string[] + * + * @throws NoConfigurationException on no configured types + */ + public function getAllowedTypes($option) + { + return call_user_func($this->get, 'allowedTypes', $option, sprintf('No allowed types were set for the "%s" option.', $option)); + } + + /** + * @param string $option + * + * @return mixed[] + * + * @throws NoConfigurationException on no configured values + */ + public function getAllowedValues($option) + { + return call_user_func($this->get, 'allowedValues', $option, sprintf('No allowed values were set for the "%s" option.', $option)); + } + + /** + * @param string $option + * + * @return \Closure + * + * @throws NoConfigurationException on no configured normalizer + */ + public function getNormalizer($option) + { + return call_user_func($this->get, 'normalizers', $option, sprintf('No normalizer was set for the "%s" option.', $option)); + } +} diff --git a/src/Symfony/Component/OptionsResolver/Exception/NoConfigurationException.php b/src/Symfony/Component/OptionsResolver/Exception/NoConfigurationException.php new file mode 100644 index 0000000000000..6693ec14df892 --- /dev/null +++ b/src/Symfony/Component/OptionsResolver/Exception/NoConfigurationException.php @@ -0,0 +1,26 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\OptionsResolver\Exception; + +use Symfony\Component\OptionsResolver\Debug\OptionsResolverIntrospector; + +/** + * Thrown when trying to introspect an option definition property + * for which no value was configured inside the OptionsResolver instance. + * + * @see OptionsResolverIntrospector + * + * @author Maxime Steinhausser + */ +class NoConfigurationException extends \RuntimeException implements ExceptionInterface +{ +} diff --git a/src/Symfony/Component/OptionsResolver/Tests/Debug/OptionsResolverIntrospectorTest.php b/src/Symfony/Component/OptionsResolver/Tests/Debug/OptionsResolverIntrospectorTest.php new file mode 100644 index 0000000000000..7c4753ab5f6b4 --- /dev/null +++ b/src/Symfony/Component/OptionsResolver/Tests/Debug/OptionsResolverIntrospectorTest.php @@ -0,0 +1,203 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\OptionsResolver\Tests\Debug; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\OptionsResolver\Debug\OptionsResolverIntrospector; +use Symfony\Component\OptionsResolver\Options; +use Symfony\Component\OptionsResolver\OptionsResolver; + +class OptionsResolverIntrospectorTest extends TestCase +{ + public function testGetDefault() + { + $resolver = new OptionsResolver(); + $resolver->setDefault($option = 'foo', 'bar'); + + $debug = new OptionsResolverIntrospector($resolver); + $this->assertSame('bar', $debug->getDefault($option)); + } + + public function testGetDefaultNull() + { + $resolver = new OptionsResolver(); + $resolver->setDefault($option = 'foo', null); + + $debug = new OptionsResolverIntrospector($resolver); + $this->assertNull($debug->getDefault($option)); + } + + /** + * @expectedException \Symfony\Component\OptionsResolver\Exception\NoConfigurationException + * @expectedExceptionMessage No default value was set for the "foo" option. + */ + public function testGetDefaultThrowsOnNoConfiguredValue() + { + $resolver = new OptionsResolver(); + $resolver->setDefined($option = 'foo'); + + $debug = new OptionsResolverIntrospector($resolver); + $this->assertSame('bar', $debug->getDefault($option)); + } + + /** + * @expectedException \Symfony\Component\OptionsResolver\Exception\UndefinedOptionsException + * @expectedExceptionMessage The option "foo" does not exist. + */ + public function testGetDefaultThrowsOnNotDefinedOption() + { + $resolver = new OptionsResolver(); + + $debug = new OptionsResolverIntrospector($resolver); + $this->assertSame('bar', $debug->getDefault('foo')); + } + + public function testGetLazyClosures() + { + $resolver = new OptionsResolver(); + $closures = array(); + $resolver->setDefault($option = 'foo', $closures[] = function (Options $options) {}); + + $debug = new OptionsResolverIntrospector($resolver); + $this->assertSame($closures, $debug->getLazyClosures($option)); + } + + /** + * @expectedException \Symfony\Component\OptionsResolver\Exception\NoConfigurationException + * @expectedExceptionMessage No lazy closures were set for the "foo" option. + */ + public function testGetLazyClosuresThrowsOnNoConfiguredValue() + { + $resolver = new OptionsResolver(); + $resolver->setDefined($option = 'foo'); + + $debug = new OptionsResolverIntrospector($resolver); + $this->assertSame('bar', $debug->getLazyClosures($option)); + } + + /** + * @expectedException \Symfony\Component\OptionsResolver\Exception\UndefinedOptionsException + * @expectedExceptionMessage The option "foo" does not exist. + */ + public function testGetLazyClosuresThrowsOnNotDefinedOption() + { + $resolver = new OptionsResolver(); + + $debug = new OptionsResolverIntrospector($resolver); + $this->assertSame('bar', $debug->getLazyClosures('foo')); + } + + public function testGetAllowedTypes() + { + $resolver = new OptionsResolver(); + $resolver->setDefined($option = 'foo'); + $resolver->setAllowedTypes($option = 'foo', $allowedTypes = array('string', 'bool')); + + $debug = new OptionsResolverIntrospector($resolver); + $this->assertSame($allowedTypes, $debug->getAllowedTypes($option)); + } + + /** + * @expectedException \Symfony\Component\OptionsResolver\Exception\NoConfigurationException + * @expectedExceptionMessage No allowed types were set for the "foo" option. + */ + public function testGetAllowedTypesThrowsOnNoConfiguredValue() + { + $resolver = new OptionsResolver(); + $resolver->setDefined($option = 'foo'); + + $debug = new OptionsResolverIntrospector($resolver); + $this->assertSame('bar', $debug->getAllowedTypes($option)); + } + + /** + * @expectedException \Symfony\Component\OptionsResolver\Exception\UndefinedOptionsException + * @expectedExceptionMessage The option "foo" does not exist. + */ + public function testGetAllowedTypesThrowsOnNotDefinedOption() + { + $resolver = new OptionsResolver(); + + $debug = new OptionsResolverIntrospector($resolver); + $this->assertSame('bar', $debug->getAllowedTypes('foo')); + } + + public function testGetAllowedValues() + { + $resolver = new OptionsResolver(); + $resolver->setDefined($option = 'foo'); + $resolver->setAllowedValues($option = 'foo', $allowedValues = array('bar', 'baz')); + + $debug = new OptionsResolverIntrospector($resolver); + $this->assertSame($allowedValues, $debug->getAllowedValues($option)); + } + + /** + * @expectedException \Symfony\Component\OptionsResolver\Exception\NoConfigurationException + * @expectedExceptionMessage No allowed values were set for the "foo" option. + */ + public function testGetAllowedValuesThrowsOnNoConfiguredValue() + { + $resolver = new OptionsResolver(); + $resolver->setDefined($option = 'foo'); + + $debug = new OptionsResolverIntrospector($resolver); + $this->assertSame('bar', $debug->getAllowedValues($option)); + } + + /** + * @expectedException \Symfony\Component\OptionsResolver\Exception\UndefinedOptionsException + * @expectedExceptionMessage The option "foo" does not exist. + */ + public function testGetAllowedValuesThrowsOnNotDefinedOption() + { + $resolver = new OptionsResolver(); + + $debug = new OptionsResolverIntrospector($resolver); + $this->assertSame('bar', $debug->getAllowedValues('foo')); + } + + public function testGetNormalizer() + { + $resolver = new OptionsResolver(); + $resolver->setDefined($option = 'foo'); + $resolver->setNormalizer($option = 'foo', $normalizer = function () {}); + + $debug = new OptionsResolverIntrospector($resolver); + $this->assertSame($normalizer, $debug->getNormalizer($option)); + } + + /** + * @expectedException \Symfony\Component\OptionsResolver\Exception\NoConfigurationException + * @expectedExceptionMessage No normalizer was set for the "foo" option. + */ + public function testGetNormalizerThrowsOnNoConfiguredValue() + { + $resolver = new OptionsResolver(); + $resolver->setDefined($option = 'foo'); + + $debug = new OptionsResolverIntrospector($resolver); + $this->assertSame('bar', $debug->getNormalizer($option)); + } + + /** + * @expectedException \Symfony\Component\OptionsResolver\Exception\UndefinedOptionsException + * @expectedExceptionMessage The option "foo" does not exist. + */ + public function testGetNormalizerThrowsOnNotDefinedOption() + { + $resolver = new OptionsResolver(); + + $debug = new OptionsResolverIntrospector($resolver); + $this->assertSame('bar', $debug->getNormalizer('foo')); + } +} From ed57e748dc26c5210581d205b698f1d89e05d09a Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Tue, 3 Oct 2017 15:54:22 +0200 Subject: [PATCH 0993/1099] fix version in changelog --- src/Symfony/Component/Filesystem/CHANGELOG.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/Filesystem/CHANGELOG.md b/src/Symfony/Component/Filesystem/CHANGELOG.md index ba3eff0f0d1e4..d01f5f45e1a7d 100644 --- a/src/Symfony/Component/Filesystem/CHANGELOG.md +++ b/src/Symfony/Component/Filesystem/CHANGELOG.md @@ -1,11 +1,15 @@ CHANGELOG ========= +3.4.0 +----- + + * support for passing relative paths to `Filesystem::makePathRelative()` is deprecated and will be removed in 4.0 + 3.3.0 ----- * added `appendToFile()` to append contents to existing files - * support for passing relative paths to `Filesystem::makePathRelative()` is deprecated and will be removed in 4.0 3.2.0 ----- From 5518896c2650ea678c8b70e70d62fada53de3b0d Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Tue, 3 Oct 2017 17:01:31 +0200 Subject: [PATCH 0994/1099] fix refreshing line numbers for the inline parser --- src/Symfony/Component/Yaml/Inline.php | 7 +++++-- src/Symfony/Component/Yaml/Parser.php | 5 ++--- src/Symfony/Component/Yaml/Tests/ParserTest.php | 4 ++-- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/src/Symfony/Component/Yaml/Inline.php b/src/Symfony/Component/Yaml/Inline.php index 12d99a20bfb7e..1ba3c57c59945 100644 --- a/src/Symfony/Component/Yaml/Inline.php +++ b/src/Symfony/Component/Yaml/Inline.php @@ -39,14 +39,17 @@ class Inline * @param int|null $parsedLineNumber * @param string|null $parsedFilename */ - public static function initialize($flags, $parsedLineNumber = 0, $parsedFilename = null) + public static function initialize($flags, $parsedLineNumber = null, $parsedFilename = null) { self::$exceptionOnInvalidType = (bool) (Yaml::PARSE_EXCEPTION_ON_INVALID_TYPE & $flags); self::$objectSupport = (bool) (Yaml::PARSE_OBJECT & $flags); self::$objectForMap = (bool) (Yaml::PARSE_OBJECT_FOR_MAP & $flags); self::$constantSupport = (bool) (Yaml::PARSE_CONSTANT & $flags); self::$parsedFilename = $parsedFilename; - self::$parsedLineNumber = $parsedLineNumber; + + if (null !== $parsedLineNumber) { + self::$parsedLineNumber = $parsedLineNumber; + } } /** diff --git a/src/Symfony/Component/Yaml/Parser.php b/src/Symfony/Component/Yaml/Parser.php index b81871730c95d..82391b216d709 100644 --- a/src/Symfony/Component/Yaml/Parser.php +++ b/src/Symfony/Component/Yaml/Parser.php @@ -201,6 +201,8 @@ private function doParse($value, $flags) throw new ParseException('A YAML file cannot contain tabs as indentation.', $this->getRealCurrentLineNb() + 1, $this->currentLine, $this->filename); } + Inline::initialize($flags, $this->getRealCurrentLineNb(), $this->filename); + $isRef = $mergeNode = false; if (self::preg_match('#^\-((?P\s+)(?P.+))?$#u', rtrim($this->currentLine), $values)) { if ($context && 'mapping' == $context) { @@ -252,7 +254,6 @@ private function doParse($value, $flags) } $context = 'mapping'; - Inline::initialize($flags, $this->getRealCurrentLineNb(), $this->filename); try { $i = 0; $evaluateKey = !(Yaml::PARSE_KEYS_AS_STRINGS & $flags); @@ -402,7 +403,6 @@ private function doParse($value, $flags) // 1-liner optionally followed by newline(s) if (is_string($value) && $this->lines[0] === trim($value)) { try { - Inline::$parsedLineNumber = $this->getRealCurrentLineNb(); $value = Inline::parse($this->lines[0], $flags, $this->refs); } catch (ParseException $e) { $e->setParsedLine($this->getRealCurrentLineNb() + 1); @@ -744,7 +744,6 @@ private function parseValue($value, $flags, $context) } } - Inline::$parsedLineNumber = $this->getRealCurrentLineNb(); $parsedValue = Inline::parse($value, $flags, $this->refs); if ('mapping' === $context && is_string($parsedValue) && '"' !== $value[0] && "'" !== $value[0] && '[' !== $value[0] && '{' !== $value[0] && '!' !== $value[0] && false !== strpos($parsedValue, ': ')) { diff --git a/src/Symfony/Component/Yaml/Tests/ParserTest.php b/src/Symfony/Component/Yaml/Tests/ParserTest.php index 38ee2e06051e2..868545683e57b 100644 --- a/src/Symfony/Component/Yaml/Tests/ParserTest.php +++ b/src/Symfony/Component/Yaml/Tests/ParserTest.php @@ -1853,8 +1853,8 @@ public function testPhpConstantTagMappingKey() /** * @group legacy * @expectedDeprecation The !php/const: tag to indicate dumped PHP constants is deprecated since version 3.4 and will be removed in 4.0. Use the !php/const (without the colon) tag instead on line 2. - * @expectedDeprecation The !php/const: tag to indicate dumped PHP constants is deprecated since version 3.4 and will be removed in 4.0. Use the !php/const (without the colon) tag instead on line 1. - * @expectedDeprecation The !php/const: tag to indicate dumped PHP constants is deprecated since version 3.4 and will be removed in 4.0. Use the !php/const (without the colon) tag instead on line 1. + * @expectedDeprecation The !php/const: tag to indicate dumped PHP constants is deprecated since version 3.4 and will be removed in 4.0. Use the !php/const (without the colon) tag instead on line 4. + * @expectedDeprecation The !php/const: tag to indicate dumped PHP constants is deprecated since version 3.4 and will be removed in 4.0. Use the !php/const (without the colon) tag instead on line 5. */ public function testDeprecatedPhpConstantTagMappingKey() { From 9011f47e8fcc29a07b8895c40185836b63f277b3 Mon Sep 17 00:00:00 2001 From: Roland Franssen Date: Sun, 10 Sep 2017 15:11:38 +0200 Subject: [PATCH 0995/1099] [FrameworkBundle] Expose dotenv in bin/console about --- .../Bundle/FrameworkBundle/CHANGELOG.md | 1 + .../FrameworkBundle/Command/AboutCommand.php | 42 +++++++++++++++++-- 2 files changed, 40 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md b/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md index f49eb6dbc2dd3..49fd03165a5b7 100644 --- a/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md +++ b/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md @@ -59,6 +59,7 @@ CHANGELOG and `YamlLintCommand` classes have been marked as final * Added `asset.request_context.base_path` and `asset.request_context.secure` parameters to provide a default request context in case the stack is empty (similar to `router.request_context.*` parameters) + * Display environment variables managed by `Dotenv` in `AboutCommand` 3.3.0 ----- diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/AboutCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/AboutCommand.php index 4a594d3ae70ce..3c5ba3e93d3cf 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/AboutCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/AboutCommand.php @@ -35,7 +35,19 @@ class AboutCommand extends ContainerAwareCommand */ protected function configure() { - $this->setDescription('Displays information about the current project'); + $this + ->setDescription('Displays information about the current project') + ->setHelp(<<<'EOT' +The %command.name% command displays information about the current Symfony project. + +The PHP section displays important configuration that could affect your application. The values might +be different between web and CLI. + +The Environment section displays the current environment variables managed by Symfony Dotenv. It will not +be shown if no variables were found. The values might be different between web and CLI. +EOT + ) + ; } /** @@ -48,7 +60,7 @@ protected function execute(InputInterface $input, OutputInterface $output) /** @var $kernel KernelInterface */ $kernel = $this->getApplication()->getKernel(); - $io->table(array(), array( + $rows = array( array('Symfony'), new TableSeparator(), array('Version', Kernel::VERSION), @@ -75,7 +87,19 @@ protected function execute(InputInterface $input, OutputInterface $output) array('OPcache', extension_loaded('Zend OPcache') && ini_get('opcache.enable') ? 'true' : 'false'), array('APCu', extension_loaded('apcu') && ini_get('apc.enabled') ? 'true' : 'false'), array('Xdebug', extension_loaded('xdebug') ? 'true' : 'false'), - )); + ); + + if ($dotenv = self::getDotEnvVars()) { + $rows = array_merge($rows, array( + new TableSeparator(), + array('Environment (.env)'), + new TableSeparator(), + ), array_map(function ($value, $name) { + return array($name, $value); + }, $dotenv, array_keys($dotenv))); + } + + $io->table(array(), $rows); } private static function formatPath($path, $baseDir = null) @@ -103,4 +127,16 @@ private static function isExpired($date) return false !== $date && new \DateTime() > $date->modify('last day of this month 23:59:59'); } + + private static function getDotEnvVars() + { + $vars = array(); + foreach (explode(',', getenv('SYMFONY_DOTENV_VARS')) as $name) { + if ('' !== $name && false !== $value = getenv($name)) { + $vars[$name] = $value; + } + } + + return $vars; + } } From 80af9b8562ca87a1a0a05ccb3179c2888e90e4a2 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Tue, 3 Oct 2017 17:15:12 +0200 Subject: [PATCH 0996/1099] treat trailing backslashes in multi-line strings --- src/Symfony/Component/Yaml/Parser.php | 21 +++++++++++++++---- .../Component/Yaml/Tests/ParserTest.php | 11 ++++++++++ 2 files changed, 28 insertions(+), 4 deletions(-) diff --git a/src/Symfony/Component/Yaml/Parser.php b/src/Symfony/Component/Yaml/Parser.php index 611bbac3ae1ba..7d40c0597fd56 100644 --- a/src/Symfony/Component/Yaml/Parser.php +++ b/src/Symfony/Component/Yaml/Parser.php @@ -384,6 +384,7 @@ private function doParse($value, $flags) if (0 === $this->currentLineNb) { $parseError = false; $previousLineWasNewline = false; + $previousLineWasTerminatedWithBackslash = false; $value = ''; foreach ($this->lines as $line) { @@ -401,13 +402,25 @@ private function doParse($value, $flags) if ('' === trim($parsedLine)) { $value .= "\n"; - $previousLineWasNewline = true; - } elseif ($previousLineWasNewline) { + } elseif (!$previousLineWasNewline && !$previousLineWasTerminatedWithBackslash) { + $value .= ' '; + } + + if ('' !== trim($parsedLine) && '\\' === substr($parsedLine, -1)) { + $value .= ltrim(substr($parsedLine, 0, -1)); + } elseif ('' !== trim($parsedLine)) { $value .= trim($parsedLine); + } + + if ('' === trim($parsedLine)) { + $previousLineWasNewline = true; + $previousLineWasTerminatedWithBackslash = false; + } elseif ('\\' === substr($parsedLine, -1)) { $previousLineWasNewline = false; + $previousLineWasTerminatedWithBackslash = true; } else { - $value .= ' '.trim($parsedLine); $previousLineWasNewline = false; + $previousLineWasTerminatedWithBackslash = false; } } catch (ParseException $e) { $parseError = true; @@ -416,7 +429,7 @@ private function doParse($value, $flags) } if (!$parseError) { - return trim($value); + return Inline::parse(trim($value)); } } diff --git a/src/Symfony/Component/Yaml/Tests/ParserTest.php b/src/Symfony/Component/Yaml/Tests/ParserTest.php index 4c62f9bd172ef..67ed642084711 100644 --- a/src/Symfony/Component/Yaml/Tests/ParserTest.php +++ b/src/Symfony/Component/Yaml/Tests/ParserTest.php @@ -1543,6 +1543,17 @@ public function testParseMultiLineQuotedString() $this->assertSame(array('foo' => 'bar baz foobar foo', 'bar' => 'baz'), $this->parser->parse($yaml)); } + public function testMultiLineQuotedStringWithTrailingBackslash() + { + $yaml = <<assertSame(array('foobar' => 'foobar'), $this->parser->parse($yaml)); + } + public function testParseMultiLineUnquotedString() { $yaml = << Date: Wed, 4 Oct 2017 00:12:02 +0200 Subject: [PATCH 0997/1099] [Yaml] parse references on merge keys --- src/Symfony/Component/Yaml/Parser.php | 16 +++++++---- .../Component/Yaml/Tests/ParserTest.php | 28 +++++++++++++++++++ 2 files changed, 38 insertions(+), 6 deletions(-) diff --git a/src/Symfony/Component/Yaml/Parser.php b/src/Symfony/Component/Yaml/Parser.php index 94eafb5d0ae5c..6817e71ea8667 100644 --- a/src/Symfony/Component/Yaml/Parser.php +++ b/src/Symfony/Component/Yaml/Parser.php @@ -181,7 +181,7 @@ private function doParse($value, $exceptionOnInvalidType = false, $objectSupport $key = (string) $key; } - if ('<<' === $key) { + if ('<<' === $key && (!isset($values['value']) || !self::preg_match('#^&(?P[^ ]+)#u', $values['value'], $refMatches))) { $mergeNode = true; $allowOverwrite = true; if (isset($values['value']) && 0 === strpos($values['value'], '*')) { @@ -226,14 +226,14 @@ private function doParse($value, $exceptionOnInvalidType = false, $objectSupport $data += $parsed; // array union } } - } elseif (isset($values['value']) && self::preg_match('#^&(?P[^ ]+) *(?P.*)#u', $values['value'], $matches)) { + } elseif ('<<' !== $key && isset($values['value']) && self::preg_match('#^&(?P[^ ]+) *(?P.*)#u', $values['value'], $matches)) { $isRef = $matches['ref']; $values['value'] = $matches['value']; } if ($mergeNode) { // Merge keys - } elseif (!isset($values['value']) || '' == trim($values['value'], ' ') || 0 === strpos(ltrim($values['value'], ' '), '#')) { + } elseif (!isset($values['value']) || '' == trim($values['value'], ' ') || 0 === strpos(ltrim($values['value'], ' '), '#') || '<<' === $key) { // hash // if next line is less indented or equal, then it means that the current value is null if (!$this->isNextLineIndented() && !$this->isNextLineUnIndentedCollection()) { @@ -244,9 +244,13 @@ private function doParse($value, $exceptionOnInvalidType = false, $objectSupport } } else { $value = $this->parseBlock($this->getRealCurrentLineNb() + 1, $this->getNextEmbedBlock(), $exceptionOnInvalidType, $objectSupport, $objectForMap); - // Spec: Keys MUST be unique; first one wins. - // But overwriting is allowed when a merge node is used in current block. - if ($allowOverwrite || !isset($data[$key])) { + + if ('<<' === $key) { + $this->refs[$refMatches['ref']] = $value; + $data += $value; + } elseif ($allowOverwrite || !isset($data[$key])) { + // Spec: Keys MUST be unique; first one wins. + // But overwriting is allowed when a merge node is used in current block. $data[$key] = $value; } } diff --git a/src/Symfony/Component/Yaml/Tests/ParserTest.php b/src/Symfony/Component/Yaml/Tests/ParserTest.php index 1ff5e3e8a5042..9be278f67ec92 100644 --- a/src/Symfony/Component/Yaml/Tests/ParserTest.php +++ b/src/Symfony/Component/Yaml/Tests/ParserTest.php @@ -1179,6 +1179,34 @@ public function testParserCleansUpReferencesBetweenRuns() YAML; $this->parser->parse($yaml); } + + public function testParseReferencesOnMergeKeys() + { + $yaml = << array( + 'a' => 'foo', + 'b' => 'bar', + 'c' => 'baz', + ), + 'mergekeyderef' => array( + 'd' => 'quux', + 'b' => 'bar', + 'c' => 'baz', + ), + ); + + $this->assertSame($expected, $this->parser->parse($yaml)); + } } class B From d314b1ff628295ef085f93463bfcc125fd65e6b3 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Wed, 4 Oct 2017 09:45:46 +0200 Subject: [PATCH 0998/1099] [DI] Allow setting any public non-initialized services --- .../DependencyInjection/Container.php | 7 ++++--- .../Tests/ContainerTest.php | 20 ++++++++++++++++--- .../Tests/Dumper/PhpDumperTest.php | 9 ++++++--- 3 files changed, 27 insertions(+), 9 deletions(-) diff --git a/src/Symfony/Component/DependencyInjection/Container.php b/src/Symfony/Component/DependencyInjection/Container.php index 6eceb0defeba9..2d43ba7a60290 100644 --- a/src/Symfony/Component/DependencyInjection/Container.php +++ b/src/Symfony/Component/DependencyInjection/Container.php @@ -190,6 +190,7 @@ public function set($id, $service) unset($this->aliases[$id]); } + $wasSet = isset($this->services[$id]); $this->services[$id] = $service; if (null === $service) { @@ -203,11 +204,11 @@ public function set($id, $service) } else { @trigger_error(sprintf('Setting the "%s" private service is deprecated since Symfony 3.2 and won\'t be supported anymore in Symfony 4.0.', $id), E_USER_DEPRECATED); } - } elseif (isset($this->methodMap[$id])) { + } elseif ($wasSet && isset($this->methodMap[$id])) { if (null === $service) { - @trigger_error(sprintf('Unsetting the "%s" pre-defined service is deprecated since Symfony 3.3 and won\'t be supported anymore in Symfony 4.0.', $id), E_USER_DEPRECATED); + @trigger_error(sprintf('Unsetting the "%s" service after it\'s been initialized is deprecated since Symfony 3.3 and won\'t be supported anymore in Symfony 4.0.', $id), E_USER_DEPRECATED); } else { - @trigger_error(sprintf('Setting the "%s" pre-defined service is deprecated since Symfony 3.3 and won\'t be supported anymore in Symfony 4.0.', $id), E_USER_DEPRECATED); + @trigger_error(sprintf('Setting the "%s" service after it\'s been initialized is deprecated since Symfony 3.3 and won\'t be supported anymore in Symfony 4.0.', $id), E_USER_DEPRECATED); } } } diff --git a/src/Symfony/Component/DependencyInjection/Tests/ContainerTest.php b/src/Symfony/Component/DependencyInjection/Tests/ContainerTest.php index e2478ea22b3b4..5cd988714ad75 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/ContainerTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/ContainerTest.php @@ -186,15 +186,29 @@ public function testSetReplacesAlias() /** * @group legacy - * @expectedDeprecation Unsetting the "bar" pre-defined service is deprecated since Symfony 3.3 and won't be supported anymore in Symfony 4.0. + * @expectedDeprecation Unsetting the "bar" service after it's been initialized is deprecated since Symfony 3.3 and won't be supported anymore in Symfony 4.0. */ - public function testSetWithNullResetPredefinedService() + public function testSetWithNullOnInitializedPredefinedService() { $sc = new Container(); $sc->set('foo', new \stdClass()); $sc->set('foo', null); $this->assertFalse($sc->has('foo'), '->set() with null service resets the service'); + $sc = new ProjectServiceContainer(); + $sc->get('bar'); + $sc->set('bar', null); + $this->assertTrue($sc->has('bar'), '->set() with null service resets the pre-defined service'); + } + + public function testSetWithNullOnUninitializedPredefinedService() + { + $sc = new Container(); + $sc->set('foo', new \stdClass()); + $sc->get('foo', null); + $sc->set('foo', null); + $this->assertFalse($sc->has('foo'), '->set() with null service resets the service'); + $sc = new ProjectServiceContainer(); $sc->set('bar', null); $this->assertTrue($sc->has('bar'), '->set() with null service resets the pre-defined service'); @@ -481,7 +495,7 @@ public function testRequestAnInternalSharedPrivateServiceIsDeprecated() /** * @group legacy - * @expectedDeprecation Setting the "bar" pre-defined service is deprecated since Symfony 3.3 and won't be supported anymore in Symfony 4.0. + * @expectedDeprecation Setting the "bar" service after it's been initialized is deprecated since Symfony 3.3 and won't be supported anymore in Symfony 4.0. */ public function testReplacingAPreDefinedServiceIsDeprecated() { diff --git a/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php b/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php index a1422bf96a29c..d832a220c7afc 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php @@ -269,7 +269,7 @@ public function testFrozenContainerWithoutAliases() /** * @group legacy - * @expectedDeprecation Setting the "bar" pre-defined service is deprecated since Symfony 3.3 and won't be supported anymore in Symfony 4.0. + * @expectedDeprecation Setting the "bar" service after it's been initialized is deprecated since Symfony 3.3 and won't be supported anymore in Symfony 4.0. */ public function testOverrideServiceWhenUsingADumpedContainer() { @@ -277,15 +277,16 @@ public function testOverrideServiceWhenUsingADumpedContainer() require_once self::$fixturesPath.'/includes/foo.php'; $container = new \ProjectServiceContainer(); - $container->set('bar', $bar = new \stdClass()); $container->setParameter('foo_bar', 'foo_bar'); + $container->get('bar'); + $container->set('bar', $bar = new \stdClass()); $this->assertSame($bar, $container->get('bar'), '->set() overrides an already defined service'); } /** * @group legacy - * @expectedDeprecation Setting the "bar" pre-defined service is deprecated since Symfony 3.3 and won't be supported anymore in Symfony 4.0. + * @expectedDeprecation Setting the "bar" service after it's been initialized is deprecated since Symfony 3.3 and won't be supported anymore in Symfony 4.0. */ public function testOverrideServiceWhenUsingADumpedContainerAndServiceIsUsedFromAnotherOne() { @@ -294,6 +295,8 @@ public function testOverrideServiceWhenUsingADumpedContainerAndServiceIsUsedFrom require_once self::$fixturesPath.'/includes/classes.php'; $container = new \ProjectServiceContainer(); + $container->setParameter('foo_bar', 'foo_bar'); + $container->get('bar'); $container->set('bar', $bar = new \stdClass()); $this->assertSame($bar, $container->get('foo')->bar, '->set() overrides an already defined service'); From fa24fa8a3cb97aaa1baae0cd5efc0eb20c8fd93f Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Wed, 4 Oct 2017 09:58:49 +0200 Subject: [PATCH 0999/1099] [Cache] Fix race condition in TagAwareAdapter --- .../Component/Cache/Adapter/TagAwareAdapter.php | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/src/Symfony/Component/Cache/Adapter/TagAwareAdapter.php b/src/Symfony/Component/Cache/Adapter/TagAwareAdapter.php index 1e0617ebe271d..d8ea34603823f 100644 --- a/src/Symfony/Component/Cache/Adapter/TagAwareAdapter.php +++ b/src/Symfony/Component/Cache/Adapter/TagAwareAdapter.php @@ -250,19 +250,12 @@ public function commit() $f = $this->getTagsByKey; $tagsByKey = $f($items); - $deletedTags = $this->deferred = array(); + $this->deferred = array(); $tagVersions = $this->getTagVersions($tagsByKey); $f = $this->createCacheItem; foreach ($tagsByKey as $key => $tags) { - if ($tags) { - $this->itemsAdapter->saveDeferred($f(static::TAGS_PREFIX.$key, array_intersect_key($tagVersions, $tags), $items[$key])); - } else { - $deletedTags[] = static::TAGS_PREFIX.$key; - } - } - if ($deletedTags) { - $this->itemsAdapter->deleteItems($deletedTags); + $this->itemsAdapter->saveDeferred($f(static::TAGS_PREFIX.$key, array_intersect_key($tagVersions, $tags), $items[$key])); } } From a7a6f8a6788019183508afc89a597d12926242ef Mon Sep 17 00:00:00 2001 From: Amaury Leroux de Lens Date: Fri, 4 Dec 2015 13:21:25 +0100 Subject: [PATCH 1000/1099] [Security] Add Guard authenticator method This method will be called before starting an authentication against a guard authhenticator. The authentication will be tried only if the supports method returned This improves understanding of code, increase consistency and removes responsability for method To decide if the current request should be supported or not. --- UPGRADE-3.4.md | 3 + UPGRADE-4.0.md | 3 + .../Guard/AbstractGuardAuthenticator.php | 19 +- .../Security/Guard/AuthenticatorInterface.php | 170 +++++++++++++++++ .../Firewall/GuardAuthenticationListener.php | 54 ++++-- .../Guard/GuardAuthenticatorHandler.php | 30 +-- .../Guard/GuardAuthenticatorInterface.php | 5 +- .../Provider/GuardAuthenticationProvider.php | 18 +- .../GuardAuthenticationListenerTest.php | 176 +++++++++++++++++- .../Tests/GuardAuthenticatorHandlerTest.php | 2 +- .../Token/PreAuthenticationGuardToken.php | 2 +- 11 files changed, 435 insertions(+), 47 deletions(-) create mode 100644 src/Symfony/Component/Security/Guard/AuthenticatorInterface.php diff --git a/UPGRADE-3.4.md b/UPGRADE-3.4.md index e5b6434c37f4e..3996618fc18ff 100644 --- a/UPGRADE-3.4.md +++ b/UPGRADE-3.4.md @@ -302,6 +302,9 @@ SecurityBundle * Using voters that do not implement the `VoterInterface`is now deprecated in the `AccessDecisionManager` and this functionality will be removed in 4.0. + * Using guard authenticator that implement the `GuardAuthenticatorInterface` is now + deprecated, this will be removed in 4.0. `AuthenticatorInterface` must be used now. + * `FirewallContext::getListeners()` now returns `\Traversable|array` * `InitAclCommand::__construct()` now takes an instance of diff --git a/UPGRADE-4.0.md b/UPGRADE-4.0.md index 2d2e04899c18b..a9a382b8e9d14 100644 --- a/UPGRADE-4.0.md +++ b/UPGRADE-4.0.md @@ -659,6 +659,9 @@ Security * The `RoleInterface` has been removed. Extend the `Symfony\Component\Security\Core\Role\Role` class instead. + * The `GuardAuthenticatorInterface` has been removed. Implement + `Symfony\Component\Security\Guard\AuthenticatorInterface` class instead. + * The `LogoutUrlGenerator::registerListener()` method expects a 6th `string $context = null` argument. * The `AccessDecisionManager::setVoters()` method has been removed. Pass the diff --git a/src/Symfony/Component/Security/Guard/AbstractGuardAuthenticator.php b/src/Symfony/Component/Security/Guard/AbstractGuardAuthenticator.php index 609d772e194b4..97c9c4a0922d9 100644 --- a/src/Symfony/Component/Security/Guard/AbstractGuardAuthenticator.php +++ b/src/Symfony/Component/Security/Guard/AbstractGuardAuthenticator.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Security\Guard; +use Symfony\Component\HttpFoundation\Request; use Symfony\Component\Security\Core\User\UserInterface; use Symfony\Component\Security\Guard\Token\PostAuthenticationGuardToken; @@ -19,8 +20,24 @@ * * @author Ryan Weaver */ -abstract class AbstractGuardAuthenticator implements GuardAuthenticatorInterface +abstract class AbstractGuardAuthenticator implements AuthenticatorInterface { + /** + * Default implementation of the AuthenticatorInterface::supports method + * As we still have the deprecated GuardAuthenticatorInterface, this method must be implemented here + * Once GuardAuthenticatorInterface will be removed, this method should be removed too. + * + * @param Request $request + * + * @return bool + */ + public function supports(Request $request) + { + @trigger_error('The Symfony\Component\Security\Guard\AbstractGuardAuthenticator::supports default implementation is used. This is provided for backward compatibility on GuardAuthenticationInterface that is deprecated since version 3.1 and will be removed in 4.0. Provide your own implementation of the supports method instead.', E_USER_DEPRECATED); + + return true; + } + /** * Shortcut to create a PostAuthenticationGuardToken for you, if you don't really * care about which authenticated token you're using. diff --git a/src/Symfony/Component/Security/Guard/AuthenticatorInterface.php b/src/Symfony/Component/Security/Guard/AuthenticatorInterface.php new file mode 100644 index 0000000000000..a1497b0eef4f9 --- /dev/null +++ b/src/Symfony/Component/Security/Guard/AuthenticatorInterface.php @@ -0,0 +1,170 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Security\Guard; + +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; +use Symfony\Component\Security\Core\Exception\AuthenticationException; +use Symfony\Component\Security\Core\User\UserInterface; +use Symfony\Component\Security\Core\User\UserProviderInterface; +use Symfony\Component\Security\Guard\Token\GuardTokenInterface; +use Symfony\Component\Security\Http\EntryPoint\AuthenticationEntryPointInterface; + +/** + * The interface for all "guard" authenticators. + * + * The methods on this interface are called throughout the guard authentication + * process to give you the power to control most parts of the process from + * one location. + * + * @author Ryan Weaver + * @author Amaury Leroux de Lens + */ +interface AuthenticatorInterface extends AuthenticationEntryPointInterface +{ + /** + * Does the authenticator support the given Request ? + * + * If this returns true, authentication will continue (e.g. getCredentials() will be called). + * If false, this authenticator is done. The next (if any) authenticators will be called and + * may authenticate the user, or leave the user as anonymous. + * + * @param Request $request + * + * @return bool + */ + public function supports(Request $request); + + /** + * Get the authentication credentials from the request and return them + * as any type (e.g. an associate array). If you return null, authentication + * will be skipped. + * + * Whatever value you return here will be passed to getUser() and checkCredentials() + * + * For example, for a form login, you might: + * + * return array( + * 'username' => $request->request->get('_username'), + * 'password' => $request->request->get('_password'), + * ); + * + * Or for an API token that's on a header, you might use: + * + * return array('api_key' => $request->headers->get('X-API-TOKEN')); + * + * @param Request $request + * + * @return mixed|null + */ + public function getCredentials(Request $request); + + /** + * Return a UserInterface object based on the credentials. + * + * The *credentials* are the return value from getCredentials() + * + * You may throw an AuthenticationException if you wish. If you return + * null, then a UsernameNotFoundException is thrown for you. + * + * @param mixed $credentials + * @param UserProviderInterface $userProvider + * + * @throws AuthenticationException + * + * @return UserInterface|null + */ + public function getUser($credentials, UserProviderInterface $userProvider); + + /** + * Returns true if the credentials are valid. + * + * If any value other than true is returned, authentication will + * fail. You may also throw an AuthenticationException if you wish + * to cause authentication to fail. + * + * The *credentials* are the return value from getCredentials() + * + * @param mixed $credentials + * @param UserInterface $user + * + * @return bool + * + * @throws AuthenticationException + */ + public function checkCredentials($credentials, UserInterface $user); + + /** + * Creates an authenticated token for the given user. + * + * If you don't care about which token class is used or don't really + * understand what a "token" is, you can skip this method by extending + * the AbstractGuardAuthenticator class from your authenticator. + * + * @see AbstractGuardAuthenticator + * + * @param UserInterface $user + * @param string $providerKey The provider (i.e. firewall) key + * + * @return GuardTokenInterface + */ + 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. + * + * If you return null, the request will continue, but the user will + * not be authenticated. This is probably not what you want to do. + * + * @param Request $request + * @param AuthenticationException $exception + * + * @return Response|null + */ + public function onAuthenticationFailure(Request $request, AuthenticationException $exception); + + /** + * Called when authentication executed and was successful! + * + * This should return the Response sent back to the user, like a + * RedirectResponse to the last page they visited. + * + * If you return null, the current request will continue, and the user + * will be authenticated. This makes sense, for example, with an API. + * + * @param Request $request + * @param TokenInterface $token + * @param string $providerKey The provider (i.e. firewall) key + * + * @return Response|null + */ + public function onAuthenticationSuccess(Request $request, TokenInterface $token, $providerKey); + + /** + * Does this method support remember me cookies? + * + * Remember me cookie will be set if *all* of the following are met: + * A) This method returns true + * B) The remember_me key under your firewall is configured + * C) The "remember me" functionality is activated. This is usually + * done by having a _remember_me checkbox in your form, but + * can be configured by the "always_remember_me" and "remember_me_parameter" + * parameters under the "remember_me" firewall key + * + * @return bool + */ + public function supportsRememberMe(); +} diff --git a/src/Symfony/Component/Security/Guard/Firewall/GuardAuthenticationListener.php b/src/Symfony/Component/Security/Guard/Firewall/GuardAuthenticationListener.php index 41a37e6fef55b..dd5ae2c16b9f4 100644 --- a/src/Symfony/Component/Security/Guard/Firewall/GuardAuthenticationListener.php +++ b/src/Symfony/Component/Security/Guard/Firewall/GuardAuthenticationListener.php @@ -18,6 +18,7 @@ use Symfony\Component\Security\Guard\Token\PreAuthenticationGuardToken; use Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface; use Symfony\Component\Security\Guard\GuardAuthenticatorInterface; +use Symfony\Component\Security\Guard\AuthenticatorInterface; use Psr\Log\LoggerInterface; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; use Symfony\Component\Security\Core\Exception\AuthenticationException; @@ -28,6 +29,7 @@ * Authentication listener for the "guard" system. * * @author Ryan Weaver + * @author Amaury Leroux de Lens */ class GuardAuthenticationListener implements ListenerInterface { @@ -39,11 +41,11 @@ class GuardAuthenticationListener implements ListenerInterface private $rememberMeServices; /** - * @param GuardAuthenticatorHandler $guardHandler The Guard handler - * @param AuthenticationManagerInterface $authenticationManager An AuthenticationManagerInterface instance - * @param string $providerKey The provider (i.e. firewall) key - * @param iterable|GuardAuthenticatorInterface[] $guardAuthenticators The authenticators, with keys that match what's passed to GuardAuthenticationProvider - * @param LoggerInterface $logger A LoggerInterface instance + * @param GuardAuthenticatorHandler $guardHandler The Guard handler + * @param AuthenticationManagerInterface $authenticationManager An AuthenticationManagerInterface instance + * @param string $providerKey The provider (i.e. firewall) key + * @param iterable|AuthenticatorInterface[] $guardAuthenticators The authenticators, with keys that match what's passed to GuardAuthenticationProvider + * @param LoggerInterface $logger A LoggerInterface instance */ public function __construct(GuardAuthenticatorHandler $guardHandler, AuthenticationManagerInterface $authenticationManager, $providerKey, $guardAuthenticators, LoggerInterface $logger = null) { @@ -92,7 +94,7 @@ public function handle(GetResponseEvent $event) } } - private function executeGuardAuthenticator($uniqueGuardKey, GuardAuthenticatorInterface $guardAuthenticator, GetResponseEvent $event) + private function executeGuardAuthenticator($uniqueGuardKey, AuthenticatorInterface $guardAuthenticator, GetResponseEvent $event) { $request = $event->getRequest(); try { @@ -100,12 +102,38 @@ private function executeGuardAuthenticator($uniqueGuardKey, GuardAuthenticatorIn $this->logger->debug('Calling getCredentials() on guard configurator.', array('firewall_key' => $this->providerKey, 'authenticator' => get_class($guardAuthenticator))); } + // abort the execution of the authenticator if it doesn't support the request. + if ($guardAuthenticator instanceof GuardAuthenticatorInterface) { + // it's a GuardAuthenticatorInterface + // we support the previous behaviour to avoid BC break. + $credentialsCanBeNull = true; + @trigger_error('The Symfony\Component\Security\Guard\GuardAuthenticatorInterface interface is deprecated since version 3.1 and will be removed in 4.0. Use Symfony\Component\Security\Guard\Authenticator\GuardAuthenticatorInterface instead.', E_USER_DEPRECATED); + } else { + if (true !== $guardAuthenticator->supports($request)) { + return; + } + // as there was a support for given request, + // authenticator is expected to give not-null credentials. + $credentialsCanBeNull = false; + } + // allow the authenticator to fetch authentication info from the request $credentials = $guardAuthenticator->getCredentials($request); - // allow null to be returned to skip authentication if (null === $credentials) { - return; + // if GuardAuthenticatorInterface is used + // allow null to skip authentication. + if ($credentialsCanBeNull) { + return; + } + + // otherwise something went wrong and the authentication must fail + throw new \UnexpectedValueException(sprintf( + 'You must return some credentials from %s:getCredentials(). + To skip authentication, return false from %s::supports().', + get_class($guardAuthenticator), + get_class($guardAuthenticator) + )); } // create a token with the unique key, so that the provider knows which authenticator to use @@ -172,12 +200,12 @@ public function setRememberMeServices(RememberMeServicesInterface $rememberMeSer * Checks to see if remember me is supported in the authenticator and * on the firewall. If it is, the RememberMeServicesInterface is notified. * - * @param GuardAuthenticatorInterface $guardAuthenticator - * @param Request $request - * @param TokenInterface $token - * @param Response $response + * @param AuthenticatorInterface $guardAuthenticator + * @param Request $request + * @param TokenInterface $token + * @param Response $response */ - private function triggerRememberMe(GuardAuthenticatorInterface $guardAuthenticator, Request $request, TokenInterface $token, Response $response = null) + private function triggerRememberMe(AuthenticatorInterface $guardAuthenticator, Request $request, TokenInterface $token, Response $response = null) { if (null === $this->rememberMeServices) { if (null !== $this->logger) { diff --git a/src/Symfony/Component/Security/Guard/GuardAuthenticatorHandler.php b/src/Symfony/Component/Security/Guard/GuardAuthenticatorHandler.php index 5e1351dcc25ee..c8fb6e394e992 100644 --- a/src/Symfony/Component/Security/Guard/GuardAuthenticatorHandler.php +++ b/src/Symfony/Component/Security/Guard/GuardAuthenticatorHandler.php @@ -61,14 +61,14 @@ public function authenticateWithToken(TokenInterface $token, Request $request) /** * Returns the "on success" response for the given GuardAuthenticator. * - * @param TokenInterface $token - * @param Request $request - * @param GuardAuthenticatorInterface $guardAuthenticator - * @param string $providerKey The provider (i.e. firewall) key + * @param TokenInterface $token + * @param Request $request + * @param AuthenticatorInterface $guardAuthenticator + * @param string $providerKey The provider (i.e. firewall) key * * @return null|Response */ - public function handleAuthenticationSuccess(TokenInterface $token, Request $request, GuardAuthenticatorInterface $guardAuthenticator, $providerKey) + public function handleAuthenticationSuccess(TokenInterface $token, Request $request, AuthenticatorInterface $guardAuthenticator, $providerKey) { $response = $guardAuthenticator->onAuthenticationSuccess($request, $token, $providerKey); @@ -88,14 +88,14 @@ public function handleAuthenticationSuccess(TokenInterface $token, Request $requ * Convenience method for authenticating the user and returning the * Response *if any* for success. * - * @param UserInterface $user - * @param Request $request - * @param GuardAuthenticatorInterface $authenticator - * @param string $providerKey The provider (i.e. firewall) key + * @param UserInterface $user + * @param Request $request + * @param AuthenticatorInterface $authenticator + * @param string $providerKey The provider (i.e. firewall) key * * @return Response|null */ - public function authenticateUserAndHandleSuccess(UserInterface $user, Request $request, GuardAuthenticatorInterface $authenticator, $providerKey) + public function authenticateUserAndHandleSuccess(UserInterface $user, Request $request, AuthenticatorInterface $authenticator, $providerKey) { // create an authenticated token for the User $token = $authenticator->createAuthenticatedToken($user, $providerKey); @@ -110,14 +110,14 @@ public function authenticateUserAndHandleSuccess(UserInterface $user, Request $r * Handles an authentication failure and returns the Response for the * GuardAuthenticator. * - * @param AuthenticationException $authenticationException - * @param Request $request - * @param GuardAuthenticatorInterface $guardAuthenticator - * @param string $providerKey The key of the firewall + * @param AuthenticationException $authenticationException + * @param Request $request + * @param AuthenticatorInterface $guardAuthenticator + * @param string $providerKey The key of the firewall * * @return null|Response */ - public function handleAuthenticationFailure(AuthenticationException $authenticationException, Request $request, GuardAuthenticatorInterface $guardAuthenticator, $providerKey) + public function handleAuthenticationFailure(AuthenticationException $authenticationException, Request $request, AuthenticatorInterface $guardAuthenticator, $providerKey) { $token = $this->tokenStorage->getToken(); if ($token instanceof PostAuthenticationGuardToken && $providerKey === $token->getProviderKey()) { diff --git a/src/Symfony/Component/Security/Guard/GuardAuthenticatorInterface.php b/src/Symfony/Component/Security/Guard/GuardAuthenticatorInterface.php index 307d70f9e973e..2078ad237b9e2 100644 --- a/src/Symfony/Component/Security/Guard/GuardAuthenticatorInterface.php +++ b/src/Symfony/Component/Security/Guard/GuardAuthenticatorInterface.php @@ -18,7 +18,6 @@ use Symfony\Component\Security\Core\User\UserInterface; use Symfony\Component\Security\Core\User\UserProviderInterface; use Symfony\Component\Security\Guard\Token\GuardTokenInterface; -use Symfony\Component\Security\Http\EntryPoint\AuthenticationEntryPointInterface; /** * The interface for all "guard" authenticators. @@ -28,8 +27,10 @@ * one location. * * @author Ryan Weaver + * + * @deprecated Symfony\Component\Security\Guard\AuthenticatorInterface must be used instead */ -interface GuardAuthenticatorInterface extends AuthenticationEntryPointInterface +interface GuardAuthenticatorInterface extends AuthenticatorInterface { /** * Get the authentication credentials from the request and return them diff --git a/src/Symfony/Component/Security/Guard/Provider/GuardAuthenticationProvider.php b/src/Symfony/Component/Security/Guard/Provider/GuardAuthenticationProvider.php index 90b9580a3a876..c93776a34857d 100644 --- a/src/Symfony/Component/Security/Guard/Provider/GuardAuthenticationProvider.php +++ b/src/Symfony/Component/Security/Guard/Provider/GuardAuthenticationProvider.php @@ -14,7 +14,7 @@ use Symfony\Component\Security\Core\Authentication\Provider\AuthenticationProviderInterface; use Symfony\Component\Security\Core\Exception\BadCredentialsException; use Symfony\Component\Security\Core\Exception\UsernameNotFoundException; -use Symfony\Component\Security\Guard\GuardAuthenticatorInterface; +use Symfony\Component\Security\Guard\AuthenticatorInterface; use Symfony\Component\Security\Guard\Token\GuardTokenInterface; use Symfony\Component\Security\Guard\Token\PreAuthenticationGuardToken; use Symfony\Component\Security\Core\User\UserCheckerInterface; @@ -32,7 +32,7 @@ class GuardAuthenticationProvider implements AuthenticationProviderInterface { /** - * @var GuardAuthenticatorInterface[] + * @var AuthenticatorInterface[] */ private $guardAuthenticators; private $userProvider; @@ -40,10 +40,10 @@ class GuardAuthenticationProvider implements AuthenticationProviderInterface private $userChecker; /** - * @param iterable|GuardAuthenticatorInterface[] $guardAuthenticators The authenticators, with keys that match what's passed to GuardAuthenticationListener - * @param UserProviderInterface $userProvider The user provider - * @param string $providerKey The provider (i.e. firewall) key - * @param UserCheckerInterface $userChecker + * @param iterable|AuthenticatorInterface[] $guardAuthenticators The authenticators, with keys that match what's passed to GuardAuthenticationListener + * @param UserProviderInterface $userProvider The user provider + * @param string $providerKey The provider (i.e. firewall) key + * @param UserCheckerInterface $userChecker */ public function __construct($guardAuthenticators, UserProviderInterface $userProvider, $providerKey, UserCheckerInterface $userChecker) { @@ -56,7 +56,7 @@ public function __construct($guardAuthenticators, UserProviderInterface $userPro /** * Finds the correct authenticator for the token and calls it. * - * @param GuardTokenInterface $token + * @param TokenInterface|GuardTokenInterface $token * * @return TokenInterface */ @@ -101,7 +101,7 @@ public function authenticate(TokenInterface $token) // instances that will be checked if you have multiple firewalls. } - private function authenticateViaGuard(GuardAuthenticatorInterface $guardAuthenticator, PreAuthenticationGuardToken $token) + private function authenticateViaGuard(AuthenticatorInterface $guardAuthenticator, PreAuthenticationGuardToken $token) { // get the user from the GuardAuthenticator $user = $guardAuthenticator->getUser($token->getCredentials(), $this->userProvider); @@ -142,6 +142,6 @@ private function authenticateViaGuard(GuardAuthenticatorInterface $guardAuthenti public function supports(TokenInterface $token) { - return $token instanceof GuardTokenInterface; + return $token instanceof TokenInterface; } } diff --git a/src/Symfony/Component/Security/Guard/Tests/Firewall/GuardAuthenticationListenerTest.php b/src/Symfony/Component/Security/Guard/Tests/Firewall/GuardAuthenticationListenerTest.php index 943ca49247574..60f703904cffd 100644 --- a/src/Symfony/Component/Security/Guard/Tests/Firewall/GuardAuthenticationListenerTest.php +++ b/src/Symfony/Component/Security/Guard/Tests/Firewall/GuardAuthenticationListenerTest.php @@ -20,6 +20,7 @@ /** * @author Ryan Weaver + * @author Amaury Leroux de Lens */ class GuardAuthenticationListenerTest extends TestCase { @@ -32,11 +33,16 @@ class GuardAuthenticationListenerTest extends TestCase public function testHandleSuccess() { - $authenticator = $this->getMockBuilder('Symfony\Component\Security\Guard\GuardAuthenticatorInterface')->getMock(); + $authenticator = $this->getMockBuilder('Symfony\Component\Security\Guard\AuthenticatorInterface')->getMock(); $authenticateToken = $this->getMockBuilder('Symfony\Component\Security\Core\Authentication\Token\TokenInterface')->getMock(); $providerKey = 'my_firewall'; $credentials = array('username' => 'weaverryan', 'password' => 'all_your_base'); + + $authenticator + ->expects($this->once()) + ->method('supports') + ->willReturn(true); $authenticator ->expects($this->once()) ->method('getCredentials') @@ -82,10 +88,14 @@ public function testHandleSuccess() public function testHandleSuccessStopsAfterResponseIsSet() { - $authenticator1 = $this->getMockBuilder('Symfony\Component\Security\Guard\GuardAuthenticatorInterface')->getMock(); - $authenticator2 = $this->getMockBuilder('Symfony\Component\Security\Guard\GuardAuthenticatorInterface')->getMock(); + $authenticator1 = $this->getMockBuilder('Symfony\Component\Security\Guard\AuthenticatorInterface')->getMock(); + $authenticator2 = $this->getMockBuilder('Symfony\Component\Security\Guard\AuthenticatorInterface')->getMock(); // mock the first authenticator to fail, and set a Response + $authenticator1 + ->expects($this->once()) + ->method('supports') + ->willReturn(true); $authenticator1 ->expects($this->once()) ->method('getCredentials') @@ -94,6 +104,7 @@ public function testHandleSuccessStopsAfterResponseIsSet() ->expects($this->once()) ->method('handleAuthenticationFailure') ->willReturn(new Response()); + // the second authenticator should *never* be called $authenticator2 ->expects($this->never()) @@ -112,10 +123,15 @@ public function testHandleSuccessStopsAfterResponseIsSet() public function testHandleSuccessWithRememberMe() { - $authenticator = $this->getMockBuilder('Symfony\Component\Security\Guard\GuardAuthenticatorInterface')->getMock(); + $authenticator = $this->getMockBuilder('Symfony\Component\Security\Guard\AuthenticatorInterface')->getMock(); $authenticateToken = $this->getMockBuilder('Symfony\Component\Security\Core\Authentication\Token\TokenInterface')->getMock(); $providerKey = 'my_firewall_with_rememberme'; + $authenticator + ->expects($this->once()) + ->method('supports') + ->with($this->equalTo($this->request)) + ->willReturn(true); $authenticator ->expects($this->once()) ->method('getCredentials') @@ -155,10 +171,14 @@ public function testHandleSuccessWithRememberMe() public function testHandleCatchesAuthenticationException() { - $authenticator = $this->getMockBuilder('Symfony\Component\Security\Guard\GuardAuthenticatorInterface')->getMock(); + $authenticator = $this->getMockBuilder('Symfony\Component\Security\Guard\AuthenticatorInterface')->getMock(); $providerKey = 'my_firewall2'; $authException = new AuthenticationException('Get outta here crazy user with a bad password!'); + $authenticator + ->expects($this->once()) + ->method('supports') + ->willReturn(true); $authenticator ->expects($this->once()) ->method('getCredentials') @@ -185,6 +205,96 @@ public function testHandleCatchesAuthenticationException() $listener->handle($this->event); } + /** + * @group legacy + */ + public function testLegacyInterfaceNullCredentials() + { + $authenticatorA = $this->getMockBuilder('Symfony\Component\Security\Guard\GuardAuthenticatorInterface')->getMock(); + $providerKey = 'my_firewall3'; + + $authenticatorA + ->expects($this->once()) + ->method('getCredentials') + ->will($this->returnValue(null)); + + // this is not called + $this->authenticationManager + ->expects($this->never()) + ->method('authenticate'); + + $this->guardAuthenticatorHandler + ->expects($this->never()) + ->method('handleAuthenticationSuccess'); + + $listener = new GuardAuthenticationListener( + $this->guardAuthenticatorHandler, + $this->authenticationManager, + $providerKey, + array($authenticatorA), + $this->logger + ); + + $listener->handle($this->event); + } + + /** + * @group legacy + */ + public function testLegacyInterfaceKeepsWorking() + { + $authenticator = $this->getMockBuilder('Symfony\Component\Security\Guard\GuardAuthenticatorInterface')->getMock(); + $authenticateToken = $this->getMockBuilder('Symfony\Component\Security\Core\Authentication\Token\TokenInterface')->getMock(); + $providerKey = 'my_firewall'; + + $credentials = array('username' => 'weaverryan', 'password' => 'all_your_base'); + + $authenticator + ->expects($this->once()) + ->method('getCredentials') + ->with($this->equalTo($this->request)) + ->will($this->returnValue($credentials)); + + // a clone of the token that should be created internally + $uniqueGuardKey = 'my_firewall_0'; + $nonAuthedToken = new PreAuthenticationGuardToken($credentials, $uniqueGuardKey); + + $this->authenticationManager + ->expects($this->once()) + ->method('authenticate') + ->with($this->equalTo($nonAuthedToken)) + ->will($this->returnValue($authenticateToken)); + + $this->guardAuthenticatorHandler + ->expects($this->once()) + ->method('authenticateWithToken') + ->with($authenticateToken, $this->request); + + $this->guardAuthenticatorHandler + ->expects($this->once()) + ->method('handleAuthenticationSuccess') + ->with($authenticateToken, $this->request, $authenticator, $providerKey); + + $listener = new GuardAuthenticationListener( + $this->guardAuthenticatorHandler, + $this->authenticationManager, + $providerKey, + array($authenticator), + $this->logger + ); + + $listener->setRememberMeServices($this->rememberMeServices); + // should never be called - our handleAuthenticationSuccess() does not return a Response + $this->rememberMeServices + ->expects($this->never()) + ->method('loginSuccess'); + + $listener->handle($this->event); + } + + /** + * @group legacy + */ public function testReturnNullToSkipAuth() { $authenticatorA = $this->getMockBuilder('Symfony\Component\Security\Guard\GuardAuthenticatorInterface')->getMock(); @@ -220,6 +330,62 @@ public function testReturnNullToSkipAuth() $listener->handle($this->event); } + public function testSupportsReturnFalseSkipAuth() + { + $authenticator = $this->getMockBuilder('Symfony\Component\Security\Guard\AuthenticatorInterface')->getMock(); + $providerKey = 'my_firewall4'; + + $authenticator + ->expects($this->once()) + ->method('supports') + ->will($this->returnValue(false)); + + // this is not called + $authenticator + ->expects($this->never()) + ->method('getCredentials'); + + $listener = new GuardAuthenticationListener( + $this->guardAuthenticatorHandler, + $this->authenticationManager, + $providerKey, + array($authenticator), + $this->logger + ); + + $listener->handle($this->event); + } + + /** + * @expectedException \UnexpectedValueException + */ + public function testSupportsReturnTrueRaiseMissingCredentialsException() + { + $authenticator = $this->getMockBuilder('Symfony\Component\Security\Guard\AuthenticatorInterface')->getMock(); + $providerKey = 'my_firewall4'; + + $authenticator + ->expects($this->once()) + ->method('supports') + ->will($this->returnValue(true)); + + // this will raise exception + $authenticator + ->expects($this->once()) + ->method('getCredentials') + ->will($this->returnValue(null)); + + $listener = new GuardAuthenticationListener( + $this->guardAuthenticatorHandler, + $this->authenticationManager, + $providerKey, + array($authenticator), + $this->logger + ); + + $listener->handle($this->event); + } + protected function setUp() { $this->authenticationManager = $this->getMockBuilder('Symfony\Component\Security\Core\Authentication\AuthenticationProviderManager') diff --git a/src/Symfony/Component/Security/Guard/Tests/GuardAuthenticatorHandlerTest.php b/src/Symfony/Component/Security/Guard/Tests/GuardAuthenticatorHandlerTest.php index b46bc4a78d4f1..29199d820eb11 100644 --- a/src/Symfony/Component/Security/Guard/Tests/GuardAuthenticatorHandlerTest.php +++ b/src/Symfony/Component/Security/Guard/Tests/GuardAuthenticatorHandlerTest.php @@ -128,7 +128,7 @@ protected function setUp() $this->dispatcher = $this->getMockBuilder('Symfony\Component\EventDispatcher\EventDispatcherInterface')->getMock(); $this->token = $this->getMockBuilder('Symfony\Component\Security\Core\Authentication\Token\TokenInterface')->getMock(); $this->request = new Request(array(), array(), array(), array(), array(), array()); - $this->guardAuthenticator = $this->getMockBuilder('Symfony\Component\Security\Guard\GuardAuthenticatorInterface')->getMock(); + $this->guardAuthenticator = $this->getMockBuilder('Symfony\Component\Security\Guard\AuthenticatorInterface')->getMock(); } protected function tearDown() diff --git a/src/Symfony/Component/Security/Guard/Token/PreAuthenticationGuardToken.php b/src/Symfony/Component/Security/Guard/Token/PreAuthenticationGuardToken.php index abbe985c9e0b2..e1b39417d78e2 100644 --- a/src/Symfony/Component/Security/Guard/Token/PreAuthenticationGuardToken.php +++ b/src/Symfony/Component/Security/Guard/Token/PreAuthenticationGuardToken.php @@ -29,7 +29,7 @@ class PreAuthenticationGuardToken extends AbstractToken implements GuardTokenInt /** * @param mixed $credentials - * @param string $guardProviderKey Unique key that bind this token to a specific GuardAuthenticatorInterface + * @param string $guardProviderKey Unique key that bind this token to a specific AuthenticatorInterface */ public function __construct($credentials, $guardProviderKey) { From b1290da21bf0aec570e7852ebcdd032ff86a5074 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Wed, 4 Oct 2017 11:26:14 +0200 Subject: [PATCH 1001/1099] [Config] Fix dumped files invalidation by OPCache --- src/Symfony/Component/Config/ConfigCache.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Symfony/Component/Config/ConfigCache.php b/src/Symfony/Component/Config/ConfigCache.php index a34328ee8f31f..814ae7fb3b46b 100644 --- a/src/Symfony/Component/Config/ConfigCache.php +++ b/src/Symfony/Component/Config/ConfigCache.php @@ -149,6 +149,10 @@ public function write($content, array $metadata = null) // discard chmod failure (some filesystem may not support it) } } + + if (\function_exists('opcache_invalidate') && ini_get('opcache.enable')) { + @opcache_invalidate($this->file, true); + } } /** From d779845c3b54fd17b5edb2dec8e601e4b12d541e Mon Sep 17 00:00:00 2001 From: Tobias Schultze Date: Wed, 4 Oct 2017 18:30:17 +0200 Subject: [PATCH 1002/1099] [DI] remove inheritdoc from dumped container --- .../DependencyInjection/Dumper/PhpDumper.php | 27 ------------------- .../Tests/Fixtures/php/services1-1.php | 9 ------- .../Tests/Fixtures/php/services1.php | 9 ------- .../Tests/Fixtures/php/services10.php | 21 --------------- .../Tests/Fixtures/php/services12.php | 21 --------------- .../Tests/Fixtures/php/services13.php | 9 ------- .../Tests/Fixtures/php/services19.php | 9 ------- .../Tests/Fixtures/php/services24.php | 9 ------- .../Tests/Fixtures/php/services26.php | 21 --------------- .../Tests/Fixtures/php/services31.php | 9 ------- .../Tests/Fixtures/php/services33.php | 9 ------- .../Tests/Fixtures/php/services8.php | 21 --------------- .../Tests/Fixtures/php/services9_as_files.txt | 24 ----------------- .../Tests/Fixtures/php/services9_compiled.php | 21 --------------- .../Fixtures/php/services_array_params.php | 21 --------------- .../Fixtures/php/services_base64_env.php | 21 --------------- .../Fixtures/php/services_legacy_privates.php | 9 ------- .../Tests/Fixtures/php/services_locator.php | 9 ------- .../Fixtures/php/services_private_frozen.php | 9 ------- .../php/services_private_in_expression.php | 9 ------- .../Tests/Fixtures/php/services_rot13_env.php | 21 --------------- .../Fixtures/php/services_subscriber.php | 9 ------- .../php/services_uninitialized_ref.php | 9 ------- 23 files changed, 336 deletions(-) diff --git a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php index e08e385e35851..c8a4d5cd3af68 100644 --- a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php +++ b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php @@ -899,25 +899,16 @@ public function __construct() if ($this->container->isCompiled()) { $code .= <<docStar} - * {@inheritdoc} - */ public function compile() { throw new LogicException('You cannot compile a dumped container that was already compiled.'); } - /*{$this->docStar} - * {@inheritdoc} - */ public function isCompiled() { return true; } - /*{$this->docStar} - * {@inheritdoc} - */ public function isFrozen() { @trigger_error(sprintf('The %s() method is deprecated since version 3.3 and will be removed in 4.0. Use the isCompiled() method instead.', __METHOD__), E_USER_DEPRECATED); @@ -931,9 +922,6 @@ public function isFrozen() if ($this->asFiles) { $code .= <<docStar} - * {@inheritdoc} - */ protected function load(\$file, \$lazyLoad = true) { return require \$file; @@ -1125,9 +1113,6 @@ private function addDefaultParametersMethod() if ($this->container->isCompiled()) { $code .= <<<'EOF' - /** - * {@inheritdoc} - */ public function getParameter($name) { if (!(isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters))) { @@ -1144,9 +1129,6 @@ public function getParameter($name) return $this->parameters[$name]; } - /** - * {@inheritdoc} - */ public function hasParameter($name) { $name = $this->normalizeParameterName($name); @@ -1154,17 +1136,11 @@ public function hasParameter($name) return isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters); } - /** - * {@inheritdoc} - */ public function setParameter($name, $value) { throw new LogicException('Impossible to call set() on a frozen ParameterBag.'); } - /** - * {@inheritdoc} - */ public function getParameterBag() { if (null === $this->parameterBag) { @@ -1179,9 +1155,6 @@ public function getParameterBag() } EOF; - if ('' === $this->docStar) { - $code = str_replace('/**', '/*', $code); - } if ($dynamicPhp) { $loadedDynamicParameters = $this->exportParameters(array_combine(array_keys($dynamicPhp), array_fill(0, count($dynamicPhp), false)), '', 8); diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services1-1.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services1-1.php index b791398c138ab..e696dec6aedb4 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services1-1.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services1-1.php @@ -28,25 +28,16 @@ public function __construct() $this->aliases = array(); } - /** - * {@inheritdoc} - */ public function compile() { throw new LogicException('You cannot compile a dumped container that was already compiled.'); } - /** - * {@inheritdoc} - */ public function isCompiled() { return true; } - /** - * {@inheritdoc} - */ public function isFrozen() { @trigger_error(sprintf('The %s() method is deprecated since version 3.3 and will be removed in 4.0. Use the isCompiled() method instead.', __METHOD__), E_USER_DEPRECATED); diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services1.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services1.php index 44c052c0a9521..c339856f0276b 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services1.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services1.php @@ -26,25 +26,16 @@ public function __construct() $this->aliases = array(); } - /** - * {@inheritdoc} - */ public function compile() { throw new LogicException('You cannot compile a dumped container that was already compiled.'); } - /** - * {@inheritdoc} - */ public function isCompiled() { return true; } - /** - * {@inheritdoc} - */ public function isFrozen() { @trigger_error(sprintf('The %s() method is deprecated since version 3.3 and will be removed in 4.0. Use the isCompiled() method instead.', __METHOD__), E_USER_DEPRECATED); diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services10.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services10.php index 4353f7b06574b..219cf3431b573 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services10.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services10.php @@ -31,25 +31,16 @@ public function __construct() $this->aliases = array(); } - /** - * {@inheritdoc} - */ public function compile() { throw new LogicException('You cannot compile a dumped container that was already compiled.'); } - /** - * {@inheritdoc} - */ public function isCompiled() { return true; } - /** - * {@inheritdoc} - */ public function isFrozen() { @trigger_error(sprintf('The %s() method is deprecated since version 3.3 and will be removed in 4.0. Use the isCompiled() method instead.', __METHOD__), E_USER_DEPRECATED); @@ -67,9 +58,6 @@ protected function getTestService() return $this->services['test'] = new \stdClass(array('only dot' => '.', 'concatenation as value' => '.\'\'.', 'concatenation from the start value' => '\'\'.', '.' => 'dot as a key', '.\'\'.' => 'concatenation as a key', '\'\'.' => 'concatenation from the start key', 'optimize concatenation' => 'string1-string2', 'optimize concatenation with empty string' => 'string1string2', 'optimize concatenation from the start' => 'start', 'optimize concatenation at the end' => 'end')); } - /** - * {@inheritdoc} - */ public function getParameter($name) { if (!(isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters))) { @@ -86,9 +74,6 @@ public function getParameter($name) return $this->parameters[$name]; } - /** - * {@inheritdoc} - */ public function hasParameter($name) { $name = $this->normalizeParameterName($name); @@ -96,17 +81,11 @@ public function hasParameter($name) return isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters); } - /** - * {@inheritdoc} - */ public function setParameter($name, $value) { throw new LogicException('Impossible to call set() on a frozen ParameterBag.'); } - /** - * {@inheritdoc} - */ public function getParameterBag() { if (null === $this->parameterBag) { diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services12.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services12.php index 9017441bd69ae..2bd134a9f8400 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services12.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services12.php @@ -35,25 +35,16 @@ public function __construct() $this->aliases = array(); } - /** - * {@inheritdoc} - */ public function compile() { throw new LogicException('You cannot compile a dumped container that was already compiled.'); } - /** - * {@inheritdoc} - */ public function isCompiled() { return true; } - /** - * {@inheritdoc} - */ public function isFrozen() { @trigger_error(sprintf('The %s() method is deprecated since version 3.3 and will be removed in 4.0. Use the isCompiled() method instead.', __METHOD__), E_USER_DEPRECATED); @@ -71,9 +62,6 @@ protected function getTestService() return $this->services['test'] = new \stdClass(('wiz'.$this->targetDirs[1]), array(('wiz'.$this->targetDirs[1]) => ($this->targetDirs[2].'/'))); } - /** - * {@inheritdoc} - */ public function getParameter($name) { if (!(isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters))) { @@ -90,9 +78,6 @@ public function getParameter($name) return $this->parameters[$name]; } - /** - * {@inheritdoc} - */ public function hasParameter($name) { $name = $this->normalizeParameterName($name); @@ -100,17 +85,11 @@ public function hasParameter($name) return isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters); } - /** - * {@inheritdoc} - */ public function setParameter($name, $value) { throw new LogicException('Impossible to call set() on a frozen ParameterBag.'); } - /** - * {@inheritdoc} - */ public function getParameterBag() { if (null === $this->parameterBag) { diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services13.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services13.php index a7fe891692018..4cc353ca278de 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services13.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services13.php @@ -29,25 +29,16 @@ public function __construct() $this->aliases = array(); } - /** - * {@inheritdoc} - */ public function compile() { throw new LogicException('You cannot compile a dumped container that was already compiled.'); } - /** - * {@inheritdoc} - */ public function isCompiled() { return true; } - /** - * {@inheritdoc} - */ public function isFrozen() { @trigger_error(sprintf('The %s() method is deprecated since version 3.3 and will be removed in 4.0. Use the isCompiled() method instead.', __METHOD__), E_USER_DEPRECATED); diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services19.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services19.php index e6870bcc45e4b..0a6b97e65ded6 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services19.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services19.php @@ -30,25 +30,16 @@ public function __construct() $this->aliases = array(); } - /** - * {@inheritdoc} - */ public function compile() { throw new LogicException('You cannot compile a dumped container that was already compiled.'); } - /** - * {@inheritdoc} - */ public function isCompiled() { return true; } - /** - * {@inheritdoc} - */ public function isFrozen() { @trigger_error(sprintf('The %s() method is deprecated since version 3.3 and will be removed in 4.0. Use the isCompiled() method instead.', __METHOD__), E_USER_DEPRECATED); diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services24.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services24.php index 7cff4f35bbb85..7546b1765a658 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services24.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services24.php @@ -29,25 +29,16 @@ public function __construct() $this->aliases = array(); } - /** - * {@inheritdoc} - */ public function compile() { throw new LogicException('You cannot compile a dumped container that was already compiled.'); } - /** - * {@inheritdoc} - */ public function isCompiled() { return true; } - /** - * {@inheritdoc} - */ public function isFrozen() { @trigger_error(sprintf('The %s() method is deprecated since version 3.3 and will be removed in 4.0. Use the isCompiled() method instead.', __METHOD__), E_USER_DEPRECATED); diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services26.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services26.php index c802c9ae090cc..7dc51d12afed1 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services26.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services26.php @@ -35,25 +35,16 @@ public function __construct() $this->aliases = array(); } - /** - * {@inheritdoc} - */ public function compile() { throw new LogicException('You cannot compile a dumped container that was already compiled.'); } - /** - * {@inheritdoc} - */ public function isCompiled() { return true; } - /** - * {@inheritdoc} - */ public function isFrozen() { @trigger_error(sprintf('The %s() method is deprecated since version 3.3 and will be removed in 4.0. Use the isCompiled() method instead.', __METHOD__), E_USER_DEPRECATED); @@ -73,9 +64,6 @@ protected function getTestService() return $this->services['test'] = new $class($this->getEnv('Bar'), 'foo'.$this->getEnv('string:FOO').'baz', $this->getEnv('int:Baz')); } - /** - * {@inheritdoc} - */ public function getParameter($name) { if (!(isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters))) { @@ -92,9 +80,6 @@ public function getParameter($name) return $this->parameters[$name]; } - /** - * {@inheritdoc} - */ public function hasParameter($name) { $name = $this->normalizeParameterName($name); @@ -102,17 +87,11 @@ public function hasParameter($name) return isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters); } - /** - * {@inheritdoc} - */ public function setParameter($name, $value) { throw new LogicException('Impossible to call set() on a frozen ParameterBag.'); } - /** - * {@inheritdoc} - */ public function getParameterBag() { if (null === $this->parameterBag) { diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services31.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services31.php index 51d9626372ca4..ffc76d892226a 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services31.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services31.php @@ -30,25 +30,16 @@ public function __construct() $this->aliases = array(); } - /** - * {@inheritdoc} - */ public function compile() { throw new LogicException('You cannot compile a dumped container that was already compiled.'); } - /** - * {@inheritdoc} - */ public function isCompiled() { return true; } - /** - * {@inheritdoc} - */ public function isFrozen() { @trigger_error(sprintf('The %s() method is deprecated since version 3.3 and will be removed in 4.0. Use the isCompiled() method instead.', __METHOD__), E_USER_DEPRECATED); diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services33.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services33.php index af310ce2bd58f..e36cdcaedb918 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services33.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services33.php @@ -34,25 +34,16 @@ public function __construct() $this->aliases = array(); } - /** - * {@inheritdoc} - */ public function compile() { throw new LogicException('You cannot compile a dumped container that was already compiled.'); } - /** - * {@inheritdoc} - */ public function isCompiled() { return true; } - /** - * {@inheritdoc} - */ public function isFrozen() { @trigger_error(sprintf('The %s() method is deprecated since version 3.3 and will be removed in 4.0. Use the isCompiled() method instead.', __METHOD__), E_USER_DEPRECATED); diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services8.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services8.php index f9de3098273d4..357b8aa697560 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services8.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services8.php @@ -28,25 +28,16 @@ public function __construct() $this->aliases = array(); } - /** - * {@inheritdoc} - */ public function compile() { throw new LogicException('You cannot compile a dumped container that was already compiled.'); } - /** - * {@inheritdoc} - */ public function isCompiled() { return true; } - /** - * {@inheritdoc} - */ public function isFrozen() { @trigger_error(sprintf('The %s() method is deprecated since version 3.3 and will be removed in 4.0. Use the isCompiled() method instead.', __METHOD__), E_USER_DEPRECATED); @@ -54,9 +45,6 @@ public function isFrozen() return true; } - /** - * {@inheritdoc} - */ public function getParameter($name) { if (!(isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters))) { @@ -73,9 +61,6 @@ public function getParameter($name) return $this->parameters[$name]; } - /** - * {@inheritdoc} - */ public function hasParameter($name) { $name = $this->normalizeParameterName($name); @@ -83,17 +68,11 @@ public function hasParameter($name) return isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters); } - /** - * {@inheritdoc} - */ public function setParameter($name, $value) { throw new LogicException('Impossible to call set() on a frozen ParameterBag.'); } - /** - * {@inheritdoc} - */ public function getParameterBag() { if (null === $this->parameterBag) { diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_as_files.txt b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_as_files.txt index ced52118cf1b6..3795ade4806e6 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_as_files.txt +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_as_files.txt @@ -322,25 +322,16 @@ class Container%s extends Container ); } - /** - * {@inheritdoc} - */ public function compile() { throw new LogicException('You cannot compile a dumped container that was already compiled.'); } - /** - * {@inheritdoc} - */ public function isCompiled() { return true; } - /** - * {@inheritdoc} - */ public function isFrozen() { @trigger_error(sprintf('The %s() method is deprecated since version 3.3 and will be removed in 4.0. Use the isCompiled() method instead.', __METHOD__), E_USER_DEPRECATED); @@ -348,9 +339,6 @@ class Container%s extends Container return true; } - /** - * {@inheritdoc} - */ protected function load($file, $lazyLoad = true) { return require $file; @@ -366,9 +354,6 @@ class Container%s extends Container return new \Bar\FooClass(${($_ = isset($this->services['deprecated_service']) ? $this->services['deprecated_service'] : $this->load(__DIR__.'/getDeprecatedServiceService.php')) && false ?: '_'}); } - /** - * {@inheritdoc} - */ public function getParameter($name) { if (!(isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters))) { @@ -385,9 +370,6 @@ class Container%s extends Container return $this->parameters[$name]; } - /** - * {@inheritdoc} - */ public function hasParameter($name) { $name = $this->normalizeParameterName($name); @@ -395,17 +377,11 @@ class Container%s extends Container return isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters); } - /** - * {@inheritdoc} - */ public function setParameter($name, $value) { throw new LogicException('Impossible to call set() on a frozen ParameterBag.'); } - /** - * {@inheritdoc} - */ public function getParameterBag() { if (null === $this->parameterBag) { diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_compiled.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_compiled.php index c75138447deb6..7ec609ca5e6cb 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_compiled.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_compiled.php @@ -58,25 +58,16 @@ public function __construct() ); } - /** - * {@inheritdoc} - */ public function compile() { throw new LogicException('You cannot compile a dumped container that was already compiled.'); } - /** - * {@inheritdoc} - */ public function isCompiled() { return true; } - /** - * {@inheritdoc} - */ public function isFrozen() { @trigger_error(sprintf('The %s() method is deprecated since version 3.3 and will be removed in 4.0. Use the isCompiled() method instead.', __METHOD__), E_USER_DEPRECATED); @@ -374,9 +365,6 @@ protected function getTaggedIteratorFooService() return $this->services['tagged_iterator_foo'] = new \Bar(); } - /** - * {@inheritdoc} - */ public function getParameter($name) { if (!(isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters))) { @@ -393,9 +381,6 @@ public function getParameter($name) return $this->parameters[$name]; } - /** - * {@inheritdoc} - */ public function hasParameter($name) { $name = $this->normalizeParameterName($name); @@ -403,17 +388,11 @@ public function hasParameter($name) return isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters); } - /** - * {@inheritdoc} - */ public function setParameter($name, $value) { throw new LogicException('Impossible to call set() on a frozen ParameterBag.'); } - /** - * {@inheritdoc} - */ public function getParameterBag() { if (null === $this->parameterBag) { diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_array_params.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_array_params.php index 9c6f55d25966a..e5159861b4708 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_array_params.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_array_params.php @@ -35,25 +35,16 @@ public function __construct() $this->aliases = array(); } - /** - * {@inheritdoc} - */ public function compile() { throw new LogicException('You cannot compile a dumped container that was already compiled.'); } - /** - * {@inheritdoc} - */ public function isCompiled() { return true; } - /** - * {@inheritdoc} - */ public function isFrozen() { @trigger_error(sprintf('The %s() method is deprecated since version 3.3 and will be removed in 4.0. Use the isCompiled() method instead.', __METHOD__), E_USER_DEPRECATED); @@ -75,9 +66,6 @@ protected function getBarService() return $instance; } - /** - * {@inheritdoc} - */ public function getParameter($name) { if (!(isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters))) { @@ -94,9 +82,6 @@ public function getParameter($name) return $this->parameters[$name]; } - /** - * {@inheritdoc} - */ public function hasParameter($name) { $name = $this->normalizeParameterName($name); @@ -104,17 +89,11 @@ public function hasParameter($name) return isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters); } - /** - * {@inheritdoc} - */ public function setParameter($name, $value) { throw new LogicException('Impossible to call set() on a frozen ParameterBag.'); } - /** - * {@inheritdoc} - */ public function getParameterBag() { if (null === $this->parameterBag) { diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_base64_env.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_base64_env.php index 49fcf6e45891c..8513e25d2e085 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_base64_env.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_base64_env.php @@ -28,25 +28,16 @@ public function __construct() $this->aliases = array(); } - /** - * {@inheritdoc} - */ public function compile() { throw new LogicException('You cannot compile a dumped container that was already compiled.'); } - /** - * {@inheritdoc} - */ public function isCompiled() { return true; } - /** - * {@inheritdoc} - */ public function isFrozen() { @trigger_error(sprintf('The %s() method is deprecated since version 3.3 and will be removed in 4.0. Use the isCompiled() method instead.', __METHOD__), E_USER_DEPRECATED); @@ -54,9 +45,6 @@ public function isFrozen() return true; } - /** - * {@inheritdoc} - */ public function getParameter($name) { if (!(isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters))) { @@ -73,9 +61,6 @@ public function getParameter($name) return $this->parameters[$name]; } - /** - * {@inheritdoc} - */ public function hasParameter($name) { $name = $this->normalizeParameterName($name); @@ -83,17 +68,11 @@ public function hasParameter($name) return isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters); } - /** - * {@inheritdoc} - */ public function setParameter($name, $value) { throw new LogicException('Impossible to call set() on a frozen ParameterBag.'); } - /** - * {@inheritdoc} - */ public function getParameterBag() { if (null === $this->parameterBag) { diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_legacy_privates.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_legacy_privates.php index bedf268d47b28..fad546d7fc348 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_legacy_privates.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_legacy_privates.php @@ -55,25 +55,16 @@ public function __construct() ); } - /** - * {@inheritdoc} - */ public function compile() { throw new LogicException('You cannot compile a dumped container that was already compiled.'); } - /** - * {@inheritdoc} - */ public function isCompiled() { return true; } - /** - * {@inheritdoc} - */ public function isFrozen() { @trigger_error(sprintf('The %s() method is deprecated since version 3.3 and will be removed in 4.0. Use the isCompiled() method instead.', __METHOD__), E_USER_DEPRECATED); diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_locator.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_locator.php index 87c8b5800349e..74e2a8ce094a2 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_locator.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_locator.php @@ -40,25 +40,16 @@ public function __construct() $this->aliases = array(); } - /** - * {@inheritdoc} - */ public function compile() { throw new LogicException('You cannot compile a dumped container that was already compiled.'); } - /** - * {@inheritdoc} - */ public function isCompiled() { return true; } - /** - * {@inheritdoc} - */ public function isFrozen() { @trigger_error(sprintf('The %s() method is deprecated since version 3.3 and will be removed in 4.0. Use the isCompiled() method instead.', __METHOD__), E_USER_DEPRECATED); diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_private_frozen.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_private_frozen.php index bbb0e9e00eccc..c7ea243ae81a0 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_private_frozen.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_private_frozen.php @@ -34,25 +34,16 @@ public function __construct() $this->aliases = array(); } - /** - * {@inheritdoc} - */ public function compile() { throw new LogicException('You cannot compile a dumped container that was already compiled.'); } - /** - * {@inheritdoc} - */ public function isCompiled() { return true; } - /** - * {@inheritdoc} - */ public function isFrozen() { @trigger_error(sprintf('The %s() method is deprecated since version 3.3 and will be removed in 4.0. Use the isCompiled() method instead.', __METHOD__), E_USER_DEPRECATED); diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_private_in_expression.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_private_in_expression.php index 8f3e7aa7fc8ab..8269736c0b8df 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_private_in_expression.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_private_in_expression.php @@ -33,25 +33,16 @@ public function __construct() $this->aliases = array(); } - /** - * {@inheritdoc} - */ public function compile() { throw new LogicException('You cannot compile a dumped container that was already compiled.'); } - /** - * {@inheritdoc} - */ public function isCompiled() { return true; } - /** - * {@inheritdoc} - */ public function isFrozen() { @trigger_error(sprintf('The %s() method is deprecated since version 3.3 and will be removed in 4.0. Use the isCompiled() method instead.', __METHOD__), E_USER_DEPRECATED); diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_rot13_env.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_rot13_env.php index 0d2bb22b75361..3b26928577247 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_rot13_env.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_rot13_env.php @@ -35,25 +35,16 @@ public function __construct() $this->aliases = array(); } - /** - * {@inheritdoc} - */ public function compile() { throw new LogicException('You cannot compile a dumped container that was already compiled.'); } - /** - * {@inheritdoc} - */ public function isCompiled() { return true; } - /** - * {@inheritdoc} - */ public function isFrozen() { @trigger_error(sprintf('The %s() method is deprecated since version 3.3 and will be removed in 4.0. Use the isCompiled() method instead.', __METHOD__), E_USER_DEPRECATED); @@ -83,9 +74,6 @@ protected function getContainer_EnvVarProcessorsLocatorService() })); } - /** - * {@inheritdoc} - */ public function getParameter($name) { if (!(isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters))) { @@ -102,9 +90,6 @@ public function getParameter($name) return $this->parameters[$name]; } - /** - * {@inheritdoc} - */ public function hasParameter($name) { $name = $this->normalizeParameterName($name); @@ -112,17 +97,11 @@ public function hasParameter($name) return isset($this->parameters[$name]) || isset($this->loadedDynamicParameters[$name]) || array_key_exists($name, $this->parameters); } - /** - * {@inheritdoc} - */ public function setParameter($name, $value) { throw new LogicException('Impossible to call set() on a frozen ParameterBag.'); } - /** - * {@inheritdoc} - */ public function getParameterBag() { if (null === $this->parameterBag) { diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_subscriber.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_subscriber.php index 400b28ca97e97..a4ab454e3efc0 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_subscriber.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_subscriber.php @@ -38,25 +38,16 @@ public function __construct() $this->aliases = array(); } - /** - * {@inheritdoc} - */ public function compile() { throw new LogicException('You cannot compile a dumped container that was already compiled.'); } - /** - * {@inheritdoc} - */ public function isCompiled() { return true; } - /** - * {@inheritdoc} - */ public function isFrozen() { @trigger_error(sprintf('The %s() method is deprecated since version 3.3 and will be removed in 4.0. Use the isCompiled() method instead.', __METHOD__), E_USER_DEPRECATED); diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_uninitialized_ref.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_uninitialized_ref.php index ef70ffb76c18d..c47e7c15d1291 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_uninitialized_ref.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_uninitialized_ref.php @@ -35,25 +35,16 @@ public function __construct() $this->aliases = array(); } - /** - * {@inheritdoc} - */ public function compile() { throw new LogicException('You cannot compile a dumped container that was already compiled.'); } - /** - * {@inheritdoc} - */ public function isCompiled() { return true; } - /** - * {@inheritdoc} - */ public function isFrozen() { @trigger_error(sprintf('The %s() method is deprecated since version 3.3 and will be removed in 4.0. Use the isCompiled() method instead.', __METHOD__), E_USER_DEPRECATED); From 3e8076023d2fe472e0612eb940e18f64d3407e43 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Wed, 4 Oct 2017 14:14:21 +0200 Subject: [PATCH 1003/1099] [DI] Improve some deprecation messages --- .../Component/DependencyInjection/Container.php | 12 ++++++------ .../DependencyInjection/Tests/ContainerTest.php | 12 ++++++------ .../Tests/Dumper/PhpDumperTest.php | 4 ++-- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/Symfony/Component/DependencyInjection/Container.php b/src/Symfony/Component/DependencyInjection/Container.php index 2d43ba7a60290..c878af3d9e0e4 100644 --- a/src/Symfony/Component/DependencyInjection/Container.php +++ b/src/Symfony/Component/DependencyInjection/Container.php @@ -199,16 +199,16 @@ public function set($id, $service) if (isset($this->privates[$id])) { if (null === $service) { - @trigger_error(sprintf('Unsetting the "%s" private service is deprecated since Symfony 3.2 and won\'t be supported anymore in Symfony 4.0.', $id), E_USER_DEPRECATED); + @trigger_error(sprintf('The "%s" service is private, unsetting it is deprecated since Symfony 3.2 and will fail in 4.0.', $id), E_USER_DEPRECATED); unset($this->privates[$id]); } else { - @trigger_error(sprintf('Setting the "%s" private service is deprecated since Symfony 3.2 and won\'t be supported anymore in Symfony 4.0.', $id), E_USER_DEPRECATED); + @trigger_error(sprintf('The "%s" service is private, replacing it is deprecated since Symfony 3.2 and will fail in 4.0.', $id), E_USER_DEPRECATED); } } elseif ($wasSet && isset($this->methodMap[$id])) { if (null === $service) { - @trigger_error(sprintf('Unsetting the "%s" service after it\'s been initialized is deprecated since Symfony 3.3 and won\'t be supported anymore in Symfony 4.0.', $id), E_USER_DEPRECATED); + @trigger_error(sprintf('The "%s" service is already initialized, unsetting it is deprecated since Symfony 3.3 and will fail in 4.0.', $id), E_USER_DEPRECATED); } else { - @trigger_error(sprintf('Setting the "%s" service after it\'s been initialized is deprecated since Symfony 3.3 and won\'t be supported anymore in Symfony 4.0.', $id), E_USER_DEPRECATED); + @trigger_error(sprintf('The "%s" service is already initialized, replacing it is deprecated since Symfony 3.3 and will fail in 4.0.', $id), E_USER_DEPRECATED); } } } @@ -224,7 +224,7 @@ public function has($id) { for ($i = 2;;) { if (isset($this->privates[$id])) { - @trigger_error(sprintf('Checking for the existence of the "%s" private service is deprecated since Symfony 3.2 and won\'t be supported anymore in Symfony 4.0.', $id), E_USER_DEPRECATED); + @trigger_error(sprintf('The "%s" service is private, checking for its existence is deprecated since Symfony 3.2 and will fail in 4.0.', $id), E_USER_DEPRECATED); } if (isset($this->aliases[$id])) { $id = $this->aliases[$id]; @@ -282,7 +282,7 @@ public function get($id, $invalidBehavior = self::EXCEPTION_ON_INVALID_REFERENCE // calling $this->normalizeId($id) unless necessary. for ($i = 2;;) { if (isset($this->privates[$id])) { - @trigger_error(sprintf('Requesting the "%s" private service is deprecated since Symfony 3.2 and won\'t be supported anymore in Symfony 4.0.', $id), E_USER_DEPRECATED); + @trigger_error(sprintf('The "%s" service is private, getting it from the container is deprecated since Symfony 3.2 and will fail in 4.0. You should either make the service public, or stop getting services directly from the container and use dependency injection instead.', $id), E_USER_DEPRECATED); } if (isset($this->aliases[$id])) { $id = $this->aliases[$id]; diff --git a/src/Symfony/Component/DependencyInjection/Tests/ContainerTest.php b/src/Symfony/Component/DependencyInjection/Tests/ContainerTest.php index 5cd988714ad75..3afc118b3d505 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/ContainerTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/ContainerTest.php @@ -186,7 +186,7 @@ public function testSetReplacesAlias() /** * @group legacy - * @expectedDeprecation Unsetting the "bar" service after it's been initialized is deprecated since Symfony 3.3 and won't be supported anymore in Symfony 4.0. + * @expectedDeprecation The "bar" service is already initialized, unsetting it is deprecated since Symfony 3.3 and will fail in 4.0. */ public function testSetWithNullOnInitializedPredefinedService() { @@ -452,7 +452,7 @@ public function testThatCloningIsNotSupported() /** * @group legacy - * @expectedDeprecation Unsetting the "internal" private service is deprecated since Symfony 3.2 and won't be supported anymore in Symfony 4.0. + * @expectedDeprecation The "internal" service is private, unsetting it is deprecated since Symfony 3.2 and will fail in 4.0. */ public function testUnsetInternalPrivateServiceIsDeprecated() { @@ -462,7 +462,7 @@ public function testUnsetInternalPrivateServiceIsDeprecated() /** * @group legacy - * @expectedDeprecation Setting the "internal" private service is deprecated since Symfony 3.2 and won't be supported anymore in Symfony 4.0. + * @expectedDeprecation The "internal" service is private, replacing it is deprecated since Symfony 3.2 and will fail in 4.0. */ public function testChangeInternalPrivateServiceIsDeprecated() { @@ -473,7 +473,7 @@ public function testChangeInternalPrivateServiceIsDeprecated() /** * @group legacy - * @expectedDeprecation Checking for the existence of the "internal" private service is deprecated since Symfony 3.2 and won't be supported anymore in Symfony 4.0. + * @expectedDeprecation The "internal" service is private, checking for its existence is deprecated since Symfony 3.2 and will fail in 4.0. */ public function testCheckExistenceOfAnInternalPrivateServiceIsDeprecated() { @@ -484,7 +484,7 @@ public function testCheckExistenceOfAnInternalPrivateServiceIsDeprecated() /** * @group legacy - * @expectedDeprecation Requesting the "internal" private service is deprecated since Symfony 3.2 and won't be supported anymore in Symfony 4.0. + * @expectedDeprecation The "internal" service is private, getting it from the container is deprecated since Symfony 3.2 and will fail in 4.0. You should either make the service public, or stop getting services directly from the container and use dependency injection instead. */ public function testRequestAnInternalSharedPrivateServiceIsDeprecated() { @@ -495,7 +495,7 @@ public function testRequestAnInternalSharedPrivateServiceIsDeprecated() /** * @group legacy - * @expectedDeprecation Setting the "bar" service after it's been initialized is deprecated since Symfony 3.3 and won't be supported anymore in Symfony 4.0. + * @expectedDeprecation The "bar" service is already initialized, replacing it is deprecated since Symfony 3.3 and will fail in 4.0. */ public function testReplacingAPreDefinedServiceIsDeprecated() { diff --git a/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php b/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php index d832a220c7afc..991337681fc07 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php @@ -269,7 +269,7 @@ public function testFrozenContainerWithoutAliases() /** * @group legacy - * @expectedDeprecation Setting the "bar" service after it's been initialized is deprecated since Symfony 3.3 and won't be supported anymore in Symfony 4.0. + * @expectedDeprecation The "bar" service is already initialized, replacing it is deprecated since Symfony 3.3 and will fail in 4.0. */ public function testOverrideServiceWhenUsingADumpedContainer() { @@ -286,7 +286,7 @@ public function testOverrideServiceWhenUsingADumpedContainer() /** * @group legacy - * @expectedDeprecation Setting the "bar" service after it's been initialized is deprecated since Symfony 3.3 and won't be supported anymore in Symfony 4.0. + * @expectedDeprecation The "bar" service is already initialized, replacing it is deprecated since Symfony 3.3 and will fail in 4.0. */ public function testOverrideServiceWhenUsingADumpedContainerAndServiceIsUsedFromAnotherOne() { From 87bd741f2d4f6b66f03b5856d6bafa9fa7e7f6c5 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Wed, 4 Oct 2017 16:43:22 +0200 Subject: [PATCH 1004/1099] [Console][HttpKernel] Handle new SHELL_VERBOSITY, also configures the default logger --- src/Symfony/Component/Console/Application.php | 21 ++++++++++++++++++- src/Symfony/Component/Console/CHANGELOG.md | 1 + .../Console/Tests/ApplicationTest.php | 7 +++++++ .../DependencyInjection/LoggerPass.php | 12 ++++------- src/Symfony/Component/HttpKernel/Kernel.php | 6 ++++++ .../Component/HttpKernel/Log/Logger.php | 17 +++++++++++++-- .../DependencyInjection/LoggerPassTest.php | 12 ----------- 7 files changed, 53 insertions(+), 23 deletions(-) diff --git a/src/Symfony/Component/Console/Application.php b/src/Symfony/Component/Console/Application.php index da9d803d1b66c..481a63e732d02 100644 --- a/src/Symfony/Component/Console/Application.php +++ b/src/Symfony/Component/Console/Application.php @@ -895,18 +895,37 @@ protected function configureIO(InputInterface $input, OutputInterface $output) } } + switch ($shellVerbosity = (int) getenv('SHELL_VERBOSITY')) { + case -1: $output->setVerbosity(OutputInterface::VERBOSITY_QUIET); break; + case 1: $output->setVerbosity(OutputInterface::VERBOSITY_VERBOSE); break; + case 2: $output->setVerbosity(OutputInterface::VERBOSITY_VERY_VERBOSE); break; + case 3: $output->setVerbosity(OutputInterface::VERBOSITY_DEBUG); break; + default: $shellVerbosity = 0; break; + } + if (true === $input->hasParameterOption(array('--quiet', '-q'), true)) { $output->setVerbosity(OutputInterface::VERBOSITY_QUIET); - $input->setInteractive(false); + $shellVerbosity = -1; } else { if ($input->hasParameterOption('-vvv', true) || $input->hasParameterOption('--verbose=3', true) || 3 === $input->getParameterOption('--verbose', false, true)) { $output->setVerbosity(OutputInterface::VERBOSITY_DEBUG); + $shellVerbosity = 3; } elseif ($input->hasParameterOption('-vv', true) || $input->hasParameterOption('--verbose=2', true) || 2 === $input->getParameterOption('--verbose', false, true)) { $output->setVerbosity(OutputInterface::VERBOSITY_VERY_VERBOSE); + $shellVerbosity = 2; } elseif ($input->hasParameterOption('-v', true) || $input->hasParameterOption('--verbose=1', true) || $input->hasParameterOption('--verbose', true) || $input->getParameterOption('--verbose', false, true)) { $output->setVerbosity(OutputInterface::VERBOSITY_VERBOSE); + $shellVerbosity = 1; } } + + if (-1 === $shellVerbosity) { + $input->setInteractive(false); + } + + putenv('SHELL_VERBOSITY='.$shellVerbosity); + $_ENV['SHELL_VERBOSITY'] = $shellVerbosity; + $_SERVER['SHELL_VERBOSITY'] = $shellVerbosity; } /** diff --git a/src/Symfony/Component/Console/CHANGELOG.md b/src/Symfony/Component/Console/CHANGELOG.md index 24d7ff7af40e0..946ff1e0ba08f 100644 --- a/src/Symfony/Component/Console/CHANGELOG.md +++ b/src/Symfony/Component/Console/CHANGELOG.md @@ -4,6 +4,7 @@ CHANGELOG 3.4.0 ----- + * added `SHELL_VERBOSITY` env var to control verbosity * added `CommandLoaderInterface`, `FactoryCommandLoader` and PSR-11 `ContainerCommandLoader` for commands lazy-loading * added a case-insensitive command name matching fallback diff --git a/src/Symfony/Component/Console/Tests/ApplicationTest.php b/src/Symfony/Component/Console/Tests/ApplicationTest.php index d96f5e98f8850..396c35c733d0e 100644 --- a/src/Symfony/Component/Console/Tests/ApplicationTest.php +++ b/src/Symfony/Component/Console/Tests/ApplicationTest.php @@ -1580,6 +1580,13 @@ public function testErrorIsRethrownIfNotHandledByConsoleErrorEventWithCatchingEn $this->assertSame($e->getMessage(), 'Class \'UnknownClass\' not found'); } } + + protected function tearDown() + { + putenv('SHELL_VERBOSITY'); + unset($_ENV['SHELL_VERBOSITY']); + unset($_SERVER['SHELL_VERBOSITY']); + } } class CustomApplication extends Application diff --git a/src/Symfony/Component/HttpKernel/DependencyInjection/LoggerPass.php b/src/Symfony/Component/HttpKernel/DependencyInjection/LoggerPass.php index 2cffb99b321ec..2ad7f322289f3 100644 --- a/src/Symfony/Component/HttpKernel/DependencyInjection/LoggerPass.php +++ b/src/Symfony/Component/HttpKernel/DependencyInjection/LoggerPass.php @@ -12,7 +12,6 @@ namespace Symfony\Component\HttpKernel\DependencyInjection; use Psr\Log\LoggerInterface; -use Psr\Log\LogLevel; use Symfony\Component\HttpKernel\Log\Logger; use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; use Symfony\Component\DependencyInjection\ContainerBuilder; @@ -29,17 +28,14 @@ class LoggerPass implements CompilerPassInterface */ public function process(ContainerBuilder $container) { - $alias = $container->setAlias(LoggerInterface::class, 'logger'); - $alias->setPublic(false); + $container->setAlias(LoggerInterface::class, 'logger') + ->setPublic(false); if ($container->has('logger')) { return; } - $loggerDefinition = $container->register('logger', Logger::class); - $loggerDefinition->setPublic(false); - if ($container->getParameter('kernel.debug')) { - $loggerDefinition->addArgument(LogLevel::DEBUG); - } + $container->register('logger', Logger::class) + ->setPublic(false); } } diff --git a/src/Symfony/Component/HttpKernel/Kernel.php b/src/Symfony/Component/HttpKernel/Kernel.php index 986b7cbcd640a..6f4f2b72b63b7 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -177,6 +177,12 @@ public function shutdown() public function handle(Request $request, $type = HttpKernelInterface::MASTER_REQUEST, $catch = true) { if (false === $this->booted) { + if ($this->debug && !isset($_SERVER['SHELL_VERBOSITY'])) { + putenv('SHELL_VERBOSITY=3'); + $_ENV['SHELL_VERBOSITY'] = 3; + $_SERVER['SHELL_VERBOSITY'] = 3; + } + $this->boot(); } diff --git a/src/Symfony/Component/HttpKernel/Log/Logger.php b/src/Symfony/Component/HttpKernel/Log/Logger.php index cf20ca258a322..c43936ed40943 100644 --- a/src/Symfony/Component/HttpKernel/Log/Logger.php +++ b/src/Symfony/Component/HttpKernel/Log/Logger.php @@ -37,15 +37,28 @@ class Logger extends AbstractLogger private $formatter; private $handle; - public function __construct($minLevel = LogLevel::WARNING, $output = 'php://stderr', callable $formatter = null) + public function __construct($minLevel = null, $output = 'php://stderr', callable $formatter = null) { + if (!$minLevel) { + $minLevel = LogLevel::WARNING; + + if (isset($_SERVER['SHELL_VERBOSITY'])) { + switch ((int) $_SERVER['SHELL_VERBOSITY']) { + case -1: $minLevel = LogLevel::ERROR; break; + case 1: $minLevel = LogLevel::NOTICE; break; + case 2: $minLevel = LogLevel::INFO; break; + case 3: $minLevel = LogLevel::DEBUG; break; + } + } + } + if (!isset(self::$levels[$minLevel])) { throw new InvalidArgumentException(sprintf('The log level "%s" does not exist.', $minLevel)); } $this->minLevelIndex = self::$levels[$minLevel]; $this->formatter = $formatter ?: array($this, 'format'); - if (false === $this->handle = @fopen($output, 'a')) { + if (false === $this->handle = is_resource($output) ? $output : @fopen($output, 'a')) { throw new InvalidArgumentException(sprintf('Unable to open "%s".', $output)); } } diff --git a/src/Symfony/Component/HttpKernel/Tests/DependencyInjection/LoggerPassTest.php b/src/Symfony/Component/HttpKernel/Tests/DependencyInjection/LoggerPassTest.php index d018929b2a830..b199e11dabe75 100644 --- a/src/Symfony/Component/HttpKernel/Tests/DependencyInjection/LoggerPassTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/DependencyInjection/LoggerPassTest.php @@ -13,7 +13,6 @@ use PHPUnit\Framework\TestCase; use Psr\Log\LoggerInterface; -use Psr\Log\LogLevel; use Symfony\Component\HttpKernel\DependencyInjection\LoggerPass; use Symfony\Component\HttpKernel\Log\Logger; use Symfony\Component\DependencyInjection\ContainerBuilder; @@ -54,15 +53,4 @@ public function testRegisterLogger() $this->assertSame(Logger::class, $definition->getClass()); $this->assertFalse($definition->isPublic()); } - - public function testSetMinLevelWhenDebugging() - { - $container = new ContainerBuilder(); - $container->setParameter('kernel.debug', true); - - (new LoggerPass())->process($container); - - $definition = $container->getDefinition('logger'); - $this->assertSame(LogLevel::DEBUG, $definition->getArgument(0)); - } } From 8c39bf7845c1517284cacd979db16a0abaf20c83 Mon Sep 17 00:00:00 2001 From: "Alexander M. Turek" Date: Thu, 5 Oct 2017 11:48:08 +0200 Subject: [PATCH 1005/1099] Reset profiler. --- UPGRADE-3.4.md | 14 +++++++-- UPGRADE-4.0.md | 10 +++++-- composer.json | 2 +- .../DataCollector/DoctrineDataCollector.php | 14 +++++++++ .../DoctrineDataCollectorTest.php | 14 +++++++++ src/Symfony/Bridge/Monolog/Logger.php | 10 +++++++ .../Monolog/Processor/DebugProcessor.php | 9 ++++++ .../Bridge/Monolog/Tests/LoggerTest.php | 13 ++++++++ .../Twig/DataCollector/TwigDataCollector.php | 10 +++++++ src/Symfony/Bridge/Twig/composer.json | 2 +- .../FrameworkExtension.php | 6 ++-- .../DataCollector/SecurityDataCollector.php | 8 +++++ .../DataCollector/CacheDataCollector.php | 9 ++++++ .../Component/EventDispatcher/CHANGELOG.md | 5 ++++ .../Debug/TraceableEventDispatcher.php | 5 ++++ .../TraceableEventDispatcherInterface.php | 2 ++ .../Debug/TraceableEventDispatcherTest.php | 15 ++++++++++ .../DataCollector/FormDataCollector.php | 16 ++++++---- .../DataCollector/FormDataCollectorTest.php | 30 +++++++++++++++++++ src/Symfony/Component/HttpKernel/CHANGELOG.md | 4 ++- .../DataCollector/AjaxDataCollector.php | 5 ++++ .../DataCollector/ConfigDataCollector.php | 8 +++++ .../DataCollector/DataCollectorInterface.php | 2 ++ .../DataCollector/EventDataCollector.php | 16 ++++++++++ .../DataCollector/ExceptionDataCollector.php | 8 +++++ .../DataCollector/LoggerDataCollector.php | 15 ++++++++++ .../DataCollector/MemoryDataCollector.php | 16 +++++++--- .../DataCollector/RequestDataCollector.php | 6 ++++ .../DataCollector/RouterDataCollector.php | 22 +++++++++----- .../DataCollector/TimeDataCollector.php | 8 +++++ .../HttpKernel/Log/DebugLoggerInterface.php | 2 ++ .../HttpKernel/Profiler/Profiler.php | 25 +++++++++++++++- .../ExceptionDataCollectorTest.php | 19 ++++++++++++ .../DataCollector/LoggerDataCollectorTest.php | 22 ++++++++++++-- .../DataCollector/CloneVarDataCollector.php | 5 ++++ .../Tests/Fixtures/TestEventDispatcher.php | 4 +++ .../Tests/Profiler/ProfilerTest.php | 14 +++++++++ .../TranslationDataCollector.php | 8 +++++ .../DataCollector/ValidatorDataCollector.php | 25 ++++++++++++---- .../ValidatorDataCollectorTest.php | 27 +++++++++++++++++ .../Validator/TraceableValidator.php | 8 +++-- 41 files changed, 426 insertions(+), 37 deletions(-) diff --git a/UPGRADE-3.4.md b/UPGRADE-3.4.md index e5b6434c37f4e..c0573eb219ab8 100644 --- a/UPGRADE-3.4.md +++ b/UPGRADE-3.4.md @@ -63,6 +63,12 @@ Debug * Support for stacked errors in the `ErrorHandler` is deprecated and will be removed in Symfony 4.0. +EventDispatcher +--------------- + + * Implementing `TraceableEventDispatcherInterface` without the `reset()` method + is deprecated and will be unsupported in 4.0. + Filesystem ---------- @@ -270,6 +276,10 @@ HttpKernel * The `Symfony\Component\HttpKernel\Config\EnvParametersResource` class has been deprecated and will be removed in 4.0. + * Implementing `DataCollectorInterface` without a `reset()` method has been deprecated and will be unsupported in 4.0. + + * Implementing `DebugLoggerInterface` without a `clear()` method has been deprecated and will be unsupported in 4.0. + * The `ChainCacheClearer::add()` method has been deprecated and will be removed in 4.0, inject the list of clearers as a constructor argument instead. @@ -320,11 +330,11 @@ SecurityBundle * Deprecated the HTTP digest authentication: `HttpDigestFactory` will be removed in 4.0. Use another authentication system like `http_basic` instead. - + * Deprecated setting the `switch_user.stateless` option to false when the firewall is `stateless`. Setting it to false will have no effect in 4.0. - * Not configuring explicitly the provider on a firewall is ambiguous when there is more than one registered provider. + * Not configuring explicitly the provider on a firewall is ambiguous when there is more than one registered provider. Using the first configured provider is deprecated since 3.4 and will throw an exception on 4.0. Explicitly configure the provider to use on your firewalls. diff --git a/UPGRADE-4.0.md b/UPGRADE-4.0.md index 2d2e04899c18b..5bc486f44f466 100644 --- a/UPGRADE-4.0.md +++ b/UPGRADE-4.0.md @@ -192,6 +192,8 @@ EventDispatcher * The `ContainerAwareEventDispatcher` class has been removed. Use `EventDispatcher` with closure factories instead. + * The `reset()` method has been added to `TraceableEventDispatcherInterface`. + ExpressionLanguage ------------------ @@ -611,6 +613,10 @@ HttpKernel * The `Symfony\Component\HttpKernel\Config\EnvParametersResource` class has been removed. + * The `reset()` method has been added to `Symfony\Component\HttpKernel\DataCollector\DataCollectorInterface`. + + * The `clear()` method has been added to `Symfony\Component\HttpKernel\Log\DebugLoggerInterface`. + * The `ChainCacheClearer::add()` method has been removed, inject the list of clearers as a constructor argument instead. @@ -693,10 +699,10 @@ SecurityBundle * Removed the HTTP digest authentication system. The `HttpDigestFactory` class has been removed. Use another authentication system like `http_basic` instead. - + * The `switch_user.stateless` option is now always true if the firewall is stateless. - * Not configuring explicitly the provider on a firewall is ambiguous when there is more than one registered provider. + * Not configuring explicitly the provider on a firewall is ambiguous when there is more than one registered provider. The first configured provider is not used anymore and an exception is thrown instead. Explicitly configure the provider to use on your firewalls. diff --git a/composer.json b/composer.json index 7b55e30efd330..373e4b6aca9c1 100644 --- a/composer.json +++ b/composer.json @@ -20,7 +20,7 @@ "ext-xml": "*", "doctrine/common": "~2.4", "fig/link-util": "^1.0", - "twig/twig": "~1.34|~2.4", + "twig/twig": "^1.35|^2.4.4", "psr/cache": "~1.0", "psr/container": "^1.0", "psr/link": "^1.0", diff --git a/src/Symfony/Bridge/Doctrine/DataCollector/DoctrineDataCollector.php b/src/Symfony/Bridge/Doctrine/DataCollector/DoctrineDataCollector.php index 62c6a2381a940..bca53ef4092b7 100644 --- a/src/Symfony/Bridge/Doctrine/DataCollector/DoctrineDataCollector.php +++ b/src/Symfony/Bridge/Doctrine/DataCollector/DoctrineDataCollector.php @@ -28,6 +28,10 @@ class DoctrineDataCollector extends DataCollector private $registry; private $connections; private $managers; + + /** + * @var DebugStack[] + */ private $loggers = array(); public function __construct(ManagerRegistry $registry) @@ -65,6 +69,16 @@ public function collect(Request $request, Response $response, \Exception $except ); } + public function reset() + { + $this->data = array(); + + foreach ($this->loggers as $logger) { + $logger->queries = array(); + $logger->currentQuery = 0; + } + } + public function getManagers() { return $this->data['managers']; diff --git a/src/Symfony/Bridge/Doctrine/Tests/DataCollector/DoctrineDataCollectorTest.php b/src/Symfony/Bridge/Doctrine/Tests/DataCollector/DoctrineDataCollectorTest.php index 8cbd2c3eacb3c..cc20869c7c5c6 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/DataCollector/DoctrineDataCollectorTest.php +++ b/src/Symfony/Bridge/Doctrine/Tests/DataCollector/DoctrineDataCollectorTest.php @@ -101,6 +101,20 @@ public function testCollectQueryWithNoParams() $this->assertTrue($collectedQueries['default'][1]['explainable']); } + public function testReset() + { + $queries = array( + array('sql' => 'SELECT * FROM table1', 'params' => array(), 'types' => array(), 'executionMS' => 1), + ); + $c = $this->createCollector($queries); + $c->collect(new Request(), new Response()); + + $c->reset(); + $c->collect(new Request(), new Response()); + + $this->assertEquals(array('default' => array()), $c->getQueries()); + } + /** * @dataProvider paramProvider */ diff --git a/src/Symfony/Bridge/Monolog/Logger.php b/src/Symfony/Bridge/Monolog/Logger.php index ec6434fe791b8..7cd75c5ec11ca 100644 --- a/src/Symfony/Bridge/Monolog/Logger.php +++ b/src/Symfony/Bridge/Monolog/Logger.php @@ -45,6 +45,16 @@ public function countErrors() return 0; } + /** + * {@inheritdoc} + */ + public function clear() + { + if (($logger = $this->getDebugLogger()) && method_exists($logger, 'clear')) { + $logger->clear(); + } + } + /** * Returns a DebugLoggerInterface instance if one is registered with this logger. * diff --git a/src/Symfony/Bridge/Monolog/Processor/DebugProcessor.php b/src/Symfony/Bridge/Monolog/Processor/DebugProcessor.php index 22a4faac5cc9a..8774045192f3b 100644 --- a/src/Symfony/Bridge/Monolog/Processor/DebugProcessor.php +++ b/src/Symfony/Bridge/Monolog/Processor/DebugProcessor.php @@ -55,4 +55,13 @@ public function countErrors() { return $this->errorCount; } + + /** + * {@inheritdoc} + */ + public function clear() + { + $this->records = array(); + $this->errorCount = 0; + } } diff --git a/src/Symfony/Bridge/Monolog/Tests/LoggerTest.php b/src/Symfony/Bridge/Monolog/Tests/LoggerTest.php index c24c7a4133baf..a5fab0583c749 100644 --- a/src/Symfony/Bridge/Monolog/Tests/LoggerTest.php +++ b/src/Symfony/Bridge/Monolog/Tests/LoggerTest.php @@ -128,4 +128,17 @@ public function testGetLogsWithDebugProcessor2() $this->assertEquals('test', $record['message']); $this->assertEquals(Logger::INFO, $record['priority']); } + + public function testClear() + { + $handler = new TestHandler(); + $logger = new Logger('test', array($handler)); + $logger->pushProcessor(new DebugProcessor()); + + $logger->addInfo('test'); + $logger->clear(); + + $this->assertEmpty($logger->getLogs()); + $this->assertSame(0, $logger->countErrors()); + } } diff --git a/src/Symfony/Bridge/Twig/DataCollector/TwigDataCollector.php b/src/Symfony/Bridge/Twig/DataCollector/TwigDataCollector.php index d5efaa805362c..66f2a764e7617 100644 --- a/src/Symfony/Bridge/Twig/DataCollector/TwigDataCollector.php +++ b/src/Symfony/Bridge/Twig/DataCollector/TwigDataCollector.php @@ -44,6 +44,16 @@ public function collect(Request $request, Response $response, \Exception $except { } + /** + * {@inheritdoc} + */ + public function reset() + { + $this->profile->reset(); + $this->computed = null; + $this->data = array(); + } + /** * {@inheritdoc} */ diff --git a/src/Symfony/Bridge/Twig/composer.json b/src/Symfony/Bridge/Twig/composer.json index e1e86408cff33..bf4deb3f6e787 100644 --- a/src/Symfony/Bridge/Twig/composer.json +++ b/src/Symfony/Bridge/Twig/composer.json @@ -17,7 +17,7 @@ ], "require": { "php": "^5.5.9|>=7.0.8", - "twig/twig": "~1.34|~2.4" + "twig/twig": "^1.35|^2.4.4" }, "require-dev": { "fig/link-util": "^1.0", diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php index 0e136bfe436f7..90673719814b5 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php @@ -609,9 +609,9 @@ private function registerProfilerConfiguration(array $config, ContainerBuilder $ } } - if (!$config['collect']) { - $container->getDefinition('profiler')->addMethodCall('disable', array()); - } + $container->getDefinition('profiler') + ->addArgument($config['collect']) + ->addTag('kernel.reset', array('method' => 'reset')); } /** diff --git a/src/Symfony/Bundle/SecurityBundle/DataCollector/SecurityDataCollector.php b/src/Symfony/Bundle/SecurityBundle/DataCollector/SecurityDataCollector.php index fbd146452f26d..086cea89d9620 100644 --- a/src/Symfony/Bundle/SecurityBundle/DataCollector/SecurityDataCollector.php +++ b/src/Symfony/Bundle/SecurityBundle/DataCollector/SecurityDataCollector.php @@ -203,6 +203,14 @@ public function collect(Request $request, Response $response, \Exception $except } } + /** + * {@inheritdoc} + */ + public function reset() + { + $this->data = array(); + } + public function lateCollect() { $this->data = $this->cloneVar($this->data); diff --git a/src/Symfony/Component/Cache/DataCollector/CacheDataCollector.php b/src/Symfony/Component/Cache/DataCollector/CacheDataCollector.php index 07ddaf3f4790a..62d502f01fd6b 100644 --- a/src/Symfony/Component/Cache/DataCollector/CacheDataCollector.php +++ b/src/Symfony/Component/Cache/DataCollector/CacheDataCollector.php @@ -53,6 +53,15 @@ public function collect(Request $request, Response $response, \Exception $except $this->data['total']['statistics'] = $this->calculateTotalStatistics(); } + public function reset() + { + $this->data = array(); + foreach ($this->instances as $instance) { + // Calling getCalls() will clear the calls. + $instance->getCalls(); + } + } + public function lateCollect() { $this->data = $this->cloneVar($this->data); diff --git a/src/Symfony/Component/EventDispatcher/CHANGELOG.md b/src/Symfony/Component/EventDispatcher/CHANGELOG.md index 736bd84903b4b..c6aa5389ac724 100644 --- a/src/Symfony/Component/EventDispatcher/CHANGELOG.md +++ b/src/Symfony/Component/EventDispatcher/CHANGELOG.md @@ -1,6 +1,11 @@ CHANGELOG ========= +3.4.0 +----- + + * Implementing `TraceableEventDispatcherInterface` without the `reset()` method has been deprecated. + 3.3.0 ----- diff --git a/src/Symfony/Component/EventDispatcher/Debug/TraceableEventDispatcher.php b/src/Symfony/Component/EventDispatcher/Debug/TraceableEventDispatcher.php index 3f1035e13dd98..2fb795f77b246 100644 --- a/src/Symfony/Component/EventDispatcher/Debug/TraceableEventDispatcher.php +++ b/src/Symfony/Component/EventDispatcher/Debug/TraceableEventDispatcher.php @@ -212,6 +212,11 @@ public function getNotCalledListeners() return $notCalled; } + public function reset() + { + $this->called = array(); + } + /** * Proxies all method calls to the original event dispatcher. * diff --git a/src/Symfony/Component/EventDispatcher/Debug/TraceableEventDispatcherInterface.php b/src/Symfony/Component/EventDispatcher/Debug/TraceableEventDispatcherInterface.php index 5483e815068c4..f0212753be591 100644 --- a/src/Symfony/Component/EventDispatcher/Debug/TraceableEventDispatcherInterface.php +++ b/src/Symfony/Component/EventDispatcher/Debug/TraceableEventDispatcherInterface.php @@ -15,6 +15,8 @@ /** * @author Fabien Potencier + * + * @method reset() Resets the trace. */ interface TraceableEventDispatcherInterface extends EventDispatcherInterface { diff --git a/src/Symfony/Component/EventDispatcher/Tests/Debug/TraceableEventDispatcherTest.php b/src/Symfony/Component/EventDispatcher/Tests/Debug/TraceableEventDispatcherTest.php index a1cf6708b3a56..53a3421afaf6a 100644 --- a/src/Symfony/Component/EventDispatcher/Tests/Debug/TraceableEventDispatcherTest.php +++ b/src/Symfony/Component/EventDispatcher/Tests/Debug/TraceableEventDispatcherTest.php @@ -124,6 +124,21 @@ public function testGetCalledListeners() $this->assertEquals(array(), $tdispatcher->getNotCalledListeners()); } + public function testClearCalledListeners() + { + $tdispatcher = new TraceableEventDispatcher(new EventDispatcher(), new Stopwatch()); + $tdispatcher->addListener('foo', function () {}, 5); + + $tdispatcher->dispatch('foo'); + $tdispatcher->reset(); + + $listeners = $tdispatcher->getNotCalledListeners(); + $this->assertArrayHasKey('stub', $listeners['foo.closure']); + unset($listeners['foo.closure']['stub']); + $this->assertEquals(array(), $tdispatcher->getCalledListeners()); + $this->assertEquals(array('foo.closure' => array('event' => 'foo', 'pretty' => 'closure', 'priority' => 5)), $listeners); + } + public function testGetCalledListenersNested() { $tdispatcher = null; diff --git a/src/Symfony/Component/Form/Extension/DataCollector/FormDataCollector.php b/src/Symfony/Component/Form/Extension/DataCollector/FormDataCollector.php index 378edf563b972..db854b01bf7a0 100644 --- a/src/Symfony/Component/Form/Extension/DataCollector/FormDataCollector.php +++ b/src/Symfony/Component/Form/Extension/DataCollector/FormDataCollector.php @@ -72,12 +72,9 @@ class FormDataCollector extends DataCollector implements FormDataCollectorInterf public function __construct(FormDataExtractorInterface $dataExtractor) { $this->dataExtractor = $dataExtractor; - $this->data = array( - 'forms' => array(), - 'forms_by_hash' => array(), - 'nb_errors' => 0, - ); $this->hasVarDumper = class_exists(ClassStub::class); + + $this->reset(); } /** @@ -87,6 +84,15 @@ public function collect(Request $request, Response $response, \Exception $except { } + public function reset() + { + $this->data = array( + 'forms' => array(), + 'forms_by_hash' => array(), + 'nb_errors' => 0, + ); + } + /** * {@inheritdoc} */ diff --git a/src/Symfony/Component/Form/Tests/Extension/DataCollector/FormDataCollectorTest.php b/src/Symfony/Component/Form/Tests/Extension/DataCollector/FormDataCollectorTest.php index 24c0f8e871da1..7e591d414e456 100644 --- a/src/Symfony/Component/Form/Tests/Extension/DataCollector/FormDataCollectorTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/DataCollector/FormDataCollectorTest.php @@ -695,6 +695,36 @@ public function testCollectSubmittedDataExpandedFormsErrors() $this->assertFalse(isset($child21Data['has_children_error']), 'The leaf data does not contains "has_children_error" property.'); } + public function testReset() + { + $form = $this->createForm('my_form'); + + $this->dataExtractor->expects($this->any()) + ->method('extractConfiguration') + ->will($this->returnValue(array())); + $this->dataExtractor->expects($this->any()) + ->method('extractDefaultData') + ->will($this->returnValue(array())); + $this->dataExtractor->expects($this->any()) + ->method('extractSubmittedData') + ->with($form) + ->will($this->returnValue(array('errors' => array('baz')))); + + $this->dataCollector->buildPreliminaryFormTree($form); + $this->dataCollector->collectSubmittedData($form); + + $this->dataCollector->reset(); + + $this->assertSame( + array( + 'forms' => array(), + 'forms_by_hash' => array(), + 'nb_errors' => 0, + ), + $this->dataCollector->getData() + ); + } + private function createForm($name) { $builder = new FormBuilder($name, null, $this->dispatcher, $this->factory); diff --git a/src/Symfony/Component/HttpKernel/CHANGELOG.md b/src/Symfony/Component/HttpKernel/CHANGELOG.md index 1da376f7ad36c..fb29f76962928 100644 --- a/src/Symfony/Component/HttpKernel/CHANGELOG.md +++ b/src/Symfony/Component/HttpKernel/CHANGELOG.md @@ -14,7 +14,9 @@ CHANGELOG * deprecated the `ChainCacheClearer::add()` method * deprecated the `CacheaWarmerAggregate::add()` and `setWarmers()` methods * made `CacheWarmerAggregate` and `ChainCacheClearer` classes final - + * added the possibility to reset the profiler to its initial state + * deprecated data collectors without a `reset()` method + * deprecated implementing `DebugLoggerInterface` without a `clear()` method 3.3.0 ----- diff --git a/src/Symfony/Component/HttpKernel/DataCollector/AjaxDataCollector.php b/src/Symfony/Component/HttpKernel/DataCollector/AjaxDataCollector.php index b8405d5945af0..370a874fe5d5c 100644 --- a/src/Symfony/Component/HttpKernel/DataCollector/AjaxDataCollector.php +++ b/src/Symfony/Component/HttpKernel/DataCollector/AjaxDataCollector.php @@ -26,6 +26,11 @@ public function collect(Request $request, Response $response, \Exception $except // all collecting is done client side } + public function reset() + { + // all collecting is done client side + } + public function getName() { return 'ajax'; diff --git a/src/Symfony/Component/HttpKernel/DataCollector/ConfigDataCollector.php b/src/Symfony/Component/HttpKernel/DataCollector/ConfigDataCollector.php index 965342191b4cf..0a6aa82b263bd 100644 --- a/src/Symfony/Component/HttpKernel/DataCollector/ConfigDataCollector.php +++ b/src/Symfony/Component/HttpKernel/DataCollector/ConfigDataCollector.php @@ -95,6 +95,14 @@ public function collect(Request $request, Response $response, \Exception $except } } + /** + * {@inheritdoc} + */ + public function reset() + { + $this->data = array(); + } + public function lateCollect() { $this->data = $this->cloneVar($this->data); diff --git a/src/Symfony/Component/HttpKernel/DataCollector/DataCollectorInterface.php b/src/Symfony/Component/HttpKernel/DataCollector/DataCollectorInterface.php index 2820ad5b289b5..c0a0c0a982b3b 100644 --- a/src/Symfony/Component/HttpKernel/DataCollector/DataCollectorInterface.php +++ b/src/Symfony/Component/HttpKernel/DataCollector/DataCollectorInterface.php @@ -18,6 +18,8 @@ * DataCollectorInterface. * * @author Fabien Potencier + * + * @method reset() Resets this data collector to its initial state. */ interface DataCollectorInterface { diff --git a/src/Symfony/Component/HttpKernel/DataCollector/EventDataCollector.php b/src/Symfony/Component/HttpKernel/DataCollector/EventDataCollector.php index 3d75f322d831b..ab44405edb2e7 100644 --- a/src/Symfony/Component/HttpKernel/DataCollector/EventDataCollector.php +++ b/src/Symfony/Component/HttpKernel/DataCollector/EventDataCollector.php @@ -27,6 +27,9 @@ class EventDataCollector extends DataCollector implements LateDataCollectorInter public function __construct(EventDispatcherInterface $dispatcher = null) { + if ($dispatcher instanceof TraceableEventDispatcherInterface && !method_exists($dispatcher, 'reset')) { + @trigger_error(sprintf('Implementing "%s" without the "reset()" method is deprecated since version 3.4 and will be unsupported in 4.0 for class "%s".', TraceableEventDispatcherInterface::class, \get_class($dispatcher)), E_USER_DEPRECATED); + } $this->dispatcher = $dispatcher; } @@ -41,6 +44,19 @@ public function collect(Request $request, Response $response, \Exception $except ); } + public function reset() + { + $this->data = array(); + + if ($this->dispatcher instanceof TraceableEventDispatcherInterface) { + if (!method_exists($this->dispatcher, 'reset')) { + return; // @deprecated + } + + $this->dispatcher->reset(); + } + } + public function lateCollect() { if ($this->dispatcher instanceof TraceableEventDispatcherInterface) { diff --git a/src/Symfony/Component/HttpKernel/DataCollector/ExceptionDataCollector.php b/src/Symfony/Component/HttpKernel/DataCollector/ExceptionDataCollector.php index 9fe826446b195..7a25f149215b8 100644 --- a/src/Symfony/Component/HttpKernel/DataCollector/ExceptionDataCollector.php +++ b/src/Symfony/Component/HttpKernel/DataCollector/ExceptionDataCollector.php @@ -34,6 +34,14 @@ public function collect(Request $request, Response $response, \Exception $except } } + /** + * {@inheritdoc} + */ + public function reset() + { + $this->data = array(); + } + /** * Checks if the exception is not null. * diff --git a/src/Symfony/Component/HttpKernel/DataCollector/LoggerDataCollector.php b/src/Symfony/Component/HttpKernel/DataCollector/LoggerDataCollector.php index 92fd0da71e648..ee645d53e8fdb 100644 --- a/src/Symfony/Component/HttpKernel/DataCollector/LoggerDataCollector.php +++ b/src/Symfony/Component/HttpKernel/DataCollector/LoggerDataCollector.php @@ -29,6 +29,10 @@ class LoggerDataCollector extends DataCollector implements LateDataCollectorInte public function __construct($logger = null, $containerPathPrefix = null) { if (null !== $logger && $logger instanceof DebugLoggerInterface) { + if (!method_exists($logger, 'clear')) { + @trigger_error(sprintf('Implementing "%s" without the "clear()" method is deprecated since version 3.4 and will be unsupported in 4.0 for class "%s".', DebugLoggerInterface::class, \get_class($logger)), E_USER_DEPRECATED); + } + $this->logger = $logger; } @@ -43,6 +47,17 @@ public function collect(Request $request, Response $response, \Exception $except // everything is done as late as possible } + /** + * {@inheritdoc} + */ + public function reset() + { + if ($this->logger && method_exists($this->logger, 'clear')) { + $this->logger->clear(); + } + $this->data = array(); + } + /** * {@inheritdoc} */ diff --git a/src/Symfony/Component/HttpKernel/DataCollector/MemoryDataCollector.php b/src/Symfony/Component/HttpKernel/DataCollector/MemoryDataCollector.php index b7f61f46fd19b..8d8cc1a04d181 100644 --- a/src/Symfony/Component/HttpKernel/DataCollector/MemoryDataCollector.php +++ b/src/Symfony/Component/HttpKernel/DataCollector/MemoryDataCollector.php @@ -23,10 +23,7 @@ class MemoryDataCollector extends DataCollector implements LateDataCollectorInte { public function __construct() { - $this->data = array( - 'memory' => 0, - 'memory_limit' => $this->convertToBytes(ini_get('memory_limit')), - ); + $this->reset(); } /** @@ -37,6 +34,17 @@ public function collect(Request $request, Response $response, \Exception $except $this->updateMemoryUsage(); } + /** + * {@inheritdoc} + */ + public function reset() + { + $this->data = array( + 'memory' => 0, + 'memory_limit' => $this->convertToBytes(ini_get('memory_limit')), + ); + } + /** * {@inheritdoc} */ diff --git a/src/Symfony/Component/HttpKernel/DataCollector/RequestDataCollector.php b/src/Symfony/Component/HttpKernel/DataCollector/RequestDataCollector.php index 7049844f9ed5d..d27940266a8f1 100644 --- a/src/Symfony/Component/HttpKernel/DataCollector/RequestDataCollector.php +++ b/src/Symfony/Component/HttpKernel/DataCollector/RequestDataCollector.php @@ -156,6 +156,12 @@ public function lateCollect() $this->data = $this->cloneVar($this->data); } + public function reset() + { + $this->data = array(); + $this->controllers = new \SplObjectStorage(); + } + public function getMethod() { return $this->data['method']; diff --git a/src/Symfony/Component/HttpKernel/DataCollector/RouterDataCollector.php b/src/Symfony/Component/HttpKernel/DataCollector/RouterDataCollector.php index 76d962346175e..59f77c4ba29d8 100644 --- a/src/Symfony/Component/HttpKernel/DataCollector/RouterDataCollector.php +++ b/src/Symfony/Component/HttpKernel/DataCollector/RouterDataCollector.php @@ -23,17 +23,14 @@ */ class RouterDataCollector extends DataCollector { + /** + * @var \SplObjectStorage + */ protected $controllers; public function __construct() { - $this->controllers = new \SplObjectStorage(); - - $this->data = array( - 'redirect' => false, - 'url' => null, - 'route' => null, - ); + $this->reset(); } /** @@ -53,6 +50,17 @@ public function collect(Request $request, Response $response, \Exception $except unset($this->controllers[$request]); } + public function reset() + { + $this->controllers = new \SplObjectStorage(); + + $this->data = array( + 'redirect' => false, + 'url' => null, + 'route' => null, + ); + } + protected function guessRoute(Request $request, $controller) { return 'n/a'; diff --git a/src/Symfony/Component/HttpKernel/DataCollector/TimeDataCollector.php b/src/Symfony/Component/HttpKernel/DataCollector/TimeDataCollector.php index 2d39156e69e44..6588304935d3d 100644 --- a/src/Symfony/Component/HttpKernel/DataCollector/TimeDataCollector.php +++ b/src/Symfony/Component/HttpKernel/DataCollector/TimeDataCollector.php @@ -49,6 +49,14 @@ public function collect(Request $request, Response $response, \Exception $except ); } + /** + * {@inheritdoc} + */ + public function reset() + { + $this->data = array(); + } + /** * {@inheritdoc} */ diff --git a/src/Symfony/Component/HttpKernel/Log/DebugLoggerInterface.php b/src/Symfony/Component/HttpKernel/Log/DebugLoggerInterface.php index 5635a2184f007..f0606d3b0e5ee 100644 --- a/src/Symfony/Component/HttpKernel/Log/DebugLoggerInterface.php +++ b/src/Symfony/Component/HttpKernel/Log/DebugLoggerInterface.php @@ -15,6 +15,8 @@ * DebugLoggerInterface. * * @author Fabien Potencier + * + * @method clear() Removes all log records. */ interface DebugLoggerInterface { diff --git a/src/Symfony/Component/HttpKernel/Profiler/Profiler.php b/src/Symfony/Component/HttpKernel/Profiler/Profiler.php index 2580b4fffa002..85a71641be6fe 100644 --- a/src/Symfony/Component/HttpKernel/Profiler/Profiler.php +++ b/src/Symfony/Component/HttpKernel/Profiler/Profiler.php @@ -40,6 +40,11 @@ class Profiler */ private $logger; + /** + * @var bool + */ + private $initiallyEnabled = true; + /** * @var bool */ @@ -48,11 +53,13 @@ class Profiler /** * @param ProfilerStorageInterface $storage A ProfilerStorageInterface instance * @param LoggerInterface $logger A LoggerInterface instance + * @param bool $enable The initial enabled state */ - public function __construct(ProfilerStorageInterface $storage, LoggerInterface $logger = null) + public function __construct(ProfilerStorageInterface $storage, LoggerInterface $logger = null, $enable = true) { $this->storage = $storage; $this->logger = $logger; + $this->initiallyEnabled = $this->enabled = (bool) $enable; } /** @@ -188,6 +195,18 @@ public function collect(Request $request, Response $response, \Exception $except return $profile; } + public function reset() + { + foreach ($this->collectors as $collector) { + if (!method_exists($collector, 'reset')) { + continue; + } + + $collector->reset(); + } + $this->enabled = $this->initiallyEnabled; + } + /** * Gets the Collectors associated with this profiler. * @@ -218,6 +237,10 @@ public function set(array $collectors = array()) */ public function add(DataCollectorInterface $collector) { + if (!method_exists($collector, 'reset')) { + @trigger_error(sprintf('Implementing "%s" without the "reset()" method is deprecated since version 3.4 and will be unsupported in 4.0 for class "%s".', DataCollectorInterface::class, \get_class($collector)), E_USER_DEPRECATED); + } + $this->collectors[$collector->getName()] = $collector; } diff --git a/src/Symfony/Component/HttpKernel/Tests/DataCollector/ExceptionDataCollectorTest.php b/src/Symfony/Component/HttpKernel/Tests/DataCollector/ExceptionDataCollectorTest.php index afad9f58af638..178f1f01a3fc0 100644 --- a/src/Symfony/Component/HttpKernel/Tests/DataCollector/ExceptionDataCollectorTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/DataCollector/ExceptionDataCollectorTest.php @@ -37,4 +37,23 @@ public function testCollect() $this->assertSame('exception', $c->getName()); $this->assertSame($trace, $c->getTrace()); } + + public function testCollectWithoutException() + { + $c = new ExceptionDataCollector(); + $c->collect(new Request(), new Response()); + + $this->assertFalse($c->hasException()); + } + + public function testReset() + { + $c = new ExceptionDataCollector(); + + $c->collect(new Request(), new Response(), new \Exception()); + $c->reset(); + $c->collect(new Request(), new Response()); + + $this->assertFalse($c->hasException()); + } } diff --git a/src/Symfony/Component/HttpKernel/Tests/DataCollector/LoggerDataCollectorTest.php b/src/Symfony/Component/HttpKernel/Tests/DataCollector/LoggerDataCollectorTest.php index 62bf2c00c7586..3dec3bd7f87a0 100644 --- a/src/Symfony/Component/HttpKernel/Tests/DataCollector/LoggerDataCollectorTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/DataCollector/LoggerDataCollectorTest.php @@ -19,7 +19,10 @@ class LoggerDataCollectorTest extends TestCase { public function testCollectWithUnexpectedFormat() { - $logger = $this->getMockBuilder('Symfony\Component\HttpKernel\Log\DebugLoggerInterface')->getMock(); + $logger = $this + ->getMockBuilder('Symfony\Component\HttpKernel\Log\DebugLoggerInterface') + ->setMethods(array('countErrors', 'getLogs', 'clear')) + ->getMock(); $logger->expects($this->once())->method('countErrors')->will($this->returnValue('foo')); $logger->expects($this->exactly(2))->method('getLogs')->will($this->returnValue(array())); @@ -43,7 +46,10 @@ public function testCollectWithUnexpectedFormat() */ public function testCollect($nb, $logs, $expectedLogs, $expectedDeprecationCount, $expectedScreamCount, $expectedPriorities = null) { - $logger = $this->getMockBuilder('Symfony\Component\HttpKernel\Log\DebugLoggerInterface')->getMock(); + $logger = $this + ->getMockBuilder('Symfony\Component\HttpKernel\Log\DebugLoggerInterface') + ->setMethods(array('countErrors', 'getLogs', 'clear')) + ->getMock(); $logger->expects($this->once())->method('countErrors')->will($this->returnValue($nb)); $logger->expects($this->exactly(2))->method('getLogs')->will($this->returnValue($logs)); @@ -70,6 +76,18 @@ public function testCollect($nb, $logs, $expectedLogs, $expectedDeprecationCount } } + public function testReset() + { + $logger = $this + ->getMockBuilder('Symfony\Component\HttpKernel\Log\DebugLoggerInterface') + ->setMethods(array('countErrors', 'getLogs', 'clear')) + ->getMock(); + $logger->expects($this->once())->method('clear'); + + $c = new LoggerDataCollector($logger); + $c->reset(); + } + public function getCollectTestData() { yield 'simple log' => array( diff --git a/src/Symfony/Component/HttpKernel/Tests/Fixtures/DataCollector/CloneVarDataCollector.php b/src/Symfony/Component/HttpKernel/Tests/Fixtures/DataCollector/CloneVarDataCollector.php index 867ccdce57892..89dec36af4110 100644 --- a/src/Symfony/Component/HttpKernel/Tests/Fixtures/DataCollector/CloneVarDataCollector.php +++ b/src/Symfony/Component/HttpKernel/Tests/Fixtures/DataCollector/CloneVarDataCollector.php @@ -29,6 +29,11 @@ public function collect(Request $request, Response $response, \Exception $except $this->data = $this->cloneVar($this->varToClone); } + public function reset() + { + $this->data = array(); + } + public function getData() { return $this->data; diff --git a/src/Symfony/Component/HttpKernel/Tests/Fixtures/TestEventDispatcher.php b/src/Symfony/Component/HttpKernel/Tests/Fixtures/TestEventDispatcher.php index da7ef5bd60381..ca2e6a693da6e 100644 --- a/src/Symfony/Component/HttpKernel/Tests/Fixtures/TestEventDispatcher.php +++ b/src/Symfony/Component/HttpKernel/Tests/Fixtures/TestEventDispatcher.php @@ -25,4 +25,8 @@ public function getNotCalledListeners() { return array('bar'); } + + public function reset() + { + } } diff --git a/src/Symfony/Component/HttpKernel/Tests/Profiler/ProfilerTest.php b/src/Symfony/Component/HttpKernel/Tests/Profiler/ProfilerTest.php index 1a6f54636a508..243c3c5c5a7cb 100644 --- a/src/Symfony/Component/HttpKernel/Tests/Profiler/ProfilerTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/Profiler/ProfilerTest.php @@ -12,6 +12,7 @@ namespace Symfony\Component\HttpKernel\Tests\Profiler; use PHPUnit\Framework\TestCase; +use Symfony\Component\HttpKernel\DataCollector\DataCollectorInterface; use Symfony\Component\HttpKernel\DataCollector\RequestDataCollector; use Symfony\Component\HttpKernel\Profiler\FileProfilerStorage; use Symfony\Component\HttpKernel\Profiler\Profiler; @@ -40,6 +41,19 @@ public function testCollect() $this->assertSame('bar', $profile->getCollector('request')->getRequestQuery()->all()['foo']->getValue()); } + public function testReset() + { + $collector = $this->getMockBuilder(DataCollectorInterface::class) + ->setMethods(['collect', 'getName', 'reset']) + ->getMock(); + $collector->expects($this->any())->method('getName')->willReturn('mock'); + $collector->expects($this->once())->method('reset'); + + $profiler = new Profiler($this->storage); + $profiler->add($collector); + $profiler->reset(); + } + public function testFindWorksWithDates() { $profiler = new Profiler($this->storage); diff --git a/src/Symfony/Component/Translation/DataCollector/TranslationDataCollector.php b/src/Symfony/Component/Translation/DataCollector/TranslationDataCollector.php index 1696fc71ffeea..da45cce31e659 100644 --- a/src/Symfony/Component/Translation/DataCollector/TranslationDataCollector.php +++ b/src/Symfony/Component/Translation/DataCollector/TranslationDataCollector.php @@ -58,6 +58,14 @@ public function collect(Request $request, Response $response, \Exception $except { } + /** + * {@inheritdoc} + */ + public function reset() + { + $this->data = array(); + } + /** * @return array */ diff --git a/src/Symfony/Component/Validator/DataCollector/ValidatorDataCollector.php b/src/Symfony/Component/Validator/DataCollector/ValidatorDataCollector.php index d2b3f4626264c..aa8c61f96bff9 100644 --- a/src/Symfony/Component/Validator/DataCollector/ValidatorDataCollector.php +++ b/src/Symfony/Component/Validator/DataCollector/ValidatorDataCollector.php @@ -19,6 +19,7 @@ use Symfony\Component\Validator\Validator\TraceableValidator; use Symfony\Component\VarDumper\Caster\Caster; use Symfony\Component\VarDumper\Caster\ClassStub; +use Symfony\Component\VarDumper\Cloner\Data; use Symfony\Component\VarDumper\Cloner\Stub; /** @@ -31,10 +32,7 @@ class ValidatorDataCollector extends DataCollector implements LateDataCollectorI public function __construct(TraceableValidator $validator) { $this->validator = $validator; - $this->data = array( - 'calls' => array(), - 'violations_count' => 0, - ); + $this->reset(); } /** @@ -45,6 +43,15 @@ public function collect(Request $request, Response $response, \Exception $except // Everything is collected once, on kernel terminate. } + public function reset() + { + $this->validator->reset(); + $this->data = array( + 'calls' => $this->cloneVar(array()), + 'violations_count' => 0, + ); + } + /** * {@inheritdoc} */ @@ -52,16 +59,22 @@ public function lateCollect() { $collected = $this->validator->getCollectedData(); $this->data['calls'] = $this->cloneVar($collected); - $this->data['violations_count'] += array_reduce($collected, function ($previous, $item) { - return $previous += count($item['violations']); + $this->data['violations_count'] = array_reduce($collected, function ($previous, $item) { + return $previous + count($item['violations']); }, 0); } + /** + * @return Data + */ public function getCalls() { return $this->data['calls']; } + /** + * @return int + */ public function getViolationsCount() { return $this->data['violations_count']; diff --git a/src/Symfony/Component/Validator/Tests/DataCollector/ValidatorDataCollectorTest.php b/src/Symfony/Component/Validator/Tests/DataCollector/ValidatorDataCollectorTest.php index 811a55829a479..c078d283509c6 100644 --- a/src/Symfony/Component/Validator/Tests/DataCollector/ValidatorDataCollectorTest.php +++ b/src/Symfony/Component/Validator/Tests/DataCollector/ValidatorDataCollectorTest.php @@ -50,6 +50,33 @@ public function testCollectsValidatorCalls() $this->assertCount(2, $call['violations']); } + public function testReset() + { + $originalValidator = $this->createMock(ValidatorInterface::class); + $validator = new TraceableValidator($originalValidator); + + $collector = new ValidatorDataCollector($validator); + + $violations = new ConstraintViolationList(array( + $this->createMock(ConstraintViolation::class), + $this->createMock(ConstraintViolation::class), + )); + $originalValidator->method('validate')->willReturn($violations); + + $validator->validate(new \stdClass()); + + $collector->lateCollect(); + $collector->reset(); + + $this->assertCount(0, $collector->getCalls()); + $this->assertSame(0, $collector->getViolationsCount()); + + $collector->lateCollect(); + + $this->assertCount(0, $collector->getCalls()); + $this->assertSame(0, $collector->getViolationsCount()); + } + protected function createMock($classname) { return $this->getMockBuilder($classname)->disableOriginalConstructor()->getMock(); diff --git a/src/Symfony/Component/Validator/Validator/TraceableValidator.php b/src/Symfony/Component/Validator/Validator/TraceableValidator.php index 019559ae0023d..96134e2767468 100644 --- a/src/Symfony/Component/Validator/Validator/TraceableValidator.php +++ b/src/Symfony/Component/Validator/Validator/TraceableValidator.php @@ -11,7 +11,6 @@ namespace Symfony\Component\Validator\Validator; -use Symfony\Component\Validator\ConstraintViolationList; use Symfony\Component\Validator\Context\ExecutionContextInterface; /** @@ -30,13 +29,18 @@ public function __construct(ValidatorInterface $validator) } /** - * @return ConstraintViolationList[] + * @return array */ public function getCollectedData() { return $this->collectedData; } + public function reset() + { + $this->collectedData = array(); + } + /** * {@inheritdoc} */ From 78eecba780a059034028660ebb1ea81dcb8a511f Mon Sep 17 00:00:00 2001 From: Robin Chalas Date: Thu, 5 Oct 2017 09:59:11 +0200 Subject: [PATCH 1006/1099] Fix BC layer --- UPGRADE-3.4.md | 6 +- UPGRADE-4.0.md | 6 +- src/Symfony/Component/Security/CHANGELOG.md | 1 + .../Guard/AbstractGuardAuthenticator.php | 10 +- .../Security/Guard/AuthenticatorInterface.php | 121 +----------------- .../Firewall/GuardAuthenticationListener.php | 31 ++--- .../Guard/GuardAuthenticatorHandler.php | 8 +- .../Guard/GuardAuthenticatorInterface.php | 5 +- .../Provider/GuardAuthenticationProvider.php | 6 +- .../GuardAuthenticationListenerTest.php | 30 +++-- .../Tests/GuardAuthenticatorHandlerTest.php | 3 +- .../GuardAuthenticationProviderTest.php | 65 ++++++++++ 12 files changed, 122 insertions(+), 170 deletions(-) diff --git a/UPGRADE-3.4.md b/UPGRADE-3.4.md index 3996618fc18ff..c410d5c4cc44d 100644 --- a/UPGRADE-3.4.md +++ b/UPGRADE-3.4.md @@ -295,6 +295,9 @@ Security * Deprecated the HTTP digest authentication: `NonceExpiredException`, `DigestAuthenticationListener` and `DigestAuthenticationEntryPoint` will be removed in 4.0. Use another authentication system like `http_basic` instead. + + * The `GuardAuthenticatorInterface` has been deprecated and will be removed in 4.0. + Use `AuthenticatorInterface` instead. SecurityBundle -------------- @@ -302,9 +305,6 @@ SecurityBundle * Using voters that do not implement the `VoterInterface`is now deprecated in the `AccessDecisionManager` and this functionality will be removed in 4.0. - * Using guard authenticator that implement the `GuardAuthenticatorInterface` is now - deprecated, this will be removed in 4.0. `AuthenticatorInterface` must be used now. - * `FirewallContext::getListeners()` now returns `\Traversable|array` * `InitAclCommand::__construct()` now takes an instance of diff --git a/UPGRADE-4.0.md b/UPGRADE-4.0.md index a9a382b8e9d14..bd645e3444987 100644 --- a/UPGRADE-4.0.md +++ b/UPGRADE-4.0.md @@ -659,9 +659,6 @@ Security * The `RoleInterface` has been removed. Extend the `Symfony\Component\Security\Core\Role\Role` class instead. - * The `GuardAuthenticatorInterface` has been removed. Implement - `Symfony\Component\Security\Guard\AuthenticatorInterface` class instead. - * The `LogoutUrlGenerator::registerListener()` method expects a 6th `string $context = null` argument. * The `AccessDecisionManager::setVoters()` method has been removed. Pass the @@ -676,6 +673,9 @@ Security `DigestAuthenticationListener` and `DigestAuthenticationEntryPoint` classes have been removed. Use another authentication system like `http_basic` instead. + * The `GuardAuthenticatorInterface` interface has been removed. + Use `AuthenticatorInterface` instead. + SecurityBundle -------------- diff --git a/src/Symfony/Component/Security/CHANGELOG.md b/src/Symfony/Component/Security/CHANGELOG.md index 25e89572a557a..bd1b7b59eb793 100644 --- a/src/Symfony/Component/Security/CHANGELOG.md +++ b/src/Symfony/Component/Security/CHANGELOG.md @@ -15,6 +15,7 @@ CHANGELOG requests. * deprecated HTTP digest authentication * Added a new password encoder for the Argon2i hashing algorithm + * deprecated `GuardAuthenticatorInterface` in favor of `AuthenticatorInterface` 3.3.0 ----- diff --git a/src/Symfony/Component/Security/Guard/AbstractGuardAuthenticator.php b/src/Symfony/Component/Security/Guard/AbstractGuardAuthenticator.php index 97c9c4a0922d9..5eceb8470a567 100644 --- a/src/Symfony/Component/Security/Guard/AbstractGuardAuthenticator.php +++ b/src/Symfony/Component/Security/Guard/AbstractGuardAuthenticator.php @@ -23,17 +23,13 @@ abstract class AbstractGuardAuthenticator implements AuthenticatorInterface { /** - * Default implementation of the AuthenticatorInterface::supports method - * As we still have the deprecated GuardAuthenticatorInterface, this method must be implemented here - * Once GuardAuthenticatorInterface will be removed, this method should be removed too. + * {@inheritdoc} * - * @param Request $request - * - * @return bool + * @deprecated since version 3.4, to be removed in 4.0 */ public function supports(Request $request) { - @trigger_error('The Symfony\Component\Security\Guard\AbstractGuardAuthenticator::supports default implementation is used. This is provided for backward compatibility on GuardAuthenticationInterface that is deprecated since version 3.1 and will be removed in 4.0. Provide your own implementation of the supports method instead.', E_USER_DEPRECATED); + @trigger_error(sprintf('The "%s()" method is deprecated since version 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); return true; } diff --git a/src/Symfony/Component/Security/Guard/AuthenticatorInterface.php b/src/Symfony/Component/Security/Guard/AuthenticatorInterface.php index a1497b0eef4f9..f68b8d6f43b08 100644 --- a/src/Symfony/Component/Security/Guard/AuthenticatorInterface.php +++ b/src/Symfony/Component/Security/Guard/AuthenticatorInterface.php @@ -12,13 +12,6 @@ namespace Symfony\Component\Security\Guard; use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\Response; -use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; -use Symfony\Component\Security\Core\Exception\AuthenticationException; -use Symfony\Component\Security\Core\User\UserInterface; -use Symfony\Component\Security\Core\User\UserProviderInterface; -use Symfony\Component\Security\Guard\Token\GuardTokenInterface; -use Symfony\Component\Security\Http\EntryPoint\AuthenticationEntryPointInterface; /** * The interface for all "guard" authenticators. @@ -30,14 +23,12 @@ * @author Ryan Weaver * @author Amaury Leroux de Lens */ -interface AuthenticatorInterface extends AuthenticationEntryPointInterface +interface AuthenticatorInterface extends GuardAuthenticatorInterface { /** - * Does the authenticator support the given Request ? + * Does the authenticator support the given Request? * - * If this returns true, authentication will continue (e.g. getCredentials() will be called). - * If false, this authenticator is done. The next (if any) authenticators will be called and - * may authenticate the user, or leave the user as anonymous. + * If this returns false, the authenticator will be skipped. * * @param Request $request * @@ -47,8 +38,7 @@ public function supports(Request $request); /** * Get the authentication credentials from the request and return them - * as any type (e.g. an associate array). If you return null, authentication - * will be skipped. + * as any type (e.g. an associate array). * * Whatever value you return here will be passed to getUser() and checkCredentials() * @@ -65,106 +55,9 @@ public function supports(Request $request); * * @param Request $request * - * @return mixed|null - */ - public function getCredentials(Request $request); - - /** - * Return a UserInterface object based on the credentials. - * - * The *credentials* are the return value from getCredentials() - * - * You may throw an AuthenticationException if you wish. If you return - * null, then a UsernameNotFoundException is thrown for you. + * @return mixed Any non-null value * - * @param mixed $credentials - * @param UserProviderInterface $userProvider - * - * @throws AuthenticationException - * - * @return UserInterface|null + * @throws \UnexpectedValueException If null is returned */ - public function getUser($credentials, UserProviderInterface $userProvider); - - /** - * Returns true if the credentials are valid. - * - * If any value other than true is returned, authentication will - * fail. You may also throw an AuthenticationException if you wish - * to cause authentication to fail. - * - * The *credentials* are the return value from getCredentials() - * - * @param mixed $credentials - * @param UserInterface $user - * - * @return bool - * - * @throws AuthenticationException - */ - public function checkCredentials($credentials, UserInterface $user); - - /** - * Creates an authenticated token for the given user. - * - * If you don't care about which token class is used or don't really - * understand what a "token" is, you can skip this method by extending - * the AbstractGuardAuthenticator class from your authenticator. - * - * @see AbstractGuardAuthenticator - * - * @param UserInterface $user - * @param string $providerKey The provider (i.e. firewall) key - * - * @return GuardTokenInterface - */ - 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. - * - * If you return null, the request will continue, but the user will - * not be authenticated. This is probably not what you want to do. - * - * @param Request $request - * @param AuthenticationException $exception - * - * @return Response|null - */ - public function onAuthenticationFailure(Request $request, AuthenticationException $exception); - - /** - * Called when authentication executed and was successful! - * - * This should return the Response sent back to the user, like a - * RedirectResponse to the last page they visited. - * - * If you return null, the current request will continue, and the user - * will be authenticated. This makes sense, for example, with an API. - * - * @param Request $request - * @param TokenInterface $token - * @param string $providerKey The provider (i.e. firewall) key - * - * @return Response|null - */ - public function onAuthenticationSuccess(Request $request, TokenInterface $token, $providerKey); - - /** - * Does this method support remember me cookies? - * - * Remember me cookie will be set if *all* of the following are met: - * A) This method returns true - * B) The remember_me key under your firewall is configured - * C) The "remember me" functionality is activated. This is usually - * done by having a _remember_me checkbox in your form, but - * can be configured by the "always_remember_me" and "remember_me_parameter" - * parameters under the "remember_me" firewall key - * - * @return bool - */ - public function supportsRememberMe(); + public function getCredentials(Request $request); } diff --git a/src/Symfony/Component/Security/Guard/Firewall/GuardAuthenticationListener.php b/src/Symfony/Component/Security/Guard/Firewall/GuardAuthenticationListener.php index dd5ae2c16b9f4..4ec0b8f32630d 100644 --- a/src/Symfony/Component/Security/Guard/Firewall/GuardAuthenticationListener.php +++ b/src/Symfony/Component/Security/Guard/Firewall/GuardAuthenticationListener.php @@ -15,9 +15,9 @@ use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\Event\GetResponseEvent; use Symfony\Component\Security\Guard\GuardAuthenticatorHandler; +use Symfony\Component\Security\Guard\GuardAuthenticatorInterface; use Symfony\Component\Security\Guard\Token\PreAuthenticationGuardToken; use Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface; -use Symfony\Component\Security\Guard\GuardAuthenticatorInterface; use Symfony\Component\Security\Guard\AuthenticatorInterface; use Psr\Log\LoggerInterface; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; @@ -94,7 +94,7 @@ public function handle(GetResponseEvent $event) } } - private function executeGuardAuthenticator($uniqueGuardKey, AuthenticatorInterface $guardAuthenticator, GetResponseEvent $event) + private function executeGuardAuthenticator($uniqueGuardKey, GuardAuthenticatorInterface $guardAuthenticator, GetResponseEvent $event) { $request = $event->getRequest(); try { @@ -102,38 +102,29 @@ private function executeGuardAuthenticator($uniqueGuardKey, AuthenticatorInterfa $this->logger->debug('Calling getCredentials() on guard configurator.', array('firewall_key' => $this->providerKey, 'authenticator' => get_class($guardAuthenticator))); } - // abort the execution of the authenticator if it doesn't support the request. - if ($guardAuthenticator instanceof GuardAuthenticatorInterface) { - // it's a GuardAuthenticatorInterface - // we support the previous behaviour to avoid BC break. - $credentialsCanBeNull = true; - @trigger_error('The Symfony\Component\Security\Guard\GuardAuthenticatorInterface interface is deprecated since version 3.1 and will be removed in 4.0. Use Symfony\Component\Security\Guard\Authenticator\GuardAuthenticatorInterface instead.', E_USER_DEPRECATED); - } else { - if (true !== $guardAuthenticator->supports($request)) { + // abort the execution of the authenticator if it doesn't support the request + if ($guardAuthenticator instanceof AuthenticatorInterface) { + if (!$guardAuthenticator->supports($request)) { return; } // as there was a support for given request, // authenticator is expected to give not-null credentials. $credentialsCanBeNull = false; + } else { + // deprecated since version 3.4, to be removed in 4.0 + $credentialsCanBeNull = true; } // allow the authenticator to fetch authentication info from the request $credentials = $guardAuthenticator->getCredentials($request); if (null === $credentials) { - // if GuardAuthenticatorInterface is used - // allow null to skip authentication. + // deprecated since version 3.4, to be removed in 4.0 if ($credentialsCanBeNull) { return; } - // otherwise something went wrong and the authentication must fail - throw new \UnexpectedValueException(sprintf( - 'You must return some credentials from %s:getCredentials(). - To skip authentication, return false from %s::supports().', - get_class($guardAuthenticator), - get_class($guardAuthenticator) - )); + throw new \UnexpectedValueException(sprintf('The return value of "%s::getCredentials()" must not be null. Return false from "%s::supports()" instead.', get_class($guardAuthenticator), get_class($guardAuthenticator))); } // create a token with the unique key, so that the provider knows which authenticator to use @@ -205,7 +196,7 @@ public function setRememberMeServices(RememberMeServicesInterface $rememberMeSer * @param TokenInterface $token * @param Response $response */ - private function triggerRememberMe(AuthenticatorInterface $guardAuthenticator, Request $request, TokenInterface $token, Response $response = null) + private function triggerRememberMe(GuardAuthenticatorInterface $guardAuthenticator, Request $request, TokenInterface $token, Response $response = null) { if (null === $this->rememberMeServices) { if (null !== $this->logger) { diff --git a/src/Symfony/Component/Security/Guard/GuardAuthenticatorHandler.php b/src/Symfony/Component/Security/Guard/GuardAuthenticatorHandler.php index c8fb6e394e992..abe263d888d5f 100644 --- a/src/Symfony/Component/Security/Guard/GuardAuthenticatorHandler.php +++ b/src/Symfony/Component/Security/Guard/GuardAuthenticatorHandler.php @@ -29,6 +29,8 @@ * can be called directly (e.g. for manual authentication) or overridden. * * @author Ryan Weaver + * + * @final since version 3.4 */ class GuardAuthenticatorHandler { @@ -68,7 +70,7 @@ public function authenticateWithToken(TokenInterface $token, Request $request) * * @return null|Response */ - public function handleAuthenticationSuccess(TokenInterface $token, Request $request, AuthenticatorInterface $guardAuthenticator, $providerKey) + public function handleAuthenticationSuccess(TokenInterface $token, Request $request, GuardAuthenticatorInterface $guardAuthenticator, $providerKey) { $response = $guardAuthenticator->onAuthenticationSuccess($request, $token, $providerKey); @@ -95,7 +97,7 @@ public function handleAuthenticationSuccess(TokenInterface $token, Request $requ * * @return Response|null */ - public function authenticateUserAndHandleSuccess(UserInterface $user, Request $request, AuthenticatorInterface $authenticator, $providerKey) + public function authenticateUserAndHandleSuccess(UserInterface $user, Request $request, GuardAuthenticatorInterface $authenticator, $providerKey) { // create an authenticated token for the User $token = $authenticator->createAuthenticatedToken($user, $providerKey); @@ -117,7 +119,7 @@ public function authenticateUserAndHandleSuccess(UserInterface $user, Request $r * * @return null|Response */ - public function handleAuthenticationFailure(AuthenticationException $authenticationException, Request $request, AuthenticatorInterface $guardAuthenticator, $providerKey) + public function handleAuthenticationFailure(AuthenticationException $authenticationException, Request $request, GuardAuthenticatorInterface $guardAuthenticator, $providerKey) { $token = $this->tokenStorage->getToken(); if ($token instanceof PostAuthenticationGuardToken && $providerKey === $token->getProviderKey()) { diff --git a/src/Symfony/Component/Security/Guard/GuardAuthenticatorInterface.php b/src/Symfony/Component/Security/Guard/GuardAuthenticatorInterface.php index 2078ad237b9e2..0d11573c03b11 100644 --- a/src/Symfony/Component/Security/Guard/GuardAuthenticatorInterface.php +++ b/src/Symfony/Component/Security/Guard/GuardAuthenticatorInterface.php @@ -18,6 +18,7 @@ use Symfony\Component\Security\Core\User\UserInterface; use Symfony\Component\Security\Core\User\UserProviderInterface; use Symfony\Component\Security\Guard\Token\GuardTokenInterface; +use Symfony\Component\Security\Http\EntryPoint\AuthenticationEntryPointInterface; /** * The interface for all "guard" authenticators. @@ -28,9 +29,9 @@ * * @author Ryan Weaver * - * @deprecated Symfony\Component\Security\Guard\AuthenticatorInterface must be used instead + * @deprecated since version 3.4, to be removed in 4.0. Use AuthenticatorInterface instead */ -interface GuardAuthenticatorInterface extends AuthenticatorInterface +interface GuardAuthenticatorInterface extends AuthenticationEntryPointInterface { /** * Get the authentication credentials from the request and return them diff --git a/src/Symfony/Component/Security/Guard/Provider/GuardAuthenticationProvider.php b/src/Symfony/Component/Security/Guard/Provider/GuardAuthenticationProvider.php index c93776a34857d..2f2678035fbcf 100644 --- a/src/Symfony/Component/Security/Guard/Provider/GuardAuthenticationProvider.php +++ b/src/Symfony/Component/Security/Guard/Provider/GuardAuthenticationProvider.php @@ -56,7 +56,7 @@ public function __construct($guardAuthenticators, UserProviderInterface $userPro /** * Finds the correct authenticator for the token and calls it. * - * @param TokenInterface|GuardTokenInterface $token + * @param GuardTokenInterface $token * * @return TokenInterface */ @@ -101,7 +101,7 @@ public function authenticate(TokenInterface $token) // instances that will be checked if you have multiple firewalls. } - private function authenticateViaGuard(AuthenticatorInterface $guardAuthenticator, PreAuthenticationGuardToken $token) + private function authenticateViaGuard($guardAuthenticator, PreAuthenticationGuardToken $token) { // get the user from the GuardAuthenticator $user = $guardAuthenticator->getUser($token->getCredentials(), $this->userProvider); @@ -142,6 +142,6 @@ private function authenticateViaGuard(AuthenticatorInterface $guardAuthenticator public function supports(TokenInterface $token) { - return $token instanceof TokenInterface; + return $token instanceof GuardTokenInterface; } } diff --git a/src/Symfony/Component/Security/Guard/Tests/Firewall/GuardAuthenticationListenerTest.php b/src/Symfony/Component/Security/Guard/Tests/Firewall/GuardAuthenticationListenerTest.php index 60f703904cffd..5af9f130f8645 100644 --- a/src/Symfony/Component/Security/Guard/Tests/Firewall/GuardAuthenticationListenerTest.php +++ b/src/Symfony/Component/Security/Guard/Tests/Firewall/GuardAuthenticationListenerTest.php @@ -14,7 +14,10 @@ use PHPUnit\Framework\TestCase; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; +use Symfony\Component\Security\Guard\AuthenticatorInterface; use Symfony\Component\Security\Guard\Firewall\GuardAuthenticationListener; +use Symfony\Component\Security\Guard\GuardAuthenticatorInterface; use Symfony\Component\Security\Guard\Token\PreAuthenticationGuardToken; use Symfony\Component\Security\Core\Exception\AuthenticationException; @@ -33,8 +36,8 @@ class GuardAuthenticationListenerTest extends TestCase public function testHandleSuccess() { - $authenticator = $this->getMockBuilder('Symfony\Component\Security\Guard\AuthenticatorInterface')->getMock(); - $authenticateToken = $this->getMockBuilder('Symfony\Component\Security\Core\Authentication\Token\TokenInterface')->getMock(); + $authenticator = $this->getMockBuilder(AuthenticatorInterface::class)->getMock(); + $authenticateToken = $this->getMockBuilder(TokenInterface::class)->getMock(); $providerKey = 'my_firewall'; $credentials = array('username' => 'weaverryan', 'password' => 'all_your_base'); @@ -88,8 +91,8 @@ public function testHandleSuccess() public function testHandleSuccessStopsAfterResponseIsSet() { - $authenticator1 = $this->getMockBuilder('Symfony\Component\Security\Guard\AuthenticatorInterface')->getMock(); - $authenticator2 = $this->getMockBuilder('Symfony\Component\Security\Guard\AuthenticatorInterface')->getMock(); + $authenticator1 = $this->getMockBuilder(AuthenticatorInterface::class)->getMock(); + $authenticator2 = $this->getMockBuilder(AuthenticatorInterface::class)->getMock(); // mock the first authenticator to fail, and set a Response $authenticator1 @@ -104,7 +107,6 @@ public function testHandleSuccessStopsAfterResponseIsSet() ->expects($this->once()) ->method('handleAuthenticationFailure') ->willReturn(new Response()); - // the second authenticator should *never* be called $authenticator2 ->expects($this->never()) @@ -123,8 +125,8 @@ public function testHandleSuccessStopsAfterResponseIsSet() public function testHandleSuccessWithRememberMe() { - $authenticator = $this->getMockBuilder('Symfony\Component\Security\Guard\AuthenticatorInterface')->getMock(); - $authenticateToken = $this->getMockBuilder('Symfony\Component\Security\Core\Authentication\Token\TokenInterface')->getMock(); + $authenticator = $this->getMockBuilder(AuthenticatorInterface::class)->getMock(); + $authenticateToken = $this->getMockBuilder(TokenInterface::class)->getMock(); $providerKey = 'my_firewall_with_rememberme'; $authenticator @@ -171,7 +173,7 @@ public function testHandleSuccessWithRememberMe() public function testHandleCatchesAuthenticationException() { - $authenticator = $this->getMockBuilder('Symfony\Component\Security\Guard\AuthenticatorInterface')->getMock(); + $authenticator = $this->getMockBuilder(AuthenticatorInterface::class)->getMock(); $providerKey = 'my_firewall2'; $authException = new AuthenticationException('Get outta here crazy user with a bad password!'); @@ -210,7 +212,7 @@ public function testHandleCatchesAuthenticationException() */ public function testLegacyInterfaceNullCredentials() { - $authenticatorA = $this->getMockBuilder('Symfony\Component\Security\Guard\GuardAuthenticatorInterface')->getMock(); + $authenticatorA = $this->getMockBuilder(GuardAuthenticatorInterface::class)->getMock(); $providerKey = 'my_firewall3'; $authenticatorA @@ -243,8 +245,8 @@ public function testLegacyInterfaceNullCredentials() */ public function testLegacyInterfaceKeepsWorking() { - $authenticator = $this->getMockBuilder('Symfony\Component\Security\Guard\GuardAuthenticatorInterface')->getMock(); - $authenticateToken = $this->getMockBuilder('Symfony\Component\Security\Core\Authentication\Token\TokenInterface')->getMock(); + $authenticator = $this->getMockBuilder(GuardAuthenticatorInterface::class)->getMock(); + $authenticateToken = $this->getMockBuilder(TokenInterface::class)->getMock(); $providerKey = 'my_firewall'; $credentials = array('username' => 'weaverryan', 'password' => 'all_your_base'); @@ -332,7 +334,7 @@ public function testReturnNullToSkipAuth() public function testSupportsReturnFalseSkipAuth() { - $authenticator = $this->getMockBuilder('Symfony\Component\Security\Guard\AuthenticatorInterface')->getMock(); + $authenticator = $this->getMockBuilder(AuthenticatorInterface::class)->getMock(); $providerKey = 'my_firewall4'; $authenticator @@ -359,9 +361,9 @@ public function testSupportsReturnFalseSkipAuth() /** * @expectedException \UnexpectedValueException */ - public function testSupportsReturnTrueRaiseMissingCredentialsException() + public function testReturnNullFromGetCredentials() { - $authenticator = $this->getMockBuilder('Symfony\Component\Security\Guard\AuthenticatorInterface')->getMock(); + $authenticator = $this->getMockBuilder(AuthenticatorInterface::class)->getMock(); $providerKey = 'my_firewall4'; $authenticator diff --git a/src/Symfony/Component/Security/Guard/Tests/GuardAuthenticatorHandlerTest.php b/src/Symfony/Component/Security/Guard/Tests/GuardAuthenticatorHandlerTest.php index 29199d820eb11..c67f38e9ef91c 100644 --- a/src/Symfony/Component/Security/Guard/Tests/GuardAuthenticatorHandlerTest.php +++ b/src/Symfony/Component/Security/Guard/Tests/GuardAuthenticatorHandlerTest.php @@ -14,6 +14,7 @@ use PHPUnit\Framework\TestCase; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\Security\Guard\AuthenticatorInterface; use Symfony\Component\Security\Guard\GuardAuthenticatorHandler; use Symfony\Component\Security\Core\Exception\AuthenticationException; use Symfony\Component\Security\Http\Event\InteractiveLoginEvent; @@ -128,7 +129,7 @@ protected function setUp() $this->dispatcher = $this->getMockBuilder('Symfony\Component\EventDispatcher\EventDispatcherInterface')->getMock(); $this->token = $this->getMockBuilder('Symfony\Component\Security\Core\Authentication\Token\TokenInterface')->getMock(); $this->request = new Request(array(), array(), array(), array(), array(), array()); - $this->guardAuthenticator = $this->getMockBuilder('Symfony\Component\Security\Guard\AuthenticatorInterface')->getMock(); + $this->guardAuthenticator = $this->getMockBuilder(AuthenticatorInterface::class)->getMock(); } protected function tearDown() diff --git a/src/Symfony/Component/Security/Guard/Tests/Provider/GuardAuthenticationProviderTest.php b/src/Symfony/Component/Security/Guard/Tests/Provider/GuardAuthenticationProviderTest.php index ed3920533fe92..9d8301fce8011 100644 --- a/src/Symfony/Component/Security/Guard/Tests/Provider/GuardAuthenticationProviderTest.php +++ b/src/Symfony/Component/Security/Guard/Tests/Provider/GuardAuthenticationProviderTest.php @@ -12,6 +12,9 @@ namespace Symfony\Component\Security\Guard\Tests\Provider; use PHPUnit\Framework\TestCase; +use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; +use Symfony\Component\Security\Core\User\UserInterface; +use Symfony\Component\Security\Guard\AuthenticatorInterface; use Symfony\Component\Security\Guard\Provider\GuardAuthenticationProvider; use Symfony\Component\Security\Guard\Token\PostAuthenticationGuardToken; @@ -28,6 +31,68 @@ public function testAuthenticate() { $providerKey = 'my_cool_firewall'; + $authenticatorA = $this->getMockBuilder(AuthenticatorInterface::class)->getMock(); + $authenticatorB = $this->getMockBuilder(AuthenticatorInterface::class)->getMock(); + $authenticatorC = $this->getMockBuilder(AuthenticatorInterface::class)->getMock(); + $authenticators = array($authenticatorA, $authenticatorB, $authenticatorC); + + // called 2 times - for authenticator A and B (stops on B because of match) + $this->preAuthenticationToken->expects($this->exactly(2)) + ->method('getGuardProviderKey') + // it will return the "1" index, which will match authenticatorB + ->will($this->returnValue('my_cool_firewall_1')); + + $enteredCredentials = array( + 'username' => '_weaverryan_test_user', + 'password' => 'guard_auth_ftw', + ); + $this->preAuthenticationToken->expects($this->atLeastOnce()) + ->method('getCredentials') + ->will($this->returnValue($enteredCredentials)); + + // authenticators A and C are never called + $authenticatorA->expects($this->never()) + ->method('getUser'); + $authenticatorC->expects($this->never()) + ->method('getUser'); + + $mockedUser = $this->getMockBuilder(UserInterface::class)->getMock(); + $authenticatorB->expects($this->once()) + ->method('getUser') + ->with($enteredCredentials, $this->userProvider) + ->will($this->returnValue($mockedUser)); + // checkCredentials is called + $authenticatorB->expects($this->once()) + ->method('checkCredentials') + ->with($enteredCredentials, $mockedUser) + // authentication works! + ->will($this->returnValue(true)); + $authedToken = $this->getMockBuilder(TokenInterface::class)->getMock(); + $authenticatorB->expects($this->once()) + ->method('createAuthenticatedToken') + ->with($mockedUser, $providerKey) + ->will($this->returnValue($authedToken)); + + // user checker should be called + $this->userChecker->expects($this->once()) + ->method('checkPreAuth') + ->with($mockedUser); + $this->userChecker->expects($this->once()) + ->method('checkPostAuth') + ->with($mockedUser); + + $provider = new GuardAuthenticationProvider($authenticators, $this->userProvider, $providerKey, $this->userChecker); + $actualAuthedToken = $provider->authenticate($this->preAuthenticationToken); + $this->assertSame($authedToken, $actualAuthedToken); + } + + /** + * @group legacy + */ + public function testLegacyAuthenticate() + { + $providerKey = 'my_cool_firewall'; + $authenticatorA = $this->getMockBuilder('Symfony\Component\Security\Guard\GuardAuthenticatorInterface')->getMock(); $authenticatorB = $this->getMockBuilder('Symfony\Component\Security\Guard\GuardAuthenticatorInterface')->getMock(); $authenticatorC = $this->getMockBuilder('Symfony\Component\Security\Guard\GuardAuthenticatorInterface')->getMock(); From 6651af07c2fad05d79b4ab4f972579e15b382f51 Mon Sep 17 00:00:00 2001 From: Tobias Schultze Date: Thu, 5 Oct 2017 14:27:30 +0200 Subject: [PATCH 1007/1099] [HttpFoundation] deprecate using with the legacy mongo extension; use it with the mongodb/mongodb package and ext-mongodb instead --- UPGRADE-3.4.md | 3 +++ UPGRADE-4.0.md | 3 +++ src/Symfony/Component/HttpFoundation/CHANGELOG.md | 1 + .../Storage/Handler/MongoDbSessionHandler.php | 13 +++++++++++-- 4 files changed, 18 insertions(+), 2 deletions(-) diff --git a/UPGRADE-3.4.md b/UPGRADE-3.4.md index e5b6434c37f4e..c6d5675d782fe 100644 --- a/UPGRADE-3.4.md +++ b/UPGRADE-3.4.md @@ -234,6 +234,9 @@ HttpFoundation * `NativeSessionStorage::setSaveHandler()` now takes an instance of `\SessionHandlerInterface` as argument. Not passing it is deprecated and will throw a `TypeError` in 4.0. + * Using `Symfony\Component\HttpFoundation\Session\Storage\Handler\MongoDbSessionHandler` with the legacy mongo extension + has been deprecated and will be removed in 4.0. Use it with the mongodb/mongodb package and ext-mongodb instead. + HttpKernel ---------- diff --git a/UPGRADE-4.0.md b/UPGRADE-4.0.md index 2d2e04899c18b..04fd5197add8c 100644 --- a/UPGRADE-4.0.md +++ b/UPGRADE-4.0.md @@ -540,6 +540,9 @@ HttpFoundation * `NativeSessionStorage::setSaveHandler()` now requires an instance of `\SessionHandlerInterface` as argument. + * The `Symfony\Component\HttpFoundation\Session\Storage\Handler\MongoDbSessionHandler` does not work with the legacy + mongo extension anymore. It requires mongodb/mongodb package and ext-mongodb. + HttpKernel ---------- diff --git a/src/Symfony/Component/HttpFoundation/CHANGELOG.md b/src/Symfony/Component/HttpFoundation/CHANGELOG.md index d60ebdfe8daaa..608bac2d6db10 100644 --- a/src/Symfony/Component/HttpFoundation/CHANGELOG.md +++ b/src/Symfony/Component/HttpFoundation/CHANGELOG.md @@ -7,6 +7,7 @@ CHANGELOG * deprecated the `NativeSessionHandler` class, * deprecated the `AbstractProxy`, `NativeProxy` and `SessionHandlerProxy` classes, * deprecated setting session save handlers that do not implement `\SessionHandlerInterface` in `NativeSessionStorage::setSaveHandler()` + * deprecated using `MongoDbSessionHandler` with the legacy mongo extension; use it with the mongodb/mongodb package and ext-mongodb instead 3.3.0 ----- diff --git a/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/MongoDbSessionHandler.php b/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/MongoDbSessionHandler.php index 80ecc1cc3c788..20e1a897e480b 100644 --- a/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/MongoDbSessionHandler.php +++ b/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/MongoDbSessionHandler.php @@ -12,7 +12,12 @@ namespace Symfony\Component\HttpFoundation\Session\Storage\Handler; /** + * Session handler using the mongodb/mongodb package and MongoDB driver extension. + * * @author Markus Bachmann + * + * @see https://packagist.org/packages/mongodb/mongodb + * @see http://php.net/manual/en/set.mongodb.php */ class MongoDbSessionHandler implements \SessionHandlerInterface { @@ -57,14 +62,18 @@ class MongoDbSessionHandler implements \SessionHandlerInterface * If you use such an index, you can drop `gc_probability` to 0 since * no garbage-collection is required. * - * @param \Mongo|\MongoClient|\MongoDB\Client $mongo A MongoDB\Client, MongoClient or Mongo instance - * @param array $options An associative array of field options + * @param \MongoDB\Client $mongo A MongoDB\Client instance + * @param array $options An associative array of field options * * @throws \InvalidArgumentException When MongoClient or Mongo instance not provided * @throws \InvalidArgumentException When "database" or "collection" not provided */ public function __construct($mongo, array $options) { + if ($mongo instanceof \MongoClient || $mongo instanceof \Mongo) { + @trigger_error(sprintf('Using %s with the legacy mongo extension is deprecated as of 3.4 and will be removed in 4.0. Use it with the mongodb/mongodb package and ext-mongodb instead.', __CLASS__), E_USER_DEPRECATED); + } + if (!($mongo instanceof \MongoDB\Client || $mongo instanceof \MongoClient || $mongo instanceof \Mongo)) { throw new \InvalidArgumentException('MongoClient or Mongo instance required'); } From d535ff60c2477f45e8552b80a4935004b44a3608 Mon Sep 17 00:00:00 2001 From: Tobias Schultze Date: Thu, 5 Oct 2017 14:34:03 +0200 Subject: [PATCH 1008/1099] [VarDumper] deprecate MongoCaster --- src/Symfony/Component/VarDumper/CHANGELOG.md | 1 + src/Symfony/Component/VarDumper/Caster/MongoCaster.php | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/src/Symfony/Component/VarDumper/CHANGELOG.md b/src/Symfony/Component/VarDumper/CHANGELOG.md index 24a5843f64dff..2d44cad2259c0 100644 --- a/src/Symfony/Component/VarDumper/CHANGELOG.md +++ b/src/Symfony/Component/VarDumper/CHANGELOG.md @@ -5,6 +5,7 @@ CHANGELOG ----- * added `AbstractCloner::setMinDepth()` function to ensure minimum tree depth + * deprecated `MongoCaster` 2.7.0 ----- diff --git a/src/Symfony/Component/VarDumper/Caster/MongoCaster.php b/src/Symfony/Component/VarDumper/Caster/MongoCaster.php index 92258f06fa238..2219386bc243d 100644 --- a/src/Symfony/Component/VarDumper/Caster/MongoCaster.php +++ b/src/Symfony/Component/VarDumper/Caster/MongoCaster.php @@ -13,10 +13,14 @@ use Symfony\Component\VarDumper\Cloner\Stub; +@trigger_error('The '.__NAMESPACE__.'\MongoCaster class is deprecated since version 3.4 and will be removed in 4.0.', E_USER_DEPRECATED); + /** * Casts classes from the MongoDb extension to array representation. * * @author Nicolas Grekas + * + * @deprecated since version 3.4, to be removed in 4.0. */ class MongoCaster { From af0aa1e530215e2c09b95a8f9d4657c4ab28ef4e Mon Sep 17 00:00:00 2001 From: Tobias Schultze Date: Thu, 5 Oct 2017 15:13:44 +0200 Subject: [PATCH 1009/1099] Add changelog for deprecated DbalSessionHandler --- UPGRADE-3.4.md | 7 +++++++ UPGRADE-4.0.md | 7 +++++++ src/Symfony/Bridge/Doctrine/CHANGELOG.md | 2 ++ 3 files changed, 16 insertions(+) diff --git a/UPGRADE-3.4.md b/UPGRADE-3.4.md index a06a8cd5151e4..8bbaf85fb0116 100644 --- a/UPGRADE-3.4.md +++ b/UPGRADE-3.4.md @@ -63,6 +63,13 @@ Debug * Support for stacked errors in the `ErrorHandler` is deprecated and will be removed in Symfony 4.0. +DoctrineBridge +-------------- + +* Deprecated `Symfony\Bridge\Doctrine\HttpFoundation\DbalSessionHandler` and + `Symfony\Bridge\Doctrine\HttpFoundation\DbalSessionHandlerSchema`. Use + `Symfony\Component\HttpFoundation\Session\Storage\Handler\PdoSessionHandler` instead. + EventDispatcher --------------- diff --git a/UPGRADE-4.0.md b/UPGRADE-4.0.md index 46fa72302e271..daf14138b60a8 100644 --- a/UPGRADE-4.0.md +++ b/UPGRADE-4.0.md @@ -186,6 +186,13 @@ DependencyInjection * The `ExtensionCompilerPass` has been moved to before-optimization passes with priority -1000. +DoctrineBridge +-------------- + +* The `Symfony\Bridge\Doctrine\HttpFoundation\DbalSessionHandler` and + `Symfony\Bridge\Doctrine\HttpFoundation\DbalSessionHandlerSchema` have been removed. Use + `Symfony\Component\HttpFoundation\Session\Storage\Handler\PdoSessionHandler` instead. + EventDispatcher --------------- diff --git a/src/Symfony/Bridge/Doctrine/CHANGELOG.md b/src/Symfony/Bridge/Doctrine/CHANGELOG.md index 0258a36a998ee..378db70d14926 100644 --- a/src/Symfony/Bridge/Doctrine/CHANGELOG.md +++ b/src/Symfony/Bridge/Doctrine/CHANGELOG.md @@ -6,6 +6,8 @@ CHANGELOG * added support for doctrine/dbal v2.6 types * added cause of UniqueEntity constraint violation + * deprecated `DbalSessionHandler` and `DbalSessionHandlerSchema` in favor of + `Symfony\Component\HttpFoundation\Session\Storage\Handler\PdoSessionHandler` 3.1.0 ----- From 5d29dd0d28aaf3e15967c393d889dbb400721d13 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Thu, 5 Oct 2017 10:44:57 +0200 Subject: [PATCH 1010/1099] [FrameworkBundle] Fix bad interface hint in AbstractController --- .../FrameworkBundle/Controller/ControllerTrait.php | 10 +++++----- .../Tests/Controller/ControllerTraitTest.php | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/Controller/ControllerTrait.php b/src/Symfony/Bundle/FrameworkBundle/Controller/ControllerTrait.php index 8a8eafe0ced59..7d47d59585762 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Controller/ControllerTrait.php +++ b/src/Symfony/Bundle/FrameworkBundle/Controller/ControllerTrait.php @@ -231,10 +231,10 @@ protected function renderView($view, array $parameters = array()) protected function render($view, array $parameters = array(), Response $response = null) { if ($this->container->has('templating')) { - return $this->container->get('templating')->renderResponse($view, $parameters, $response); - } - - if (!$this->container->has('twig')) { + $content = $this->container->get('templating')->render($view, $parameters); + } elseif ($this->container->has('twig')) { + $content = $this->container->get('twig')->render($view, $parameters); + } else { throw new \LogicException('You can not use the "render" method if the Templating Component or the Twig Bundle are not available.'); } @@ -242,7 +242,7 @@ protected function render($view, array $parameters = array(), Response $response $response = new Response(); } - $response->setContent($this->container->get('twig')->render($view, $parameters)); + $response->setContent($content); return $response; } diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/ControllerTraitTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/ControllerTraitTest.php index 3feabfd12e273..8321ebd5b49ab 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/ControllerTraitTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/ControllerTraitTest.php @@ -451,7 +451,7 @@ public function testRenderViewTemplating() public function testRenderTemplating() { $templating = $this->getMockBuilder('Symfony\Bundle\FrameworkBundle\Templating\EngineInterface')->getMock(); - $templating->expects($this->once())->method('renderResponse')->willReturn(new Response('bar')); + $templating->expects($this->once())->method('render')->willReturn('bar'); $container = new Container(); $container->set('templating', $templating); From df9c8748e3d6d37b7c62da896fffd84577e923a1 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Tue, 3 Oct 2017 11:46:06 +0200 Subject: [PATCH 1011/1099] [Bridge\Doctrine][FrameworkBundle] Deprecate some remaining uses of ContainerAwareTrait --- .../Bridge/Doctrine/ManagerRegistry.php | 19 +++++++- .../Doctrine/Tests/ManagerRegistryTest.php | 7 ++- .../Controller/ControllerResolver.php | 20 ++++---- .../Controller/RedirectController.php | 43 +++++++++++++++-- .../Controller/TemplateController.php | 43 ++++++++++++++--- .../Resources/config/routing.xml | 11 +++++ .../Controller/RedirectControllerTest.php | 48 ++++++++++++++----- .../Controller/TemplateControllerTest.php | 37 ++++++++++---- .../Handler/MongoDbSessionHandlerTest.php | 1 + 9 files changed, 187 insertions(+), 42 deletions(-) diff --git a/src/Symfony/Bridge/Doctrine/ManagerRegistry.php b/src/Symfony/Bridge/Doctrine/ManagerRegistry.php index c353e36e66282..af5ccaa1ab64e 100644 --- a/src/Symfony/Bridge/Doctrine/ManagerRegistry.php +++ b/src/Symfony/Bridge/Doctrine/ManagerRegistry.php @@ -12,9 +12,10 @@ namespace Symfony\Bridge\Doctrine; use ProxyManager\Proxy\LazyLoadingInterface; +use Psr\Container\ContainerInterface; use Symfony\Component\DependencyInjection\Container; use Symfony\Component\DependencyInjection\ContainerAwareInterface; -use Symfony\Component\DependencyInjection\ContainerAwareTrait; +use Symfony\Component\DependencyInjection\ContainerInterface as SymfonyContainerInterface; use Doctrine\Common\Persistence\AbstractManagerRegistry; /** @@ -24,7 +25,21 @@ */ abstract class ManagerRegistry extends AbstractManagerRegistry implements ContainerAwareInterface { - use ContainerAwareTrait; + /** + * @var ContainerInterface + */ + protected $container; + + /** + * @deprecated since version 3.4, to be removed in 4.0 alongside with the ContainerAwareInterface type. + * @final since version 3.4 + */ + public function setContainer(SymfonyContainerInterface $container = null) + { + @trigger_error(sprintf('The "%s()" method is deprecated since version 3.4 and will be removed in 4.0. Inject a PSR-11 container using the constructor instead.', __METHOD__), E_USER_DEPRECATED); + + $this->container = $container; + } /** * {@inheritdoc} diff --git a/src/Symfony/Bridge/Doctrine/Tests/ManagerRegistryTest.php b/src/Symfony/Bridge/Doctrine/Tests/ManagerRegistryTest.php index fa3037a609d8a..d1596a1968b76 100644 --- a/src/Symfony/Bridge/Doctrine/Tests/ManagerRegistryTest.php +++ b/src/Symfony/Bridge/Doctrine/Tests/ManagerRegistryTest.php @@ -31,7 +31,7 @@ public function testResetService() $container = new \LazyServiceProjectServiceContainer(); $registry = new TestManagerRegistry('name', array(), array('defaultManager' => 'foo'), 'defaultConnection', 'defaultManager', 'proxyInterfaceName'); - $registry->setContainer($container); + $registry->setTestContainer($container); $foo = $container->get('foo'); $foo->bar = 123; @@ -46,6 +46,11 @@ public function testResetService() class TestManagerRegistry extends ManagerRegistry { + public function setTestContainer($container) + { + $this->container = $container; + } + public function getAliasNamespace($alias) { return 'Foo'; diff --git a/src/Symfony/Bundle/FrameworkBundle/Controller/ControllerResolver.php b/src/Symfony/Bundle/FrameworkBundle/Controller/ControllerResolver.php index b88ad0cc7de33..a688abbabaf9a 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Controller/ControllerResolver.php +++ b/src/Symfony/Bundle/FrameworkBundle/Controller/ControllerResolver.php @@ -48,13 +48,7 @@ protected function createController($controller) $resolvedController = parent::createController($controller); if (1 === substr_count($controller, ':') && is_array($resolvedController)) { - if ($resolvedController[0] instanceof ContainerAwareInterface) { - $resolvedController[0]->setContainer($this->container); - } - - if ($resolvedController[0] instanceof AbstractController && null !== $previousContainer = $resolvedController[0]->setContainer($this->container)) { - $resolvedController[0]->setContainer($previousContainer); - } + $resolvedController[0] = $this->configureController($resolvedController[0]); } return $resolvedController; @@ -65,9 +59,19 @@ protected function createController($controller) */ protected function instantiateController($class) { - $controller = parent::instantiateController($class); + return $this->configureController(parent::instantiateController($class)); + } + private function configureController($controller) + { if ($controller instanceof ContainerAwareInterface) { + // @deprecated switch, to be removed in 4.0 where these classes + // won't implement ContainerAwareInterface anymore + switch (\get_class($controller)) { + case RedirectController::class: + case TemplateController::class: + return $controller; + } $controller->setContainer($this->container); } if ($controller instanceof AbstractController && null !== $previousContainer = $controller->setContainer($this->container)) { diff --git a/src/Symfony/Bundle/FrameworkBundle/Controller/RedirectController.php b/src/Symfony/Bundle/FrameworkBundle/Controller/RedirectController.php index b2cb1d1acc07d..6edee88ce5dda 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Controller/RedirectController.php +++ b/src/Symfony/Bundle/FrameworkBundle/Controller/RedirectController.php @@ -12,7 +12,7 @@ namespace Symfony\Bundle\FrameworkBundle\Controller; use Symfony\Component\DependencyInjection\ContainerAwareInterface; -use Symfony\Component\DependencyInjection\ContainerAwareTrait; +use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\HttpFoundation\RedirectResponse; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; @@ -23,10 +23,37 @@ * Redirects a request to another URL. * * @author Fabien Potencier + * + * @final since version 3.4 */ class RedirectController implements ContainerAwareInterface { - use ContainerAwareTrait; + /** + * @deprecated since version 3.4, to be removed in 4.0 + */ + protected $container; + + private $router; + private $httpPort; + private $httpsPort; + + public function __construct(UrlGeneratorInterface $router = null, $httpPort = null, $httpsPort = null) + { + $this->router = $router; + $this->httpPort = $httpPort; + $this->httpsPort = $httpsPort; + } + + /** + * @deprecated since version 3.4, to be removed in 4.0 alongside with the ContainerAwareInterface type. + */ + public function setContainer(ContainerInterface $container = null) + { + @trigger_error(sprintf('The "%s()" method is deprecated since version 3.4 and will be removed in 4.0. Inject an UrlGeneratorInterface using the constructor instead.', __METHOD__), E_USER_DEPRECATED); + + $this->container = $container; + $this->router = $container->get('router'); + } /** * Redirects to another route with the given name. @@ -61,7 +88,7 @@ public function redirectAction(Request $request, $route, $permanent = false, $ig } } - return new RedirectResponse($this->container->get('router')->generate($route, $attributes, UrlGeneratorInterface::ABSOLUTE_URL), $permanent ? 301 : 302); + return new RedirectResponse($this->router->generate($route, $attributes, UrlGeneratorInterface::ABSOLUTE_URL), $permanent ? 301 : 302); } /** @@ -115,8 +142,11 @@ public function urlRedirectAction(Request $request, $path, $permanent = false, $ if (null === $httpPort) { if ('http' === $request->getScheme()) { $httpPort = $request->getPort(); - } elseif ($this->container->hasParameter('request_listener.http_port')) { + } elseif ($this->container && $this->container->hasParameter('request_listener.http_port')) { + @trigger_error(sprintf('Passing the http port as a container parameter is deprecated since Symfony 3.4 and won\'t be possible in 4.0. Pass it to the constructor of the "%s" class instead.', __CLASS__), E_USER_DEPRECATED); $httpPort = $this->container->getParameter('request_listener.http_port'); + } else { + $httpPort = $this->httpPort; } } @@ -127,8 +157,11 @@ public function urlRedirectAction(Request $request, $path, $permanent = false, $ if (null === $httpsPort) { if ('https' === $request->getScheme()) { $httpsPort = $request->getPort(); - } elseif ($this->container->hasParameter('request_listener.https_port')) { + } elseif ($this->container && $this->container->hasParameter('request_listener.https_port')) { + @trigger_error(sprintf('Passing the https port as a container parameter is deprecated since Symfony 3.4 and won\'t be possible in 4.0. Pass it to the constructor of the "%s" class instead.', __CLASS__), E_USER_DEPRECATED); $httpsPort = $this->container->getParameter('request_listener.https_port'); + } else { + $httpsPort = $this->httpsPort; } } diff --git a/src/Symfony/Bundle/FrameworkBundle/Controller/TemplateController.php b/src/Symfony/Bundle/FrameworkBundle/Controller/TemplateController.php index 42ebd33bad9f2..5d13355208dcc 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Controller/TemplateController.php +++ b/src/Symfony/Bundle/FrameworkBundle/Controller/TemplateController.php @@ -12,17 +12,48 @@ namespace Symfony\Bundle\FrameworkBundle\Controller; use Symfony\Component\DependencyInjection\ContainerAwareInterface; -use Symfony\Component\DependencyInjection\ContainerAwareTrait; +use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\Templating\EngineInterface; +use Twig\Environment; /** * TemplateController. * * @author Fabien Potencier + * + * @final since version 3.4 */ class TemplateController implements ContainerAwareInterface { - use ContainerAwareTrait; + /** + * @deprecated since version 3.4, to be removed in 4.0 + */ + protected $container; + + private $twig; + private $templating; + + public function __construct(Environment $twig = null, EngineInterface $templating = null) + { + $this->twig = $twig; + $this->templating = $templating; + } + + /** + * @deprecated since version 3.4, to be removed in 4.0 alongside with the ContainerAwareInterface type. + */ + public function setContainer(ContainerInterface $container = null) + { + @trigger_error(sprintf('The "%s()" method is deprecated since version 3.4 and will be removed in 4.0. Inject a Twig Environment or an EngineInterface using the constructor instead.', __METHOD__), E_USER_DEPRECATED); + + if ($container->has('templating')) { + $this->templating = $container->get('templating'); + } elseif ($container->has('twig')) { + $this->twig = $container->get('twig'); + } + $this->container = $container; + } /** * Renders a template. @@ -36,10 +67,10 @@ class TemplateController implements ContainerAwareInterface */ public function templateAction($template, $maxAge = null, $sharedAge = null, $private = null) { - if ($this->container->has('templating')) { - $response = $this->container->get('templating')->renderResponse($template); - } elseif ($this->container->has('twig')) { - $response = new Response($this->container->get('twig')->render($template)); + if ($this->templating) { + $response = new Response($this->templating->render($template)); + } elseif ($this->twig) { + $response = new Response($this->twig->render($template)); } else { throw new \LogicException('You can not use the TemplateController if the Templating Component or the Twig Bundle are not available.'); } diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/routing.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/routing.xml index 6856512e20349..ed8dbfe8d7f72 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/routing.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/routing.xml @@ -110,5 +110,16 @@
+ + + + %request_listener.http_port% + %request_listener.https_port% + + + + + + diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/RedirectControllerTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/RedirectControllerTest.php index 14b6e4428e550..a95083a382639 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/RedirectControllerTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/RedirectControllerTest.php @@ -15,6 +15,7 @@ use Symfony\Component\HttpFoundation\ParameterBag; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpKernel\Exception\HttpException; +use Symfony\Component\Routing\Generator\UrlGeneratorInterface; use Symfony\Bundle\FrameworkBundle\Controller\RedirectController; use Symfony\Bundle\FrameworkBundle\Tests\TestCase; @@ -66,23 +67,14 @@ public function testRoute($permanent, $ignoreAttributes, $expectedCode, $expecte $request->attributes = new ParameterBag($attributes); - $router = $this->getMockBuilder('Symfony\Component\Routing\RouterInterface')->getMock(); + $router = $this->getMockBuilder(UrlGeneratorInterface::class)->getMock(); $router ->expects($this->once()) ->method('generate') ->with($this->equalTo($route), $this->equalTo($expectedAttributes)) ->will($this->returnValue($url)); - $container = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerInterface')->getMock(); - - $container - ->expects($this->once()) - ->method('get') - ->with($this->equalTo('router')) - ->will($this->returnValue($router)); - - $controller = new RedirectController(); - $controller->setContainer($container); + $controller = new RedirectController($router); $returnResponse = $controller->redirectAction($request, $route, $permanent, $ignoreAttributes); @@ -130,7 +122,7 @@ public function testFullURL() $this->assertEquals(302, $returnResponse->getStatusCode()); } - public function testUrlRedirectDefaultPortParameters() + public function testUrlRedirectDefaultPorts() { $host = 'www.example.com'; $baseUrl = '/base'; @@ -151,6 +143,30 @@ public function testUrlRedirectDefaultPortParameters() $this->assertRedirectUrl($returnValue, $expectedUrl); } + /** + * @group legacy + */ + public function testUrlRedirectDefaultPortParameters() + { + $host = 'www.example.com'; + $baseUrl = '/base'; + $path = '/redirect-path'; + $httpPort = 1080; + $httpsPort = 1443; + + $expectedUrl = "https://$host:$httpsPort$baseUrl$path"; + $request = $this->createRequestObject('http', $host, $httpPort, $baseUrl); + $controller = $this->createLegacyRedirectController(null, $httpsPort); + $returnValue = $controller->urlRedirectAction($request, $path, false, 'https'); + $this->assertRedirectUrl($returnValue, $expectedUrl); + + $expectedUrl = "http://$host:$httpPort$baseUrl$path"; + $request = $this->createRequestObject('https', $host, $httpPort, $baseUrl); + $controller = $this->createLegacyRedirectController($httpPort); + $returnValue = $controller->urlRedirectAction($request, $path, false, 'http'); + $this->assertRedirectUrl($returnValue, $expectedUrl); + } + public function urlRedirectProvider() { return array( @@ -256,6 +272,14 @@ private function createRequestObject($scheme, $host, $port, $baseUrl, $queryStri } private function createRedirectController($httpPort = null, $httpsPort = null) + { + return new RedirectController(null, $httpPort, $httpsPort); + } + + /** + * @deprecated + */ + private function createLegacyRedirectController($httpPort = null, $httpsPort = null) { $container = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerInterface')->getMock(); diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/TemplateControllerTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/TemplateControllerTest.php index 6afb5e3203f28..497c112eedb5f 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/TemplateControllerTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/TemplateControllerTest.php @@ -12,8 +12,8 @@ namespace Symfony\Bundle\FrameworkBundle\Tests\Controller; use Symfony\Bundle\FrameworkBundle\Controller\TemplateController; +use Symfony\Bundle\FrameworkBundle\Templating\EngineInterface; use Symfony\Bundle\FrameworkBundle\Tests\TestCase; -use Symfony\Component\HttpFoundation\Response; /** * @author Kévin Dunglas @@ -25,6 +25,29 @@ public function testTwig() $twig = $this->getMockBuilder('Twig\Environment')->disableOriginalConstructor()->getMock(); $twig->expects($this->once())->method('render')->willReturn('bar'); + $controller = new TemplateController($twig); + + $this->assertEquals('bar', $controller->templateAction('mytemplate')->getContent()); + } + + public function testTemplating() + { + $templating = $this->getMockBuilder(EngineInterface::class)->getMock(); + $templating->expects($this->once())->method('render')->willReturn('bar'); + + $controller = new TemplateController(null, $templating); + + $this->assertEquals('bar', $controller->templateAction('mytemplate')->getContent()); + } + + /** + * @group legacy + */ + public function testLegacyTwig() + { + $twig = $this->getMockBuilder('Twig\Environment')->disableOriginalConstructor()->getMock(); + $twig->expects($this->once())->method('render')->willReturn('bar'); + $container = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerInterface')->getMock(); $container->expects($this->at(0))->method('has')->will($this->returnValue(false)); $container->expects($this->at(1))->method('has')->will($this->returnValue(true)); @@ -36,10 +59,13 @@ public function testTwig() $this->assertEquals('bar', $controller->templateAction('mytemplate')->getContent()); } - public function testTemplating() + /** + * @group legacy + */ + public function testLegacyTemplating() { $templating = $this->getMockBuilder('Symfony\Bundle\FrameworkBundle\Templating\EngineInterface')->getMock(); - $templating->expects($this->once())->method('renderResponse')->willReturn(new Response('bar')); + $templating->expects($this->once())->method('render')->willReturn('bar'); $container = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerInterface')->getMock(); $container->expects($this->at(0))->method('has')->willReturn(true); @@ -57,12 +83,7 @@ public function testTemplating() */ public function testNoTwigNorTemplating() { - $container = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerInterface')->getMock(); - $container->expects($this->at(0))->method('has')->willReturn(false); - $container->expects($this->at(1))->method('has')->willReturn(false); - $controller = new TemplateController(); - $controller->setContainer($container); $controller->templateAction('mytemplate')->getContent(); } diff --git a/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/MongoDbSessionHandlerTest.php b/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/MongoDbSessionHandlerTest.php index 74366863f7126..9b28f066d6dc5 100644 --- a/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/MongoDbSessionHandlerTest.php +++ b/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/MongoDbSessionHandlerTest.php @@ -17,6 +17,7 @@ /** * @author Markus Bachmann * @group time-sensitive + * @group legacy */ class MongoDbSessionHandlerTest extends TestCase { From 51a1b57c67b57c20717491732d0703c37d4864c1 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Thu, 5 Oct 2017 17:24:04 +0200 Subject: [PATCH 1012/1099] fix merge --- .../Tests/Dumper/PhpDumperTest.php | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php b/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php index 2f29729005f2f..bda74490c9382 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php @@ -799,14 +799,14 @@ public function testDumpHandlesLiteralClassWithRootNamespace() /** * @group legacy - * @expectedDeprecation Requesting the "private" private service is deprecated since Symfony 3.2 and won't be supported anymore in Symfony 4.0. - * @expectedDeprecation Requesting the "private_alias" private service is deprecated since Symfony 3.2 and won't be supported anymore in Symfony 4.0. - * @expectedDeprecation Requesting the "decorated_private" private service is deprecated since Symfony 3.2 and won't be supported anymore in Symfony 4.0. - * @expectedDeprecation Requesting the "decorated_private_alias" private service is deprecated since Symfony 3.2 and won't be supported anymore in Symfony 4.0. - * @expectedDeprecation Requesting the "private_not_inlined" private service is deprecated since Symfony 3.2 and won't be supported anymore in Symfony 4.0. - * @expectedDeprecation Requesting the "private_not_removed" private service is deprecated since Symfony 3.2 and won't be supported anymore in Symfony 4.0. - * @expectedDeprecation Requesting the "private_child" private service is deprecated since Symfony 3.2 and won't be supported anymore in Symfony 4.0. - * @expectedDeprecation Requesting the "private_parent" private service is deprecated since Symfony 3.2 and won't be supported anymore in Symfony 4.0. + * @expectedDeprecation The "private" service is private, getting it from the container is deprecated since Symfony 3.2 and will fail in 4.0. You should either make the service public, or stop getting services directly from the container and use dependency injection instead. + * @expectedDeprecation The "private_alias" service is private, getting it from the container is deprecated since Symfony 3.2 and will fail in 4.0. You should either make the service public, or stop getting services directly from the container and use dependency injection instead. + * @expectedDeprecation The "decorated_private" service is private, getting it from the container is deprecated since Symfony 3.2 and will fail in 4.0. You should either make the service public, or stop getting services directly from the container and use dependency injection instead. + * @expectedDeprecation The "decorated_private_alias" service is private, getting it from the container is deprecated since Symfony 3.2 and will fail in 4.0. You should either make the service public, or stop getting services directly from the container and use dependency injection instead. + * @expectedDeprecation The "private_not_inlined" service is private, getting it from the container is deprecated since Symfony 3.2 and will fail in 4.0. You should either make the service public, or stop getting services directly from the container and use dependency injection instead. + * @expectedDeprecation The "private_not_removed" service is private, getting it from the container is deprecated since Symfony 3.2 and will fail in 4.0. You should either make the service public, or stop getting services directly from the container and use dependency injection instead. + * @expectedDeprecation The "private_child" service is private, getting it from the container is deprecated since Symfony 3.2 and will fail in 4.0. You should either make the service public, or stop getting services directly from the container and use dependency injection instead. + * @expectedDeprecation The "private_parent" service is private, getting it from the container is deprecated since Symfony 3.2 and will fail in 4.0. You should either make the service public, or stop getting services directly from the container and use dependency injection instead. */ public function testLegacyPrivateServices() { From 3b1b8cfdf30e5470700c356f67995f62b3179ae3 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Thu, 5 Oct 2017 17:34:34 +0200 Subject: [PATCH 1013/1099] [Bridge\Doctrine][FrameworkBundle] Remove legacy uses of ContainerAwareInterface --- .../Bridge/Doctrine/ManagerRegistry.php | 15 +---- .../Controller/ControllerResolver.php | 7 --- .../Controller/RedirectController.php | 30 +-------- .../Controller/TemplateController.php | 24 +------ .../Controller/RedirectControllerTest.php | 62 ------------------- .../Controller/TemplateControllerTest.php | 37 ----------- 6 files changed, 5 insertions(+), 170 deletions(-) diff --git a/src/Symfony/Bridge/Doctrine/ManagerRegistry.php b/src/Symfony/Bridge/Doctrine/ManagerRegistry.php index 9239fd31afa99..fd09e82ded922 100644 --- a/src/Symfony/Bridge/Doctrine/ManagerRegistry.php +++ b/src/Symfony/Bridge/Doctrine/ManagerRegistry.php @@ -14,8 +14,6 @@ use ProxyManager\Proxy\LazyLoadingInterface; use Psr\Container\ContainerInterface; use Symfony\Component\DependencyInjection\Container; -use Symfony\Component\DependencyInjection\ContainerAwareInterface; -use Symfony\Component\DependencyInjection\ContainerInterface as SymfonyContainerInterface; use Doctrine\Common\Persistence\AbstractManagerRegistry; /** @@ -23,24 +21,13 @@ * * @author Lukas Kahwe Smith */ -abstract class ManagerRegistry extends AbstractManagerRegistry implements ContainerAwareInterface +abstract class ManagerRegistry extends AbstractManagerRegistry { /** * @var ContainerInterface */ protected $container; - /** - * @deprecated since version 3.4, to be removed in 4.0 alongside with the ContainerAwareInterface type. - * @final since version 3.4 - */ - public function setContainer(SymfonyContainerInterface $container = null) - { - @trigger_error(sprintf('The "%s()" method is deprecated since version 3.4 and will be removed in 4.0. Inject a PSR-11 container using the constructor instead.', __METHOD__), E_USER_DEPRECATED); - - $this->container = $container; - } - /** * {@inheritdoc} */ diff --git a/src/Symfony/Bundle/FrameworkBundle/Controller/ControllerResolver.php b/src/Symfony/Bundle/FrameworkBundle/Controller/ControllerResolver.php index a688abbabaf9a..e42703b941e35 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Controller/ControllerResolver.php +++ b/src/Symfony/Bundle/FrameworkBundle/Controller/ControllerResolver.php @@ -65,13 +65,6 @@ protected function instantiateController($class) private function configureController($controller) { if ($controller instanceof ContainerAwareInterface) { - // @deprecated switch, to be removed in 4.0 where these classes - // won't implement ContainerAwareInterface anymore - switch (\get_class($controller)) { - case RedirectController::class: - case TemplateController::class: - return $controller; - } $controller->setContainer($this->container); } if ($controller instanceof AbstractController && null !== $previousContainer = $controller->setContainer($this->container)) { diff --git a/src/Symfony/Bundle/FrameworkBundle/Controller/RedirectController.php b/src/Symfony/Bundle/FrameworkBundle/Controller/RedirectController.php index 6edee88ce5dda..487481623e9b7 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Controller/RedirectController.php +++ b/src/Symfony/Bundle/FrameworkBundle/Controller/RedirectController.php @@ -11,8 +11,6 @@ namespace Symfony\Bundle\FrameworkBundle\Controller; -use Symfony\Component\DependencyInjection\ContainerAwareInterface; -use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\HttpFoundation\RedirectResponse; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; @@ -26,13 +24,8 @@ * * @final since version 3.4 */ -class RedirectController implements ContainerAwareInterface +class RedirectController { - /** - * @deprecated since version 3.4, to be removed in 4.0 - */ - protected $container; - private $router; private $httpPort; private $httpsPort; @@ -44,17 +37,6 @@ public function __construct(UrlGeneratorInterface $router = null, $httpPort = nu $this->httpsPort = $httpsPort; } - /** - * @deprecated since version 3.4, to be removed in 4.0 alongside with the ContainerAwareInterface type. - */ - public function setContainer(ContainerInterface $container = null) - { - @trigger_error(sprintf('The "%s()" method is deprecated since version 3.4 and will be removed in 4.0. Inject an UrlGeneratorInterface using the constructor instead.', __METHOD__), E_USER_DEPRECATED); - - $this->container = $container; - $this->router = $container->get('router'); - } - /** * Redirects to another route with the given name. * @@ -104,8 +86,8 @@ public function redirectAction(Request $request, $route, $permanent = false, $ig * @param string $path The absolute path or URL to redirect to * @param bool $permanent Whether the redirect is permanent or not * @param string|null $scheme The URL scheme (null to keep the current one) - * @param int|null $httpPort The HTTP port (null to keep the current one for the same scheme or the configured port in the container) - * @param int|null $httpsPort The HTTPS port (null to keep the current one for the same scheme or the configured port in the container) + * @param int|null $httpPort The HTTP port (null to keep the current one for the same scheme or the default configured port) + * @param int|null $httpsPort The HTTPS port (null to keep the current one for the same scheme or the default configured port) * * @return Response A Response instance * @@ -142,9 +124,6 @@ public function urlRedirectAction(Request $request, $path, $permanent = false, $ if (null === $httpPort) { if ('http' === $request->getScheme()) { $httpPort = $request->getPort(); - } elseif ($this->container && $this->container->hasParameter('request_listener.http_port')) { - @trigger_error(sprintf('Passing the http port as a container parameter is deprecated since Symfony 3.4 and won\'t be possible in 4.0. Pass it to the constructor of the "%s" class instead.', __CLASS__), E_USER_DEPRECATED); - $httpPort = $this->container->getParameter('request_listener.http_port'); } else { $httpPort = $this->httpPort; } @@ -157,9 +136,6 @@ public function urlRedirectAction(Request $request, $path, $permanent = false, $ if (null === $httpsPort) { if ('https' === $request->getScheme()) { $httpsPort = $request->getPort(); - } elseif ($this->container && $this->container->hasParameter('request_listener.https_port')) { - @trigger_error(sprintf('Passing the https port as a container parameter is deprecated since Symfony 3.4 and won\'t be possible in 4.0. Pass it to the constructor of the "%s" class instead.', __CLASS__), E_USER_DEPRECATED); - $httpsPort = $this->container->getParameter('request_listener.https_port'); } else { $httpsPort = $this->httpsPort; } diff --git a/src/Symfony/Bundle/FrameworkBundle/Controller/TemplateController.php b/src/Symfony/Bundle/FrameworkBundle/Controller/TemplateController.php index 5d13355208dcc..65eb35fc2a2fd 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Controller/TemplateController.php +++ b/src/Symfony/Bundle/FrameworkBundle/Controller/TemplateController.php @@ -11,8 +11,6 @@ namespace Symfony\Bundle\FrameworkBundle\Controller; -use Symfony\Component\DependencyInjection\ContainerAwareInterface; -use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Templating\EngineInterface; use Twig\Environment; @@ -24,13 +22,8 @@ * * @final since version 3.4 */ -class TemplateController implements ContainerAwareInterface +class TemplateController { - /** - * @deprecated since version 3.4, to be removed in 4.0 - */ - protected $container; - private $twig; private $templating; @@ -40,21 +33,6 @@ public function __construct(Environment $twig = null, EngineInterface $templatin $this->templating = $templating; } - /** - * @deprecated since version 3.4, to be removed in 4.0 alongside with the ContainerAwareInterface type. - */ - public function setContainer(ContainerInterface $container = null) - { - @trigger_error(sprintf('The "%s()" method is deprecated since version 3.4 and will be removed in 4.0. Inject a Twig Environment or an EngineInterface using the constructor instead.', __METHOD__), E_USER_DEPRECATED); - - if ($container->has('templating')) { - $this->templating = $container->get('templating'); - } elseif ($container->has('twig')) { - $this->twig = $container->get('twig'); - } - $this->container = $container; - } - /** * Renders a template. * diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/RedirectControllerTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/RedirectControllerTest.php index a95083a382639..7555f8f7aa025 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/RedirectControllerTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/RedirectControllerTest.php @@ -143,30 +143,6 @@ public function testUrlRedirectDefaultPorts() $this->assertRedirectUrl($returnValue, $expectedUrl); } - /** - * @group legacy - */ - public function testUrlRedirectDefaultPortParameters() - { - $host = 'www.example.com'; - $baseUrl = '/base'; - $path = '/redirect-path'; - $httpPort = 1080; - $httpsPort = 1443; - - $expectedUrl = "https://$host:$httpsPort$baseUrl$path"; - $request = $this->createRequestObject('http', $host, $httpPort, $baseUrl); - $controller = $this->createLegacyRedirectController(null, $httpsPort); - $returnValue = $controller->urlRedirectAction($request, $path, false, 'https'); - $this->assertRedirectUrl($returnValue, $expectedUrl); - - $expectedUrl = "http://$host:$httpPort$baseUrl$path"; - $request = $this->createRequestObject('https', $host, $httpPort, $baseUrl); - $controller = $this->createLegacyRedirectController($httpPort); - $returnValue = $controller->urlRedirectAction($request, $path, false, 'http'); - $this->assertRedirectUrl($returnValue, $expectedUrl); - } - public function urlRedirectProvider() { return array( @@ -276,44 +252,6 @@ private function createRedirectController($httpPort = null, $httpsPort = null) return new RedirectController(null, $httpPort, $httpsPort); } - /** - * @deprecated - */ - private function createLegacyRedirectController($httpPort = null, $httpsPort = null) - { - $container = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerInterface')->getMock(); - - if (null !== $httpPort) { - $container - ->expects($this->once()) - ->method('hasParameter') - ->with($this->equalTo('request_listener.http_port')) - ->will($this->returnValue(true)); - $container - ->expects($this->once()) - ->method('getParameter') - ->with($this->equalTo('request_listener.http_port')) - ->will($this->returnValue($httpPort)); - } - if (null !== $httpsPort) { - $container - ->expects($this->once()) - ->method('hasParameter') - ->with($this->equalTo('request_listener.https_port')) - ->will($this->returnValue(true)); - $container - ->expects($this->once()) - ->method('getParameter') - ->with($this->equalTo('request_listener.https_port')) - ->will($this->returnValue($httpsPort)); - } - - $controller = new RedirectController(); - $controller->setContainer($container); - - return $controller; - } - public function assertRedirectUrl(Response $returnResponse, $expectedUrl) { $this->assertTrue($returnResponse->isRedirect($expectedUrl), "Expected: $expectedUrl\nGot: ".$returnResponse->headers->get('Location')); diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/TemplateControllerTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/TemplateControllerTest.php index 497c112eedb5f..0bc068d76a556 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/TemplateControllerTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/TemplateControllerTest.php @@ -40,43 +40,6 @@ public function testTemplating() $this->assertEquals('bar', $controller->templateAction('mytemplate')->getContent()); } - /** - * @group legacy - */ - public function testLegacyTwig() - { - $twig = $this->getMockBuilder('Twig\Environment')->disableOriginalConstructor()->getMock(); - $twig->expects($this->once())->method('render')->willReturn('bar'); - - $container = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerInterface')->getMock(); - $container->expects($this->at(0))->method('has')->will($this->returnValue(false)); - $container->expects($this->at(1))->method('has')->will($this->returnValue(true)); - $container->expects($this->at(2))->method('get')->will($this->returnValue($twig)); - - $controller = new TemplateController(); - $controller->setContainer($container); - - $this->assertEquals('bar', $controller->templateAction('mytemplate')->getContent()); - } - - /** - * @group legacy - */ - public function testLegacyTemplating() - { - $templating = $this->getMockBuilder('Symfony\Bundle\FrameworkBundle\Templating\EngineInterface')->getMock(); - $templating->expects($this->once())->method('render')->willReturn('bar'); - - $container = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerInterface')->getMock(); - $container->expects($this->at(0))->method('has')->willReturn(true); - $container->expects($this->at(1))->method('get')->will($this->returnValue($templating)); - - $controller = new TemplateController(); - $controller->setContainer($container); - - $this->assertEquals('bar', $controller->templateAction('mytemplate')->getContent()); - } - /** * @expectedException \LogicException * @expectedExceptionMessage You can not use the TemplateController if the Templating Component or the Twig Bundle are not available. From 989326b98819edfc119391f6c3f4e61b2455135e Mon Sep 17 00:00:00 2001 From: Tobias Schultze Date: Thu, 5 Oct 2017 17:58:33 +0200 Subject: [PATCH 1014/1099] [Session] deprecate MemcacheSessionHandler memcache extension didn't get a release since 4.5 years and is not compatible with PHP 7 --- UPGRADE-3.4.md | 3 +++ UPGRADE-4.0.md | 3 +++ src/Symfony/Component/HttpFoundation/CHANGELOG.md | 1 + .../Session/Storage/Handler/MemcacheSessionHandler.php | 4 ++++ .../Session/Storage/Handler/MemcacheSessionHandlerTest.php | 1 + 5 files changed, 12 insertions(+) diff --git a/UPGRADE-3.4.md b/UPGRADE-3.4.md index a06a8cd5151e4..763e45285ef81 100644 --- a/UPGRADE-3.4.md +++ b/UPGRADE-3.4.md @@ -243,6 +243,9 @@ HttpFoundation * Using `Symfony\Component\HttpFoundation\Session\Storage\Handler\MongoDbSessionHandler` with the legacy mongo extension has been deprecated and will be removed in 4.0. Use it with the mongodb/mongodb package and ext-mongodb instead. + * The `Symfony\Component\HttpFoundation\Session\Storage\Handler\MemcacheSessionHandler` class has been deprecated and + will be removed in 4.0. Use `Symfony\Component\HttpFoundation\Session\Storage\Handler\MemcachedSessionHandler` instead. + HttpKernel ---------- diff --git a/UPGRADE-4.0.md b/UPGRADE-4.0.md index 46fa72302e271..11e7cdfe92c0e 100644 --- a/UPGRADE-4.0.md +++ b/UPGRADE-4.0.md @@ -545,6 +545,9 @@ HttpFoundation * The `Symfony\Component\HttpFoundation\Session\Storage\Handler\MongoDbSessionHandler` does not work with the legacy mongo extension anymore. It requires mongodb/mongodb package and ext-mongodb. + * The `Symfony\Component\HttpFoundation\Session\Storage\Handler\MemcacheSessionHandler` class has been removed. + Use `Symfony\Component\HttpFoundation\Session\Storage\Handler\MemcachedSessionHandler` instead. + HttpKernel ---------- diff --git a/src/Symfony/Component/HttpFoundation/CHANGELOG.md b/src/Symfony/Component/HttpFoundation/CHANGELOG.md index 608bac2d6db10..83a3c8e32eaf6 100644 --- a/src/Symfony/Component/HttpFoundation/CHANGELOG.md +++ b/src/Symfony/Component/HttpFoundation/CHANGELOG.md @@ -8,6 +8,7 @@ CHANGELOG * deprecated the `AbstractProxy`, `NativeProxy` and `SessionHandlerProxy` classes, * deprecated setting session save handlers that do not implement `\SessionHandlerInterface` in `NativeSessionStorage::setSaveHandler()` * deprecated using `MongoDbSessionHandler` with the legacy mongo extension; use it with the mongodb/mongodb package and ext-mongodb instead + * deprecated `MemcacheSessionHandler`; use `MemcachedSessionHandler` instead 3.3.0 ----- diff --git a/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/MemcacheSessionHandler.php b/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/MemcacheSessionHandler.php index d31aa7667e657..2978ef4a2c1fa 100644 --- a/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/MemcacheSessionHandler.php +++ b/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/MemcacheSessionHandler.php @@ -11,8 +11,12 @@ namespace Symfony\Component\HttpFoundation\Session\Storage\Handler; +@trigger_error(sprintf('The class %s is deprecated since version 3.4 and will be removed in 4.0. Use Symfony\Component\HttpFoundation\Session\Storage\Handler\MemcachedSessionHandler instead.', MemcacheSessionHandler::class), E_USER_DEPRECATED); + /** * @author Drak + * + * @deprecated since version 3.4, to be removed in 4.0. Use Symfony\Component\HttpFoundation\Session\Storage\Handler\MemcachedSessionHandler instead. */ class MemcacheSessionHandler implements \SessionHandlerInterface { diff --git a/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/MemcacheSessionHandlerTest.php b/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/MemcacheSessionHandlerTest.php index 06193c8befbeb..05470ed80a363 100644 --- a/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/MemcacheSessionHandlerTest.php +++ b/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/MemcacheSessionHandlerTest.php @@ -17,6 +17,7 @@ /** * @requires extension memcache * @group time-sensitive + * @group legacy */ class MemcacheSessionHandlerTest extends TestCase { From 0a7af3fb50544f9cf1a07e4c79c11c3ce69ab697 Mon Sep 17 00:00:00 2001 From: Tobias Schultze Date: Thu, 5 Oct 2017 19:59:13 +0200 Subject: [PATCH 1015/1099] [Session] remove deprecated session handlers --- .../HttpFoundation/DbalSessionHandler.php | 276 ------------------ .../DbalSessionHandlerSchema.php | 49 ---- .../HttpFoundation/DbalSessionHandlerTest.php | 33 --- .../Handler/MemcacheSessionHandler.php | 121 -------- .../Storage/Handler/MongoDbSessionHandler.php | 79 +---- .../Handler/MemcacheSessionHandlerTest.php | 130 --------- .../Handler/MongoDbSessionHandlerTest.php | 151 ++-------- .../VarDumper/Caster/MongoCaster.php | 38 --- .../VarDumper/Cloner/AbstractCloner.php | 2 - 9 files changed, 37 insertions(+), 842 deletions(-) delete mode 100644 src/Symfony/Bridge/Doctrine/HttpFoundation/DbalSessionHandler.php delete mode 100644 src/Symfony/Bridge/Doctrine/HttpFoundation/DbalSessionHandlerSchema.php delete mode 100644 src/Symfony/Bridge/Doctrine/Tests/HttpFoundation/DbalSessionHandlerTest.php delete mode 100644 src/Symfony/Component/HttpFoundation/Session/Storage/Handler/MemcacheSessionHandler.php delete mode 100644 src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/MemcacheSessionHandlerTest.php delete mode 100644 src/Symfony/Component/VarDumper/Caster/MongoCaster.php diff --git a/src/Symfony/Bridge/Doctrine/HttpFoundation/DbalSessionHandler.php b/src/Symfony/Bridge/Doctrine/HttpFoundation/DbalSessionHandler.php deleted file mode 100644 index 6036636f5c46f..0000000000000 --- a/src/Symfony/Bridge/Doctrine/HttpFoundation/DbalSessionHandler.php +++ /dev/null @@ -1,276 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bridge\Doctrine\HttpFoundation; - -@trigger_error(sprintf('The class %s is deprecated since version 3.4 and will be removed in 4.0. Use Symfony\Component\HttpFoundation\Session\Storage\Handler\PdoSessionHandler instead.', DbalSessionHandler::class), E_USER_DEPRECATED); - -use Doctrine\DBAL\Connection; -use Doctrine\DBAL\Driver\DriverException; -use Doctrine\DBAL\Driver\ServerInfoAwareConnection; -use Doctrine\DBAL\Platforms\SQLServer2008Platform; - -/** - * DBAL based session storage. - * - * This implementation is very similar to Symfony\Component\HttpFoundation\Session\Storage\Handler\PdoSessionHandler - * but uses a Doctrine connection and thus also works with non-PDO-based drivers like mysqli and OCI8. - * - * @author Fabien Potencier - * @author Johannes M. Schmitt - * @author Tobias Schultze - * - * @deprecated since version 3.4, to be removed in 4.0. Use Symfony\Component\HttpFoundation\Session\Storage\Handler\PdoSessionHandler instead. - */ -class DbalSessionHandler implements \SessionHandlerInterface -{ - /** - * @var Connection - */ - private $con; - - /** - * @var string - */ - private $table; - - /** - * @var string Column for session id - */ - private $idCol = 'sess_id'; - - /** - * @var string Column for session data - */ - private $dataCol = 'sess_data'; - - /** - * @var string Column for timestamp - */ - private $timeCol = 'sess_time'; - - /** - * @param Connection $con A connection - * @param string $tableName Table name - */ - public function __construct(Connection $con, $tableName = 'sessions') - { - $this->con = $con; - $this->table = $tableName; - } - - /** - * {@inheritdoc} - */ - public function open($savePath, $sessionName) - { - return true; - } - - /** - * {@inheritdoc} - */ - public function close() - { - return true; - } - - /** - * {@inheritdoc} - */ - public function destroy($sessionId) - { - // delete the record associated with this id - $sql = "DELETE FROM $this->table WHERE $this->idCol = :id"; - - try { - $stmt = $this->con->prepare($sql); - $stmt->bindParam(':id', $sessionId, \PDO::PARAM_STR); - $stmt->execute(); - } catch (\Exception $e) { - throw new \RuntimeException(sprintf('Exception was thrown when trying to delete a session: %s', $e->getMessage()), 0, $e); - } - - return true; - } - - /** - * {@inheritdoc} - */ - public function gc($maxlifetime) - { - // delete the session records that have expired - $sql = "DELETE FROM $this->table WHERE $this->timeCol < :time"; - - try { - $stmt = $this->con->prepare($sql); - $stmt->bindValue(':time', time() - $maxlifetime, \PDO::PARAM_INT); - $stmt->execute(); - } catch (\Exception $e) { - throw new \RuntimeException(sprintf('Exception was thrown when trying to delete expired sessions: %s', $e->getMessage()), 0, $e); - } - - return true; - } - - /** - * {@inheritdoc} - */ - public function read($sessionId) - { - $sql = "SELECT $this->dataCol FROM $this->table WHERE $this->idCol = :id"; - - try { - $stmt = $this->con->prepare($sql); - $stmt->bindParam(':id', $sessionId, \PDO::PARAM_STR); - $stmt->execute(); - - // We use fetchAll instead of fetchColumn to make sure the DB cursor gets closed - $sessionRows = $stmt->fetchAll(\PDO::FETCH_NUM); - - if ($sessionRows) { - return base64_decode($sessionRows[0][0]); - } - - return ''; - } catch (\Exception $e) { - throw new \RuntimeException(sprintf('Exception was thrown when trying to read the session data: %s', $e->getMessage()), 0, $e); - } - } - - /** - * {@inheritdoc} - */ - public function write($sessionId, $data) - { - $encoded = base64_encode($data); - - try { - // We use a single MERGE SQL query when supported by the database. - $mergeSql = $this->getMergeSql(); - - if (null !== $mergeSql) { - $mergeStmt = $this->con->prepare($mergeSql); - $mergeStmt->bindParam(':id', $sessionId, \PDO::PARAM_STR); - $mergeStmt->bindParam(':data', $encoded, \PDO::PARAM_STR); - $mergeStmt->bindValue(':time', time(), \PDO::PARAM_INT); - - // Oracle has a bug that will intermittently happen if you - // have only 1 bind on a CLOB field for 2 different statements - // (INSERT and UPDATE in this case) - if ('oracle' == $this->con->getDatabasePlatform()->getName()) { - $mergeStmt->bindParam(':data2', $encoded, \PDO::PARAM_STR); - } - - $mergeStmt->execute(); - - return true; - } - - $updateStmt = $this->con->prepare( - "UPDATE $this->table SET $this->dataCol = :data, $this->timeCol = :time WHERE $this->idCol = :id" - ); - $updateStmt->bindParam(':id', $sessionId, \PDO::PARAM_STR); - $updateStmt->bindParam(':data', $encoded, \PDO::PARAM_STR); - $updateStmt->bindValue(':time', time(), \PDO::PARAM_INT); - $updateStmt->execute(); - - // When MERGE is not supported, like in Postgres < 9.5, we have to use this approach that can result in - // duplicate key errors when the same session is written simultaneously. We can just catch such an - // error and re-execute the update. This is similar to a serializable transaction with retry logic - // on serialization failures but without the overhead and without possible false positives due to - // longer gap locking. - if (!$updateStmt->rowCount()) { - try { - $insertStmt = $this->con->prepare( - "INSERT INTO $this->table ($this->idCol, $this->dataCol, $this->timeCol) VALUES (:id, :data, :time)" - ); - $insertStmt->bindParam(':id', $sessionId, \PDO::PARAM_STR); - $insertStmt->bindParam(':data', $encoded, \PDO::PARAM_STR); - $insertStmt->bindValue(':time', time(), \PDO::PARAM_INT); - $insertStmt->execute(); - } catch (\Exception $e) { - $driverException = $e->getPrevious(); - // Handle integrity violation SQLSTATE 23000 (or a subclass like 23505 in Postgres) for duplicate keys - // DriverException only available since DBAL 2.5 - if ( - ($driverException instanceof DriverException && 0 === strpos($driverException->getSQLState(), '23')) || - ($driverException instanceof \PDOException && 0 === strpos($driverException->getCode(), '23')) - ) { - $updateStmt->execute(); - } else { - throw $e; - } - } - } - } catch (\Exception $e) { - throw new \RuntimeException(sprintf('Exception was thrown when trying to write the session data: %s', $e->getMessage()), 0, $e); - } - - return true; - } - - /** - * Returns a merge/upsert (i.e. insert or update) SQL query when supported by the database. - * - * @return string|null The SQL string or null when not supported - */ - private function getMergeSql() - { - $platform = $this->con->getDatabasePlatform()->getName(); - - switch (true) { - case 'mysql' === $platform: - return "INSERT INTO $this->table ($this->idCol, $this->dataCol, $this->timeCol) VALUES (:id, :data, :time) ". - "ON DUPLICATE KEY UPDATE $this->dataCol = VALUES($this->dataCol), $this->timeCol = VALUES($this->timeCol)"; - case 'oracle' === $platform: - // DUAL is Oracle specific dummy table - return "MERGE INTO $this->table USING DUAL ON ($this->idCol = :id) ". - "WHEN NOT MATCHED THEN INSERT ($this->idCol, $this->dataCol, $this->timeCol) VALUES (:id, :data, :time) ". - "WHEN MATCHED THEN UPDATE SET $this->dataCol = :data2, $this->timeCol = :time"; - case $this->con->getDatabasePlatform() instanceof SQLServer2008Platform: - // MERGE is only available since SQL Server 2008 and must be terminated by semicolon - // It also requires HOLDLOCK according to http://weblogs.sqlteam.com/dang/archive/2009/01/31/UPSERT-Race-Condition-With-MERGE.aspx - return "MERGE INTO $this->table WITH (HOLDLOCK) USING (SELECT 1 AS dummy) AS src ON ($this->idCol = :id) ". - "WHEN NOT MATCHED THEN INSERT ($this->idCol, $this->dataCol, $this->timeCol) VALUES (:id, :data, :time) ". - "WHEN MATCHED THEN UPDATE SET $this->dataCol = :data, $this->timeCol = :time;"; - case 'sqlite' === $platform: - return "INSERT OR REPLACE INTO $this->table ($this->idCol, $this->dataCol, $this->timeCol) VALUES (:id, :data, :time)"; - case 'postgresql' === $platform && version_compare($this->getServerVersion(), '9.5', '>='): - return "INSERT INTO $this->table ($this->idCol, $this->dataCol, $this->timeCol) VALUES (:id, :data, :time) ". - "ON CONFLICT ($this->idCol) DO UPDATE SET ($this->dataCol, $this->timeCol) = (EXCLUDED.$this->dataCol, EXCLUDED.$this->timeCol)"; - } - } - - private function getServerVersion() - { - $params = $this->con->getParams(); - - // Explicit platform version requested (supersedes auto-detection), so we respect it. - if (isset($params['serverVersion'])) { - return $params['serverVersion']; - } - - $wrappedConnection = $this->con->getWrappedConnection(); - - if ($wrappedConnection instanceof ServerInfoAwareConnection) { - return $wrappedConnection->getServerVersion(); - } - - // Support DBAL 2.4 by accessing it directly when using PDO PgSQL - if ($wrappedConnection instanceof \PDO) { - return $wrappedConnection->getAttribute(\PDO::ATTR_SERVER_VERSION); - } - - // If we cannot guess the version, the empty string will mean we won't use the code for newer versions when doing version checks. - return ''; - } -} diff --git a/src/Symfony/Bridge/Doctrine/HttpFoundation/DbalSessionHandlerSchema.php b/src/Symfony/Bridge/Doctrine/HttpFoundation/DbalSessionHandlerSchema.php deleted file mode 100644 index 7af50a65074f8..0000000000000 --- a/src/Symfony/Bridge/Doctrine/HttpFoundation/DbalSessionHandlerSchema.php +++ /dev/null @@ -1,49 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bridge\Doctrine\HttpFoundation; - -@trigger_error(sprintf('The class %s is deprecated since version 3.4 and will be removed in 4.0. Use Symfony\Component\HttpFoundation\Session\Storage\Handler\PdoSessionHandler::createTable instead.', DbalSessionHandlerSchema::class), E_USER_DEPRECATED); - -use Doctrine\DBAL\Schema\Schema; - -/** - * DBAL Session Storage Schema. - * - * @author Johannes M. Schmitt - * - * @deprecated since version 3.4, to be removed in 4.0. Use Symfony\Component\HttpFoundation\Session\Storage\Handler\PdoSessionHandler::createTable instead. - */ -final class DbalSessionHandlerSchema extends Schema -{ - public function __construct($tableName = 'sessions') - { - parent::__construct(); - - $this->addSessionTable($tableName); - } - - public function addToSchema(Schema $schema) - { - foreach ($this->getTables() as $table) { - $schema->_addTable($table); - } - } - - private function addSessionTable($tableName) - { - $table = $this->createTable($tableName); - $table->addColumn('sess_id', 'string'); - $table->addColumn('sess_data', 'text')->setNotNull(true); - $table->addColumn('sess_time', 'integer')->setNotNull(true)->setUnsigned(true); - $table->setPrimaryKey(array('sess_id')); - } -} diff --git a/src/Symfony/Bridge/Doctrine/Tests/HttpFoundation/DbalSessionHandlerTest.php b/src/Symfony/Bridge/Doctrine/Tests/HttpFoundation/DbalSessionHandlerTest.php deleted file mode 100644 index 8d46bf9e63beb..0000000000000 --- a/src/Symfony/Bridge/Doctrine/Tests/HttpFoundation/DbalSessionHandlerTest.php +++ /dev/null @@ -1,33 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bridge\Doctrine\Tests\HttpFoundation; - -use PHPUnit\Framework\TestCase; -use Symfony\Bridge\Doctrine\HttpFoundation\DbalSessionHandler; - -/** - * Test class for DbalSessionHandler. - * - * @author Drak - * - * @group legacy - */ -class DbalSessionHandlerTest extends TestCase -{ - public function testConstruct() - { - $connection = $this->getMockBuilder('Doctrine\DBAL\Connection')->disableOriginalConstructor()->getMock(); - $handler = new DbalSessionHandler($connection); - - $this->assertInstanceOf('Symfony\Bridge\Doctrine\HttpFoundation\DbalSessionHandler', $handler); - } -} diff --git a/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/MemcacheSessionHandler.php b/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/MemcacheSessionHandler.php deleted file mode 100644 index 2978ef4a2c1fa..0000000000000 --- a/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/MemcacheSessionHandler.php +++ /dev/null @@ -1,121 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Session\Storage\Handler; - -@trigger_error(sprintf('The class %s is deprecated since version 3.4 and will be removed in 4.0. Use Symfony\Component\HttpFoundation\Session\Storage\Handler\MemcachedSessionHandler instead.', MemcacheSessionHandler::class), E_USER_DEPRECATED); - -/** - * @author Drak - * - * @deprecated since version 3.4, to be removed in 4.0. Use Symfony\Component\HttpFoundation\Session\Storage\Handler\MemcachedSessionHandler instead. - */ -class MemcacheSessionHandler implements \SessionHandlerInterface -{ - /** - * @var \Memcache Memcache driver - */ - private $memcache; - - /** - * @var int Time to live in seconds - */ - private $ttl; - - /** - * @var string Key prefix for shared environments - */ - private $prefix; - - /** - * List of available options: - * * prefix: The prefix to use for the memcache keys in order to avoid collision - * * expiretime: The time to live in seconds - * - * @param \Memcache $memcache A \Memcache instance - * @param array $options An associative array of Memcache options - * - * @throws \InvalidArgumentException When unsupported options are passed - */ - public function __construct(\Memcache $memcache, array $options = array()) - { - if ($diff = array_diff(array_keys($options), array('prefix', 'expiretime'))) { - throw new \InvalidArgumentException(sprintf( - 'The following options are not supported "%s"', implode(', ', $diff) - )); - } - - $this->memcache = $memcache; - $this->ttl = isset($options['expiretime']) ? (int) $options['expiretime'] : 86400; - $this->prefix = isset($options['prefix']) ? $options['prefix'] : 'sf2s'; - } - - /** - * {@inheritdoc} - */ - public function open($savePath, $sessionName) - { - return true; - } - - /** - * {@inheritdoc} - */ - public function close() - { - return true; - } - - /** - * {@inheritdoc} - */ - public function read($sessionId) - { - return $this->memcache->get($this->prefix.$sessionId) ?: ''; - } - - /** - * {@inheritdoc} - */ - public function write($sessionId, $data) - { - return $this->memcache->set($this->prefix.$sessionId, $data, 0, time() + $this->ttl); - } - - /** - * {@inheritdoc} - */ - public function destroy($sessionId) - { - $this->memcache->delete($this->prefix.$sessionId); - - return true; - } - - /** - * {@inheritdoc} - */ - public function gc($maxlifetime) - { - // not required here because memcache will auto expire the records anyhow. - return true; - } - - /** - * Return a Memcache instance. - * - * @return \Memcache - */ - protected function getMemcache() - { - return $this->memcache; - } -} diff --git a/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/MongoDbSessionHandler.php b/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/MongoDbSessionHandler.php index 20e1a897e480b..c028acd4ffeed 100644 --- a/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/MongoDbSessionHandler.php +++ b/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/MongoDbSessionHandler.php @@ -22,7 +22,7 @@ class MongoDbSessionHandler implements \SessionHandlerInterface { /** - * @var \Mongo|\MongoClient|\MongoDB\Client + * @var \MongoDB\Client */ private $mongo; @@ -65,19 +65,10 @@ class MongoDbSessionHandler implements \SessionHandlerInterface * @param \MongoDB\Client $mongo A MongoDB\Client instance * @param array $options An associative array of field options * - * @throws \InvalidArgumentException When MongoClient or Mongo instance not provided * @throws \InvalidArgumentException When "database" or "collection" not provided */ - public function __construct($mongo, array $options) + public function __construct(\MongoDB\Client $mongo, array $options) { - if ($mongo instanceof \MongoClient || $mongo instanceof \Mongo) { - @trigger_error(sprintf('Using %s with the legacy mongo extension is deprecated as of 3.4 and will be removed in 4.0. Use it with the mongodb/mongodb package and ext-mongodb instead.', __CLASS__), E_USER_DEPRECATED); - } - - if (!($mongo instanceof \MongoDB\Client || $mongo instanceof \MongoClient || $mongo instanceof \Mongo)) { - throw new \InvalidArgumentException('MongoClient or Mongo instance required'); - } - if (!isset($options['database']) || !isset($options['collection'])) { throw new \InvalidArgumentException('You must provide the "database" and "collection" option for MongoDBSessionHandler'); } @@ -113,9 +104,7 @@ public function close() */ public function destroy($sessionId) { - $methodName = $this->mongo instanceof \MongoDB\Client ? 'deleteOne' : 'remove'; - - $this->getCollection()->$methodName(array( + $this->getCollection()->deleteOne(array( $this->options['id_field'] => $sessionId, )); @@ -127,10 +116,8 @@ public function destroy($sessionId) */ public function gc($maxlifetime) { - $methodName = $this->mongo instanceof \MongoDB\Client ? 'deleteOne' : 'remove'; - - $this->getCollection()->$methodName(array( - $this->options['expiry_field'] => array('$lt' => $this->createDateTime()), + $this->getCollection()->deleteOne(array( + $this->options['expiry_field'] => array('$lt' => new \MongoDB\BSON\UTCDateTime()), )); return true; @@ -141,28 +128,18 @@ public function gc($maxlifetime) */ public function write($sessionId, $data) { - $expiry = $this->createDateTime(time() + (int) ini_get('session.gc_maxlifetime')); + $expiry = new \MongoDB\BSON\UTCDateTime((time() + (int) ini_get('session.gc_maxlifetime')) * 1000); $fields = array( - $this->options['time_field'] => $this->createDateTime(), + $this->options['time_field'] => new \MongoDB\BSON\UTCDateTime(), $this->options['expiry_field'] => $expiry, + $this->options['data_field'] => new \MongoDB\BSON\Binary($data, \MongoDB\BSON\Binary::TYPE_OLD_BINARY), ); - $options = array('upsert' => true); - - if ($this->mongo instanceof \MongoDB\Client) { - $fields[$this->options['data_field']] = new \MongoDB\BSON\Binary($data, \MongoDB\BSON\Binary::TYPE_OLD_BINARY); - } else { - $fields[$this->options['data_field']] = new \MongoBinData($data, \MongoBinData::BYTE_ARRAY); - $options['multiple'] = false; - } - - $methodName = $this->mongo instanceof \MongoDB\Client ? 'updateOne' : 'update'; - - $this->getCollection()->$methodName( + $this->getCollection()->updateOne( array($this->options['id_field'] => $sessionId), array('$set' => $fields), - $options + array('upsert' => true) ); return true; @@ -175,23 +152,17 @@ public function read($sessionId) { $dbData = $this->getCollection()->findOne(array( $this->options['id_field'] => $sessionId, - $this->options['expiry_field'] => array('$gte' => $this->createDateTime()), + $this->options['expiry_field'] => array('$gte' => new \MongoDB\BSON\UTCDateTime()), )); if (null === $dbData) { return ''; } - if ($dbData[$this->options['data_field']] instanceof \MongoDB\BSON\Binary) { - return $dbData[$this->options['data_field']]->getData(); - } - - return $dbData[$this->options['data_field']]->bin; + return $dbData[$this->options['data_field']]->getData(); } /** - * Return a "MongoCollection" instance. - * * @return \MongoCollection */ private function getCollection() @@ -204,34 +175,10 @@ private function getCollection() } /** - * Return a Mongo instance. - * - * @return \Mongo|\MongoClient|\MongoDB\Client + * @return \MongoDB\Client */ protected function getMongo() { return $this->mongo; } - - /** - * Create a date object using the class appropriate for the current mongo connection. - * - * Return an instance of a MongoDate or \MongoDB\BSON\UTCDateTime - * - * @param int $seconds An integer representing UTC seconds since Jan 1 1970. Defaults to now. - * - * @return \MongoDate|\MongoDB\BSON\UTCDateTime - */ - private function createDateTime($seconds = null) - { - if (null === $seconds) { - $seconds = time(); - } - - if ($this->mongo instanceof \MongoDB\Client) { - return new \MongoDB\BSON\UTCDateTime($seconds * 1000); - } - - return new \MongoDate($seconds); - } } diff --git a/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/MemcacheSessionHandlerTest.php b/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/MemcacheSessionHandlerTest.php deleted file mode 100644 index d2ddad27d5802..0000000000000 --- a/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/MemcacheSessionHandlerTest.php +++ /dev/null @@ -1,130 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Tests\Session\Storage\Handler; - -use PHPUnit\Framework\TestCase; -use Symfony\Component\HttpFoundation\Session\Storage\Handler\MemcacheSessionHandler; - -/** - * @requires extension memcache - * @group time-sensitive - * @group legacy - */ -class MemcacheSessionHandlerTest extends TestCase -{ - const PREFIX = 'prefix_'; - const TTL = 1000; - /** - * @var MemcacheSessionHandler - */ - protected $storage; - - protected $memcache; - - protected function setUp() - { - parent::setUp(); - $this->memcache = $this->getMockBuilder('Memcache')->getMock(); - $this->storage = new MemcacheSessionHandler( - $this->memcache, - array('prefix' => self::PREFIX, 'expiretime' => self::TTL) - ); - } - - protected function tearDown() - { - $this->memcache = null; - $this->storage = null; - parent::tearDown(); - } - - public function testOpenSession() - { - $this->assertTrue($this->storage->open('', '')); - } - - public function testCloseSession() - { - $this->assertTrue($this->storage->close()); - } - - public function testReadSession() - { - $this->memcache - ->expects($this->once()) - ->method('get') - ->with(self::PREFIX.'id') - ; - - $this->assertEquals('', $this->storage->read('id')); - } - - public function testWriteSession() - { - $this->memcache - ->expects($this->once()) - ->method('set') - ->with(self::PREFIX.'id', 'data', 0, $this->equalTo(time() + self::TTL, 2)) - ->will($this->returnValue(true)) - ; - - $this->assertTrue($this->storage->write('id', 'data')); - } - - public function testDestroySession() - { - $this->memcache - ->expects($this->once()) - ->method('delete') - ->with(self::PREFIX.'id') - ->will($this->returnValue(true)) - ; - - $this->assertTrue($this->storage->destroy('id')); - } - - public function testGcSession() - { - $this->assertTrue($this->storage->gc(123)); - } - - /** - * @dataProvider getOptionFixtures - */ - public function testSupportedOptions($options, $supported) - { - try { - new MemcacheSessionHandler($this->memcache, $options); - $this->assertTrue($supported); - } catch (\InvalidArgumentException $e) { - $this->assertFalse($supported); - } - } - - public function getOptionFixtures() - { - return array( - array(array('prefix' => 'session'), true), - array(array('expiretime' => 100), true), - array(array('prefix' => 'session', 'expiretime' => 200), true), - array(array('expiretime' => 100, 'foo' => 'bar'), false), - ); - } - - public function testGetConnection() - { - $method = new \ReflectionMethod($this->storage, 'getMemcache'); - $method->setAccessible(true); - - $this->assertInstanceOf('\Memcache', $method->invoke($this->storage)); - } -} diff --git a/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/MongoDbSessionHandlerTest.php b/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/MongoDbSessionHandlerTest.php index 89a8c3d0cbb8a..177ee1242d1ee 100644 --- a/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/MongoDbSessionHandlerTest.php +++ b/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/MongoDbSessionHandlerTest.php @@ -32,11 +32,11 @@ protected function setUp() { parent::setUp(); - if (!class_exists('MongoDB\Client')) { + if (!class_exists(\MongoDB\Client::class)) { $this->markTestSkipped('The mongodb/mongodb package is required.'); } - $this->mongo = $this->getMockBuilder('MongoDB\Client') + $this->mongo = $this->getMockBuilder(\MongoDB\Client::class) ->disableOriginalConstructor() ->getMock(); @@ -52,14 +52,6 @@ protected function setUp() $this->storage = new MongoDbSessionHandler($this->mongo, $this->options); } - /** - * @expectedException \InvalidArgumentException - */ - public function testConstructorShouldThrowExceptionForInvalidMongo() - { - new MongoDbSessionHandler(new \stdClass(), $this->options); - } - /** * @expectedException \InvalidArgumentException */ @@ -100,27 +92,14 @@ public function testRead() $this->assertArrayHasKey($this->options['expiry_field'], $criteria); $this->assertArrayHasKey('$gte', $criteria[$this->options['expiry_field']]); - if (phpversion('mongodb')) { - $this->assertInstanceOf('MongoDB\BSON\UTCDateTime', $criteria[$this->options['expiry_field']]['$gte']); - $this->assertGreaterThanOrEqual(round((string) $criteria[$this->options['expiry_field']]['$gte'] / 1000), $testTimeout); - } else { - $this->assertInstanceOf('MongoDate', $criteria[$this->options['expiry_field']]['$gte']); - $this->assertGreaterThanOrEqual($criteria[$this->options['expiry_field']]['$gte']->sec, $testTimeout); - } + $this->assertInstanceOf(\MongoDB\BSON\UTCDateTime::class, $criteria[$this->options['expiry_field']]['$gte']); + $this->assertGreaterThanOrEqual(round((string) $criteria[$this->options['expiry_field']]['$gte'] / 1000), $testTimeout); - $fields = array( + return array( $this->options['id_field'] => 'foo', + $this->options['expiry_field'] => new \MongoDB\BSON\UTCDateTime(), + $this->options['data_field'] => new \MongoDB\BSON\Binary('bar', \MongoDB\BSON\Binary::TYPE_OLD_BINARY), ); - - if (phpversion('mongodb')) { - $fields[$this->options['data_field']] = new \MongoDB\BSON\Binary('bar', \MongoDB\BSON\Binary::TYPE_OLD_BINARY); - $fields[$this->options['id_field']] = new \MongoDB\BSON\UTCDateTime(time() * 1000); - } else { - $fields[$this->options['data_field']] = new \MongoBinData('bar', \MongoBinData::BYTE_ARRAY); - $fields[$this->options['id_field']] = new \MongoDate(); - } - - return $fields; })); $this->assertEquals('bar', $this->storage->read('foo')); @@ -135,89 +114,22 @@ public function testWrite() ->with($this->options['database'], $this->options['collection']) ->will($this->returnValue($collection)); - $data = array(); - - $methodName = phpversion('mongodb') ? 'updateOne' : 'update'; - $collection->expects($this->once()) - ->method($methodName) - ->will($this->returnCallback(function ($criteria, $updateData, $options) use (&$data) { + ->method('updateOne') + ->will($this->returnCallback(function ($criteria, $updateData, $options) { $this->assertEquals(array($this->options['id_field'] => 'foo'), $criteria); - - if (phpversion('mongodb')) { - $this->assertEquals(array('upsert' => true), $options); - } else { - $this->assertEquals(array('upsert' => true, 'multiple' => false), $options); - } + $this->assertEquals(array('upsert' => true), $options); $data = $updateData['$set']; + $expectedExpiry = time() + (int) ini_get('session.gc_maxlifetime'); + $this->assertInstanceOf(\MongoDB\BSON\Binary::class, $data[$this->options['data_field']]); + $this->assertEquals('bar', $data[$this->options['data_field']]->getData()); + $this->assertInstanceOf(\MongoDB\BSON\UTCDateTime::class, $data[$this->options['time_field']]); + $this->assertInstanceOf(\MongoDB\BSON\UTCDateTime::class, $data[$this->options['expiry_field']]); + $this->assertGreaterThanOrEqual($expectedExpiry, round((string) $data[$this->options['expiry_field']] / 1000)); })); - $expectedExpiry = time() + (int) ini_get('session.gc_maxlifetime'); $this->assertTrue($this->storage->write('foo', 'bar')); - - if (phpversion('mongodb')) { - $this->assertEquals('bar', $data[$this->options['data_field']]->getData()); - $this->assertInstanceOf('MongoDB\BSON\UTCDateTime', $data[$this->options['time_field']]); - $this->assertInstanceOf('MongoDB\BSON\UTCDateTime', $data[$this->options['expiry_field']]); - $this->assertGreaterThanOrEqual($expectedExpiry, round((string) $data[$this->options['expiry_field']] / 1000)); - } else { - $this->assertEquals('bar', $data[$this->options['data_field']]->bin); - $this->assertInstanceOf('MongoDate', $data[$this->options['time_field']]); - $this->assertInstanceOf('MongoDate', $data[$this->options['expiry_field']]); - $this->assertGreaterThanOrEqual($expectedExpiry, $data[$this->options['expiry_field']]->sec); - } - } - - public function testWriteWhenUsingExpiresField() - { - $this->options = array( - 'id_field' => '_id', - 'data_field' => 'data', - 'time_field' => 'time', - 'database' => 'sf2-test', - 'collection' => 'session-test', - 'expiry_field' => 'expiresAt', - ); - - $this->storage = new MongoDbSessionHandler($this->mongo, $this->options); - - $collection = $this->createMongoCollectionMock(); - - $this->mongo->expects($this->once()) - ->method('selectCollection') - ->with($this->options['database'], $this->options['collection']) - ->will($this->returnValue($collection)); - - $data = array(); - - $methodName = phpversion('mongodb') ? 'updateOne' : 'update'; - - $collection->expects($this->once()) - ->method($methodName) - ->will($this->returnCallback(function ($criteria, $updateData, $options) use (&$data) { - $this->assertEquals(array($this->options['id_field'] => 'foo'), $criteria); - - if (phpversion('mongodb')) { - $this->assertEquals(array('upsert' => true), $options); - } else { - $this->assertEquals(array('upsert' => true, 'multiple' => false), $options); - } - - $data = $updateData['$set']; - })); - - $this->assertTrue($this->storage->write('foo', 'bar')); - - if (phpversion('mongodb')) { - $this->assertEquals('bar', $data[$this->options['data_field']]->getData()); - $this->assertInstanceOf('MongoDB\BSON\UTCDateTime', $data[$this->options['time_field']]); - $this->assertInstanceOf('MongoDB\BSON\UTCDateTime', $data[$this->options['expiry_field']]); - } else { - $this->assertEquals('bar', $data[$this->options['data_field']]->bin); - $this->assertInstanceOf('MongoDate', $data[$this->options['time_field']]); - $this->assertInstanceOf('MongoDate', $data[$this->options['expiry_field']]); - } } public function testReplaceSessionData() @@ -231,10 +143,8 @@ public function testReplaceSessionData() $data = array(); - $methodName = phpversion('mongodb') ? 'updateOne' : 'update'; - $collection->expects($this->exactly(2)) - ->method($methodName) + ->method('updateOne') ->will($this->returnCallback(function ($criteria, $updateData, $options) use (&$data) { $data = $updateData; })); @@ -242,11 +152,7 @@ public function testReplaceSessionData() $this->storage->write('foo', 'bar'); $this->storage->write('foo', 'foobar'); - if (phpversion('mongodb')) { - $this->assertEquals('foobar', $data['$set'][$this->options['data_field']]->getData()); - } else { - $this->assertEquals('foobar', $data['$set'][$this->options['data_field']]->bin); - } + $this->assertEquals('foobar', $data['$set'][$this->options['data_field']]->getData()); } public function testDestroy() @@ -258,10 +164,8 @@ public function testDestroy() ->with($this->options['database'], $this->options['collection']) ->will($this->returnValue($collection)); - $methodName = phpversion('mongodb') ? 'deleteOne' : 'remove'; - $collection->expects($this->once()) - ->method($methodName) + ->method('deleteOne') ->with(array($this->options['id_field'] => 'foo')); $this->assertTrue($this->storage->destroy('foo')); @@ -276,18 +180,11 @@ public function testGc() ->with($this->options['database'], $this->options['collection']) ->will($this->returnValue($collection)); - $methodName = phpversion('mongodb') ? 'deleteOne' : 'remove'; - $collection->expects($this->once()) - ->method($methodName) + ->method('deleteOne') ->will($this->returnCallback(function ($criteria) { - if (phpversion('mongodb')) { - $this->assertInstanceOf('MongoDB\BSON\UTCDateTime', $criteria[$this->options['expiry_field']]['$lt']); - $this->assertGreaterThanOrEqual(time() - 1, round((string) $criteria[$this->options['expiry_field']]['$lt'] / 1000)); - } else { - $this->assertInstanceOf('MongoDate', $criteria[$this->options['expiry_field']]['$lt']); - $this->assertGreaterThanOrEqual(time() - 1, $criteria[$this->options['expiry_field']]['$lt']->sec); - } + $this->assertInstanceOf(\MongoDB\BSON\UTCDateTime::class, $criteria[$this->options['expiry_field']]['$lt']); + $this->assertGreaterThanOrEqual(time() - 1, round((string) $criteria[$this->options['expiry_field']]['$lt'] / 1000)); })); $this->assertTrue($this->storage->gc(1)); @@ -298,12 +195,12 @@ public function testGetConnection() $method = new \ReflectionMethod($this->storage, 'getMongo'); $method->setAccessible(true); - $this->assertInstanceOf('MongoDB\Client', $method->invoke($this->storage)); + $this->assertInstanceOf(\MongoDB\Client::class, $method->invoke($this->storage)); } private function createMongoCollectionMock() { - $collection = $this->getMockBuilder('MongoDB\Collection') + $collection = $this->getMockBuilder(\MongoDB\Collection::class) ->disableOriginalConstructor() ->getMock(); diff --git a/src/Symfony/Component/VarDumper/Caster/MongoCaster.php b/src/Symfony/Component/VarDumper/Caster/MongoCaster.php deleted file mode 100644 index 2219386bc243d..0000000000000 --- a/src/Symfony/Component/VarDumper/Caster/MongoCaster.php +++ /dev/null @@ -1,38 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\VarDumper\Caster; - -use Symfony\Component\VarDumper\Cloner\Stub; - -@trigger_error('The '.__NAMESPACE__.'\MongoCaster class is deprecated since version 3.4 and will be removed in 4.0.', E_USER_DEPRECATED); - -/** - * Casts classes from the MongoDb extension to array representation. - * - * @author Nicolas Grekas - * - * @deprecated since version 3.4, to be removed in 4.0. - */ -class MongoCaster -{ - public static function castCursor(\MongoCursorInterface $cursor, array $a, Stub $stub, $isNested) - { - if ($info = $cursor->info()) { - foreach ($info as $k => $v) { - $a[Caster::PREFIX_VIRTUAL.$k] = $v; - } - } - $a[Caster::PREFIX_VIRTUAL.'dead'] = $cursor->dead(); - - return $a; - } -} diff --git a/src/Symfony/Component/VarDumper/Cloner/AbstractCloner.php b/src/Symfony/Component/VarDumper/Cloner/AbstractCloner.php index 6c5b5ff4a63eb..c8e6929c6eb6e 100644 --- a/src/Symfony/Component/VarDumper/Cloner/AbstractCloner.php +++ b/src/Symfony/Component/VarDumper/Cloner/AbstractCloner.php @@ -104,8 +104,6 @@ abstract class AbstractCloner implements ClonerInterface 'SplPriorityQueue' => array('Symfony\Component\VarDumper\Caster\SplCaster', 'castHeap'), 'OuterIterator' => array('Symfony\Component\VarDumper\Caster\SplCaster', 'castOuterIterator'), - 'MongoCursorInterface' => array('Symfony\Component\VarDumper\Caster\MongoCaster', 'castCursor'), - 'Redis' => array('Symfony\Component\VarDumper\Caster\RedisCaster', 'castRedis'), 'RedisArray' => array('Symfony\Component\VarDumper\Caster\RedisCaster', 'castRedisArray'), From 3408152365ab971b6193f9501de7a3636d84bd4f Mon Sep 17 00:00:00 2001 From: Robin Chalas Date: Thu, 5 Oct 2017 19:29:32 +0200 Subject: [PATCH 1016/1099] [Security][Guard] Remove GuardAuthenticatorInterface --- src/Symfony/Component/Security/CHANGELOG.md | 2 + .../Guard/AbstractGuardAuthenticator.php | 13 -- .../Security/Guard/AuthenticatorInterface.php | 109 +++++++++++- .../Firewall/GuardAuthenticationListener.php | 24 +-- .../Guard/GuardAuthenticatorHandler.php | 6 +- .../Guard/GuardAuthenticatorInterface.php | 163 ------------------ .../FormLoginAuthenticatorTest.php | 5 + .../GuardAuthenticationListenerTest.php | 126 -------------- .../GuardAuthenticationProviderTest.php | 64 +------ 9 files changed, 124 insertions(+), 388 deletions(-) delete mode 100644 src/Symfony/Component/Security/Guard/GuardAuthenticatorInterface.php diff --git a/src/Symfony/Component/Security/CHANGELOG.md b/src/Symfony/Component/Security/CHANGELOG.md index c8aece01401db..945e3cb3264b4 100644 --- a/src/Symfony/Component/Security/CHANGELOG.md +++ b/src/Symfony/Component/Security/CHANGELOG.md @@ -11,6 +11,8 @@ CHANGELOG * removed support for voters that don't implement the `VoterInterface` * added a sixth `string $context` argument to `LogoutUrlGenerator::registerListener()` * removed HTTP digest authentication + * removed `GuardAuthenticatorInterface` in favor of `AuthenticatorInterface` + * removed `AbstractGuardAuthenticator::supports()` 3.4.0 ----- diff --git a/src/Symfony/Component/Security/Guard/AbstractGuardAuthenticator.php b/src/Symfony/Component/Security/Guard/AbstractGuardAuthenticator.php index 5eceb8470a567..cdfb613593928 100644 --- a/src/Symfony/Component/Security/Guard/AbstractGuardAuthenticator.php +++ b/src/Symfony/Component/Security/Guard/AbstractGuardAuthenticator.php @@ -11,7 +11,6 @@ namespace Symfony\Component\Security\Guard; -use Symfony\Component\HttpFoundation\Request; use Symfony\Component\Security\Core\User\UserInterface; use Symfony\Component\Security\Guard\Token\PostAuthenticationGuardToken; @@ -22,18 +21,6 @@ */ abstract class AbstractGuardAuthenticator implements AuthenticatorInterface { - /** - * {@inheritdoc} - * - * @deprecated since version 3.4, to be removed in 4.0 - */ - public function supports(Request $request) - { - @trigger_error(sprintf('The "%s()" method is deprecated since version 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); - - return true; - } - /** * Shortcut to create a PostAuthenticationGuardToken for you, if you don't really * care about which authenticated token you're using. diff --git a/src/Symfony/Component/Security/Guard/AuthenticatorInterface.php b/src/Symfony/Component/Security/Guard/AuthenticatorInterface.php index f68b8d6f43b08..10577d74cdffc 100644 --- a/src/Symfony/Component/Security/Guard/AuthenticatorInterface.php +++ b/src/Symfony/Component/Security/Guard/AuthenticatorInterface.php @@ -12,6 +12,13 @@ namespace Symfony\Component\Security\Guard; use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; +use Symfony\Component\Security\Core\Exception\AuthenticationException; +use Symfony\Component\Security\Core\User\UserInterface; +use Symfony\Component\Security\Core\User\UserProviderInterface; +use Symfony\Component\Security\Guard\Token\GuardTokenInterface; +use Symfony\Component\Security\Http\EntryPoint\AuthenticationEntryPointInterface; /** * The interface for all "guard" authenticators. @@ -23,7 +30,7 @@ * @author Ryan Weaver * @author Amaury Leroux de Lens */ -interface AuthenticatorInterface extends GuardAuthenticatorInterface +interface AuthenticatorInterface extends AuthenticationEntryPointInterface { /** * Does the authenticator support the given Request? @@ -60,4 +67,104 @@ public function supports(Request $request); * @throws \UnexpectedValueException If null is returned */ public function getCredentials(Request $request); + + /** + * Return a UserInterface object based on the credentials. + * + * The *credentials* are the return value from getCredentials() + * + * You may throw an AuthenticationException if you wish. If you return + * null, then a UsernameNotFoundException is thrown for you. + * + * @param mixed $credentials + * @param UserProviderInterface $userProvider + * + * @throws AuthenticationException + * + * @return UserInterface|null + */ + public function getUser($credentials, UserProviderInterface $userProvider); + + /** + * Returns true if the credentials are valid. + * + * If any value other than true is returned, authentication will + * fail. You may also throw an AuthenticationException if you wish + * to cause authentication to fail. + * + * The *credentials* are the return value from getCredentials() + * + * @param mixed $credentials + * @param UserInterface $user + * + * @return bool + * + * @throws AuthenticationException + */ + public function checkCredentials($credentials, UserInterface $user); + + /** + * Create an authenticated token for the given user. + * + * If you don't care about which token class is used or don't really + * understand what a "token" is, you can skip this method by extending + * the AbstractGuardAuthenticator class from your authenticator. + * + * @see AbstractGuardAuthenticator + * + * @param UserInterface $user + * @param string $providerKey The provider (i.e. firewall) key + * + * @return GuardTokenInterface + */ + 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. + * + * If you return null, the request will continue, but the user will + * not be authenticated. This is probably not what you want to do. + * + * @param Request $request + * @param AuthenticationException $exception + * + * @return Response|null + */ + public function onAuthenticationFailure(Request $request, AuthenticationException $exception); + + /** + * Called when authentication executed and was successful! + * + * This should return the Response sent back to the user, like a + * RedirectResponse to the last page they visited. + * + * If you return null, the current request will continue, and the user + * will be authenticated. This makes sense, for example, with an API. + * + * @param Request $request + * @param TokenInterface $token + * @param string $providerKey The provider (i.e. firewall) key + * + * @return Response|null + */ + public function onAuthenticationSuccess(Request $request, TokenInterface $token, $providerKey); + + /** + * Does this method support remember me cookies? + * + * Remember me cookie will be set if *all* of the following are met: + * A) This method returns true + * B) The remember_me key under your firewall is configured + * C) The "remember me" functionality is activated. This is usually + * done by having a _remember_me checkbox in your form, but + * can be configured by the "always_remember_me" and "remember_me_parameter" + * parameters under the "remember_me" firewall key + * D) The onAuthenticationSuccess method returns a Response object + * + * @return bool + */ + public function supportsRememberMe(); } diff --git a/src/Symfony/Component/Security/Guard/Firewall/GuardAuthenticationListener.php b/src/Symfony/Component/Security/Guard/Firewall/GuardAuthenticationListener.php index 4ec0b8f32630d..0e2c7d91b2533 100644 --- a/src/Symfony/Component/Security/Guard/Firewall/GuardAuthenticationListener.php +++ b/src/Symfony/Component/Security/Guard/Firewall/GuardAuthenticationListener.php @@ -15,10 +15,9 @@ use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\Event\GetResponseEvent; use Symfony\Component\Security\Guard\GuardAuthenticatorHandler; -use Symfony\Component\Security\Guard\GuardAuthenticatorInterface; +use Symfony\Component\Security\Guard\AuthenticatorInterface; use Symfony\Component\Security\Guard\Token\PreAuthenticationGuardToken; use Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface; -use Symfony\Component\Security\Guard\AuthenticatorInterface; use Psr\Log\LoggerInterface; use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; use Symfony\Component\Security\Core\Exception\AuthenticationException; @@ -94,7 +93,7 @@ public function handle(GetResponseEvent $event) } } - private function executeGuardAuthenticator($uniqueGuardKey, GuardAuthenticatorInterface $guardAuthenticator, GetResponseEvent $event) + private function executeGuardAuthenticator($uniqueGuardKey, AuthenticatorInterface $guardAuthenticator, GetResponseEvent $event) { $request = $event->getRequest(); try { @@ -103,27 +102,14 @@ private function executeGuardAuthenticator($uniqueGuardKey, GuardAuthenticatorIn } // abort the execution of the authenticator if it doesn't support the request - if ($guardAuthenticator instanceof AuthenticatorInterface) { - if (!$guardAuthenticator->supports($request)) { - return; - } - // as there was a support for given request, - // authenticator is expected to give not-null credentials. - $credentialsCanBeNull = false; - } else { - // deprecated since version 3.4, to be removed in 4.0 - $credentialsCanBeNull = true; + if (!$guardAuthenticator->supports($request)) { + return; } // allow the authenticator to fetch authentication info from the request $credentials = $guardAuthenticator->getCredentials($request); if (null === $credentials) { - // deprecated since version 3.4, to be removed in 4.0 - if ($credentialsCanBeNull) { - return; - } - throw new \UnexpectedValueException(sprintf('The return value of "%s::getCredentials()" must not be null. Return false from "%s::supports()" instead.', get_class($guardAuthenticator), get_class($guardAuthenticator))); } @@ -196,7 +182,7 @@ public function setRememberMeServices(RememberMeServicesInterface $rememberMeSer * @param TokenInterface $token * @param Response $response */ - private function triggerRememberMe(GuardAuthenticatorInterface $guardAuthenticator, Request $request, TokenInterface $token, Response $response = null) + private function triggerRememberMe(AuthenticatorInterface $guardAuthenticator, Request $request, TokenInterface $token, Response $response = null) { if (null === $this->rememberMeServices) { if (null !== $this->logger) { diff --git a/src/Symfony/Component/Security/Guard/GuardAuthenticatorHandler.php b/src/Symfony/Component/Security/Guard/GuardAuthenticatorHandler.php index abe263d888d5f..8bec87c318d80 100644 --- a/src/Symfony/Component/Security/Guard/GuardAuthenticatorHandler.php +++ b/src/Symfony/Component/Security/Guard/GuardAuthenticatorHandler.php @@ -70,7 +70,7 @@ public function authenticateWithToken(TokenInterface $token, Request $request) * * @return null|Response */ - public function handleAuthenticationSuccess(TokenInterface $token, Request $request, GuardAuthenticatorInterface $guardAuthenticator, $providerKey) + public function handleAuthenticationSuccess(TokenInterface $token, Request $request, AuthenticatorInterface $guardAuthenticator, $providerKey) { $response = $guardAuthenticator->onAuthenticationSuccess($request, $token, $providerKey); @@ -97,7 +97,7 @@ public function handleAuthenticationSuccess(TokenInterface $token, Request $requ * * @return Response|null */ - public function authenticateUserAndHandleSuccess(UserInterface $user, Request $request, GuardAuthenticatorInterface $authenticator, $providerKey) + public function authenticateUserAndHandleSuccess(UserInterface $user, Request $request, AuthenticatorInterface $authenticator, $providerKey) { // create an authenticated token for the User $token = $authenticator->createAuthenticatedToken($user, $providerKey); @@ -119,7 +119,7 @@ public function authenticateUserAndHandleSuccess(UserInterface $user, Request $r * * @return null|Response */ - public function handleAuthenticationFailure(AuthenticationException $authenticationException, Request $request, GuardAuthenticatorInterface $guardAuthenticator, $providerKey) + public function handleAuthenticationFailure(AuthenticationException $authenticationException, Request $request, AuthenticatorInterface $guardAuthenticator, $providerKey) { $token = $this->tokenStorage->getToken(); if ($token instanceof PostAuthenticationGuardToken && $providerKey === $token->getProviderKey()) { diff --git a/src/Symfony/Component/Security/Guard/GuardAuthenticatorInterface.php b/src/Symfony/Component/Security/Guard/GuardAuthenticatorInterface.php deleted file mode 100644 index 0d11573c03b11..0000000000000 --- a/src/Symfony/Component/Security/Guard/GuardAuthenticatorInterface.php +++ /dev/null @@ -1,163 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Security\Guard; - -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\Response; -use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; -use Symfony\Component\Security\Core\Exception\AuthenticationException; -use Symfony\Component\Security\Core\User\UserInterface; -use Symfony\Component\Security\Core\User\UserProviderInterface; -use Symfony\Component\Security\Guard\Token\GuardTokenInterface; -use Symfony\Component\Security\Http\EntryPoint\AuthenticationEntryPointInterface; - -/** - * The interface for all "guard" authenticators. - * - * The methods on this interface are called throughout the guard authentication - * process to give you the power to control most parts of the process from - * one location. - * - * @author Ryan Weaver - * - * @deprecated since version 3.4, to be removed in 4.0. Use AuthenticatorInterface instead - */ -interface GuardAuthenticatorInterface extends AuthenticationEntryPointInterface -{ - /** - * Get the authentication credentials from the request and return them - * as any type (e.g. an associate array). If you return null, authentication - * will be skipped. - * - * Whatever value you return here will be passed to getUser() and checkCredentials() - * - * For example, for a form login, you might: - * - * if ($request->request->has('_username')) { - * return array( - * 'username' => $request->request->get('_username'), - * 'password' => $request->request->get('_password'), - * ); - * } else { - * return; - * } - * - * Or for an API token that's on a header, you might use: - * - * return array('api_key' => $request->headers->get('X-API-TOKEN')); - * - * @param Request $request - * - * @return mixed|null - */ - public function getCredentials(Request $request); - - /** - * Return a UserInterface object based on the credentials. - * - * The *credentials* are the return value from getCredentials() - * - * You may throw an AuthenticationException if you wish. If you return - * null, then a UsernameNotFoundException is thrown for you. - * - * @param mixed $credentials - * @param UserProviderInterface $userProvider - * - * @throws AuthenticationException - * - * @return UserInterface|null - */ - public function getUser($credentials, UserProviderInterface $userProvider); - - /** - * Returns true if the credentials are valid. - * - * If any value other than true is returned, authentication will - * fail. You may also throw an AuthenticationException if you wish - * to cause authentication to fail. - * - * The *credentials* are the return value from getCredentials() - * - * @param mixed $credentials - * @param UserInterface $user - * - * @return bool - * - * @throws AuthenticationException - */ - public function checkCredentials($credentials, UserInterface $user); - - /** - * Create an authenticated token for the given user. - * - * If you don't care about which token class is used or don't really - * understand what a "token" is, you can skip this method by extending - * the AbstractGuardAuthenticator class from your authenticator. - * - * @see AbstractGuardAuthenticator - * - * @param UserInterface $user - * @param string $providerKey The provider (i.e. firewall) key - * - * @return GuardTokenInterface - */ - 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. - * - * If you return null, the request will continue, but the user will - * not be authenticated. This is probably not what you want to do. - * - * @param Request $request - * @param AuthenticationException $exception - * - * @return Response|null - */ - public function onAuthenticationFailure(Request $request, AuthenticationException $exception); - - /** - * Called when authentication executed and was successful! - * - * This should return the Response sent back to the user, like a - * RedirectResponse to the last page they visited. - * - * If you return null, the current request will continue, and the user - * will be authenticated. This makes sense, for example, with an API. - * - * @param Request $request - * @param TokenInterface $token - * @param string $providerKey The provider (i.e. firewall) key - * - * @return Response|null - */ - public function onAuthenticationSuccess(Request $request, TokenInterface $token, $providerKey); - - /** - * Does this method support remember me cookies? - * - * Remember me cookie will be set if *all* of the following are met: - * A) This method returns true - * B) The remember_me key under your firewall is configured - * C) The "remember me" functionality is activated. This is usually - * done by having a _remember_me checkbox in your form, but - * can be configured by the "always_remember_me" and "remember_me_parameter" - * parameters under the "remember_me" firewall key - * D) The onAuthenticationSuccess method returns a Response object - * - * @return bool - */ - public function supportsRememberMe(); -} diff --git a/src/Symfony/Component/Security/Guard/Tests/Authenticator/FormLoginAuthenticatorTest.php b/src/Symfony/Component/Security/Guard/Tests/Authenticator/FormLoginAuthenticatorTest.php index 1789b95d8c4ed..e9759cd4f2ec0 100644 --- a/src/Symfony/Component/Security/Guard/Tests/Authenticator/FormLoginAuthenticatorTest.php +++ b/src/Symfony/Component/Security/Guard/Tests/Authenticator/FormLoginAuthenticatorTest.php @@ -104,6 +104,11 @@ class TestFormLoginAuthenticator extends AbstractFormLoginAuthenticator private $loginUrl; private $defaultSuccessRedirectUrl; + public function supports(Request $request) + { + return true; + } + public function onAuthenticationSuccess(Request $request, TokenInterface $token, $providerKey) { } diff --git a/src/Symfony/Component/Security/Guard/Tests/Firewall/GuardAuthenticationListenerTest.php b/src/Symfony/Component/Security/Guard/Tests/Firewall/GuardAuthenticationListenerTest.php index 5af9f130f8645..e4a47fd8f0eb9 100644 --- a/src/Symfony/Component/Security/Guard/Tests/Firewall/GuardAuthenticationListenerTest.php +++ b/src/Symfony/Component/Security/Guard/Tests/Firewall/GuardAuthenticationListenerTest.php @@ -17,7 +17,6 @@ use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; use Symfony\Component\Security\Guard\AuthenticatorInterface; use Symfony\Component\Security\Guard\Firewall\GuardAuthenticationListener; -use Symfony\Component\Security\Guard\GuardAuthenticatorInterface; use Symfony\Component\Security\Guard\Token\PreAuthenticationGuardToken; use Symfony\Component\Security\Core\Exception\AuthenticationException; @@ -207,131 +206,6 @@ public function testHandleCatchesAuthenticationException() $listener->handle($this->event); } - /** - * @group legacy - */ - public function testLegacyInterfaceNullCredentials() - { - $authenticatorA = $this->getMockBuilder(GuardAuthenticatorInterface::class)->getMock(); - $providerKey = 'my_firewall3'; - - $authenticatorA - ->expects($this->once()) - ->method('getCredentials') - ->will($this->returnValue(null)); - - // this is not called - $this->authenticationManager - ->expects($this->never()) - ->method('authenticate'); - - $this->guardAuthenticatorHandler - ->expects($this->never()) - ->method('handleAuthenticationSuccess'); - - $listener = new GuardAuthenticationListener( - $this->guardAuthenticatorHandler, - $this->authenticationManager, - $providerKey, - array($authenticatorA), - $this->logger - ); - - $listener->handle($this->event); - } - - /** - * @group legacy - */ - public function testLegacyInterfaceKeepsWorking() - { - $authenticator = $this->getMockBuilder(GuardAuthenticatorInterface::class)->getMock(); - $authenticateToken = $this->getMockBuilder(TokenInterface::class)->getMock(); - $providerKey = 'my_firewall'; - - $credentials = array('username' => 'weaverryan', 'password' => 'all_your_base'); - - $authenticator - ->expects($this->once()) - ->method('getCredentials') - ->with($this->equalTo($this->request)) - ->will($this->returnValue($credentials)); - - // a clone of the token that should be created internally - $uniqueGuardKey = 'my_firewall_0'; - $nonAuthedToken = new PreAuthenticationGuardToken($credentials, $uniqueGuardKey); - - $this->authenticationManager - ->expects($this->once()) - ->method('authenticate') - ->with($this->equalTo($nonAuthedToken)) - ->will($this->returnValue($authenticateToken)); - - $this->guardAuthenticatorHandler - ->expects($this->once()) - ->method('authenticateWithToken') - ->with($authenticateToken, $this->request); - - $this->guardAuthenticatorHandler - ->expects($this->once()) - ->method('handleAuthenticationSuccess') - ->with($authenticateToken, $this->request, $authenticator, $providerKey); - - $listener = new GuardAuthenticationListener( - $this->guardAuthenticatorHandler, - $this->authenticationManager, - $providerKey, - array($authenticator), - $this->logger - ); - - $listener->setRememberMeServices($this->rememberMeServices); - // should never be called - our handleAuthenticationSuccess() does not return a Response - $this->rememberMeServices - ->expects($this->never()) - ->method('loginSuccess'); - - $listener->handle($this->event); - } - - /** - * @group legacy - */ - public function testReturnNullToSkipAuth() - { - $authenticatorA = $this->getMockBuilder('Symfony\Component\Security\Guard\GuardAuthenticatorInterface')->getMock(); - $authenticatorB = $this->getMockBuilder('Symfony\Component\Security\Guard\GuardAuthenticatorInterface')->getMock(); - $providerKey = 'my_firewall3'; - - $authenticatorA - ->expects($this->once()) - ->method('getCredentials') - ->will($this->returnValue(null)); - $authenticatorB - ->expects($this->once()) - ->method('getCredentials') - ->will($this->returnValue(null)); - - // this is not called - $this->authenticationManager - ->expects($this->never()) - ->method('authenticate'); - - $this->guardAuthenticatorHandler - ->expects($this->never()) - ->method('handleAuthenticationSuccess'); - - $listener = new GuardAuthenticationListener( - $this->guardAuthenticatorHandler, - $this->authenticationManager, - $providerKey, - array($authenticatorA, $authenticatorB), - $this->logger - ); - - $listener->handle($this->event); - } - public function testSupportsReturnFalseSkipAuth() { $authenticator = $this->getMockBuilder(AuthenticatorInterface::class)->getMock(); diff --git a/src/Symfony/Component/Security/Guard/Tests/Provider/GuardAuthenticationProviderTest.php b/src/Symfony/Component/Security/Guard/Tests/Provider/GuardAuthenticationProviderTest.php index 9d8301fce8011..71b53f62f36b2 100644 --- a/src/Symfony/Component/Security/Guard/Tests/Provider/GuardAuthenticationProviderTest.php +++ b/src/Symfony/Component/Security/Guard/Tests/Provider/GuardAuthenticationProviderTest.php @@ -86,68 +86,6 @@ public function testAuthenticate() $this->assertSame($authedToken, $actualAuthedToken); } - /** - * @group legacy - */ - public function testLegacyAuthenticate() - { - $providerKey = 'my_cool_firewall'; - - $authenticatorA = $this->getMockBuilder('Symfony\Component\Security\Guard\GuardAuthenticatorInterface')->getMock(); - $authenticatorB = $this->getMockBuilder('Symfony\Component\Security\Guard\GuardAuthenticatorInterface')->getMock(); - $authenticatorC = $this->getMockBuilder('Symfony\Component\Security\Guard\GuardAuthenticatorInterface')->getMock(); - $authenticators = array($authenticatorA, $authenticatorB, $authenticatorC); - - // called 2 times - for authenticator A and B (stops on B because of match) - $this->preAuthenticationToken->expects($this->exactly(2)) - ->method('getGuardProviderKey') - // it will return the "1" index, which will match authenticatorB - ->will($this->returnValue('my_cool_firewall_1')); - - $enteredCredentials = array( - 'username' => '_weaverryan_test_user', - 'password' => 'guard_auth_ftw', - ); - $this->preAuthenticationToken->expects($this->atLeastOnce()) - ->method('getCredentials') - ->will($this->returnValue($enteredCredentials)); - - // authenticators A and C are never called - $authenticatorA->expects($this->never()) - ->method('getUser'); - $authenticatorC->expects($this->never()) - ->method('getUser'); - - $mockedUser = $this->getMockBuilder('Symfony\Component\Security\Core\User\UserInterface')->getMock(); - $authenticatorB->expects($this->once()) - ->method('getUser') - ->with($enteredCredentials, $this->userProvider) - ->will($this->returnValue($mockedUser)); - // checkCredentials is called - $authenticatorB->expects($this->once()) - ->method('checkCredentials') - ->with($enteredCredentials, $mockedUser) - // authentication works! - ->will($this->returnValue(true)); - $authedToken = $this->getMockBuilder('Symfony\Component\Security\Core\Authentication\Token\TokenInterface')->getMock(); - $authenticatorB->expects($this->once()) - ->method('createAuthenticatedToken') - ->with($mockedUser, $providerKey) - ->will($this->returnValue($authedToken)); - - // user checker should be called - $this->userChecker->expects($this->once()) - ->method('checkPreAuth') - ->with($mockedUser); - $this->userChecker->expects($this->once()) - ->method('checkPostAuth') - ->with($mockedUser); - - $provider = new GuardAuthenticationProvider($authenticators, $this->userProvider, $providerKey, $this->userChecker); - $actualAuthedToken = $provider->authenticate($this->preAuthenticationToken); - $this->assertSame($authedToken, $actualAuthedToken); - } - /** * @expectedException \Symfony\Component\Security\Core\Exception\BadCredentialsException */ @@ -155,7 +93,7 @@ public function testCheckCredentialsReturningNonTrueFailsAuthentication() { $providerKey = 'my_uncool_firewall'; - $authenticator = $this->getMockBuilder('Symfony\Component\Security\Guard\GuardAuthenticatorInterface')->getMock(); + $authenticator = $this->getMockBuilder(AuthenticatorInterface::class)->getMock(); // make sure the authenticator is used $this->preAuthenticationToken->expects($this->any()) From e6895bfac53e12e76e2552ed17e582a3d13d416a Mon Sep 17 00:00:00 2001 From: Tobias Schultze Date: Thu, 5 Oct 2017 21:04:13 +0200 Subject: [PATCH 1017/1099] [Session] fix MongoDb session handler to gc all expired sessions --- .../Session/Storage/Handler/MongoDbSessionHandler.php | 2 +- .../Tests/Session/Storage/Handler/MongoDbSessionHandlerTest.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/MongoDbSessionHandler.php b/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/MongoDbSessionHandler.php index 80ecc1cc3c788..f140939dbd49a 100644 --- a/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/MongoDbSessionHandler.php +++ b/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/MongoDbSessionHandler.php @@ -118,7 +118,7 @@ public function destroy($sessionId) */ public function gc($maxlifetime) { - $methodName = $this->mongo instanceof \MongoDB\Client ? 'deleteOne' : 'remove'; + $methodName = $this->mongo instanceof \MongoDB\Client ? 'deleteMany' : 'remove'; $this->getCollection()->$methodName(array( $this->options['expiry_field'] => array('$lt' => $this->createDateTime()), diff --git a/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/MongoDbSessionHandlerTest.php b/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/MongoDbSessionHandlerTest.php index 128b9b52f505f..8ea0c52a87d71 100644 --- a/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/MongoDbSessionHandlerTest.php +++ b/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/MongoDbSessionHandlerTest.php @@ -291,7 +291,7 @@ public function testGc() $that = $this; - $methodName = phpversion('mongodb') ? 'deleteOne' : 'remove'; + $methodName = phpversion('mongodb') ? 'deleteMany' : 'remove'; $collection->expects($this->once()) ->method($methodName) From 261eae970f351a0cfc8006cbf7ea97080f24cef8 Mon Sep 17 00:00:00 2001 From: Alex Bowers Date: Fri, 28 Jul 2017 22:09:12 +0100 Subject: [PATCH 1018/1099] Added deprecation to cwd not existing Fixes #18249 --- UPGRADE-3.4.md | 2 + UPGRADE-4.0.md | 2 + src/Symfony/Component/Process/CHANGELOG.md | 1 + src/Symfony/Component/Process/Process.php | 16 +++++-- .../Component/Process/Tests/ProcessTest.php | 44 ++++++++++++++++++- 5 files changed, 59 insertions(+), 6 deletions(-) diff --git a/UPGRADE-3.4.md b/UPGRADE-3.4.md index 2c80252b5b8ab..9ad662ffed825 100644 --- a/UPGRADE-3.4.md +++ b/UPGRADE-3.4.md @@ -210,6 +210,8 @@ Process * The `Symfony\Component\Process\ProcessBuilder` class has been deprecated, use the `Symfony\Component\Process\Process` class directly instead. + * Calling `Process::start()` without setting a valid working directory (via `setWorkingDirectory()` or constructor) beforehand is deprecated and will throw an exception in 4.0. + Profiler -------- diff --git a/UPGRADE-4.0.md b/UPGRADE-4.0.md index 9f8017c47e8a4..59f4607863ad1 100644 --- a/UPGRADE-4.0.md +++ b/UPGRADE-4.0.md @@ -567,6 +567,8 @@ Ldap Process ------- + * Passing a not existing working directory to the constructor of the `Symfony\Component\Process\Process` class is not supported anymore. + * The `Symfony\Component\Process\ProcessBuilder` class has been removed, use the `Symfony\Component\Process\Process` class directly instead. diff --git a/src/Symfony/Component/Process/CHANGELOG.md b/src/Symfony/Component/Process/CHANGELOG.md index 7193c498d4326..c5cdb9944164b 100644 --- a/src/Symfony/Component/Process/CHANGELOG.md +++ b/src/Symfony/Component/Process/CHANGELOG.md @@ -5,6 +5,7 @@ CHANGELOG ----- * deprecated the ProcessBuilder class + * deprecated calling `Process::start()` without setting a valid working directory beforehand (via `setWorkingDirectory()` or constructor) 3.3.0 ----- diff --git a/src/Symfony/Component/Process/Process.php b/src/Symfony/Component/Process/Process.php index e925e913863a9..79cb20cb66ebd 100644 --- a/src/Symfony/Component/Process/Process.php +++ b/src/Symfony/Component/Process/Process.php @@ -334,6 +334,14 @@ public function start(callable $callback = null/*, array $env = array()*/) $ptsWorkaround = fopen(__FILE__, 'r'); } + if (!is_dir($this->cwd)) { + if ('\\' === DIRECTORY_SEPARATOR) { + throw new RuntimeException('The provided cwd does not exist.'); + } + + @trigger_error('The provided cwd does not exist. Command is currently ran against getcwd(). This behavior is deprecated since version 3.4 and will be removed in 4.0.', E_USER_DEPRECATED); + } + $this->process = proc_open($commandline, $descriptors, $this->processPipes->pipes, $this->cwd, $env, $this->options); foreach ($envBackup as $k => $v) { @@ -831,7 +839,7 @@ public function isRunning() */ public function isStarted() { - return $this->status != self::STATUS_READY; + return self::STATUS_READY != $this->status; } /** @@ -843,7 +851,7 @@ public function isTerminated() { $this->updateStatus(false); - return $this->status == self::STATUS_TERMINATED; + return self::STATUS_TERMINATED == $this->status; } /** @@ -1322,7 +1330,7 @@ public function areEnvironmentVariablesInherited() */ public function checkTimeout() { - if ($this->status !== self::STATUS_STARTED) { + if (self::STATUS_STARTED !== $this->status) { return; } @@ -1513,7 +1521,7 @@ private function readPipes($blocking, $close) $callback = $this->callback; foreach ($result as $type => $data) { if (3 !== $type) { - $callback($type === self::STDOUT ? self::OUT : self::ERR, $data); + $callback(self::STDOUT === $type ? self::OUT : self::ERR, $data); } elseif (!isset($this->fallbackStatus['signaled'])) { $this->fallbackStatus['exitcode'] = (int) $data; } diff --git a/src/Symfony/Component/Process/Tests/ProcessTest.php b/src/Symfony/Component/Process/Tests/ProcessTest.php index 267257117d43d..1ad601c715aaf 100644 --- a/src/Symfony/Component/Process/Tests/ProcessTest.php +++ b/src/Symfony/Component/Process/Tests/ProcessTest.php @@ -48,6 +48,46 @@ protected function tearDown() } } + /** + * @group legacy + * @expectedDeprecation The provided cwd does not exist. Command is currently ran against getcwd(). This behavior is deprecated since version 3.4 and will be removed in 4.0. + */ + public function testInvalidCwd() + { + if ('\\' === DIRECTORY_SEPARATOR) { + $this->markTestSkipped('Windows handles this automatically.'); + } + + // Check that it works fine if the CWD exists + $cmd = new Process('echo test', __DIR__); + $cmd->run(); + + $cmd = new Process('echo test', __DIR__.'/notfound/'); + $cmd->run(); + } + + /** + * @expectedException \Symfony\Component\Process\Exception\RuntimeException + * @expectedExceptionMessage The provided cwd does not exist. + */ + public function testInvalidCwdOnWindows() + { + if ('\\' !== DIRECTORY_SEPARATOR) { + $this->markTestSkipped('Unix handles this automatically.'); + } + + try { + // Check that it works fine if the CWD exists + $cmd = new Process('echo test', __DIR__); + $cmd->run(); + } catch (\Exception $e) { + $this->fail($e); + } + + $cmd = new Process('echo test', __DIR__.'/notfound/'); + $cmd->run(); + } + public function testThatProcessDoesNotThrowWarningDuringRun() { if ('\\' === DIRECTORY_SEPARATOR) { @@ -313,7 +353,7 @@ public function testCallbackIsExecutedForOutput() $called = false; $p->run(function ($type, $buffer) use (&$called) { - $called = $buffer === 'foo'; + $called = 'foo' === $buffer; }); $this->assertTrue($called, 'The callback should be executed with the output'); @@ -326,7 +366,7 @@ public function testCallbackIsExecutedForOutputWheneverOutputIsDisabled() $called = false; $p->run(function ($type, $buffer) use (&$called) { - $called = $buffer === 'foo'; + $called = 'foo' === $buffer; }); $this->assertTrue($called, 'The callback should be executed with the output'); From 88f8c6526a741178c31388106c0cfb5b0fa5b366 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Thu, 5 Oct 2017 15:51:42 -0700 Subject: [PATCH 1019/1099] updated CHANGELOG for 2.7.35 --- CHANGELOG-2.7.md | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/CHANGELOG-2.7.md b/CHANGELOG-2.7.md index f742ca8ea0385..4a58749b55582 100644 --- a/CHANGELOG-2.7.md +++ b/CHANGELOG-2.7.md @@ -7,6 +7,33 @@ in 2.7 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/v2.7.0...v2.7.1 +* 2.7.35 (2017-10-05) + + * bug #24448 [Session] fix MongoDb session handler to gc all expired sessions (Tobion) + * bug #24417 [Yaml] parse references on merge keys (xabbuh) + * bug #24421 [Config] Fix dumped files invalidation by OPCache (nicolas-grekas) + * bug #23980 Tests and fix for issue in array model data in EntityType field with multiple=true (stoccc) + * bug #22586 [Form] Fixed PercentToLocalizedStringTransformer to accept both comma and dot as decimal separator, if possible (aaa2000) + * bug #24157 [Intl] Fixed support of Locale::getFallback (lyrixx) + * bug #24198 [HttpFoundation] Fix file upload multiple with no files (enumag) + * bug #24036 [Form] Fix precision of MoneyToLocalizedStringTransformer's divisions and multiplications (Rubinum) + * bug #24367 PdoSessionHandler: fix advisory lock for pgsql (Tobion) + * bug #24243 HttpCache does not consider ESI resources in HEAD requests (mpdude) + * bug #24304 [FrameworkBundle] Fix Routing\DelegatingLoader (nicolas-grekas) + * bug #24219 [Console] Preserving line breaks between sentences according to the exception message (yceruto) + * bug #23722 [Form] Fixed GroupSequence with "constraints" option (HeahDude) + * bug #22321 [Filesystem] Fixed makePathRelative (ausi) + * bug #23473 [Filesystem] mirror - fix copying content with same name as source/target. (gitlost) + * bug #24162 [WebProfilerBundle] fixed TemplateManager when using Twig 2 without compat interfaces (fabpot) + * bug #24141 [DomCrawler] Fix conversion to int on GetPhpFiles (MaraBlaga) + * bug #23853 Filtering empty uuids in ORMQueryBuilderLoader. (mlazovla) + * bug #24101 [Security] Fix exception when use_referer option is true and referer is not set or empty (linniksa) + * bug #24105 [Filesystem] check permissions if dump target dir is missing (xabbuh) + * bug #24115 [FrameworkBundle] Get KERNEL_DIR through $_ENV too for KernelTestCase (yceruto) + * bug #24041 [ExpressionLanguage] throws an exception on calling uncallable method (fmata) + * bug #24096 Fix ArrayInput::toString() for VALUE_IS_ARRAY options/args (chalasr) + * bug #23730 Fixed the escaping of back slashes and << in console output (javiereguiluz) + * 2.7.34 (2017-08-28) * bug #23989 [Debug] Remove false-positive check in DebugClassLoader (nicolas-grekas) From 4d3f3255dda5465191d8e2d1f5f44276a61baf7c Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Thu, 5 Oct 2017 15:51:49 -0700 Subject: [PATCH 1020/1099] update CONTRIBUTORS for 2.7.35 --- CONTRIBUTORS.md | 99 ++++++++++++++++++++++++++++++++----------------- 1 file changed, 64 insertions(+), 35 deletions(-) diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md index ced9b18126294..450e53dbc0947 100644 --- a/CONTRIBUTORS.md +++ b/CONTRIBUTORS.md @@ -18,9 +18,9 @@ Symfony is the result of the work of many people who made the code better - Kévin Dunglas (dunglas) - Ryan Weaver (weaverryan) - Javier Eguiluz (javier.eguiluz) - - Hugo Hamon (hhamon) - Maxime Steinhausser (ogizanagi) - Robin Chalas (chalas_r) + - Hugo Hamon (hhamon) - Abdellatif Ait boudad (aitboudad) - Grégoire Pineau (lyrixx) - Romain Neutron (romain) @@ -31,10 +31,10 @@ Symfony is the result of the work of many people who made the code better - Lukas Kahwe Smith (lsmith) - Martin Hasoň (hason) - Jeremy Mikola (jmikola) + - Roland Franssen (ro0) - Jean-François Simon (jfsimon) - Benjamin Eberlei (beberlei) - Igor Wiedler (igorw) - - Roland Franssen (ro0) - Eriksen Costa (eriksencosta) - Jules Pietri (heah) - Guilhem Niot (energetick) @@ -47,39 +47,42 @@ Symfony is the result of the work of many people who made the code better - Francis Besset (francisbesset) - stealth35 ‏ (stealth35) - Alexander Mols (asm89) - - Bulat Shakirzyanov (avalanche123) - Iltar van der Berg (kjarli) + - Bulat Shakirzyanov (avalanche123) - Peter Rehm (rpet) - Saša Stamenković (umpirsky) - Henrik Bjørnskov (henrikbjorn) - Miha Vrhovnik + - Matthias Pigulla (mpdude) - Diego Saint Esteben (dii3g0) - Konstantin Kudryashov (everzet) - - Matthias Pigulla (mpdude) - Bilal Amarni (bamarni) - Florin Patan (florinpatan) - - Gábor Egyed (1ed) + - Dany Maillard (maidmaid) + - Jérémy DERUSSÉ (jderusse) - Kevin Bond (kbond) - - Andrej Hudec (pulzarraider) + - Yonel Ceruto (yonelceruto) + - Gábor Egyed (1ed) - Pierre du Plessis (pierredup) + - Andrej Hudec (pulzarraider) - Michel Weimerskirch (mweimerskirch) - Eric Clemmons (ericclemmons) - Charles Sarrazin (csarrazi) - Konstantin Myakshin (koc) - Christian Raue - - Dany Maillard (maidmaid) + - Jáchym Toušek (enumag) - Arnout Boks (aboks) - - Jérémy DERUSSÉ (jderusse) - Deni + - Alexander M. Turek (derrabus) - Henrik Westphal (snc) - Dariusz Górecki (canni) - - Jáchym Toušek (enumag) - Titouan Galopin (tgalopin) - Douglas Greenshields (shieldo) - Lee McDermott - Brandon Turner - Luis Cordova (cordoval) - Graham Campbell (graham) + - Tobias Nyholm (tobias) - Daniel Holmes (dholmes) - Toni Uebernickel (havvg) - Bart van den Burg (burgov) @@ -87,16 +90,13 @@ Symfony is the result of the work of many people who made the code better - Jérôme Tamarelle (gromnan) - John Wards (johnwards) - Dariusz Ruminski - - Alexander M. Turek (derrabus) - Fran Moreno (franmomu) + - Issei Murasawa (issei_m) - Antoine Hérault (herzult) - - Tobias Nyholm (tobias) - Paráda József (paradajozsef) - - Issei Murasawa (issei_m) - Arnaud Le Blanc (arnaud-lb) - Maxime STEINHAUSSER - Michal Piotrowski (eventhorizon) - - Yonel Ceruto González (yonelceruto) - Tim Nagel (merk) - Brice BERNARD (brikou) - Baptiste Clavié (talus) @@ -142,6 +142,7 @@ Symfony is the result of the work of many people who made the code better - Mikael Pajunen - Joel Wurtz (brouznouf) - Jérôme Vasseur (jvasseur) + - Oleg Voronkovich - Grégoire Paris (greg0ire) - Philipp Wahala (hifi) - Vyacheslav Pavlov @@ -152,7 +153,6 @@ Symfony is the result of the work of many people who made the code better - Rouven Weßling (realityking) - Teoh Han Hui (teohhanhui) - Clemens Tolboom - - Oleg Voronkovich - Helmer Aaviksoo - Lars Strojny (lstrojny) - Hiromi Hishida (77web) @@ -170,10 +170,12 @@ Symfony is the result of the work of many people who made the code better - Clément JOBEILI (dator) - Possum - Dorian Villet (gnutix) + - Sergey Linnik (linniksa) - Richard Miller (mr_r_miller) - Julien Falque (julienfalque) - Mario A. Alvarez Garcia (nomack84) - Dennis Benkert (denderello) + - SpacePossum - Benjamin Dulau (dbenjamin) - Mathieu Lemoine (lemoinem) - Christian Schmidt @@ -206,19 +208,20 @@ Symfony is the result of the work of many people who made the code better - Sven Paulus (subsven) - Rui Marinho (ruimarinho) - Marek Štípek (maryo) - - SpacePossum - Eugene Wissner - Julien Brochet (mewt) - Tristan Darricau (nicofuma) - - Sergey Linnik (linniksa) - Michaël Perrin (michael.perrin) - Marcel Beerta (mazen) - Loïc Faugeron - Jannik Zschiesche (apfelbox) + - Hidde Wieringa (hiddewie) - Marco Pivetta (ocramius) + - Rob Frawley 2nd (robfrawley) - julien pauli (jpauli) - Lorenz Schori - Sébastien Lavoie (lavoiesl) + - Gregor Harlan (gharlan) - Francois Zaninotto - Alexander Kotynia (olden) - Daniel Tschinder @@ -262,8 +265,7 @@ Symfony is the result of the work of many people who made the code better - Pavel Batanov (scaytrase) - Nikita Konstantinov - Wodor Wodorski - - Rob Frawley 2nd (robfrawley) - - Gregor Harlan (gharlan) + - Oskar Stark (oskarstark) - Thomas Lallement (raziel057) - Giorgio Premi - Matthieu Napoli (mnapoli) @@ -274,11 +276,12 @@ Symfony is the result of the work of many people who made the code better - Antonio J. García Lagar (ajgarlag) - Kim Hemsø Rasmussen (kimhemsoe) - Wouter Van Hecke + - Jérôme Parmentier (lctrs) - Peter Kruithof (pkruithof) - Michael Holm (hollo) - Marc Weistroff (futurecat) - Christian Schmidt - - Hidde Wieringa (hiddewie) + - Amrouche Hamza - Chad Sikorra (chadsikorra) - Chris Smith (cs278) - Florian Klein (docteurklein) @@ -315,6 +318,7 @@ Symfony is the result of the work of many people who made the code better - Thierry Thuon (lepiaf) - Ricard Clau (ricardclau) - Mark Challoner (markchalloner) + - Dariusz - Gennady Telegin (gtelegin) - Ben Davies (bendavies) - Erin Millard @@ -334,7 +338,6 @@ Symfony is the result of the work of many people who made the code better - Damien Alexandre (damienalexandre) - Felix Labrecque - Yaroslav Kiliba - - Amrouche Hamza - Terje Bråten - Robbert Klarenbeek (robbertkl) - Thomas Calvet (fancyweb) @@ -344,6 +347,7 @@ Symfony is the result of the work of many people who made the code better - David Badura (davidbadura) - hossein zolfi (ocean) - Clément Gautier (clementgautier) + - Sanpi - Eduardo Gulias (egulias) - giulio de donato (liuggio) - ShinDarth @@ -389,7 +393,6 @@ Symfony is the result of the work of many people who made the code better - Karel Souffriau - Christophe L. (christophelau) - Anthon Pang (robocoder) - - Jérôme Parmentier (lctrs) - Emanuele Gaspari (inmarelibero) - Sébastien Santoro (dereckson) - Brian King @@ -397,8 +400,10 @@ Symfony is the result of the work of many people who made the code better - Michel Salib (michelsalib) - geoffrey - Steffen Roßkamp + - Alexandru Furculita (afurculita) - Valentin Jonovs (valentins-jonovs) - Jeanmonod David (jeanmonod) + - Christopher Davis (chrisguitarguy) - Jan Schumann - Niklas Fiekas - Markus Bachmann (baachi) @@ -424,9 +429,11 @@ Symfony is the result of the work of many people who made the code better - Dirk Pahl (dirkaholic) - cedric lombardot (cedriclombardot) - Jonas Flodén (flojon) + - Thomas Perez (scullwm) - Marcin Sikoń (marphi) - Dominik Zogg (dominik.zogg) - Marek Pietrzak + - Luc Vieillescazes (iamluc) - franek (franek) - Christian Wahler - Gintautas Miselis @@ -434,8 +441,8 @@ Symfony is the result of the work of many people who made the code better - Zander Baldwin - Adam Harvey - Maxime Veber (nek-) - - Sanpi - Alex Bakhturin + - Yanick Witschi (toflar) - Alexander Obuhovich (aik099) - boombatower - Fabrice Bernhard (fabriceb) @@ -463,6 +470,7 @@ Symfony is the result of the work of many people who made the code better - ondrowan - Barry vd. Heuvel (barryvdh) - Wouter J + - Florent Mata - Evan S Kaufman (evanskaufman) - mcben - Jérôme Vieilledent (lolautruche) @@ -499,7 +507,6 @@ Symfony is the result of the work of many people who made the code better - sasezaki - Dawid Pakuła (zulusx) - Florian Rey (nervo) - - Oskar Stark (oskarstark) - Rodrigo Borrego Bernabé (rodrigobb) - MatTheCat - Denis Gorbachev (starfall) @@ -534,13 +541,13 @@ Symfony is the result of the work of many people who made the code better - Mantas Var (mvar) - Sebastian Krebs - Jean-Christophe Cuvelier [Artack] - - Christopher Davis (chrisguitarguy) - alcaeus - vitaliytv - Sebastian Blum - aubx - Marvin Butkereit - Ricky Su (ricky) + - Zan Baldwin - Gildas Quéméner (gquemener) - Charles-Henri Bruyand - Max Rath (drak3) @@ -579,8 +586,8 @@ Symfony is the result of the work of many people who made the code better - Vincent Simonin - Alex Bogomazov (alebo) - maxime.steinhausser + - adev - Stefan Warman - - Thomas Perez (scullwm) - Tristan Maindron (tmaindron) - Wesley Lancel - Ke WANG (yktd26) @@ -593,7 +600,6 @@ Symfony is the result of the work of many people who made the code better - Chris Heng (gigablah) - Richard Bradley - Ulumuddin Yunus (joenoez) - - Luc Vieillescazes (iamluc) - Johann Saunier (prophet777) - Michael Devery (mickadoo) - Antoine Corcy @@ -610,6 +616,7 @@ Symfony is the result of the work of many people who made the code better - Cameron Porter - Hossein Bukhamsin - Oliver Hoff + - Martin Auswöger - Disparity - origaminal - Matteo Beccati (matteobeccati) @@ -625,6 +632,7 @@ Symfony is the result of the work of many people who made the code better - Tiago Brito (blackmx) - Richard van den Brand (ricbra) - develop + - VJ - ReenExe - Mark Sonnabaum - Richard Quadling @@ -645,6 +653,7 @@ Symfony is the result of the work of many people who made the code better - Baldur Rensch (brensch) - Vladyslav Petrovych - Alex Xandra Albert Sim + - Craig Duncan (duncan3dc) - Carson Full - Trent Steel (trsteel88) - Yuen-Chi Lian @@ -700,7 +709,6 @@ Symfony is the result of the work of many people who made the code better - Jan Prieser - Adrien Lucas (adrienlucas) - Zhuravlev Alexander (scif) - - Yanick Witschi (toflar) - James Michael DuPont - Tom Klingenberg - Christopher Hall (mythmakr) @@ -725,6 +733,7 @@ Symfony is the result of the work of many people who made the code better - Dmitry Parnas (parnas) - Paul LE CORRE - DQNEO + - Shawn Iwinski - Emanuele Iannone - Tony Malzhacker - Mathieu MARCHOIS @@ -741,6 +750,7 @@ Symfony is the result of the work of many people who made the code better - Aleksey Podskrebyshev - Calin Mihai Pristavu - David Marín Carreño (davefx) + - Fabien LUCAS (flucas2) - Jörn Lang (j.lang) - Omar Yepez (oyepez003) - mwsaz @@ -804,7 +814,6 @@ Symfony is the result of the work of many people who made the code better - stefan.r - Valérian Galliat - Rikijs Murgs - - Alexandru Furculita (afurculita) - Ben Ramsey (ramsey) - Christian Jul Jensen - Alexandre GESLIN (alexandregeslin) @@ -838,6 +847,7 @@ Symfony is the result of the work of many people who made the code better - Anton Babenko (antonbabenko) - Irmantas Šiupšinskas (irmantas) - Danilo Silva + - Arnaud PETITPAS (apetitpa) - Zachary Tong (polyfractal) - Hryhorii Hrebiniuk - Dennis Fridrich (dfridrich) @@ -864,6 +874,8 @@ Symfony is the result of the work of many people who made the code better - Israel J. Carberry - Bob van de Vijver - Christian Neff + - Oliver Hoff + - Ole Rößner (basster) - Per Sandström (per) - Goran Juric - Laurent Ghirardotti (laurentg) @@ -876,6 +888,7 @@ Symfony is the result of the work of many people who made the code better - Ville Mattila - ilyes kooli - gr1ev0us + - mlazovla - Boris Vujicic (boris.vujicic) - Max Beutel - Antanas Arvasevicius @@ -895,6 +908,7 @@ Symfony is the result of the work of many people who made the code better - Martijn Evers - Benjamin Paap (benjaminpaap) - Christian + - Denis Golubovskiy (bukashk0zzz) - Sergii Smertin (nfx) - hugofonseca (fonsecas72) - Martynas Narbutas @@ -956,6 +970,7 @@ Symfony is the result of the work of many people who made the code better - Yannick - spdionis - rchoquet + - gitlost - Taras Girnyk - Eduardo García Sanz (coma) - James Gilliland @@ -963,10 +978,12 @@ Symfony is the result of the work of many people who made the code better - Rhodri Pugh (rodnaph) - David de Boer (ddeboer) - Klaus Purer + - arnaud (arnooo999) - Gilles Doge (gido) - abulford - Philipp Kretzschmar - antograssiot + - Ilya Vertakov - Brooks Boyd - Roger Webb - Dmitriy Simushev @@ -1006,13 +1023,13 @@ Symfony is the result of the work of many people who made the code better - Jeroen van den Enden (stoefke) - Jelte Steijaert (jelte) - Quique Porta (quiqueporta) + - stoccc - Tomasz Szymczyk (karion) - Xavier Coureau - ConneXNL - Aharon Perkel - matze - Abdul.Mohsen B. A. A - - Martin Auswöger - Benoît Burnichon - pthompson - Malaney J. Hill @@ -1036,6 +1053,7 @@ Symfony is the result of the work of many people who made the code better - Marc J. Schmidt (marcjs) - Marco Jantke - Saem Ghani + - Clément LEFEBVRE - Conrad Kleinespel - Sebastian Utz - Adrien Gallou (agallou) @@ -1053,6 +1071,7 @@ Symfony is the result of the work of many people who made the code better - Cédric Lahouste (rapotor) - Samuel Vogel (samuelvogel) - Berat Doğan + - Guillaume LECERF - Juanmi Rodriguez Cerón - Andy Raines - Anthony Ferrara @@ -1084,7 +1103,6 @@ Symfony is the result of the work of many people who made the code better - Alberto Pirovano (geezmo) - Pete Mitchell (peterjmit) - Tom Corrigan (tomcorrigan) - - adev - Luis Galeas - Martin Pärtel - Patrick Daley (padrig) @@ -1115,12 +1133,12 @@ Symfony is the result of the work of many people who made the code better - Alexander Schranz - Rafał Muszyński (rafmus90) - Timothy Anido (xanido) + - Mara Blaga - Rick Prent - skalpa - Martin Eckhardt - Pieter Jordaan - Damien Tournoud - - Craig Duncan (duncan3dc) - Jon Gotlin (jongotlin) - Michael Dowling (mtdowling) - Karlos Presumido (oneko) @@ -1136,12 +1154,14 @@ Symfony is the result of the work of many people who made the code better - Jānis Lukss - rkerner - Alex Silcock + - Qingshan Luo - Matthew J Mucklo - fdgdfg (psampaz) - Stéphane Seng - Maxwell Vandervelde - kaywalker - Mike Meier + - Tim Jabs - Sebastian Ionescu - Thomas Ploch - Simon Neidhold @@ -1170,6 +1190,7 @@ Symfony is the result of the work of many people who made the code better - Zdeněk Drahoš - Dan Harper - moldcraft + - Antoine Bellion (abellion) - Ramon Kleiss (akathos) - César Suárez (csuarez) - Nicolas Badey (nico-b) @@ -1177,6 +1198,7 @@ Symfony is the result of the work of many people who made the code better - Johannes Goslar - Geoff - georaldc + - Maarten de Boer - Malte Wunsch - wusuopu - povilas @@ -1255,13 +1277,13 @@ Symfony is the result of the work of many people who made the code better - Romain Dorgueil - Christopher Parotat - Grayson Koonce (breerly) - - Fabien LUCAS (flucas2) - Indra Gunawan (indragunawan) - Karim Cassam Chenaï (ka) - Michal Kurzeja (mkurzeja) - Nicolas Bastien (nicolas_bastien) - Denis (yethee) - Andrew Zhilin (zhil) + - Oleksii Zhurbytskyi - Andy Stanberry - Luiz “Felds” Liscia - Thomas Rothe @@ -1276,7 +1298,6 @@ Symfony is the result of the work of many people who made the code better - Koalabaerchen - michalmarcinkowski - Warwick - - VJ - Chris - Florent Olivaud - JakeFr @@ -1343,6 +1364,7 @@ Symfony is the result of the work of many people who made the code better - bertillon - Bertalan Attila - Yannick Bensacq (cibou) + - Freek Van der Herten (freekmurze) - Gawain Lynch (gawain) - Luca Genuzio (genuzio) - Hans Nilsson (hansnilsson) @@ -1365,6 +1387,7 @@ Symfony is the result of the work of many people who made the code better - James Hudson - Tom Maguire - David Zuelke + - Oleg Andreyev - Pierre Rineau - adenkejawen - Ari Pringle (apringle) @@ -1407,6 +1430,7 @@ Symfony is the result of the work of many people who made the code better - Dane Powell - Gerrit Drost - Linnaea Von Lavia + - Simon Mönch - Javan Eskander - Lenar Lõhmus - Cristian Gonzalez @@ -1440,6 +1464,7 @@ Symfony is the result of the work of many people who made the code better - Ian Jenkins (jenkoian) - Jorge Martin (jorgemartind) - Joeri Verdeyen (jverdeyen) + - Kevin Verschaeve (keversc) - Kevin Herrera (kherge) - Luis Ramón López López (lrlopez) - Bart Reunes (metalarend) @@ -1504,13 +1529,14 @@ Symfony is the result of the work of many people who made the code better - jc - BenjaminBeck - Aurelijus Rožėnas + - Vladimir Tsykun - znerol - Christian Eikermann - Antonio Angelino - Matt Fields - - Shawn Iwinski - Niklas Keller - Vladimir Sazhin + - Billie Thompson - lol768 - jamogon - Vyacheslav Slinko @@ -1574,7 +1600,6 @@ Symfony is the result of the work of many people who made the code better - Matt Janssen - Peter Gribanov - Ben Johnson - - Florent Mata - kwiateusz - David Soria Parra - Sergiy Sokolenko @@ -1594,6 +1619,7 @@ Symfony is the result of the work of many people who made the code better - Christian Stocker - Dawid Nowak - Lesnykh Ilia + - darnel - Karolis Daužickas - Nicolas - Sergio Santoro @@ -1636,6 +1662,7 @@ Symfony is the result of the work of many people who made the code better - Fabien D. (fabd) - Carsten Eilers (fnc) - Sorin Gitlan (forapathy) + - Forfarle (forfarle) - Yohan Giarelli (frequence-web) - Gerry Vandermaesen (gerryvdm) - Ghazy Ben Ahmed (ghazy) @@ -1678,6 +1705,7 @@ Symfony is the result of the work of many people who made the code better - Philipp Hoffmann (philipphoffmann) - Alex Carol (picard89) - Daniel Perez Pinazo (pitiflautico) + - Phil Taylor (prazgod) - Brayden Williams (redstar504) - Rich Sage (richsage) - Bart Ruysseveldt (ruyss) @@ -1689,6 +1717,7 @@ Symfony is the result of the work of many people who made the code better - Bruno Ziegler (sfcoder) - Andrea Giuliano (shark) - Schuyler Jager (sjager) + - Pascal Luna (skalpa) - Volker (skydiablo) - Julien Sanchez (sumbobyboys) - Guillermo Gisinger (t3chn0r) From 2c907d5156cc052357ca2d240153ed81a4a9e83f Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Thu, 5 Oct 2017 15:51:51 -0700 Subject: [PATCH 1021/1099] updated VERSION for 2.7.35 --- src/Symfony/Component/HttpKernel/Kernel.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/HttpKernel/Kernel.php b/src/Symfony/Component/HttpKernel/Kernel.php index 1bdb89cff749b..3fa96efcb3b78 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -58,12 +58,12 @@ abstract class Kernel implements KernelInterface, TerminableInterface protected $startTime; protected $loadClassCache; - const VERSION = '2.7.35-DEV'; + const VERSION = '2.7.35'; const VERSION_ID = 20735; const MAJOR_VERSION = 2; const MINOR_VERSION = 7; const RELEASE_VERSION = 35; - const EXTRA_VERSION = 'DEV'; + const EXTRA_VERSION = ''; const END_OF_MAINTENANCE = '05/2018'; const END_OF_LIFE = '05/2019'; From dd490af864f2077e722bf7d98dd87623af475652 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Thu, 5 Oct 2017 16:05:57 -0700 Subject: [PATCH 1022/1099] bumped Symfony version to 2.7.36 --- src/Symfony/Component/HttpKernel/Kernel.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Symfony/Component/HttpKernel/Kernel.php b/src/Symfony/Component/HttpKernel/Kernel.php index 3fa96efcb3b78..404fbaaacb609 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -58,12 +58,12 @@ abstract class Kernel implements KernelInterface, TerminableInterface protected $startTime; protected $loadClassCache; - const VERSION = '2.7.35'; - const VERSION_ID = 20735; + const VERSION = '2.7.36-DEV'; + const VERSION_ID = 20736; const MAJOR_VERSION = 2; const MINOR_VERSION = 7; - const RELEASE_VERSION = 35; - const EXTRA_VERSION = ''; + const RELEASE_VERSION = 36; + const EXTRA_VERSION = 'DEV'; const END_OF_MAINTENANCE = '05/2018'; const END_OF_LIFE = '05/2019'; From f0b32cfd9d63aaab836ad21ed02a5fbdc877f84d Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Thu, 5 Oct 2017 16:23:57 -0700 Subject: [PATCH 1023/1099] updated CHANGELOG for 2.8.28 --- CHANGELOG-2.8.md | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/CHANGELOG-2.8.md b/CHANGELOG-2.8.md index abb1235519a77..d1500fd86a157 100644 --- a/CHANGELOG-2.8.md +++ b/CHANGELOG-2.8.md @@ -7,6 +7,33 @@ in 2.8 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/v2.8.0...v2.8.1 +* 2.8.28 (2017-10-05) + + * bug #24448 [Session] fix MongoDb session handler to gc all expired sessions (Tobion) + * bug #24417 [Yaml] parse references on merge keys (xabbuh) + * bug #24421 [Config] Fix dumped files invalidation by OPCache (nicolas-grekas) + * bug #23980 Tests and fix for issue in array model data in EntityType field with multiple=true (stoccc) + * bug #22586 [Form] Fixed PercentToLocalizedStringTransformer to accept both comma and dot as decimal separator, if possible (aaa2000) + * bug #24157 [Intl] Fixed support of Locale::getFallback (lyrixx) + * bug #24198 [HttpFoundation] Fix file upload multiple with no files (enumag) + * bug #24036 [Form] Fix precision of MoneyToLocalizedStringTransformer's divisions and multiplications (Rubinum) + * bug #24367 PdoSessionHandler: fix advisory lock for pgsql (Tobion) + * bug #24243 HttpCache does not consider ESI resources in HEAD requests (mpdude) + * bug #24304 [FrameworkBundle] Fix Routing\DelegatingLoader (nicolas-grekas) + * bug #24219 [Console] Preserving line breaks between sentences according to the exception message (yceruto) + * bug #23722 [Form] Fixed GroupSequence with "constraints" option (HeahDude) + * bug #22321 [Filesystem] Fixed makePathRelative (ausi) + * bug #23473 [Filesystem] mirror - fix copying content with same name as source/target. (gitlost) + * bug #24162 [WebProfilerBundle] fixed TemplateManager when using Twig 2 without compat interfaces (fabpot) + * bug #24141 [DomCrawler] Fix conversion to int on GetPhpFiles (MaraBlaga) + * bug #23853 Filtering empty uuids in ORMQueryBuilderLoader. (mlazovla) + * bug #24101 [Security] Fix exception when use_referer option is true and referer is not set or empty (linniksa) + * bug #24105 [Filesystem] check permissions if dump target dir is missing (xabbuh) + * bug #24115 [FrameworkBundle] Get KERNEL_DIR through $_ENV too for KernelTestCase (yceruto) + * bug #24041 [ExpressionLanguage] throws an exception on calling uncallable method (fmata) + * bug #24096 Fix ArrayInput::toString() for VALUE_IS_ARRAY options/args (chalasr) + * bug #23730 Fixed the escaping of back slashes and << in console output (javiereguiluz) + * 2.8.27 (2017-08-28) * bug #23989 [Debug] Remove false-positive check in DebugClassLoader (nicolas-grekas) From ebf0c076fa585daf1c955f60b5d6c9f845881cd4 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Thu, 5 Oct 2017 16:24:02 -0700 Subject: [PATCH 1024/1099] updated VERSION for 2.8.28 --- 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 1e9aa3c2bdbfa..4aa404f272735 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -59,12 +59,12 @@ abstract class Kernel implements KernelInterface, TerminableInterface protected $startTime; protected $loadClassCache; - const VERSION = '2.8.28-DEV'; + const VERSION = '2.8.28'; const VERSION_ID = 20828; const MAJOR_VERSION = 2; const MINOR_VERSION = 8; const RELEASE_VERSION = 28; - const EXTRA_VERSION = 'DEV'; + const EXTRA_VERSION = ''; const END_OF_MAINTENANCE = '11/2018'; const END_OF_LIFE = '11/2019'; From 81517602fa03e2640781b9c6cc294c60cb5cdfcb Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Thu, 5 Oct 2017 16:35:26 -0700 Subject: [PATCH 1025/1099] bumped Symfony version to 2.8.29 --- 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 4aa404f272735..d5bf812292b7d 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -59,12 +59,12 @@ abstract class Kernel implements KernelInterface, TerminableInterface protected $startTime; protected $loadClassCache; - const VERSION = '2.8.28'; - const VERSION_ID = 20828; + const VERSION = '2.8.29-DEV'; + const VERSION_ID = 20829; const MAJOR_VERSION = 2; const MINOR_VERSION = 8; - const RELEASE_VERSION = 28; - const EXTRA_VERSION = ''; + const RELEASE_VERSION = 29; + const EXTRA_VERSION = 'DEV'; const END_OF_MAINTENANCE = '11/2018'; const END_OF_LIFE = '11/2019'; From 7a1cb838f93f7efa4cd311cc487df4f9a412f849 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Thu, 5 Oct 2017 16:39:08 -0700 Subject: [PATCH 1026/1099] updated CHANGELOG for 3.3.10 --- CHANGELOG-3.3.md | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/CHANGELOG-3.3.md b/CHANGELOG-3.3.md index 320bf84f1dc7d..7dc9c7050b1f5 100644 --- a/CHANGELOG-3.3.md +++ b/CHANGELOG-3.3.md @@ -7,6 +7,44 @@ in 3.3 minor versions. To get the diff for a specific change, go to https://github.com/symfony/symfony/commit/XXX where XXX is the change hash To get the diff between two versions, go to https://github.com/symfony/symfony/compare/v3.3.0...v3.3.1 +* 3.3.10 (2017-10-05) + + * bug #23906 Added support for guards when advancing workflow from a command (GDIBass) + * bug #24448 [Session] fix MongoDb session handler to gc all expired sessions (Tobion) + * bug #24431 [FrameworkBundle] Fix bad interface hint in AbstractController (nicolas-grekas) + * bug #24419 [Cache] Fix race condition in TagAwareAdapter (nicolas-grekas) + * bug #24417 [Yaml] parse references on merge keys (xabbuh) + * bug #24416 [Yaml] treat trailing backslashes in multi-line strings (xabbuh) + * bug #24421 [Config] Fix dumped files invalidation by OPCache (nicolas-grekas) + * bug #24418 [DI] Allow setting any public non-initialized services (nicolas-grekas) + * bug #23980 Tests and fix for issue in array model data in EntityType field with multiple=true (stoccc) + * bug #22586 [Form] Fixed PercentToLocalizedStringTransformer to accept both comma and dot as decimal separator, if possible (aaa2000) + * bug #24157 [Intl] Fixed support of Locale::getFallback (lyrixx) + * bug #24198 [HttpFoundation] Fix file upload multiple with no files (enumag) + * bug #24379 [PHPUnitBridge] don't remove when set to empty string (Simperfit) + * bug #24036 [Form] Fix precision of MoneyToLocalizedStringTransformer's divisions and multiplications (Rubinum) + * bug #24191 [DependencyInjection] include file and line number in deprecation (xabbuh) + * bug #24367 PdoSessionHandler: fix advisory lock for pgsql (Tobion) + * bug #24189 [Yaml] parse merge keys with PARSE_OBJECT_FOR_MAP flag (xabbuh) + * bug #24243 HttpCache does not consider ESI resources in HEAD requests (mpdude) + * bug #24237 [WebProfilerBundle] Added missing link to profile token (vtsykun) + * bug #24244 TwigBundle exception/deprecation tweaks (ro0NL) + * bug #24281 [TwigBundle] Remove profiler related scripting (ro0NL, javiereguiluz) + * bug #24251 [PropertyAccess] Set a NullLogger in ApcuAdapter when Apcu is disabled in CLI (iamluc) + * bug #24304 [FrameworkBundle] Fix Routing\DelegatingLoader (nicolas-grekas) + * bug #24305 [HttpKernel] Make array vs "::" controller definitions consistent (nicolas-grekas) + * bug #24255 [TwigBundle] Break long lines in exceptions (kevin-verschaeve) + * bug #24219 [Console] Preserving line breaks between sentences according to the exception message (yceruto) + * bug #24192 [PhpUnitBridge] do not require an error context (xabbuh) + * bug #23722 [Form] Fixed GroupSequence with "constraints" option (HeahDude) + * bug #22321 [Filesystem] Fixed makePathRelative (ausi) + * bug #24234 [DI] Fix decorated service merge in ResolveInstanceofConditionalsPass (dunglas) + * bug #24203 [Security] Preserve URI fragment in HttpUtils::generateUri() (chalasr) + * bug #24199 [DI] Fix non-instantiables auto-discovery (nicolas-grekas) + * bug #23473 [Filesystem] mirror - fix copying content with same name as source/target. (gitlost) + * bug #24177 [FrameworkBundle] Add support to environment variables APP_ENV/DEBUG in KernelTestCase (yceruto) + * bug #24162 [WebProfilerBundle] fixed TemplateManager when using Twig 2 without compat interfaces (fabpot) + * 3.3.9 (2017-09-11) * bug #24141 [DomCrawler] Fix conversion to int on GetPhpFiles (MaraBlaga) From 8fc46c7bb331d6aa97c6695c0477b668d6134bec Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Thu, 5 Oct 2017 16:40:19 -0700 Subject: [PATCH 1027/1099] updated VERSION for 3.3.10 --- 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 dc74cb0a8adcb..3a29e7b0bb4bd 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -61,12 +61,12 @@ abstract class Kernel implements KernelInterface, TerminableInterface private $projectDir; - const VERSION = '3.3.10-DEV'; + const VERSION = '3.3.10'; const VERSION_ID = 30310; const MAJOR_VERSION = 3; const MINOR_VERSION = 3; const RELEASE_VERSION = 10; - const EXTRA_VERSION = 'DEV'; + const EXTRA_VERSION = ''; const END_OF_MAINTENANCE = '01/2018'; const END_OF_LIFE = '07/2018'; From bf0e6f6565d4aff7c4a888f3d40c4aabd50bbeee Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Thu, 5 Oct 2017 17:17:10 -0700 Subject: [PATCH 1028/1099] bumped Symfony version to 3.3.11 --- 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 3a29e7b0bb4bd..f40e3bf749b34 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -61,12 +61,12 @@ abstract class Kernel implements KernelInterface, TerminableInterface private $projectDir; - const VERSION = '3.3.10'; - const VERSION_ID = 30310; + const VERSION = '3.3.11-DEV'; + const VERSION_ID = 30311; const MAJOR_VERSION = 3; const MINOR_VERSION = 3; - const RELEASE_VERSION = 10; - const EXTRA_VERSION = ''; + const RELEASE_VERSION = 11; + const EXTRA_VERSION = 'DEV'; const END_OF_MAINTENANCE = '01/2018'; const END_OF_LIFE = '07/2018'; From 53d78570928db0d2934581ee0ef26cdb365f7899 Mon Sep 17 00:00:00 2001 From: Tobias Nyholm Date: Thu, 5 Oct 2017 21:36:40 -0400 Subject: [PATCH 1029/1099] Use for=ID on radio/checkbox label. This is required for some screen reader like Jaws --- .../Twig/Resources/views/Form/bootstrap_3_layout.html.twig | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_3_layout.html.twig b/src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_3_layout.html.twig index 3e9f133d37b46..2efc0c4d4a213 100644 --- a/src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_3_layout.html.twig +++ b/src/Symfony/Bridge/Twig/Resources/views/Form/bootstrap_3_layout.html.twig @@ -148,10 +148,14 @@ {% endblock %} {% block checkbox_label -%} + {%- set label_attr = label_attr|merge({'for': id}) -%} + {{- block('checkbox_radio_label') -}} {%- endblock checkbox_label %} {% block radio_label -%} + {%- set label_attr = label_attr|merge({'for': id}) -%} + {{- block('checkbox_radio_label') -}} {%- endblock radio_label %} From 9499bc291cc9c18ed59f9c9339d4dd2816d793d9 Mon Sep 17 00:00:00 2001 From: Alain Flaus Date: Thu, 13 Jul 2017 12:20:18 +0200 Subject: [PATCH 1030/1099] [Workflow] Added guard 'is_valid()' method support --- .../FrameworkExtension.php | 1 + src/Symfony/Component/Workflow/CHANGELOG.md | 1 + .../EventListener/ExpressionLanguage.php | 14 +++++++++++++ .../Workflow/EventListener/GuardListener.php | 7 ++++++- .../Workflow/Exception/RuntimeException.php | 21 +++++++++++++++++++ 5 files changed, 43 insertions(+), 1 deletion(-) create mode 100644 src/Symfony/Component/Workflow/Exception/RuntimeException.php diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php index 90673719814b5..568bb0913ebc7 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php @@ -752,6 +752,7 @@ private function registerWorkflowConfiguration(array $config, ContainerBuilder $ new Reference('security.authorization_checker'), new Reference('security.authentication.trust_resolver'), new Reference('security.role_hierarchy'), + new Reference('validator', ContainerInterface::NULL_ON_INVALID_REFERENCE), )); $container->setDefinition(sprintf('%s.listener.guard', $workflowId), $guard); diff --git a/src/Symfony/Component/Workflow/CHANGELOG.md b/src/Symfony/Component/Workflow/CHANGELOG.md index 02c04f6dc08f6..328420c6f1e1f 100644 --- a/src/Symfony/Component/Workflow/CHANGELOG.md +++ b/src/Symfony/Component/Workflow/CHANGELOG.md @@ -4,6 +4,7 @@ CHANGELOG 3.4.0 ----- + * Add guard `is_valid()` method support * Added support for `Event::getWorkflowName()` for "announce" events. * Added `workflow.completed` events which are fired after a transition is completed. diff --git a/src/Symfony/Component/Workflow/EventListener/ExpressionLanguage.php b/src/Symfony/Component/Workflow/EventListener/ExpressionLanguage.php index 46d5d7520c0fb..df7e21a92855c 100644 --- a/src/Symfony/Component/Workflow/EventListener/ExpressionLanguage.php +++ b/src/Symfony/Component/Workflow/EventListener/ExpressionLanguage.php @@ -12,6 +12,8 @@ namespace Symfony\Component\Workflow\EventListener; use Symfony\Component\Security\Core\Authorization\ExpressionLanguage as BaseExpressionLanguage; +use Symfony\Component\Validator\Validator\ValidatorInterface; +use Symfony\Component\Workflow\Exception\RuntimeException; /** * Adds some function to the default Symfony Security ExpressionLanguage. @@ -29,5 +31,17 @@ protected function registerFunctions() }, function (array $variables, $attributes, $object = null) { return $variables['auth_checker']->isGranted($attributes, $object); }); + + $this->register('is_valid', function ($object = 'null', $groups = 'null') { + return sprintf('0 === count($validator->validate(%s, null, %s))', $object, $groups); + }, function (array $variables, $object = null, $groups = null) { + if (!$variables['validator'] instanceof ValidatorInterface) { + throw new RuntimeException('Validator not defined, did you install the component?'); + } + + $errors = $variables['validator']->validate($object, null, $groups); + + return 0 === count($errors); + }); } } diff --git a/src/Symfony/Component/Workflow/EventListener/GuardListener.php b/src/Symfony/Component/Workflow/EventListener/GuardListener.php index 20ba04c007fc2..1fa082ac4d1c0 100644 --- a/src/Symfony/Component/Workflow/EventListener/GuardListener.php +++ b/src/Symfony/Component/Workflow/EventListener/GuardListener.php @@ -15,6 +15,7 @@ use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface; use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface; use Symfony\Component\Security\Core\Role\RoleHierarchyInterface; +use Symfony\Component\Validator\Validator\ValidatorInterface; use Symfony\Component\Workflow\Event\GuardEvent; /** @@ -28,8 +29,9 @@ class GuardListener private $authenticationChecker; private $trustResolver; private $roleHierarchy; + private $validator; - public function __construct($configuration, ExpressionLanguage $expressionLanguage, TokenStorageInterface $tokenStorage, AuthorizationCheckerInterface $authenticationChecker, AuthenticationTrustResolverInterface $trustResolver, RoleHierarchyInterface $roleHierarchy = null) + public function __construct($configuration, ExpressionLanguage $expressionLanguage, TokenStorageInterface $tokenStorage, AuthorizationCheckerInterface $authenticationChecker, AuthenticationTrustResolverInterface $trustResolver, RoleHierarchyInterface $roleHierarchy = null, ValidatorInterface $validator = null) { $this->configuration = $configuration; $this->expressionLanguage = $expressionLanguage; @@ -37,6 +39,7 @@ public function __construct($configuration, ExpressionLanguage $expressionLangua $this->authenticationChecker = $authenticationChecker; $this->trustResolver = $trustResolver; $this->roleHierarchy = $roleHierarchy; + $this->validator = $validator; } public function onTransition(GuardEvent $event, $eventName) @@ -72,6 +75,8 @@ private function getVariables(GuardEvent $event) 'auth_checker' => $this->authenticationChecker, // needed for the is_* expression function 'trust_resolver' => $this->trustResolver, + // needed for the is_valid expression function + 'validator' => $this->validator, ); return $variables; diff --git a/src/Symfony/Component/Workflow/Exception/RuntimeException.php b/src/Symfony/Component/Workflow/Exception/RuntimeException.php new file mode 100644 index 0000000000000..7e9caf1bf5b1f --- /dev/null +++ b/src/Symfony/Component/Workflow/Exception/RuntimeException.php @@ -0,0 +1,21 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Workflow\Exception; + +/** + * Base RuntimeException for the Workflow component. + * + * @author Alain Flaus + */ +class RuntimeException extends \RuntimeException implements ExceptionInterface +{ +} From 06d81987145eb9136683ae715925d193bfbc2c58 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9goire=20Pineau?= Date: Fri, 18 Aug 2017 16:07:04 +0200 Subject: [PATCH 1031/1099] [Workflow] Added tests for the is_valid() guard expression --- .../Compiler/WorkflowGuardListenerPass.php | 26 +++--- .../FrameworkExtension.php | 1 + .../WorkflowGuardListenerPassTest.php | 45 +++------- src/Symfony/Component/Workflow/CHANGELOG.md | 2 +- .../EventListener/ExpressionLanguage.php | 2 +- .../Tests/EventListener/GuardListenerTest.php | 90 +++++++++++++------ src/Symfony/Component/Workflow/composer.json | 3 +- 7 files changed, 95 insertions(+), 74 deletions(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/WorkflowGuardListenerPass.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/WorkflowGuardListenerPass.php index 349d78cfc4fed..c5498adc4728d 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/WorkflowGuardListenerPass.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/WorkflowGuardListenerPass.php @@ -17,6 +17,7 @@ /** * @author Christian Flothmann + * @author Grégoire Pineau */ class WorkflowGuardListenerPass implements CompilerPassInterface { @@ -31,20 +32,17 @@ public function process(ContainerBuilder $container) $container->getParameterBag()->remove('workflow.has_guard_listeners'); - if (!$container->has('security.token_storage')) { - throw new LogicException('The "security.token_storage" service is needed to be able to use the workflow guard listener.'); - } - - if (!$container->has('security.authorization_checker')) { - throw new LogicException('The "security.authorization_checker" service is needed to be able to use the workflow guard listener.'); - } - - if (!$container->has('security.authentication.trust_resolver')) { - throw new LogicException('The "security.authentication.trust_resolver" service is needed to be able to use the workflow guard listener.'); - } - - if (!$container->has('security.role_hierarchy')) { - throw new LogicException('The "security.role_hierarchy" service is needed to be able to use the workflow guard listener.'); + $servicesNeeded = array( + 'security.token_storage', + 'security.authorization_checker', + 'security.authentication.trust_resolver', + 'security.role_hierarchy', + ); + + foreach ($servicesNeeded as $service) { + if (!$container->has($service)) { + throw new LogicException(sprintf('The "%s" service is needed to be able to use the workflow guard listener.', $service)); + } } } } diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php index 568bb0913ebc7..9bdbb373bb0f9 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php @@ -85,6 +85,7 @@ use Symfony\Component\Translation\Translator; use Symfony\Component\Validator\ConstraintValidatorInterface; use Symfony\Component\Validator\ObjectInitializerInterface; +use Symfony\Component\Validator\Validator\ValidatorInterface; use Symfony\Component\WebLink\HttpHeaderSerializer; use Symfony\Component\Workflow; use Symfony\Component\Yaml\Command\LintCommand as BaseYamlLintCommand; diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/WorkflowGuardListenerPassTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/WorkflowGuardListenerPassTest.php index fead9e28f26d0..44c87b188fa17 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/WorkflowGuardListenerPassTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/WorkflowGuardListenerPassTest.php @@ -14,12 +14,11 @@ use PHPUnit\Framework\TestCase; use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\WorkflowGuardListenerPass; use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Exception\LogicException; use Symfony\Component\Security\Core\Authentication\AuthenticationTrustResolverInterface; use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface; use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface; use Symfony\Component\Security\Core\Role\RoleHierarchy; -use Symfony\Component\Workflow\EventListener\GuardListener; +use Symfony\Component\Validator\Validator\ValidatorInterface; class WorkflowGuardListenerPassTest extends TestCase { @@ -29,53 +28,37 @@ class WorkflowGuardListenerPassTest extends TestCase protected function setUp() { $this->container = new ContainerBuilder(); - $this->container->register('foo.listener.guard', GuardListener::class); - $this->container->register('bar.listener.guard', GuardListener::class); $this->compilerPass = new WorkflowGuardListenerPass(); } - public function testListenersAreNotRemovedIfParameterIsNotSet() + public function testNoExeptionIfParameterIsNotSet() { $this->compilerPass->process($this->container); - $this->assertTrue($this->container->hasDefinition('foo.listener.guard')); - $this->assertTrue($this->container->hasDefinition('bar.listener.guard')); - } - - public function testParameterIsRemovedWhenThePassIsProcessed() - { - $this->container->setParameter('workflow.has_guard_listeners', array('foo.listener.guard', 'bar.listener.guard')); - - try { - $this->compilerPass->process($this->container); - } catch (LogicException $e) { - // Here, we are not interested in the exception handling. This is tested further down. - } - $this->assertFalse($this->container->hasParameter('workflow.has_guard_listeners')); } - public function testListenersAreNotRemovedIfAllDependenciesArePresent() + public function testNoExeptionIfAllDependenciesArePresent() { - $this->container->setParameter('workflow.has_guard_listeners', array('foo.listener.guard', 'bar.listener.guard')); + $this->container->setParameter('workflow.has_guard_listeners', true); $this->container->register('security.token_storage', TokenStorageInterface::class); $this->container->register('security.authorization_checker', AuthorizationCheckerInterface::class); $this->container->register('security.authentication.trust_resolver', AuthenticationTrustResolverInterface::class); $this->container->register('security.role_hierarchy', RoleHierarchy::class); + $this->container->register('validator', ValidatorInterface::class); $this->compilerPass->process($this->container); - $this->assertTrue($this->container->hasDefinition('foo.listener.guard')); - $this->assertTrue($this->container->hasDefinition('bar.listener.guard')); + $this->assertFalse($this->container->hasParameter('workflow.has_guard_listeners')); } /** * @expectedException \Symfony\Component\DependencyInjection\Exception\LogicException * @expectedExceptionMessage The "security.token_storage" service is needed to be able to use the workflow guard listener. */ - public function testListenersAreRemovedIfTheTokenStorageServiceIsNotPresent() + public function testExceptionIfTheTokenStorageServiceIsNotPresent() { - $this->container->setParameter('workflow.has_guard_listeners', array('foo.listener.guard', 'bar.listener.guard')); + $this->container->setParameter('workflow.has_guard_listeners', true); $this->container->register('security.authorization_checker', AuthorizationCheckerInterface::class); $this->container->register('security.authentication.trust_resolver', AuthenticationTrustResolverInterface::class); $this->container->register('security.role_hierarchy', RoleHierarchy::class); @@ -87,9 +70,9 @@ public function testListenersAreRemovedIfTheTokenStorageServiceIsNotPresent() * @expectedException \Symfony\Component\DependencyInjection\Exception\LogicException * @expectedExceptionMessage The "security.authorization_checker" service is needed to be able to use the workflow guard listener. */ - public function testListenersAreRemovedIfTheAuthorizationCheckerServiceIsNotPresent() + public function testExceptionIfTheAuthorizationCheckerServiceIsNotPresent() { - $this->container->setParameter('workflow.has_guard_listeners', array('foo.listener.guard', 'bar.listener.guard')); + $this->container->setParameter('workflow.has_guard_listeners', true); $this->container->register('security.token_storage', TokenStorageInterface::class); $this->container->register('security.authentication.trust_resolver', AuthenticationTrustResolverInterface::class); $this->container->register('security.role_hierarchy', RoleHierarchy::class); @@ -101,9 +84,9 @@ public function testListenersAreRemovedIfTheAuthorizationCheckerServiceIsNotPres * @expectedException \Symfony\Component\DependencyInjection\Exception\LogicException * @expectedExceptionMessage The "security.authentication.trust_resolver" service is needed to be able to use the workflow guard listener. */ - public function testListenersAreRemovedIfTheAuthenticationTrustResolverServiceIsNotPresent() + public function testExceptionIfTheAuthenticationTrustResolverServiceIsNotPresent() { - $this->container->setParameter('workflow.has_guard_listeners', array('foo.listener.guard', 'bar.listener.guard')); + $this->container->setParameter('workflow.has_guard_listeners', true); $this->container->register('security.token_storage', TokenStorageInterface::class); $this->container->register('security.authorization_checker', AuthorizationCheckerInterface::class); $this->container->register('security.role_hierarchy', RoleHierarchy::class); @@ -115,9 +98,9 @@ public function testListenersAreRemovedIfTheAuthenticationTrustResolverServiceIs * @expectedException \Symfony\Component\DependencyInjection\Exception\LogicException * @expectedExceptionMessage The "security.role_hierarchy" service is needed to be able to use the workflow guard listener. */ - public function testListenersAreRemovedIfTheRoleHierarchyServiceIsNotPresent() + public function testExceptionIfTheRoleHierarchyServiceIsNotPresent() { - $this->container->setParameter('workflow.has_guard_listeners', array('foo.listener.guard', 'bar.listener.guard')); + $this->container->setParameter('workflow.has_guard_listeners', true); $this->container->register('security.token_storage', TokenStorageInterface::class); $this->container->register('security.authorization_checker', AuthorizationCheckerInterface::class); $this->container->register('security.authentication.trust_resolver', AuthenticationTrustResolverInterface::class); diff --git a/src/Symfony/Component/Workflow/CHANGELOG.md b/src/Symfony/Component/Workflow/CHANGELOG.md index 328420c6f1e1f..abbf3238011c1 100644 --- a/src/Symfony/Component/Workflow/CHANGELOG.md +++ b/src/Symfony/Component/Workflow/CHANGELOG.md @@ -4,7 +4,7 @@ CHANGELOG 3.4.0 ----- - * Add guard `is_valid()` method support + * Added guard `is_valid()` method support. * Added support for `Event::getWorkflowName()` for "announce" events. * Added `workflow.completed` events which are fired after a transition is completed. diff --git a/src/Symfony/Component/Workflow/EventListener/ExpressionLanguage.php b/src/Symfony/Component/Workflow/EventListener/ExpressionLanguage.php index df7e21a92855c..e1bcc7997d317 100644 --- a/src/Symfony/Component/Workflow/EventListener/ExpressionLanguage.php +++ b/src/Symfony/Component/Workflow/EventListener/ExpressionLanguage.php @@ -36,7 +36,7 @@ protected function registerFunctions() return sprintf('0 === count($validator->validate(%s, null, %s))', $object, $groups); }, function (array $variables, $object = null, $groups = null) { if (!$variables['validator'] instanceof ValidatorInterface) { - throw new RuntimeException('Validator not defined, did you install the component?'); + throw new RuntimeException('"is_valid" cannot be used as the Validator component is not installed.'); } $errors = $variables['validator']->validate($object, null, $groups); diff --git a/src/Symfony/Component/Workflow/Tests/EventListener/GuardListenerTest.php b/src/Symfony/Component/Workflow/Tests/EventListener/GuardListenerTest.php index b46ee9092c573..f532639ae09c5 100644 --- a/src/Symfony/Component/Workflow/Tests/EventListener/GuardListenerTest.php +++ b/src/Symfony/Component/Workflow/Tests/EventListener/GuardListenerTest.php @@ -8,6 +8,7 @@ use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface; use Symfony\Component\Security\Core\Role\Role; +use Symfony\Component\Validator\Validator\ValidatorInterface; use Symfony\Component\Workflow\EventListener\ExpressionLanguage; use Symfony\Component\Workflow\EventListener\GuardListener; use Symfony\Component\Workflow\Event\GuardEvent; @@ -16,59 +17,85 @@ class GuardListenerTest extends TestCase { - private $tokenStorage; + private $authenticationChecker; + private $validator; private $listener; protected function setUp() { $configuration = array( - 'event_name_a' => 'true', - 'event_name_b' => 'false', + 'test_is_granted' => 'is_granted("something")', + 'test_is_valid' => 'is_valid(subject)', ); - $expressionLanguage = new ExpressionLanguage(); - $this->tokenStorage = $this->getMockBuilder(TokenStorageInterface::class)->getMock(); - $authenticationChecker = $this->getMockBuilder(AuthorizationCheckerInterface::class)->getMock(); + $token = $this->getMockBuilder(TokenInterface::class)->getMock(); + $token->expects($this->any())->method('getRoles')->willReturn(array(new Role('ROLE_USER'))); + $tokenStorage = $this->getMockBuilder(TokenStorageInterface::class)->getMock(); + $tokenStorage->expects($this->any())->method('getToken')->willReturn($token); + $this->authenticationChecker = $this->getMockBuilder(AuthorizationCheckerInterface::class)->getMock(); $trustResolver = $this->getMockBuilder(AuthenticationTrustResolverInterface::class)->getMock(); - - $this->listener = new GuardListener($configuration, $expressionLanguage, $this->tokenStorage, $authenticationChecker, $trustResolver); + $this->validator = $this->getMockBuilder(ValidatorInterface::class)->getMock(); + $this->listener = new GuardListener($configuration, $expressionLanguage, $tokenStorage, $this->authenticationChecker, $trustResolver, null, $this->validator); } protected function tearDown() { + $this->authenticationChecker = null; + $this->validator = null; $this->listener = null; } public function testWithNotSupportedEvent() { $event = $this->createEvent(); - $this->configureTokenStorage(false); + $this->configureAuthenticationChecker(false); + $this->configureValidator(false); $this->listener->onTransition($event, 'not supported'); $this->assertFalse($event->isBlocked()); } - public function testWithSupportedEventAndReject() + public function testWithSecuritySupportedEventAndReject() { $event = $this->createEvent(); - $this->configureTokenStorage(true); + $this->configureAuthenticationChecker(true, false); - $this->listener->onTransition($event, 'event_name_a'); + $this->listener->onTransition($event, 'test_is_granted'); + + $this->assertTrue($event->isBlocked()); + } + + public function testWithSecuritySupportedEventAndAccept() + { + $event = $this->createEvent(); + $this->configureAuthenticationChecker(true, true); + + $this->listener->onTransition($event, 'test_is_granted'); $this->assertFalse($event->isBlocked()); } - public function testWithSupportedEventAndAccept() + public function testWithValidatorSupportedEventAndReject() { $event = $this->createEvent(); - $this->configureTokenStorage(true); + $this->configureValidator(true, false); - $this->listener->onTransition($event, 'event_name_b'); + $this->listener->onTransition($event, 'test_is_valid'); $this->assertTrue($event->isBlocked()); } + public function testWithValidatorSupportedEventAndAccept() + { + $event = $this->createEvent(); + $this->configureValidator(true, true); + + $this->listener->onTransition($event, 'test_is_valid'); + + $this->assertFalse($event->isBlocked()); + } + private function createEvent() { $subject = new \stdClass(); @@ -78,28 +105,39 @@ private function createEvent() return new GuardEvent($subject, $subject->marking, $transition); } - private function configureTokenStorage($hasUser) + private function configureAuthenticationChecker($isUsed, $granted = true) { - if (!$hasUser) { - $this->tokenStorage + if (!$isUsed) { + $this->authenticationChecker ->expects($this->never()) - ->method('getToken') + ->method('isGranted') ; return; } - $token = $this->getMockBuilder(TokenInterface::class)->getMock(); - $token + $this->authenticationChecker ->expects($this->once()) - ->method('getRoles') - ->willReturn(array(new Role('ROLE_ADMIN'))) + ->method('isGranted') + ->willReturn($granted) ; + } + + private function configureValidator($isUsed, $valid = true) + { + if (!$isUsed) { + $this->validator + ->expects($this->never()) + ->method('validate') + ; + + return; + } - $this->tokenStorage + $this->validator ->expects($this->once()) - ->method('getToken') - ->willReturn($token) + ->method('validate') + ->willReturn($valid ? array() : array('a violation')) ; } } diff --git a/src/Symfony/Component/Workflow/composer.json b/src/Symfony/Component/Workflow/composer.json index 9a472dec60e34..1ff206983b822 100644 --- a/src/Symfony/Component/Workflow/composer.json +++ b/src/Symfony/Component/Workflow/composer.json @@ -28,7 +28,8 @@ "symfony/dependency-injection": "~2.8|~3.0|~4.0", "symfony/event-dispatcher": "~2.1|~3.0|~4.0", "symfony/expression-language": "~2.8|~3.0|~4.0", - "symfony/security-core": "~2.8|~3.0|~4.0" + "symfony/security-core": "~2.8|~3.0|~4.0", + "symfony/validator": "~2.8|~3.4|~4.0" }, "autoload": { "psr-4": { "Symfony\\Component\\Workflow\\": "" } From ce10f356a3882f362da703eec3be83cb55263879 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Fri, 6 Oct 2017 14:26:09 +0200 Subject: [PATCH 1032/1099] parse references on merge keys with objects --- src/Symfony/Component/Yaml/Parser.php | 5 ++++ .../Component/Yaml/Tests/ParserTest.php | 28 +++++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/src/Symfony/Component/Yaml/Parser.php b/src/Symfony/Component/Yaml/Parser.php index f3f168fee5338..5093d7cd1297f 100644 --- a/src/Symfony/Component/Yaml/Parser.php +++ b/src/Symfony/Component/Yaml/Parser.php @@ -332,6 +332,11 @@ private function doParse($value, $flags) $value = $this->parseBlock($this->getRealCurrentLineNb() + 1, $this->getNextEmbedBlock(), $flags); if ('<<' === $key) { $this->refs[$refMatches['ref']] = $value; + + if (Yaml::PARSE_OBJECT_FOR_MAP & $flags && $value instanceof \stdClass) { + $value = (array) $value; + } + $data += $value; } elseif ($allowOverwrite || !isset($data[$key])) { // Spec: Keys MUST be unique; first one wins. diff --git a/src/Symfony/Component/Yaml/Tests/ParserTest.php b/src/Symfony/Component/Yaml/Tests/ParserTest.php index 44b48674241ad..6cae75ae6ebbc 100644 --- a/src/Symfony/Component/Yaml/Tests/ParserTest.php +++ b/src/Symfony/Component/Yaml/Tests/ParserTest.php @@ -1941,6 +1941,34 @@ public function testParseReferencesOnMergeKeys() $this->assertSame($expected, $this->parser->parse($yaml)); } + + public function testParseReferencesOnMergeKeysWithMappingsParsedAsObjects() + { + $yaml = << (object) array( + 'a' => 'foo', + 'b' => 'bar', + 'c' => 'baz', + ), + 'mergekeyderef' => (object) array( + 'd' => 'quux', + 'b' => 'bar', + 'c' => 'baz', + ), + ); + + $this->assertEquals($expected, $this->parser->parse($yaml, Yaml::PARSE_OBJECT_FOR_MAP)); + } } class B From 45dd40cde8fa19a568f40026ea55987d78037531 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Thu, 28 Sep 2017 18:40:37 +0200 Subject: [PATCH 1033/1099] remove deprecated features --- .../Bundle/SecurityBundle/CHANGELOG.md | 3 ++ .../DependencyInjection/MainConfiguration.php | 4 +- .../DependencyInjection/SecurityExtension.php | 11 +--- .../SecurityExtensionTest.php | 54 +------------------ .../DependencyInjection/CHANGELOG.md | 43 +++++++++++++++ .../Compiler/AutowirePass.php | 45 ---------------- .../Loader/YamlFileLoader.php | 8 --- .../Tests/Compiler/AutowirePassTest.php | 39 ++------------ src/Symfony/Component/Filesystem/CHANGELOG.md | 1 + .../Exception/InvalidArgumentException.php | 19 +++++++ .../Component/Filesystem/Filesystem.php | 9 +++- .../Filesystem/Tests/FilesystemTest.php | 32 ++++------- .../Component/HttpKernel/Tests/KernelTest.php | 1 - .../Routing/Loader/YamlFileLoader.php | 8 --- .../Http/Firewall/ContextListener.php | 14 ++--- .../Tests/Firewall/ContextListenerTest.php | 18 +------ .../Translation/Loader/YamlFileLoader.php | 8 --- .../Mapping/Loader/YamlFileLoader.php | 8 --- 18 files changed, 97 insertions(+), 228 deletions(-) create mode 100644 src/Symfony/Component/Filesystem/Exception/InvalidArgumentException.php diff --git a/src/Symfony/Bundle/SecurityBundle/CHANGELOG.md b/src/Symfony/Bundle/SecurityBundle/CHANGELOG.md index 698d54011000d..1789357b85162 100644 --- a/src/Symfony/Bundle/SecurityBundle/CHANGELOG.md +++ b/src/Symfony/Bundle/SecurityBundle/CHANGELOG.md @@ -14,6 +14,9 @@ CHANGELOG * removed command `init:acl` along with `InitAclCommand` class * removed `acl` configuration key and related services, use symfony/acl-bundle instead * removed auto picking the first registered provider when no configured provider on a firewall and ambiguous + * the firewall option `logout_on_user_change` is now always true, which will trigger a logout if the user changes + between requests + * the `switch_user.stateless` firewall option is `true` for stateless firewalls 3.4.0 ----- diff --git a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/MainConfiguration.php b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/MainConfiguration.php index c0527dc716069..716d05a43d30b 100644 --- a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/MainConfiguration.php +++ b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/MainConfiguration.php @@ -202,8 +202,8 @@ private function addFirewallsSection(ArrayNodeDefinition $rootNode, array $facto ->booleanNode('stateless')->defaultFalse()->end() ->scalarNode('context')->cannotBeEmpty()->end() ->booleanNode('logout_on_user_change') - ->defaultFalse() - ->info('When true, it will trigger a logout for the user if something has changed. This will be the default behavior as of Syfmony 4.0.') + ->defaultTrue() + ->info('When true, it will trigger a logout for the user if something has changed.') ->end() ->arrayNode('logout') ->treatTrueLike(array()) diff --git a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php index 2b886d93a998a..0f1e21a5af740 100644 --- a/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php +++ b/src/Symfony/Bundle/SecurityBundle/DependencyInjection/SecurityExtension.php @@ -188,10 +188,6 @@ private function createFirewalls($config, ContainerBuilder $container) $customUserChecker = true; } - if (!isset($firewall['logout_on_user_change']) || !$firewall['logout_on_user_change']) { - @trigger_error('Setting logout_on_user_change to false is deprecated as of 3.4 and will always be true in 4.0. Set logout_on_user_change to true in your firewall configuration.', E_USER_DEPRECATED); - } - $contextListenerDefinition->addMethodCall('setLogoutOnUserChange', array($firewall['logout_on_user_change'])); $configId = 'security.firewall.map.config.'.$name; @@ -610,11 +606,6 @@ private function createSwitchUserListener($container, $id, $config, $defaultProv { $userProvider = isset($config['provider']) ? $this->getUserProviderId($config['provider']) : $defaultProvider; - // in 4.0, ignore the `switch_user.stateless` key if $stateless is `true` - if ($stateless && false === $config['stateless']) { - @trigger_error(sprintf('Firewall "%s" is configured as "stateless" but the "switch_user.stateless" key is set to false. Both should have the same value, the firewall\'s "stateless" value will be used as default value for the "switch_user.stateless" key in 4.0.', $id), E_USER_DEPRECATED); - } - $switchUserListenerId = 'security.authentication.switchuser_listener.'.$id; $listener = $container->setDefinition($switchUserListenerId, new ChildDefinition('security.authentication.switchuser_listener')); $listener->replaceArgument(1, new Reference($userProvider)); @@ -622,7 +613,7 @@ private function createSwitchUserListener($container, $id, $config, $defaultProv $listener->replaceArgument(3, $id); $listener->replaceArgument(6, $config['parameter']); $listener->replaceArgument(7, $config['role']); - $listener->replaceArgument(9, $config['stateless']); + $listener->replaceArgument(9, $stateless ?: $config['stateless']); return $switchUserListenerId; } diff --git a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/SecurityExtensionTest.php b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/SecurityExtensionTest.php index 18821f9aedd36..71171ae4f5d7f 100644 --- a/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/SecurityExtensionTest.php +++ b/src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/SecurityExtensionTest.php @@ -123,35 +123,6 @@ public function testDisableRoleHierarchyVoter() $this->assertFalse($container->hasDefinition('security.access.role_hierarchy_voter')); } - /** - * @group legacy - * @expectedDeprecation Setting logout_on_user_change to false is deprecated as of 3.4 and will always be true in 4.0. Set logout_on_user_change to true in your firewall configuration. - */ - public function testDeprecationForUserLogout() - { - $container = $this->getRawContainer(); - - $container->loadFromExtension('security', array( - 'providers' => array( - 'default' => array('id' => 'foo'), - ), - - 'firewalls' => array( - 'some_firewall' => array( - 'pattern' => '/.*', - 'http_basic' => null, - 'logout_on_user_change' => false, - ), - ), - )); - - $container->compile(); - } - - /** - * @group legacy - * @expectedDeprecation Firewall "some_firewall" is configured as "stateless" but the "switch_user.stateless" key is set to false. Both should have the same value, the firewall's "stateless" value will be used as default value for the "switch_user.stateless" key in 4.0. - */ public function testSwitchUserNotStatelessOnStatelessFirewall() { $container = $this->getRawContainer(); @@ -172,31 +143,8 @@ public function testSwitchUserNotStatelessOnStatelessFirewall() )); $container->compile(); - } - /** - * @expectedException \Symfony\Component\Config\Definition\Exception\InvalidConfigurationException - * @expectedExceptionMessage Not configuring explicitly the provider on "default" firewall is ambiguous as there is more than one registered provider. - */ - public function testDeprecationForAmbiguousProvider() - { - $container = $this->getRawContainer(); - - $container->loadFromExtension('security', array( - 'providers' => array( - 'first' => array('id' => 'foo'), - 'second' => array('id' => 'bar'), - ), - - 'firewalls' => array( - 'default' => array( - 'http_basic' => null, - 'logout_on_user_change' => true, - ), - ), - )); - - $container->compile(); + $this->assertTrue($container->getDefinition('security.authentication.switchuser_listener.some_firewall')->getArgument(9)); } protected function getRawContainer() diff --git a/src/Symfony/Component/DependencyInjection/CHANGELOG.md b/src/Symfony/Component/DependencyInjection/CHANGELOG.md index ca437e2cf6701..43a41fa621c88 100644 --- a/src/Symfony/Component/DependencyInjection/CHANGELOG.md +++ b/src/Symfony/Component/DependencyInjection/CHANGELOG.md @@ -4,6 +4,49 @@ CHANGELOG 4.0.0 ----- + * Relying on service auto-registration while autowiring is not supported anymore. + Explicitly inject your dependencies or create services whose ids are + their fully-qualified class name. + + Before: + + ```php + namespace App\Controller; + + use App\Mailer; + + class DefaultController + { + public function __construct(Mailer $mailer) { + // ... + } + + // ... + } + ``` + ```yml + services: + App\Controller\DefaultController: + autowire: true + ``` + + After: + + ```php + // same PHP code + ``` + ```yml + services: + App\Controller\DefaultController: + autowire: true + + # or + # App\Controller\DefaultController: + # arguments: { $mailer: "@App\Mailer" } + + App\Mailer: + autowire: true + ``` * removed autowiring services based on the types they implement * added a third `$methodName` argument to the `getProxyFactoryCode()` method of the `DumperInterface` diff --git a/src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php b/src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php index 1b099e0ac8885..ec3baa974057c 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php @@ -253,8 +253,6 @@ private function getAutowiredReference(TypedReference $reference, $deprecationMe if (isset($this->autowired[$type])) { return $this->autowired[$type] ? new TypedReference($this->autowired[$type], $type) : null; } - - return $this->createAutowiredDefinition($type); } /** @@ -325,49 +323,6 @@ private function set($type, $id) $this->ambiguousServiceTypes[$type][] = $id; } - /** - * Registers a definition for the type if possible or throws an exception. - * - * @param string $type - * - * @return TypedReference|null A reference to the registered definition - */ - private function createAutowiredDefinition($type) - { - if (!($typeHint = $this->container->getReflectionClass($type, false)) || !$typeHint->isInstantiable()) { - return; - } - - $currentId = $this->currentId; - $this->currentId = $type; - $this->autowired[$type] = $argumentId = sprintf('autowired.%s', $type); - $argumentDefinition = new Definition($type); - $argumentDefinition->setPublic(false); - $argumentDefinition->setAutowired(true); - - try { - $originalThrowSetting = $this->throwOnAutowiringException; - $this->throwOnAutowiringException = true; - $this->processValue($argumentDefinition, true); - $this->container->setDefinition($argumentId, $argumentDefinition); - } catch (AutowiringFailedException $e) { - $this->autowired[$type] = false; - $this->lastFailure = $e->getMessage(); - $this->container->log($this, $this->lastFailure); - - return; - } finally { - $this->throwOnAutowiringException = $originalThrowSetting; - $this->currentId = $currentId; - } - - @trigger_error(sprintf('Relying on service auto-registration for type "%s" is deprecated since version 3.4 and won\'t be supported in 4.0. Create a service named "%s" instead.', $type, $type), E_USER_DEPRECATED); - - $this->container->log($this, sprintf('Type "%s" has been auto-registered for service "%s".', $type, $this->currentId)); - - return new TypedReference($argumentId, $type); - } - private function createTypeNotFoundMessage(TypedReference $reference, $label) { if (!$r = $this->container->getReflectionClass($type = $reference->getType(), false)) { diff --git a/src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php b/src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php index 39e2c9ca5b269..d3b261d57b177 100644 --- a/src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php +++ b/src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php @@ -636,18 +636,10 @@ protected function loadFile($file) $this->yamlParser = new YamlParser(); } - $prevErrorHandler = set_error_handler(function ($level, $message, $script, $line) use ($file, &$prevErrorHandler) { - $message = E_USER_DEPRECATED === $level ? preg_replace('/ on line \d+/', ' in "'.$file.'"$0', $message) : $message; - - return $prevErrorHandler ? $prevErrorHandler($level, $message, $script, $line) : false; - }); - try { $configuration = $this->yamlParser->parseFile($file, Yaml::PARSE_CONSTANT | Yaml::PARSE_CUSTOM_TAGS); } catch (ParseException $e) { throw new InvalidArgumentException(sprintf('The file "%s" does not contain valid YAML.', $file), 0, $e); - } finally { - restore_error_handler(); } return $this->validate($configuration, $file); diff --git a/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowirePassTest.php b/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowirePassTest.php index c47d813220973..d28a5e613930a 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowirePassTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowirePassTest.php @@ -247,11 +247,10 @@ public function testWithTypeSet() } /** - * @group legacy - * @expectedDeprecation Relying on service auto-registration for type "Symfony\Component\DependencyInjection\Tests\Compiler\Lille" is deprecated since version 3.4 and won't be supported in 4.0. Create a service named "Symfony\Component\DependencyInjection\Tests\Compiler\Lille" instead. - * @expectedDeprecation Relying on service auto-registration for type "Symfony\Component\DependencyInjection\Tests\Compiler\Dunglas" is deprecated since version 3.4 and won't be supported in 4.0. Create a service named "Symfony\Component\DependencyInjection\Tests\Compiler\Dunglas" instead. + * @expectedException \Symfony\Component\DependencyInjection\Exception\AutowiringFailedException + * @expectedExceptionMessage Cannot autowire service "coop_tilleuls": argument "$j" of method "Symfony\Component\DependencyInjection\Tests\Compiler\LesTilleuls::__construct()" references class "Symfony\Component\DependencyInjection\Tests\Compiler\Dunglas" but no such service exists. */ - public function testCreateDefinition() + public function testServicesAreNotAutoCreated() { $container = new ContainerBuilder(); @@ -260,19 +259,6 @@ public function testCreateDefinition() $pass = new AutowirePass(); $pass->process($container); - - $this->assertCount(2, $container->getDefinition('coop_tilleuls')->getArguments()); - $this->assertEquals('autowired.Symfony\Component\DependencyInjection\Tests\Compiler\Dunglas', $container->getDefinition('coop_tilleuls')->getArgument(0)); - $this->assertEquals('autowired.Symfony\Component\DependencyInjection\Tests\Compiler\Dunglas', $container->getDefinition('coop_tilleuls')->getArgument(1)); - - $dunglasDefinition = $container->getDefinition('autowired.Symfony\Component\DependencyInjection\Tests\Compiler\Dunglas'); - $this->assertEquals(__NAMESPACE__.'\Dunglas', $dunglasDefinition->getClass()); - $this->assertFalse($dunglasDefinition->isPublic()); - $this->assertCount(1, $dunglasDefinition->getArguments()); - $this->assertEquals('autowired.Symfony\Component\DependencyInjection\Tests\Compiler\Lille', $dunglasDefinition->getArgument(0)); - - $lilleDefinition = $container->getDefinition('autowired.Symfony\Component\DependencyInjection\Tests\Compiler\Lille'); - $this->assertEquals(__NAMESPACE__.'\Lille', $lilleDefinition->getClass()); } public function testResolveParameter() @@ -563,25 +549,6 @@ public function testExplicitMethodInjection() ); } - /** - * @group legacy - * @expectedDeprecation Relying on service auto-registration for type "Symfony\Component\DependencyInjection\Tests\Compiler\A" is deprecated since version 3.4 and won't be supported in 4.0. Create a service named "Symfony\Component\DependencyInjection\Tests\Compiler\A" instead. - */ - public function testTypedReference() - { - $container = new ContainerBuilder(); - - $container - ->register('bar', Bar::class) - ->setProperty('a', array(new TypedReference(A::class, A::class, Bar::class))) - ; - - $pass = new AutowirePass(); - $pass->process($container); - - $this->assertSame(A::class, $container->getDefinition('autowired.'.A::class)->getClass()); - } - public function getCreateResourceTests() { return array( diff --git a/src/Symfony/Component/Filesystem/CHANGELOG.md b/src/Symfony/Component/Filesystem/CHANGELOG.md index 901d18a3e5cdc..9f1f817e753dd 100644 --- a/src/Symfony/Component/Filesystem/CHANGELOG.md +++ b/src/Symfony/Component/Filesystem/CHANGELOG.md @@ -5,6 +5,7 @@ CHANGELOG ----- * removed `LockHandler` + * Support for passing relative paths to `Filesystem::makePathRelative()` has been removed. 3.4.0 ----- diff --git a/src/Symfony/Component/Filesystem/Exception/InvalidArgumentException.php b/src/Symfony/Component/Filesystem/Exception/InvalidArgumentException.php new file mode 100644 index 0000000000000..abadc20029763 --- /dev/null +++ b/src/Symfony/Component/Filesystem/Exception/InvalidArgumentException.php @@ -0,0 +1,19 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Filesystem\Exception; + +/** + * @author Christian Flothmann + */ +class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface +{ +} diff --git a/src/Symfony/Component/Filesystem/Filesystem.php b/src/Symfony/Component/Filesystem/Filesystem.php index 3a8cae3eacb75..cacda17f899c5 100644 --- a/src/Symfony/Component/Filesystem/Filesystem.php +++ b/src/Symfony/Component/Filesystem/Filesystem.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Filesystem; +use Symfony\Component\Filesystem\Exception\InvalidArgumentException; use Symfony\Component\Filesystem\Exception\IOException; use Symfony\Component\Filesystem\Exception\FileNotFoundException; @@ -450,8 +451,12 @@ public function readlink($path, $canonicalize = false) */ public function makePathRelative($endPath, $startPath) { - if (!$this->isAbsolutePath($endPath) || !$this->isAbsolutePath($startPath)) { - @trigger_error(sprintf('Support for passing relative paths to %s() is deprecated since version 3.4 and will be removed in 4.0.', __METHOD__), E_USER_DEPRECATED); + if (!$this->isAbsolutePath($startPath)) { + throw new InvalidArgumentException(sprintf('The start path "%s" is not absolute.', $startPath)); + } + + if (!$this->isAbsolutePath($endPath)) { + throw new InvalidArgumentException(sprintf('The end path "%s" is not absolute.', $endPath)); } // Normalize separators on Windows diff --git a/src/Symfony/Component/Filesystem/Tests/FilesystemTest.php b/src/Symfony/Component/Filesystem/Tests/FilesystemTest.php index c72b9a2c4c9a6..4733660a38a2d 100644 --- a/src/Symfony/Component/Filesystem/Tests/FilesystemTest.php +++ b/src/Symfony/Component/Filesystem/Tests/FilesystemTest.php @@ -1141,33 +1141,21 @@ public function providePathsForMakePathRelative() } /** - * @group legacy - * @dataProvider provideLegacyPathsForMakePathRelativeWithRelativePaths - * @expectedDeprecation Support for passing relative paths to Symfony\Component\Filesystem\Filesystem::makePathRelative() is deprecated since version 3.4 and will be removed in 4.0. + * @expectedException \Symfony\Component\Filesystem\Exception\InvalidArgumentException + * @expectedExceptionMessage The start path "var/lib/symfony/src/Symfony/Component" is not absolute. */ - public function testMakePathRelativeWithRelativePaths($endPath, $startPath, $expectedPath) + public function testMakePathRelativeWithRelativeStartPath() { - $path = $this->filesystem->makePathRelative($endPath, $startPath); - - $this->assertEquals($expectedPath, $path); + $this->assertSame('../../../', $this->filesystem->makePathRelative('/var/lib/symfony/', 'var/lib/symfony/src/Symfony/Component')); } - public function provideLegacyPathsForMakePathRelativeWithRelativePaths() + /** + * @expectedException \Symfony\Component\Filesystem\Exception\InvalidArgumentException + * @expectedExceptionMessage The end path "var/lib/symfony/" is not absolute. + */ + public function testMakePathRelativeWithRelativeEndPath() { - return array( - array('usr/lib/symfony/', 'var/lib/symfony/src/Symfony/Component', '../../../../../../usr/lib/symfony/'), - array('aa/bb', 'aa/cc', '../bb/'), - array('aa/cc', 'bb/cc', '../../aa/cc/'), - array('aa/bb', 'aa/./cc', '../bb/'), - array('aa/./bb', 'aa/cc', '../bb/'), - array('aa/./bb', 'aa/./cc', '../bb/'), - array('../../', '../../', './'), - array('../aa/bb/', 'aa/bb/', '../../../aa/bb/'), - array('../../../', '../../', '../'), - array('', '', './'), - array('', 'aa/', '../'), - array('aa/', '', 'aa/'), - ); + $this->assertSame('../../../', $this->filesystem->makePathRelative('var/lib/symfony/', '/var/lib/symfony/src/Symfony/Component')); } public function testMirrorCopiesFilesAndDirectoriesRecursively() diff --git a/src/Symfony/Component/HttpKernel/Tests/KernelTest.php b/src/Symfony/Component/HttpKernel/Tests/KernelTest.php index 352e71f4bdc2d..5b259e7ff66eb 100644 --- a/src/Symfony/Component/HttpKernel/Tests/KernelTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/KernelTest.php @@ -415,7 +415,6 @@ public function testLocateResourceOnDirectories() } /** - * @group legacy * @expectedException \LogicException * @expectedExceptionMessage Trying to register two bundles with the same name "DuplicateName" */ diff --git a/src/Symfony/Component/Routing/Loader/YamlFileLoader.php b/src/Symfony/Component/Routing/Loader/YamlFileLoader.php index 037d581d05eab..f3072c927b73e 100644 --- a/src/Symfony/Component/Routing/Loader/YamlFileLoader.php +++ b/src/Symfony/Component/Routing/Loader/YamlFileLoader.php @@ -57,18 +57,10 @@ public function load($file, $type = null) $this->yamlParser = new YamlParser(); } - $prevErrorHandler = set_error_handler(function ($level, $message, $script, $line) use ($file, &$prevErrorHandler) { - $message = E_USER_DEPRECATED === $level ? preg_replace('/ on line \d+/', ' in "'.$file.'"$0', $message) : $message; - - return $prevErrorHandler ? $prevErrorHandler($level, $message, $script, $line) : false; - }); - try { $parsedConfig = $this->yamlParser->parseFile($path); } catch (ParseException $e) { throw new \InvalidArgumentException(sprintf('The file "%s" does not contain valid YAML.', $path), 0, $e); - } finally { - restore_error_handler(); } $collection = new RouteCollection(); diff --git a/src/Symfony/Component/Security/Http/Firewall/ContextListener.php b/src/Symfony/Component/Security/Http/Firewall/ContextListener.php index 553246ed8f0cf..7c762032aa151 100644 --- a/src/Symfony/Component/Security/Http/Firewall/ContextListener.php +++ b/src/Symfony/Component/Security/Http/Firewall/ContextListener.php @@ -43,7 +43,7 @@ class ContextListener implements ListenerInterface private $dispatcher; private $registered; private $trustResolver; - private $logoutOnUserChange = false; + private $logoutOnUserChange = true; /** * @param TokenStorageInterface $tokenStorage @@ -74,7 +74,7 @@ public function __construct(TokenStorageInterface $tokenStorage, iterable $userP */ public function setLogoutOnUserChange($logoutOnUserChange) { - $this->logoutOnUserChange = (bool) $logoutOnUserChange; + // no-op, method to be deprecated in 4.1 } /** @@ -183,15 +183,11 @@ protected function refreshUser(TokenInterface $token) // tokens can be deauthenticated if the user has been changed. if (!$token->isAuthenticated()) { - if ($this->logoutOnUserChange) { - if (null !== $this->logger) { - $this->logger->debug('Token was deauthenticated after trying to refresh it.', array('username' => $refreshedUser->getUsername(), 'provider' => get_class($provider))); - } - - return null; + if (null !== $this->logger) { + $this->logger->debug('Token was deauthenticated after trying to refresh it.', array('username' => $refreshedUser->getUsername(), 'provider' => get_class($provider))); } - @trigger_error('Refreshing a deauthenticated user is deprecated as of 3.4 and will trigger a logout in 4.0.', E_USER_DEPRECATED); + return null; } if (null !== $this->logger) { diff --git a/src/Symfony/Component/Security/Http/Tests/Firewall/ContextListenerTest.php b/src/Symfony/Component/Security/Http/Tests/Firewall/ContextListenerTest.php index d27569fa3a0ba..bb80cc25ab017 100644 --- a/src/Symfony/Component/Security/Http/Tests/Firewall/ContextListenerTest.php +++ b/src/Symfony/Component/Security/Http/Tests/Firewall/ContextListenerTest.php @@ -249,24 +249,11 @@ public function testHandleRemovesTokenIfNoPreviousSessionWasFound() $listener->handle($event); } - /** - * @group legacy - * @expectedDeprecation Refreshing a deauthenticated user is deprecated as of 3.4 and will trigger a logout in 4.0. - */ - public function testIfTokenIsDeauthenticatedTriggersDeprecations() - { - $tokenStorage = new TokenStorage(); - $refreshedUser = new User('foobar', 'baz'); - $this->handleEventWithPreviousSession($tokenStorage, array(new NotSupportingUserProvider(), new SupportingUserProvider($refreshedUser))); - - $this->assertSame($refreshedUser, $tokenStorage->getToken()->getUser()); - } - public function testIfTokenIsDeauthenticated() { $tokenStorage = new TokenStorage(); $refreshedUser = new User('foobar', 'baz'); - $this->handleEventWithPreviousSession($tokenStorage, array(new NotSupportingUserProvider(), new SupportingUserProvider($refreshedUser)), null, true); + $this->handleEventWithPreviousSession($tokenStorage, array(new NotSupportingUserProvider(), new SupportingUserProvider($refreshedUser))); $this->assertNull($tokenStorage->getToken()); } @@ -342,7 +329,7 @@ protected function runSessionOnKernelResponse($newToken, $original = null) return $session; } - private function handleEventWithPreviousSession(TokenStorageInterface $tokenStorage, $userProviders, UserInterface $user = null, $logoutOnUserChange = false) + private function handleEventWithPreviousSession(TokenStorageInterface $tokenStorage, $userProviders, UserInterface $user = null) { $user = $user ?: new User('foo', 'bar'); $session = new Session(new MockArraySessionStorage()); @@ -353,7 +340,6 @@ private function handleEventWithPreviousSession(TokenStorageInterface $tokenStor $request->cookies->set('MOCKSESSID', true); $listener = new ContextListener($tokenStorage, $userProviders, 'context_key'); - $listener->setLogoutOnUserChange($logoutOnUserChange); $listener->handle(new GetResponseEvent($this->getMockBuilder('Symfony\Component\HttpKernel\HttpKernelInterface')->getMock(), $request, HttpKernelInterface::MASTER_REQUEST)); } } diff --git a/src/Symfony/Component/Translation/Loader/YamlFileLoader.php b/src/Symfony/Component/Translation/Loader/YamlFileLoader.php index 07914f263155c..874fa3a8943e8 100644 --- a/src/Symfony/Component/Translation/Loader/YamlFileLoader.php +++ b/src/Symfony/Component/Translation/Loader/YamlFileLoader.php @@ -38,18 +38,10 @@ protected function loadResource($resource) $this->yamlParser = new YamlParser(); } - $prevErrorHandler = set_error_handler(function ($level, $message, $script, $line) use ($resource, &$prevErrorHandler) { - $message = E_USER_DEPRECATED === $level ? preg_replace('/ on line \d+/', ' in "'.$resource.'"$0', $message) : $message; - - return $prevErrorHandler ? $prevErrorHandler($level, $message, $script, $line) : false; - }); - try { $messages = $this->yamlParser->parseFile($resource); } catch (ParseException $e) { throw new InvalidResourceException(sprintf('Error parsing YAML, invalid file "%s"', $resource), 0, $e); - } finally { - restore_error_handler(); } return $messages; diff --git a/src/Symfony/Component/Validator/Mapping/Loader/YamlFileLoader.php b/src/Symfony/Component/Validator/Mapping/Loader/YamlFileLoader.php index a213b292acaae..e5e84c38c35dd 100644 --- a/src/Symfony/Component/Validator/Mapping/Loader/YamlFileLoader.php +++ b/src/Symfony/Component/Validator/Mapping/Loader/YamlFileLoader.php @@ -115,18 +115,10 @@ protected function parseNodes(array $nodes) */ private function parseFile($path) { - $prevErrorHandler = set_error_handler(function ($level, $message, $script, $line) use ($path, &$prevErrorHandler) { - $message = E_USER_DEPRECATED === $level ? preg_replace('/ on line \d+/', ' in "'.$path.'"$0', $message) : $message; - - return $prevErrorHandler ? $prevErrorHandler($level, $message, $script, $line) : false; - }); - try { $classes = $this->yamlParser->parseFile($path, Yaml::PARSE_CONSTANT); } catch (ParseException $e) { throw new \InvalidArgumentException(sprintf('The file "%s" does not contain valid YAML.', $path), 0, $e); - } finally { - restore_error_handler(); } // empty file From 33d2aa538248424aec9266cd9274f0670d18e749 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Fri, 6 Oct 2017 14:19:42 +0200 Subject: [PATCH 1034/1099] [Yaml] initialize inline line numbers Without this change, tests from `InlineTest` cannot be executed standalone as the parsed line number would never be initialized. --- src/Symfony/Component/Yaml/Tests/InlineTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/Yaml/Tests/InlineTest.php b/src/Symfony/Component/Yaml/Tests/InlineTest.php index 0b5c6cc4bcfe1..815c694b37abb 100644 --- a/src/Symfony/Component/Yaml/Tests/InlineTest.php +++ b/src/Symfony/Component/Yaml/Tests/InlineTest.php @@ -20,7 +20,7 @@ class InlineTest extends TestCase { protected function setUp() { - Inline::initialize(0); + Inline::initialize(0, 0); } /** From 3702e5ff37bbacf85151541d16d79e532acb6303 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Fri, 6 Oct 2017 17:17:51 +0200 Subject: [PATCH 1035/1099] remove unused fixtures file --- .../Tests/Fixtures/php/services31.php | 71 ------------------- 1 file changed, 71 deletions(-) delete mode 100644 src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services31.php diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services31.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services31.php deleted file mode 100644 index 51d9626372ca4..0000000000000 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services31.php +++ /dev/null @@ -1,71 +0,0 @@ -services = array(); - $this->methodMap = array( - 'bar' => 'getBarService', - 'foo' => 'getFooService', - ); - - $this->aliases = array(); - } - - /** - * {@inheritdoc} - */ - public function compile() - { - throw new LogicException('You cannot compile a dumped container that was already compiled.'); - } - - /** - * {@inheritdoc} - */ - public function isCompiled() - { - return true; - } - - /** - * {@inheritdoc} - */ - public function isFrozen() - { - @trigger_error(sprintf('The %s() method is deprecated since version 3.3 and will be removed in 4.0. Use the isCompiled() method instead.', __METHOD__), E_USER_DEPRECATED); - - return true; - } - - /** - * Gets the 'foo' service. - * - * This service is shared. - * This method always returns the same instance of the service. - * - * @return \Symfony\Component\DependencyInjection\Tests\Fixtures\Container31\Foo A Symfony\Component\DependencyInjection\Tests\Fixtures\Container31\Foo instance - */ - protected function getFooService() - { - return $this->services['foo'] = new \Symfony\Component\DependencyInjection\Tests\Fixtures\Container31\Foo(); - } -} From b43bdf398de2eee50b98aeab03ee66a63bd5830c Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Fri, 6 Oct 2017 08:49:22 -0700 Subject: [PATCH 1036/1099] fixed CS --- .../FrameworkBundle/DependencyInjection/FrameworkExtension.php | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php index 9bdbb373bb0f9..568bb0913ebc7 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php @@ -85,7 +85,6 @@ use Symfony\Component\Translation\Translator; use Symfony\Component\Validator\ConstraintValidatorInterface; use Symfony\Component\Validator\ObjectInitializerInterface; -use Symfony\Component\Validator\Validator\ValidatorInterface; use Symfony\Component\WebLink\HttpHeaderSerializer; use Symfony\Component\Workflow; use Symfony\Component\Yaml\Command\LintCommand as BaseYamlLintCommand; From ade7c905899439f86f98ad7d659432e41b205fdc Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Fri, 6 Oct 2017 18:17:48 +0200 Subject: [PATCH 1037/1099] drop non-existent working directory support --- src/Symfony/Component/Process/CHANGELOG.md | 2 ++ src/Symfony/Component/Process/Process.php | 6 +---- .../Component/Process/Tests/ProcessTest.php | 24 +------------------ 3 files changed, 4 insertions(+), 28 deletions(-) diff --git a/src/Symfony/Component/Process/CHANGELOG.md b/src/Symfony/Component/Process/CHANGELOG.md index a9f9173580afe..726a24c61423c 100644 --- a/src/Symfony/Component/Process/CHANGELOG.md +++ b/src/Symfony/Component/Process/CHANGELOG.md @@ -15,6 +15,8 @@ CHANGELOG * support for passing `proc_open()` options has been removed * removed the `ProcessBuilder` class, use the `Process` class instead * removed the `getEnhanceWindowsCompatibility()` and `setEnhanceWindowsCompatibility()` methods of the `Process` class + * passing a not existing working directory to the constructor of the `Symfony\Component\Process\Process` class is not + supported anymore 3.4.0 ----- diff --git a/src/Symfony/Component/Process/Process.php b/src/Symfony/Component/Process/Process.php index a9c63e9be11bb..7c5e4a5a338aa 100644 --- a/src/Symfony/Component/Process/Process.php +++ b/src/Symfony/Component/Process/Process.php @@ -297,11 +297,7 @@ public function start(callable $callback = null, array $env = array()) } if (!is_dir($this->cwd)) { - if ('\\' === DIRECTORY_SEPARATOR) { - throw new RuntimeException('The provided cwd does not exist.'); - } - - @trigger_error('The provided cwd does not exist. Command is currently ran against getcwd(). This behavior is deprecated since version 3.4 and will be removed in 4.0.', E_USER_DEPRECATED); + throw new RuntimeException('The provided cwd does not exist.'); } $this->process = proc_open($commandline, $descriptors, $this->processPipes->pipes, $this->cwd, null, $options); diff --git a/src/Symfony/Component/Process/Tests/ProcessTest.php b/src/Symfony/Component/Process/Tests/ProcessTest.php index 06ab288e6af34..8d490f361a216 100644 --- a/src/Symfony/Component/Process/Tests/ProcessTest.php +++ b/src/Symfony/Component/Process/Tests/ProcessTest.php @@ -47,34 +47,12 @@ protected function tearDown() } } - /** - * @group legacy - * @expectedDeprecation The provided cwd does not exist. Command is currently ran against getcwd(). This behavior is deprecated since version 3.4 and will be removed in 4.0. - */ - public function testInvalidCwd() - { - if ('\\' === DIRECTORY_SEPARATOR) { - $this->markTestSkipped('Windows handles this automatically.'); - } - - // Check that it works fine if the CWD exists - $cmd = new Process('echo test', __DIR__); - $cmd->run(); - - $cmd = new Process('echo test', __DIR__.'/notfound/'); - $cmd->run(); - } - /** * @expectedException \Symfony\Component\Process\Exception\RuntimeException * @expectedExceptionMessage The provided cwd does not exist. */ - public function testInvalidCwdOnWindows() + public function testInvalidCwd() { - if ('\\' !== DIRECTORY_SEPARATOR) { - $this->markTestSkipped('Unix handles this automatically.'); - } - try { // Check that it works fine if the CWD exists $cmd = new Process('echo test', __DIR__); From e5d0934b87ee4d7bb5fe8948e19a4849dbadcb30 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Fri, 6 Oct 2017 19:34:39 +0200 Subject: [PATCH 1038/1099] [DI] Turn private defs to non-public ones before removing passes --- .../Compiler/PassConfig.php | 6 +++ .../Compiler/ResolveChildDefinitionsPass.php | 23 ----------- .../Compiler/ResolvePrivatesPass.php | 40 +++++++++++++++++++ .../ResolveChildDefinitionsPassTest.php | 20 ---------- .../Compiler/ResolvePrivatesPassTest.php | 39 ++++++++++++++++++ 5 files changed, 85 insertions(+), 43 deletions(-) create mode 100644 src/Symfony/Component/DependencyInjection/Compiler/ResolvePrivatesPass.php create mode 100644 src/Symfony/Component/DependencyInjection/Tests/Compiler/ResolvePrivatesPassTest.php diff --git a/src/Symfony/Component/DependencyInjection/Compiler/PassConfig.php b/src/Symfony/Component/DependencyInjection/Compiler/PassConfig.php index 6c0448ecb4e81..bfae5ae6d6770 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/PassConfig.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/PassConfig.php @@ -71,6 +71,12 @@ public function __construct() new CheckArgumentsValidityPass(false), )); + $this->beforeRemovingPasses = array( + -100 => array( + new ResolvePrivatesPass(), + ), + ); + $this->removingPasses = array(array( new RemovePrivateAliasesPass(), new ReplaceAliasByActualDefinitionPass(), diff --git a/src/Symfony/Component/DependencyInjection/Compiler/ResolveChildDefinitionsPass.php b/src/Symfony/Component/DependencyInjection/Compiler/ResolveChildDefinitionsPass.php index 460fb55e472be..a124e472aca81 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/ResolveChildDefinitionsPass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/ResolveChildDefinitionsPass.php @@ -12,7 +12,6 @@ namespace Symfony\Component\DependencyInjection\Compiler; use Symfony\Component\DependencyInjection\ChildDefinition; -use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\DependencyInjection\Exception\ExceptionInterface; use Symfony\Component\DependencyInjection\Exception\RuntimeException; @@ -26,28 +25,6 @@ */ class ResolveChildDefinitionsPass extends AbstractRecursivePass { - /** - * {@inheritdoc} - */ - public function process(ContainerBuilder $container) - { - parent::process($container); - - foreach ($container->getDefinitions() as $definition) { - if ($definition->isPrivate()) { - $definition->setPublic(false); - $definition->setPrivate(true); - } - } - - foreach ($container->getAliases() as $alias) { - if ($alias->isPrivate()) { - $alias->setPublic(false); - $alias->setPrivate(true); - } - } - } - protected function processValue($value, $isRoot = false) { if (!$value instanceof Definition) { diff --git a/src/Symfony/Component/DependencyInjection/Compiler/ResolvePrivatesPass.php b/src/Symfony/Component/DependencyInjection/Compiler/ResolvePrivatesPass.php new file mode 100644 index 0000000000000..1bd993458a40e --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Compiler/ResolvePrivatesPass.php @@ -0,0 +1,40 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Compiler; + +use Symfony\Component\DependencyInjection\ContainerBuilder; + +/** + * @author Nicolas Grekas + */ +class ResolvePrivatesPass implements CompilerPassInterface +{ + /** + * {@inheritdoc} + */ + public function process(ContainerBuilder $container) + { + foreach ($container->getDefinitions() as $id => $definition) { + if ($definition->isPrivate()) { + $definition->setPublic(false); + $definition->setPrivate(true); + } + } + + foreach ($container->getAliases() as $id => $alias) { + if ($alias->isPrivate()) { + $alias->setPublic(false); + $alias->setPrivate(true); + } + } + } +} diff --git a/src/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveChildDefinitionsPassTest.php b/src/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveChildDefinitionsPassTest.php index c8135b965e80d..23a1915fd777c 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveChildDefinitionsPassTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Compiler/ResolveChildDefinitionsPassTest.php @@ -397,26 +397,6 @@ public function testSetAutoconfiguredOnServiceIsParent() $this->assertFalse($container->getDefinition('child1')->isAutoconfigured()); } - public function testPrivateHasHigherPrecedenceThanPublic() - { - $container = new ContainerBuilder(); - - $container->register('foo', 'stdClass') - ->setPublic(true) - ->setPrivate(true) - ; - - $container->setAlias('bar', 'foo') - ->setPublic(false) - ->setPrivate(false) - ; - - $this->process($container); - - $this->assertFalse($container->getDefinition('foo')->isPublic()); - $this->assertFalse($container->getAlias('bar')->isPublic()); - } - /** * @group legacy */ diff --git a/src/Symfony/Component/DependencyInjection/Tests/Compiler/ResolvePrivatesPassTest.php b/src/Symfony/Component/DependencyInjection/Tests/Compiler/ResolvePrivatesPassTest.php new file mode 100644 index 0000000000000..89af24f2c9c8e --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Tests/Compiler/ResolvePrivatesPassTest.php @@ -0,0 +1,39 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\DependencyInjection\Tests\Compiler; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\DependencyInjection\Compiler\ResolvePrivatesPass; +use Symfony\Component\DependencyInjection\ContainerBuilder; + +class ResolvePrivatesPassTest extends TestCase +{ + public function testPrivateHasHigherPrecedenceThanPublic() + { + $container = new ContainerBuilder(); + + $container->register('foo', 'stdClass') + ->setPublic(true) + ->setPrivate(true) + ; + + $container->setAlias('bar', 'foo') + ->setPublic(false) + ->setPrivate(false) + ; + + (new ResolvePrivatesPass())->process($container); + + $this->assertFalse($container->getDefinition('foo')->isPublic()); + $this->assertFalse($container->getAlias('bar')->isPublic()); + } +} From fe7f26d4f32afe6c05dcd67ffd094158020cfdcd Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Sat, 7 Oct 2017 23:38:34 +0200 Subject: [PATCH 1039/1099] [DI] Throw accurate failures when accessing removed services --- .../DependencyInjection/Container.php | 50 +++++++++----- .../DependencyInjection/ContainerBuilder.php | 28 ++++++-- .../DependencyInjection/Dumper/PhpDumper.php | 65 +++++++++++++++++++ .../Exception/ServiceNotFoundException.php | 6 +- .../Tests/ContainerTest.php | 18 ++++- .../Tests/Dumper/PhpDumperTest.php | 46 ++++--------- .../Tests/Fixtures/config/services9.php | 6 +- .../Tests/Fixtures/containers/container9.php | 4 +- .../Tests/Fixtures/php/services1-1.php | 8 +++ .../Tests/Fixtures/php/services1.php | 8 +++ .../Tests/Fixtures/php/services10.php | 8 +++ .../Tests/Fixtures/php/services12.php | 8 +++ .../Tests/Fixtures/php/services13.php | 9 +++ .../Tests/Fixtures/php/services19.php | 8 +++ .../Tests/Fixtures/php/services24.php | 8 +++ .../Tests/Fixtures/php/services26.php | 8 +++ .../Tests/Fixtures/php/services33.php | 8 +++ .../Tests/Fixtures/php/services8.php | 8 +++ .../Tests/Fixtures/php/services9.php | 3 + .../Tests/Fixtures/php/services9_as_files.txt | 21 ++++++ .../Tests/Fixtures/php/services9_compiled.php | 17 +++++ .../Fixtures/php/services_array_params.php | 8 +++ .../Fixtures/php/services_base64_env.php | 8 +++ .../Fixtures/php/services_legacy_privates.php | 11 ++++ .../Tests/Fixtures/php/services_locator.php | 11 ++++ .../Fixtures/php/services_private_frozen.php | 8 +++ .../php/services_private_in_expression.php | 9 +++ .../Tests/Fixtures/php/services_rot13_env.php | 8 +++ .../Fixtures/php/services_subscriber.php | 9 +++ .../php/services_uninitialized_ref.php | 9 +++ .../Tests/Fixtures/xml/services6.xml | 4 +- .../Tests/Fixtures/yaml/services6.yml | 12 ++-- .../Tests/Fixtures/yaml/services9.yml | 12 ++-- 33 files changed, 377 insertions(+), 77 deletions(-) diff --git a/src/Symfony/Component/DependencyInjection/Container.php b/src/Symfony/Component/DependencyInjection/Container.php index 8e33a3260feeb..754cfb7568c24 100644 --- a/src/Symfony/Component/DependencyInjection/Container.php +++ b/src/Symfony/Component/DependencyInjection/Container.php @@ -50,6 +50,7 @@ class Container implements ResettableContainerInterface protected $aliases = array(); protected $loading = array(); protected $resolving = array(); + protected $syntheticIds = array(); /** * @internal @@ -179,31 +180,34 @@ public function set($id, $service) throw new InvalidArgumentException('You cannot set service "service_container".'); } - if (isset($this->aliases[$id])) { - unset($this->aliases[$id]); - } - - $wasSet = isset($this->services[$id]); - $this->services[$id] = $service; - - if (null === $service) { - unset($this->services[$id]); - } - - if (isset($this->privates[$id])) { - if (null === $service) { + if (isset($this->privates[$id]) || !(isset($this->fileMap[$id]) || isset($this->methodMap[$id]))) { + if (isset($this->syntheticIds[$id]) || (!isset($this->privates[$id]) && !isset($this->getRemovedIds()[$id]))) { + // no-op + } elseif (null === $service) { @trigger_error(sprintf('The "%s" service is private, unsetting it is deprecated since Symfony 3.2 and will fail in 4.0.', $id), E_USER_DEPRECATED); unset($this->privates[$id]); } else { @trigger_error(sprintf('The "%s" service is private, replacing it is deprecated since Symfony 3.2 and will fail in 4.0.', $id), E_USER_DEPRECATED); } - } elseif ($wasSet && (isset($this->fileMap[$id]) || isset($this->methodMap[$id]))) { + } elseif (isset($this->services[$id])) { if (null === $service) { @trigger_error(sprintf('The "%s" service is already initialized, unsetting it is deprecated since Symfony 3.3 and will fail in 4.0.', $id), E_USER_DEPRECATED); } else { @trigger_error(sprintf('The "%s" service is already initialized, replacing it is deprecated since Symfony 3.3 and will fail in 4.0.', $id), E_USER_DEPRECATED); } } + + if (isset($this->aliases[$id])) { + unset($this->aliases[$id]); + } + + if (null === $service) { + unset($this->services[$id]); + + return; + } + + $this->services[$id] = $service; } /** @@ -275,7 +279,7 @@ public function get($id, $invalidBehavior = self::EXCEPTION_ON_INVALID_REFERENCE // calling $this->normalizeId($id) unless necessary. for ($i = 2;;) { if (isset($this->privates[$id])) { - @trigger_error(sprintf('The "%s" service is private, getting it from the container is deprecated since Symfony 3.2 and will fail in 4.0. You should either make the service public, or stop getting services directly from the container and use dependency injection instead.', $id), E_USER_DEPRECATED); + @trigger_error(sprintf('The "%s" service is private, getting it from the container is deprecated since Symfony 3.2 and will fail in 4.0. You should either make the service public, or stop using the container directly and use dependency injection instead.', $id), E_USER_DEPRECATED); } if (isset($this->aliases[$id])) { $id = $this->aliases[$id]; @@ -325,6 +329,12 @@ public function get($id, $invalidBehavior = self::EXCEPTION_ON_INVALID_REFERENCE if (!$id) { throw new ServiceNotFoundException($id); } + if (isset($this->syntheticIds[$id])) { + throw new ServiceNotFoundException($id, null, null, array(), sprintf('The "%s" service is synthetic, it needs to be set at boot time before it can be used.', $id)); + } + if (isset($this->getRemovedIds()[$id])) { + throw new ServiceNotFoundException($id, null, null, array(), sprintf('The "%s" service or alias has been removed or inlined when the container was compiled. You should either make it public, or stop using the container directly and use dependency injection instead.', $id)); + } $alternatives = array(); foreach ($this->getServiceIds() as $knownId) { @@ -397,6 +407,16 @@ public function getServiceIds() return array_unique(array_merge($ids, array_keys($this->methodMap), array_keys($this->fileMap), array_keys($this->services))); } + /** + * Gets service ids that existed at compile time. + * + * @return array + */ + public function getRemovedIds() + { + return array(); + } + /** * Camelizes a string. * diff --git a/src/Symfony/Component/DependencyInjection/ContainerBuilder.php b/src/Symfony/Component/DependencyInjection/ContainerBuilder.php index d46da389f05b4..17098f1e51452 100644 --- a/src/Symfony/Component/DependencyInjection/ContainerBuilder.php +++ b/src/Symfony/Component/DependencyInjection/ContainerBuilder.php @@ -121,6 +121,8 @@ class ContainerBuilder extends Container implements TaggedContainerInterface private $autoconfiguredInstanceof = array(); + private $removedIds = array(); + public function __construct(ParameterBagInterface $parameterBag = null) { parent::__construct($parameterBag); @@ -517,7 +519,7 @@ public function set($id, $service) throw new BadMethodCallException(sprintf('Setting service "%s" for an unknown or non-synthetic service definition on a compiled container is not allowed.', $id)); } - unset($this->definitions[$id], $this->aliasDefinitions[$id]); + unset($this->definitions[$id], $this->aliasDefinitions[$id], $this->removedIds[$id]); parent::set($id, $service); } @@ -529,7 +531,10 @@ public function set($id, $service) */ public function removeDefinition($id) { - unset($this->definitions[$this->normalizeId($id)]); + if (isset($this->definitions[$id = $this->normalizeId($id)])) { + unset($this->definitions[$id]); + $this->removedIds[$id] = true; + } } /** @@ -793,6 +798,16 @@ public function getServiceIds() return array_unique(array_merge(array_keys($this->getDefinitions()), array_keys($this->aliasDefinitions), parent::getServiceIds())); } + /** + * Gets removed service or alias ids. + * + * @return array + */ + public function getRemovedIds() + { + return $this->removedIds; + } + /** * Adds the service aliases. * @@ -841,7 +856,7 @@ public function setAlias($alias, $id) throw new InvalidArgumentException(sprintf('An alias can not reference itself, got a circular reference on "%s".', $alias)); } - unset($this->definitions[$alias]); + unset($this->definitions[$alias], $this->removedIds[$alias]); return $this->aliasDefinitions[$alias] = $id; } @@ -853,7 +868,10 @@ public function setAlias($alias, $id) */ public function removeAlias($alias) { - unset($this->aliasDefinitions[$this->normalizeId($alias)]); + if (isset($this->aliasDefinitions[$alias = $this->normalizeId($alias)])) { + unset($this->aliasDefinitions[$alias]); + $this->removedIds[$alias] = true; + } } /** @@ -981,7 +999,7 @@ public function setDefinition($id, Definition $definition) $id = $this->normalizeId($id); - unset($this->aliasDefinitions[$id]); + unset($this->aliasDefinitions[$id], $this->removedIds[$id]); return $this->definitions[$id] = $definition; } diff --git a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php index c8a4d5cd3af68..f12d813890615 100644 --- a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php +++ b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php @@ -172,6 +172,16 @@ public function dump(array $options = array()) EOF; $files = array(); + + if ($ids = array_keys($this->container->getRemovedIds())) { + sort($ids); + $c = "export($id)." => true,\n"; + } + $files['removed-ids.php'] = $c .= ");\n"; + } + foreach ($this->generateServiceFiles() as $file => $c) { $files[$file] = $fileStart.$c; } @@ -888,6 +898,7 @@ public function __construct() } $code .= $this->addNormalizedIds(); + $code .= $this->addSyntheticIds(); $code .= $this->addMethodMap(); $code .= $this->asFiles ? $this->addFileMap() : ''; $code .= $this->addPrivateServices(); @@ -896,6 +907,8 @@ public function __construct() } EOF; + $code .= $this->addRemovedIds(); + if ($this->container->isCompiled()) { $code .= <<normalizedIds = array(\n".$code." );\n" : ''; } + /** + * Adds the syntheticIds definition. + * + * @return string + */ + private function addSyntheticIds() + { + $code = ''; + $definitions = $this->container->getDefinitions(); + ksort($definitions); + foreach ($definitions as $id => $definition) { + if ($definition->isSynthetic() && 'service_container' !== $id) { + $code .= ' '.$this->export($id)." => true,\n"; + } + } + + return $code ? " \$this->syntheticIds = array(\n{$code} );\n" : ''; + } + + /** + * Adds the removedIds definition. + * + * @return string + */ + private function addRemovedIds() + { + if (!$ids = $this->container->getRemovedIds()) { + return ''; + } + if ($this->asFiles) { + $code = "require __DIR__.'/removed-ids.php'"; + } else { + $code = ''; + $ids = array_keys($ids); + sort($ids); + foreach ($ids as $id) { + $code .= ' '.$this->export($id)." => true,\n"; + } + + $code = "array(\n{$code} )"; + } + + return <<get('request'); } + /** + * @expectedException \Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException + * @expectedExceptionMessage The "inlined" service or alias has been removed or inlined when the container was compiled. You should either make it public, or stop using the container directly and use dependency injection instead. + */ + public function testGetRemovedServiceThrows() + { + require_once __DIR__.'/Fixtures/php/services9_compiled.php'; + + $container = new \ProjectServiceContainer(); + $container->get('inlined'); + } + public function testHas() { $sc = new ProjectServiceContainer(); @@ -505,7 +517,7 @@ public function testCheckExistenceOfAnInternalPrivateServiceIsDeprecated() /** * @group legacy - * @expectedDeprecation The "internal" service is private, getting it from the container is deprecated since Symfony 3.2 and will fail in 4.0. You should either make the service public, or stop getting services directly from the container and use dependency injection instead. + * @expectedDeprecation The "internal" service is private, getting it from the container is deprecated since Symfony 3.2 and will fail in 4.0. You should either make the service public, or stop using the container directly and use dependency injection instead. */ public function testRequestAnInternalSharedPrivateServiceIsDeprecated() { diff --git a/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php b/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php index bda74490c9382..014ce3c16f885 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php @@ -287,37 +287,17 @@ public function testFrozenContainerWithoutAliases() /** * @group legacy - * @expectedDeprecation The "bar" service is already initialized, replacing it is deprecated since Symfony 3.3 and will fail in 4.0. + * @expectedDeprecation The "decorator_service" service is already initialized, replacing it is deprecated since Symfony 3.3 and will fail in 4.0. */ public function testOverrideServiceWhenUsingADumpedContainer() { - require_once self::$fixturesPath.'/php/services9.php'; - require_once self::$fixturesPath.'/includes/foo.php'; + require_once self::$fixturesPath.'/php/services9_compiled.php'; $container = new \ProjectServiceContainer(); - $container->setParameter('foo_bar', 'foo_bar'); - $container->get('bar'); - $container->set('bar', $bar = new \stdClass()); - - $this->assertSame($bar, $container->get('bar'), '->set() overrides an already defined service'); - } - - /** - * @group legacy - * @expectedDeprecation The "bar" service is already initialized, replacing it is deprecated since Symfony 3.3 and will fail in 4.0. - */ - public function testOverrideServiceWhenUsingADumpedContainerAndServiceIsUsedFromAnotherOne() - { - require_once self::$fixturesPath.'/php/services9.php'; - require_once self::$fixturesPath.'/includes/foo.php'; - require_once self::$fixturesPath.'/includes/classes.php'; - - $container = new \ProjectServiceContainer(); - $container->setParameter('foo_bar', 'foo_bar'); - $container->get('bar'); - $container->set('bar', $bar = new \stdClass()); + $container->get('decorator_service'); + $container->set('decorator_service', $decorator = new \stdClass()); - $this->assertSame($bar, $container->get('foo')->bar, '->set() overrides an already defined service'); + $this->assertSame($decorator, $container->get('decorator_service'), '->set() overrides an already defined service'); } /** @@ -799,14 +779,14 @@ public function testDumpHandlesLiteralClassWithRootNamespace() /** * @group legacy - * @expectedDeprecation The "private" service is private, getting it from the container is deprecated since Symfony 3.2 and will fail in 4.0. You should either make the service public, or stop getting services directly from the container and use dependency injection instead. - * @expectedDeprecation The "private_alias" service is private, getting it from the container is deprecated since Symfony 3.2 and will fail in 4.0. You should either make the service public, or stop getting services directly from the container and use dependency injection instead. - * @expectedDeprecation The "decorated_private" service is private, getting it from the container is deprecated since Symfony 3.2 and will fail in 4.0. You should either make the service public, or stop getting services directly from the container and use dependency injection instead. - * @expectedDeprecation The "decorated_private_alias" service is private, getting it from the container is deprecated since Symfony 3.2 and will fail in 4.0. You should either make the service public, or stop getting services directly from the container and use dependency injection instead. - * @expectedDeprecation The "private_not_inlined" service is private, getting it from the container is deprecated since Symfony 3.2 and will fail in 4.0. You should either make the service public, or stop getting services directly from the container and use dependency injection instead. - * @expectedDeprecation The "private_not_removed" service is private, getting it from the container is deprecated since Symfony 3.2 and will fail in 4.0. You should either make the service public, or stop getting services directly from the container and use dependency injection instead. - * @expectedDeprecation The "private_child" service is private, getting it from the container is deprecated since Symfony 3.2 and will fail in 4.0. You should either make the service public, or stop getting services directly from the container and use dependency injection instead. - * @expectedDeprecation The "private_parent" service is private, getting it from the container is deprecated since Symfony 3.2 and will fail in 4.0. You should either make the service public, or stop getting services directly from the container and use dependency injection instead. + * @expectedDeprecation The "private" service is private, getting it from the container is deprecated since Symfony 3.2 and will fail in 4.0. You should either make the service public, or stop using the container directly and use dependency injection instead. + * @expectedDeprecation The "private_alias" service is private, getting it from the container is deprecated since Symfony 3.2 and will fail in 4.0. You should either make the service public, or stop using the container directly and use dependency injection instead. + * @expectedDeprecation The "decorated_private" service is private, getting it from the container is deprecated since Symfony 3.2 and will fail in 4.0. You should either make the service public, or stop using the container directly and use dependency injection instead. + * @expectedDeprecation The "decorated_private_alias" service is private, getting it from the container is deprecated since Symfony 3.2 and will fail in 4.0. You should either make the service public, or stop using the container directly and use dependency injection instead. + * @expectedDeprecation The "private_not_inlined" service is private, getting it from the container is deprecated since Symfony 3.2 and will fail in 4.0. You should either make the service public, or stop using the container directly and use dependency injection instead. + * @expectedDeprecation The "private_not_removed" service is private, getting it from the container is deprecated since Symfony 3.2 and will fail in 4.0. You should either make the service public, or stop using the container directly and use dependency injection instead. + * @expectedDeprecation The "private_child" service is private, getting it from the container is deprecated since Symfony 3.2 and will fail in 4.0. You should either make the service public, or stop using the container directly and use dependency injection instead. + * @expectedDeprecation The "private_parent" service is private, getting it from the container is deprecated since Symfony 3.2 and will fail in 4.0. You should either make the service public, or stop using the container directly and use dependency injection instead. */ public function testLegacyPrivateServices() { diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/services9.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/services9.php index 3f4d5f15ea71a..b013e5126d3b6 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/services9.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/config/services9.php @@ -40,9 +40,6 @@ ->args(array(ref('deprecated_service'))) ->share(false); - $s->alias('alias_for_foo', 'foo')->private()->public(); - $s->alias('alias_for_alias', ref('alias_for_foo')); - $s->set('method_call1', 'Bar\FooClass') ->file(realpath(__DIR__.'/../includes/foo.php')) ->call('setBar', array(ref('foo'))) @@ -125,4 +122,7 @@ $s->set('tagged_iterator', 'Bar') ->public() ->args(array(tagged('foo'))); + + $s->alias('alias_for_foo', 'foo')->private()->public(); + $s->alias('alias_for_alias', ref('alias_for_foo')); }; diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container9.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container9.php index 452dab6d806b6..21d35611c33ae 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container9.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container9.php @@ -48,8 +48,6 @@ 'foo_class' => 'Bar\FooClass', 'foo' => 'bar', )); -$container->setAlias('alias_for_foo', 'foo')->setPublic(true); -$container->setAlias('alias_for_alias', 'alias_for_foo')->setPublic(true); $container ->register('method_call1', 'Bar\FooClass') ->setFile(realpath(__DIR__.'/../includes/foo.php')) @@ -172,5 +170,7 @@ ->addArgument(new TaggedIteratorArgument('foo')) ->setPublic(true) ; +$container->setAlias('alias_for_foo', 'foo')->setPublic(true); +$container->setAlias('alias_for_alias', 'alias_for_foo')->setPublic(true); return $container; diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services1-1.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services1-1.php index e696dec6aedb4..349358c384549 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services1-1.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services1-1.php @@ -28,6 +28,14 @@ public function __construct() $this->aliases = array(); } + public function getRemovedIds() + { + return array( + 'Psr\\Container\\ContainerInterface' => true, + 'Symfony\\Component\\DependencyInjection\\ContainerInterface' => true, + ); + } + public function compile() { throw new LogicException('You cannot compile a dumped container that was already compiled.'); diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services1.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services1.php index c339856f0276b..8d7aab16c77b1 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services1.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services1.php @@ -26,6 +26,14 @@ public function __construct() $this->aliases = array(); } + public function getRemovedIds() + { + return array( + 'Psr\\Container\\ContainerInterface' => true, + 'Symfony\\Component\\DependencyInjection\\ContainerInterface' => true, + ); + } + public function compile() { throw new LogicException('You cannot compile a dumped container that was already compiled.'); diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services10.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services10.php index 219cf3431b573..bfd6587a4eb33 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services10.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services10.php @@ -31,6 +31,14 @@ public function __construct() $this->aliases = array(); } + public function getRemovedIds() + { + return array( + 'Psr\\Container\\ContainerInterface' => true, + 'Symfony\\Component\\DependencyInjection\\ContainerInterface' => true, + ); + } + public function compile() { throw new LogicException('You cannot compile a dumped container that was already compiled.'); diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services12.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services12.php index 2bd134a9f8400..c5c434ec7d7c1 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services12.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services12.php @@ -35,6 +35,14 @@ public function __construct() $this->aliases = array(); } + public function getRemovedIds() + { + return array( + 'Psr\\Container\\ContainerInterface' => true, + 'Symfony\\Component\\DependencyInjection\\ContainerInterface' => true, + ); + } + public function compile() { throw new LogicException('You cannot compile a dumped container that was already compiled.'); diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services13.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services13.php index 4cc353ca278de..577e0221d0185 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services13.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services13.php @@ -29,6 +29,15 @@ public function __construct() $this->aliases = array(); } + public function getRemovedIds() + { + return array( + 'Psr\\Container\\ContainerInterface' => true, + 'Symfony\\Component\\DependencyInjection\\ContainerInterface' => true, + 'foo' => true, + ); + } + public function compile() { throw new LogicException('You cannot compile a dumped container that was already compiled.'); diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services19.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services19.php index 0a6b97e65ded6..0b2682420ff53 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services19.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services19.php @@ -30,6 +30,14 @@ public function __construct() $this->aliases = array(); } + public function getRemovedIds() + { + return array( + 'Psr\\Container\\ContainerInterface' => true, + 'Symfony\\Component\\DependencyInjection\\ContainerInterface' => true, + ); + } + public function compile() { throw new LogicException('You cannot compile a dumped container that was already compiled.'); diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services24.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services24.php index 7546b1765a658..02a7a1b0c2657 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services24.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services24.php @@ -29,6 +29,14 @@ public function __construct() $this->aliases = array(); } + public function getRemovedIds() + { + return array( + 'Psr\\Container\\ContainerInterface' => true, + 'Symfony\\Component\\DependencyInjection\\ContainerInterface' => true, + ); + } + public function compile() { throw new LogicException('You cannot compile a dumped container that was already compiled.'); diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services26.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services26.php index 7dc51d12afed1..6519a9dff76a4 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services26.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services26.php @@ -35,6 +35,14 @@ public function __construct() $this->aliases = array(); } + public function getRemovedIds() + { + return array( + 'Psr\\Container\\ContainerInterface' => true, + 'Symfony\\Component\\DependencyInjection\\ContainerInterface' => true, + ); + } + public function compile() { throw new LogicException('You cannot compile a dumped container that was already compiled.'); diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services33.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services33.php index e36cdcaedb918..1a8b3f0c5215d 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services33.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services33.php @@ -34,6 +34,14 @@ public function __construct() $this->aliases = array(); } + public function getRemovedIds() + { + return array( + 'Psr\\Container\\ContainerInterface' => true, + 'Symfony\\Component\\DependencyInjection\\ContainerInterface' => true, + ); + } + public function compile() { throw new LogicException('You cannot compile a dumped container that was already compiled.'); diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services8.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services8.php index 357b8aa697560..8db48ade93bb9 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services8.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services8.php @@ -28,6 +28,14 @@ public function __construct() $this->aliases = array(); } + public function getRemovedIds() + { + return array( + 'Psr\\Container\\ContainerInterface' => true, + 'Symfony\\Component\\DependencyInjection\\ContainerInterface' => true, + ); + } + public function compile() { throw new LogicException('You cannot compile a dumped container that was already compiled.'); diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9.php index b05b886871ab1..30b94d456ef6f 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9.php @@ -26,6 +26,9 @@ public function __construct() 'psr\\container\\containerinterface' => 'Psr\\Container\\ContainerInterface', 'symfony\\component\\dependencyinjection\\containerinterface' => 'Symfony\\Component\\DependencyInjection\\ContainerInterface', ); + $this->syntheticIds = array( + 'request' => true, + ); $this->methodMap = array( 'bar' => 'getBarService', 'baz' => 'getBazService', diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_as_files.txt b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_as_files.txt index 3795ade4806e6..83074c984e382 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_as_files.txt +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_as_files.txt @@ -1,5 +1,18 @@ Array ( + [Container%s/removed-ids.php] => true, + 'Symfony\\Component\\DependencyInjection\\ContainerInterface' => true, + 'configurator_service' => true, + 'configurator_service_simple' => true, + 'decorated.pif-pouf' => true, + 'decorator_service.inner' => true, + 'inlined' => true, + 'new_factory' => true, +); + [Container%s/getBarService.php] => parameters = $this->getDefaultParameters(); $this->services = array(); + $this->syntheticIds = array( + 'request' => true, + ); $this->methodMap = array( 'foo_bar' => 'getFooBarService', ); @@ -322,6 +338,11 @@ class Container%s extends Container ); } + public function getRemovedIds() + { + return require __DIR__.'/removed-ids.php'; + } + public function compile() { throw new LogicException('You cannot compile a dumped container that was already compiled.'); diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_compiled.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_compiled.php index 7ec609ca5e6cb..403eb12954fe1 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_compiled.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_compiled.php @@ -24,6 +24,9 @@ public function __construct() $this->parameters = $this->getDefaultParameters(); $this->services = array(); + $this->syntheticIds = array( + 'request' => true, + ); $this->methodMap = array( 'bar' => 'getBarService', 'baz' => 'getBazService', @@ -58,6 +61,20 @@ public function __construct() ); } + public function getRemovedIds() + { + return array( + 'Psr\\Container\\ContainerInterface' => true, + 'Symfony\\Component\\DependencyInjection\\ContainerInterface' => true, + 'configurator_service' => true, + 'configurator_service_simple' => true, + 'decorated.pif-pouf' => true, + 'decorator_service.inner' => true, + 'inlined' => true, + 'new_factory' => true, + ); + } + public function compile() { throw new LogicException('You cannot compile a dumped container that was already compiled.'); diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_array_params.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_array_params.php index e5159861b4708..65e6b61e34e57 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_array_params.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_array_params.php @@ -35,6 +35,14 @@ public function __construct() $this->aliases = array(); } + public function getRemovedIds() + { + return array( + 'Psr\\Container\\ContainerInterface' => true, + 'Symfony\\Component\\DependencyInjection\\ContainerInterface' => true, + ); + } + public function compile() { throw new LogicException('You cannot compile a dumped container that was already compiled.'); diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_base64_env.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_base64_env.php index 8513e25d2e085..d796c0dae676f 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_base64_env.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_base64_env.php @@ -28,6 +28,14 @@ public function __construct() $this->aliases = array(); } + public function getRemovedIds() + { + return array( + 'Psr\\Container\\ContainerInterface' => true, + 'Symfony\\Component\\DependencyInjection\\ContainerInterface' => true, + ); + } + public function compile() { throw new LogicException('You cannot compile a dumped container that was already compiled.'); diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_legacy_privates.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_legacy_privates.php index fad546d7fc348..f8c33ae59966a 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_legacy_privates.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_legacy_privates.php @@ -55,6 +55,17 @@ public function __construct() ); } + public function getRemovedIds() + { + return array( + 'Psr\\Container\\ContainerInterface' => true, + 'Symfony\\Component\\DependencyInjection\\ContainerInterface' => true, + 'foo' => true, + 'private_alias_decorator.inner' => true, + 'private_decorator.inner' => true, + ); + } + public function compile() { throw new LogicException('You cannot compile a dumped container that was already compiled.'); diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_locator.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_locator.php index 74e2a8ce094a2..339076ea3bea2 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_locator.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_locator.php @@ -40,6 +40,17 @@ public function __construct() $this->aliases = array(); } + public function getRemovedIds() + { + return array( + 'Psr\\Container\\ContainerInterface' => true, + 'Symfony\\Component\\DependencyInjection\\ContainerInterface' => true, + 'translator.loader_1_locator' => true, + 'translator.loader_2_locator' => true, + 'translator.loader_3_locator' => true, + ); + } + public function compile() { throw new LogicException('You cannot compile a dumped container that was already compiled.'); diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_private_frozen.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_private_frozen.php index c7ea243ae81a0..59857ecac3ef8 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_private_frozen.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_private_frozen.php @@ -34,6 +34,14 @@ public function __construct() $this->aliases = array(); } + public function getRemovedIds() + { + return array( + 'Psr\\Container\\ContainerInterface' => true, + 'Symfony\\Component\\DependencyInjection\\ContainerInterface' => true, + ); + } + public function compile() { throw new LogicException('You cannot compile a dumped container that was already compiled.'); diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_private_in_expression.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_private_in_expression.php index 8269736c0b8df..70af6ce7e3661 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_private_in_expression.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_private_in_expression.php @@ -33,6 +33,15 @@ public function __construct() $this->aliases = array(); } + public function getRemovedIds() + { + return array( + 'Psr\\Container\\ContainerInterface' => true, + 'Symfony\\Component\\DependencyInjection\\ContainerInterface' => true, + 'private_bar' => true, + ); + } + public function compile() { throw new LogicException('You cannot compile a dumped container that was already compiled.'); diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_rot13_env.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_rot13_env.php index 3b26928577247..d888187bf534b 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_rot13_env.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_rot13_env.php @@ -35,6 +35,14 @@ public function __construct() $this->aliases = array(); } + public function getRemovedIds() + { + return array( + 'Psr\\Container\\ContainerInterface' => true, + 'Symfony\\Component\\DependencyInjection\\ContainerInterface' => true, + ); + } + public function compile() { throw new LogicException('You cannot compile a dumped container that was already compiled.'); diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_subscriber.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_subscriber.php index a4ab454e3efc0..76d87489a98b6 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_subscriber.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_subscriber.php @@ -38,6 +38,15 @@ public function __construct() $this->aliases = array(); } + public function getRemovedIds() + { + return array( + 'Psr\\Container\\ContainerInterface' => true, + 'Symfony\\Component\\DependencyInjection\\ContainerInterface' => true, + 'service_locator.jmktfsv' => true, + ); + } + public function compile() { throw new LogicException('You cannot compile a dumped container that was already compiled.'); diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_uninitialized_ref.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_uninitialized_ref.php index c47e7c15d1291..df5a40c839749 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_uninitialized_ref.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services_uninitialized_ref.php @@ -35,6 +35,15 @@ public function __construct() $this->aliases = array(); } + public function getRemovedIds() + { + return array( + 'Psr\\Container\\ContainerInterface' => true, + 'Symfony\\Component\\DependencyInjection\\ContainerInterface' => true, + 'foo2' => true, + ); + } + public function compile() { throw new LogicException('You cannot compile a dumped container that was already compiled.'); diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services6.xml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services6.xml index 5134ff7671f11..cffd5df6059ac 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services6.xml +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services6.xml @@ -43,8 +43,6 @@
- - @@ -61,5 +59,7 @@ + + diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services6.yml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services6.yml index bfc995d44e450..1ee6c6ec740eb 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services6.yml +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services6.yml @@ -17,16 +17,10 @@ services: class: FooClass calls: - [ setBar, [ foo, '@foo', [true, false] ] ] - alias_for_foo: '@foo' - another_alias_for_foo: - alias: foo - public: false request: class: Request synthetic: true lazy: true - another_third_alias_for_foo: - alias: foo decorator_service: decorates: decorated decorator_service_with_name: @@ -41,3 +35,9 @@ services: new_factory3: { class: FooBarClass, factory: [BazClass, getInstance]} new_factory4: { class: BazClass, factory: [~, getInstance]} Acme\WithShortCutArgs: [foo, '@baz'] + alias_for_foo: '@foo' + another_alias_for_foo: + alias: foo + public: false + another_third_alias_for_foo: + alias: foo diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services9.yml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services9.yml index cf713d189e57e..2501ddcc1b5c9 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services9.yml +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services9.yml @@ -139,12 +139,6 @@ services: class: LazyContext arguments: [!iterator ['@foo.baz', '@?invalid'], !iterator []] public: true - alias_for_foo: - alias: 'foo' - public: true - alias_for_alias: - alias: 'foo' - public: true tagged_iterator_foo: class: Bar tags: @@ -161,3 +155,9 @@ services: Symfony\Component\DependencyInjection\ContainerInterface: alias: service_container public: false + alias_for_foo: + alias: 'foo' + public: true + alias_for_alias: + alias: 'foo' + public: true From 79978dba0511b8df48a5d63b44619548f6319a7c Mon Sep 17 00:00:00 2001 From: 243083df <243083df@dispostable.com> Date: Sun, 8 Oct 2017 02:59:09 +0400 Subject: [PATCH 1040/1099] Replace function chain to a single call. --- src/Symfony/Component/HttpFoundation/HeaderBag.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/HttpFoundation/HeaderBag.php b/src/Symfony/Component/HttpFoundation/HeaderBag.php index e0b51ad125609..d0789be295400 100644 --- a/src/Symfony/Component/HttpFoundation/HeaderBag.php +++ b/src/Symfony/Component/HttpFoundation/HeaderBag.php @@ -46,7 +46,7 @@ public function __toString() $max = max(array_map('strlen', array_keys($headers))) + 1; $content = ''; foreach ($headers as $name => $values) { - $name = implode('-', array_map('ucfirst', explode('-', $name))); + $name = ucwords($name, '-'); foreach ($values as $value) { $content .= sprintf("%-{$max}s %s\r\n", $name.':', $value); } From dca930f5792a3e69a4312d486454b5b1c246a033 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Sun, 8 Oct 2017 11:22:26 +0200 Subject: [PATCH 1041/1099] [DI] Remove colon from env placeholders --- .../ParameterBag/EnvPlaceholderParameterBag.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/DependencyInjection/ParameterBag/EnvPlaceholderParameterBag.php b/src/Symfony/Component/DependencyInjection/ParameterBag/EnvPlaceholderParameterBag.php index e0fe4c7cdfc57..ddc7e84fa636e 100644 --- a/src/Symfony/Component/DependencyInjection/ParameterBag/EnvPlaceholderParameterBag.php +++ b/src/Symfony/Component/DependencyInjection/ParameterBag/EnvPlaceholderParameterBag.php @@ -48,7 +48,7 @@ public function get($name) } $uniqueName = md5($name.uniqid(mt_rand(), true)); - $placeholder = sprintf('env_%s_%s', $env, $uniqueName); + $placeholder = sprintf('env_%s_%s', str_replace(':', '_', $env), $uniqueName); $this->envPlaceholders[$env][$placeholder] = $placeholder; return $placeholder; From 214105647180dd640a4c207afcaea670198848ef Mon Sep 17 00:00:00 2001 From: Samuel ROZE Date: Fri, 6 Oct 2017 09:50:51 +0100 Subject: [PATCH 1042/1099] Escape command usage when displaying it in the text descriptor --- src/Symfony/Component/Console/Descriptor/TextDescriptor.php | 2 +- src/Symfony/Component/Console/Tests/Fixtures/command_2.txt | 6 +++--- .../Component/Console/Tests/Fixtures/command_mbstring.txt | 6 +++--- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/Symfony/Component/Console/Descriptor/TextDescriptor.php b/src/Symfony/Component/Console/Descriptor/TextDescriptor.php index 5b82b3deefa8e..249eb9cb840aa 100644 --- a/src/Symfony/Component/Console/Descriptor/TextDescriptor.php +++ b/src/Symfony/Component/Console/Descriptor/TextDescriptor.php @@ -143,7 +143,7 @@ protected function describeCommand(Command $command, array $options = array()) $this->writeText('Usage:', $options); foreach (array_merge(array($command->getSynopsis(true)), $command->getAliases(), $command->getUsages()) as $usage) { $this->writeText("\n"); - $this->writeText(' '.$usage, $options); + $this->writeText(' '.OutputFormatter::escape($usage), $options); } $this->writeText("\n"); diff --git a/src/Symfony/Component/Console/Tests/Fixtures/command_2.txt b/src/Symfony/Component/Console/Tests/Fixtures/command_2.txt index cad9cb45f2c8b..2864c7bdc33ec 100644 --- a/src/Symfony/Component/Console/Tests/Fixtures/command_2.txt +++ b/src/Symfony/Component/Console/Tests/Fixtures/command_2.txt @@ -1,7 +1,7 @@ Usage: - descriptor:command2 [options] [--] - descriptor:command2 -o|--option_name - descriptor:command2 + descriptor:command2 [options] [--] \ + descriptor:command2 -o|--option_name \ + descriptor:command2 \ Arguments: argument_name diff --git a/src/Symfony/Component/Console/Tests/Fixtures/command_mbstring.txt b/src/Symfony/Component/Console/Tests/Fixtures/command_mbstring.txt index 969a0652420b2..cde457dcab863 100644 --- a/src/Symfony/Component/Console/Tests/Fixtures/command_mbstring.txt +++ b/src/Symfony/Component/Console/Tests/Fixtures/command_mbstring.txt @@ -1,7 +1,7 @@ Usage: - descriptor:åèä [options] [--] - descriptor:åèä -o|--option_name - descriptor:åèä + descriptor:åèä [options] [--] \ + descriptor:åèä -o|--option_name \ + descriptor:åèä \ Arguments: argument_åèä From 042eac4624f24b38edfa4d93c4e9e075a74cd3e9 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Fri, 6 Oct 2017 13:28:39 +0200 Subject: [PATCH 1043/1099] [Form] fix parsing invalid floating point numbers --- .../PercentToLocalizedStringTransformer.php | 33 ++++++++- ...ercentToLocalizedStringTransformerTest.php | 70 ++++++++++++++++++- 2 files changed, 98 insertions(+), 5 deletions(-) diff --git a/src/Symfony/Component/Form/Extension/Core/DataTransformer/PercentToLocalizedStringTransformer.php b/src/Symfony/Component/Form/Extension/Core/DataTransformer/PercentToLocalizedStringTransformer.php index ad8baeb7c9b25..fdb142f84e761 100644 --- a/src/Symfony/Component/Form/Extension/Core/DataTransformer/PercentToLocalizedStringTransformer.php +++ b/src/Symfony/Component/Form/Extension/Core/DataTransformer/PercentToLocalizedStringTransformer.php @@ -116,6 +116,7 @@ public function reverseTransform($value) return; } + $position = 0; $formatter = $this->getNumberFormatter(); $groupSep = $formatter->getSymbol(\NumberFormatter::GROUPING_SEPARATOR_SYMBOL); $decSep = $formatter->getSymbol(\NumberFormatter::DECIMAL_SEPARATOR_SYMBOL); @@ -129,18 +130,44 @@ public function reverseTransform($value) $value = str_replace(',', $decSep, $value); } + if (false !== strpos($value, $decSep)) { + $type = \NumberFormatter::TYPE_DOUBLE; + } else { + $type = \PHP_INT_SIZE === 8 ? \NumberFormatter::TYPE_INT64 : \NumberFormatter::TYPE_INT32; + } + // replace normal spaces so that the formatter can read them - $value = $formatter->parse(str_replace(' ', "\xc2\xa0", $value)); + $result = $formatter->parse(str_replace(' ', "\xc2\xa0", $value), $type, $position); if (intl_is_failure($formatter->getErrorCode())) { throw new TransformationFailedException($formatter->getErrorMessage()); } if (self::FRACTIONAL == $this->type) { - $value /= 100; + $result /= 100; } - return $value; + if (\function_exists('mb_detect_encoding') && false !== $encoding = mb_detect_encoding($value, null, true)) { + $length = mb_strlen($value, $encoding); + $remainder = mb_substr($value, $position, $length, $encoding); + } else { + $length = \strlen($value); + $remainder = substr($value, $position, $length); + } + + // After parsing, position holds the index of the character where the + // parsing stopped + if ($position < $length) { + // Check if there are unrecognized characters at the end of the + // number (excluding whitespace characters) + $remainder = trim($remainder, " \t\n\r\0\x0b\xc2\xa0"); + + if ('' !== $remainder) { + throw new TransformationFailedException(sprintf('The number contains unrecognized characters: "%s"', $remainder)); + } + } + + return $result; } /** diff --git a/src/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/PercentToLocalizedStringTransformerTest.php b/src/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/PercentToLocalizedStringTransformerTest.php index 24cef424d1c3e..3467e891c9bdd 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/PercentToLocalizedStringTransformerTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/PercentToLocalizedStringTransformerTest.php @@ -141,10 +141,10 @@ public function testDecimalSeparatorMayBeDotIfGroupingSeparatorIsNotDot() */ public function testDecimalSeparatorMayNotBeDotIfGroupingSeparatorIsDot() { - // Since we test against "de_AT", we need the full implementation + // Since we test against "de_DE", we need the full implementation IntlTestHelper::requireFullIntl($this, '4.8.1.1'); - \Locale::setDefault('de_AT'); + \Locale::setDefault('de_DE'); $transformer = new PercentToLocalizedStringTransformer(1, 'integer'); @@ -236,4 +236,70 @@ public function testDecimalSeparatorMayBeCommaIfGroupingSeparatorIsCommaButNoGro $this->assertEquals(1234.5, $transformer->reverseTransform('1234,5')); $this->assertEquals(1234.5, $transformer->reverseTransform('1234.5')); } + + /** + * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException + */ + public function testReverseTransformDisallowsLeadingExtraCharacters() + { + $transformer = new PercentToLocalizedStringTransformer(); + + $transformer->reverseTransform('foo123'); + } + + /** + * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException + * @expectedExceptionMessage The number contains unrecognized characters: "foo3" + */ + public function testReverseTransformDisallowsCenteredExtraCharacters() + { + $transformer = new PercentToLocalizedStringTransformer(); + + $transformer->reverseTransform('12foo3'); + } + + /** + * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException + * @expectedExceptionMessage The number contains unrecognized characters: "foo8" + * @requires extension mbstring + */ + public function testReverseTransformDisallowsCenteredExtraCharactersMultibyte() + { + // Since we test against other locales, we need the full implementation + IntlTestHelper::requireFullIntl($this, false); + + \Locale::setDefault('ru'); + + $transformer = new PercentToLocalizedStringTransformer(); + + $transformer->reverseTransform("12\xc2\xa0345,67foo8"); + } + + /** + * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException + * @expectedExceptionMessage The number contains unrecognized characters: "foo" + */ + public function testReverseTransformDisallowsTrailingExtraCharacters() + { + $transformer = new PercentToLocalizedStringTransformer(); + + $transformer->reverseTransform('123foo'); + } + + /** + * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException + * @expectedExceptionMessage The number contains unrecognized characters: "foo" + * @requires extension mbstring + */ + public function testReverseTransformDisallowsTrailingExtraCharactersMultibyte() + { + // Since we test against other locales, we need the full implementation + IntlTestHelper::requireFullIntl($this, false); + + \Locale::setDefault('ru'); + + $transformer = new PercentToLocalizedStringTransformer(); + + $transformer->reverseTransform("12\xc2\xa0345,678foo"); + } } From 427212d8699c067480da164682e8b1e49215c3fb Mon Sep 17 00:00:00 2001 From: Samuel ROZE Date: Sat, 7 Oct 2017 16:55:15 +0100 Subject: [PATCH 1044/1099] Clarify the exceptions are going to be rendered just after --- src/Symfony/Bundle/FrameworkBundle/Console/Application.php | 2 +- .../Bundle/FrameworkBundle/Tests/Console/ApplicationTest.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/Console/Application.php b/src/Symfony/Bundle/FrameworkBundle/Console/Application.php index d53ee24d1fa88..892bdf90fea59 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Console/Application.php +++ b/src/Symfony/Bundle/FrameworkBundle/Console/Application.php @@ -190,7 +190,7 @@ private function renderRegistrationErrors(InputInterface $input, OutputInterface $output = $output->getErrorOutput(); } - (new SymfonyStyle($input, $output))->warning('Some commands could not be registered.'); + (new SymfonyStyle($input, $output))->warning('Some commands could not be registered:'); foreach ($this->registrationErrors as $error) { $this->doRenderException($error, $output); diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Console/ApplicationTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Console/ApplicationTest.php index 9396b68212d9d..d06e98be77706 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Console/ApplicationTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Console/ApplicationTest.php @@ -160,7 +160,7 @@ public function testRunOnlyWarnsOnUnregistrableCommand() $output = $tester->getDisplay(); $this->assertSame(0, $tester->getStatusCode()); - $this->assertContains('Some commands could not be registered.', $output); + $this->assertContains('Some commands could not be registered:', $output); $this->assertContains('throwing', $output); $this->assertContains('fine', $output); } From 1f76a70b6f2cd597e922250b12cb8f89ca67d53b Mon Sep 17 00:00:00 2001 From: Christian Schmidt Date: Sun, 8 Oct 2017 16:27:20 +0200 Subject: [PATCH 1045/1099] [HttpFoundation] Combine Cache-Control headers --- src/Symfony/Component/HttpFoundation/HeaderBag.php | 2 +- .../HttpFoundation/Tests/ResponseHeaderBagTest.php | 11 +++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/HttpFoundation/HeaderBag.php b/src/Symfony/Component/HttpFoundation/HeaderBag.php index a824ed8649268..a797d7a2e68f7 100644 --- a/src/Symfony/Component/HttpFoundation/HeaderBag.php +++ b/src/Symfony/Component/HttpFoundation/HeaderBag.php @@ -146,7 +146,7 @@ public function set($key, $values, $replace = true) } if ('cache-control' === $key) { - $this->cacheControl = $this->parseCacheControl($values[0]); + $this->cacheControl = $this->parseCacheControl(implode(', ', $this->headers[$key])); } } diff --git a/src/Symfony/Component/HttpFoundation/Tests/ResponseHeaderBagTest.php b/src/Symfony/Component/HttpFoundation/Tests/ResponseHeaderBagTest.php index debcdc1faf16d..c55a7f6a51d40 100644 --- a/src/Symfony/Component/HttpFoundation/Tests/ResponseHeaderBagTest.php +++ b/src/Symfony/Component/HttpFoundation/Tests/ResponseHeaderBagTest.php @@ -110,6 +110,17 @@ public function testCacheControlHeader() $bag = new ResponseHeaderBag(); $bag->set('Last-Modified', 'abcde'); $this->assertEquals('private, must-revalidate', $bag->get('Cache-Control')); + + $bag = new ResponseHeaderBag(); + $bag->set('Cache-Control', array('public', 'must-revalidate')); + $this->assertCount(1, $bag->get('Cache-Control', null, false)); + $this->assertEquals('must-revalidate, public', $bag->get('Cache-Control')); + + $bag = new ResponseHeaderBag(); + $bag->set('Cache-Control', 'public'); + $bag->set('Cache-Control', 'must-revalidate', false); + $this->assertCount(1, $bag->get('Cache-Control', null, false)); + $this->assertEquals('must-revalidate, public', $bag->get('Cache-Control')); } public function testToStringIncludesCookieHeaders() From d90e7212ea359d57b904b5fbf22c9199ddc762d9 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Sun, 8 Oct 2017 16:29:36 +0200 Subject: [PATCH 1046/1099] [DI] Exclude inline services declared in XML from autowiring candidates --- .../DependencyInjection/Compiler/AutowirePass.php | 2 +- .../DependencyInjection/Loader/XmlFileLoader.php | 2 +- .../Tests/Compiler/AutowirePassTest.php | 14 ++++++++++++++ .../Fixtures/xml/services_inline_not_candidate.xml | 11 +++++++++++ 4 files changed, 27 insertions(+), 2 deletions(-) create mode 100644 src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services_inline_not_candidate.xml diff --git a/src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php b/src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php index b7bcb1309c1f9..98293a3198223 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/AutowirePass.php @@ -345,7 +345,7 @@ private function populateAvailableType($id, Definition $definition) unset($this->ambiguousServiceTypes[$type]); } - if ($definition->isDeprecated() || !$reflectionClass = $this->container->getReflectionClass($definition->getClass(), false)) { + if (preg_match('/^\d+_[^~]++~[._a-zA-Z\d]{7}$/', $id) || $definition->isDeprecated() || !$reflectionClass = $this->container->getReflectionClass($definition->getClass(), false)) { return; } diff --git a/src/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php b/src/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php index e5a43e391d20d..c5ff57e97a843 100644 --- a/src/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php +++ b/src/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php @@ -412,7 +412,7 @@ private function processAnonymousServices(\DOMDocument $xml, $file, $defaults) foreach ($nodes as $node) { if ($services = $this->getChildren($node, 'service')) { // give it a unique name - $id = sprintf('%d_%s', ++$count, preg_replace('/^.*\\\\/', '', $node->getAttribute('class')).$suffix); + $id = sprintf('%d_%s', ++$count, preg_replace('/^.*\\\\/', '', $services[0]->getAttribute('class')).'~'.$suffix); $node->setAttribute('id', $id); $node->setAttribute('service', $id); diff --git a/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowirePassTest.php b/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowirePassTest.php index 2c68eb3d4c94f..a4a1cdb9b2511 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowirePassTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Compiler/AutowirePassTest.php @@ -12,11 +12,13 @@ namespace Symfony\Component\DependencyInjection\Tests\Compiler; use PHPUnit\Framework\TestCase; +use Symfony\Component\Config\FileLocator; use Symfony\Component\DependencyInjection\Compiler\AutowireRequiredMethodsPass; use Symfony\Component\DependencyInjection\Compiler\AutowirePass; use Symfony\Component\DependencyInjection\Compiler\ResolveClassPass; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Exception\RuntimeException; +use Symfony\Component\DependencyInjection\Loader\XmlFileLoader; use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\DependencyInjection\Tests\Fixtures\includes\FooVariadic; use Symfony\Component\DependencyInjection\TypedReference; @@ -869,4 +871,16 @@ public function testExceptionWhenAliasDoesNotExist() $pass = new AutowirePass(); $pass->process($container); } + + public function testInlineServicesAreNotCandidates() + { + $container = new ContainerBuilder(); + $loader = new XmlFileLoader($container, new FileLocator(realpath(__DIR__.'/../Fixtures/xml'))); + $loader->load('services_inline_not_candidate.xml'); + + $pass = new AutowirePass(); + $pass->process($container); + + $this->assertSame(array(), $container->getDefinition('autowired')->getArguments()); + } } diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services_inline_not_candidate.xml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services_inline_not_candidate.xml new file mode 100644 index 0000000000000..72560585396af --- /dev/null +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services_inline_not_candidate.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + From dbc9a44333d34d9262c7f2cefa2c756fa1cc3da8 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Mon, 9 Oct 2017 11:21:24 +0200 Subject: [PATCH 1047/1099] [HttpFoundation] Add missing session.lazy_write config option --- .../HttpFoundation/Session/Storage/NativeSessionStorage.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.php b/src/Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.php index 5888323bd7c30..9bf438c159136 100644 --- a/src/Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.php +++ b/src/Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.php @@ -76,6 +76,7 @@ class NativeSessionStorage implements SessionStorageInterface * gc_probability, "1" * hash_bits_per_character, "4" * hash_function, "0" + * lazy_write, "1" * name, "PHPSESSID" * referer_check, "" * serialize_handler, "php" @@ -337,7 +338,7 @@ public function setOptions(array $options) 'cookie_lifetime', 'cookie_path', 'cookie_secure', 'entropy_file', 'entropy_length', 'gc_divisor', 'gc_maxlifetime', 'gc_probability', 'hash_bits_per_character', - 'hash_function', 'name', 'referer_check', + 'hash_function', 'lazy_write', 'name', 'referer_check', 'serialize_handler', 'use_strict_mode', 'use_cookies', 'use_only_cookies', 'use_trans_sid', 'upload_progress.enabled', 'upload_progress.cleanup', 'upload_progress.prefix', 'upload_progress.name', From f09f0ae7bafcc6bb0af2ca67adf2d6439e1bdf72 Mon Sep 17 00:00:00 2001 From: 243083df <243083df@dispostable.com> Date: Mon, 9 Oct 2017 13:31:38 +0400 Subject: [PATCH 1048/1099] Remove unnecessary condition; --- src/Symfony/Component/HttpKernel/HttpKernel.php | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/Symfony/Component/HttpKernel/HttpKernel.php b/src/Symfony/Component/HttpKernel/HttpKernel.php index 394147fc3fdc5..0ea5bf376c4d2 100644 --- a/src/Symfony/Component/HttpKernel/HttpKernel.php +++ b/src/Symfony/Component/HttpKernel/HttpKernel.php @@ -157,9 +157,7 @@ private function handleRaw(Request $request, int $type = self::MASTER_REQUEST) if ($event->hasResponse()) { $response = $event->getResponse(); - } - - if (!$response instanceof Response) { + } else { $msg = sprintf('The controller must return a response (%s given).', $this->varToString($response)); // the user may have forgotten to return something From e229dd03021b35c4288f01a72f1955218e68abc8 Mon Sep 17 00:00:00 2001 From: Amrouche Hamza Date: Sat, 29 Jul 2017 11:14:02 +0200 Subject: [PATCH 1049/1099] Fix PHP 7.2 support --- .github/build-packages.php | 1 - .travis.yml | 8 ++-- .../LegacyDefaultCsrfProviderTest.php | 6 ++- .../Session/Storage/NativeSessionStorage.php | 18 ++++++--- .../Storage/Handler/PdoSessionHandlerTest.php | 38 +++++++++++++++++++ .../Storage/NativeSessionStorageTest.php | 2 +- .../EventListener/LocaleListenerTest.php | 6 ++- .../EventListener/TestSessionListenerTest.php | 2 +- .../NativeSessionTokenStorageTest.php | 6 ++- 9 files changed, 69 insertions(+), 18 deletions(-) diff --git a/.github/build-packages.php b/.github/build-packages.php index 56112b753ad32..3d186e927c097 100644 --- a/.github/build-packages.php +++ b/.github/build-packages.php @@ -9,7 +9,6 @@ $dirs = $_SERVER['argv']; array_shift($dirs); $mergeBase = trim(shell_exec(sprintf('git merge-base %s HEAD', array_shift($dirs)))); - $packages = array(); $flags = \PHP_VERSION_ID >= 50400 ? JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE : 0; diff --git a/.travis.yml b/.travis.yml index e01ab63ab3227..8409baaf05cc4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -27,7 +27,7 @@ matrix: - php: 7.0 env: deps=high - php: 7.1 - env: deps=low + - php: 7.2 fast_finish: true cache: @@ -137,7 +137,7 @@ install: export SYMFONY_DEPRECATIONS_HELPER=weak && cp composer.json composer.json.orig && echo -e '{\n"require":{'"$(grep phpunit-bridge composer.json)"'"php":"*"},"minimum-stability":"dev"}' > composer.json && - php .github/build-packages.php HEAD^ $COMPONENTS && + (php .github/build-packages.php HEAD^ $COMPONENTS) && mv composer.json composer.json.phpunit && mv composer.json.orig composer.json fi @@ -176,9 +176,9 @@ install: if [[ $skip ]]; then echo -e "\\n\\e[1;34mIntermediate PHP version $PHP is skipped for pull requests.\\e[0m" elif [[ $deps = high ]]; then - echo "$COMPONENTS" | parallel --gnu -j10% "tfold {} 'cd {} && $COMPOSER_UP && $PHPUNIT_X$LEGACY'" + echo "$COMPONENTS" | parallel --gnu -j10% "tfold {} 'cd {} && ($COMPOSER_UP) && $PHPUNIT_X$LEGACY'" elif [[ $deps = low ]]; then - echo "$COMPONENTS" | parallel --gnu -j10% "tfold {} 'cd {} && $COMPOSER_UP --prefer-lowest --prefer-stable && $PHPUNIT_X'" + echo "$COMPONENTS" | parallel --gnu -j10% "tfold {} 'cd {} && ($COMPOSER_UP --prefer-lowest --prefer-stable) && $PHPUNIT_X'" elif [[ $PHP = hhvm* ]]; then $PHPUNIT --exclude-group benchmark,intl-data else diff --git a/src/Symfony/Component/Form/Tests/Extension/Csrf/CsrfProvider/LegacyDefaultCsrfProviderTest.php b/src/Symfony/Component/Form/Tests/Extension/Csrf/CsrfProvider/LegacyDefaultCsrfProviderTest.php index 824e81c553032..c22bd46a7bdf7 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Csrf/CsrfProvider/LegacyDefaultCsrfProviderTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Csrf/CsrfProvider/LegacyDefaultCsrfProviderTest.php @@ -25,8 +25,10 @@ class LegacyDefaultCsrfProviderTest extends TestCase public static function setUpBeforeClass() { - ini_set('session.save_handler', 'files'); - ini_set('session.save_path', sys_get_temp_dir()); + if (\PHP_VERSION_ID < 70200) { + ini_set('session.save_handler', 'files'); + ini_set('session.save_path', sys_get_temp_dir()); + } } protected function setUp() diff --git a/src/Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.php b/src/Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.php index 5888323bd7c30..1ee6d3f34e531 100644 --- a/src/Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.php +++ b/src/Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.php @@ -101,8 +101,12 @@ class NativeSessionStorage implements SessionStorageInterface */ public function __construct(array $options = array(), $handler = null, MetadataBag $metaBag = null) { - session_cache_limiter(''); // disable by default because it's managed by HeaderBag (if used) - ini_set('session.use_cookies', 1); + if (empty($options)) { + $options += array('cache_limiter' => 'public'); + } + if (1 !== (int) ini_get('session.use_cookies')) { + ini_set('session.use_cookies', 1); + } if (\PHP_VERSION_ID >= 50400) { session_register_shutdown(); @@ -345,9 +349,11 @@ public function setOptions(array $options) 'sid_length', 'sid_bits_per_character', 'trans_sid_hosts', 'trans_sid_tags', )); - foreach ($options as $key => $value) { - if (isset($validOptions[$key])) { - ini_set('session.'.$key, $value); + if (PHP_VERSION_ID < 70200 || !headers_sent()) { + foreach ($options as $key => $value) { + if (isset($validOptions[$key])) { + ini_set('session.'.$key, $value); + } } } } @@ -392,7 +398,7 @@ public function setSaveHandler($saveHandler = null) } $this->saveHandler = $saveHandler; - if ($this->saveHandler instanceof \SessionHandlerInterface) { + if ($this->saveHandler instanceof \SessionHandlerInterface && false === headers_sent()) { if (\PHP_VERSION_ID >= 50400) { session_set_save_handler($this->saveHandler, false); } else { diff --git a/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/PdoSessionHandlerTest.php b/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/PdoSessionHandlerTest.php index a47120f1807e2..88509b11b95d7 100644 --- a/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/PdoSessionHandlerTest.php +++ b/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/PdoSessionHandlerTest.php @@ -271,6 +271,10 @@ public function testSessionDestroy() public function testSessionGC() { + if (\PHP_VERSION_ID >= 70200) { + $this->markTestSkipped('PHP version is 7.2'); + } + $previousLifeTime = ini_set('session.gc_maxlifetime', 1000); $pdo = $this->getMemorySqlitePdo(); $storage = new PdoSessionHandler($pdo); @@ -282,10 +286,12 @@ public function testSessionGC() $storage->open('', 'sid'); $storage->read('gc_id'); + // IN 7.2 this does not work ini_set('session.gc_maxlifetime', -1); // test that you can set lifetime of a session after it has been read $storage->write('gc_id', 'data'); $storage->close(); $this->assertEquals(2, $pdo->query('SELECT COUNT(*) FROM sessions')->fetchColumn(), 'No session pruned because gc not called'); + $storage->destroy('gc_id'); $storage->open('', 'sid'); $data = $storage->read('gc_id'); @@ -293,7 +299,39 @@ public function testSessionGC() $storage->close(); ini_set('session.gc_maxlifetime', $previousLifeTime); + $this->assertSame('', $data, 'Session already considered garbage, so not returning data even if it is not pruned yet'); + $this->assertEquals(1, $pdo->query('SELECT COUNT(*) FROM sessions')->fetchColumn(), 'Expired session is pruned'); + } + + public function testSessionGC72() + { + if (\PHP_VERSION_ID <= 70200) { + $this->markTestSkipped('PHP version is not 7.2'); + } + + $previousLifeTime = false === headers_sent() && ini_set('session.gc_maxlifetime', 1000); + $pdo = $this->getMemorySqlitePdo(); + $storage = new PdoSessionHandler($pdo); + + $storage->open('', 'sid'); + $storage->read('id'); + $storage->write('id', 'data'); + $storage->close(); + + $storage->open('', 'sid'); + $storage->read('gc_id'); + false === headers_sent() && ini_set('session.gc_maxlifetime', -1); // test that you can set lifetime of a session after it has been read + $storage->write('gc_id', 'data'); + $storage->close(); + $this->assertEquals(2, $pdo->query('SELECT COUNT(*) FROM sessions')->fetchColumn(), 'No session pruned because gc not called'); + true === headers_sent() && $storage->destroy('gc_id'); + + $storage->open('', 'sid'); + $data = $storage->read('gc_id'); + $storage->gc(-1); + $storage->close(); + false === headers_sent() && ini_set('session.gc_maxlifetime', $previousLifeTime); $this->assertSame('', $data, 'Session already considered garbage, so not returning data even if it is not pruned yet'); $this->assertEquals(1, $pdo->query('SELECT COUNT(*) FROM sessions')->fetchColumn(), 'Expired session is pruned'); } diff --git a/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/NativeSessionStorageTest.php b/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/NativeSessionStorageTest.php index 20f9ca060bc3c..d5281c644d003 100644 --- a/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/NativeSessionStorageTest.php +++ b/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/NativeSessionStorageTest.php @@ -152,7 +152,7 @@ public function testDefaultSessionCacheLimiter() { $this->iniSet('session.cache_limiter', 'nocache'); - $storage = new NativeSessionStorage(); + $storage = new NativeSessionStorage(array('cache_limiter' => '')); $this->assertEquals('', ini_get('session.cache_limiter')); } diff --git a/src/Symfony/Component/HttpKernel/Tests/EventListener/LocaleListenerTest.php b/src/Symfony/Component/HttpKernel/Tests/EventListener/LocaleListenerTest.php index b6977ea88b6de..24f9038f35ed5 100644 --- a/src/Symfony/Component/HttpKernel/Tests/EventListener/LocaleListenerTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/EventListener/LocaleListenerTest.php @@ -38,7 +38,11 @@ public function testDefaultLocaleWithoutSession() public function testLocaleFromRequestAttribute() { $request = Request::create('/'); - session_name('foo'); + + if (PHP_VERSION_ID < 70200 || !headers_sent()) { + session_name('foo'); + } + $request->cookies->set('foo', 'value'); $request->attributes->set('_locale', 'es'); diff --git a/src/Symfony/Component/HttpKernel/Tests/EventListener/TestSessionListenerTest.php b/src/Symfony/Component/HttpKernel/Tests/EventListener/TestSessionListenerTest.php index 52794e0272832..63d5338182854 100644 --- a/src/Symfony/Component/HttpKernel/Tests/EventListener/TestSessionListenerTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/EventListener/TestSessionListenerTest.php @@ -63,7 +63,7 @@ public function testDoesNotDeleteCookieIfUsingSessionLifetime() $this->sessionHasBeenStarted(); $params = session_get_cookie_params(); - session_set_cookie_params(0, $params['path'], $params['domain'], $params['secure'], $params['httponly']); + // session_set_cookie_params(0, $params['path'], $params['domain'], $params['secure'], $params['httponly']); $response = $this->filterResponse(new Request(), HttpKernelInterface::MASTER_REQUEST); $cookies = $response->headers->getCookies(); diff --git a/src/Symfony/Component/Security/Csrf/Tests/TokenStorage/NativeSessionTokenStorageTest.php b/src/Symfony/Component/Security/Csrf/Tests/TokenStorage/NativeSessionTokenStorageTest.php index ea20cff5291ff..869f14f82ec76 100644 --- a/src/Symfony/Component/Security/Csrf/Tests/TokenStorage/NativeSessionTokenStorageTest.php +++ b/src/Symfony/Component/Security/Csrf/Tests/TokenStorage/NativeSessionTokenStorageTest.php @@ -31,8 +31,10 @@ class NativeSessionTokenStorageTest extends TestCase public static function setUpBeforeClass() { - ini_set('session.save_handler', 'files'); - ini_set('session.save_path', sys_get_temp_dir()); + if (\PHP_VERSION_ID < 70200) { + ini_set('session.save_handler', 'files'); + ini_set('session.save_path', sys_get_temp_dir()); + } parent::setUpBeforeClass(); } From e07c2f17b6bfc749f02f16895531557603cb22ca Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Mon, 9 Oct 2017 16:32:35 +0200 Subject: [PATCH 1050/1099] [Bridge\PhpUnit] Fix infinite loop when running isolated method --- src/Symfony/Bridge/PhpUnit/bin/simple-phpunit | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/Symfony/Bridge/PhpUnit/bin/simple-phpunit b/src/Symfony/Bridge/PhpUnit/bin/simple-phpunit index 869e8dc0d52b5..56aed0cb58b14 100755 --- a/src/Symfony/Bridge/PhpUnit/bin/simple-phpunit +++ b/src/Symfony/Bridge/PhpUnit/bin/simple-phpunit @@ -81,6 +81,11 @@ if (!file_exists("$PHPUNIT_DIR/phpunit-$PHPUNIT_VERSION/phpunit") || md5_file(__ define('PHPUNIT_COMPOSER_INSTALL', __DIR__.'/vendor/autoload.php'); require PHPUNIT_COMPOSER_INSTALL; +if (class_exists('PHPUnit_Util_Blacklist')) { + PHPUnit_Util_Blacklist::$blacklistedClassNames['\PHPUnit\Framework\TestCase'] = 3; +} else { + PHPUnit\Util\Blacklist::$blacklistedClassNames['\PHPUnit\Framework\TestCase'] = 3; +} Symfony\Bridge\PhpUnit\TextUI\Command::main(); EOPHP From 9d9d596524e5fed6fb75adfab1bb275dffca2074 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Mon, 9 Oct 2017 17:25:01 +0200 Subject: [PATCH 1051/1099] [Bridge\PhpUnit] Fix infinite loop when running isolated method (bis) --- src/Symfony/Bridge/PhpUnit/bin/simple-phpunit | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Bridge/PhpUnit/bin/simple-phpunit b/src/Symfony/Bridge/PhpUnit/bin/simple-phpunit index 56aed0cb58b14..beba0450aa4cd 100755 --- a/src/Symfony/Bridge/PhpUnit/bin/simple-phpunit +++ b/src/Symfony/Bridge/PhpUnit/bin/simple-phpunit @@ -81,11 +81,18 @@ if (!file_exists("$PHPUNIT_DIR/phpunit-$PHPUNIT_VERSION/phpunit") || md5_file(__ define('PHPUNIT_COMPOSER_INSTALL', __DIR__.'/vendor/autoload.php'); require PHPUNIT_COMPOSER_INSTALL; + +if (!class_exists('SymfonyBlacklistPhpunit', false)) { + class SymfonyBlacklistPhpunit {} +} if (class_exists('PHPUnit_Util_Blacklist')) { - PHPUnit_Util_Blacklist::$blacklistedClassNames['\PHPUnit\Framework\TestCase'] = 3; + PHPUnit_Util_Blacklist::$blacklistedClassNames['SymfonyBlacklistPhpunit'] = 1; + PHPUnit_Util_Blacklist::$blacklistedClassNames['SymfonyBlacklistSimplePhpunit'] = 1; } else { - PHPUnit\Util\Blacklist::$blacklistedClassNames['\PHPUnit\Framework\TestCase'] = 3; + PHPUnit\Util\Blacklist::$blacklistedClassNames['SymfonyBlacklistPhpunit'] = 1; + PHPUnit\Util\Blacklist::$blacklistedClassNames['SymfonyBlacklistSimplePhpunit'] = 1; } + Symfony\Bridge\PhpUnit\TextUI\Command::main(); EOPHP @@ -204,6 +211,9 @@ if ($components) { } } } elseif (!isset($argv[1]) || 'install' !== $argv[1] || file_exists('install')) { + if (!class_exists('SymfonyBlacklistSimplePhpunit', false)) { + class SymfonyBlacklistSimplePhpunit {} + } array_splice($argv, 1, 0, array('--colors=always')); $_SERVER['argv'] = $argv; $_SERVER['argc'] = ++$argc; From 9b6b3c0304965e31faee3d75dffd45034cf6700a Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Mon, 9 Oct 2017 17:28:48 +0200 Subject: [PATCH 1052/1099] bug #24499 [Bridge\PhpUnit] Fix infinite loop when running isolated method (bis) (nicolas-grekas) This PR was merged into the 4.0-dev branch. Discussion ---------- [Bridge\PhpUnit] Fix infinite loop when running isolated method (bis) | Q | A | ------------- | --- | Branch? | 3.3 | Bug fix? | yes | New feature? | no | BC breaks? | no | Deprecations? | no | Tests pass? | yes | Fixed tickets | - | License | MIT | Doc PR | - The blacklisting system is a bit rigid, so let's work around it. Commits ------- 9d9d596 [Bridge\PhpUnit] Fix infinite loop when running isolated method (bis) --- src/Symfony/Bridge/PhpUnit/bin/simple-phpunit | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Bridge/PhpUnit/bin/simple-phpunit b/src/Symfony/Bridge/PhpUnit/bin/simple-phpunit index 56aed0cb58b14..beba0450aa4cd 100755 --- a/src/Symfony/Bridge/PhpUnit/bin/simple-phpunit +++ b/src/Symfony/Bridge/PhpUnit/bin/simple-phpunit @@ -81,11 +81,18 @@ if (!file_exists("$PHPUNIT_DIR/phpunit-$PHPUNIT_VERSION/phpunit") || md5_file(__ define('PHPUNIT_COMPOSER_INSTALL', __DIR__.'/vendor/autoload.php'); require PHPUNIT_COMPOSER_INSTALL; + +if (!class_exists('SymfonyBlacklistPhpunit', false)) { + class SymfonyBlacklistPhpunit {} +} if (class_exists('PHPUnit_Util_Blacklist')) { - PHPUnit_Util_Blacklist::$blacklistedClassNames['\PHPUnit\Framework\TestCase'] = 3; + PHPUnit_Util_Blacklist::$blacklistedClassNames['SymfonyBlacklistPhpunit'] = 1; + PHPUnit_Util_Blacklist::$blacklistedClassNames['SymfonyBlacklistSimplePhpunit'] = 1; } else { - PHPUnit\Util\Blacklist::$blacklistedClassNames['\PHPUnit\Framework\TestCase'] = 3; + PHPUnit\Util\Blacklist::$blacklistedClassNames['SymfonyBlacklistPhpunit'] = 1; + PHPUnit\Util\Blacklist::$blacklistedClassNames['SymfonyBlacklistSimplePhpunit'] = 1; } + Symfony\Bridge\PhpUnit\TextUI\Command::main(); EOPHP @@ -204,6 +211,9 @@ if ($components) { } } } elseif (!isset($argv[1]) || 'install' !== $argv[1] || file_exists('install')) { + if (!class_exists('SymfonyBlacklistSimplePhpunit', false)) { + class SymfonyBlacklistSimplePhpunit {} + } array_splice($argv, 1, 0, array('--colors=always')); $_SERVER['argv'] = $argv; $_SERVER['argc'] = ++$argc; From 91c9287c556ffe43e890c55ef2e030f940e67d00 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Sun, 8 Oct 2017 15:44:15 +0200 Subject: [PATCH 1053/1099] [DI] Prefixed env vars and load time inlining are incompatible --- .../MergeExtensionConfigurationPass.php | 27 +++++++++++++++++++ .../Compiler/RegisterEnvVarProcessorsPass.php | 18 ++++++------- .../MergeExtensionConfigurationPassTest.php | 21 +++++++++++++++ 3 files changed, 56 insertions(+), 10 deletions(-) diff --git a/src/Symfony/Component/DependencyInjection/Compiler/MergeExtensionConfigurationPass.php b/src/Symfony/Component/DependencyInjection/Compiler/MergeExtensionConfigurationPass.php index af3a6baf0b898..1518952d7a7ee 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/MergeExtensionConfigurationPass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/MergeExtensionConfigurationPass.php @@ -13,6 +13,7 @@ use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Exception\LogicException; +use Symfony\Component\DependencyInjection\Exception\RuntimeException; use Symfony\Component\DependencyInjection\Extension\ConfigurationExtensionInterface; use Symfony\Component\DependencyInjection\Extension\Extension; use Symfony\Component\DependencyInjection\Extension\ExtensionInterface; @@ -164,4 +165,30 @@ public function compile($resolveEnvPlaceholders = false) { throw new LogicException(sprintf('Cannot compile the container in extension "%s".', $this->extensionClass)); } + + /** + * {@inheritdoc} + */ + public function resolveEnvPlaceholders($value, $format = null, array &$usedEnvs = null) + { + if (true !== $format || !\is_string($value)) { + return parent::resolveEnvPlaceholders($value, $format, $usedEnvs); + } + + $bag = $this->getParameterBag(); + $value = $bag->resolveValue($value); + + foreach ($bag->getEnvPlaceholders() as $env => $placeholders) { + if (false === strpos($env, ':')) { + continue; + } + foreach ($placeholders as $placeholder) { + if (false !== stripos($value, $placeholder)) { + throw new RuntimeException(sprintf('Using a cast in "env(%s)" is incompatible with resolution at compile time in "%s". The logic in the extension should be moved to a compiler pass, or an env parameter with no cast should be used instead.', $env, $this->extensionClass)); + } + } + } + + return parent::resolveEnvPlaceholders($value, $format, $usedEnvs); + } } diff --git a/src/Symfony/Component/DependencyInjection/Compiler/RegisterEnvVarProcessorsPass.php b/src/Symfony/Component/DependencyInjection/Compiler/RegisterEnvVarProcessorsPass.php index 68f2f9a41c134..38349f06569a6 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/RegisterEnvVarProcessorsPass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/RegisterEnvVarProcessorsPass.php @@ -34,16 +34,14 @@ public function process(ContainerBuilder $container) $types = array(); $processors = array(); foreach ($container->findTaggedServiceIds('container.env_var_processor') as $id => $tags) { - foreach ($tags as $attr) { - if (!$r = $container->getReflectionClass($class = $container->getDefinition($id)->getClass())) { - throw new InvalidArgumentException(sprintf('Class "%s" used for service "%s" cannot be found.', $class, $id)); - } elseif (!$r->isSubclassOf(EnvVarProcessorInterface::class)) { - throw new InvalidArgumentException(sprintf('Service "%s" must implement interface "%s".', $id, EnvVarProcessorInterface::class)); - } - foreach ($class::getProvidedTypes() as $prefix => $type) { - $processors[$prefix] = new ServiceClosureArgument(new Reference($id)); - $types[$prefix] = self::validateProvidedTypes($type, $class); - } + if (!$r = $container->getReflectionClass($class = $container->getDefinition($id)->getClass())) { + throw new InvalidArgumentException(sprintf('Class "%s" used for service "%s" cannot be found.', $class, $id)); + } elseif (!$r->isSubclassOf(EnvVarProcessorInterface::class)) { + throw new InvalidArgumentException(sprintf('Service "%s" must implement interface "%s".', $id, EnvVarProcessorInterface::class)); + } + foreach ($class::getProvidedTypes() as $prefix => $type) { + $processors[$prefix] = new ServiceClosureArgument(new Reference($id)); + $types[$prefix] = self::validateProvidedTypes($type, $class); } } diff --git a/src/Symfony/Component/DependencyInjection/Tests/Compiler/MergeExtensionConfigurationPassTest.php b/src/Symfony/Component/DependencyInjection/Tests/Compiler/MergeExtensionConfigurationPassTest.php index 57bb634f4bff0..b64aa7778cbe8 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Compiler/MergeExtensionConfigurationPassTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Compiler/MergeExtensionConfigurationPassTest.php @@ -101,6 +101,19 @@ public function testOverriddenEnvsAreMerged() $this->assertSame(array('BAZ', 'FOO'), array_keys($container->getParameterBag()->getEnvPlaceholders())); $this->assertSame(array('BAZ' => 1, 'FOO' => 0), $container->getEnvCounters()); } + + /** + * @expectedException \Symfony\Component\DependencyInjection\Exception\RuntimeException + * @expectedExceptionMessage Using a cast in "env(int:FOO)" is incompatible with resolution at compile time in "Symfony\Component\DependencyInjection\Tests\Compiler\BarExtension". The logic in the extension should be moved to a compiler pass, or an env parameter with no cast should be used instead. + */ + public function testProcessedEnvsAreIncompatibleWithResolve() + { + $container = new ContainerBuilder(); + $container->registerExtension(new BarExtension()); + $container->prependExtensionConfig('bar', array()); + + (new MergeExtensionConfigurationPass())->process($container); + } } class FooConfiguration implements ConfigurationInterface @@ -142,3 +155,11 @@ public function load(array $configs, ContainerBuilder $container) } } } + +class BarExtension extends Extension +{ + public function load(array $configs, ContainerBuilder $container) + { + $container->resolveEnvPlaceholders('%env(int:FOO)%', true); + } +} From fdf285b5c9a85b2cbd9d569ed1682bf7f12e014a Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Mon, 9 Oct 2017 12:39:15 +0200 Subject: [PATCH 1054/1099] Fix 7.2 compat layer --- .github/build-packages.php | 1 + .travis.yml | 9 ++-- .../Bridge/Twig/Tests/AppVariableTest.php | 3 ++ src/Symfony/Bridge/Twig/composer.json | 1 + .../CacheClearCommandTest.php | 2 +- .../Tests/Controller/ControllerTest.php | 3 ++ .../Bundle/FrameworkBundle/composer.json | 2 +- .../Debug/Tests/ErrorHandlerTest.php | 4 +- .../Debug/Tests/Fixtures/Throwing.php | 4 +- .../Tests/Loader/XmlFileLoaderTest.php | 3 ++ .../LegacyDefaultCsrfProviderTest.php | 8 ---- .../Session/Storage/NativeSessionStorage.php | 33 +++++++++------ .../Storage/Handler/PdoSessionHandlerTest.php | 41 ++----------------- .../Storage/NativeSessionStorageTest.php | 2 +- .../EventListener/LocaleListenerTest.php | 7 +--- .../EventListener/TestSessionListenerTest.php | 3 +- .../Component/HttpKernel/composer.json | 2 +- .../Routing/Tests/Fixtures/validresource.php | 3 ++ .../NativeSessionTokenStorageTest.php | 10 ----- 19 files changed, 55 insertions(+), 86 deletions(-) diff --git a/.github/build-packages.php b/.github/build-packages.php index 3d186e927c097..56112b753ad32 100644 --- a/.github/build-packages.php +++ b/.github/build-packages.php @@ -9,6 +9,7 @@ $dirs = $_SERVER['argv']; array_shift($dirs); $mergeBase = trim(shell_exec(sprintf('git merge-base %s HEAD', array_shift($dirs)))); + $packages = array(); $flags = \PHP_VERSION_ID >= 50400 ? JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE : 0; diff --git a/.travis.yml b/.travis.yml index 8409baaf05cc4..e34ba5a8bcaaf 100644 --- a/.travis.yml +++ b/.travis.yml @@ -25,9 +25,10 @@ matrix: - php: 5.5 - php: 5.6 - php: 7.0 - env: deps=high - php: 7.1 + env: deps=high - php: 7.2 + env: deps=low fast_finish: true cache: @@ -137,7 +138,7 @@ install: export SYMFONY_DEPRECATIONS_HELPER=weak && cp composer.json composer.json.orig && echo -e '{\n"require":{'"$(grep phpunit-bridge composer.json)"'"php":"*"},"minimum-stability":"dev"}' > composer.json && - (php .github/build-packages.php HEAD^ $COMPONENTS) && + php .github/build-packages.php HEAD^ $COMPONENTS && mv composer.json composer.json.phpunit && mv composer.json.orig composer.json fi @@ -176,9 +177,9 @@ install: if [[ $skip ]]; then echo -e "\\n\\e[1;34mIntermediate PHP version $PHP is skipped for pull requests.\\e[0m" elif [[ $deps = high ]]; then - echo "$COMPONENTS" | parallel --gnu -j10% "tfold {} 'cd {} && ($COMPOSER_UP) && $PHPUNIT_X$LEGACY'" + echo "$COMPONENTS" | parallel --gnu -j10% "tfold {} 'cd {} && $COMPOSER_UP && $PHPUNIT_X$LEGACY'" elif [[ $deps = low ]]; then - echo "$COMPONENTS" | parallel --gnu -j10% "tfold {} 'cd {} && ($COMPOSER_UP --prefer-lowest --prefer-stable) && $PHPUNIT_X'" + echo "$COMPONENTS" | parallel --gnu -j10% "tfold {} 'cd {} && $COMPOSER_UP --prefer-lowest --prefer-stable && $PHPUNIT_X'" elif [[ $PHP = hhvm* ]]; then $PHPUNIT --exclude-group benchmark,intl-data else diff --git a/src/Symfony/Bridge/Twig/Tests/AppVariableTest.php b/src/Symfony/Bridge/Twig/Tests/AppVariableTest.php index 9abb0e3b6ea78..b9aa168fd763d 100644 --- a/src/Symfony/Bridge/Twig/Tests/AppVariableTest.php +++ b/src/Symfony/Bridge/Twig/Tests/AppVariableTest.php @@ -44,6 +44,9 @@ public function testEnvironment() $this->assertEquals('dev', $this->appVariable->getEnvironment()); } + /** + * @runInSeparateProcess + */ public function testGetSession() { $request = $this->getMockBuilder('Symfony\Component\HttpFoundation\Request')->getMock(); diff --git a/src/Symfony/Bridge/Twig/composer.json b/src/Symfony/Bridge/Twig/composer.json index 9610edc8085b5..04e3819176844 100644 --- a/src/Symfony/Bridge/Twig/composer.json +++ b/src/Symfony/Bridge/Twig/composer.json @@ -23,6 +23,7 @@ "symfony/asset": "~2.7", "symfony/finder": "~2.3", "symfony/form": "~2.7.30|^2.8.23", + "symfony/http-foundation": "~2.7.36|^2.8.29", "symfony/http-kernel": "~2.3", "symfony/intl": "~2.3", "symfony/routing": "~2.2", diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/CacheClearCommand/CacheClearCommandTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/CacheClearCommand/CacheClearCommandTest.php index f1140e86bb378..a25aa8e637e44 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/CacheClearCommand/CacheClearCommandTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/CacheClearCommand/CacheClearCommandTest.php @@ -55,7 +55,7 @@ public function testCacheIsFreshAfterCacheClearedWithWarmup() $finder = new Finder(); $metaFiles = $finder->files()->in($this->kernel->getCacheDir())->name('*.php.meta'); // simply check that cache is warmed up - $this->assertGreaterThanOrEqual(1, count($metaFiles)); + $this->assertNotEmpty($metaFiles); foreach ($metaFiles as $file) { $configCache = new ConfigCache(substr($file, 0, -5), true); $this->assertTrue( diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/ControllerTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/ControllerTest.php index d7f40a24d8b4a..cb813c61d62ac 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/ControllerTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Controller/ControllerTest.php @@ -143,6 +143,9 @@ public function testRedirectToRoute() $this->assertSame(302, $response->getStatusCode()); } + /** + * @runInSeparateProcess + */ public function testAddFlash() { $flashBag = new FlashBag(); diff --git a/src/Symfony/Bundle/FrameworkBundle/composer.json b/src/Symfony/Bundle/FrameworkBundle/composer.json index 76648774f3baa..ed611114fe2aa 100644 --- a/src/Symfony/Bundle/FrameworkBundle/composer.json +++ b/src/Symfony/Bundle/FrameworkBundle/composer.json @@ -23,7 +23,7 @@ "symfony/config": "~2.4", "symfony/event-dispatcher": "~2.5", "symfony/finder": "^2.0.5", - "symfony/http-foundation": "~2.7", + "symfony/http-foundation": "~2.7.36|^2.8.29", "symfony/http-kernel": "~2.7.29|^2.8.22", "symfony/filesystem": "~2.3", "symfony/routing": "~2.7.24|^2.8.17", diff --git a/src/Symfony/Component/Debug/Tests/ErrorHandlerTest.php b/src/Symfony/Component/Debug/Tests/ErrorHandlerTest.php index 898a985a29e2f..fd9ac577ee73a 100644 --- a/src/Symfony/Component/Debug/Tests/ErrorHandlerTest.php +++ b/src/Symfony/Component/Debug/Tests/ErrorHandlerTest.php @@ -79,7 +79,9 @@ public function testNotice() $this->assertEquals(E_NOTICE, $exception->getSeverity()); $this->assertEquals(__FILE__, $exception->getFile()); $this->assertRegExp('/^Notice: Undefined variable: (foo|bar)/', $exception->getMessage()); - $this->assertArrayHasKey('foobar', $exception->getContext()); + if (\PHP_VERSION_ID < 70200) { + $this->assertArrayHasKey('foobar', $exception->getContext()); + } $trace = $exception->getTrace(); $this->assertEquals(__FILE__, $trace[0]['file']); diff --git a/src/Symfony/Component/Debug/Tests/Fixtures/Throwing.php b/src/Symfony/Component/Debug/Tests/Fixtures/Throwing.php index 21e0aba17d358..d338ca9d5752b 100644 --- a/src/Symfony/Component/Debug/Tests/Fixtures/Throwing.php +++ b/src/Symfony/Component/Debug/Tests/Fixtures/Throwing.php @@ -1,3 +1,5 @@ markTestSkipped('To run this test, add "phar" to the "suhosin.executor.include.whitelist" settings in your php.ini file.'); } + if (defined('HHVM_VERSION')) { + $this->markTestSkipped('HHVM makes this test conflict with those run in separate processes.'); + } require_once self::$fixturesPath.'/includes/ProjectWithXsdExtensionInPhar.phar'; diff --git a/src/Symfony/Component/Form/Tests/Extension/Csrf/CsrfProvider/LegacyDefaultCsrfProviderTest.php b/src/Symfony/Component/Form/Tests/Extension/Csrf/CsrfProvider/LegacyDefaultCsrfProviderTest.php index c22bd46a7bdf7..8cca486369ec0 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Csrf/CsrfProvider/LegacyDefaultCsrfProviderTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Csrf/CsrfProvider/LegacyDefaultCsrfProviderTest.php @@ -23,14 +23,6 @@ class LegacyDefaultCsrfProviderTest extends TestCase { protected $provider; - public static function setUpBeforeClass() - { - if (\PHP_VERSION_ID < 70200) { - ini_set('session.save_handler', 'files'); - ini_set('session.save_path', sys_get_temp_dir()); - } - } - protected function setUp() { $this->provider = new DefaultCsrfProvider('SECRET'); diff --git a/src/Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.php b/src/Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.php index 1ee6d3f34e531..09cb242f92c2d 100644 --- a/src/Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.php +++ b/src/Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.php @@ -101,12 +101,11 @@ class NativeSessionStorage implements SessionStorageInterface */ public function __construct(array $options = array(), $handler = null, MetadataBag $metaBag = null) { - if (empty($options)) { - $options += array('cache_limiter' => 'public'); - } - if (1 !== (int) ini_get('session.use_cookies')) { - ini_set('session.use_cookies', 1); - } + $options += array( + // disable by default because it's managed by HeaderBag (if used) + 'cache_limiter' => '', + 'use_cookies' => 1, + ); if (\PHP_VERSION_ID >= 50400) { session_register_shutdown(); @@ -212,6 +211,10 @@ public function regenerate($destroy = false, $lifetime = null) return false; } + if (headers_sent()) { + return false; + } + if (null !== $lifetime) { ini_set('session.cookie_lifetime', $lifetime); } @@ -336,6 +339,10 @@ public function isStarted() */ public function setOptions(array $options) { + if (headers_sent()) { + return; + } + $validOptions = array_flip(array( 'cache_limiter', 'cookie_domain', 'cookie_httponly', 'cookie_lifetime', 'cookie_path', 'cookie_secure', @@ -349,11 +356,9 @@ public function setOptions(array $options) 'sid_length', 'sid_bits_per_character', 'trans_sid_hosts', 'trans_sid_tags', )); - if (PHP_VERSION_ID < 70200 || !headers_sent()) { - foreach ($options as $key => $value) { - if (isset($validOptions[$key])) { - ini_set('session.'.$key, $value); - } + foreach ($options as $key => $value) { + if (isset($validOptions[$key])) { + ini_set('session.'.$key, $value); } } } @@ -389,6 +394,10 @@ public function setSaveHandler($saveHandler = null) throw new \InvalidArgumentException('Must be instance of AbstractProxy or NativeSessionHandler; implement \SessionHandlerInterface; or be null.'); } + if (headers_sent($file, $line)) { + throw new \RuntimeException(sprintf('Failed to set the session handler because headers have already been sent by "%s" at line %d.', $file, $line)); + } + // Wrap $saveHandler in proxy and prevent double wrapping of proxy if (!$saveHandler instanceof AbstractProxy && $saveHandler instanceof \SessionHandlerInterface) { $saveHandler = new SessionHandlerProxy($saveHandler); @@ -398,7 +407,7 @@ public function setSaveHandler($saveHandler = null) } $this->saveHandler = $saveHandler; - if ($this->saveHandler instanceof \SessionHandlerInterface && false === headers_sent()) { + if ($this->saveHandler instanceof \SessionHandlerInterface) { if (\PHP_VERSION_ID >= 50400) { session_set_save_handler($this->saveHandler, false); } else { diff --git a/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/PdoSessionHandlerTest.php b/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/PdoSessionHandlerTest.php index 88509b11b95d7..a9884c1c92ea3 100644 --- a/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/PdoSessionHandlerTest.php +++ b/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/PdoSessionHandlerTest.php @@ -269,12 +269,11 @@ public function testSessionDestroy() $this->assertSame('', $data, 'Destroyed session returns empty string'); } + /** + * @runInSeparateProcess + */ public function testSessionGC() { - if (\PHP_VERSION_ID >= 70200) { - $this->markTestSkipped('PHP version is 7.2'); - } - $previousLifeTime = ini_set('session.gc_maxlifetime', 1000); $pdo = $this->getMemorySqlitePdo(); $storage = new PdoSessionHandler($pdo); @@ -286,12 +285,10 @@ public function testSessionGC() $storage->open('', 'sid'); $storage->read('gc_id'); - // IN 7.2 this does not work ini_set('session.gc_maxlifetime', -1); // test that you can set lifetime of a session after it has been read $storage->write('gc_id', 'data'); $storage->close(); $this->assertEquals(2, $pdo->query('SELECT COUNT(*) FROM sessions')->fetchColumn(), 'No session pruned because gc not called'); - $storage->destroy('gc_id'); $storage->open('', 'sid'); $data = $storage->read('gc_id'); @@ -299,39 +296,7 @@ public function testSessionGC() $storage->close(); ini_set('session.gc_maxlifetime', $previousLifeTime); - $this->assertSame('', $data, 'Session already considered garbage, so not returning data even if it is not pruned yet'); - $this->assertEquals(1, $pdo->query('SELECT COUNT(*) FROM sessions')->fetchColumn(), 'Expired session is pruned'); - } - - public function testSessionGC72() - { - if (\PHP_VERSION_ID <= 70200) { - $this->markTestSkipped('PHP version is not 7.2'); - } - - $previousLifeTime = false === headers_sent() && ini_set('session.gc_maxlifetime', 1000); - $pdo = $this->getMemorySqlitePdo(); - $storage = new PdoSessionHandler($pdo); - - $storage->open('', 'sid'); - $storage->read('id'); - $storage->write('id', 'data'); - $storage->close(); - - $storage->open('', 'sid'); - $storage->read('gc_id'); - false === headers_sent() && ini_set('session.gc_maxlifetime', -1); // test that you can set lifetime of a session after it has been read - $storage->write('gc_id', 'data'); - $storage->close(); - $this->assertEquals(2, $pdo->query('SELECT COUNT(*) FROM sessions')->fetchColumn(), 'No session pruned because gc not called'); - true === headers_sent() && $storage->destroy('gc_id'); - - $storage->open('', 'sid'); - $data = $storage->read('gc_id'); - $storage->gc(-1); - $storage->close(); - false === headers_sent() && ini_set('session.gc_maxlifetime', $previousLifeTime); $this->assertSame('', $data, 'Session already considered garbage, so not returning data even if it is not pruned yet'); $this->assertEquals(1, $pdo->query('SELECT COUNT(*) FROM sessions')->fetchColumn(), 'Expired session is pruned'); } diff --git a/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/NativeSessionStorageTest.php b/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/NativeSessionStorageTest.php index d5281c644d003..20f9ca060bc3c 100644 --- a/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/NativeSessionStorageTest.php +++ b/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/NativeSessionStorageTest.php @@ -152,7 +152,7 @@ public function testDefaultSessionCacheLimiter() { $this->iniSet('session.cache_limiter', 'nocache'); - $storage = new NativeSessionStorage(array('cache_limiter' => '')); + $storage = new NativeSessionStorage(); $this->assertEquals('', ini_get('session.cache_limiter')); } diff --git a/src/Symfony/Component/HttpKernel/Tests/EventListener/LocaleListenerTest.php b/src/Symfony/Component/HttpKernel/Tests/EventListener/LocaleListenerTest.php index 24f9038f35ed5..1898ee0863a4b 100644 --- a/src/Symfony/Component/HttpKernel/Tests/EventListener/LocaleListenerTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/EventListener/LocaleListenerTest.php @@ -38,12 +38,7 @@ public function testDefaultLocaleWithoutSession() public function testLocaleFromRequestAttribute() { $request = Request::create('/'); - - if (PHP_VERSION_ID < 70200 || !headers_sent()) { - session_name('foo'); - } - - $request->cookies->set('foo', 'value'); + $request->cookies->set(session_name(), 'value'); $request->attributes->set('_locale', 'es'); $listener = new LocaleListener('fr', null, $this->requestStack); diff --git a/src/Symfony/Component/HttpKernel/Tests/EventListener/TestSessionListenerTest.php b/src/Symfony/Component/HttpKernel/Tests/EventListener/TestSessionListenerTest.php index 63d5338182854..47ee153342df5 100644 --- a/src/Symfony/Component/HttpKernel/Tests/EventListener/TestSessionListenerTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/EventListener/TestSessionListenerTest.php @@ -62,8 +62,7 @@ public function testDoesNotDeleteCookieIfUsingSessionLifetime() { $this->sessionHasBeenStarted(); - $params = session_get_cookie_params(); - // session_set_cookie_params(0, $params['path'], $params['domain'], $params['secure'], $params['httponly']); + @ini_set('session.cookie_lifetime', 0); $response = $this->filterResponse(new Request(), HttpKernelInterface::MASTER_REQUEST); $cookies = $response->headers->getCookies(); diff --git a/src/Symfony/Component/HttpKernel/composer.json b/src/Symfony/Component/HttpKernel/composer.json index 6b6ec3f17b886..1b6b096a8a61f 100644 --- a/src/Symfony/Component/HttpKernel/composer.json +++ b/src/Symfony/Component/HttpKernel/composer.json @@ -18,7 +18,7 @@ "require": { "php": ">=5.3.9", "symfony/event-dispatcher": "^2.6.7", - "symfony/http-foundation": "~2.7.20|^2.8.13", + "symfony/http-foundation": "~2.7.36|^2.8.29", "symfony/debug": "^2.6.2", "psr/log": "~1.0" }, diff --git a/src/Symfony/Component/Routing/Tests/Fixtures/validresource.php b/src/Symfony/Component/Routing/Tests/Fixtures/validresource.php index 482c80b29e919..f59a234d6589a 100644 --- a/src/Symfony/Component/Routing/Tests/Fixtures/validresource.php +++ b/src/Symfony/Component/Routing/Tests/Fixtures/validresource.php @@ -1,5 +1,8 @@ import('validpattern.php'); diff --git a/src/Symfony/Component/Security/Csrf/Tests/TokenStorage/NativeSessionTokenStorageTest.php b/src/Symfony/Component/Security/Csrf/Tests/TokenStorage/NativeSessionTokenStorageTest.php index 869f14f82ec76..d7931c09b2099 100644 --- a/src/Symfony/Component/Security/Csrf/Tests/TokenStorage/NativeSessionTokenStorageTest.php +++ b/src/Symfony/Component/Security/Csrf/Tests/TokenStorage/NativeSessionTokenStorageTest.php @@ -29,16 +29,6 @@ class NativeSessionTokenStorageTest extends TestCase */ private $storage; - public static function setUpBeforeClass() - { - if (\PHP_VERSION_ID < 70200) { - ini_set('session.save_handler', 'files'); - ini_set('session.save_path', sys_get_temp_dir()); - } - - parent::setUpBeforeClass(); - } - protected function setUp() { $_SESSION = array(); From 8ad32f0ef56b13fb7930fea9dcface331f6ded22 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Tue, 10 Oct 2017 10:04:23 +0200 Subject: [PATCH 1055/1099] never match invalid IP addresses --- .../Component/HttpFoundation/IpUtils.php | 4 ++++ .../HttpFoundation/Tests/IpUtilsTest.php | 17 +++++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/src/Symfony/Component/HttpFoundation/IpUtils.php b/src/Symfony/Component/HttpFoundation/IpUtils.php index dc6d3ec818a32..3bb33140f5055 100644 --- a/src/Symfony/Component/HttpFoundation/IpUtils.php +++ b/src/Symfony/Component/HttpFoundation/IpUtils.php @@ -87,6 +87,10 @@ public static function checkIp4($requestIp, $ip) $netmask = 32; } + if (false === ip2long($address)) { + return self::$checkedIps[$cacheKey] = false; + } + return self::$checkedIps[$cacheKey] = 0 === substr_compare(sprintf('%032b', ip2long($requestIp)), sprintf('%032b', ip2long($address)), 0, $netmask); } diff --git a/src/Symfony/Component/HttpFoundation/Tests/IpUtilsTest.php b/src/Symfony/Component/HttpFoundation/Tests/IpUtilsTest.php index 297ee3d8d3542..54cbb5c20672d 100644 --- a/src/Symfony/Component/HttpFoundation/Tests/IpUtilsTest.php +++ b/src/Symfony/Component/HttpFoundation/Tests/IpUtilsTest.php @@ -82,4 +82,21 @@ public function testAnIpv6WithOptionDisabledIpv6() IpUtils::checkIp('2a01:198:603:0:396e:4789:8e99:890f', '2a01:198:603:0::/65'); } + + /** + * @dataProvider invalidIpAddressData + */ + public function testInvalidIpAddressesDoNotMatch($requestIp, $proxyIp) + { + $this->assertFalse(IpUtils::checkIp4($requestIp, $proxyIp)); + } + + public function invalidIpAddressData() + { + return array( + 'invalid proxy wildcard' => array('192.168.20.13', '*'), + 'invalid proxy missing netmask' => array('192.168.20.13', '0.0.0.0'), + 'invalid request IP with invalid proxy wildcard' => array('0.0.0.0', '*'), + ); + } } From e71c4f71f54f30f32b49d45948055d30178f2b5d Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Tue, 10 Oct 2017 12:05:53 +0200 Subject: [PATCH 1056/1099] fix merge --- .../Tests/Compiler/OptionalServiceClass.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/DependencyInjection/Tests/Compiler/OptionalServiceClass.php b/src/Symfony/Component/DependencyInjection/Tests/Compiler/OptionalServiceClass.php index 7e9238f22301b..33372695903e9 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Compiler/OptionalServiceClass.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Compiler/OptionalServiceClass.php @@ -13,6 +13,8 @@ use Symfony\Bug\NotExistClass; -class OptionalServiceClass extends NotExistClass -{ +if (!function_exists('__phpunit_run_isolated_test')) { + class OptionalServiceClass extends NotExistClass + { + } } From 2ee6fd54e19437fb8893e10f7a8c43f1709c6512 Mon Sep 17 00:00:00 2001 From: Pierre du Plessis Date: Sun, 1 Oct 2017 10:07:08 +0200 Subject: [PATCH 1057/1099] [FORM] Prevent forms from extending itself as a parent --- src/Symfony/Component/Form/FormRegistry.php | 32 ++++++++++++----- .../Tests/Fixtures/FormWithSameParentType.php | 22 ++++++++++++ .../Tests/Fixtures/RecursiveFormTypeBar.php | 22 ++++++++++++ .../Tests/Fixtures/RecursiveFormTypeBaz.php | 22 ++++++++++++ .../Tests/Fixtures/RecursiveFormTypeFoo.php | 22 ++++++++++++ .../Component/Form/Tests/FormRegistryTest.php | 34 +++++++++++++++++++ 6 files changed, 145 insertions(+), 9 deletions(-) create mode 100644 src/Symfony/Component/Form/Tests/Fixtures/FormWithSameParentType.php create mode 100644 src/Symfony/Component/Form/Tests/Fixtures/RecursiveFormTypeBar.php create mode 100644 src/Symfony/Component/Form/Tests/Fixtures/RecursiveFormTypeBaz.php create mode 100644 src/Symfony/Component/Form/Tests/Fixtures/RecursiveFormTypeFoo.php diff --git a/src/Symfony/Component/Form/FormRegistry.php b/src/Symfony/Component/Form/FormRegistry.php index 6e00755378f5a..c81d45957b008 100644 --- a/src/Symfony/Component/Form/FormRegistry.php +++ b/src/Symfony/Component/Form/FormRegistry.php @@ -12,6 +12,7 @@ namespace Symfony\Component\Form; use Symfony\Component\Form\Exception\ExceptionInterface; +use Symfony\Component\Form\Exception\LogicException; use Symfony\Component\Form\Exception\UnexpectedTypeException; use Symfony\Component\Form\Exception\InvalidArgumentException; @@ -44,6 +45,8 @@ class FormRegistry implements FormRegistryInterface */ private $resolvedTypeFactory; + private $checkedTypes = array(); + /** * @param FormExtensionInterface[] $extensions An array of FormExtensionInterface * @param ResolvedFormTypeFactoryInterface $resolvedTypeFactory The factory for resolved form types @@ -106,18 +109,29 @@ private function resolveType(FormTypeInterface $type) $parentType = $type->getParent(); $fqcn = get_class($type); - foreach ($this->extensions as $extension) { - $typeExtensions = array_merge( + if (isset($this->checkedTypes[$fqcn])) { + $types = implode(' > ', array_merge(array_keys($this->checkedTypes), array($fqcn))); + throw new LogicException(sprintf('Circular reference detected for form "%s" (%s).', $fqcn, $types)); + } + + $this->checkedTypes[$fqcn] = true; + + try { + foreach ($this->extensions as $extension) { + $typeExtensions = array_merge( + $typeExtensions, + $extension->getTypeExtensions($fqcn) + ); + } + + return $this->resolvedTypeFactory->createResolvedType( + $type, $typeExtensions, - $extension->getTypeExtensions($fqcn) + $parentType ? $this->getType($parentType) : null ); + } finally { + unset($this->checkedTypes[$fqcn]); } - - return $this->resolvedTypeFactory->createResolvedType( - $type, - $typeExtensions, - $parentType ? $this->getType($parentType) : null - ); } /** diff --git a/src/Symfony/Component/Form/Tests/Fixtures/FormWithSameParentType.php b/src/Symfony/Component/Form/Tests/Fixtures/FormWithSameParentType.php new file mode 100644 index 0000000000000..098f9a2a2b708 --- /dev/null +++ b/src/Symfony/Component/Form/Tests/Fixtures/FormWithSameParentType.php @@ -0,0 +1,22 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Tests\Fixtures; + +use Symfony\Component\Form\AbstractType; + +class FormWithSameParentType extends AbstractType +{ + public function getParent() + { + return self::class; + } +} diff --git a/src/Symfony/Component/Form/Tests/Fixtures/RecursiveFormTypeBar.php b/src/Symfony/Component/Form/Tests/Fixtures/RecursiveFormTypeBar.php new file mode 100644 index 0000000000000..a7b0d4df35b00 --- /dev/null +++ b/src/Symfony/Component/Form/Tests/Fixtures/RecursiveFormTypeBar.php @@ -0,0 +1,22 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Tests\Fixtures; + +use Symfony\Component\Form\AbstractType; + +class RecursiveFormTypeBar extends AbstractType +{ + public function getParent() + { + return RecursiveFormTypeBaz::class; + } +} diff --git a/src/Symfony/Component/Form/Tests/Fixtures/RecursiveFormTypeBaz.php b/src/Symfony/Component/Form/Tests/Fixtures/RecursiveFormTypeBaz.php new file mode 100644 index 0000000000000..63f62e757f93e --- /dev/null +++ b/src/Symfony/Component/Form/Tests/Fixtures/RecursiveFormTypeBaz.php @@ -0,0 +1,22 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Tests\Fixtures; + +use Symfony\Component\Form\AbstractType; + +class RecursiveFormTypeBaz extends AbstractType +{ + public function getParent() + { + return RecursiveFormTypeFoo::class; + } +} diff --git a/src/Symfony/Component/Form/Tests/Fixtures/RecursiveFormTypeFoo.php b/src/Symfony/Component/Form/Tests/Fixtures/RecursiveFormTypeFoo.php new file mode 100644 index 0000000000000..a41f63ee0b9cb --- /dev/null +++ b/src/Symfony/Component/Form/Tests/Fixtures/RecursiveFormTypeFoo.php @@ -0,0 +1,22 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Form\Tests\Fixtures; + +use Symfony\Component\Form\AbstractType; + +class RecursiveFormTypeFoo extends AbstractType +{ + public function getParent() + { + return RecursiveFormTypeBar::class; + } +} diff --git a/src/Symfony/Component/Form/Tests/FormRegistryTest.php b/src/Symfony/Component/Form/Tests/FormRegistryTest.php index 5deddff422b42..4fbcb4339a1a1 100644 --- a/src/Symfony/Component/Form/Tests/FormRegistryTest.php +++ b/src/Symfony/Component/Form/Tests/FormRegistryTest.php @@ -16,6 +16,10 @@ use Symfony\Component\Form\FormTypeGuesserChain; use Symfony\Component\Form\ResolvedFormType; use Symfony\Component\Form\ResolvedFormTypeFactoryInterface; +use Symfony\Component\Form\Tests\Fixtures\FormWithSameParentType; +use Symfony\Component\Form\Tests\Fixtures\RecursiveFormTypeBar; +use Symfony\Component\Form\Tests\Fixtures\RecursiveFormTypeBaz; +use Symfony\Component\Form\Tests\Fixtures\RecursiveFormTypeFoo; use Symfony\Component\Form\Tests\Fixtures\FooSubType; use Symfony\Component\Form\Tests\Fixtures\FooType; use Symfony\Component\Form\Tests\Fixtures\FooTypeBarExtension; @@ -156,6 +160,36 @@ public function testGetTypeConnectsParent() $this->assertSame($resolvedType, $this->registry->getType(get_class($type))); } + /** + * @expectedException \Symfony\Component\Form\Exception\LogicException + * @expectedExceptionMessage Circular reference detected for form "Symfony\Component\Form\Tests\Fixtures\FormWithSameParentType" (Symfony\Component\Form\Tests\Fixtures\FormWithSameParentType > Symfony\Component\Form\Tests\Fixtures\FormWithSameParentType). + */ + public function testFormCannotHaveItselfAsAParent() + { + $type = new FormWithSameParentType(); + + $this->extension2->addType($type); + + $this->registry->getType(FormWithSameParentType::class); + } + + /** + * @expectedException \Symfony\Component\Form\Exception\LogicException + * @expectedExceptionMessage Circular reference detected for form "Symfony\Component\Form\Tests\Fixtures\RecursiveFormTypeFoo" (Symfony\Component\Form\Tests\Fixtures\RecursiveFormTypeFoo > Symfony\Component\Form\Tests\Fixtures\RecursiveFormTypeBar > Symfony\Component\Form\Tests\Fixtures\RecursiveFormTypeBaz > Symfony\Component\Form\Tests\Fixtures\RecursiveFormTypeFoo). + */ + public function testRecursiveFormDependencies() + { + $foo = new RecursiveFormTypeFoo(); + $bar = new RecursiveFormTypeBar(); + $baz = new RecursiveFormTypeBaz(); + + $this->extension2->addType($foo); + $this->extension2->addType($bar); + $this->extension2->addType($baz); + + $this->registry->getType(RecursiveFormTypeFoo::class); + } + /** * @expectedException \Symfony\Component\Form\Exception\InvalidArgumentException */ From 6595615255847fdc88243e38e730e473b13ef4b6 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Tue, 10 Oct 2017 12:32:49 +0200 Subject: [PATCH 1058/1099] fix merge --- src/Symfony/Bridge/Twig/Tests/AppVariableTest.php | 6 ++++++ .../FrameworkBundle/Tests/Fixtures/Validation/Article.php | 8 +++++--- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Bridge/Twig/Tests/AppVariableTest.php b/src/Symfony/Bridge/Twig/Tests/AppVariableTest.php index accbf1c682ee8..9071a3e4f779f 100644 --- a/src/Symfony/Bridge/Twig/Tests/AppVariableTest.php +++ b/src/Symfony/Bridge/Twig/Tests/AppVariableTest.php @@ -168,6 +168,9 @@ public function testGetFlashesWithNoRequest() $this->assertEquals(array(), $this->appVariable->getFlashes()); } + /** + * @runInSeparateProcess + */ public function testGetFlashesWithNoSessionStarted() { $request = $this->getMockBuilder('Symfony\Component\HttpFoundation\Request')->getMock(); @@ -178,6 +181,9 @@ public function testGetFlashesWithNoSessionStarted() $this->assertEquals(array(), $this->appVariable->getFlashes()); } + /** + * @runInSeparateProcess + */ public function testGetFlashes() { $flashMessages = $this->setFlashMessages(); diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Validation/Article.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Validation/Article.php index a1ecee6d0b375..5f28d0648f388 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Validation/Article.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Fixtures/Validation/Article.php @@ -2,7 +2,9 @@ namespace Symfony\Bundle\FrameworkBundle\Tests\Fixtures\Validation; -class Article implements NotExistingInterface -{ - public $category; +if (!function_exists('__phpunit_run_isolated_test')) { + class Article implements NotExistingInterface + { + public $category; + } } From 9719fba0ab5f1abcfd21af0a3702c1e24903d8c3 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Tue, 10 Oct 2017 12:34:18 +0200 Subject: [PATCH 1059/1099] fix merge --- src/Symfony/Component/Config/Tests/Fixtures/BadParent.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/Config/Tests/Fixtures/BadParent.php b/src/Symfony/Component/Config/Tests/Fixtures/BadParent.php index 68d7296ed8696..3f9720bb8a962 100644 --- a/src/Symfony/Component/Config/Tests/Fixtures/BadParent.php +++ b/src/Symfony/Component/Config/Tests/Fixtures/BadParent.php @@ -2,6 +2,8 @@ namespace Symfony\Component\Config\Tests\Fixtures; -class BadParent extends MissingParent -{ +if (!function_exists('__phpunit_run_isolated_test')) { + class BadParent extends MissingParent + { + } } From d762dd1dc6a45ec0c0a0638242ca96f6dd5fcb33 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Tue, 10 Oct 2017 12:58:54 +0200 Subject: [PATCH 1060/1099] remove deprecated features --- src/Symfony/Bridge/Monolog/Logger.php | 2 +- src/Symfony/Component/EventDispatcher/CHANGELOG.md | 1 + .../Debug/TraceableEventDispatcherInterface.php | 7 +++++-- .../HttpKernel/DataCollector/DataCollectorInterface.php | 7 +++++-- .../HttpKernel/DataCollector/EventDataCollector.php | 7 ------- .../HttpKernel/DataCollector/LoggerDataCollector.php | 6 +----- .../Component/HttpKernel/Log/DebugLoggerInterface.php | 7 +++++-- src/Symfony/Component/HttpKernel/Profiler/Profiler.php | 8 -------- 8 files changed, 18 insertions(+), 27 deletions(-) diff --git a/src/Symfony/Bridge/Monolog/Logger.php b/src/Symfony/Bridge/Monolog/Logger.php index 7cd75c5ec11ca..d4771f2894d89 100644 --- a/src/Symfony/Bridge/Monolog/Logger.php +++ b/src/Symfony/Bridge/Monolog/Logger.php @@ -50,7 +50,7 @@ public function countErrors() */ public function clear() { - if (($logger = $this->getDebugLogger()) && method_exists($logger, 'clear')) { + if ($logger = $this->getDebugLogger()) { $logger->clear(); } } diff --git a/src/Symfony/Component/EventDispatcher/CHANGELOG.md b/src/Symfony/Component/EventDispatcher/CHANGELOG.md index cde9a680a53fa..e570303e742cc 100644 --- a/src/Symfony/Component/EventDispatcher/CHANGELOG.md +++ b/src/Symfony/Component/EventDispatcher/CHANGELOG.md @@ -5,6 +5,7 @@ CHANGELOG ----- * removed the `ContainerAwareEventDispatcher` class + * added the `reset()` method to the `TraceableEventDispatcherInterface` 3.4.0 ----- diff --git a/src/Symfony/Component/EventDispatcher/Debug/TraceableEventDispatcherInterface.php b/src/Symfony/Component/EventDispatcher/Debug/TraceableEventDispatcherInterface.php index f0212753be591..4adbe9693a787 100644 --- a/src/Symfony/Component/EventDispatcher/Debug/TraceableEventDispatcherInterface.php +++ b/src/Symfony/Component/EventDispatcher/Debug/TraceableEventDispatcherInterface.php @@ -15,8 +15,6 @@ /** * @author Fabien Potencier - * - * @method reset() Resets the trace. */ interface TraceableEventDispatcherInterface extends EventDispatcherInterface { @@ -33,4 +31,9 @@ public function getCalledListeners(); * @return array An array of not called listeners */ public function getNotCalledListeners(); + + /** + * Resets the trace. + */ + public function reset(); } diff --git a/src/Symfony/Component/HttpKernel/DataCollector/DataCollectorInterface.php b/src/Symfony/Component/HttpKernel/DataCollector/DataCollectorInterface.php index c0a0c0a982b3b..9e76a99fc52ff 100644 --- a/src/Symfony/Component/HttpKernel/DataCollector/DataCollectorInterface.php +++ b/src/Symfony/Component/HttpKernel/DataCollector/DataCollectorInterface.php @@ -18,8 +18,6 @@ * DataCollectorInterface. * * @author Fabien Potencier - * - * @method reset() Resets this data collector to its initial state. */ interface DataCollectorInterface { @@ -38,4 +36,9 @@ public function collect(Request $request, Response $response, \Exception $except * @return string The collector name */ public function getName(); + + /** + * Resets this data collector to its initial state. + */ + public function reset(); } diff --git a/src/Symfony/Component/HttpKernel/DataCollector/EventDataCollector.php b/src/Symfony/Component/HttpKernel/DataCollector/EventDataCollector.php index ab44405edb2e7..e82a1fc19bb09 100644 --- a/src/Symfony/Component/HttpKernel/DataCollector/EventDataCollector.php +++ b/src/Symfony/Component/HttpKernel/DataCollector/EventDataCollector.php @@ -27,9 +27,6 @@ class EventDataCollector extends DataCollector implements LateDataCollectorInter public function __construct(EventDispatcherInterface $dispatcher = null) { - if ($dispatcher instanceof TraceableEventDispatcherInterface && !method_exists($dispatcher, 'reset')) { - @trigger_error(sprintf('Implementing "%s" without the "reset()" method is deprecated since version 3.4 and will be unsupported in 4.0 for class "%s".', TraceableEventDispatcherInterface::class, \get_class($dispatcher)), E_USER_DEPRECATED); - } $this->dispatcher = $dispatcher; } @@ -49,10 +46,6 @@ public function reset() $this->data = array(); if ($this->dispatcher instanceof TraceableEventDispatcherInterface) { - if (!method_exists($this->dispatcher, 'reset')) { - return; // @deprecated - } - $this->dispatcher->reset(); } } diff --git a/src/Symfony/Component/HttpKernel/DataCollector/LoggerDataCollector.php b/src/Symfony/Component/HttpKernel/DataCollector/LoggerDataCollector.php index ee645d53e8fdb..f1df6e2d7e0eb 100644 --- a/src/Symfony/Component/HttpKernel/DataCollector/LoggerDataCollector.php +++ b/src/Symfony/Component/HttpKernel/DataCollector/LoggerDataCollector.php @@ -29,10 +29,6 @@ class LoggerDataCollector extends DataCollector implements LateDataCollectorInte public function __construct($logger = null, $containerPathPrefix = null) { if (null !== $logger && $logger instanceof DebugLoggerInterface) { - if (!method_exists($logger, 'clear')) { - @trigger_error(sprintf('Implementing "%s" without the "clear()" method is deprecated since version 3.4 and will be unsupported in 4.0 for class "%s".', DebugLoggerInterface::class, \get_class($logger)), E_USER_DEPRECATED); - } - $this->logger = $logger; } @@ -52,7 +48,7 @@ public function collect(Request $request, Response $response, \Exception $except */ public function reset() { - if ($this->logger && method_exists($this->logger, 'clear')) { + if ($this->logger instanceof DebugLoggerInterface) { $this->logger->clear(); } $this->data = array(); diff --git a/src/Symfony/Component/HttpKernel/Log/DebugLoggerInterface.php b/src/Symfony/Component/HttpKernel/Log/DebugLoggerInterface.php index f0606d3b0e5ee..1d955c48296ae 100644 --- a/src/Symfony/Component/HttpKernel/Log/DebugLoggerInterface.php +++ b/src/Symfony/Component/HttpKernel/Log/DebugLoggerInterface.php @@ -15,8 +15,6 @@ * DebugLoggerInterface. * * @author Fabien Potencier - * - * @method clear() Removes all log records. */ interface DebugLoggerInterface { @@ -37,4 +35,9 @@ public function getLogs(); * @return int The number of errors */ public function countErrors(); + + /** + * Removes all log records. + */ + public function clear(); } diff --git a/src/Symfony/Component/HttpKernel/Profiler/Profiler.php b/src/Symfony/Component/HttpKernel/Profiler/Profiler.php index 85a71641be6fe..c99e7113fc88f 100644 --- a/src/Symfony/Component/HttpKernel/Profiler/Profiler.php +++ b/src/Symfony/Component/HttpKernel/Profiler/Profiler.php @@ -198,10 +198,6 @@ public function collect(Request $request, Response $response, \Exception $except public function reset() { foreach ($this->collectors as $collector) { - if (!method_exists($collector, 'reset')) { - continue; - } - $collector->reset(); } $this->enabled = $this->initiallyEnabled; @@ -237,10 +233,6 @@ public function set(array $collectors = array()) */ public function add(DataCollectorInterface $collector) { - if (!method_exists($collector, 'reset')) { - @trigger_error(sprintf('Implementing "%s" without the "reset()" method is deprecated since version 3.4 and will be unsupported in 4.0 for class "%s".', DataCollectorInterface::class, \get_class($collector)), E_USER_DEPRECATED); - } - $this->collectors[$collector->getName()] = $collector; } From 48eb43daede6dcfd4fddea0f5fa96538e9e2180b Mon Sep 17 00:00:00 2001 From: Pierre du Plessis Date: Tue, 10 Oct 2017 13:00:46 +0200 Subject: [PATCH 1061/1099] [Form] Fix error message in circular reference dependencies check --- src/Symfony/Component/Form/FormRegistry.php | 2 +- src/Symfony/Component/Form/Tests/FormRegistryTest.php | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Component/Form/FormRegistry.php b/src/Symfony/Component/Form/FormRegistry.php index c81d45957b008..7d08d690dffba 100644 --- a/src/Symfony/Component/Form/FormRegistry.php +++ b/src/Symfony/Component/Form/FormRegistry.php @@ -111,7 +111,7 @@ private function resolveType(FormTypeInterface $type) if (isset($this->checkedTypes[$fqcn])) { $types = implode(' > ', array_merge(array_keys($this->checkedTypes), array($fqcn))); - throw new LogicException(sprintf('Circular reference detected for form "%s" (%s).', $fqcn, $types)); + throw new LogicException(sprintf('Circular reference detected for form type "%s" (%s).', $fqcn, $types)); } $this->checkedTypes[$fqcn] = true; diff --git a/src/Symfony/Component/Form/Tests/FormRegistryTest.php b/src/Symfony/Component/Form/Tests/FormRegistryTest.php index 4fbcb4339a1a1..b304eaed40fb9 100644 --- a/src/Symfony/Component/Form/Tests/FormRegistryTest.php +++ b/src/Symfony/Component/Form/Tests/FormRegistryTest.php @@ -162,7 +162,7 @@ public function testGetTypeConnectsParent() /** * @expectedException \Symfony\Component\Form\Exception\LogicException - * @expectedExceptionMessage Circular reference detected for form "Symfony\Component\Form\Tests\Fixtures\FormWithSameParentType" (Symfony\Component\Form\Tests\Fixtures\FormWithSameParentType > Symfony\Component\Form\Tests\Fixtures\FormWithSameParentType). + * @expectedExceptionMessage Circular reference detected for form type "Symfony\Component\Form\Tests\Fixtures\FormWithSameParentType" (Symfony\Component\Form\Tests\Fixtures\FormWithSameParentType > Symfony\Component\Form\Tests\Fixtures\FormWithSameParentType). */ public function testFormCannotHaveItselfAsAParent() { @@ -175,7 +175,7 @@ public function testFormCannotHaveItselfAsAParent() /** * @expectedException \Symfony\Component\Form\Exception\LogicException - * @expectedExceptionMessage Circular reference detected for form "Symfony\Component\Form\Tests\Fixtures\RecursiveFormTypeFoo" (Symfony\Component\Form\Tests\Fixtures\RecursiveFormTypeFoo > Symfony\Component\Form\Tests\Fixtures\RecursiveFormTypeBar > Symfony\Component\Form\Tests\Fixtures\RecursiveFormTypeBaz > Symfony\Component\Form\Tests\Fixtures\RecursiveFormTypeFoo). + * @expectedExceptionMessage Circular reference detected for form type "Symfony\Component\Form\Tests\Fixtures\RecursiveFormTypeFoo" (Symfony\Component\Form\Tests\Fixtures\RecursiveFormTypeFoo > Symfony\Component\Form\Tests\Fixtures\RecursiveFormTypeBar > Symfony\Component\Form\Tests\Fixtures\RecursiveFormTypeBaz > Symfony\Component\Form\Tests\Fixtures\RecursiveFormTypeFoo). */ public function testRecursiveFormDependencies() { From 2d2022cc11968065787aced6108d0e6f37642d4d Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Tue, 10 Oct 2017 15:22:55 +0200 Subject: [PATCH 1062/1099] fix PHP 7.2 compatibility * the `phpdocumentor/type-resolver` package was not PHP 7.2 compatible before release 0.2.1 (see see phpDocumentor/TypeResolver@e224fb2) * the validator must not call `get_class()` if no object but a class name was passed to the `validatePropertyValue()` method --- composer.json | 2 +- src/Symfony/Bundle/FrameworkBundle/composer.json | 2 +- src/Symfony/Component/PropertyInfo/composer.json | 2 +- src/Symfony/Component/Serializer/composer.json | 1 + .../Validator/Validator/RecursiveContextualValidator.php | 4 +++- 5 files changed, 7 insertions(+), 4 deletions(-) diff --git a/composer.json b/composer.json index d55f29f6aaa8a..f27e19e242468 100644 --- a/composer.json +++ b/composer.json @@ -103,7 +103,7 @@ }, "conflict": { "phpdocumentor/reflection-docblock": "<3.0||>=3.2.0,<3.2.2", - "phpdocumentor/type-resolver": "<0.2.0", + "phpdocumentor/type-resolver": "<0.2.1", "phpunit/phpunit": "<4.8.35|<5.4.3,>=5.0" }, "provide": { diff --git a/src/Symfony/Bundle/FrameworkBundle/composer.json b/src/Symfony/Bundle/FrameworkBundle/composer.json index cdf6e4d2b8c94..f4ebfe5104b42 100644 --- a/src/Symfony/Bundle/FrameworkBundle/composer.json +++ b/src/Symfony/Bundle/FrameworkBundle/composer.json @@ -61,7 +61,7 @@ }, "conflict": { "phpdocumentor/reflection-docblock": "<3.0", - "phpdocumentor/type-resolver": "<0.2.0", + "phpdocumentor/type-resolver": "<0.2.1", "phpunit/phpunit": "<4.8.35|<5.4.3,>=5.0", "symfony/asset": "<3.3", "symfony/console": "<3.3", diff --git a/src/Symfony/Component/PropertyInfo/composer.json b/src/Symfony/Component/PropertyInfo/composer.json index d068a5ff6a3c3..f9e029e50465c 100644 --- a/src/Symfony/Component/PropertyInfo/composer.json +++ b/src/Symfony/Component/PropertyInfo/composer.json @@ -35,7 +35,7 @@ }, "conflict": { "phpdocumentor/reflection-docblock": "<3.0||>=3.2.0,<3.2.2", - "phpdocumentor/type-resolver": "<0.2.0", + "phpdocumentor/type-resolver": "<0.2.1", "symfony/dependency-injection": "<3.3" }, "suggest": { diff --git a/src/Symfony/Component/Serializer/composer.json b/src/Symfony/Component/Serializer/composer.json index e4ee63a730bc0..e1d6ded4aa2ed 100644 --- a/src/Symfony/Component/Serializer/composer.json +++ b/src/Symfony/Component/Serializer/composer.json @@ -31,6 +31,7 @@ "phpdocumentor/reflection-docblock": "^3.0|^4.0" }, "conflict": { + "phpdocumentor/type-resolver": "<0.2.1", "symfony/dependency-injection": "<3.2", "symfony/property-access": ">=3.0,<3.0.4|>=2.8,<2.8.4", "symfony/property-info": "<3.1", diff --git a/src/Symfony/Component/Validator/Validator/RecursiveContextualValidator.php b/src/Symfony/Component/Validator/Validator/RecursiveContextualValidator.php index 838d12b4033fd..3b55ab3db1944 100644 --- a/src/Symfony/Component/Validator/Validator/RecursiveContextualValidator.php +++ b/src/Symfony/Component/Validator/Validator/RecursiveContextualValidator.php @@ -261,11 +261,13 @@ public function validatePropertyValue($objectOrClass, $propertyName, $value, $gr if (is_object($objectOrClass)) { $object = $objectOrClass; + $class = get_class($object); $cacheKey = spl_object_hash($objectOrClass); $propertyPath = PropertyPath::append($this->defaultPropertyPath, $propertyName); } else { // $objectOrClass contains a class name $object = null; + $class = $objectOrClass; $cacheKey = null; $propertyPath = $this->defaultPropertyPath; } @@ -280,7 +282,7 @@ public function validatePropertyValue($objectOrClass, $propertyName, $value, $gr $this->validateGenericNode( $value, $object, - $cacheKey.':'.get_class($object).':'.$propertyName, + $cacheKey.':'.$class.':'.$propertyName, $propertyMetadata, $propertyPath, $groups, From a00862425765f583a60feb28b26ab5cb1b94b6da Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Tue, 10 Oct 2017 14:22:51 +0200 Subject: [PATCH 1063/1099] fix deps --- src/Symfony/Bundle/TwigBundle/composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Bundle/TwigBundle/composer.json b/src/Symfony/Bundle/TwigBundle/composer.json index 3d5fff2779a10..96d6ee24c7839 100644 --- a/src/Symfony/Bundle/TwigBundle/composer.json +++ b/src/Symfony/Bundle/TwigBundle/composer.json @@ -33,7 +33,7 @@ "symfony/routing": "~2.8|~3.0|~4.0", "symfony/templating": "~2.8|~3.0|~4.0", "symfony/yaml": "~2.8|~3.0|~4.0", - "symfony/framework-bundle": "^3.3|~4.0", + "symfony/framework-bundle": "^3.3.11|~4.0", "symfony/web-link": "~3.3|~4.0", "doctrine/annotations": "~1.0", "doctrine/cache": "~1.0" From 7a5985526fd909ae0601fe8e03f98aa7d21bc08d Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Tue, 10 Oct 2017 19:08:27 +0200 Subject: [PATCH 1064/1099] Skip tests affected by PHP bug 75354 --- .../Component/VarDumper/Tests/Caster/DateCasterTest.php | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/Symfony/Component/VarDumper/Tests/Caster/DateCasterTest.php b/src/Symfony/Component/VarDumper/Tests/Caster/DateCasterTest.php index 0130882bd925c..ee0413beb33fb 100644 --- a/src/Symfony/Component/VarDumper/Tests/Caster/DateCasterTest.php +++ b/src/Symfony/Component/VarDumper/Tests/Caster/DateCasterTest.php @@ -102,6 +102,10 @@ public function provideDateTimes() */ public function testDumpInterval($intervalSpec, $ms, $invert, $expected) { + if ($ms && PHP_VERSION_ID >= 70200 && version_compare(PHP_VERSION, '7.2.0rc2', '<=')) { + $this->markTestSkipped('Skipped on 7.2 before rc3 because of php bug #75354.'); + } + $interval = $this->createInterval($intervalSpec, $ms, $invert); $xDump = <<= 70200 && version_compare(PHP_VERSION, '7.2.0rc2', '<=')) { + $this->markTestSkipped('Skipped on 7.2 before rc3 because of php bug #75354.'); + } + $interval = $this->createInterval($intervalSpec, $ms, $invert); $xDump = << Date: Tue, 10 Oct 2017 19:19:34 +0200 Subject: [PATCH 1065/1099] fix --- .../Component/VarDumper/Tests/Caster/DateCasterTest.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Symfony/Component/VarDumper/Tests/Caster/DateCasterTest.php b/src/Symfony/Component/VarDumper/Tests/Caster/DateCasterTest.php index ee0413beb33fb..1967d360e9385 100644 --- a/src/Symfony/Component/VarDumper/Tests/Caster/DateCasterTest.php +++ b/src/Symfony/Component/VarDumper/Tests/Caster/DateCasterTest.php @@ -102,8 +102,8 @@ public function provideDateTimes() */ public function testDumpInterval($intervalSpec, $ms, $invert, $expected) { - if ($ms && PHP_VERSION_ID >= 70200 && version_compare(PHP_VERSION, '7.2.0rc2', '<=')) { - $this->markTestSkipped('Skipped on 7.2 before rc3 because of php bug #75354.'); + if ($ms && PHP_VERSION_ID >= 70200 && version_compare(PHP_VERSION, '7.2.0rc3', '<=')) { + $this->markTestSkipped('Skipped on 7.2 before rc4 because of php bug #75354.'); } $interval = $this->createInterval($intervalSpec, $ms, $invert); @@ -122,8 +122,8 @@ public function testDumpInterval($intervalSpec, $ms, $invert, $expected) */ public function testDumpIntervalExcludingVerbosity($intervalSpec, $ms, $invert, $expected) { - if ($ms && PHP_VERSION_ID >= 70200 && version_compare(PHP_VERSION, '7.2.0rc2', '<=')) { - $this->markTestSkipped('Skipped on 7.2 before rc3 because of php bug #75354.'); + if ($ms && PHP_VERSION_ID >= 70200 && version_compare(PHP_VERSION, '7.2.0rc3', '<=')) { + $this->markTestSkipped('Skipped on 7.2 before rc4 because of php bug #75354.'); } $interval = $this->createInterval($intervalSpec, $ms, $invert); From 2e3d422c4df5fbf1ca700ec5b808b4faffe2d8d7 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Tue, 10 Oct 2017 19:27:52 +0200 Subject: [PATCH 1066/1099] fix (ter) --- .../Component/VarDumper/Tests/Caster/DateCasterTest.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Symfony/Component/VarDumper/Tests/Caster/DateCasterTest.php b/src/Symfony/Component/VarDumper/Tests/Caster/DateCasterTest.php index 1967d360e9385..49d054b5199ad 100644 --- a/src/Symfony/Component/VarDumper/Tests/Caster/DateCasterTest.php +++ b/src/Symfony/Component/VarDumper/Tests/Caster/DateCasterTest.php @@ -142,6 +142,10 @@ public function testDumpIntervalExcludingVerbosity($intervalSpec, $ms, $invert, */ public function testCastInterval($intervalSpec, $ms, $invert, $xInterval, $xSeconds) { + if ($ms && PHP_VERSION_ID >= 70200 && version_compare(PHP_VERSION, '7.2.0rc3', '<=')) { + $this->markTestSkipped('Skipped on 7.2 before rc4 because of php bug #75354.'); + } + $interval = $this->createInterval($intervalSpec, $ms, $invert); $stub = new Stub(); From a3b136a93832879f1fc6df5e287a094604998da1 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Tue, 10 Oct 2017 22:05:27 +0200 Subject: [PATCH 1067/1099] dont use 7.2, it breaks for now --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index b8b7e886f93c1..ae93184f54fe9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -23,7 +23,7 @@ matrix: - php: 7.1.3 - php: 7.1 env: deps=high - - php: 7.2 + - php: 7.1 env: deps=low fast_finish: true From cd602d691a558f7f71f6aeaca0acbfc5f6b98e5b Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Tue, 10 Oct 2017 13:14:08 +0200 Subject: [PATCH 1068/1099] implement reset() in DumpDataCollector --- .../HttpKernel/DataCollector/DumpDataCollector.php | 10 ++++++++++ .../HttpKernel/DataCollector/TimeDataCollector.php | 7 ++++++- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/HttpKernel/DataCollector/DumpDataCollector.php b/src/Symfony/Component/HttpKernel/DataCollector/DumpDataCollector.php index b50386cb961c9..f9730b1485045 100644 --- a/src/Symfony/Component/HttpKernel/DataCollector/DumpDataCollector.php +++ b/src/Symfony/Component/HttpKernel/DataCollector/DumpDataCollector.php @@ -164,6 +164,16 @@ public function collect(Request $request, Response $response, \Exception $except } } + public function reset() + { + $this->stopwatch->reset(); + $this->data = array(); + $this->dataCount = 0; + $this->isCollected = false; + $this->clonesCount = 0; + $this->clonesIndex = 0; + } + public function serialize() { if ($this->clonesCount !== $this->clonesIndex) { diff --git a/src/Symfony/Component/HttpKernel/DataCollector/TimeDataCollector.php b/src/Symfony/Component/HttpKernel/DataCollector/TimeDataCollector.php index 6588304935d3d..e489d77598620 100644 --- a/src/Symfony/Component/HttpKernel/DataCollector/TimeDataCollector.php +++ b/src/Symfony/Component/HttpKernel/DataCollector/TimeDataCollector.php @@ -14,6 +14,7 @@ use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\KernelInterface; +use Symfony\Component\Stopwatch\Stopwatch; /** * TimeDataCollector. @@ -25,7 +26,7 @@ class TimeDataCollector extends DataCollector implements LateDataCollectorInterf protected $kernel; protected $stopwatch; - public function __construct(KernelInterface $kernel = null, $stopwatch = null) + public function __construct(KernelInterface $kernel = null, Stopwatch $stopwatch = null) { $this->kernel = $kernel; $this->stopwatch = $stopwatch; @@ -55,6 +56,10 @@ public function collect(Request $request, Response $response, \Exception $except public function reset() { $this->data = array(); + + if (null !== $this->stopwatch) { + $this->stopwatch->reset(); + } } /** From 2c9c3d80cf4b5b69453927041b2ed9030a9982c4 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Wed, 11 Oct 2017 09:38:40 +0200 Subject: [PATCH 1069/1099] replace parameters in dummy identity translator --- src/Symfony/Bridge/Twig/Extension/TranslationExtension.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Bridge/Twig/Extension/TranslationExtension.php b/src/Symfony/Bridge/Twig/Extension/TranslationExtension.php index a748e1ed72e7b..01d0f6c6442e3 100644 --- a/src/Symfony/Bridge/Twig/Extension/TranslationExtension.php +++ b/src/Symfony/Bridge/Twig/Extension/TranslationExtension.php @@ -95,7 +95,7 @@ public function getTranslationNodeVisitor() public function trans($message, array $arguments = array(), $domain = null, $locale = null) { if (null === $this->translator) { - return $message; + return strtr($message, $arguments); } return $this->translator->trans($message, $arguments, $domain, $locale); @@ -104,7 +104,7 @@ public function trans($message, array $arguments = array(), $domain = null, $loc public function transchoice($message, $count, array $arguments = array(), $domain = null, $locale = null) { if (null === $this->translator) { - return $message; + return strtr($message, $arguments); } return $this->translator->transChoice($message, $count, array_merge(array('%count%' => $count), $arguments), $domain, $locale); From 5ecafc5e25aa073f6cf109a6b87453689369c4a4 Mon Sep 17 00:00:00 2001 From: Ivo Bathke Date: Mon, 25 Sep 2017 18:15:09 +0200 Subject: [PATCH 1070/1099] added ability to handle parent classes for PropertyNormalizer --- .../Normalizer/PropertyNormalizer.php | 42 +++++++++++++++---- .../Tests/Fixtures/GroupDummyChild.php | 33 +++++++++++++++ .../Normalizer/PropertyNormalizerTest.php | 34 ++++++++++++++- 3 files changed, 99 insertions(+), 10 deletions(-) create mode 100644 src/Symfony/Component/Serializer/Tests/Fixtures/GroupDummyChild.php diff --git a/src/Symfony/Component/Serializer/Normalizer/PropertyNormalizer.php b/src/Symfony/Component/Serializer/Normalizer/PropertyNormalizer.php index 2d96608ff2400..2921e5baf9532 100644 --- a/src/Symfony/Component/Serializer/Normalizer/PropertyNormalizer.php +++ b/src/Symfony/Component/Serializer/Normalizer/PropertyNormalizer.php @@ -79,7 +79,7 @@ protected function isAllowedAttribute($classOrObject, $attribute, $format = null } try { - $reflectionProperty = new \ReflectionProperty(is_string($classOrObject) ? $classOrObject : get_class($classOrObject), $attribute); + $reflectionProperty = $this->getReflectionProperty($classOrObject, $attribute); if ($reflectionProperty->isStatic()) { return false; } @@ -98,13 +98,15 @@ protected function extractAttributes($object, $format = null, array $context = a $reflectionObject = new \ReflectionObject($object); $attributes = array(); - foreach ($reflectionObject->getProperties() as $property) { - if (!$this->isAllowedAttribute($object, $property->name)) { - continue; - } + do { + foreach ($reflectionObject->getProperties() as $property) { + if (!$this->isAllowedAttribute($reflectionObject->getName(), $property->name)) { + continue; + } - $attributes[] = $property->name; - } + $attributes[] = $property->name; + } + } while ($reflectionObject = $reflectionObject->getParentClass()); return $attributes; } @@ -115,7 +117,7 @@ protected function extractAttributes($object, $format = null, array $context = a protected function getAttributeValue($object, $attribute, $format = null, array $context = array()) { try { - $reflectionProperty = new \ReflectionProperty(get_class($object), $attribute); + $reflectionProperty = $this->getReflectionProperty($object, $attribute); } catch (\ReflectionException $reflectionException) { return; } @@ -134,7 +136,7 @@ protected function getAttributeValue($object, $attribute, $format = null, array protected function setAttributeValue($object, $attribute, $value, $format = null, array $context = array()) { try { - $reflectionProperty = new \ReflectionProperty(get_class($object), $attribute); + $reflectionProperty = $this->getReflectionProperty($object, $attribute); } catch (\ReflectionException $reflectionException) { return; } @@ -150,4 +152,26 @@ protected function setAttributeValue($object, $attribute, $value, $format = null $reflectionProperty->setValue($object, $value); } + + /** + * @param string|object $classOrObject + * @param string $attribute + * + * @return \ReflectionProperty + * + * @throws \ReflectionException + */ + private function getReflectionProperty($classOrObject, $attribute) + { + $reflectionClass = new \ReflectionClass($classOrObject); + while (true) { + try { + return $reflectionClass->getProperty($attribute); + } catch (\ReflectionException $e) { + if (!$reflectionClass = $reflectionClass->getParentClass()) { + throw $e; + } + } + } + } } diff --git a/src/Symfony/Component/Serializer/Tests/Fixtures/GroupDummyChild.php b/src/Symfony/Component/Serializer/Tests/Fixtures/GroupDummyChild.php new file mode 100644 index 0000000000000..fa72160ec657f --- /dev/null +++ b/src/Symfony/Component/Serializer/Tests/Fixtures/GroupDummyChild.php @@ -0,0 +1,33 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Serializer\Tests\Fixtures; + +class GroupDummyChild extends GroupDummy +{ + private $baz; + + /** + * @return mixed + */ + public function getBaz() + { + return $this->baz; + } + + /** + * @param mixed $baz + */ + public function setBaz($baz) + { + $this->baz = $baz; + } +} diff --git a/src/Symfony/Component/Serializer/Tests/Normalizer/PropertyNormalizerTest.php b/src/Symfony/Component/Serializer/Tests/Normalizer/PropertyNormalizerTest.php index 73b5f689c1d90..954de0b03e323 100644 --- a/src/Symfony/Component/Serializer/Tests/Normalizer/PropertyNormalizerTest.php +++ b/src/Symfony/Component/Serializer/Tests/Normalizer/PropertyNormalizerTest.php @@ -20,6 +20,7 @@ use Symfony\Component\Serializer\Serializer; use Symfony\Component\Serializer\SerializerInterface; use Symfony\Component\Serializer\Tests\Fixtures\GroupDummy; +use Symfony\Component\Serializer\Tests\Fixtures\GroupDummyChild; use Symfony\Component\Serializer\Tests\Fixtures\MaxDepthDummy; use Symfony\Component\Serializer\Tests\Fixtures\PropertyCircularReferenceDummy; use Symfony\Component\Serializer\Tests\Fixtures\PropertySiblingHolder; @@ -65,6 +66,35 @@ public function testDenormalize() $this->assertEquals('bar', $obj->getBar()); } + public function testNormalizeWithParentClass() + { + $group = new GroupDummyChild(); + $group->setBaz('baz'); + $group->setFoo('foo'); + $group->setBar('bar'); + $group->setKevin('Kevin'); + $group->setCoopTilleuls('coop'); + $this->assertEquals( + array('foo' => 'foo', 'bar' => 'bar', 'kevin' => 'Kevin', + 'coopTilleuls' => 'coop', 'fooBar' => null, 'symfony' => null, 'baz' => 'baz', ), + $this->normalizer->normalize($group, 'any') + ); + } + + public function testDenormalizeWithParentClass() + { + $obj = $this->normalizer->denormalize( + array('foo' => 'foo', 'bar' => 'bar', 'kevin' => 'Kevin', 'baz' => 'baz'), + GroupDummyChild::class, + 'any' + ); + $this->assertEquals('foo', $obj->getFoo()); + $this->assertEquals('bar', $obj->getBar()); + $this->assertEquals('Kevin', $obj->getKevin()); + $this->assertEquals('baz', $obj->getBaz()); + $this->assertNull($obj->getSymfony()); + } + public function testConstructorDenormalize() { $obj = $this->normalizer->denormalize( @@ -147,12 +177,14 @@ public function testGroupsNormalize() 'bar' => 'bar', ), $this->normalizer->normalize($obj, null, array(PropertyNormalizer::GROUPS => array('c')))); - // The PropertyNormalizer is not able to hydrate properties from parent classes + // The PropertyNormalizer is also able to hydrate properties from parent classes $this->assertEquals(array( 'symfony' => 'symfony', 'foo' => 'foo', 'fooBar' => 'fooBar', 'bar' => 'bar', + 'kevin' => 'kevin', + 'coopTilleuls' => 'coopTilleuls', ), $this->normalizer->normalize($obj, null, array(PropertyNormalizer::GROUPS => array('a', 'c')))); } From c6ed0e4f86a0cda30f906237e7032ce978e40b70 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Thu, 12 Oct 2017 09:08:46 +0200 Subject: [PATCH 1071/1099] [Translation] minor: remove unused variable in test --- src/Symfony/Component/Translation/Tests/TranslatorTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/Translation/Tests/TranslatorTest.php b/src/Symfony/Component/Translation/Tests/TranslatorTest.php index 960d8f4d3c549..6047cf7c3c834 100644 --- a/src/Symfony/Component/Translation/Tests/TranslatorTest.php +++ b/src/Symfony/Component/Translation/Tests/TranslatorTest.php @@ -25,7 +25,7 @@ class TranslatorTest extends TestCase */ public function testConstructorInvalidLocale($locale) { - $translator = new Translator($locale, new MessageSelector()); + new Translator($locale, new MessageSelector()); } /** From 345f2fc60e54f2429b6b862a9336edaaadd3a184 Mon Sep 17 00:00:00 2001 From: Artur Eshenbrener Date: Thu, 12 Oct 2017 14:28:41 +0300 Subject: [PATCH 1072/1099] [DI] Fix possible incorrect php-code when dumped strings contains newlines --- .../Component/DependencyInjection/Dumper/PhpDumper.php | 7 +++++++ .../DependencyInjection/Tests/Dumper/PhpDumperTest.php | 1 + .../DependencyInjection/Tests/Fixtures/php/services10.php | 2 +- 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php index 5a0f89c8b4018..01d9ca7192d2f 100644 --- a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php +++ b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php @@ -1574,6 +1574,13 @@ private function export($value) return $dirname; } + if (is_string($value) && false !== strpos($value, "\n")) { + $cleanParts = explode("\n", $value); + $cleanParts = array_map(function ($part) { return var_export($part, true); }, $cleanParts); + + return implode('."\n".', $cleanParts); + } + return var_export($value, true); } } diff --git a/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php b/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php index e238649361a3f..57f8a47a907aa 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php @@ -55,6 +55,7 @@ public function testDumpOptimizationString() 'optimize concatenation with empty string' => 'string1%empty_value%string2', 'optimize concatenation from the start' => '%empty_value%start', 'optimize concatenation at the end' => 'end%empty_value%', + 'new line' => "string with \nnew line", )); $container = new ContainerBuilder(); diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services10.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services10.php index a674eae8b49d3..6538f0ae53dfa 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services10.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services10.php @@ -56,7 +56,7 @@ public function isFrozen() */ protected function getTestService() { - return $this->services['test'] = new \stdClass(array('only dot' => '.', 'concatenation as value' => '.\'\'.', 'concatenation from the start value' => '\'\'.', '.' => 'dot as a key', '.\'\'.' => 'concatenation as a key', '\'\'.' => 'concatenation from the start key', 'optimize concatenation' => 'string1-string2', 'optimize concatenation with empty string' => 'string1string2', 'optimize concatenation from the start' => 'start', 'optimize concatenation at the end' => 'end')); + return $this->services['test'] = new \stdClass(array('only dot' => '.', 'concatenation as value' => '.\'\'.', 'concatenation from the start value' => '\'\'.', '.' => 'dot as a key', '.\'\'.' => 'concatenation as a key', '\'\'.' => 'concatenation from the start key', 'optimize concatenation' => 'string1-string2', 'optimize concatenation with empty string' => 'string1string2', 'optimize concatenation from the start' => 'start', 'optimize concatenation at the end' => 'end', 'new line' => 'string with '."\n".'new line')); } /** From d066a238607e86e882ec8e80786bc722c3f0f9c9 Mon Sep 17 00:00:00 2001 From: Pierre du Plessis Date: Thu, 8 Jun 2017 22:30:26 +0200 Subject: [PATCH 1073/1099] Support array of types in allowed type --- .../Component/OptionsResolver/CHANGELOG.md | 1 + .../OptionsResolver/OptionsResolver.php | 85 +++++++++++++++---- .../Tests/OptionsResolverTest.php | 85 +++++++++++++++++++ 3 files changed, 156 insertions(+), 15 deletions(-) diff --git a/src/Symfony/Component/OptionsResolver/CHANGELOG.md b/src/Symfony/Component/OptionsResolver/CHANGELOG.md index d19116f37c280..c8f0244602195 100644 --- a/src/Symfony/Component/OptionsResolver/CHANGELOG.md +++ b/src/Symfony/Component/OptionsResolver/CHANGELOG.md @@ -5,6 +5,7 @@ CHANGELOG ----- * added `OptionsResolverIntrospector` to inspect options definitions inside an `OptionsResolver` instance + * added array of types support in allowed types (e.g int[]) 2.6.0 ----- diff --git a/src/Symfony/Component/OptionsResolver/OptionsResolver.php b/src/Symfony/Component/OptionsResolver/OptionsResolver.php index 32ac5663fdcb1..fb1ec60980b62 100644 --- a/src/Symfony/Component/OptionsResolver/OptionsResolver.php +++ b/src/Symfony/Component/OptionsResolver/OptionsResolver.php @@ -792,21 +792,12 @@ public function offsetGet($option) // Validate the type of the resolved option if (isset($this->allowedTypes[$option])) { $valid = false; + $invalidTypes = array(); foreach ($this->allowedTypes[$option] as $type) { $type = isset(self::$typeAliases[$type]) ? self::$typeAliases[$type] : $type; - if (function_exists($isFunction = 'is_'.$type)) { - if ($isFunction($value)) { - $valid = true; - break; - } - - continue; - } - - if ($value instanceof $type) { - $valid = true; + if ($valid = $this->verifyTypes($type, $value, $invalidTypes)) { break; } } @@ -818,7 +809,7 @@ public function offsetGet($option) $option, $this->formatValue($value), implode('" or "', $this->allowedTypes[$option]), - $this->formatTypeOf($value) + implode('|', array_keys($invalidTypes)) )); } } @@ -895,6 +886,45 @@ public function offsetGet($option) return $value; } + /** + * @param string $type + * @param mixed $value + * @param array &$invalidTypes + * + * @return bool + */ + private function verifyTypes($type, $value, array &$invalidTypes) + { + if ('[]' === substr($type, -2) && is_array($value)) { + $originalType = $type; + $type = substr($type, 0, -2); + $invalidValues = array_filter( // Filter out valid values, keeping invalid values in the resulting array + $value, + function ($value) use ($type) { + return (function_exists($isFunction = 'is_'.$type) && !$isFunction($value)) || !$value instanceof $type; + } + ); + + if (!$invalidValues) { + return true; + } + + $invalidTypes[$this->formatTypeOf($value, $originalType)] = true; + + return false; + } + + if ((function_exists($isFunction = 'is_'.$type) && $isFunction($value)) || $value instanceof $type) { + return true; + } + + if (!$invalidTypes) { + $invalidTypes[$this->formatTypeOf($value, null)] = true; + } + + return false; + } + /** * Returns whether a resolved option with the given name exists. * @@ -963,13 +993,38 @@ public function count() * parameters should usually not be included in messages aimed at * non-technical people. * - * @param mixed $value The value to return the type of + * @param mixed $value The value to return the type of + * @param string $type * * @return string The type of the value */ - private function formatTypeOf($value) + private function formatTypeOf($value, $type) { - return is_object($value) ? get_class($value) : gettype($value); + $suffix = ''; + + if ('[]' === substr($type, -2)) { + $suffix = '[]'; + $type = substr($type, 0, -2); + while ('[]' === substr($type, -2)) { + $type = substr($type, 0, -2); + $value = array_shift($value); + if (!is_array($value)) { + break; + } + $suffix .= '[]'; + } + + if (is_array($value)) { + $subTypes = array(); + foreach ($value as $val) { + $subTypes[$this->formatTypeOf($val, null)] = true; + } + + return implode('|', array_keys($subTypes)).$suffix; + } + } + + return (is_object($value) ? get_class($value) : gettype($value)).$suffix; } /** diff --git a/src/Symfony/Component/OptionsResolver/Tests/OptionsResolverTest.php b/src/Symfony/Component/OptionsResolver/Tests/OptionsResolverTest.php index d09dece33cc8b..b95e039dc32cf 100644 --- a/src/Symfony/Component/OptionsResolver/Tests/OptionsResolverTest.php +++ b/src/Symfony/Component/OptionsResolver/Tests/OptionsResolverTest.php @@ -500,6 +500,65 @@ public function testFailIfSetAllowedTypesFromLazyOption() $this->resolver->resolve(); } + /** + * @expectedException \Symfony\Component\OptionsResolver\Exception\InvalidOptionsException + * @expectedExceptionMessage The option "foo" with value array is expected to be of type "int[]", but is of type "DateTime[]". + */ + public function testResolveFailsIfInvalidTypedArray() + { + $this->resolver->setDefined('foo'); + $this->resolver->setAllowedTypes('foo', 'int[]'); + + $this->resolver->resolve(array('foo' => array(new \DateTime()))); + } + + /** + * @expectedException \Symfony\Component\OptionsResolver\Exception\InvalidOptionsException + * @expectedExceptionMessage The option "foo" with value "bar" is expected to be of type "int[]", but is of type "string". + */ + public function testResolveFailsWithNonArray() + { + $this->resolver->setDefined('foo'); + $this->resolver->setAllowedTypes('foo', 'int[]'); + + $this->resolver->resolve(array('foo' => 'bar')); + } + + /** + * @expectedException \Symfony\Component\OptionsResolver\Exception\InvalidOptionsException + * @expectedExceptionMessage The option "foo" with value array is expected to be of type "int[]", but is of type "integer|stdClass|array|DateTime[]". + */ + public function testResolveFailsIfTypedArrayContainsInvalidTypes() + { + $this->resolver->setDefined('foo'); + $this->resolver->setAllowedTypes('foo', 'int[]'); + $values = range(1, 5); + $values[] = new \stdClass(); + $values[] = array(); + $values[] = new \DateTime(); + $values[] = 123; + + $this->resolver->resolve(array('foo' => $values)); + } + + /** + * @expectedException \Symfony\Component\OptionsResolver\Exception\InvalidOptionsException + * @expectedExceptionMessage The option "foo" with value array is expected to be of type "int[][]", but is of type "double[][]". + */ + public function testResolveFailsWithCorrectLevelsButWrongScalar() + { + $this->resolver->setDefined('foo'); + $this->resolver->setAllowedTypes('foo', 'int[][]'); + + $this->resolver->resolve( + array( + 'foo' => array( + array(1.2), + ), + ) + ); + } + /** * @dataProvider provideInvalidTypes */ @@ -568,6 +627,32 @@ public function testResolveSucceedsIfInstanceOfClass() $this->assertNotEmpty($this->resolver->resolve()); } + public function testResolveSucceedsIfTypedArray() + { + $this->resolver->setDefault('foo', null); + $this->resolver->setAllowedTypes('foo', array('null', 'DateTime[]')); + + $data = array( + 'foo' => array( + new \DateTime(), + new \DateTime(), + ), + ); + $result = $this->resolver->resolve($data); + $this->assertEquals($data, $result); + } + + /** + * @expectedException \Symfony\Component\OptionsResolver\Exception\InvalidOptionsException + */ + public function testResolveFailsIfNotInstanceOfClass() + { + $this->resolver->setDefault('foo', 'bar'); + $this->resolver->setAllowedTypes('foo', '\stdClass'); + + $this->resolver->resolve(); + } + //////////////////////////////////////////////////////////////////////////// // addAllowedTypes() //////////////////////////////////////////////////////////////////////////// From f15da8075f0f8325d1f680aacf4c013861e4c535 Mon Sep 17 00:00:00 2001 From: den Date: Thu, 12 Oct 2017 20:40:40 +0300 Subject: [PATCH 1074/1099] Fix LogLevel::DEBUG as min level --- src/Symfony/Component/HttpKernel/Log/Logger.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/HttpKernel/Log/Logger.php b/src/Symfony/Component/HttpKernel/Log/Logger.php index c43936ed40943..8facb03c5a29d 100644 --- a/src/Symfony/Component/HttpKernel/Log/Logger.php +++ b/src/Symfony/Component/HttpKernel/Log/Logger.php @@ -39,7 +39,7 @@ class Logger extends AbstractLogger public function __construct($minLevel = null, $output = 'php://stderr', callable $formatter = null) { - if (!$minLevel) { + if (null === $minLevel) { $minLevel = LogLevel::WARNING; if (isset($_SERVER['SHELL_VERBOSITY'])) { From 9efb76572ae71d3bee17efeb39f0451760bf31db Mon Sep 17 00:00:00 2001 From: loru88 Date: Wed, 11 Oct 2017 16:39:25 +0200 Subject: [PATCH 1075/1099] [Validator] added magic method __isset() to File Constraint class --- src/Symfony/Component/Validator/Constraints/File.php | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/Symfony/Component/Validator/Constraints/File.php b/src/Symfony/Component/Validator/Constraints/File.php index 7756978b35216..54e7351562c9d 100644 --- a/src/Symfony/Component/Validator/Constraints/File.php +++ b/src/Symfony/Component/Validator/Constraints/File.php @@ -88,6 +88,15 @@ public function __get($option) return parent::__get($option); } + public function __isset($option) + { + if ('maxSize' === $option) { + return true; + } + + return parent::__isset($option); + } + private function normalizeBinaryFormat($maxSize) { $sizeInt = (int) $maxSize; From e0d8ce4403ec8c2d1089189800c288f82ae6fcd8 Mon Sep 17 00:00:00 2001 From: den Date: Thu, 12 Oct 2017 20:40:40 +0300 Subject: [PATCH 1076/1099] Fix LogLevel::DEBUG as min level --- src/Symfony/Component/HttpKernel/Log/Logger.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/HttpKernel/Log/Logger.php b/src/Symfony/Component/HttpKernel/Log/Logger.php index c43936ed40943..8facb03c5a29d 100644 --- a/src/Symfony/Component/HttpKernel/Log/Logger.php +++ b/src/Symfony/Component/HttpKernel/Log/Logger.php @@ -39,7 +39,7 @@ class Logger extends AbstractLogger public function __construct($minLevel = null, $output = 'php://stderr', callable $formatter = null) { - if (!$minLevel) { + if (null === $minLevel) { $minLevel = LogLevel::WARNING; if (isset($_SERVER['SHELL_VERBOSITY'])) { From ff379efb59de25bcdb88225f7389013fecf54b17 Mon Sep 17 00:00:00 2001 From: Paul Mitchum Date: Fri, 2 Jun 2017 12:44:10 -0700 Subject: [PATCH 1077/1099] [Bridge\PhpUnit] Handle deprecations triggered in separate processes --- .../PhpUnit/DeprecationErrorHandler.php | 14 +++++ .../Legacy/SymfonyTestsListenerTrait.php | 59 ++++++++++++++----- .../PhpUnit/Tests/ProcessIsolationTest.php | 23 ++++++++ src/Symfony/Bridge/PhpUnit/bootstrap.php | 4 ++ 4 files changed, 86 insertions(+), 14 deletions(-) create mode 100644 src/Symfony/Bridge/PhpUnit/Tests/ProcessIsolationTest.php diff --git a/src/Symfony/Bridge/PhpUnit/DeprecationErrorHandler.php b/src/Symfony/Bridge/PhpUnit/DeprecationErrorHandler.php index 0f54a52bb8cab..a7dbc08e0c6c2 100644 --- a/src/Symfony/Bridge/PhpUnit/DeprecationErrorHandler.php +++ b/src/Symfony/Bridge/PhpUnit/DeprecationErrorHandler.php @@ -238,6 +238,20 @@ public static function register($mode = 0) } } + public static function collectDeprecations($outputFile) + { + $deprecations = array(); + $previousErrorHandler = set_error_handler(function ($type, $msg, $file, $line, $context = array()) use (&$deprecations, &$previousErrorHandler) { + if (E_USER_DEPRECATED !== $type && E_DEPRECATED !== $type) { + return $previousErrorHandler ? $previousErrorHandler($type, $msg, $file, $line, $context) : false; + } + $deprecations[] = array(error_reporting(), $msg); + }); + register_shutdown_function(function () use ($outputFile, &$deprecations) { + file_put_contents($outputFile, serialize($deprecations)); + }); + } + private static function hasColorSupport() { if ('\\' === DIRECTORY_SEPARATOR) { diff --git a/src/Symfony/Bridge/PhpUnit/Legacy/SymfonyTestsListenerTrait.php b/src/Symfony/Bridge/PhpUnit/Legacy/SymfonyTestsListenerTrait.php index b561c8f2f53a5..166c44a3f8f2c 100644 --- a/src/Symfony/Bridge/PhpUnit/Legacy/SymfonyTestsListenerTrait.php +++ b/src/Symfony/Bridge/PhpUnit/Legacy/SymfonyTestsListenerTrait.php @@ -39,6 +39,7 @@ class SymfonyTestsListenerTrait private $testsWithWarnings; private $reportUselessTests; private $error; + private $runsInSeparateProcess = false; /** * @param array $mockedNamespaces List of namespaces, indexed by mocked features (time-sensitive or dns-sensitive) @@ -183,6 +184,12 @@ public function startTest($test) $this->reportUselessTests = $test->getTestResultObject()->isStrictAboutTestsThatDoNotTestAnything(); } + // This event is triggered before the test is re-run in isolation + if ($this->willBeIsolated($test)) { + $this->runsInSeparateProcess = tempnam(sys_get_temp_dir(), 'deprec'); + putenv('SYMFONY_DEPRECATIONS_SERIALIZE='.$this->runsInSeparateProcess); + } + if (class_exists('PHPUnit_Util_Blacklist', false)) { $Test = 'PHPUnit_Util_Test'; $AssertionFailedError = 'PHPUnit_Framework_AssertionFailedError'; @@ -192,12 +199,14 @@ public function startTest($test) } $groups = $Test::getGroups(get_class($test), $test->getName(false)); - if (in_array('time-sensitive', $groups, true)) { - ClockMock::register(get_class($test)); - ClockMock::withClockMock(true); - } - if (in_array('dns-sensitive', $groups, true)) { - DnsMock::register(get_class($test)); + if (!$this->runsInSeparateProcess) { + if (in_array('time-sensitive', $groups, true)) { + ClockMock::register(get_class($test)); + ClockMock::withClockMock(true); + } + if (in_array('dns-sensitive', $groups, true)) { + DnsMock::register(get_class($test)); + } } $annotations = $Test::parseTestMethodAnnotations(get_class($test), $test->getName(false)); @@ -245,15 +254,20 @@ public function endTest($test, $time) $this->reportUselessTests = null; } - $errored = false; + if ($errored = null !== $this->error) { + $test->getTestResultObject()->addError($test, $this->error, 0); + $this->error = null; + } - if (null !== $this->error) { - if ($BaseTestRunner::STATUS_PASSED === $test->getStatus()) { - $test->getTestResultObject()->addError($test, $this->error, 0); - $errored = true; + if ($this->runsInSeparateProcess) { + foreach (unserialize(file_get_contents($this->runsInSeparateProcess)) as $deprecation) { + if ($deprecation[0]) { + trigger_error($deprecation[1], E_USER_DEPRECATED); + } else { + @trigger_error($deprecation[1], E_USER_DEPRECATED); + } } - - $this->error = null; + $this->runsInSeparateProcess = false; } if ($this->expectedDeprecations) { @@ -277,7 +291,7 @@ public function endTest($test, $time) $this->expectedDeprecations = $this->gatheredDeprecations = array(); $this->previousErrorHandler = null; } - if (-2 < $this->state && ($test instanceof \PHPUnit_Framework_TestCase || $test instanceof TestCase)) { + if (!$this->runsInSeparateProcess && -2 < $this->state && ($test instanceof \PHPUnit_Framework_TestCase || $test instanceof TestCase)) { if (in_array('time-sensitive', $groups, true)) { ClockMock::withClockMock(false); } @@ -315,4 +329,21 @@ public function handleError($type, $msg, $file, $line, $context = array()) } $this->gatheredDeprecations[] = $msg; } + + /** + * @param Test $test + * + * @return bool + */ + private function willBeIsolated($test) + { + if ($test->isInIsolation()) { + return false; + } + + $r = new \ReflectionProperty($test, 'runTestInSeparateProcess'); + $r->setAccessible(true); + + return $r->getValue($test); + } } diff --git a/src/Symfony/Bridge/PhpUnit/Tests/ProcessIsolationTest.php b/src/Symfony/Bridge/PhpUnit/Tests/ProcessIsolationTest.php new file mode 100644 index 0000000000000..d8677097e5c26 --- /dev/null +++ b/src/Symfony/Bridge/PhpUnit/Tests/ProcessIsolationTest.php @@ -0,0 +1,23 @@ + Date: Fri, 13 Oct 2017 15:21:24 +0200 Subject: [PATCH 1078/1099] [BrowserKit] Handle deprecations triggered in insulated requests --- src/Symfony/Component/BrowserKit/Client.php | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/Symfony/Component/BrowserKit/Client.php b/src/Symfony/Component/BrowserKit/Client.php index 2f2b08d81894d..fb7a254e2c56d 100644 --- a/src/Symfony/Component/BrowserKit/Client.php +++ b/src/Symfony/Component/BrowserKit/Client.php @@ -343,9 +343,23 @@ public function request($method, $uri, array $parameters = array(), array $files */ protected function doRequestInProcess($request) { + $deprecationsFile = tempnam(sys_get_temp_dir(), 'deprec'); + putenv('SYMFONY_DEPRECATIONS_SERIALIZE='.$deprecationsFile); $process = new PhpProcess($this->getScript($request), null, null); $process->run(); + if (file_exists($deprecationsFile)) { + $deprecations = file_get_contents($deprecationsFile); + unlink($deprecationsFile); + foreach ($deprecations ? unserialize($deprecations) : array() as $deprecation) { + if ($deprecation[0]) { + trigger_error($deprecation[1], E_USER_DEPRECATED); + } else { + @trigger_error($deprecation[1], E_USER_DEPRECATED); + } + } + } + if (!$process->isSuccessful() || !preg_match('/^O\:\d+\:/', $process->getOutput())) { throw new \RuntimeException(sprintf('OUTPUT: %s ERROR OUTPUT: %s', $process->getOutput(), $process->getErrorOutput())); } From ee70361e53eabf3ca86ab1de28506bd7af5e608b Mon Sep 17 00:00:00 2001 From: Yonel Ceruto Date: Thu, 12 Oct 2017 18:51:51 -0400 Subject: [PATCH 1079/1099] [Form] Fix 5.5 compatibility for ResizeFormListener --- .../Core/EventListener/ResizeFormListener.php | 4 +- .../EventListener/ResizeFormListenerTest.php | 47 +++++++++++++++++++ 2 files changed, 49 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/Form/Extension/Core/EventListener/ResizeFormListener.php b/src/Symfony/Component/Form/Extension/Core/EventListener/ResizeFormListener.php index 402a1f07253ed..8ce2d2e0655d5 100644 --- a/src/Symfony/Component/Form/Extension/Core/EventListener/ResizeFormListener.php +++ b/src/Symfony/Component/Form/Extension/Core/EventListener/ResizeFormListener.php @@ -149,12 +149,12 @@ public function onSubmit(FormEvent $event) throw new UnexpectedTypeException($data, 'array or (\Traversable and \ArrayAccess)'); } - if ($entryFilter = $this->deleteEmpty) { + if ($this->deleteEmpty) { $previousData = $form->getData(); /** @var FormInterface $child */ foreach ($form as $name => $child) { $isNew = !isset($previousData[$name]); - $isEmpty = is_callable($entryFilter) ? $entryFilter($child->getData()) : $child->isEmpty(); + $isEmpty = is_callable($this->deleteEmpty) ? call_user_func($this->deleteEmpty, $child->getData()) : $child->isEmpty(); // $isNew can only be true if allowAdd is true, so we don't // need to check allowAdd again diff --git a/src/Symfony/Component/Form/Tests/Extension/Core/EventListener/ResizeFormListenerTest.php b/src/Symfony/Component/Form/Tests/Extension/Core/EventListener/ResizeFormListenerTest.php index 281581bcffc1c..017c1bdc040c9 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Core/EventListener/ResizeFormListenerTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Core/EventListener/ResizeFormListenerTest.php @@ -275,4 +275,51 @@ public function testOnSubmitDealsWithArrayBackedIteratorAggregate() $this->assertArrayNotHasKey(0, $event->getData()); $this->assertArrayNotHasKey(2, $event->getData()); } + + public function testOnSubmitDeleteEmptyNotCompoundEntriesIfAllowDelete() + { + $this->form->setData(array('0' => 'first', '1' => 'second')); + $this->form->add($this->getForm('0')); + $this->form->add($this->getForm('1')); + + $data = array(0 => 'first', 1 => ''); + foreach ($data as $child => $dat) { + $this->form->get($child)->setData($dat); + } + $event = new FormEvent($this->form, $data); + $listener = new ResizeFormListener('text', array(), false, true, true); + $listener->onSubmit($event); + + $this->assertEquals(array(0 => 'first'), $event->getData()); + } + + public function testOnSubmitDeleteEmptyCompoundEntriesIfAllowDelete() + { + $this->form->setData(array('0' => array('name' => 'John'), '1' => array('name' => 'Jane'))); + $form1 = $this->getBuilder('0') + ->setCompound(true) + ->setDataMapper($this->getDataMapper()) + ->getForm(); + $form1->add($this->getForm('name')); + $form2 = $this->getBuilder('1') + ->setCompound(true) + ->setDataMapper($this->getDataMapper()) + ->getForm(); + $form2->add($this->getForm('name')); + $this->form->add($form1); + $this->form->add($form2); + + $data = array('0' => array('name' => 'John'), '1' => array('name' => '')); + foreach ($data as $child => $dat) { + $this->form->get($child)->setData($dat); + } + $event = new FormEvent($this->form, $data); + $callback = function ($data) { + return '' === $data['name']; + }; + $listener = new ResizeFormListener('text', array(), false, true, $callback); + $listener->onSubmit($event); + + $this->assertEquals(array('0' => array('name' => 'John')), $event->getData()); + } } From 4a2f608f1efeeab84086c70d846799a3db6b60f8 Mon Sep 17 00:00:00 2001 From: David Maicher Date: Thu, 12 Oct 2017 14:26:49 +0200 Subject: [PATCH 1080/1099] [TwigBridge] fix BC for FormExtension if renderer is FormRenderer --- .../Bridge/Twig/Extension/FormExtension.php | 4 +- .../Tests/Extension/FormExtensionTest.php | 76 +++++++++++++++++++ src/Symfony/Bridge/Twig/composer.json | 1 + 3 files changed, 79 insertions(+), 2 deletions(-) create mode 100644 src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionTest.php diff --git a/src/Symfony/Bridge/Twig/Extension/FormExtension.php b/src/Symfony/Bridge/Twig/Extension/FormExtension.php index 945cd0bc37b1a..d21601af76e7f 100644 --- a/src/Symfony/Bridge/Twig/Extension/FormExtension.php +++ b/src/Symfony/Bridge/Twig/Extension/FormExtension.php @@ -54,7 +54,7 @@ public function initRuntime(Environment $environment) { if ($this->renderer instanceof TwigRendererInterface) { $this->renderer->setEnvironment($environment); - } elseif (null !== $this->renderer) { + } elseif (is_array($this->renderer)) { $this->renderer[2] = $environment; } } @@ -118,7 +118,7 @@ public function __get($name) if (is_array($this->renderer)) { $renderer = $this->renderer[0]->get($this->renderer[1]); - if (isset($this->renderer[2])) { + if (isset($this->renderer[2]) && $renderer instanceof TwigRendererInterface) { $renderer->setEnvironment($this->renderer[2]); } $this->renderer = $renderer; diff --git a/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionTest.php b/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionTest.php new file mode 100644 index 0000000000000..a4d7350716e64 --- /dev/null +++ b/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionTest.php @@ -0,0 +1,76 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bridge\Twig\Tests\Extension; + +use PHPUnit\Framework\TestCase; +use Symfony\Bridge\Twig\Extension\FormExtension; +use Symfony\Bridge\Twig\Form\TwigRendererInterface; +use Symfony\Component\DependencyInjection\ContainerInterface; +use Symfony\Component\Form\FormRendererInterface; +use Twig\Environment; + +/** + * @group legacy + */ +class FormExtensionTest extends TestCase +{ + /** + * @dataProvider rendererDataProvider + */ + public function testInitRuntimeAndAccessRenderer($rendererConstructor, $expectedAccessedRenderer) + { + $extension = new FormExtension($rendererConstructor); + $extension->initRuntime($this->getMockBuilder(Environment::class)->disableOriginalConstructor()->getMock()); + $this->assertSame($expectedAccessedRenderer, $extension->renderer); + } + + /** + * @dataProvider rendererDataProvider + */ + public function testAccessRendererAndInitRuntime($rendererConstructor, $expectedAccessedRenderer) + { + $extension = new FormExtension($rendererConstructor); + $this->assertSame($expectedAccessedRenderer, $extension->renderer); + $extension->initRuntime($this->getMockBuilder(Environment::class)->disableOriginalConstructor()->getMock()); + } + + public function rendererDataProvider() + { + $twigRenderer = $this->getMockBuilder(TwigRendererInterface::class)->getMock(); + $twigRenderer->expects($this->once()) + ->method('setEnvironment'); + + yield array($twigRenderer, $twigRenderer); + + $twigRenderer = $this->getMockBuilder(TwigRendererInterface::class)->getMock(); + $twigRenderer->expects($this->once()) + ->method('setEnvironment'); + + $container = $this->getMockBuilder(ContainerInterface::class)->getMock(); + $container->expects($this->once()) + ->method('get') + ->with('service_id') + ->willReturn($twigRenderer); + + yield array(array($container, 'service_id'), $twigRenderer); + + $formRenderer = $this->getMockBuilder(FormRendererInterface::class)->getMock(); + + $container = $this->getMockBuilder(ContainerInterface::class)->getMock(); + $container->expects($this->once()) + ->method('get') + ->with('service_id') + ->willReturn($formRenderer); + + yield array(array($container, 'service_id'), $formRenderer); + } +} diff --git a/src/Symfony/Bridge/Twig/composer.json b/src/Symfony/Bridge/Twig/composer.json index e7e7e4889fc23..33ac7d5849c7c 100644 --- a/src/Symfony/Bridge/Twig/composer.json +++ b/src/Symfony/Bridge/Twig/composer.json @@ -22,6 +22,7 @@ "require-dev": { "fig/link-util": "^1.0", "symfony/asset": "~2.8|~3.0|~4.0", + "symfony/dependency-injection": "~2.8|~3.0|~4.0", "symfony/finder": "~2.8|~3.0|~4.0", "symfony/form": "~3.4|~4.0", "symfony/http-foundation": "^3.3.11|~4.0", From 2f5a0bd72f8f606230aac3920ed810f206884ad9 Mon Sep 17 00:00:00 2001 From: Christian Flothmann Date: Fri, 13 Oct 2017 16:04:01 +0200 Subject: [PATCH 1081/1099] fix serialized deprecations handling --- .../Bridge/PhpUnit/Legacy/SymfonyTestsListenerTrait.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Bridge/PhpUnit/Legacy/SymfonyTestsListenerTrait.php b/src/Symfony/Bridge/PhpUnit/Legacy/SymfonyTestsListenerTrait.php index 166c44a3f8f2c..4d9b48dfc7e56 100644 --- a/src/Symfony/Bridge/PhpUnit/Legacy/SymfonyTestsListenerTrait.php +++ b/src/Symfony/Bridge/PhpUnit/Legacy/SymfonyTestsListenerTrait.php @@ -260,7 +260,9 @@ public function endTest($test, $time) } if ($this->runsInSeparateProcess) { - foreach (unserialize(file_get_contents($this->runsInSeparateProcess)) as $deprecation) { + $deprecations = file_get_contents($this->runsInSeparateProcess); + unlink($this->runsInSeparateProcess); + foreach ($deprecations ? unserialize($deprecations) : array() as $deprecation) { if ($deprecation[0]) { trigger_error($deprecation[1], E_USER_DEPRECATED); } else { From e0681f99552cab9c8035efd54c5f6496d918c22f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Edi=20Modri=C4=87?= Date: Tue, 2 May 2017 12:14:20 +0200 Subject: [PATCH 1082/1099] [Form] [TwigBridge] Added option to disable usage of default themes when rendering a form --- src/Symfony/Bridge/Twig/CHANGELOG.md | 1 + .../Bridge/Twig/Form/TwigRendererEngine.php | 8 +++--- .../Bridge/Twig/Node/FormThemeNode.php | 6 +++-- ...xtensionBootstrap3HorizontalLayoutTest.php | 4 +-- .../FormExtensionBootstrap3LayoutTest.php | 4 +-- ...xtensionBootstrap4HorizontalLayoutTest.php | 4 +-- .../FormExtensionBootstrap4LayoutTest.php | 4 +-- .../Extension/FormExtensionDivLayoutTest.php | 4 +-- .../FormExtensionTableLayoutTest.php | 4 +-- .../Bridge/Twig/Tests/Node/FormThemeTest.php | 25 +++++++++++++++++-- .../TokenParser/FormThemeTokenParserTest.php | 15 +++++++++++ .../Twig/TokenParser/FormThemeTokenParser.php | 7 +++++- .../Templating/Helper/FormHelper.php | 9 ++++--- .../Helper/FormHelperDivLayoutTest.php | 4 +-- .../Helper/FormHelperTableLayoutTest.php | 4 +-- .../Component/Form/AbstractRendererEngine.php | 10 +++++++- src/Symfony/Component/Form/CHANGELOG.md | 2 ++ .../Templating/TemplatingRendererEngine.php | 8 +++--- src/Symfony/Component/Form/FormRenderer.php | 5 ++-- .../Form/FormRendererEngineInterface.php | 10 +++++--- .../Component/Form/FormRendererInterface.php | 10 +++++--- .../Form/Tests/AbstractLayoutTest.php | 2 +- 22 files changed, 107 insertions(+), 43 deletions(-) diff --git a/src/Symfony/Bridge/Twig/CHANGELOG.md b/src/Symfony/Bridge/Twig/CHANGELOG.md index 397134150c318..8d5d6f56b6771 100644 --- a/src/Symfony/Bridge/Twig/CHANGELOG.md +++ b/src/Symfony/Bridge/Twig/CHANGELOG.md @@ -4,6 +4,7 @@ CHANGELOG 3.4.0 ----- + * added an `only` keyword to `form_theme` tag to disable usage of default themes when rendering a form * deprecated `Symfony\Bridge\Twig\Form\TwigRenderer` * deprecated `DebugCommand::set/getTwigEnvironment`. Pass an instance of `Twig\Environment` as first argument of the constructor instead diff --git a/src/Symfony/Bridge/Twig/Form/TwigRendererEngine.php b/src/Symfony/Bridge/Twig/Form/TwigRendererEngine.php index 7e375f45e2996..59120ee552d78 100644 --- a/src/Symfony/Bridge/Twig/Form/TwigRendererEngine.php +++ b/src/Symfony/Bridge/Twig/Form/TwigRendererEngine.php @@ -124,9 +124,11 @@ protected function loadResourceForBlockName($cacheKey, FormView $view, $blockNam // Check the default themes once we reach the root view without success if (!$view->parent) { - for ($i = count($this->defaultThemes) - 1; $i >= 0; --$i) { - $this->loadResourcesFromTheme($cacheKey, $this->defaultThemes[$i]); - // CONTINUE LOADING (see doc comment) + if (!isset($this->useDefaultThemes[$cacheKey]) || $this->useDefaultThemes[$cacheKey]) { + for ($i = count($this->defaultThemes) - 1; $i >= 0; --$i) { + $this->loadResourcesFromTheme($cacheKey, $this->defaultThemes[$i]); + // CONTINUE LOADING (see doc comment) + } } } diff --git a/src/Symfony/Bridge/Twig/Node/FormThemeNode.php b/src/Symfony/Bridge/Twig/Node/FormThemeNode.php index a66a13adc0287..8fcd9380a620a 100644 --- a/src/Symfony/Bridge/Twig/Node/FormThemeNode.php +++ b/src/Symfony/Bridge/Twig/Node/FormThemeNode.php @@ -22,9 +22,9 @@ */ class FormThemeNode extends Node { - public function __construct(Node $form, Node $resources, $lineno, $tag = null) + public function __construct(Node $form, Node $resources, $lineno, $tag = null, $only = false) { - parent::__construct(array('form' => $form, 'resources' => $resources), array(), $lineno, $tag); + parent::__construct(array('form' => $form, 'resources' => $resources), array('only' => (bool) $only), $lineno, $tag); } public function compile(Compiler $compiler) @@ -44,6 +44,8 @@ public function compile(Compiler $compiler) ->subcompile($this->getNode('form')) ->raw(', ') ->subcompile($this->getNode('resources')) + ->raw(', ') + ->raw(false === $this->getAttribute('only') ? 'true' : 'false') ->raw(");\n"); } } diff --git a/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionBootstrap3HorizontalLayoutTest.php b/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionBootstrap3HorizontalLayoutTest.php index 5625b09411ff6..e5ee8903efe4a 100644 --- a/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionBootstrap3HorizontalLayoutTest.php +++ b/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionBootstrap3HorizontalLayoutTest.php @@ -99,8 +99,8 @@ protected function renderEnd(FormView $view, array $vars = array()) return (string) $this->renderer->renderBlock($view, 'form_end', $vars); } - protected function setTheme(FormView $view, array $themes) + protected function setTheme(FormView $view, array $themes, $useDefaultThemes = true) { - $this->renderer->setTheme($view, $themes); + $this->renderer->setTheme($view, $themes, $useDefaultThemes); } } diff --git a/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionBootstrap3LayoutTest.php b/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionBootstrap3LayoutTest.php index 68f42a411a576..5e872b83eb67d 100644 --- a/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionBootstrap3LayoutTest.php +++ b/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionBootstrap3LayoutTest.php @@ -119,8 +119,8 @@ protected function renderEnd(FormView $view, array $vars = array()) return (string) $this->renderer->renderBlock($view, 'form_end', $vars); } - protected function setTheme(FormView $view, array $themes) + protected function setTheme(FormView $view, array $themes, $useDefaultThemes = true) { - $this->renderer->setTheme($view, $themes); + $this->renderer->setTheme($view, $themes, $useDefaultThemes); } } diff --git a/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionBootstrap4HorizontalLayoutTest.php b/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionBootstrap4HorizontalLayoutTest.php index d7afc2cf26238..063edd889aed4 100644 --- a/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionBootstrap4HorizontalLayoutTest.php +++ b/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionBootstrap4HorizontalLayoutTest.php @@ -100,8 +100,8 @@ protected function renderEnd(FormView $view, array $vars = array()) return (string) $this->renderer->renderBlock($view, 'form_end', $vars); } - protected function setTheme(FormView $view, array $themes) + protected function setTheme(FormView $view, array $themes, $useDefaultThemes = true) { - $this->renderer->setTheme($view, $themes); + $this->renderer->setTheme($view, $themes, $useDefaultThemes); } } diff --git a/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionBootstrap4LayoutTest.php b/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionBootstrap4LayoutTest.php index 0dfa1ebadbe39..d3822ee77796a 100644 --- a/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionBootstrap4LayoutTest.php +++ b/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionBootstrap4LayoutTest.php @@ -122,8 +122,8 @@ protected function renderEnd(FormView $view, array $vars = array()) return (string) $this->renderer->renderBlock($view, 'form_end', $vars); } - protected function setTheme(FormView $view, array $themes) + protected function setTheme(FormView $view, array $themes, $useDefaultThemes = true) { - $this->renderer->setTheme($view, $themes); + $this->renderer->setTheme($view, $themes, $useDefaultThemes); } } diff --git a/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionDivLayoutTest.php b/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionDivLayoutTest.php index f65cdea0253c8..75d6f1e0504b8 100644 --- a/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionDivLayoutTest.php +++ b/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionDivLayoutTest.php @@ -193,9 +193,9 @@ protected function renderEnd(FormView $view, array $vars = array()) return (string) $this->renderer->renderBlock($view, 'form_end', $vars); } - protected function setTheme(FormView $view, array $themes) + protected function setTheme(FormView $view, array $themes, $useDefaultThemes = true) { - $this->renderer->setTheme($view, $themes); + $this->renderer->setTheme($view, $themes, $useDefaultThemes); } public static function themeBlockInheritanceProvider() diff --git a/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionTableLayoutTest.php b/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionTableLayoutTest.php index 594084787fff2..5119480d90e4c 100644 --- a/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionTableLayoutTest.php +++ b/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionTableLayoutTest.php @@ -120,8 +120,8 @@ protected function renderEnd(FormView $view, array $vars = array()) return (string) $this->renderer->renderBlock($view, 'form_end', $vars); } - protected function setTheme(FormView $view, array $themes) + protected function setTheme(FormView $view, array $themes, $useDefaultThemes = true) { - $this->renderer->setTheme($view, $themes); + $this->renderer->setTheme($view, $themes, $useDefaultThemes); } } diff --git a/src/Symfony/Bridge/Twig/Tests/Node/FormThemeTest.php b/src/Symfony/Bridge/Twig/Tests/Node/FormThemeTest.php index 05d6507fd7438..7ad445f02e6e5 100644 --- a/src/Symfony/Bridge/Twig/Tests/Node/FormThemeTest.php +++ b/src/Symfony/Bridge/Twig/Tests/Node/FormThemeTest.php @@ -39,6 +39,7 @@ public function testConstructor() $this->assertEquals($form, $node->getNode('form')); $this->assertEquals($resources, $node->getNode('resources')); + $this->assertFalse($node->getAttribute('only')); } public function testCompile() @@ -60,7 +61,17 @@ public function testCompile() $this->assertEquals( sprintf( - '$this->env->getRuntime("Symfony\\\\Component\\\\Form\\\\FormRenderer")->setTheme(%s, array(0 => "tpl1", 1 => "tpl2"));', + '$this->env->getRuntime("Symfony\\\\Component\\\\Form\\\\FormRenderer")->setTheme(%s, array(0 => "tpl1", 1 => "tpl2"), true);', + $this->getVariableGetter('form') + ), + trim($compiler->compile($node)->getSource()) + ); + + $node = new FormThemeNode($form, $resources, 0, null, true); + + $this->assertEquals( + sprintf( + '$this->env->getRuntime("Symfony\\\\Component\\\\Form\\\\FormRenderer")->setTheme(%s, array(0 => "tpl1", 1 => "tpl2"), false);', $this->getVariableGetter('form') ), trim($compiler->compile($node)->getSource()) @@ -72,7 +83,17 @@ public function testCompile() $this->assertEquals( sprintf( - '$this->env->getRuntime("Symfony\\\\Component\\\\Form\\\\FormRenderer")->setTheme(%s, "tpl1");', + '$this->env->getRuntime("Symfony\\\\Component\\\\Form\\\\FormRenderer")->setTheme(%s, "tpl1", true);', + $this->getVariableGetter('form') + ), + trim($compiler->compile($node)->getSource()) + ); + + $node = new FormThemeNode($form, $resources, 0, null, true); + + $this->assertEquals( + sprintf( + '$this->env->getRuntime("Symfony\\\\Component\\\\Form\\\\FormRenderer")->setTheme(%s, "tpl1", false);', $this->getVariableGetter('form') ), trim($compiler->compile($node)->getSource()) diff --git a/src/Symfony/Bridge/Twig/Tests/TokenParser/FormThemeTokenParserTest.php b/src/Symfony/Bridge/Twig/Tests/TokenParser/FormThemeTokenParserTest.php index 0972b15e23fdc..cd9a34cab67b9 100644 --- a/src/Symfony/Bridge/Twig/Tests/TokenParser/FormThemeTokenParserTest.php +++ b/src/Symfony/Bridge/Twig/Tests/TokenParser/FormThemeTokenParserTest.php @@ -100,6 +100,21 @@ public function getTestsForFormTheme() 'form_theme' ), ), + array( + '{% form_theme form with ["tpl1", "tpl2"] only %}', + new FormThemeNode( + new NameExpression('form', 1), + new ArrayExpression(array( + new ConstantExpression(0, 1), + new ConstantExpression('tpl1', 1), + new ConstantExpression(1, 1), + new ConstantExpression('tpl2', 1), + ), 1), + 1, + 'form_theme', + true + ), + ), ); } } diff --git a/src/Symfony/Bridge/Twig/TokenParser/FormThemeTokenParser.php b/src/Symfony/Bridge/Twig/TokenParser/FormThemeTokenParser.php index 12c2541851e63..3ead804e7e6ca 100644 --- a/src/Symfony/Bridge/Twig/TokenParser/FormThemeTokenParser.php +++ b/src/Symfony/Bridge/Twig/TokenParser/FormThemeTokenParser.php @@ -37,10 +37,15 @@ public function parse(Token $token) $stream = $this->parser->getStream(); $form = $this->parser->getExpressionParser()->parseExpression(); + $only = false; if ($this->parser->getStream()->test(Token::NAME_TYPE, 'with')) { $this->parser->getStream()->next(); $resources = $this->parser->getExpressionParser()->parseExpression(); + + if ($this->parser->getStream()->nextIf(Token::NAME_TYPE, 'only')) { + $only = true; + } } else { $resources = new ArrayExpression(array(), $stream->getCurrent()->getLine()); do { @@ -50,7 +55,7 @@ public function parse(Token $token) $stream->expect(Token::BLOCK_END_TYPE); - return new FormThemeNode($form, $resources, $lineno, $this->getTag()); + return new FormThemeNode($form, $resources, $lineno, $this->getTag(), $only); } /** diff --git a/src/Symfony/Bundle/FrameworkBundle/Templating/Helper/FormHelper.php b/src/Symfony/Bundle/FrameworkBundle/Templating/Helper/FormHelper.php index 7c695d8df3b09..f7c2b2c6986bb 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Templating/Helper/FormHelper.php +++ b/src/Symfony/Bundle/FrameworkBundle/Templating/Helper/FormHelper.php @@ -49,12 +49,13 @@ public function getName() * * The theme format is ":". * - * @param FormView $view A FormView instance - * @param string|array $themes A theme or an array of theme + * @param FormView $view A FormView instance + * @param string|array $themes A theme or an array of theme + * @param bool $useDefaultThemes If true, will use default themes defined in the renderer */ - public function setTheme(FormView $view, $themes) + public function setTheme(FormView $view, $themes, $useDefaultThemes = true) { - $this->renderer->setTheme($view, $themes); + $this->renderer->setTheme($view, $themes, $useDefaultThemes); } /** diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Templating/Helper/FormHelperDivLayoutTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Templating/Helper/FormHelperDivLayoutTest.php index 74bdd81604d4e..b86d54b78cdb4 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Templating/Helper/FormHelperDivLayoutTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Templating/Helper/FormHelperDivLayoutTest.php @@ -121,9 +121,9 @@ protected function renderEnd(FormView $view, array $vars = array()) return (string) $this->engine->get('form')->end($view, $vars); } - protected function setTheme(FormView $view, array $themes) + protected function setTheme(FormView $view, array $themes, $useDefaultThemes = true) { - $this->engine->get('form')->setTheme($view, $themes); + $this->engine->get('form')->setTheme($view, $themes, $useDefaultThemes); } public static function themeBlockInheritanceProvider() diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Templating/Helper/FormHelperTableLayoutTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Templating/Helper/FormHelperTableLayoutTest.php index 1e67134c8cb27..8dd6fffa79f41 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Templating/Helper/FormHelperTableLayoutTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Templating/Helper/FormHelperTableLayoutTest.php @@ -122,8 +122,8 @@ protected function renderEnd(FormView $view, array $vars = array()) return (string) $this->engine->get('form')->end($view, $vars); } - protected function setTheme(FormView $view, array $themes) + protected function setTheme(FormView $view, array $themes, $useDefaultThemes = true) { - $this->engine->get('form')->setTheme($view, $themes); + $this->engine->get('form')->setTheme($view, $themes, $useDefaultThemes); } } diff --git a/src/Symfony/Component/Form/AbstractRendererEngine.php b/src/Symfony/Component/Form/AbstractRendererEngine.php index 7519011225282..ab39f1fed309b 100644 --- a/src/Symfony/Component/Form/AbstractRendererEngine.php +++ b/src/Symfony/Component/Form/AbstractRendererEngine.php @@ -33,6 +33,11 @@ abstract class AbstractRendererEngine implements FormRendererEngineInterface */ protected $themes = array(); + /** + * @var array + */ + protected $useDefaultThemes = array(); + /** * @var array */ @@ -57,13 +62,16 @@ public function __construct(array $defaultThemes = array()) /** * {@inheritdoc} */ - public function setTheme(FormView $view, $themes) + public function setTheme(FormView $view, $themes /*, $useDefaultThemes = true */) { $cacheKey = $view->vars[self::CACHE_KEY_VAR]; // Do not cast, as casting turns objects into arrays of properties $this->themes[$cacheKey] = is_array($themes) ? $themes : array($themes); + $args = func_get_args(); + $this->useDefaultThemes[$cacheKey] = isset($args[2]) ? (bool) $args[2] : true; + // Unset instead of resetting to an empty array, in order to allow // implementations (like TwigRendererEngine) to check whether $cacheKey // is set at all. diff --git a/src/Symfony/Component/Form/CHANGELOG.md b/src/Symfony/Component/Form/CHANGELOG.md index 62c52a897d3f2..19105b9e4db98 100644 --- a/src/Symfony/Component/Form/CHANGELOG.md +++ b/src/Symfony/Component/Form/CHANGELOG.md @@ -7,6 +7,8 @@ CHANGELOG * added `DebugCommand` * deprecated `ChoiceLoaderInterface` implementation in `TimezoneType` * added options "input" and "regions" to `TimezoneType` + * added an option to ``Symfony\Component\Form\FormRendererEngineInterface::setTheme()`` and + ``Symfony\Component\Form\FormRendererInterface::setTheme()`` to disable usage of default themes when rendering a form 3.3.0 ----- diff --git a/src/Symfony/Component/Form/Extension/Templating/TemplatingRendererEngine.php b/src/Symfony/Component/Form/Extension/Templating/TemplatingRendererEngine.php index 72b0a4f3dfa3a..16249c6067e81 100644 --- a/src/Symfony/Component/Form/Extension/Templating/TemplatingRendererEngine.php +++ b/src/Symfony/Component/Form/Extension/Templating/TemplatingRendererEngine.php @@ -72,9 +72,11 @@ protected function loadResourceForBlockName($cacheKey, FormView $view, $blockNam // Check the default themes once we reach the root form without success if (!$view->parent) { - for ($i = count($this->defaultThemes) - 1; $i >= 0; --$i) { - if ($this->loadResourceFromTheme($cacheKey, $blockName, $this->defaultThemes[$i])) { - return true; + if (!isset($this->useDefaultThemes[$cacheKey]) || $this->useDefaultThemes[$cacheKey]) { + for ($i = count($this->defaultThemes) - 1; $i >= 0; --$i) { + if ($this->loadResourceFromTheme($cacheKey, $blockName, $this->defaultThemes[$i])) { + return true; + } } } } diff --git a/src/Symfony/Component/Form/FormRenderer.php b/src/Symfony/Component/Form/FormRenderer.php index 8234b45f94437..c8a9d1812eb8b 100644 --- a/src/Symfony/Component/Form/FormRenderer.php +++ b/src/Symfony/Component/Form/FormRenderer.php @@ -70,9 +70,10 @@ public function getEngine() /** * {@inheritdoc} */ - public function setTheme(FormView $view, $themes) + public function setTheme(FormView $view, $themes /*, $useDefaultThemes = true */) { - $this->engine->setTheme($view, $themes); + $args = func_get_args(); + $this->engine->setTheme($view, $themes, isset($args[2]) ? (bool) $args[2] : true); } /** diff --git a/src/Symfony/Component/Form/FormRendererEngineInterface.php b/src/Symfony/Component/Form/FormRendererEngineInterface.php index 9d116b8608846..dcc15b6a2450f 100644 --- a/src/Symfony/Component/Form/FormRendererEngineInterface.php +++ b/src/Symfony/Component/Form/FormRendererEngineInterface.php @@ -21,11 +21,13 @@ interface FormRendererEngineInterface /** * Sets the theme(s) to be used for rendering a view and its children. * - * @param FormView $view The view to assign the theme(s) to - * @param mixed $themes The theme(s). The type of these themes - * is open to the implementation. + * @param FormView $view The view to assign the theme(s) to + * @param mixed $themes The theme(s). The type of these themes + * is open to the implementation. + * @param bool $useDefaultThemes If true, will use default themes specified + * in the engine, will be added to the interface in 4.0 */ - public function setTheme(FormView $view, $themes); + public function setTheme(FormView $view, $themes /*, $useDefaultThemes = true */); /** * Returns the resource for a block name. diff --git a/src/Symfony/Component/Form/FormRendererInterface.php b/src/Symfony/Component/Form/FormRendererInterface.php index 34c7822455c19..33530aeb82c47 100644 --- a/src/Symfony/Component/Form/FormRendererInterface.php +++ b/src/Symfony/Component/Form/FormRendererInterface.php @@ -28,11 +28,13 @@ public function getEngine(); /** * Sets the theme(s) to be used for rendering a view and its children. * - * @param FormView $view The view to assign the theme(s) to - * @param mixed $themes The theme(s). The type of these themes - * is open to the implementation. + * @param FormView $view The view to assign the theme(s) to + * @param mixed $themes The theme(s). The type of these themes + * is open to the implementation. + * @param bool $useDefaultThemes If true, will use default themes specified + * in the renderer, will be added to the interface in 4.0 */ - public function setTheme(FormView $view, $themes); + public function setTheme(FormView $view, $themes /*, $useDefaultThemes = true */); /** * Renders a named block of the form theme. diff --git a/src/Symfony/Component/Form/Tests/AbstractLayoutTest.php b/src/Symfony/Component/Form/Tests/AbstractLayoutTest.php index 98d2d48cbe360..4f2afa6644226 100644 --- a/src/Symfony/Component/Form/Tests/AbstractLayoutTest.php +++ b/src/Symfony/Component/Form/Tests/AbstractLayoutTest.php @@ -125,7 +125,7 @@ abstract protected function renderStart(FormView $view, array $vars = array()); abstract protected function renderEnd(FormView $view, array $vars = array()); - abstract protected function setTheme(FormView $view, array $themes); + abstract protected function setTheme(FormView $view, array $themes, $useDefaultThemes = true); public function testLabel() { From 7ba7550dfb3924c20691b4b9709c096cc5e316f0 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Fri, 13 Oct 2017 18:39:56 +0200 Subject: [PATCH 1083/1099] Fix phpunit bridge --- src/Symfony/Bridge/PhpUnit/Tests/ProcessIsolationTest.php | 1 + src/Symfony/Bridge/PhpUnit/bin/simple-phpunit | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Bridge/PhpUnit/Tests/ProcessIsolationTest.php b/src/Symfony/Bridge/PhpUnit/Tests/ProcessIsolationTest.php index d8677097e5c26..7d4cffa719db1 100644 --- a/src/Symfony/Bridge/PhpUnit/Tests/ProcessIsolationTest.php +++ b/src/Symfony/Bridge/PhpUnit/Tests/ProcessIsolationTest.php @@ -19,5 +19,6 @@ class ProcessIsolationTest extends TestCase public function testIsolation() { @trigger_error('Test abc', E_USER_DEPRECATED); + $test->addToAssertionCount(1); } } diff --git a/src/Symfony/Bridge/PhpUnit/bin/simple-phpunit b/src/Symfony/Bridge/PhpUnit/bin/simple-phpunit index beba0450aa4cd..52d10d4bce6a8 100755 --- a/src/Symfony/Bridge/PhpUnit/bin/simple-phpunit +++ b/src/Symfony/Bridge/PhpUnit/bin/simple-phpunit @@ -68,7 +68,7 @@ if (!file_exists("$PHPUNIT_DIR/phpunit-$PHPUNIT_VERSION/phpunit") || md5_file(__ if (5.1 <= $PHPUNIT_VERSION && $PHPUNIT_VERSION < 5.4) { passthru("$COMPOSER require --no-update phpunit/phpunit-mock-objects \"~3.1.0\""); } - passthru("$COMPOSER require --no-update symfony/phpunit-bridge \">=3.2@dev\""); + passthru("$COMPOSER require --no-update symfony/phpunit-bridge \">=3.3.11@dev\""); $prevRoot = getenv('COMPOSER_ROOT_VERSION'); putenv("COMPOSER_ROOT_VERSION=$PHPUNIT_VERSION"); $exit = proc_close(proc_open("$COMPOSER install --no-dev --prefer-dist --no-progress --ansi", array(), $p, getcwd(), null, array('bypass_shell' => true))); From 9de153b3303bad12392e00d343987363e50e6c9e Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Fri, 13 Oct 2017 18:48:45 +0200 Subject: [PATCH 1084/1099] Fix phpunit bridge (bis) --- src/Symfony/Bridge/PhpUnit/bin/simple-phpunit | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Bridge/PhpUnit/bin/simple-phpunit b/src/Symfony/Bridge/PhpUnit/bin/simple-phpunit index 52d10d4bce6a8..277bb73753580 100755 --- a/src/Symfony/Bridge/PhpUnit/bin/simple-phpunit +++ b/src/Symfony/Bridge/PhpUnit/bin/simple-phpunit @@ -70,7 +70,7 @@ if (!file_exists("$PHPUNIT_DIR/phpunit-$PHPUNIT_VERSION/phpunit") || md5_file(__ } passthru("$COMPOSER require --no-update symfony/phpunit-bridge \">=3.3.11@dev\""); $prevRoot = getenv('COMPOSER_ROOT_VERSION'); - putenv("COMPOSER_ROOT_VERSION=$PHPUNIT_VERSION"); + putenv("COMPOSER_ROOT_VERSION=$PHPUNIT_VERSION.99"); $exit = proc_close(proc_open("$COMPOSER install --no-dev --prefer-dist --no-progress --ansi", array(), $p, getcwd(), null, array('bypass_shell' => true))); putenv('COMPOSER_ROOT_VERSION'.(false !== $prevRoot ? '='.$prevRoot : '')); if ($exit) { From a522f5e855014c8118ed3ac061f91f74de6b5096 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Fri, 13 Oct 2017 18:55:35 +0200 Subject: [PATCH 1085/1099] Fix phpunit bridge (ter) --- src/Symfony/Bridge/PhpUnit/Tests/ProcessIsolationTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Bridge/PhpUnit/Tests/ProcessIsolationTest.php b/src/Symfony/Bridge/PhpUnit/Tests/ProcessIsolationTest.php index 7d4cffa719db1..0cfbe515ee9e4 100644 --- a/src/Symfony/Bridge/PhpUnit/Tests/ProcessIsolationTest.php +++ b/src/Symfony/Bridge/PhpUnit/Tests/ProcessIsolationTest.php @@ -19,6 +19,6 @@ class ProcessIsolationTest extends TestCase public function testIsolation() { @trigger_error('Test abc', E_USER_DEPRECATED); - $test->addToAssertionCount(1); + $this->addToAssertionCount(1); } } From 8fcbc5572b0a20fc3ef4980e49c499d27b10eda6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Thu, 12 Oct 2017 09:04:00 +0200 Subject: [PATCH 1086/1099] [Console] Sync ConsoleLogger::interpolate with the one in HttpKernel --- .../Console/Logger/ConsoleLogger.php | 20 +++++++++++++------ .../Tests/Logger/ConsoleLoggerTest.php | 4 +--- 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/src/Symfony/Component/Console/Logger/ConsoleLogger.php b/src/Symfony/Component/Console/Logger/ConsoleLogger.php index d7bcdfad003f5..ee2e1857545d6 100644 --- a/src/Symfony/Component/Console/Logger/ConsoleLogger.php +++ b/src/Symfony/Component/Console/Logger/ConsoleLogger.php @@ -121,15 +121,23 @@ public function hasErrored() */ private function interpolate($message, array $context) { - // build a replacement array with braces around the context keys - $replace = array(); + if (false === strpos($message, '{')) { + return $message; + } + + $replacements = array(); foreach ($context as $key => $val) { - if (!is_array($val) && (!is_object($val) || method_exists($val, '__toString'))) { - $replace[sprintf('{%s}', $key)] = $val; + if (null === $val || is_scalar($val) || (\is_object($val) && method_exists($val, '__toString'))) { + $replacements["{{$key}}"] = $val; + } elseif ($val instanceof \DateTimeInterface) { + $replacements["{{$key}}"] = $val->format(\DateTime::RFC3339); + } elseif (\is_object($val)) { + $replacements["{{$key}}"] = '[object '.\get_class($val).']'; + } else { + $replacements["{{$key}}"] = '['.\gettype($val).']'; } } - // interpolate replacement values into the message and return - return strtr($message, $replace); + return strtr($message, $replacements); } } diff --git a/src/Symfony/Component/Console/Tests/Logger/ConsoleLoggerTest.php b/src/Symfony/Component/Console/Tests/Logger/ConsoleLoggerTest.php index 342992982aa50..734a153e8ab59 100644 --- a/src/Symfony/Component/Console/Tests/Logger/ConsoleLoggerTest.php +++ b/src/Symfony/Component/Console/Tests/Logger/ConsoleLoggerTest.php @@ -166,9 +166,7 @@ public function testObjectCastToString() } else { $dummy = $this->getMock('Symfony\Component\Console\Tests\Logger\DummyTest', array('__toString')); } - $dummy->expects($this->once()) - ->method('__toString') - ->will($this->returnValue('DUMMY')); + $dummy->method('__toString')->will($this->returnValue('DUMMY')); $this->getLogger()->warning($dummy); From 16f728117876258a52f664daad156bc11382f9a9 Mon Sep 17 00:00:00 2001 From: endroid Date: Sat, 14 Oct 2017 00:01:11 +0000 Subject: [PATCH 1087/1099] [Routing] Ensure uniqueness without repeated check --- src/Symfony/Component/Routing/RouteCollection.php | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/Symfony/Component/Routing/RouteCollection.php b/src/Symfony/Component/Routing/RouteCollection.php index f8b18084be126..c6229cfde2dee 100644 --- a/src/Symfony/Component/Routing/RouteCollection.php +++ b/src/Symfony/Component/Routing/RouteCollection.php @@ -128,7 +128,9 @@ public function addCollection(RouteCollection $collection) $this->routes[$name] = $route; } - $this->resources = array_merge($this->resources, $collection->getResources()); + foreach ($collection->getResources() as $resource) { + $this->addResource($resource); + } } /** @@ -262,16 +264,21 @@ public function setMethods($methods) */ public function getResources() { - return array_unique($this->resources); + return array_values($this->resources); } /** - * Adds a resource for this collection. + * Adds a resource for this collection. If the resource already exists + * it is not added. * * @param ResourceInterface $resource A resource instance */ public function addResource(ResourceInterface $resource) { - $this->resources[] = $resource; + $key = (string) $resource; + + if (!isset($this->resources[$key])) { + $this->resources[$key] = $resource; + } } } From 347939c9b3202ec55fcfa545bfdefd18e414789f Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Tue, 10 Oct 2017 11:13:08 +0200 Subject: [PATCH 1088/1099] [HttpFoundation] Make sessions secure and lazy --- UPGRADE-3.4.md | 13 +- UPGRADE-4.0.md | 11 +- composer.json | 2 +- .../Bundle/FrameworkBundle/CHANGELOG.md | 1 + .../DependencyInjection/Configuration.php | 7 +- .../FrameworkExtension.php | 9 +- .../Resources/config/session.xml | 12 +- .../DependencyInjection/ConfigurationTest.php | 1 + .../Component/HttpFoundation/CHANGELOG.md | 5 +- .../Handler/AbstractSessionHandler.php | 165 +++++++++++++++ .../Handler/MemcachedSessionHandler.php | 18 +- .../Storage/Handler/MongoDbSessionHandler.php | 45 +++-- .../Storage/Handler/NativeSessionHandler.php | 6 +- .../Storage/Handler/NullSessionHandler.php | 20 +- .../Storage/Handler/PdoSessionHandler.php | 44 +++- .../Storage/Handler/StrictSessionHandler.php | 89 +++++++++ .../Handler/WriteCheckSessionHandler.php | 4 + .../Session/Storage/NativeSessionStorage.php | 44 ++-- .../Session/Storage/Proxy/AbstractProxy.php | 4 - .../Storage/Proxy/SessionHandlerProxy.php | 4 - .../Handler/AbstractSessionHandlerTest.php | 61 ++++++ .../Storage/Handler/Fixtures/common.inc | 152 ++++++++++++++ .../Handler/Fixtures/empty_destroys.expected | 17 ++ .../Handler/Fixtures/empty_destroys.php | 8 + .../Handler/Fixtures/read_only.expected | 14 ++ .../Storage/Handler/Fixtures/read_only.php | 8 + .../Handler/Fixtures/regenerate.expected | 24 +++ .../Storage/Handler/Fixtures/regenerate.php | 10 + .../Storage/Handler/Fixtures/storage.expected | 20 ++ .../Storage/Handler/Fixtures/storage.php | 24 +++ .../Handler/Fixtures/with_cookie.expected | 15 ++ .../Storage/Handler/Fixtures/with_cookie.php | 8 + .../Handler/NativeSessionHandlerTest.php | 3 + .../Storage/Handler/PdoSessionHandlerTest.php | 3 + .../Handler/StrictSessionHandlerTest.php | 189 ++++++++++++++++++ .../Handler/WriteCheckSessionHandlerTest.php | 2 + .../Storage/NativeSessionStorageTest.php | 8 +- .../Storage/Proxy/AbstractProxyTest.php | 2 - .../Storage/Proxy/SessionHandlerProxyTest.php | 1 - .../Component/HttpFoundation/composer.json | 3 +- .../NativeSessionTokenStorage.php | 12 +- 41 files changed, 984 insertions(+), 104 deletions(-) create mode 100644 src/Symfony/Component/HttpFoundation/Session/Storage/Handler/AbstractSessionHandler.php create mode 100644 src/Symfony/Component/HttpFoundation/Session/Storage/Handler/StrictSessionHandler.php create mode 100644 src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/AbstractSessionHandlerTest.php create mode 100644 src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/Fixtures/common.inc create mode 100644 src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/Fixtures/empty_destroys.expected create mode 100644 src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/Fixtures/empty_destroys.php create mode 100644 src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/Fixtures/read_only.expected create mode 100644 src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/Fixtures/read_only.php create mode 100644 src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/Fixtures/regenerate.expected create mode 100644 src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/Fixtures/regenerate.php create mode 100644 src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/Fixtures/storage.expected create mode 100644 src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/Fixtures/storage.php create mode 100644 src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/Fixtures/with_cookie.expected create mode 100644 src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/Fixtures/with_cookie.php create mode 100644 src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/StrictSessionHandlerTest.php diff --git a/UPGRADE-3.4.md b/UPGRADE-3.4.md index 5ef2448bf27a7..1b9a40c452dde 100644 --- a/UPGRADE-3.4.md +++ b/UPGRADE-3.4.md @@ -126,6 +126,8 @@ Form FrameworkBundle --------------- + * The `session.use_strict_mode` option has been deprecated and is enabled by default. + * The `cache:clear` command doesn't clear "app" PSR-6 cache pools anymore, but still clears "system" ones. Use the `cache:pool:clear` command to clear "app" pools instead. @@ -235,18 +237,13 @@ HttpFoundation * The `Symfony\Component\HttpFoundation\Session\Storage\Handler\NativeSessionHandler` class has been deprecated and will be removed in 4.0. Use the `\SessionHandler` class instead. - * The `Symfony\Component\HttpFoundation\Session\Storage\Proxy\AbstractProxy` class has been - deprecated and will be removed in 4.0. Use your `\SessionHandlerInterface` implementation directly. + * The `Symfony\Component\HttpFoundation\Session\Storage\Handler\WriteCheckSessionHandler` class has been + deprecated and will be removed in 4.0. Implement `SessionUpdateTimestampHandlerInterface` or + extend `AbstractSessionHandler` instead. * The `Symfony\Component\HttpFoundation\Session\Storage\Proxy\NativeProxy` class has been deprecated and will be removed in 4.0. Use your `\SessionHandlerInterface` implementation directly. - * The `Symfony\Component\HttpFoundation\Session\Storage\Proxy\SessionHandlerProxy` class has been - deprecated and will be removed in 4.0. Use your `\SessionHandlerInterface` implementation directly. - - * `NativeSessionStorage::setSaveHandler()` now takes an instance of `\SessionHandlerInterface` as argument. - Not passing it is deprecated and will throw a `TypeError` in 4.0. - * Using `Symfony\Component\HttpFoundation\Session\Storage\Handler\MongoDbSessionHandler` with the legacy mongo extension has been deprecated and will be removed in 4.0. Use it with the mongodb/mongodb package and ext-mongodb instead. diff --git a/UPGRADE-4.0.md b/UPGRADE-4.0.md index b2854c5925494..77959fa48bab1 100644 --- a/UPGRADE-4.0.md +++ b/UPGRADE-4.0.md @@ -329,6 +329,8 @@ Form FrameworkBundle --------------- + * The `session.use_strict_mode` option has been removed and strict mode is always enabled. + * The `validator.mapping.cache.doctrine.apc` service has been removed. * The "framework.trusted_proxies" configuration option and the corresponding "kernel.trusted_proxies" parameter have been removed. Use the `Request::setTrustedProxies()` method in your front controller instead. @@ -542,12 +544,11 @@ HttpFoundation * The ability to check only for cacheable HTTP methods using `Request::isMethodSafe()` is not supported anymore, use `Request::isMethodCacheable()` instead. - * The `Symfony\Component\HttpFoundation\Session\Storage\Handler\NativeSessionHandler`, - `Symfony\Component\HttpFoundation\Session\Storage\Proxy\AbstractProxy`, - `Symfony\Component\HttpFoundation\Session\Storage\Proxy\NativeProxy` and - `Symfony\Component\HttpFoundation\Session\Storage\Proxy\SessionHandlerProxy` classes have been removed. + * The `Symfony\Component\HttpFoundation\Session\Storage\Handler\WriteCheckSessionHandler` class has been + removed. Implement `SessionUpdateTimestampHandlerInterface` or extend `AbstractSessionHandler` instead. - * `NativeSessionStorage::setSaveHandler()` now requires an instance of `\SessionHandlerInterface` as argument. + * The `Symfony\Component\HttpFoundation\Session\Storage\Handler\NativeSessionHandler` and + `Symfony\Component\HttpFoundation\Session\Storage\Proxy\NativeProxy` classes have been removed. * The `Symfony\Component\HttpFoundation\Session\Storage\Handler\MongoDbSessionHandler` does not work with the legacy mongo extension anymore. It requires mongodb/mongodb package and ext-mongodb. diff --git a/composer.json b/composer.json index 3d96b012ce0b9..5b8e7985aae34 100644 --- a/composer.json +++ b/composer.json @@ -30,7 +30,7 @@ "symfony/polyfill-intl-icu": "~1.0", "symfony/polyfill-mbstring": "~1.0", "symfony/polyfill-php56": "~1.0", - "symfony/polyfill-php70": "~1.0", + "symfony/polyfill-php70": "~1.6", "symfony/polyfill-util": "~1.0" }, "replace": { diff --git a/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md b/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md index 49fd03165a5b7..db3d480b3e6c1 100644 --- a/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md +++ b/src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md @@ -4,6 +4,7 @@ CHANGELOG 3.4.0 ----- + * Session `use_strict_mode` is now enabled by default and the corresponding option has been deprecated * Made the `cache:clear` command to *not* clear "app" PSR-6 cache pools anymore, but to still clear "system" ones; use the `cache:pool:clear` command to clear "app" pools instead * Always register a minimalist logger that writes in `stderr` diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php index 4d5af046cbec2..14c61e1395323 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php @@ -462,11 +462,14 @@ private function addSessionSection(ArrayNodeDefinition $rootNode) ->scalarNode('gc_divisor')->end() ->scalarNode('gc_probability')->defaultValue(1)->end() ->scalarNode('gc_maxlifetime')->end() - ->booleanNode('use_strict_mode')->end() + ->booleanNode('use_strict_mode') + ->defaultTrue() + ->setDeprecated('The "%path%.%node%" option is enabled by default and deprecated since Symfony 3.4. It will be always enabled in 4.0.') + ->end() ->scalarNode('save_path')->defaultValue('%kernel.cache_dir%/sessions')->end() ->integerNode('metadata_update_threshold') ->defaultValue('0') - ->info('seconds to wait between 2 session metadata updates, it will also prevent the session handler to write if the session has not changed') + ->info('seconds to wait between 2 session metadata updates') ->end() ->end() ->end() diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php index 568bb0913ebc7..5eb3c24dff08f 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php @@ -916,14 +916,7 @@ private function registerSessionConfiguration(array $config, ContainerBuilder $c $container->getDefinition('session.storage.native')->replaceArgument(1, null); $container->getDefinition('session.storage.php_bridge')->replaceArgument(0, null); } else { - $handlerId = $config['handler_id']; - - if ($config['metadata_update_threshold'] > 0) { - $container->getDefinition('session.handler.write_check')->addArgument(new Reference($handlerId)); - $handlerId = 'session.handler.write_check'; - } - - $container->setAlias('session.handler', $handlerId)->setPrivate(true); + $container->setAlias('session.handler', $config['handler_id'])->setPrivate(true); } $container->setParameter('session.save_path', $config['save_path']); diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/session.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/session.xml index 335c14a8a6611..ce7a3dd7eee7d 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/session.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/session.xml @@ -48,11 +48,17 @@ - - %session.save_path% + + + + %session.save_path% + + - + + The "%service_id%" service is deprecated since Symfony 3.4 and will be removed in 4.0. Use the `session.lazy_write` ini setting instead. + diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/ConfigurationTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/ConfigurationTest.php index e6e83d40b538d..80f54afd20cad 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/ConfigurationTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/ConfigurationTest.php @@ -301,6 +301,7 @@ protected static function getBundleDefaultConfig() 'gc_probability' => 1, 'save_path' => '%kernel.cache_dir%/sessions', 'metadata_update_threshold' => '0', + 'use_strict_mode' => true, ), 'request' => array( 'enabled' => false, diff --git a/src/Symfony/Component/HttpFoundation/CHANGELOG.md b/src/Symfony/Component/HttpFoundation/CHANGELOG.md index 83a3c8e32eaf6..ee5b6cecf2e85 100644 --- a/src/Symfony/Component/HttpFoundation/CHANGELOG.md +++ b/src/Symfony/Component/HttpFoundation/CHANGELOG.md @@ -4,8 +4,9 @@ CHANGELOG 3.4.0 ----- - * deprecated the `NativeSessionHandler` class, - * deprecated the `AbstractProxy`, `NativeProxy` and `SessionHandlerProxy` classes, + * implemented PHP 7.0's `SessionUpdateTimestampHandlerInterface` with a new + `AbstractSessionHandler` base class and a new `StrictSessionHandler` wrapper + * deprecated the `WriteCheckSessionHandler`, `NativeSessionHandler` and `NativeProxy` classes * deprecated setting session save handlers that do not implement `\SessionHandlerInterface` in `NativeSessionStorage::setSaveHandler()` * deprecated using `MongoDbSessionHandler` with the legacy mongo extension; use it with the mongodb/mongodb package and ext-mongodb instead * deprecated `MemcacheSessionHandler`; use `MemcachedSessionHandler` instead diff --git a/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/AbstractSessionHandler.php b/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/AbstractSessionHandler.php new file mode 100644 index 0000000000000..c20a23b20e5d9 --- /dev/null +++ b/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/AbstractSessionHandler.php @@ -0,0 +1,165 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation\Session\Storage\Handler; + +/** + * This abstract session handler provides a generic implementation + * of the PHP 7.0 SessionUpdateTimestampHandlerInterface, + * enabling strict and lazy session handling. + * + * @author Nicolas Grekas + */ +abstract class AbstractSessionHandler implements \SessionHandlerInterface, \SessionUpdateTimestampHandlerInterface +{ + private $sessionName; + private $prefetchId; + private $prefetchData; + private $newSessionId; + private $igbinaryEmptyData; + + /** + * {@inheritdoc} + */ + public function open($savePath, $sessionName) + { + $this->sessionName = $sessionName; + + return true; + } + + /** + * @param string $sessionId + * + * @return string + */ + abstract protected function doRead($sessionId); + + /** + * @param string $sessionId + * @param string $data + * + * @return bool + */ + abstract protected function doWrite($sessionId, $data); + + /** + * @param string $sessionId + * + * @return bool + */ + abstract protected function doDestroy($sessionId); + + /** + * {@inheritdoc} + */ + public function validateId($sessionId) + { + $this->prefetchData = $this->read($sessionId); + $this->prefetchId = $sessionId; + + return '' !== $this->prefetchData; + } + + /** + * {@inheritdoc} + */ + public function read($sessionId) + { + if (null !== $this->prefetchId) { + $prefetchId = $this->prefetchId; + $prefetchData = $this->prefetchData; + $this->prefetchId = $this->prefetchData = null; + + if ($prefetchId === $sessionId || '' === $prefetchData) { + $this->newSessionId = '' === $prefetchData ? $sessionId : null; + + return $prefetchData; + } + } + + $data = $this->doRead($sessionId); + $this->newSessionId = '' === $data ? $sessionId : null; + if (\PHP_VERSION_ID < 70000) { + $this->prefetchData = $data; + } + + return $data; + } + + /** + * {@inheritdoc} + */ + public function write($sessionId, $data) + { + if (\PHP_VERSION_ID < 70000 && $this->prefetchData) { + $readData = $this->prefetchData; + $this->prefetchData = null; + + if ($readData === $data) { + return $this->updateTimestamp($sessionId, $data); + } + } + if (null === $this->igbinaryEmptyData) { + // see https://github.com/igbinary/igbinary/issues/146 + $this->igbinaryEmptyData = \function_exists('igbinary_serialize') ? igbinary_serialize(array()) : ''; + } + if ('' === $data || $this->igbinaryEmptyData === $data) { + return $this->destroy($sessionId); + } + $this->newSessionId = null; + + return $this->doWrite($sessionId, $data); + } + + /** + * {@inheritdoc} + */ + public function destroy($sessionId) + { + if (\PHP_VERSION_ID < 70000) { + $this->prefetchData = null; + } + if (!headers_sent() && ini_get('session.use_cookies')) { + if (!$this->sessionName) { + throw new \LogicException(sprintf('Session name cannot be empty, did you forget to call "parent::open()" in "%s"?.', get_class($this))); + } + $sessionCookie = sprintf(' %s=', urlencode($this->sessionName)); + $sessionCookieWithId = sprintf('%s%s;', $sessionCookie, urlencode($sessionId)); + $sessionCookieFound = false; + $otherCookies = array(); + 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; + } + } else { + $otherCookies[] = $h; + } + } + if ($sessionCookieFound) { + header_remove('Set-Cookie'); + foreach ($otherCookies as $h) { + header('Set-Cookie:'.$h, false); + } + } else { + setcookie($this->sessionName, '', 0, ini_get('session.cookie_path'), ini_get('session.cookie_domain'), ini_get('session.cookie_secure'), ini_get('session.cookie_httponly')); + } + } + + return $this->newSessionId === $sessionId || $this->doDestroy($sessionId); + } +} diff --git a/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/MemcachedSessionHandler.php b/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/MemcachedSessionHandler.php index 3bbde5420d16a..a31642cc83524 100644 --- a/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/MemcachedSessionHandler.php +++ b/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/MemcachedSessionHandler.php @@ -19,7 +19,7 @@ * * @author Drak */ -class MemcachedSessionHandler implements \SessionHandlerInterface +class MemcachedSessionHandler extends AbstractSessionHandler { /** * @var \Memcached Memcached driver @@ -39,7 +39,7 @@ class MemcachedSessionHandler implements \SessionHandlerInterface /** * List of available options: * * prefix: The prefix to use for the memcached keys in order to avoid collision - * * expiretime: The time to live in seconds + * * expiretime: The time to live in seconds. * * @param \Memcached $memcached A \Memcached instance * @param array $options An associative array of Memcached options @@ -63,7 +63,7 @@ public function __construct(\Memcached $memcached, array $options = array()) /** * {@inheritdoc} */ - public function open($savePath, $sessionName) + public function close() { return true; } @@ -71,23 +71,23 @@ public function open($savePath, $sessionName) /** * {@inheritdoc} */ - public function close() + protected function doRead($sessionId) { - return true; + return $this->memcached->get($this->prefix.$sessionId) ?: ''; } /** * {@inheritdoc} */ - public function read($sessionId) + public function updateTimestamp($sessionId, $data) { - return $this->memcached->get($this->prefix.$sessionId) ?: ''; + return $this->memcached->touch($this->prefix.$sessionId, time() + $this->ttl); } /** * {@inheritdoc} */ - public function write($sessionId, $data) + protected function doWrite($sessionId, $data) { return $this->memcached->set($this->prefix.$sessionId, $data, time() + $this->ttl); } @@ -95,7 +95,7 @@ public function write($sessionId, $data) /** * {@inheritdoc} */ - public function destroy($sessionId) + protected function doDestroy($sessionId) { $result = $this->memcached->delete($this->prefix.$sessionId); diff --git a/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/MongoDbSessionHandler.php b/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/MongoDbSessionHandler.php index d532fb92c6c26..7d770421c55ef 100644 --- a/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/MongoDbSessionHandler.php +++ b/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/MongoDbSessionHandler.php @@ -19,7 +19,7 @@ * @see https://packagist.org/packages/mongodb/mongodb * @see http://php.net/manual/en/set.mongodb.php */ -class MongoDbSessionHandler implements \SessionHandlerInterface +class MongoDbSessionHandler extends AbstractSessionHandler { /** * @var \Mongo|\MongoClient|\MongoDB\Client @@ -43,7 +43,7 @@ class MongoDbSessionHandler implements \SessionHandlerInterface * * id_field: The field name for storing the session id [default: _id] * * data_field: The field name for storing the session data [default: data] * * time_field: The field name for storing the timestamp [default: time] - * * expiry_field: The field name for storing the expiry-timestamp [default: expires_at] + * * expiry_field: The field name for storing the expiry-timestamp [default: expires_at]. * * It is strongly recommended to put an index on the `expiry_field` for * garbage-collection. Alternatively it's possible to automatically expire @@ -92,14 +92,6 @@ public function __construct($mongo, array $options) ), $options); } - /** - * {@inheritdoc} - */ - public function open($savePath, $sessionName) - { - return true; - } - /** * {@inheritdoc} */ @@ -111,7 +103,7 @@ public function close() /** * {@inheritdoc} */ - public function destroy($sessionId) + protected function doDestroy($sessionId) { $methodName = $this->mongo instanceof \MongoDB\Client ? 'deleteOne' : 'remove'; @@ -139,7 +131,7 @@ public function gc($maxlifetime) /** * {@inheritdoc} */ - public function write($sessionId, $data) + protected function doWrite($sessionId, $data) { $expiry = $this->createDateTime(time() + (int) ini_get('session.gc_maxlifetime')); @@ -171,7 +163,34 @@ public function write($sessionId, $data) /** * {@inheritdoc} */ - public function read($sessionId) + public function updateTimestamp($sessionId, $data) + { + $expiry = $this->createDateTime(time() + (int) ini_get('session.gc_maxlifetime')); + + if ($this->mongo instanceof \MongoDB\Client) { + $methodName = 'updateOne'; + $options = array(); + } else { + $methodName = 'update'; + $options = array('multiple' => false); + } + + $this->getCollection()->$methodName( + array($this->options['id_field'] => $sessionId), + array('$set' => array( + $this->options['time_field'] => $this->createDateTime(), + $this->options['expiry_field'] => $expiry, + )), + $options + ); + + return true; + } + + /** + * {@inheritdoc} + */ + protected function doRead($sessionId) { $dbData = $this->getCollection()->findOne(array( $this->options['id_field'] => $sessionId, diff --git a/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/NativeSessionHandler.php b/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/NativeSessionHandler.php index daa7dbd15b7c8..9ea4629ca16b3 100644 --- a/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/NativeSessionHandler.php +++ b/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/NativeSessionHandler.php @@ -11,12 +11,14 @@ namespace Symfony\Component\HttpFoundation\Session\Storage\Handler; -@trigger_error('The '.__NAMESPACE__.'\NativeSessionHandler class is deprecated since version 3.4 and will be removed in 4.0. Use the \SessionHandler class instead.', E_USER_DEPRECATED); - /** * @deprecated since version 3.4, to be removed in 4.0. Use \SessionHandler instead. * @see http://php.net/sessionhandler */ class NativeSessionHandler extends \SessionHandler { + public function __construct() + { + @trigger_error('The '.__NAMESPACE__.'\NativeSessionHandler class is deprecated since version 3.4 and will be removed in 4.0. Use the \SessionHandler class instead.', E_USER_DEPRECATED); + } } diff --git a/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/NullSessionHandler.php b/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/NullSessionHandler.php index 981d96d93a978..8d193155b090f 100644 --- a/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/NullSessionHandler.php +++ b/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/NullSessionHandler.php @@ -16,12 +16,12 @@ * * @author Drak */ -class NullSessionHandler implements \SessionHandlerInterface +class NullSessionHandler extends AbstractSessionHandler { /** * {@inheritdoc} */ - public function open($savePath, $sessionName) + public function close() { return true; } @@ -29,7 +29,7 @@ public function open($savePath, $sessionName) /** * {@inheritdoc} */ - public function close() + public function validateId($sessionId) { return true; } @@ -37,7 +37,7 @@ public function close() /** * {@inheritdoc} */ - public function read($sessionId) + protected function doRead($sessionId) { return ''; } @@ -45,7 +45,15 @@ public function read($sessionId) /** * {@inheritdoc} */ - public function write($sessionId, $data) + public function updateTimestamp($sessionId, $data) + { + return true; + } + + /** + * {@inheritdoc} + */ + protected function doWrite($sessionId, $data) { return true; } @@ -53,7 +61,7 @@ public function write($sessionId, $data) /** * {@inheritdoc} */ - public function destroy($sessionId) + protected function doDestroy($sessionId) { return true; } diff --git a/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/PdoSessionHandler.php b/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/PdoSessionHandler.php index 5cdac639399f0..19bf6e9bcaeef 100644 --- a/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/PdoSessionHandler.php +++ b/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/PdoSessionHandler.php @@ -38,7 +38,7 @@ * @author Michael Williams * @author Tobias Schultze */ -class PdoSessionHandler implements \SessionHandlerInterface +class PdoSessionHandler extends AbstractSessionHandler { /** * No locking is done. This means sessions are prone to loss of data due to @@ -260,11 +260,13 @@ public function isSessionExpired() */ public function open($savePath, $sessionName) { + $this->sessionExpired = false; + if (null === $this->pdo) { $this->connect($this->dsn ?: $savePath); } - return true; + return parent::open($savePath, $sessionName); } /** @@ -273,7 +275,7 @@ public function open($savePath, $sessionName) public function read($sessionId) { try { - return $this->doRead($sessionId); + return parent::read($sessionId); } catch (\PDOException $e) { $this->rollback(); @@ -296,7 +298,7 @@ public function gc($maxlifetime) /** * {@inheritdoc} */ - public function destroy($sessionId) + protected function doDestroy($sessionId) { // delete the record associated with this id $sql = "DELETE FROM $this->table WHERE $this->idCol = :id"; @@ -317,7 +319,7 @@ public function destroy($sessionId) /** * {@inheritdoc} */ - public function write($sessionId, $data) + protected function doWrite($sessionId, $data) { $maxlifetime = (int) ini_get('session.gc_maxlifetime'); @@ -372,6 +374,30 @@ public function write($sessionId, $data) return true; } + /** + * {@inheritdoc} + */ + public function updateTimestamp($sessionId, $data) + { + $maxlifetime = (int) ini_get('session.gc_maxlifetime'); + + try { + $updateStmt = $this->pdo->prepare( + "UPDATE $this->table SET $this->lifetimeCol = :lifetime, $this->timeCol = :time WHERE $this->idCol = :id" + ); + $updateStmt->bindParam(':id', $sessionId, \PDO::PARAM_STR); + $updateStmt->bindParam(':lifetime', $maxlifetime, \PDO::PARAM_INT); + $updateStmt->bindValue(':time', time(), \PDO::PARAM_INT); + $updateStmt->execute(); + } catch (\PDOException $e) { + $this->rollback(); + + throw $e; + } + + return true; + } + /** * {@inheritdoc} */ @@ -491,10 +517,8 @@ private function rollback() * * @return string The session data */ - private function doRead($sessionId) + protected function doRead($sessionId) { - $this->sessionExpired = false; - if (self::LOCK_ADVISORY === $this->lockMode) { $this->unlockStatements[] = $this->doAdvisoryLock($sessionId); } @@ -517,7 +541,9 @@ private function doRead($sessionId) return is_resource($sessionRows[0][0]) ? stream_get_contents($sessionRows[0][0]) : $sessionRows[0][0]; } - if (self::LOCK_TRANSACTIONAL === $this->lockMode && 'sqlite' !== $this->driver) { + if (!ini_get('session.use_strict_mode') && self::LOCK_TRANSACTIONAL === $this->lockMode && 'sqlite' !== $this->driver) { + // In strict mode, session fixation is not possible: new sessions always start with a unique + // random id, so that concurrency is not possible and this code path can be skipped. // Exclusive-reading of non-existent rows does not block, so we need to do an insert to block // until other connections to the session are committed. try { diff --git a/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/StrictSessionHandler.php b/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/StrictSessionHandler.php new file mode 100644 index 0000000000000..1bad0641e81b1 --- /dev/null +++ b/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/StrictSessionHandler.php @@ -0,0 +1,89 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation\Session\Storage\Handler; + +/** + * Adds basic `SessionUpdateTimestampHandlerInterface` behaviors to another `SessionHandlerInterface`. + * + * @author Nicolas Grekas + */ +class StrictSessionHandler extends AbstractSessionHandler +{ + private $handler; + + public function __construct(\SessionHandlerInterface $handler) + { + if ($handler instanceof \SessionUpdateTimestampHandlerInterface) { + throw new \LogicException(sprintf('"%s" is already an instance of "SessionUpdateTimestampHandlerInterface", you cannot wrap it with "%s".', get_class($handler), self::class)); + } + + $this->handler = $handler; + } + + /** + * {@inheritdoc} + */ + public function open($savePath, $sessionName) + { + parent::open($savePath, $sessionName); + + return $this->handler->open($savePath, $sessionName); + } + + /** + * {@inheritdoc} + */ + protected function doRead($sessionId) + { + return $this->handler->read($sessionId); + } + + /** + * {@inheritdoc} + */ + public function updateTimestamp($sessionId, $data) + { + return $this->write($sessionId, $data); + } + + /** + * {@inheritdoc} + */ + protected function doWrite($sessionId, $data) + { + return $this->handler->write($sessionId, $data); + } + + /** + * {@inheritdoc} + */ + protected function doDestroy($sessionId) + { + return $this->handler->destroy($sessionId); + } + + /** + * {@inheritdoc} + */ + public function close() + { + return $this->handler->close(); + } + + /** + * {@inheritdoc} + */ + public function gc($maxlifetime) + { + return $this->handler->gc($maxlifetime); + } +} diff --git a/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/WriteCheckSessionHandler.php b/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/WriteCheckSessionHandler.php index d49c36cae5876..638a633076e38 100644 --- a/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/WriteCheckSessionHandler.php +++ b/src/Symfony/Component/HttpFoundation/Session/Storage/Handler/WriteCheckSessionHandler.php @@ -11,10 +11,14 @@ namespace Symfony\Component\HttpFoundation\Session\Storage\Handler; +@trigger_error(sprintf('The %s class is deprecated since version 3.4 and will be removed in 4.0. Implement `SessionUpdateTimestampHandlerInterface` or extend `AbstractSessionHandler` instead.', WriteCheckSessionHandler::class), E_USER_DEPRECATED); + /** * Wraps another SessionHandlerInterface to only write the session when it has been modified. * * @author Adrien Brault + * + * @deprecated since version 3.4, to be removed in 4.0. Implement `SessionUpdateTimestampHandlerInterface` or extend `AbstractSessionHandler` instead. */ class WriteCheckSessionHandler implements \SessionHandlerInterface { diff --git a/src/Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.php b/src/Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.php index 623d38721bcf9..092d21830d732 100644 --- a/src/Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.php +++ b/src/Symfony/Component/HttpFoundation/Session/Storage/NativeSessionStorage.php @@ -11,8 +11,8 @@ namespace Symfony\Component\HttpFoundation\Session\Storage; -use Symfony\Component\Debug\Exception\ContextErrorException; use Symfony\Component\HttpFoundation\Session\SessionBagInterface; +use Symfony\Component\HttpFoundation\Session\Storage\Handler\StrictSessionHandler; use Symfony\Component\HttpFoundation\Session\Storage\Proxy\AbstractProxy; use Symfony\Component\HttpFoundation\Session\Storage\Proxy\SessionHandlerProxy; @@ -26,7 +26,7 @@ class NativeSessionStorage implements SessionStorageInterface /** * @var SessionBagInterface[] */ - protected $bags; + protected $bags = array(); /** * @var bool @@ -100,9 +100,9 @@ class NativeSessionStorage implements SessionStorageInterface public function __construct(array $options = array(), $handler = null, MetadataBag $metaBag = null) { $options += array( - // disable by default because it's managed by HeaderBag (if used) - 'cache_limiter' => '', + 'cache_limiter' => 'private_no_expire', 'use_cookies' => 1, + 'lazy_write' => 1, ); session_register_shutdown(); @@ -217,15 +217,31 @@ public function regenerate($destroy = false, $lifetime = null) */ public function save() { + $session = $_SESSION; + + foreach ($this->bags as $bag) { + if (empty($_SESSION[$key = $bag->getStorageKey()])) { + unset($_SESSION[$key]); + } + } + if (array($key = $this->metadataBag->getStorageKey()) === array_keys($_SESSION)) { + unset($_SESSION[$key]); + } + // Register custom error handler to catch a possible failure warning during session write - set_error_handler(function ($errno, $errstr, $errfile, $errline, $errcontext) { - throw new ContextErrorException($errstr, $errno, E_WARNING, $errfile, $errline, $errcontext); + set_error_handler(function ($errno, $errstr, $errfile, $errline) { + throw new \ErrorException($errstr, $errno, E_WARNING, $errfile, $errline); }, E_WARNING); try { + $e = null; session_write_close(); + } catch (\ErrorException $e) { + } finally { restore_error_handler(); - } catch (ContextErrorException $e) { + $_SESSION = $session; + } + if (null !== $e) { // The default PHP error message is not very helpful, as it does not give any information on the current save handler. // Therefore, we catch this error and trigger a warning with a better error message $handler = $this->getSaveHandler(); @@ -233,7 +249,6 @@ public function save() $handler = $handler->getHandler(); } - restore_error_handler(); trigger_error(sprintf('session_write_close(): Failed to write session data with %s handler', get_class($handler)), E_USER_WARNING); } @@ -386,13 +401,6 @@ public function setSaveHandler($saveHandler = null) throw new \InvalidArgumentException('Must be instance of AbstractProxy; implement \SessionHandlerInterface; or be null.'); } - if ($saveHandler instanceof AbstractProxy) { - @trigger_error( - 'Using session save handlers that are instances of AbstractProxy is deprecated since version 3.4 and will be removed in 4.0.', - E_USER_DEPRECATED - ); - } - if (headers_sent($file, $line)) { throw new \RuntimeException(sprintf('Failed to set the session handler because headers have already been sent by "%s" at line %d.', $file, $line)); } @@ -401,11 +409,13 @@ public function setSaveHandler($saveHandler = null) if (!$saveHandler instanceof AbstractProxy && $saveHandler instanceof \SessionHandlerInterface) { $saveHandler = new SessionHandlerProxy($saveHandler); } elseif (!$saveHandler instanceof AbstractProxy) { - $saveHandler = new SessionHandlerProxy(new \SessionHandler()); + $saveHandler = new SessionHandlerProxy(new StrictSessionHandler(new \SessionHandler())); } $this->saveHandler = $saveHandler; - if ($this->saveHandler instanceof \SessionHandlerInterface) { + if ($this->saveHandler instanceof SessionHandlerProxy) { + session_set_save_handler($this->saveHandler->getHandler(), false); + } elseif ($this->saveHandler instanceof \SessionHandlerInterface) { session_set_save_handler($this->saveHandler, false); } } diff --git a/src/Symfony/Component/HttpFoundation/Session/Storage/Proxy/AbstractProxy.php b/src/Symfony/Component/HttpFoundation/Session/Storage/Proxy/AbstractProxy.php index c1c8b9b1f7dd2..09c92483c7575 100644 --- a/src/Symfony/Component/HttpFoundation/Session/Storage/Proxy/AbstractProxy.php +++ b/src/Symfony/Component/HttpFoundation/Session/Storage/Proxy/AbstractProxy.php @@ -11,11 +11,7 @@ namespace Symfony\Component\HttpFoundation\Session\Storage\Proxy; -@trigger_error('The '.__NAMESPACE__.'\AbstractProxy class is deprecated since version 3.4 and will be removed in 4.0. Use your session handler implementation directly.', E_USER_DEPRECATED); - /** - * @deprecated since version 3.4, to be removed in 4.0. Use your session handler implementation directly. - * * @author Drak */ abstract class AbstractProxy diff --git a/src/Symfony/Component/HttpFoundation/Session/Storage/Proxy/SessionHandlerProxy.php b/src/Symfony/Component/HttpFoundation/Session/Storage/Proxy/SessionHandlerProxy.php index d6adef82dbf65..359bb877b5e30 100644 --- a/src/Symfony/Component/HttpFoundation/Session/Storage/Proxy/SessionHandlerProxy.php +++ b/src/Symfony/Component/HttpFoundation/Session/Storage/Proxy/SessionHandlerProxy.php @@ -11,11 +11,7 @@ namespace Symfony\Component\HttpFoundation\Session\Storage\Proxy; -@trigger_error('The '.__NAMESPACE__.'\SessionHandlerProxy class is deprecated since version 3.4 and will be removed in 4.0. Use your session handler implementation directly.', E_USER_DEPRECATED); - /** - * @deprecated since version 3.4, to be removed in 4.0. Use your session handler implementation directly. - * * @author Drak */ class SessionHandlerProxy extends AbstractProxy implements \SessionHandlerInterface diff --git a/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/AbstractSessionHandlerTest.php b/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/AbstractSessionHandlerTest.php new file mode 100644 index 0000000000000..3ac081e3884c1 --- /dev/null +++ b/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/AbstractSessionHandlerTest.php @@ -0,0 +1,61 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation\Tests\Session\Storage\Handler; + +use PHPUnit\Framework\TestCase; + +/** + * @requires PHP 7.0 + */ +class AbstractSessionHandlerTest extends TestCase +{ + private static $server; + + public static function setUpBeforeClass() + { + $spec = array( + 1 => array('file', '/dev/null', 'w'), + 2 => array('file', '/dev/null', 'w'), + ); + if (!self::$server = @proc_open('exec php -S localhost:8053', $spec, $pipes, __DIR__.'/Fixtures')) { + self::markTestSkipped('PHP server unable to start.'); + } + sleep(1); + } + + public static function tearDownAfterClass() + { + if (self::$server) { + proc_terminate(self::$server); + proc_close(self::$server); + } + } + + /** + * @dataProvider provideSession + */ + public function testSession($fixture) + { + $context = array('http' => array('header' => "Cookie: sid=123abc\r\n")); + $context = stream_context_create($context); + $result = file_get_contents(sprintf('http://localhost:8053/%s.php', $fixture), false, $context); + + $this->assertStringEqualsFile(__DIR__.sprintf('/Fixtures/%s.expected', $fixture), $result); + } + + public function provideSession() + { + foreach (glob(__DIR__.'/Fixtures/*.php') as $file) { + yield array(pathinfo($file, PATHINFO_FILENAME)); + } + } +} diff --git a/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/Fixtures/common.inc b/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/Fixtures/common.inc new file mode 100644 index 0000000000000..5c183acfff324 --- /dev/null +++ b/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/Fixtures/common.inc @@ -0,0 +1,152 @@ +data = $data; + } + + public function open($path, $name) + { + echo __FUNCTION__, "\n"; + + return parent::open($path, $name); + } + + public function validateId($sessionId) + { + echo __FUNCTION__, "\n"; + + return parent::validateId($sessionId); + } + + /** + * {@inheritdoc} + */ + public function read($sessionId) + { + echo __FUNCTION__, "\n"; + + return parent::read($sessionId); + } + + /** + * {@inheritdoc} + */ + public function updateTimestamp($sessionId, $data) + { + echo __FUNCTION__, "\n"; + + return true; + } + + /** + * {@inheritdoc} + */ + public function write($sessionId, $data) + { + echo __FUNCTION__, "\n"; + + return parent::write($sessionId, $data); + } + + /** + * {@inheritdoc} + */ + public function destroy($sessionId) + { + echo __FUNCTION__, "\n"; + + return parent::destroy($sessionId); + } + + public function close() + { + echo __FUNCTION__, "\n"; + + return true; + } + + public function gc($maxLifetime) + { + echo __FUNCTION__, "\n"; + + return true; + } + + protected function doRead($sessionId) + { + echo __FUNCTION__.': ', $this->data, "\n"; + + return $this->data; + } + + protected function doWrite($sessionId, $data) + { + echo __FUNCTION__.': ', $data, "\n"; + + return true; + } + + protected function doDestroy($sessionId) + { + echo __FUNCTION__, "\n"; + + return true; + } +} diff --git a/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/Fixtures/empty_destroys.expected b/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/Fixtures/empty_destroys.expected new file mode 100644 index 0000000000000..1720bf0558386 --- /dev/null +++ b/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/Fixtures/empty_destroys.expected @@ -0,0 +1,17 @@ +open +validateId +read +doRead: abc|i:123; +read + +write +destroy +doDestroy +close +Array +( + [0] => Content-Type: text/plain; charset=utf-8 + [1] => Cache-Control: private, max-age=10800 + [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/empty_destroys.php b/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/Fixtures/empty_destroys.php new file mode 100644 index 0000000000000..3cfc1250adad1 --- /dev/null +++ b/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/Fixtures/empty_destroys.php @@ -0,0 +1,8 @@ + Content-Type: text/plain; charset=utf-8 + [1] => Cache-Control: private, max-age=10800 +) +shutdown diff --git a/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/Fixtures/read_only.php b/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/Fixtures/read_only.php new file mode 100644 index 0000000000000..3e62fb9ecbbdd --- /dev/null +++ b/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/Fixtures/read_only.php @@ -0,0 +1,8 @@ + Content-Type: text/plain; charset=utf-8 + [1] => Cache-Control: private, max-age=10800 + [2] => Set-Cookie: sid=random_session_id; path=/; secure; HttpOnly +) +shutdown diff --git a/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/Fixtures/regenerate.php b/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/Fixtures/regenerate.php new file mode 100644 index 0000000000000..a0f635c8712ec --- /dev/null +++ b/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/Fixtures/regenerate.php @@ -0,0 +1,10 @@ + bar +) +$_SESSION is not empty +write +destroy +close +$_SESSION is not empty +Array +( + [0] => Content-Type: text/plain; charset=utf-8 + [1] => Cache-Control: private, max-age=10800 +) +shutdown diff --git a/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/Fixtures/storage.php b/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/Fixtures/storage.php new file mode 100644 index 0000000000000..96dca3c2c0006 --- /dev/null +++ b/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/Fixtures/storage.php @@ -0,0 +1,24 @@ +setSaveHandler(new TestSessionHandler()); +$flash = new FlashBag(); +$storage->registerBag($flash); +$storage->start(); + +$flash->add('foo', 'bar'); + +print_r($flash->get('foo')); +echo empty($_SESSION) ? '$_SESSION is empty' : '$_SESSION is not empty'; +echo "\n"; + +$storage->save(); + +echo empty($_SESSION) ? '$_SESSION is empty' : '$_SESSION is not empty'; + +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_cookie.expected b/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/Fixtures/with_cookie.expected new file mode 100644 index 0000000000000..47ae4da82449d --- /dev/null +++ b/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/Fixtures/with_cookie.expected @@ -0,0 +1,15 @@ +open +validateId +read +doRead: abc|i:123; +read + +updateTimestamp +close +Array +( + [0] => Content-Type: text/plain; charset=utf-8 + [1] => Cache-Control: private, max-age=10800 + [2] => Set-Cookie: abc=def +) +shutdown diff --git a/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/Fixtures/with_cookie.php b/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/Fixtures/with_cookie.php new file mode 100644 index 0000000000000..ffb5b20a3774e --- /dev/null +++ b/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/Fixtures/with_cookie.php @@ -0,0 +1,8 @@ +markTestSkipped('PHPUnit_MockObject cannot mock the PDOStatement class on HHVM. See https://github.com/sebastianbergmann/phpunit-mock-objects/pull/289'); } + if (ini_get('session.use_strict_mode')) { + $this->markTestSkipped('Strict mode needs no locking for new sessions.'); + } $pdo = new MockPdo('pgsql'); $selectStmt = $this->getMockBuilder('PDOStatement')->getMock(); diff --git a/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/StrictSessionHandlerTest.php b/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/StrictSessionHandlerTest.php new file mode 100644 index 0000000000000..9d2c1949f3d72 --- /dev/null +++ b/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/StrictSessionHandlerTest.php @@ -0,0 +1,189 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation\Tests\Session\Storage\Handler; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\HttpFoundation\Session\Storage\Handler\AbstractSessionHandler; +use Symfony\Component\HttpFoundation\Session\Storage\Handler\StrictSessionHandler; + +class StrictSessionHandlerTest extends TestCase +{ + public function testOpen() + { + $handler = $this->getMockBuilder('SessionHandlerInterface')->getMock(); + $handler->expects($this->once())->method('open') + ->with('path', 'name')->willReturn(true); + $proxy = new StrictSessionHandler($handler); + + $this->assertInstanceof('SessionUpdateTimestampHandlerInterface', $proxy); + $this->assertInstanceof(AbstractSessionHandler::class, $proxy); + $this->assertTrue($proxy->open('path', 'name')); + } + + public function testCloseSession() + { + $handler = $this->getMockBuilder('SessionHandlerInterface')->getMock(); + $handler->expects($this->once())->method('close') + ->willReturn(true); + $proxy = new StrictSessionHandler($handler); + + $this->assertTrue($proxy->close()); + } + + public function testValidateIdOK() + { + $handler = $this->getMockBuilder('SessionHandlerInterface')->getMock(); + $handler->expects($this->once())->method('read') + ->with('id')->willReturn('data'); + $proxy = new StrictSessionHandler($handler); + + $this->assertTrue($proxy->validateId('id')); + } + + public function testValidateIdKO() + { + $handler = $this->getMockBuilder('SessionHandlerInterface')->getMock(); + $handler->expects($this->once())->method('read') + ->with('id')->willReturn(''); + $proxy = new StrictSessionHandler($handler); + + $this->assertFalse($proxy->validateId('id')); + } + + public function testRead() + { + $handler = $this->getMockBuilder('SessionHandlerInterface')->getMock(); + $handler->expects($this->once())->method('read') + ->with('id')->willReturn('data'); + $proxy = new StrictSessionHandler($handler); + + $this->assertSame('data', $proxy->read('id')); + } + + public function testReadWithValidateIdOK() + { + $handler = $this->getMockBuilder('SessionHandlerInterface')->getMock(); + $handler->expects($this->once())->method('read') + ->with('id')->willReturn('data'); + $proxy = new StrictSessionHandler($handler); + + $this->assertTrue($proxy->validateId('id')); + $this->assertSame('data', $proxy->read('id')); + } + + public function testReadWithValidateIdMismatch() + { + $handler = $this->getMockBuilder('SessionHandlerInterface')->getMock(); + $handler->expects($this->exactly(2))->method('read') + ->withConsecutive(array('id1'), array('id2')) + ->will($this->onConsecutiveCalls('data1', 'data2')); + $proxy = new StrictSessionHandler($handler); + + $this->assertTrue($proxy->validateId('id1')); + $this->assertSame('data2', $proxy->read('id2')); + } + + public function testUpdateTimestamp() + { + $handler = $this->getMockBuilder('SessionHandlerInterface')->getMock(); + $handler->expects($this->once())->method('write') + ->with('id', 'data')->willReturn(true); + $proxy = new StrictSessionHandler($handler); + + $this->assertTrue($proxy->updateTimestamp('id', 'data')); + } + + public function testWrite() + { + $handler = $this->getMockBuilder('SessionHandlerInterface')->getMock(); + $handler->expects($this->once())->method('write') + ->with('id', 'data')->willReturn(true); + $proxy = new StrictSessionHandler($handler); + + $this->assertTrue($proxy->write('id', 'data')); + } + + public function testWriteEmptyNewSession() + { + $handler = $this->getMockBuilder('SessionHandlerInterface')->getMock(); + $handler->expects($this->once())->method('read') + ->with('id')->willReturn(''); + $handler->expects($this->never())->method('write'); + $handler->expects($this->never())->method('destroy'); + $proxy = new StrictSessionHandler($handler); + + $this->assertFalse($proxy->validateId('id')); + $this->assertSame('', $proxy->read('id')); + $this->assertTrue($proxy->write('id', '')); + } + + public function testWriteEmptyExistingSession() + { + $handler = $this->getMockBuilder('SessionHandlerInterface')->getMock(); + $handler->expects($this->once())->method('read') + ->with('id')->willReturn('data'); + $handler->expects($this->never())->method('write'); + $handler->expects($this->once())->method('destroy')->willReturn(true); + $proxy = new StrictSessionHandler($handler); + + $this->assertSame('data', $proxy->read('id')); + $this->assertTrue($proxy->write('id', '')); + } + + public function testDestroy() + { + $handler = $this->getMockBuilder('SessionHandlerInterface')->getMock(); + $handler->expects($this->once())->method('destroy') + ->with('id')->willReturn(true); + $proxy = new StrictSessionHandler($handler); + + $this->assertTrue($proxy->destroy('id')); + } + + public function testDestroyNewSession() + { + $handler = $this->getMockBuilder('SessionHandlerInterface')->getMock(); + $handler->expects($this->once())->method('read') + ->with('id')->willReturn(''); + $handler->expects($this->never())->method('destroy'); + $proxy = new StrictSessionHandler($handler); + + $this->assertSame('', $proxy->read('id')); + $this->assertTrue($proxy->destroy('id')); + } + + public function testDestroyNonEmptyNewSession() + { + $handler = $this->getMockBuilder('SessionHandlerInterface')->getMock(); + $handler->expects($this->once())->method('read') + ->with('id')->willReturn(''); + $handler->expects($this->once())->method('write') + ->with('id', 'data')->willReturn(true); + $handler->expects($this->once())->method('destroy') + ->with('id')->willReturn(true); + $proxy = new StrictSessionHandler($handler); + + $this->assertSame('', $proxy->read('id')); + $this->assertTrue($proxy->write('id', 'data')); + $this->assertTrue($proxy->destroy('id')); + } + + public function testGc() + { + $handler = $this->getMockBuilder('SessionHandlerInterface')->getMock(); + $handler->expects($this->once())->method('gc') + ->with(123)->willReturn(true); + $proxy = new StrictSessionHandler($handler); + + $this->assertTrue($proxy->gc(123)); + } +} diff --git a/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/WriteCheckSessionHandlerTest.php b/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/WriteCheckSessionHandlerTest.php index 5e41a4743edd5..898a7d11a5ae2 100644 --- a/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/WriteCheckSessionHandlerTest.php +++ b/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Handler/WriteCheckSessionHandlerTest.php @@ -16,6 +16,8 @@ /** * @author Adrien Brault + * + * @group legacy */ class WriteCheckSessionHandlerTest extends TestCase { diff --git a/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/NativeSessionStorageTest.php b/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/NativeSessionStorageTest.php index 818c63a9d2ae2..93de175fd3c67 100644 --- a/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/NativeSessionStorageTest.php +++ b/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/NativeSessionStorageTest.php @@ -14,7 +14,7 @@ use PHPUnit\Framework\TestCase; use Symfony\Component\HttpFoundation\Session\Attribute\AttributeBag; use Symfony\Component\HttpFoundation\Session\Flash\FlashBag; -use Symfony\Component\HttpFoundation\Session\Storage\Handler\NativeSessionHandler; +use Symfony\Component\HttpFoundation\Session\Storage\Handler\NativeFileSessionHandler; use Symfony\Component\HttpFoundation\Session\Storage\Handler\NullSessionHandler; use Symfony\Component\HttpFoundation\Session\Storage\NativeSessionStorage; use Symfony\Component\HttpFoundation\Session\Storage\Proxy\SessionHandlerProxy; @@ -152,7 +152,7 @@ public function testDefaultSessionCacheLimiter() $this->iniSet('session.cache_limiter', 'nocache'); $storage = new NativeSessionStorage(); - $this->assertEquals('', ini_get('session.cache_limiter')); + $this->assertEquals('private_no_expire', ini_get('session.cache_limiter')); } public function testExplicitSessionCacheLimiter() @@ -201,9 +201,9 @@ public function testSetSaveHandler() $this->assertInstanceOf('Symfony\Component\HttpFoundation\Session\Storage\Proxy\SessionHandlerProxy', $storage->getSaveHandler()); $storage->setSaveHandler(null); $this->assertInstanceOf('Symfony\Component\HttpFoundation\Session\Storage\Proxy\SessionHandlerProxy', $storage->getSaveHandler()); - $storage->setSaveHandler(new SessionHandlerProxy(new NativeSessionHandler())); + $storage->setSaveHandler(new SessionHandlerProxy(new NativeFileSessionHandler())); $this->assertInstanceOf('Symfony\Component\HttpFoundation\Session\Storage\Proxy\SessionHandlerProxy', $storage->getSaveHandler()); - $storage->setSaveHandler(new NativeSessionHandler()); + $storage->setSaveHandler(new NativeFileSessionHandler()); $this->assertInstanceOf('Symfony\Component\HttpFoundation\Session\Storage\Proxy\SessionHandlerProxy', $storage->getSaveHandler()); $storage->setSaveHandler(new SessionHandlerProxy(new NullSessionHandler())); $this->assertInstanceOf('Symfony\Component\HttpFoundation\Session\Storage\Proxy\SessionHandlerProxy', $storage->getSaveHandler()); diff --git a/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Proxy/AbstractProxyTest.php b/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Proxy/AbstractProxyTest.php index f2be722c8f522..cbb291f19fc3f 100644 --- a/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Proxy/AbstractProxyTest.php +++ b/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Proxy/AbstractProxyTest.php @@ -18,8 +18,6 @@ /** * Test class for AbstractProxy. * - * @group legacy - * * @author Drak */ class AbstractProxyTest extends TestCase diff --git a/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Proxy/SessionHandlerProxyTest.php b/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Proxy/SessionHandlerProxyTest.php index fdd1dae254198..682825356a724 100644 --- a/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Proxy/SessionHandlerProxyTest.php +++ b/src/Symfony/Component/HttpFoundation/Tests/Session/Storage/Proxy/SessionHandlerProxyTest.php @@ -21,7 +21,6 @@ * * @runTestsInSeparateProcesses * @preserveGlobalState disabled - * @group legacy */ class SessionHandlerProxyTest extends TestCase { diff --git a/src/Symfony/Component/HttpFoundation/composer.json b/src/Symfony/Component/HttpFoundation/composer.json index 4f13511e9ac7a..f6c6f2e623fe6 100644 --- a/src/Symfony/Component/HttpFoundation/composer.json +++ b/src/Symfony/Component/HttpFoundation/composer.json @@ -17,7 +17,8 @@ ], "require": { "php": "^5.5.9|>=7.0.8", - "symfony/polyfill-mbstring": "~1.1" + "symfony/polyfill-mbstring": "~1.1", + "symfony/polyfill-php70": "~1.6" }, "require-dev": { "symfony/expression-language": "~2.8|~3.0|~4.0" diff --git a/src/Symfony/Component/Security/Csrf/TokenStorage/NativeSessionTokenStorage.php b/src/Symfony/Component/Security/Csrf/TokenStorage/NativeSessionTokenStorage.php index 5ce2774114737..d441ba6ed3d02 100644 --- a/src/Symfony/Component/Security/Csrf/TokenStorage/NativeSessionTokenStorage.php +++ b/src/Symfony/Component/Security/Csrf/TokenStorage/NativeSessionTokenStorage.php @@ -97,12 +97,18 @@ public function removeToken($tokenId) $this->startSession(); } - $token = isset($_SESSION[$this->namespace][$tokenId]) - ? (string) $_SESSION[$this->namespace][$tokenId] - : null; + if (!isset($_SESSION[$this->namespace][$tokenId])) { + return; + } + + $token = (string) $_SESSION[$this->namespace][$tokenId]; unset($_SESSION[$this->namespace][$tokenId]); + if (!$_SESSION[$this->namespace]) { + unset($_SESSION[$this->namespace]); + } + return $token; } From 41df5123497be20155b615e44edbbb08c4f14129 Mon Sep 17 00:00:00 2001 From: Ryan Weaver Date: Mon, 16 Oct 2017 20:25:51 -0400 Subject: [PATCH 1089/1099] Adding a new debug:autowiring command --- .../Command/DebugAutowiringCommand.php | 97 +++++++++++++++++++ .../Resources/config/console.xml | 4 + .../Functional/DebugAutowiringCommandTest.php | 63 ++++++++++++ 3 files changed, 164 insertions(+) create mode 100644 src/Symfony/Bundle/FrameworkBundle/Command/DebugAutowiringCommand.php create mode 100644 src/Symfony/Bundle/FrameworkBundle/Tests/Functional/DebugAutowiringCommandTest.php diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/DebugAutowiringCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/DebugAutowiringCommand.php new file mode 100644 index 0000000000000..23d688495db74 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Command/DebugAutowiringCommand.php @@ -0,0 +1,97 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\FrameworkBundle\Command; + +use Symfony\Component\Console\Input\InputArgument; +use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Output\OutputInterface; +use Symfony\Component\Console\Style\SymfonyStyle; + +/** + * A console command for autowiring information. + * + * @author Ryan Weaver + * + * @internal + */ +class DebugAutowiringCommand extends ContainerDebugCommand +{ + protected static $defaultName = 'debug:autowiring'; + + /** + * {@inheritdoc} + */ + protected function configure() + { + $this + ->setDefinition(array( + new InputArgument('search', InputArgument::OPTIONAL, 'A search filter'), + )) + ->setDescription('Lists classes/interfaces you can use for autowiring') + ->setHelp(<<<'EOF' +The %command.name% command displays all classes and interfaces that +you can use as type-hints for autowiring: + + php %command.full_name% + +You can also pass a search term to filter the list: + + php %command.full_name% log + +EOF + ) + ; + } + + /** + * {@inheritdoc} + */ + protected function execute(InputInterface $input, OutputInterface $output) + { + $io = new SymfonyStyle($input, $output); + $errorIo = $io->getErrorStyle(); + + $builder = $this->getContainerBuilder(); + $serviceIds = $builder->getServiceIds(); + $serviceIds = array_filter($serviceIds, array($this, 'filterToServiceTypes')); + + if ($search = $input->getArgument('search')) { + $serviceIds = array_filter($serviceIds, function ($serviceId) use ($search) { + return false !== stripos($serviceId, $search); + }); + + if (empty($serviceIds)) { + $errorIo->error(sprintf('No autowirable classes or interfaces found matching "%s"', $search)); + + return 1; + } + } + + asort($serviceIds); + + $io->title('Autowirable Services'); + $io->text('The following classes & interfaces can be used as type-hints when autowiring:'); + if ($search) { + $io->text(sprintf('(only showing classes/interfaces matching %s)', $search)); + } + $io->newLine(); + $tableRows = array(); + foreach ($serviceIds as $serviceId) { + $tableRows[] = array(sprintf('%s', $serviceId)); + if ($builder->hasAlias($serviceId)) { + $tableRows[] = array(sprintf(' alias to %s', $builder->getAlias($serviceId))); + } + } + + $io->table(array(), $tableRows); + } +} diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/console.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/console.xml index 7dc4ea6d2fbae..cebf6014f0462 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/console.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/console.xml @@ -55,6 +55,10 @@ + + + + diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/DebugAutowiringCommandTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/DebugAutowiringCommandTest.php new file mode 100644 index 0000000000000..0b7f9290a50bb --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/DebugAutowiringCommandTest.php @@ -0,0 +1,63 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\FrameworkBundle\Tests\Functional; + +use Symfony\Bundle\FrameworkBundle\Console\Application; +use Symfony\Component\Console\Tester\ApplicationTester; + +/** + * @group functional + */ +class DebugAutowiringCommandTest extends WebTestCase +{ + public function testBasicFunctionality() + { + static::bootKernel(array('test_case' => 'ContainerDebug', 'root_config' => 'config.yml')); + + $application = new Application(static::$kernel); + $application->setAutoExit(false); + + $tester = new ApplicationTester($application); + $tester->run(array('command' => 'debug:autowiring')); + + $this->assertContains('Symfony\Component\HttpKernel\HttpKernelInterface', $tester->getDisplay()); + $this->assertContains('alias to http_kernel', $tester->getDisplay()); + } + + public function testSearchArgument() + { + static::bootKernel(array('test_case' => 'ContainerDebug', 'root_config' => 'config.yml')); + + $application = new Application(static::$kernel); + $application->setAutoExit(false); + + $tester = new ApplicationTester($application); + $tester->run(array('command' => 'debug:autowiring', 'search' => 'kern')); + + $this->assertContains('Symfony\Component\HttpKernel\HttpKernelInterface', $tester->getDisplay()); + $this->assertNotContains('Symfony\Component\Routing\RouterInterface', $tester->getDisplay()); + } + + public function testSearchNoResults() + { + static::bootKernel(array('test_case' => 'ContainerDebug', 'root_config' => 'config.yml')); + + $application = new Application(static::$kernel); + $application->setAutoExit(false); + + $tester = new ApplicationTester($application); + $tester->run(array('command' => 'debug:autowiring', 'search' => 'foo_fake'), array('capture_stderr_separately' => true)); + + $this->assertContains('No autowirable classes or interfaces found matching "foo_fake"', $tester->getErrorOutput()); + $this->assertEquals(1, $tester->getStatusCode()); + } +} From 454f65a77d707cc31c08d1417f27247b23bd0e89 Mon Sep 17 00:00:00 2001 From: Ryan Weaver Date: Tue, 17 Oct 2017 00:33:38 -0400 Subject: [PATCH 1090/1099] adding AdapterInterface alias for cache.app --- src/Symfony/Bundle/FrameworkBundle/Resources/config/cache.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/cache.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/cache.xml index b4d23a576ed0f..9466d992c0fa4 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/cache.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/cache.xml @@ -111,5 +111,6 @@ + From 921a8794c60678c08c10bb5bd51298de50edff96 Mon Sep 17 00:00:00 2001 From: Christophe Coevoet Date: Tue, 17 Oct 2017 16:03:36 +0200 Subject: [PATCH 1091/1099] Add extra autowiring aliases This adds autowiring for RequestContextAwareInterface for the routing layer and for AuthenticationManagerInterface in the security layer. --- src/Symfony/Bundle/FrameworkBundle/Resources/config/routing.xml | 1 + src/Symfony/Bundle/SecurityBundle/Resources/config/security.xml | 1 + 2 files changed, 2 insertions(+) diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/routing.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/routing.xml index 94579d93b5019..f515d33c0c311 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/routing.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/routing.xml @@ -85,6 +85,7 @@ + %router.request_context.base_url% diff --git a/src/Symfony/Bundle/SecurityBundle/Resources/config/security.xml b/src/Symfony/Bundle/SecurityBundle/Resources/config/security.xml index 0225df0ee47ae..4ebbbb85421df 100644 --- a/src/Symfony/Bundle/SecurityBundle/Resources/config/security.xml +++ b/src/Symfony/Bundle/SecurityBundle/Resources/config/security.xml @@ -52,6 +52,7 @@ + %security.authentication.trust_resolver.anonymous_class% From a1df9af20f50762007a64ca75601bf9f5f85f675 Mon Sep 17 00:00:00 2001 From: Yonel Ceruto Date: Wed, 18 Oct 2017 01:29:21 -0400 Subject: [PATCH 1092/1099] don't bind scalar values to controller method arguments --- .../RegisterControllerArgumentLocatorsPass.php | 5 +++++ ...egisterControllerArgumentLocatorsPassTest.php | 16 ++++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/src/Symfony/Component/HttpKernel/DependencyInjection/RegisterControllerArgumentLocatorsPass.php b/src/Symfony/Component/HttpKernel/DependencyInjection/RegisterControllerArgumentLocatorsPass.php index 6a9f0586f7b77..985dfb71d7064 100644 --- a/src/Symfony/Component/HttpKernel/DependencyInjection/RegisterControllerArgumentLocatorsPass.php +++ b/src/Symfony/Component/HttpKernel/DependencyInjection/RegisterControllerArgumentLocatorsPass.php @@ -135,6 +135,11 @@ public function process(ContainerBuilder $container) $binding = $bindings[$bindingName]; list($bindingValue, $bindingId) = $binding->getValues(); + + if (!$bindingValue instanceof Reference) { + continue; + } + $binding->setValues(array($bindingValue, $bindingId, true)); $args[$p->name] = $bindingValue; diff --git a/src/Symfony/Component/HttpKernel/Tests/DependencyInjection/RegisterControllerArgumentLocatorsPassTest.php b/src/Symfony/Component/HttpKernel/Tests/DependencyInjection/RegisterControllerArgumentLocatorsPassTest.php index 0e524b92d8873..4016deb4ab294 100644 --- a/src/Symfony/Component/HttpKernel/Tests/DependencyInjection/RegisterControllerArgumentLocatorsPassTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/DependencyInjection/RegisterControllerArgumentLocatorsPassTest.php @@ -310,6 +310,22 @@ public function provideBindings() { return array(array(ControllerDummy::class), array('$bar')); } + + public function testDoNotBindScalarValueToControllerArgument() + { + $container = new ContainerBuilder(); + $resolver = $container->register('argument_resolver.service')->addArgument(array()); + + $container->register('foo', ArgumentWithoutTypeController::class) + ->setBindings(array('$someArg' => '%foo%')) + ->addTag('controller.service_arguments'); + + $pass = new RegisterControllerArgumentLocatorsPass(); + $pass->process($container); + + $locator = $container->getDefinition((string) $resolver->getArgument(0))->getArgument(0); + $this->assertEmpty($locator); + } } class RegisterTestController From 5c366092f3f21263cad2f1ff8859254b96cefc3d Mon Sep 17 00:00:00 2001 From: David Maicher Date: Wed, 18 Oct 2017 12:06:44 +0200 Subject: [PATCH 1093/1099] [TwigBridge] fix merge of 3.4 into master --- .../Tests/Extension/FormExtensionTest.php | 76 ------------------- 1 file changed, 76 deletions(-) delete mode 100644 src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionTest.php diff --git a/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionTest.php b/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionTest.php deleted file mode 100644 index a4d7350716e64..0000000000000 --- a/src/Symfony/Bridge/Twig/Tests/Extension/FormExtensionTest.php +++ /dev/null @@ -1,76 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Bridge\Twig\Tests\Extension; - -use PHPUnit\Framework\TestCase; -use Symfony\Bridge\Twig\Extension\FormExtension; -use Symfony\Bridge\Twig\Form\TwigRendererInterface; -use Symfony\Component\DependencyInjection\ContainerInterface; -use Symfony\Component\Form\FormRendererInterface; -use Twig\Environment; - -/** - * @group legacy - */ -class FormExtensionTest extends TestCase -{ - /** - * @dataProvider rendererDataProvider - */ - public function testInitRuntimeAndAccessRenderer($rendererConstructor, $expectedAccessedRenderer) - { - $extension = new FormExtension($rendererConstructor); - $extension->initRuntime($this->getMockBuilder(Environment::class)->disableOriginalConstructor()->getMock()); - $this->assertSame($expectedAccessedRenderer, $extension->renderer); - } - - /** - * @dataProvider rendererDataProvider - */ - public function testAccessRendererAndInitRuntime($rendererConstructor, $expectedAccessedRenderer) - { - $extension = new FormExtension($rendererConstructor); - $this->assertSame($expectedAccessedRenderer, $extension->renderer); - $extension->initRuntime($this->getMockBuilder(Environment::class)->disableOriginalConstructor()->getMock()); - } - - public function rendererDataProvider() - { - $twigRenderer = $this->getMockBuilder(TwigRendererInterface::class)->getMock(); - $twigRenderer->expects($this->once()) - ->method('setEnvironment'); - - yield array($twigRenderer, $twigRenderer); - - $twigRenderer = $this->getMockBuilder(TwigRendererInterface::class)->getMock(); - $twigRenderer->expects($this->once()) - ->method('setEnvironment'); - - $container = $this->getMockBuilder(ContainerInterface::class)->getMock(); - $container->expects($this->once()) - ->method('get') - ->with('service_id') - ->willReturn($twigRenderer); - - yield array(array($container, 'service_id'), $twigRenderer); - - $formRenderer = $this->getMockBuilder(FormRendererInterface::class)->getMock(); - - $container = $this->getMockBuilder(ContainerInterface::class)->getMock(); - $container->expects($this->once()) - ->method('get') - ->with('service_id') - ->willReturn($formRenderer); - - yield array(array($container, 'service_id'), $formRenderer); - } -} From 6a6256c6a8bb6b5734c7ff491c5be0e291bcae2a Mon Sep 17 00:00:00 2001 From: Robin Chalas Date: Wed, 18 Oct 2017 11:36:53 +0200 Subject: [PATCH 1094/1099] Do not process bindings in AbstractRecursivePass --- .../Compiler/AbstractRecursivePass.php | 1 - ...xceptionOnInvalidReferenceBehaviorPassTest.php | 15 +++++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/DependencyInjection/Compiler/AbstractRecursivePass.php b/src/Symfony/Component/DependencyInjection/Compiler/AbstractRecursivePass.php index 765b5752da173..cbe9b30468f51 100644 --- a/src/Symfony/Component/DependencyInjection/Compiler/AbstractRecursivePass.php +++ b/src/Symfony/Component/DependencyInjection/Compiler/AbstractRecursivePass.php @@ -67,7 +67,6 @@ protected function processValue($value, $isRoot = false) $value->setArguments($this->processValue($value->getArguments())); $value->setProperties($this->processValue($value->getProperties())); $value->setMethodCalls($this->processValue($value->getMethodCalls())); - $value->setBindings($this->processValue($value->getBindings())); $changes = $value->getChanges(); if (isset($changes['factory'])) { diff --git a/src/Symfony/Component/DependencyInjection/Tests/Compiler/CheckExceptionOnInvalidReferenceBehaviorPassTest.php b/src/Symfony/Component/DependencyInjection/Tests/Compiler/CheckExceptionOnInvalidReferenceBehaviorPassTest.php index dc20b39bc4dca..ac002d834d1c5 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Compiler/CheckExceptionOnInvalidReferenceBehaviorPassTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Compiler/CheckExceptionOnInvalidReferenceBehaviorPassTest.php @@ -12,6 +12,7 @@ namespace Symfony\Component\DependencyInjection\Tests\Compiler; use PHPUnit\Framework\TestCase; +use Symfony\Component\DependencyInjection\Argument\BoundArgument; use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\DependencyInjection\Compiler\CheckExceptionOnInvalidReferenceBehaviorPass; use Symfony\Component\DependencyInjection\Reference; @@ -88,6 +89,20 @@ public function testProcessThrowsExceptionOnNonSharedUninitializedReference() $this->process($container); } + public function testProcessDefinitionWithBindings() + { + $container = new ContainerBuilder(); + + $container + ->register('b') + ->setBindings(array(new BoundArgument(new Reference('a')))) + ; + + $this->process($container); + + $this->addToAssertionCount(1); + } + private function process(ContainerBuilder $container) { $pass = new CheckExceptionOnInvalidReferenceBehaviorPass(); From a024e80f1cc45731e509d65f0bc5dedfeb015dd2 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Wed, 18 Oct 2017 14:45:28 -0700 Subject: [PATCH 1095/1099] updated CHANGELOG for 3.4.0-BETA1 --- CHANGELOG-3.4.md | 217 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 217 insertions(+) create mode 100644 CHANGELOG-3.4.md diff --git a/CHANGELOG-3.4.md b/CHANGELOG-3.4.md new file mode 100644 index 0000000000000..2790538d54831 --- /dev/null +++ b/CHANGELOG-3.4.md @@ -0,0 +1,217 @@ +CHANGELOG for 3.4.x +=================== + +This changelog references the relevant changes (bug and security fixes) done +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.0-BETA1 (2017-10-18) + + * feature #24583 Adding a new debug:autowiring command (weaverryan) + * feature #24523 [HttpFoundation] Make sessions secure and lazy (nicolas-grekas) + * feature #22610 [Form] [TwigBridge] Added option to disable usage of default themes when rendering a form (emodric) + * feature #23112 [OptionsResolver] Support array of types in allowed type (pierredup) + * feature #24321 added ability to handle parent classes for PropertyNormalizer (ivoba) + * feature #24505 [HttpKernel] implement reset() in DumpDataCollector (xabbuh) + * feature #24425 [Console][HttpKernel] Handle new SHELL_VERBOSITY env var, also configures the default logger (nicolas-grekas) + * feature #24387 [FORM] Prevent forms from extending itself as a parent (pierredup) + * feature #24484 [DI] Throw accurate failures when accessing removed services (nicolas-grekas) + * feature #24208 [Form] Display option definition from a given form type (yceruto, ogizanagi) + * feature #23499 [Workflow] add guard is_valid() method support (alain-flaus, lyrixx) + * feature #24388 [Security] Look at headers for switch_user username (chalasr) + * feature #23708 Added deprecation to cwd not existing Fixes #18249 (alexbowers) + * feature #24443 [Session] deprecate MemcacheSessionHandler (Tobion) + * feature #24409 [Bridge\Doctrine][FrameworkBundle] Deprecate some remaining uses of ContainerAwareTrait (nicolas-grekas) + * feature #24438 [Session][VarDumper] Deprecate accepting legacy mongo extension (Tobion) + * feature #24389 [DoctrineBridge] Deprecate dbal session handler (Tobion) + * feature #16835 [Security] Add Guard authenticator method (Amo, chalasr) + * feature #24289 [FrameworkBundle][HttpKernel] Reset profiler (derrabus) + * feature #24144 [FrameworkBundle] Expose dotenv in bin/console about (ro0NL) + * feature #24403 [FrameworkBundle][Routing] Show welcome message if no routes are configured (yceruto) + * feature #22679 [Form] Add tel and color types (apetitpa) + * feature #23845 [Validator] Add unique entity violation cause (Ilya Vertakov) + * feature #22132 [Lock] Automaticaly release lock when user forget it (jderusse) + * feature #21751 Bootstrap4 support for Twig form theme (hiddewie, javiereguiluz) + * feature #24383 [FrameworkBundle] Don't clear app pools on cache:clear (nicolas-grekas) + * feature #24148 [Form] Hide label button when its setted to false (TeLiXj) + * feature #24378 [SecurityBundle] Deprecate auto picking the first provider (ogizanagi) + * feature #24260 [Security] Add impersonation support for stateless authentication (chalasr) + * feature #24300 [HttpKernel][FrameworkBundle] Add a minimalist default PSR-3 logger (dunglas) + * feature #21604 [Security] Argon2i Password Encoder (zanbaldwin) + * feature #24372 [DowCrawler] Default to UTF-8 when possible (nicolas-grekas) + * feature #24264 [TwigBundle] Improve the overriding of bundle templates (yceruto) + * feature #24197 [Translation] Moved PhpExtractor and PhpStringTokenParser to Translation component (Nyholm) + * feature #24362 [HttpKernel] Deprecate some compiler passes in favor of tagged iterator args (nicolas-grekas) + * feature #21027 [Asset] Provide default context (ro0NL) + * feature #22200 [DI] Reference tagged services in config (ro0NL) + * feature #24337 Adding a shortcuts for the main security functionality (weaverryan, javiereguiluz) + * feature #24358 [TwigBundle] register an identity translator as fallback (xabbuh) + * feature #24357 [Yaml] include file and line no in deprecation message (xabbuh) + * feature #24330 [FrameworkBundle] register class metadata factory alias (xabbuh) + * feature #24349 [SecurityBundle] Add missing AclSchemaListener deprecation (ogizanagi) + * feature #24202 [Filesystem] deprecate relative paths in makePathRelative() (xabbuh) + * feature #21716 [Serializer] Add Support for `object_to_populate` in CustomNormalizer (chrisguitarguy) + * feature #21960 Remove Validator\TypeTestCase and add validator logic to base TypeTestCase (pierredup) + * feature #22113 [Lock] Include lock component in framework bundle (jderusse) + * feature #24236 [WebProfilerBundle] Render file links for twig templates (ro0NL) + * feature #21239 [Serializer] throw more specific exceptions (xabbuh) + * feature #24256 CsvEncoder handling variable structures and custom header order (Oliver Hoff) + * feature #23471 [Finder] Add a method to check if any results were found (duncan3dc) + * feature #23149 [PhpUnitBridge] Added a CoverageListener to enhance the code coverage report (lyrixx) + * feature #24318 [SecurityBundle] Deprecate ACL related code (chalasr) + * feature #24335 [Security][SecurityBundle] Deprecate the HTTP digest auth (ogizanagi) + * feature #21951 [Security][Firewall] Passing the newly generated security token to the event during user switching (klandaika) + * feature #23485 [Config] extracted the xml parsing from XmlUtils::loadFile into XmlUtils::parse (Basster) + * feature #22890 [HttpKernel] Add ability to configure catching exceptions for Client (kbond) + * feature #24239 [HttpFoundation] Deprecate compatibility with PHP <5.4 sessions (afurculita) + * feature #23882 [Security] Deprecated not being logged out after user change (iltar) + * feature #24200 Added an alias for FlashBagInterface in config (tifabien) + * feature #24295 [DI][DX] Throw exception on some ContainerBuilder methods used from extensions (ogizanagi) + * feature #24253 [Yaml] support parsing files (xabbuh) + * feature #24290 Adding Definition::addError() and a compiler pass to throw errors as exceptions (weaverryan) + * feature #24301 [DI] Add AutowireRequiredMethodsPass to fix bindings for `@required` methods (nicolas-grekas) + * feature #24226 [Cache] Add ResettableInterface to allow resetting any pool's local state (nicolas-grekas) + * feature #24303 [FrameworkBundle] allow forms without translations and validator (xabbuh) + * feature #24291 [SecurityBundle] Reset the authentication token between requests (derrabus) + * feature #24280 [VarDumper] Make `dump()` a little bit more easier to use (freekmurze) + * feature #24277 [Serializer] Getter for extra attributes in ExtraAttributesException (mdeboer) + * feature #24257 [HttpKernel][DI] Enable Kernel to implement CompilerPassInterface (nicolas-grekas) + * feature #23834 [DI] Add "PHP fluent format" for configuring the container (nicolas-grekas) + * feature #24180 [Routing] Add PHP fluent DSL for configuring routes (nicolas-grekas) + * feature #24232 [Bridge\Doctrine] Add "DoctrineType::reset()" method (nicolas-grekas) + * feature #24238 [DI] Turn services and aliases private by default, with BC layer (nicolas-grekas) + * feature #23648 [Form] Add input + regions options to TimezoneType (ro0NL) + * feature #24185 [Form] Display general forms information on debug:form (yceruto) + * feature #23747 [Serializer][FrameworkBundle] Add a DateInterval normalizer (Lctrs) + * feature #24193 [FrameworkBundle] Reset stopwatch between requests (derrabus) + * feature #24160 [HttpKernel] Deprecate bundle inheritance (fabpot) + * feature #24155 [FrameworkBundle][HttpKernel] Add DI tag for resettable services (derrabus) + * feature #23625 Feature #23583 Add current and fallback locales in WDT / Profiler (nemoneph) + * feature #24179 [TwigBundle] Add default templates directory and option to configure it (yceruto) + * feature #24104 Make as many services private as possible (nicolas-grekas) + * feature #18314 [Translation] added support for adding custom message formatter (aitboudad) + * feature #24158 deprecated profiler.matcher configuration (fabpot) + * feature #24131 [Console] Do not display short exception trace for common console exceptions (yceruto) + * feature #24080 Deprecated the web_profiler.position option (javiereguiluz) + * feature #24114 [SecurityBundle] Throw a meaningful exception when an undefined user provider is used inside a firewall (chalasr) + * feature #24122 [DI] rename ResolveDefinitionTemplatesPass to ResolveChildDefinitionsPass (nicolas-grekas) + * feature #23901 [DI] Allow processing env vars (nicolas-grekas) + * feature #24093 [FrameworkBundle] be able to enable workflow support explicitly (xabbuh) + * feature #24064 [TwigBridge] Show Twig's loader paths on debug:twig command (yceruto) + * feature #23978 [Cache] Use options from Memcached DSN (Bukashk0zzz) + * feature #24075 Implemented PruneableInterface on TagAwareAdapter (Toflar) + * feature #21414 [Console] Display file and line on Exception (arno14) + * feature #24068 [HttpKernel] Deprecate EnvParametersResource (ro0NL) + * feature #22542 [Lock] Check TTL expiration in lock acquisition (jderusse) + * feature #24031 [Routing] Add the possibility to define a prefix for all routes of a controller (fabpot) + * feature #23967 [VarDumper] add force-collapse/expand + use it for traces (nicolas-grekas) + * feature #24033 [DI] Add ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE (nicolas-grekas) + * feature #24026 [Security] add impersonator_user to "User was reloaded" log message (gharlan) + * feature #23603 [Cache] Add (pdo|chain) cache (adapter|simple) prune method (robfrawley) + * feature #23694 [Form] Add debug:form command (yceruto) + * feature #24028 [Yaml] mark some classes as final (xabbuh) + * feature #22543 [Lock] Expose an expiringDate and isExpired method in Lock (jderusse) + * feature #23667 [Translation] Create an TranslationReaderInterface and move TranslationLoader to TranslationComponent (Nyholm) + * feature #24024 [config] Add ability to deprecate a node (sanpii) + * feature #23668 [VarDumper] Add period caster (maidmaid) + * feature #23991 [DI] Improve psr4-based service discovery (alternative implementation) (kbond) + * feature #23947 [Translation] Adding the ability do load in xliff2.0 (Nyholm) + * feature #23887 [Console] Allow commands to provide a default name for compile time registration (chalasr, nicolas-grekas) + * feature #23874 [DI] Case sensitive parameter names (ro0NL) + * feature #23936 Remove some sf2 references (fabpot) + * feature #23680 [Webprofiler] Added blocks that allows extension of the profiler page. (Nyholm) + * feature #23665 Create an interface for TranslationWriter (Nyholm) + * feature #23890 [Translation] Adding the ability do dump in xliff2.0 (Nyholm) + * feature #23862 [SecurityBundle] resolve class name parameter inside AddSecurityVotersPass (pjarmalavicius) + * feature #23915 [DI] Allow get available services from service locator (Koc) + * feature #23792 [HttpKernel][FrameworkBundle] Add RebootableInterface, fix and un-deprecate cache:clear with warmup (nicolas-grekas) + * feature #23227 Add support for "controller" keyword for configuring routes controllers (voronkovich) + * feature #23869 [Console] Made console command shortcuts case insensitive (thanosp) + * feature #23855 [DI] Allow dumping inline services in Yaml (nicolas-grekas) + * feature #23836 [FrameworkBundle] Catch Fatal errors in commands registration (chalasr) + * feature #23805 [HttpKernel] Deprecated commands auto-registration (GuilhemN) + * feature #23816 [Debug] Detect internal and deprecated methods (GuilhemN) + * feature #23812 [FrameworkBundle] Allow micro kernel to subscribe events easily (ogizanagi) + * feature #22187 [DependencyInjection] Support local binding (GuilhemN) + * feature #23741 [DI] Generate one file per service factory (nicolas-grekas) + * feature #23807 [Debug] Trigger a deprecation when using an internal class/trait/interface (GuilhemN) + * feature #22587 [Workflow] Add transition completed event (izzyp) + * feature #23624 [FrameworkBundle] Commands as a service (ro0NL) + * feature #21111 [Validator] add groups support to the Valid constraint (xabbuh) + * feature #20361 [Config] Enable cannotBeEmpty along with requiresAtLeastOneElement (ro0NL) + * feature #23712 [DependencyInjection] Deprecate autowiring service auto-registration (GuilhemN) + * feature #23719 Autoconfigure instances of ArgumentValueResolverInterface (BPScott) + * feature #23706 [Webprofiler] Improve sql explain table display (mimol91) + * feature #23724 [Lock] Deprecate Filesystem/LockHandler (jderusse) + * feature #23593 [Workflow] Adding workflow name to the announce event (Nyholm) + * feature #20496 [Form] Allow pass filter callback to delete_empty option. (Koc) + * feature #23451 [Cache] Add (filesystem|phpfiles) cache (adapter|simple) prune method and prune command (robfrawley) + * feature #23519 [TwigBundle] Commands as a service (ro0NL) + * feature #23591 [VarDumper] Add time zone caster (maidmaid) + * feature #23510 [Console] Add a factory command loader for standalone application with lazy-loading needs (ogizanagi) + * feature #23357 [VarDumper] Add interval caster (maidmaid) + * feature #23550 [DebugBundle] Added min_depth to Configuration (james-johnston-thumbtack) + * feature #23570 [FrameworkBundle] Make RouterCacheWarmer implement ServiceSubscriberInterface (nicolas-grekas) + * feature #23437 [TwigBridge] deprecate TwigRenderer (Tobion) + * feature #23515 [VarDumper] Added setMinDepth to VarCloner (james-johnston-thumbtack) + * feature #23404 [Serializer] AbstractObjectNormalizer: Allow to disable type enforcement (ogizanagi) + * feature #21086 [MonologBridge] Add TokenProcessor (maidmaid) + * feature #22576 [Validator] Allow to use a property path to get value to compare in comparison constraints (ogizanagi) + * feature #22689 [DoctrineBridge] Add support for doctrin/dbal v2.6 types (jvasseur) + * feature #22734 [Console] Add support for command lazy-loading (chalasr) + * feature #19034 [Security] make it possible to configure a custom access decision manager service (xabbuh) + * feature #23037 [TwigBundle] Added a RuntimeExtensionInterface to take advantage of autoconfigure (lyrixx) + * feature #22176 [DI] Allow imports in string format for YAML (ro0NL) + * feature #23295 [Security] Lazy load user providers (chalasr) + * feature #23440 [Routing] Add matched and default parameters to redirect responses (artursvonda, Tobion) + * feature #22832 [Debug] Deprecate support for stacked errors (mbabker) + * feature #21469 [HttpFoundation] Find the original request protocol version (thewilkybarkid) + * feature #23431 [Validator] Add min/max amount of pixels to Image constraint (akeeman) + * feature #23223 Add support for microseconds in Stopwatch (javiereguiluz) + * feature #22341 [BrowserKit] Emulate back/forward browser navigation (e-moe) + * feature #22619 [FrameworkBundle][Translation] Move translation compiler pass (lepiaf) + * feature #22620 [FrameworkBundle][HttpKernel] Move httpkernel pass (lepiaf) + * feature #23337 [Component][Serializer][Normalizer] : Deal it with Has Method for the Normalizer/Denormalizer (jordscream) + * feature #22588 [VarDumper] Add filter in VarDumperTestTrait (maidmaid) + * feature #23288 [Yaml] deprecate the !str tag (xabbuh) + * feature #23039 [Validator] Support for parsing PHP constants in yaml loader (mimol91) + * feature #22431 [VarDumper] Add date caster (maidmaid) + * feature #23285 [Stopwatch] Add a reset method (jmgq) + * feature #23320 [WebServer] Allow * to bind all interfaces (as INADDR_ANY) (jpauli, fabpot) + * feature #23272 [FrameworkBundle] disable unusable fragment renderers (xabbuh) + * feature #23332 [Yaml] fix the displayed line number (fabpot, xabbuh) + * feature #23026 [SecurityBundle] Add user impersonation info and exit action to the profiler (yceruto) + * feature #22932 [HttpFoundation] Adds support for the immutable directive in the cache-control header (twoleds) + * feature #22554 [Profiler][Validator] Add a validator panel in profiler (ogizanagi) + * feature #22124 Shift responsibility for keeping Date header to ResponseHeaderBag (mpdude) + * feature #23122 Xml encoder optional type cast (ragboyjr) + * feature #23207 [FrameworkBundle] Allow .yaml file extension everywhere (ogizanagi) + * feature #23076 [Validator] Adds support to check specific DNS record type for URL (iisisrael) + * feature #22629 [Security] Trigger a deprecation when a voter is missing the VoterInterface (iltar) + * feature #22636 [Routing] Expose request in route conditions, if needed and possible (ro0NL) + * feature #22909 [Yaml] Deprecate using the non-specific tag (GuilhemN) + * feature #23042 Consistent error handling in remember me services (lstrojny) + * feature #22444 [Serializer] DateTimeNormalizer: allow to provide timezone (ogizanagi) + * feature #23143 [DI] Reference instead of inline for array-params (nicolas-grekas) + * feature #23154 [WebProfilerBundle] Sticky ajax window (ro0NL) + * feature #23161 [FrameworkBundle] Deprecate useless --no-prefix option (chalasr) + * feature #23105 [SecurityBundle][Profiler] Give info about called security listeners in profiler (chalasr) + * feature #23148 [FrameworkBundle] drop hard dependency on the Stopwatch component (xabbuh) + * feature #23131 [FrameworkBundle] Remove dependency on Doctrine cache (fabpot) + * feature #23114 [SecurityBundle] Lazy load security listeners (chalasr) + * feature #23111 [Process] Deprecate ProcessBuilder (nicolas-grekas) + * feature #22675 [FrameworkBundle] KernelTestCase: deprecate not using KERNEL_CLASS (ogizanagi) + * feature #22917 [VarDumper] Cycle prev/next searching in HTML dumps (ro0NL) + * feature #23044 Automatically enable the routing annotation loader (GuilhemN) + * feature #22696 [PropertyInfo] Made ReflectionExtractor's prefix lists instance variables (neemzy) + * feature #23035 Deprecate passing a concrete service in optional cache warmers (romainneutron) + * feature #23036 Implement ServiceSubscriberInterface in optional cache warmers (romainneutron) + * feature #23022 [Di] Remove closure-proxy arguments (nicolas-grekas) + * feature #22903 [DI] Deprecate XML services without ID (ro0NL) + * feature #22597 [Lock] Re-add the Lock component in 3.4 (jderusse) + * feature #22803 [DI] Deprecate Container::initialized() for privates (ro0NL) + * feature #22828 [Finder] Deprecate FilterIterator (ogizanagi) + * feature #22826 [Validator] improve strict option value deprecation (xabbuh) + From c000b454c8d44ef6aaed8fb1b991d91a4d29f522 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Wed, 18 Oct 2017 14:45:50 -0700 Subject: [PATCH 1096/1099] updated VERSION for 3.4.0-BETA1 --- 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 6f4f2b72b63b7..af68d7c39a814 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -65,12 +65,12 @@ abstract class Kernel implements KernelInterface, RebootableInterface, Terminabl private $projectDir; private $warmupDir; - const VERSION = '3.4.0-DEV'; + const VERSION = '3.4.0-BETA1'; const VERSION_ID = 30400; const MAJOR_VERSION = 3; const MINOR_VERSION = 4; const RELEASE_VERSION = 0; - const EXTRA_VERSION = 'DEV'; + const EXTRA_VERSION = 'BETA1'; const END_OF_MAINTENANCE = '11/2020'; const END_OF_LIFE = '11/2021'; From d484f7282a25572a0f1045dcccf7c79260b6fe2e Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Wed, 18 Oct 2017 15:39:44 -0700 Subject: [PATCH 1097/1099] bumped Symfony version to 3.4.0 --- src/Symfony/Component/HttpKernel/Kernel.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/HttpKernel/Kernel.php b/src/Symfony/Component/HttpKernel/Kernel.php index af68d7c39a814..6f4f2b72b63b7 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -65,12 +65,12 @@ abstract class Kernel implements KernelInterface, RebootableInterface, Terminabl private $projectDir; private $warmupDir; - const VERSION = '3.4.0-BETA1'; + const VERSION = '3.4.0-DEV'; const VERSION_ID = 30400; const MAJOR_VERSION = 3; const MINOR_VERSION = 4; const RELEASE_VERSION = 0; - const EXTRA_VERSION = 'BETA1'; + const EXTRA_VERSION = 'DEV'; const END_OF_MAINTENANCE = '11/2020'; const END_OF_LIFE = '11/2021'; From d2bd342949f1b7d632f64925154a3d02aa6fcfbf Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Wed, 18 Oct 2017 18:36:29 -0700 Subject: [PATCH 1098/1099] updated CHANGELOG for 4.0.0-BETA1 --- CHANGELOG-4.0.md | 304 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 304 insertions(+) create mode 100644 CHANGELOG-4.0.md diff --git a/CHANGELOG-4.0.md b/CHANGELOG-4.0.md new file mode 100644 index 0000000000000..6bd14a10e3ba7 --- /dev/null +++ b/CHANGELOG-4.0.md @@ -0,0 +1,304 @@ +CHANGELOG for 4.0.x +=================== + +This changelog references the relevant changes (bug and security fixes) done +in 4.0 minor versions. + +To get the diff for a specific change, go to https://github.com/symfony/symfony/commit/XXX where XXX is the change hash +To get the diff between two versions, go to https://github.com/symfony/symfony/compare/v4.0.0...v4.0.1 + +* 4.0.0-BETA1 (2017-10-19) + + * feature #24583 Adding a new debug:autowiring command (weaverryan) + * feature #24523 [HttpFoundation] Make sessions secure and lazy (nicolas-grekas) + * feature #22610 [Form] [TwigBridge] Added option to disable usage of default themes when rendering a form (emodric) + * feature #23112 [OptionsResolver] Support array of types in allowed type (pierredup) + * feature #24321 added ability to handle parent classes for PropertyNormalizer (ivoba) + * feature #24505 [HttpKernel] implement reset() in DumpDataCollector (xabbuh) + * feature #24425 [Console][HttpKernel] Handle new SHELL_VERBOSITY env var, also configures the default logger (nicolas-grekas) + * feature #24503 [MonologBridge][EventDispatcher][HttpKernel] remove deprecated features (xabbuh) + * feature #24387 [FORM] Prevent forms from extending itself as a parent (pierredup) + * feature #24484 [DI] Throw accurate failures when accessing removed services (nicolas-grekas) + * feature #24208 [Form] Display option definition from a given form type (yceruto, ogizanagi) + * feature #22228 [HttpKernel] minor: add ability to construct with headers on http exceptions (gsdevme) + * feature #24467 [Process] drop non-existent working directory support (xabbuh) + * feature #23499 [Workflow] add guard is_valid() method support (alain-flaus, lyrixx) + * feature #24364 [DependencyInjection][Filesystem][Security][SecurityBundle] remove deprecated features (xabbuh) + * feature #24441 [Bridge\Doctrine][FrameworkBundle] Remove legacy uses of ContainerAwareInterface (nicolas-grekas) + * feature #24388 [Security] Look at headers for switch_user username (chalasr) + * feature #24447 [Session] remove deprecated session handlers (Tobion) + * feature #24446 [Security] Remove GuardAuthenticatorInterface (chalasr) + * feature #23708 Added deprecation to cwd not existing Fixes #18249 (alexbowers) + * feature #24443 [Session] deprecate MemcacheSessionHandler (Tobion) + * feature #24409 [Bridge\Doctrine][FrameworkBundle] Deprecate some remaining uses of ContainerAwareTrait (nicolas-grekas) + * feature #24438 [Session][VarDumper] Deprecate accepting legacy mongo extension (Tobion) + * feature #24389 [DoctrineBridge] Deprecate dbal session handler (Tobion) + * feature #16835 [Security] Add Guard authenticator method (Amo, chalasr) + * feature #24289 [FrameworkBundle][HttpKernel] Reset profiler (derrabus) + * feature #24144 [FrameworkBundle] Expose dotenv in bin/console about (ro0NL) + * feature #24403 [FrameworkBundle][Routing] Show welcome message if no routes are configured (yceruto) + * feature #24398 [DI] Remove AutowireExceptionPass (ogizanagi) + * feature #22679 [Form] Add tel and color types (apetitpa) + * feature #23845 [Validator] Add unique entity violation cause (Ilya Vertakov) + * feature #22132 [Lock] Automaticaly release lock when user forget it (jderusse) + * feature #21751 Bootstrap4 support for Twig form theme (hiddewie, javiereguiluz) + * feature #24383 [FrameworkBundle] Don't clear app pools on cache:clear (nicolas-grekas) + * feature #24148 [Form] Hide label button when its setted to false (TeLiXj) + * feature #24380 [SecurityBundle] Remove auto picking the first provider (ogizanagi) + * feature #24378 [SecurityBundle] Deprecate auto picking the first provider (ogizanagi) + * feature #24260 [Security] Add impersonation support for stateless authentication (chalasr) + * feature #24300 [HttpKernel][FrameworkBundle] Add a minimalist default PSR-3 logger (dunglas) + * feature #21604 [Security] Argon2i Password Encoder (zanbaldwin) + * feature #24372 [DowCrawler] Default to UTF-8 when possible (nicolas-grekas) + * feature #24264 [TwigBundle] Improve the overriding of bundle templates (yceruto) + * feature #24197 [Translation] Moved PhpExtractor and PhpStringTokenParser to Translation component (Nyholm) + * feature #24362 [HttpKernel] Deprecate some compiler passes in favor of tagged iterator args (nicolas-grekas) + * feature #21027 [Asset] Provide default context (ro0NL) + * feature #22200 [DI] Reference tagged services in config (ro0NL) + * feature #24337 Adding a shortcuts for the main security functionality (weaverryan, javiereguiluz) + * feature #24358 [TwigBundle] register an identity translator as fallback (xabbuh) + * feature #24357 [Yaml] include file and line no in deprecation message (xabbuh) + * feature #24330 [FrameworkBundle] register class metadata factory alias (xabbuh) + * feature #24348 [SecurityBundle] Remove remaining ACL stuff from SecurityBundle (ogizanagi) + * feature #24349 [SecurityBundle] Add missing AclSchemaListener deprecation (ogizanagi) + * feature #24202 [Filesystem] deprecate relative paths in makePathRelative() (xabbuh) + * feature #21716 [Serializer] Add Support for `object_to_populate` in CustomNormalizer (chrisguitarguy) + * feature #21960 Remove Validator\TypeTestCase and add validator logic to base TypeTestCase (pierredup) + * feature #24338 [HttpFoundation] Removed compatibility layer for PHP <5.4 sessions (afurculita) + * feature #22113 [Lock] Include lock component in framework bundle (jderusse) + * feature #24236 [WebProfilerBundle] Render file links for twig templates (ro0NL) + * feature #21239 [Serializer] throw more specific exceptions (xabbuh) + * feature #24341 [SecurityBundle] Remove ACL related code (chalasr) + * feature #24256 CsvEncoder handling variable structures and custom header order (Oliver Hoff) + * feature #23471 [Finder] Add a method to check if any results were found (duncan3dc) + * feature #23149 [PhpUnitBridge] Added a CoverageListener to enhance the code coverage report (lyrixx) + * feature #24161 [HttpKernel] Remove bundle inheritance (fabpot) + * feature #24318 [SecurityBundle] Deprecate ACL related code (chalasr) + * feature #24335 [Security][SecurityBundle] Deprecate the HTTP digest auth (ogizanagi) + * feature #21951 [Security][Firewall] Passing the newly generated security token to the event during user switching (klandaika) + * feature #23485 [Config] extracted the xml parsing from XmlUtils::loadFile into XmlUtils::parse (Basster) + * feature #22890 [HttpKernel] Add ability to configure catching exceptions for Client (kbond) + * feature #24239 [HttpFoundation] Deprecate compatibility with PHP <5.4 sessions (afurculita) + * feature #23882 [Security] Deprecated not being logged out after user change (iltar) + * feature #24200 Added an alias for FlashBagInterface in config (tifabien) + * feature #24295 [DI][DX] Throw exception on some ContainerBuilder methods used from extensions (ogizanagi) + * feature #24253 [Yaml] support parsing files (xabbuh) + * feature #24290 Adding Definition::addError() and a compiler pass to throw errors as exceptions (weaverryan) + * feature #24301 [DI] Add AutowireRequiredMethodsPass to fix bindings for `@required` methods (nicolas-grekas) + * feature #24226 [Cache] Add ResettableInterface to allow resetting any pool's local state (nicolas-grekas) + * feature #24303 [FrameworkBundle] allow forms without translations and validator (xabbuh) + * feature #24291 [SecurityBundle] Reset the authentication token between requests (derrabus) + * feature #24280 [VarDumper] Make `dump()` a little bit more easier to use (freekmurze) + * feature #24277 [Serializer] Getter for extra attributes in ExtraAttributesException (mdeboer) + * feature #24257 [HttpKernel][DI] Enable Kernel to implement CompilerPassInterface (nicolas-grekas) + * feature #23834 [DI] Add "PHP fluent format" for configuring the container (nicolas-grekas) + * feature #24180 [Routing] Add PHP fluent DSL for configuring routes (nicolas-grekas) + * feature #24232 [Bridge\Doctrine] Add "DoctrineType::reset()" method (nicolas-grekas) + * feature #24238 [DI] Turn services and aliases private by default, with BC layer (nicolas-grekas) + * feature #24242 [Form] Remove deprecated ChoiceLoaderInterface implementation in TimezoneType (ogizanagi) + * feature #23648 [Form] Add input + regions options to TimezoneType (ro0NL) + * feature #24185 [Form] Display general forms information on debug:form (yceruto) + * feature #23747 [Serializer][FrameworkBundle] Add a DateInterval normalizer (Lctrs) + * feature #24193 [FrameworkBundle] Reset stopwatch between requests (derrabus) + * feature #24160 [HttpKernel] Deprecate bundle inheritance (fabpot) + * feature #24159 Remove the profiler.matcher configuration (fabpot) + * feature #24155 [FrameworkBundle][HttpKernel] Add DI tag for resettable services (derrabus) + * feature #23625 Feature #23583 Add current and fallback locales in WDT / Profiler (nemoneph) + * feature #24179 [TwigBundle] Add default templates directory and option to configure it (yceruto) + * feature #24176 [Translation] drop MessageSelector support in the Translator (xabbuh) + * feature #24104 Make as many services private as possible (nicolas-grekas) + * feature #18314 [Translation] added support for adding custom message formatter (aitboudad) + * feature #24158 deprecated profiler.matcher configuration (fabpot) + * feature #23728 [WebProfilerBundle] Removed the deprecated web_profiler.position option (javiereguiluz) + * feature #24131 [Console] Do not display short exception trace for common console exceptions (yceruto) + * feature #24080 Deprecated the web_profiler.position option (javiereguiluz) + * feature #24114 [SecurityBundle] Throw a meaningful exception when an undefined user provider is used inside a firewall (chalasr) + * feature #24122 [DI] rename ResolveDefinitionTemplatesPass to ResolveChildDefinitionsPass (nicolas-grekas) + * feature #23901 [DI] Allow processing env vars (nicolas-grekas) + * feature #24093 [FrameworkBundle] be able to enable workflow support explicitly (xabbuh) + * feature #24064 [TwigBridge] Show Twig's loader paths on debug:twig command (yceruto) + * feature #23978 [Cache] Use options from Memcached DSN (Bukashk0zzz) + * feature #24067 [HttpKernel] Dont register env parameter resource (ro0NL) + * feature #24075 Implemented PruneableInterface on TagAwareAdapter (Toflar) + * feature #23262 Add scalar typehints/return types (chalasr, xabbuh) + * feature #21414 [Console] Display file and line on Exception (arno14) + * feature #24068 [HttpKernel] Deprecate EnvParametersResource (ro0NL) + * feature #22542 [Lock] Check TTL expiration in lock acquisition (jderusse) + * feature #24031 [Routing] Add the possibility to define a prefix for all routes of a controller (fabpot) + * feature #24052 [DI] Remove case insensitive parameter names (ro0NL) + * feature #23967 [VarDumper] add force-collapse/expand + use it for traces (nicolas-grekas) + * feature #24033 [DI] Add ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE (nicolas-grekas) + * feature #24026 [Security] add impersonator_user to "User was reloaded" log message (gharlan) + * feature #24014 [Translator] Remove deprecated feature (maidmaid) + * feature #23603 [Cache] Add (pdo|chain) cache (adapter|simple) prune method (robfrawley) + * feature #23694 [Form] Add debug:form command (yceruto) + * feature #24028 [Yaml] mark some classes as final (xabbuh) + * feature #22543 [Lock] Expose an expiringDate and isExpired method in Lock (jderusse) + * feature #23667 [Translation] Create an TranslationReaderInterface and move TranslationLoader to TranslationComponent (Nyholm) + * feature #24024 [config] Add ability to deprecate a node (sanpii) + * feature #23668 [VarDumper] Add period caster (maidmaid) + * feature #23991 [DI] Improve psr4-based service discovery (alternative implementation) (kbond) + * feature #22382 [config] Add abbitily to deprecate a node (Nyholm, fabpot, sanpii) + * feature #23947 [Translation] Adding the ability do load in xliff2.0 (Nyholm) + * feature #23887 [Console] Allow commands to provide a default name for compile time registration (chalasr, nicolas-grekas) + * feature #23874 [DI] Case sensitive parameter names (ro0NL) + * feature #23936 Remove some sf2 references (fabpot) + * feature #23680 [Webprofiler] Added blocks that allows extension of the profiler page. (Nyholm) + * feature #23665 Create an interface for TranslationWriter (Nyholm) + * feature #23890 [Translation] Adding the ability do dump in xliff2.0 (Nyholm) + * feature #23862 [SecurityBundle] resolve class name parameter inside AddSecurityVotersPass (pjarmalavicius) + * feature #23915 [DI] Allow get available services from service locator (Koc) + * feature #23792 [HttpKernel][FrameworkBundle] Add RebootableInterface, fix and un-deprecate cache:clear with warmup (nicolas-grekas) + * feature #23227 Add support for "controller" keyword for configuring routes controllers (voronkovich) + * feature #23815 [FrameworkBundle][SecurityBundle][TwigBundle][Yaml] remove deprecated code (xabbuh) + * feature #23857 [HttpKernel] Remove convention based commands registration (chalasr) + * feature #23869 [Console] Made console command shortcuts case insensitive (thanosp) + * feature #23855 [DI] Allow dumping inline services in Yaml (nicolas-grekas) + * feature #23836 [FrameworkBundle] Catch Fatal errors in commands registration (chalasr) + * feature #23805 [HttpKernel] Deprecated commands auto-registration (GuilhemN) + * feature #23816 [Debug] Detect internal and deprecated methods (GuilhemN) + * feature #23812 [FrameworkBundle] Allow micro kernel to subscribe events easily (ogizanagi) + * feature #22187 [DependencyInjection] Support local binding (GuilhemN) + * feature #23741 [DI] Generate one file per service factory (nicolas-grekas) + * feature #23807 [Debug] Trigger a deprecation when using an internal class/trait/interface (GuilhemN) + * feature #22587 [Workflow] Add transition completed event (izzyp) + * feature #23624 [FrameworkBundle] Commands as a service (ro0NL) + * feature #21111 [Validator] add groups support to the Valid constraint (xabbuh) + * feature #20361 [Config] Enable cannotBeEmpty along with requiresAtLeastOneElement (ro0NL) + * feature #23790 [Yaml] remove legacy php/const and php/object tag support (xabbuh) + * feature #23754 [Lock] Remove Filesystem\LockHandler (jderusse) + * feature #23712 [DependencyInjection] Deprecate autowiring service auto-registration (GuilhemN) + * feature #23719 Autoconfigure instances of ArgumentValueResolverInterface (BPScott) + * feature #23706 [Webprofiler] Improve sql explain table display (mimol91) + * feature #23709 [VarDumper] Make dump() variadic (chalasr) + * feature #23724 [Lock] Deprecate Filesystem/LockHandler (jderusse) + * feature #23593 [Workflow] Adding workflow name to the announce event (Nyholm) + * feature #20496 [Form] Allow pass filter callback to delete_empty option. (Koc) + * feature #23451 [Cache] Add (filesystem|phpfiles) cache (adapter|simple) prune method and prune command (robfrawley) + * feature #23519 [TwigBundle] Commands as a service (ro0NL) + * feature #23591 [VarDumper] Add time zone caster (maidmaid) + * feature #23614 [VarDumper] Remove low PHP version and hhvm compat in interval caster (maidmaid) + * feature #22317 [Console] Make SymfonyQuestionHelper::ask optional by default (ro0NL) + * feature #23510 [Console] Add a factory command loader for standalone application with lazy-loading needs (ogizanagi) + * feature #23357 [VarDumper] Add interval caster (maidmaid) + * feature #23550 [DebugBundle] Added min_depth to Configuration (james-johnston-thumbtack) + * feature #23561 [DI] Optimize use of private and pre-defined services (nicolas-grekas) + * feature #23569 Remove last legacy codes (nicolas-grekas) + * feature #23570 [FrameworkBundle] Make RouterCacheWarmer implement ServiceSubscriberInterface (nicolas-grekas) + * feature #22783 [TwigBridge] remove deprecated features (xabbuh) + * feature #23437 [TwigBridge] deprecate TwigRenderer (Tobion) + * feature #22801 [DI] Removed deprecated setting private/pre-defined services (ro0NL) + * feature #23515 [VarDumper] Added setMinDepth to VarCloner (james-johnston-thumbtack) + * feature #23484 [DI] Remove remaining deprecated features (nicolas-grekas) + * feature #23404 [Serializer] AbstractObjectNormalizer: Allow to disable type enforcement (ogizanagi) + * feature #23380 [Process] Remove enhanced sigchild compatibility (maidmaid) + * feature #21086 [MonologBridge] Add TokenProcessor (maidmaid) + * feature #22576 [Validator] Allow to use a property path to get value to compare in comparison constraints (ogizanagi) + * feature #22689 [DoctrineBridge] Add support for doctrin/dbal v2.6 types (jvasseur) + * feature #22734 [Console] Add support for command lazy-loading (chalasr) + * feature #19034 [Security] make it possible to configure a custom access decision manager service (xabbuh) + * feature #23037 [TwigBundle] Added a RuntimeExtensionInterface to take advantage of autoconfigure (lyrixx) + * feature #22811 [DI] Remove deprecated case insensitive service ids (ro0NL) + * feature #22176 [DI] Allow imports in string format for YAML (ro0NL) + * feature #23295 [Security] Lazy load user providers (chalasr) + * feature #23440 [Routing] Add matched and default parameters to redirect responses (artursvonda, Tobion) + * feature #22804 [Debug] Removed ContextErrorException (mbabker) + * feature #22762 [Yaml] Support tagged scalars (GuilhemN) + * feature #22832 [Debug] Deprecate support for stacked errors (mbabker) + * feature #21469 [HttpFoundation] Find the original request protocol version (thewilkybarkid) + * feature #23431 [Validator] Add min/max amount of pixels to Image constraint (akeeman) + * feature #23223 Add support for microseconds in Stopwatch (javiereguiluz) + * feature #22341 [BrowserKit] Emulate back/forward browser navigation (e-moe) + * feature #22619 [FrameworkBundle][Translation] Move translation compiler pass (lepiaf) + * feature #22620 [FrameworkBundle][HttpKernel] Move httpkernel pass (lepiaf) + * feature #23402 [Ldap] Remove the RenameEntryInterface interface (maidmaid) + * feature #23337 [Component][Serializer][Normalizer] : Deal it with Has Method for the Normalizer/Denormalizer (jordscream) + * feature #23391 [Validator] Remove support of boolean value for the checkDNS option (maidmaid) + * feature #23376 [Process] Remove enhanced Windows compatibility (maidmaid) + * feature #22588 [VarDumper] Add filter in VarDumperTestTrait (maidmaid) + * feature #23288 [Yaml] deprecate the !str tag (xabbuh) + * feature #23039 [Validator] Support for parsing PHP constants in yaml loader (mimol91) + * feature #22431 [VarDumper] Add date caster (maidmaid) + * feature #23285 [Stopwatch] Add a reset method (jmgq) + * feature #23320 [WebServer] Allow * to bind all interfaces (as INADDR_ANY) (jpauli, fabpot) + * feature #23272 [FrameworkBundle] disable unusable fragment renderers (xabbuh) + * feature #23332 [Yaml] fix the displayed line number (fabpot, xabbuh) + * feature #23324 [Security] remove support for defining voters that don't implement VoterInterface. (hhamon) + * feature #23294 [Yaml][Lint] Add line numbers to JSON output. (WybrenKoelmans) + * feature #22836 [Process] remove deprecated features (xabbuh) + * feature #23286 [Yaml] remove deprecated unspecific tag behavior (xabbuh) + * feature #23026 [SecurityBundle] Add user impersonation info and exit action to the profiler (yceruto) + * feature #22863 [HttpFoundation] remove deprecated features (xabbuh) + * feature #22932 [HttpFoundation] Adds support for the immutable directive in the cache-control header (twoleds) + * feature #22554 [Profiler][Validator] Add a validator panel in profiler (ogizanagi) + * feature #22124 Shift responsibility for keeping Date header to ResponseHeaderBag (mpdude) + * feature #23122 Xml encoder optional type cast (ragboyjr) + * feature #23207 [FrameworkBundle] Allow .yaml file extension everywhere (ogizanagi) + * feature #23076 [Validator] Adds support to check specific DNS record type for URL (iisisrael) + * feature #22629 [Security] Trigger a deprecation when a voter is missing the VoterInterface (iltar) + * feature #22636 [Routing] Expose request in route conditions, if needed and possible (ro0NL) + * feature #22909 [Yaml] Deprecate using the non-specific tag (GuilhemN) + * feature #23184 [HttpFoundation] Remove obsolete ini settings for sessions (fabpot) + * feature #23042 Consistent error handling in remember me services (lstrojny) + * feature #22444 [Serializer] DateTimeNormalizer: allow to provide timezone (ogizanagi) + * feature #23143 [DI] Reference instead of inline for array-params (nicolas-grekas) + * feature #23154 [WebProfilerBundle] Sticky ajax window (ro0NL) + * feature #23161 [FrameworkBundle] Deprecate useless --no-prefix option (chalasr) + * feature #23169 [FrameworkBundle] Remove KernelTestCase deprecated code (ogizanagi) + * feature #23105 [SecurityBundle][Profiler] Give info about called security listeners in profiler (chalasr) + * feature #23148 [FrameworkBundle] drop hard dependency on the Stopwatch component (xabbuh) + * feature #23131 [FrameworkBundle] Remove dependency on Doctrine cache (fabpot) + * feature #23114 [SecurityBundle] Lazy load security listeners (chalasr) + * feature #23111 [Process] Deprecate ProcessBuilder (nicolas-grekas) + * feature #22675 [FrameworkBundle] KernelTestCase: deprecate not using KERNEL_CLASS (ogizanagi) + * feature #22917 [VarDumper] Cycle prev/next searching in HTML dumps (ro0NL) + * feature #23044 Automatically enable the routing annotation loader (GuilhemN) + * feature #22696 [PropertyInfo] Made ReflectionExtractor's prefix lists instance variables (neemzy) + * feature #23056 [WebProfilerBundle] Remove WebProfilerExtension::dumpValue() (ogizanagi) + * feature #23035 Deprecate passing a concrete service in optional cache warmers (romainneutron) + * feature #23036 Implement ServiceSubscriberInterface in optional cache warmers (romainneutron) + * feature #23046 [Form] Missing deprecated paths removal (ogizanagi) + * feature #23022 [Di] Remove closure-proxy arguments (nicolas-grekas) + * feature #22758 Remove HHVM support (fabpot) + * feature #22743 [Serializer] Remove support for deprecated signatures (dunglas) + * feature #22907 [Serializer] remove remaining deprecated features (xabbuh) + * feature #22886 [HttpKernel] remove deprecated features (xabbuh) + * feature #22906 [Console] remove remaining deprecated features (xabbuh) + * feature #22879 [Translation] remove deprecated features (xabbuh) + * feature #22880 [Routing] remove deprecated features (xabbuh) + * feature #22903 [DI] Deprecate XML services without ID (ro0NL) + * feature #22770 [Yaml] remove deprecated features (xabbuh) + * feature #22785 [ProxyManagerBridge] remove deprecated features (xabbuh) + * feature #22800 [FrameworkBundle] Remove deprecated code (ogizanagi) + * feature #22597 [Lock] Re-add the Lock component in 3.4 (jderusse) + * feature #22860 [Form] remove deprecated features (xabbuh) + * feature #22803 [DI] Deprecate Container::initialized() for privates (ro0NL) + * feature #22773 [DependencyInjection] remove deprecated autowiring_types feature (hhamon) + * feature #22809 [DI] Remove deprecated generating a dumped container without populating the method map (ro0NL) + * feature #22764 [DI] Remove deprecated dumping an uncompiled container (ro0NL) + * feature #22820 Remove PHP < 7.1.3 code (ogizanagi) + * feature #22763 [DI] Remove deprecated isFrozen() (ro0NL) + * feature #22837 [VarDumper] remove deprecated features (xabbuh) + * feature #22777 [Console] Remove deprecated console.exception event (mbabker) + * feature #22792 [PhpUnitBridge] remove deprecated features (xabbuh) + * feature #22821 [Security] remove deprecated features (xabbuh) + * feature #22750 [DependencyInjection] remove deprecated code in YamlFileLoader class (hhamon) + * feature #22828 [Finder] Deprecate FilterIterator (ogizanagi) + * feature #22791 [MonologBridge] remove deprecated features (xabbuh) + * feature #22740 [SecurityBundle][Security][Finder] Remove deprecated code paths (ogizanagi) + * feature #22823 [PropertyAccess] remove deprecated features (xabbuh) + * feature #22826 [Validator] improve strict option value deprecation (xabbuh) + * feature #22799 [Console] Remove deprecated features (chalasr) + * feature #22786 [ClassLoader][HttpKernel] Remove ClassLoader component & Kernel::loadClassCache (ogizanagi, xabbuh) + * feature #22795 [Validator] remove deprecated features (xabbuh) + * feature #22784 [DoctrineBridge] remove deprecated features (xabbuh) + * feature #22749 Remove deprecated container injections and compiler passes (chalasr) + * feature #22796 [EventDispatcher] remove deprecated features (xabbuh) + * feature #22797 [Ldap] remove deprecated features (xabbuh) + * feature #22794 [ExpressionLanguage] remove deprecated features (xabbuh) + * feature #22779 [BC Break] Removed BC layers for ControllerResolver::getArguments() (iltar) + * feature #22782 [Debug][VarDumper] Remove the symfony_debug C extension (nicolas-grekas) + * feature #22771 [Workflow] Removed deprecated features (lyrixx) + * feature #22741 [Serializer] Remove deprecated DoctrineCache support (dunglas) + * feature #22733 Bump minimum version to PHP 7.1 for Symfony 4 (fabpot, dunglas, nicolas-grekas) + From 748338874c01674ed3522c709f8ce518708f91bd Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Wed, 18 Oct 2017 18:36:38 -0700 Subject: [PATCH 1099/1099] updated VERSION for 4.0.0-BETA1 --- 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 743c7586ffd9f..26facc144de1c 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -61,12 +61,12 @@ abstract class Kernel implements KernelInterface, RebootableInterface, Terminabl private $projectDir; private $warmupDir; - const VERSION = '4.0.0-DEV'; + const VERSION = '4.0.0-BETA1'; const VERSION_ID = 40000; const MAJOR_VERSION = 4; const MINOR_VERSION = 0; const RELEASE_VERSION = 0; - const EXTRA_VERSION = 'DEV'; + const EXTRA_VERSION = 'BETA1'; const END_OF_MAINTENANCE = '07/2018'; const END_OF_LIFE = '01/2019';